diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/index')
197 files changed, 5163 insertions, 1583 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/index/AbstractIndex.java b/src/de/lmu/ifi/dbs/elki/index/AbstractIndex.java index 061d7893..30966fd1 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) 2011 + Copyright (C) 2012 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 new file mode 100644 index 00000000..30abb4a4 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/AbstractRefiningIndex.java @@ -0,0 +1,192 @@ +package de.lmu.ifi.dbs.elki.index; + +import java.util.List; +import java.util.Map; + +import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDs; +import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; +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.knn.KNNResult; +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.persistent.PageFileStatistics; +import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap; + +/** + * Abstract base class for Filter-refinement indexes. + * + * The number of refinements will be counted as individual page accesses. + * + * @author Erich Schubert + * + * @param <O> Object type + */ +public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> implements PageFileStatistics { + /** + * Refinement counter. + */ + private int refinements; + + /** + * Constructor. + * + * @param relation Relation indexed + */ + public AbstractRefiningIndex(Relation<O> relation) { + super(relation); + } + + /** + * Initialize the index. + * + * @param relation Relation to index + * @param ids database ids + */ + abstract protected void initialize(Relation<O> relation, DBIDs ids); + + /** + * Refine a given object (and count the refinement!) + * + * @param id Object id + * @return refined object + */ + protected O refine(DBID id) { + refinements++; + return relation.get(id); + } + + @Override + public PageFileStatistics getPageFileStatistics() { + return this; + } + + @Override + public long getReadOperations() { + return refinements; + } + + @Override + public long getWriteOperations() { + return 0; + } + + @Override + public void resetPageAccess() { + refinements = 0; + } + + @Override + public PageFileStatistics getInnerStatistics() { + return null; + } + + @Override + public void insertAll(DBIDs ids) { + initialize(relation, ids); + } + + /** + * Range query for this index. + * + * @author Erich Schubert + */ + public abstract class AbstractRangeQuery<D extends Distance<D>> extends AbstractDistanceRangeQuery<O, D> { + /** + * Hold the distance function to be used. + */ + private DistanceQuery<O, D> distanceQuery; + + /** + * Constructor. + * + * @param distanceQuery Distance query object + */ + public AbstractRangeQuery(DistanceQuery<O, D> distanceQuery) { + super(distanceQuery); + this.distanceQuery = distanceQuery; + } + + @Override + public List<DistanceResultPair<D>> getRangeForDBID(DBID id, D range) { + return getRangeForObject(relation.get(id), range); + } + + /** + * Refinement distance computation. + * + * @param id Candidate ID + * @param q Query object + * @return Distance + */ + protected D refine(DBID id, O q) { + AbstractRefiningIndex.this.refinements++; + return distanceQuery.distance(q, id); + } + + /** + * Count extra refinements. + * + * @param c Refinements + */ + protected void incRefinements(int c) { + AbstractRefiningIndex.this.refinements += c; + } + } + + /** + * KNN query for this index. + * + * @author Erich Schubert + */ + abstract public class AbstractKNNQuery<D extends Distance<D>> extends AbstractDistanceKNNQuery<O, D> implements KNNQuery<O, D> { + /** + * Constructor. + * + * @param distanceQuery Distance query object + */ + public AbstractKNNQuery(DistanceQuery<O, D> distanceQuery) { + super(distanceQuery); + } + + @Override + public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + throw new UnsupportedOperationException("Not yet implemented."); + } + + @Override + public void getKNNForBulkHeaps(Map<DBID, KNNHeap<D>> heaps) { + throw new UnsupportedOperationException("Not yet implemented."); + } + + @Override + public KNNResult<D> getKNNForDBID(DBID id, int k) { + return getKNNForObject(relation.get(id), k); + } + + /** + * Refinement distance computation. + * + * @param id Candidate ID + * @param q Query object + * @return Distance + */ + protected D refine(DBID id, O q) { + AbstractRefiningIndex.this.refinements++; + return distanceQuery.distance(q, id); + } + + /** + * Count extra refinements. + * + * @param c Refinements + */ + protected void incRefinements(int c) { + AbstractRefiningIndex.this.refinements += c; + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/Index.java b/src/de/lmu/ifi/dbs/elki/index/Index.java index 2021fbbb..9e77073c 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) 2011 + Copyright (C) 2012 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 b1eb649b..ac34c53f 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) 2011 + Copyright (C) 2012 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/KNNIndex.java b/src/de/lmu/ifi/dbs/elki/index/KNNIndex.java index 7fcb7376..83a37f88 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) 2011 + Copyright (C) 2012 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 f29fbe89..6c990cd8 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) 2011 + Copyright (C) 2012 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/RangeIndex.java b/src/de/lmu/ifi/dbs/elki/index/RangeIndex.java index 1bcfad12..5d64a8fa 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) 2011 + Copyright (C) 2012 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 3f9c7cce..ca7dbe28 100644 --- a/src/de/lmu/ifi/dbs/elki/index/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/package-info.java @@ -2,25 +2,25 @@ * <p>Index structure implementations</p> */ /* -This file is part of ELKI: -Environment for Developing KDD-Applications Supported by Index-Structures + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 -Ludwig-Maximilians-Universität München -Lehr- und Forschungseinheit für Datenbanksysteme -ELKI Development Team + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + This program is 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. + 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/>. -*/ + 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;
\ No newline at end of file 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 4b6fbe3a..0160480f 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -43,7 +43,7 @@ public abstract class AbstractPreprocessorIndex<O, R> extends AbstractIndex<O> { /** * The data store */ - protected WritableDataStore<R> storage; + protected WritableDataStore<R> storage = null; /** * Constructor. 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 8b4272d5..cef2fbdc 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) 2011 + Copyright (C) 2012 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/AbstractMaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/AbstractMaterializeKNNPreprocessor.java index 0579262b..b9b72d87 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,14 +23,15 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.List; - -import javax.swing.event.EventListenerList; - import de.lmu.ifi.dbs.elki.data.type.TypeInformation; -import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; +import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory; +import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil; +import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore; +import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDs; 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.KNNResult; 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; @@ -54,7 +55,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * @param <O> Object type * @param <D> Distance type */ -public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D>> extends AbstractPreprocessorIndex<O, List<DistanceResultPair<D>>> implements KNNIndex<O> { +public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D>, T extends KNNResult<D>> extends AbstractPreprocessorIndex<O, T> implements KNNIndex<O> { /** * The query k value. */ @@ -71,11 +72,6 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D protected final DistanceQuery<O, D> distanceQuery; /** - * Holds the listener. - */ - protected final EventListenerList listenerList = new EventListenerList(); - - /** * Constructor. * * @param relation Relation @@ -121,6 +117,42 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D */ protected abstract void preprocess(); + /** + * Get the k nearest neighbors. + * + * @param objid Object ID + * @return Neighbors + */ + public KNNResult<D> get(DBID objid) { + if(storage == null) { + if(getLogger().isDebugging()) { + getLogger().debug("Running kNN preprocessor: " + this.getClass()); + } + preprocess(); + } + return storage.get(objid); + } + + /** + * Create the default storage. + */ + void createStorage() { + WritableDataStore<T> s = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT, KNNResult.class); + storage = s; + } + + @Override + public void insertAll(DBIDs ids) { + if(storage == null) { + if(ids.size() > 0) { + preprocess(); + } + } + else { + throw new UnsupportedOperationException("Preprocessor already ran."); + } + } + @SuppressWarnings("unchecked") @Override public <S extends Distance<S>> KNNQuery<O, S> getKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { @@ -136,7 +168,9 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D break; } } - return new PreprocessorKNNQuery<O, S>(relation, (MaterializeKNNPreprocessor<O, S>) this); + // To make compilers happy: + AbstractMaterializeKNNPreprocessor<?, ?, ?> tmp = this; + return new PreprocessorKNNQuery<O, S, KNNResult<S>>(relation, (AbstractMaterializeKNNPreprocessor<O, S, KNNResult<S>>) tmp); } /** @@ -151,7 +185,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D * @param <O> The object type * @param <D> The distance type */ - public static abstract class Factory<O, D extends Distance<D>> implements IndexFactory<O, KNNIndex<O>> { + public static abstract class Factory<O, D extends Distance<D>, T extends KNNResult<D>> 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. @@ -197,7 +231,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D } @Override - abstract public AbstractMaterializeKNNPreprocessor<O, D> instantiate(Relation<O> relation); + abstract public AbstractMaterializeKNNPreprocessor<O, D, T> instantiate(Relation<O> relation); /** * Get the distance function. @@ -217,7 +251,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D public D getDistanceFactory() { return distanceFunction.getDistanceFactory(); } - + @Override public TypeInformation getInputTypeRestriction() { return distanceFunction.getInputTypeRestriction(); @@ -258,7 +292,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D } @Override - abstract protected Factory<O, D> makeInstance(); + abstract protected Factory<O, D, ?> makeInstance(); } } }
\ No newline at end of file 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 ef26d62b..6c677fda 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) 2011 +Copyright (C) 2012 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 new file mode 100644 index 00000000..b7c3f0ac --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNJoinMaterializeKNNPreprocessor.java @@ -0,0 +1,128 @@ +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.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; +import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNList; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Class to materialize the kNN using a spatial join on an R-tree. + * + * @author Erich Schubert + * + * @param <V> vector type + * @param <D> distance type + */ +public class KNNJoinMaterializeKNNPreprocessor<V extends NumberVector<V, ?>, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<V, D, KNNList<D>> { + /** + * Logging class. + */ + private static final Logging logger = Logging.getLogger(KNNJoinMaterializeKNNPreprocessor.class); + + /** + * Constructor. + * + * @param relation Relation to index + * @param distanceFunction Distance function + * @param k k + */ + public KNNJoinMaterializeKNNPreprocessor(Relation<V> relation, DistanceFunction<? super V, D> 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); + storage = knnjoin.run(relation.getDatabase(), relation); + } + + @Override + protected Logging getLogger() { + return logger; + } + + @Override + public String getLongName() { + return "knn-join materialized neighbors"; + } + + @Override + public String getShortName() { + return "knn-join"; + } + + /** + * The parameterizable factory. + * + * @author Erich Schubert + * + * @apiviz.landmark + * @apiviz.stereotype factory + * @apiviz.uses AbstractMaterializeKNNPreprocessor oneway - - «create» + * + * @param <O> The object type + * @param <D> The distance type + */ + public static class Factory<O extends NumberVector<O, ?>, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNList<D>> { + /** + * Constructor. + * + * @param k K + * @param distanceFunction distance function + */ + public Factory(int k, DistanceFunction<? super O, D> distanceFunction) { + super(k, distanceFunction); + } + + @Override + public KNNJoinMaterializeKNNPreprocessor<O, D> instantiate(Relation<O> relation) { + return new KNNJoinMaterializeKNNPreprocessor<O, D>(relation, distanceFunction, k); + } + + /** + * Parameterization class + * + * @author Erich Schubert + * + * @apiviz.exclude + * + * @param <O> Object type + * @param <D> Distance type + */ + public static class Parameterizer<O extends NumberVector<O, ?>, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, D> { + @Override + protected KNNJoinMaterializeKNNPreprocessor.Factory<O, D> makeInstance() { + return new KNNJoinMaterializeKNNPreprocessor.Factory<O, D>(k, distanceFunction); + } + } + } +}
\ No newline at end of file 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 c4456f83..4a726ad0 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) 2011 + Copyright (C) 2012 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 9abd4a74..1436efe2 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -34,13 +34,15 @@ 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.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.DBIDUtil; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; -import de.lmu.ifi.dbs.elki.database.ids.TreeSetDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.SetDBIDs; import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.database.query.GenericDistanceResultPair; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult; 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; @@ -51,6 +53,7 @@ import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress; import de.lmu.ifi.dbs.elki.logging.progress.StepProgress; import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap; +import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNList; import de.lmu.ifi.dbs.elki.utilities.documentation.Description; import de.lmu.ifi.dbs.elki.utilities.documentation.Title; @@ -88,7 +91,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends @Override protected void preprocess() { - storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT, List.class); + createStorage(); materialized_RkNN = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT, Set.class); FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("Materializing k nearest neighbors and reverse k nearest neighbors (k=" + k + ")", relation.size(), getLogger()) : null; materializeKNNAndRKNNs(DBIDUtil.ensureArray(relation.getDBIDs()), progress); @@ -100,7 +103,6 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends * @param ids the IDs of the objects */ private void materializeKNNAndRKNNs(ArrayDBIDs ids, FiniteProgress progress) { - // add an empty list to each rknn for(DBID id : ids) { if(materialized_RkNN.get(id) == null) { @@ -109,10 +111,10 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends } // knn query - List<List<DistanceResultPair<D>>> kNNList = knnQuery.getKNNForBulkDBIDs(ids, k); + List<KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(ids, k); for(int i = 0; i < ids.size(); i++) { DBID id = ids.get(i); - List<DistanceResultPair<D>> kNNs = kNNList.get(i); + KNNResult<D> kNNs = kNNList.get(i); storage.put(id, kNNs); for(DistanceResultPair<D> kNN : kNNs) { Set<DistanceResultPair<D>> rknns = materialized_RkNN.get(kNN.getDBID()); @@ -165,13 +167,12 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends * updated */ private ArrayDBIDs updateKNNsAndRkNNs(DBIDs ids) { - ArrayDBIDs rkNN_ids = DBIDUtil.newArray(); + ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray(); DBIDs oldids = DBIDUtil.difference(relation.getDBIDs(), ids); for(DBID id1 : oldids) { - List<DistanceResultPair<D>> kNNs = storage.get(id1); - D knnDist = kNNs.get(kNNs.size() - 1).getDistance(); + KNNResult<D> kNNs = storage.get(id1); + D knnDist = kNNs.getKNNDistance(); // look for new kNNs - List<DistanceResultPair<D>> newKNNs = new ArrayList<DistanceResultPair<D>>(); KNNHeap<D> heap = null; for(DBID id2 : ids) { D dist = distanceQuery.distance(id1, id2); @@ -184,7 +185,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends } } if(heap != null) { - newKNNs = heap.toSortedArrayList(); + KNNList<D> newKNNs = heap.toKNNList(); storage.put(id1, newKNNs); // get the difference @@ -234,7 +235,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends if(stepprog != null) { stepprog.beginStep(1, "New deletions ocurred, remove their materialized kNNs and RkNNs.", getLogger()); } - List<List<DistanceResultPair<D>>> kNNs = new ArrayList<List<DistanceResultPair<D>>>(ids.size()); + List<KNNResult<D>> kNNs = new ArrayList<KNNResult<D>>(ids.size()); List<List<DistanceResultPair<D>>> rkNNs = new ArrayList<List<DistanceResultPair<D>>>(ids.size()); for(DBID id : aids) { kNNs.add(storage.get(id)); @@ -250,7 +251,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends stepprog.beginStep(2, "New deletions ocurred, update the affected kNNs and RkNNs.", getLogger()); } // update the kNNs of the RkNNs - List<List<DistanceResultPair<D>>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k); + List<KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k); for(int i = 0; i < rkNN_ids.size(); i++) { DBID id = rkNN_ids.get(i); storage.put(id, kNNList.get(i)); @@ -260,7 +261,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends } } // update the RkNNs of the kNNs - TreeSetDBIDs idsSet = DBIDUtil.newTreeSet(ids); + SetDBIDs idsSet = DBIDUtil.ensureSet(ids); for(int i = 0; i < kNN_ids.size(); i++) { DBID id = kNN_ids.get(i); SortedSet<DistanceResultPair<D>> rkNN = materialized_RkNN.get(id); @@ -289,7 +290,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends * @param id the query id * @return the kNNs */ - public List<DistanceResultPair<D>> getKNN(DBID id) { + public KNNResult<D> getKNN(DBID id) { return storage.get(id); } @@ -333,7 +334,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends public String getShortName() { return "knn and rknn preprocessor"; } - + @Override protected Logging getLogger() { return logger; @@ -373,8 +374,8 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends */ public static class Parameterizer<O, D extends Distance<D>> extends MaterializeKNNPreprocessor.Factory.Parameterizer<O, D> { @Override - protected Factory<O,D> makeInstance() { - return new Factory<O,D>(k, distanceFunction); + protected Factory<O, D> makeInstance() { + return new Factory<O, D>(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 9d55e916..fcd6fad1 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,19 +23,22 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.ArrayList; +import java.util.Collection; import java.util.List; -import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory; -import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil; +import javax.swing.event.EventListenerList; + 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.DBIDUtil; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; -import de.lmu.ifi.dbs.elki.database.ids.TreeSetModifiableDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.SetDBIDs; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult; 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; @@ -64,7 +67,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title; */ @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> { +public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> { /** * Logger to use. */ @@ -83,30 +86,20 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra protected final KNNQuery<O, D> knnQuery; /** - * Constructor with preprocessing step. - * - * @param relation Relation to preprocess - * @param distanceFunction the distance function to use - * @param k query k + * Holds the listener. */ - public MaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k) { - this(relation, distanceFunction, k, true); - } + protected final EventListenerList listenerList = new EventListenerList(); /** - * Constructor. + * Constructor with preprocessing step. * * @param relation Relation to preprocess * @param distanceFunction the distance function to use * @param k query k */ - protected MaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k, boolean preprocess) { + public MaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> 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); - - if(preprocess) { - preprocess(); - } } /** @@ -114,13 +107,13 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra */ @Override protected void preprocess() { - storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, List.class); + createStorage(); ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs()); FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("Materializing k nearest neighbors (k=" + k + ")", ids.size(), getLogger()) : null; // Try bulk - List<List<DistanceResultPair<D>>> kNNList = null; + List<KNNResult<D>> kNNList = null; if(usebulk) { kNNList = knnQuery.getKNNForBulkDBIDs(ids, k); if(kNNList != null) { @@ -135,7 +128,7 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra } else { for(DBID id : ids) { - List<DistanceResultPair<D>> knn = knnQuery.getKNNForDBID(id, k); + KNNResult<D> knn = knnQuery.getKNNForDBID(id, k); storage.put(id, knn); if(progress != null) { progress.incrementProcessed(getLogger()); @@ -148,16 +141,6 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra } } - /** - * Get the k nearest neighbors. - * - * @param objid Object ID - * @return Neighbors - */ - public List<DistanceResultPair<D>> get(DBID objid) { - return storage.get(objid); - } - @Override public final void insert(DBID id) { objectsInserted(id); @@ -165,6 +148,9 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra @Override public void insertAll(DBIDs ids) { + if(storage == null && ids.size() > 0) { + preprocess(); + } objectsInserted(ids); } @@ -193,7 +179,7 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra if(stepprog != null) { stepprog.beginStep(1, "New insertions ocurred, materialize their new kNNs.", getLogger()); } - List<List<DistanceResultPair<D>>> kNNList = knnQuery.getKNNForBulkDBIDs(aids, k); + List<KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(aids, k); for(int i = 0; i < aids.size(); i++) { DBID id = aids.get(i); storage.put(id, kNNList.get(i)); @@ -225,13 +211,12 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra * updated */ private ArrayDBIDs updateKNNsAfterInsertion(DBIDs ids) { - ArrayDBIDs rkNN_ids = DBIDUtil.newArray(); + ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray(); DBIDs oldids = DBIDUtil.difference(relation.getDBIDs(), ids); for(DBID id1 : oldids) { - List<DistanceResultPair<D>> kNNs = storage.get(id1); + KNNResult<D> kNNs = storage.get(id1); D knnDist = kNNs.get(kNNs.size() - 1).getDistance(); // look for new kNNs - List<DistanceResultPair<D>> newKNNs = new ArrayList<DistanceResultPair<D>>(); KNNHeap<D> heap = null; for(DBID id2 : ids) { D dist = distanceQuery.distance(id1, id2); @@ -244,8 +229,8 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra } } if(heap != null) { - newKNNs = heap.toSortedArrayList(); - storage.put(id1, newKNNs); + kNNs = heap.toKNNList(); + storage.put(id1, kNNs); rkNN_ids.add(id1); } } @@ -260,10 +245,10 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra * updated */ private ArrayDBIDs updateKNNsAfterDeletion(DBIDs ids) { - TreeSetModifiableDBIDs idsSet = DBIDUtil.newTreeSet(ids); - ArrayDBIDs rkNN_ids = DBIDUtil.newArray(); + SetDBIDs idsSet = DBIDUtil.ensureSet(ids); + ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray(); for(DBID id1 : relation.iterDBIDs()) { - List<DistanceResultPair<D>> kNNs = storage.get(id1); + KNNResult<D> kNNs = storage.get(id1); for(DistanceResultPair<D> kNN : kNNs) { if(idsSet.contains(kNN.getDBID())) { rkNN_ids.add(id1); @@ -273,7 +258,7 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra } // update the kNNs of the RkNNs - List<List<DistanceResultPair<D>>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k); + List<KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k); for(int i = 0; i < rkNN_ids.size(); i++) { DBID id = rkNN_ids.get(i); storage.put(id, kNNList.get(i)); @@ -360,16 +345,18 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra * @param remove the ids to remove * @return the DBIDs in the given collection */ - protected ArrayDBIDs extractAndRemoveIDs(List<List<DistanceResultPair<D>>> extraxt, ArrayDBIDs remove) { - TreeSetModifiableDBIDs ids = DBIDUtil.newTreeSet(); - for(List<DistanceResultPair<D>> drps : extraxt) { + protected ArrayDBIDs extractAndRemoveIDs(List<? extends Collection<DistanceResultPair<D>>> extraxt, ArrayDBIDs remove) { + HashSetModifiableDBIDs ids = DBIDUtil.newHashSet(); + for(Collection<DistanceResultPair<D>> drps : extraxt) { for(DistanceResultPair<D> drp : drps) { ids.add(drp.getDBID()); } } - ids.removeAll(remove); - return DBIDUtil.ensureArray(ids); - + for(DBID id : remove) { + ids.remove(id); + } + // Convert back to array + return DBIDUtil.newArray(ids); } /** @@ -423,7 +410,7 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra * @param <O> The object type * @param <D> The distance type */ - public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D> { + public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNResult<D>> { /** * Index factory. * 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 f20e6e39..5ac7d2d2 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -28,12 +28,11 @@ import java.util.HashMap; import java.util.List; import de.lmu.ifi.dbs.elki.data.NumberVector; -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.DBID; 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.query.distance.DistanceQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult; 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; @@ -69,7 +68,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title; */ @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<? super O, ?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry<D>> extends AbstractMaterializeKNNPreprocessor<O, D> { +public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends NumberVector<? super O, ?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> { /** * Logger to use */ @@ -92,7 +91,7 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb MetricalIndexTree<O, D, N, E> index = getMetricalIndex(relation); - storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, List.class); + createStorage(); MeanVariance pagesize = new MeanVariance(); MeanVariance ksize = new MeanVariance(); if(getLogger().isVerbose()) { @@ -133,7 +132,7 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb } } ksize.put(kNN.size()); - storage.put(id, kNN.toSortedArrayList()); + storage.put(id, kNN.toKNNList()); } if(getLogger().isDebugging()) { if(cache.size() > 0) { @@ -203,7 +202,7 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb * @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<? super O, ?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D> { + public static class Factory<O extends NumberVector<? super O, ?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNResult<D>> { /** * Constructor. * 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 3e7d1b8f..90813b92 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) 2011 + Copyright (C) 2012 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.preprocessed.knn; */ import java.util.HashMap; -import java.util.List; import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory; import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil; @@ -34,6 +33,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBID; 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.query.distance.DistanceQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult; 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; @@ -61,7 +61,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; */ @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> { +public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> { // TODO: randomize/shuffle? /** @@ -85,14 +85,12 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista public PartitionApproximationMaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k, int partitions) { super(relation, distanceFunction, k); this.partitions = partitions; - // preprocess now - preprocess(); } @Override protected void preprocess() { DistanceQuery<O, D> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction); - storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, List.class); + storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNResult.class); MeanVariance ksize = new MeanVariance(); if(logger.isVerbose()) { logger.verbose("Approximating nearest neighbor lists to database objects"); @@ -130,7 +128,7 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista } } ksize.put(kNN.size()); - storage.put(id, kNN.toSortedArrayList()); + storage.put(id, kNN.toKNNList()); } if(logger.isDebugging()) { if(cache.size() > 0) { @@ -176,7 +174,7 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista * @param <O> The object type * @param <D> The distance type */ - public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D> { + public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNResult<D>> { /** * Parameter to specify the number of partitions to use for materializing * the kNN. Must be an integer greater than 1. 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 new file mode 100644 index 00000000..924c7c3c --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/RandomSampleKNNPreprocessor.java @@ -0,0 +1,237 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.Random; + +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.DBID; +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.GenericDistanceResultPair; +import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult; +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.datastructures.heap.KNNHeap; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.IntervalConstraint; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.IntervalConstraint.IntervalBoundary; +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.LongParameter; + +/** + * Class that computed the kNN only on a random sample. + * + * @author Erich Schubert + * + * @param <O> Object type + * @param <D> Distance type + */ +public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> { + /** + * Logger + */ + private static final Logging logger = Logging.getLogger(RandomSampleKNNPreprocessor.class); + + /** + * Relative share of objects to get + */ + private final double share; + + /** + * Random seed + */ + private final Long seed; + + /** + * Constructor. + * + * @param relation Relation to index + * @param distanceFunction distance function + * @param k k + * @param share Relative share + * @param seed Random seed (may be null) + */ + public RandomSampleKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k, double share, Long seed) { + super(relation, distanceFunction, k); + this.share = share; + this.seed = seed; + } + + @Override + protected void preprocess() { + DistanceQuery<O, D> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction); + storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNResult.class); + FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("Materializing random-sample k nearest neighbors (k=" + k + ")", relation.size(), getLogger()) : null; + + final ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs()); + final int samplesize = (int) (ids.size() * share); + final long iseed = (seed != null) ? seed : (new Random()).nextLong(); + + int i = 0; + for(DBID id : ids) { + KNNHeap<D> kNN = new KNNHeap<D>(k, distanceQuery.infiniteDistance()); + + long rseed = i * 0x7FFFFFFFFFFFFFE7L + iseed; + DBIDs rsamp = DBIDUtil.randomSample(ids, samplesize, rseed); + for(DBID oid : rsamp) { + D dist = distanceQuery.distance(id, oid); + kNN.add(new GenericDistanceResultPair<D>(dist, oid)); + } + + storage.put(id, kNN.toKNNList()); + if(progress != null) { + progress.incrementProcessed(getLogger()); + } + } + + if(progress != null) { + progress.ensureCompleted(getLogger()); + } + } + + @Override + protected Logging getLogger() { + return logger; + } + + @Override + public String getLongName() { + return "random sample kNN"; + } + + @Override + public String getShortName() { + return "random-sample-knn"; + } + + /** + * The parameterizable factory. + * + * @author Erich Schubert + * + * @apiviz.landmark + * @apiviz.stereotype factory + * @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, KNNResult<D>> { + /** + * Relative share of objects to get + */ + private final double share; + + /** + * Random seed + */ + private final Long seed; + + /** + * Constructor. + * + * @param k K + * @param distanceFunction distance function + * @param share Sample size (relative) + * @param seed Random seed + */ + public Factory(int k, DistanceFunction<? super O, D> distanceFunction, double share, Long seed) { + super(k, distanceFunction); + this.share = share; + this.seed = seed; + } + + @Override + public RandomSampleKNNPreprocessor<O, D> instantiate(Relation<O> relation) { + return new RandomSampleKNNPreprocessor<O, D>(relation, distanceFunction, k, share, seed); + } + + /** + * Parameterization class + * + * @author Erich Schubert + * + * @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> { + /** + * Parameter to specify how many objects to consider for computing the + * kNN. + * + * <p> + * Key: {@code -randomknn.share} + * </p> + */ + public static final OptionID SHARE_ID = OptionID.getOrCreateOptionID("randomknn.share", "The relative amount of objects to consider for kNN computations."); + + /** + * Random number generator seed. + * + * <p> + * Key: {@code -randomknn.seed} + * </p> + */ + public static final OptionID SEED_ID = OptionID.getOrCreateOptionID("randomknn.seed", "The random number seed."); + + /** + * Relative share of objects to get + */ + private double share = 0.0; + + /** + * Random seed + */ + private Long seed = null; + + @Override + protected void makeOptions(Parameterization config) { + super.makeOptions(config); + DoubleParameter shareP = new DoubleParameter(SHARE_ID, new IntervalConstraint(0.0, IntervalBoundary.OPEN, 1.0, IntervalBoundary.OPEN)); + if(config.grab(shareP)) { + share = shareP.getValue(); + } + LongParameter seedP = new LongParameter(SEED_ID, true); + if(config.grab(seedP)) { + seed = seedP.getValue(); + } + } + + @Override + protected RandomSampleKNNPreprocessor.Factory<O, D> makeInstance() { + return new RandomSampleKNNPreprocessor.Factory<O, D>(k, distanceFunction, share, seed); + } + } + } +}
\ No newline at end of file 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 320a3636..e78f5e89 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -34,6 +34,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBID; 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.query.distance.DistanceQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult; 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; @@ -68,7 +69,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; */ @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> { +public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVector<?, ?>, D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> { /** * Logger to use */ @@ -83,7 +84,6 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect */ public SpatialApproximationMaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k) { super(relation, distanceFunction, k); - preprocess(); } @Override @@ -96,7 +96,7 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect } SpatialIndexTree<N, E> index = indexes.iterator().next(); - storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, List.class); + storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNResult.class); MeanVariance pagesize = new MeanVariance(); MeanVariance ksize = new MeanVariance(); if(getLogger().isVerbose()) { @@ -137,7 +137,7 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect } } ksize.put(kNN.size()); - storage.put(id, kNN.toSortedArrayList()); + storage.put(id, kNN.toKNNList()); } if(getLogger().isDebugging()) { if(cache.size() > 0) { @@ -185,7 +185,7 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect * @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> { + public static class Factory<D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor.Factory<NumberVector<?, ?>, D, KNNResult<D>> { /** * Constructor. * 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 57fe5fbd..1780cdc0 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) 2011 +Copyright (C) 2012 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 3def22a1..9cb2b997 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) 2011 + Copyright (C) 2012 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.preprocessed.localpca; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.List; +import java.util.Collection; import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.data.type.TypeInformation; @@ -100,7 +100,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<? extends // TODO: use a bulk operation? for(DBID id : relation.iterDBIDs()) { - List<DistanceResultPair<DoubleDistance>> objects = objectsForPCA(id); + Collection<DistanceResultPair<DoubleDistance>> objects = objectsForPCA(id); PCAFilteredResult pcares = pca.processQueryResult(objects, relation); @@ -137,7 +137,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<? extends * @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 List<DistanceResultPair<DoubleDistance>> objectsForPCA(DBID id); + protected abstract Collection<DistanceResultPair<DoubleDistance>> objectsForPCA(DBID id); /** * Factory class @@ -185,7 +185,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<? extends public TypeInformation getInputTypeRestriction() { return pcaDistanceFunction.getInputTypeRestriction(); } - + /** * Parameterization class. * 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 18835caa..8130f6b3 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) 2011 + Copyright (C) 2012 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/KNNQueryFilteredPCAIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/KNNQueryFilteredPCAIndex.java index 7565ab32..8d766391 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,13 +23,11 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.localpca; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.List; - import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.database.QueryUtil; import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult; 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; @@ -88,7 +86,7 @@ public class KNNQueryFilteredPCAIndex<NV extends NumberVector<? extends NV, ?>> } @Override - protected List<DistanceResultPair<DoubleDistance>> objectsForPCA(DBID id) { + protected KNNResult<DoubleDistance> objectsForPCA(DBID id) { return knnQuery.getKNNForDBID(id, k); } 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 index 26f08ae3..7d5da770 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/RangeQueryFilteredPCAIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/RangeQueryFilteredPCAIndex.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) 2011 + Copyright (C) 2012 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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/package-info.java index f097bd14..2bd9cc7d 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) 2011 +Copyright (C) 2012 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 4c482cd2..98a55d88 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) 2011 +Copyright (C) 2012 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 13b6e28b..95c698ee 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) 2011 + Copyright (C) 2012 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/DiSHPreferenceVectorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java index 8626e5b7..ade6c114 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) 2011 + Copyright (C) 2012 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/HiSCPreferenceVectorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/HiSCPreferenceVectorIndex.java index 849e0fd6..44ddb17c 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) 2011 + Copyright (C) 2012 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.preference; import java.util.BitSet; import java.util.Iterator; -import java.util.List; import de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.HiSC; import de.lmu.ifi.dbs.elki.data.NumberVector; @@ -33,11 +32,9 @@ 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.DBID; -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.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; @@ -120,16 +117,8 @@ public class HiSCPreferenceVectorIndex<V extends NumberVector<?, ?>> extends Abs msg.append("\n knns: "); } - List<DistanceResultPair<DoubleDistance>> knns = knnQuery.getKNNForDBID(id, k); - ModifiableDBIDs knnIDs = DBIDUtil.newArray(knns.size()); - for(DistanceResultPair<DoubleDistance> knn : knns) { - knnIDs.add(knn.getDBID()); - //if(logger.isDebugging()) { - // msg.append(database.getObjectLabelQuery().get(knn.getID())).append(" "); - //} - } - - BitSet preferenceVector = determinePreferenceVector(relation, id, knnIDs, msg); + KNNResult<DoubleDistance> knns = knnQuery.getKNNForDBID(id, k); + BitSet preferenceVector = determinePreferenceVector(relation, id, knns.asDBIDs(), msg); storage.put(id, preferenceVector); if(progress != null) { 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 1f2dd10b..c01e9ddb 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) 2011 + Copyright (C) 2012 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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/package-info.java index 7676879c..69d0855b 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) 2011 +Copyright (C) 2012 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 7920fc2b..7efe26e0 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,8 +23,8 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.snn; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +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.TreeSetDBIDs; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.index.Index; import de.lmu.ifi.dbs.elki.index.IndexFactory; @@ -41,7 +41,7 @@ public interface SharedNearestNeighborIndex<O> extends Index { * @param objid Object ID * @return Neighbor DBIDs */ - public TreeSetDBIDs getNearestNeighborSet(DBID objid); + public ArrayDBIDs getNearestNeighborSet(DBID objid); /** * Get the number of neighbors 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 43bd7e30..46f47a33 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,19 +23,16 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.snn; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.List; - import de.lmu.ifi.dbs.elki.data.type.TypeInformation; 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.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.DBIDUtil; -import de.lmu.ifi.dbs.elki.database.ids.SetDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.TreeSetDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.TreeSetModifiableDBIDs; -import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult; 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.EuclideanDistanceFunction; @@ -75,7 +72,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; */ @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, TreeSetDBIDs> implements SharedNearestNeighborIndex<O> { +public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends AbstractPreprocessorIndex<O, ArrayDBIDs> implements SharedNearestNeighborIndex<O> { /** * Get a logger for this class. */ @@ -111,23 +108,24 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends if(getLogger().isVerbose()) { getLogger().verbose("Assigning nearest neighbor lists to database objects"); } - storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, SetDBIDs.class); + storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, ArrayDBIDs.class); KNNQuery<O, D> knnquery = QueryUtil.getKNNQuery(relation, distanceFunction, numberOfNeighbors); FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("assigning nearest neighbor lists", relation.size(), getLogger()) : null; for(DBID id : relation.iterDBIDs()) { - TreeSetModifiableDBIDs neighbors = DBIDUtil.newTreeSet(numberOfNeighbors); - List<DistanceResultPair<D>> kNN = knnquery.getKNNForDBID(id, numberOfNeighbors); + ArrayModifiableDBIDs neighbors = DBIDUtil.newArray(numberOfNeighbors); + KNNResult<D> kNN = knnquery.getKNNForDBID(id, numberOfNeighbors); for(int i = 0; i < kNN.size(); i++) { final DBID nid = kNN.get(i).getDBID(); // if(!id.equals(nid)) { neighbors.add(nid); // } - // Size limitation to exaclty numberOfNeighbors + // Size limitation to exactly numberOfNeighbors if(neighbors.size() >= numberOfNeighbors) { break; } } + neighbors.sort(); storage.put(id, neighbors); if(progress != null) { progress.incrementProcessed(getLogger()); @@ -139,7 +137,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends } @Override - public TreeSetDBIDs getNearestNeighborSet(DBID objid) { + public ArrayDBIDs getNearestNeighborSet(DBID objid) { if(storage == null) { preprocess(); } @@ -269,7 +267,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends @Override protected void makeOptions(Parameterization config) { super.makeOptions(config); - final IntParameter numberOfNeighborsP = new IntParameter(NUMBER_OF_NEIGHBORS_ID, new GreaterEqualConstraint(1), 1); + final IntParameter numberOfNeighborsP = new IntParameter(NUMBER_OF_NEIGHBORS_ID, new GreaterEqualConstraint(1)); if(config.grab(numberOfNeighborsP)) { numberOfNeighbors = numberOfNeighborsP.getValue(); } 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 e29cd0e0..98065df6 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) 2011 +Copyright (C) 2012 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 index 8aef442b..4a265fc9 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/AbstractSubspaceProjectionIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/AbstractSubspaceProjectionIndex.java @@ -4,7 +4,7 @@ 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) 2011 + Copyright (C) 2012 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/FourCSubspaceIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/FourCSubspaceIndex.java index 5a7fe2e0..83a9469c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/FourCSubspaceIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/FourCSubspaceIndex.java @@ -4,7 +4,7 @@ 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) 2011 + Copyright (C) 2012 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/PreDeConSubspaceIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/PreDeConSubspaceIndex.java index cc05bcd1..1e83ae80 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/PreDeConSubspaceIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/PreDeConSubspaceIndex.java @@ -4,7 +4,7 @@ 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) 2011 + Copyright (C) 2012 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/SubspaceProjectionIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/SubspaceProjectionIndex.java index d0630aac..d5070986 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/SubspaceProjectionIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/SubspaceProjectionIndex.java @@ -4,7 +4,7 @@ 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) 2011 + Copyright (C) 2012 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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/package-info.java index b364aa09..f6e5e925 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 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 2c764231..03572b35 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) 2011 + Copyright (C) 2012 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/AbstractLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractLeafEntry.java index 2183888f..d2d38976 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) 2011 + Copyright (C) 2012 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/AbstractNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractNode.java index 242267d6..42f4fa11 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -28,14 +28,16 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Enumeration; import java.util.List; import java.util.NoSuchElementException; -import java.util.logging.Logger; +import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration; -import de.lmu.ifi.dbs.elki.persistent.AbstractPage; +import de.lmu.ifi.dbs.elki.persistent.AbstractExternalizablePage; import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil; +import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; /** * Abstract superclass for nodes in an tree based index structure. @@ -43,7 +45,7 @@ import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil; * @author Elke Achtert * @param <E> the type of Entry used in the index */ -public abstract class AbstractNode<E extends Entry> extends AbstractPage implements Node<E> { +public abstract class AbstractNode<E extends Entry> extends AbstractExternalizablePage implements Node<E> { /** * The number of entries in this node. */ @@ -155,7 +157,7 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme * both nodes are of the same type (leaf node or directory node) and have * contain the same entries, <code>false</code> otherwise. * - * @see de.lmu.ifi.dbs.elki.persistent.AbstractPage#equals(Object) + * @see de.lmu.ifi.dbs.elki.persistent.AbstractExternalizablePage#equals(Object) */ @Override public boolean equals(Object o) { @@ -276,11 +278,17 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme * Returns a list of the entries. * * @return a list of the entries + * + * @deprecated Using this method means an extra copy - usually at the cost of + * performance. */ + @Deprecated public final List<E> getEntries() { - List<E> result = new ArrayList<E>(); + List<E> result = new ArrayList<E>(numEntries); for(E entry : entries) { - result.add(entry); + if(entry != null) { + result.add(entry); + } } return result; } @@ -298,6 +306,32 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme } /** + * Remove entries according to the given mask. + * + * @param mask Mask to remove + */ + public void removeMask(BitSet mask) { + int dest = mask.nextSetBit(0); + if(dest < 0) { + return; + } + int src = mask.nextClearBit(dest); + while(src < numEntries) { + if(!mask.get(src)) { + entries[dest] = entries[src]; + dest++; + } + src++; + } + int rm = src - dest; + while(dest < numEntries) { + entries[dest] = null; + dest++; + } + numEntries -= rm; + } + + /** * Redistribute entries according to the given sorting. * * @param newNode Node to split to @@ -305,7 +339,7 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme * @param splitPoint Split point */ public final void splitTo(AbstractNode<E> newNode, List<E> sorting, int splitPoint) { - assert(isLeaf() == newNode.isLeaf()); + assert (isLeaf() == newNode.isLeaf()); deleteAllEntries(); StringBuffer msg = LoggingConfiguration.DEBUG ? new StringBuffer("\n") : null; @@ -325,7 +359,7 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme } } if(msg != null) { - Logger.getLogger(this.getClass().getName()).fine(msg.toString()); + Logging.getLogger(this.getClass().getName()).fine(msg.toString()); } } @@ -337,7 +371,7 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme * @param assignmentsToSecond the assignment to the new node */ public final void splitTo(AbstractNode<E> newNode, List<E> assignmentsToFirst, List<E> assignmentsToSecond) { - assert(isLeaf() == newNode.isLeaf()); + assert (isLeaf() == newNode.isLeaf()); deleteAllEntries(); StringBuffer msg = LoggingConfiguration.DEBUG ? new StringBuffer() : null; @@ -357,7 +391,40 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme newNode.addEntry(entry); } if(msg != null) { - Logger.getLogger(this.getClass().getName()).fine(msg.toString()); + Logging.getLogger(this.getClass()).fine(msg.toString()); + } + } + + /** + * Splits the entries of this node into a new node using the given assignments + * + * @param newNode Node to split to + * @param assignment Assignment mask + */ + public final void splitByMask(AbstractNode<E> newNode, BitSet assignment) { + assert (isLeaf() == newNode.isLeaf()); + int dest = assignment.nextSetBit(0); + if(dest < 0) { + throw new AbortException("No bits set in splitting mask."); + } + int pos = dest; + while(pos < numEntries) { + if(assignment.get(pos)) { + // Move to new node + newNode.addEntry(entries[pos]); + } + else { + // Move to new position + entries[dest] = entries[pos]; + dest++; + } + pos++; + } + final int rm = numEntries - dest; + while(dest < numEntries) { + entries[dest] = null; + dest++; } + numEntries -= rm; } }
\ No newline at end of file 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 f7f1c247..6f43de11 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) 2011 + Copyright (C) 2012 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/DirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/DirectoryEntry.java index c380dd4f..68924cae 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) 2011 + Copyright (C) 2012 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/DistanceEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.java index b7bf3e0c..3cf6dfb9 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.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) 2011 + Copyright (C) 2012 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 9ac01380..77c13d8e 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) 2011 + Copyright (C) 2012 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 fa9c0e0a..e4cdc71f 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -121,7 +121,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> { * * @return page id */ - public final Integer getRootID() { + public final int getRootID() { return getPageID(rootEntry); } @@ -141,7 +141,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> { * @return Whether the page ID is the root */ protected boolean isRoot(N page) { - return getRootID().equals(page.getPageID()); + return getRootID() == page.getPageID(); } /** @@ -150,7 +150,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> { * @param entry Entry * @return Page ID */ - protected Integer getPageID(Entry entry) { + protected int getPageID(Entry entry) { if (entry.isLeafEntry()) { throw new AbortException("Leafs do not have page ids!"); } @@ -163,7 +163,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> { * @param nodeID the page id of the node to be returned * @return the node with the specified id */ - public N getNode(Integer nodeID) { + public N getNode(int nodeID) { if(nodeID == getPageID(rootEntry)) { return getRoot(); } 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 feb134e3..560bd250 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) 2011 + Copyright (C) 2012 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 362e2daf..c6eb1269 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) 2011 + Copyright (C) 2012 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 62892a22..c288a1fe 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) 2011 + Copyright (C) 2012 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/TreeIndexFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.java index b55700ec..a170ca5b 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,9 +26,9 @@ package de.lmu.ifi.dbs.elki.index.tree; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.index.Index; import de.lmu.ifi.dbs.elki.index.IndexFactory; +import de.lmu.ifi.dbs.elki.persistent.ExternalizablePage; import de.lmu.ifi.dbs.elki.persistent.LRUCache; import de.lmu.ifi.dbs.elki.persistent.MemoryPageFile; -import de.lmu.ifi.dbs.elki.persistent.Page; import de.lmu.ifi.dbs.elki.persistent.PageFile; import de.lmu.ifi.dbs.elki.persistent.PersistentPageFile; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; @@ -124,7 +124,7 @@ public abstract class TreeIndexFactory<O, I extends Index> implements IndexFacto * @return Page file */ // FIXME: make this single-shot when filename is set! - protected <N extends Page> PageFile<N> makePageFile(Class<N> cls) { + protected <N extends ExternalizablePage> PageFile<N> makePageFile(Class<N> cls) { final PageFile<N> inner; if(fileName == null) { inner = new MemoryPageFile<N>(pageSize); 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 3bb901e3..017c3571 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) 2011 + Copyright (C) 2012 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 2309c7e5..d2800d54 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) 2011 + Copyright (C) 2012 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 606921df..b98841aa 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) 2011 + Copyright (C) 2012 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/AbstractMTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTree.java index db4b5c07..5e949e0b 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) 2011 + Copyright (C) 2012 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/AbstractMTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeFactory.java index a7d701fa..9ae50bbe 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) 2011 + Copyright (C) 2012 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/AbstractMTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeNode.java index 3fec4706..85a9571d 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) 2011 + Copyright (C) 2012 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/MTreeDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeDirectoryEntry.java index 5729115a..0b07c446 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) 2011 + Copyright (C) 2012 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/MTreeEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeEntry.java index 0683a061..f6969b92 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) 2011 + Copyright (C) 2012 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 aae51378..27fbc1ba 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) 2011 + Copyright (C) 2012 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/AbstractMkTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTree.java index 00cf45a7..ffd38a74 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) 2011 + Copyright (C) 2012 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/AbstractMkTreeUnified.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnified.java index f7135682..88013000 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) 2011 + Copyright (C) 2012 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/AbstractMkTreeUnifiedFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnifiedFactory.java index dd1648a0..51df5077 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) 2011 + Copyright (C) 2012 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/MkTreeHeader.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeHeader.java index 809bc72b..c067a86c 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) 2011 + Copyright (C) 2012 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/MkAppDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppDirectoryEntry.java index 39d420ba..ce7cf104 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) 2011 + Copyright (C) 2012 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/MkAppEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java index ef50e3bc..b6eabf7e 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) 2011 + Copyright (C) 2012 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 961cdd92..4dbf0244 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) 2011 + Copyright (C) 2012 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/MkAppTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTree.java index c0fe4523..5f92ba70 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) 2011 + Copyright (C) 2012 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/MkAppTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeFactory.java index 540182e8..233129b4 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) 2011 + Copyright (C) 2012 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/MkAppTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeIndex.java index cd7042d6..eedc52ed 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) 2011 + Copyright (C) 2012 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/MkAppTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeNode.java index cd1a1c3b..bc6a83a9 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) 2011 + Copyright (C) 2012 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/PolynomialApproximation.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/PolynomialApproximation.java index d32c1c0c..83e60e0e 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) 2011 + Copyright (C) 2012 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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/package-info.java index 674ac861..0f3cfde9 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) 2011 +Copyright (C) 2012 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 0e7ccaf7..7f2aa3fe 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) 2011 + Copyright (C) 2012 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 7924c13d..7cb5a16b 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) 2011 + Copyright (C) 2012 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 dd267d95..22b4efa4 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) 2011 + Copyright (C) 2012 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/MkCoPEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java index cd1155c3..077fb1ec 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) 2011 + Copyright (C) 2012 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 9f4da83f..0daf7950 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) 2011 + Copyright (C) 2012 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/MkCoPTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java index a2f684ad..7fe67a03 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) 2011 + Copyright (C) 2012 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/MkCoPTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeIndex.java index d920cdab..2c4ffb06 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) 2011 + Copyright (C) 2012 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/MkCoPTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeNode.java index 3fafb5fc..01fca2f2 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) 2011 + Copyright (C) 2012 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/MkCopTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCopTreeFactory.java index 67968259..8d88ee79 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) 2011 + Copyright (C) 2012 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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/package-info.java index 3679e608..516af071 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) 2011 +Copyright (C) 2012 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 0de76f2f..0781dcb1 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) 2011 + Copyright (C) 2012 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/MkMaxEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxEntry.java index 141037c7..0a7032f3 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) 2011 + Copyright (C) 2012 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 0a8ee091..29221fdc 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) 2011 + Copyright (C) 2012 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/MkMaxTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTree.java index 0e637c57..5b7dc8fc 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) 2011 + Copyright (C) 2012 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/MkMaxTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeFactory.java index ba630c4e..7e9a7753 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) 2011 + Copyright (C) 2012 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/MkMaxTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeIndex.java index e3aed27e..9e1b6d6b 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) 2011 + Copyright (C) 2012 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/MkMaxTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeNode.java index 345829f1..17f85498 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) 2011 + Copyright (C) 2012 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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/package-info.java index 4ea34e49..bcde11b4 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) 2011 +Copyright (C) 2012 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 cc431b1e..f8410ad9 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) 2011 + Copyright (C) 2012 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/MkTabEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabEntry.java index dfecc0d8..88000f5d 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) 2011 + Copyright (C) 2012 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 ad3e999f..81446718 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) 2011 + Copyright (C) 2012 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/MkTabTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTree.java index 0014593c..750dfb72 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) 2011 + Copyright (C) 2012 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/MkTabTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeFactory.java index ea4fbd36..2bc6c256 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) 2011 + Copyright (C) 2012 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/MkTabTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeIndex.java index dc59b7cc..0eb54bd1 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,9 +29,10 @@ import java.util.List; import de.lmu.ifi.dbs.elki.database.ids.DBID; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; -import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNUtil; 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; @@ -46,7 +47,6 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MetricalIndex import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MetricalIndexRangeQuery; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MkTreeRKNNQuery; import de.lmu.ifi.dbs.elki.persistent.PageFile; -import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNList; import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages; /** @@ -103,8 +103,8 @@ public class MkTabTreeIndex<O, D extends Distance<D>> extends MkTabTree<O, D> im * @return the knn distance of the object with the specified id */ private List<D> knnDistances(O object) { - List<DistanceResultPair<D>> knns = knnQuery.getKNNForObject(object, getKmax() - 1); - return KNNList.asDistanceList(knns); + KNNResult<D> knns = knnQuery.getKNNForObject(object, getKmax() - 1); + return KNNUtil.asDistanceList(knns); } @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 55dfcbde..b09ac314 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) 2011 + Copyright (C) 2012 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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/package-info.java index f03cf84a..353acaa5 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) 2011 +Copyright (C) 2012 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 4fbf50bb..201d57c3 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) 2011 +Copyright (C) 2012 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 4e9b4f9e..80955b8a 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) 2011 + Copyright (C) 2012 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/MTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeFactory.java index 190a009d..2567f81f 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) 2011 + Copyright (C) 2012 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/MTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeIndex.java index 2a6d8a91..9bcd1b02 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) 2011 + Copyright (C) 2012 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/MTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeNode.java index 26c2ae00..017e7d6c 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) 2011 + Copyright (C) 2012 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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/package-info.java index 4233b17b..a34162a8 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) 2011 +Copyright (C) 2012 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 27fc5a22..b30d1193 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) 2011 +Copyright (C) 2012 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/MetricalIndexKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexKNNQuery.java index ab99bdd9..b591f700 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -28,9 +28,9 @@ import java.util.Map; import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; 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.KNNResult; import de.lmu.ifi.dbs.elki.distance.DistanceUtil; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry; @@ -82,7 +82,7 @@ public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDis final Heap<GenericMTreeDistanceSearchCandidate<D>> pq = new UpdatableHeap<GenericMTreeDistanceSearchCandidate<D>>(); // push root - pq.add(new GenericMTreeDistanceSearchCandidate<D>(getDistanceFactory().nullDistance(), index.getRootID(), null)); + pq.add(new GenericMTreeDistanceSearchCandidate<D>(distanceQuery.nullDistance(), index.getRootID(), null)); D d_k = knnList.getKNNDistance(); // search in tree @@ -102,8 +102,8 @@ public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDis MTreeEntry<D> entry = node.getEntry(i); DBID o_r = entry.getRoutingObjectID(); D r_or = entry.getCoveringRadius(); - D d1 = o_p != null ? distanceQuery.distance(o_p, q) : getDistanceFactory().nullDistance(); - D d2 = o_p != null ? distanceQuery.distance(o_r, o_p) : getDistanceFactory().nullDistance(); + D d1 = o_p != null ? distanceQuery.distance(o_p, q) : distanceQuery.nullDistance(); + D d2 = o_p != null ? distanceQuery.distance(o_r, o_p) : distanceQuery.nullDistance(); D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1); @@ -111,7 +111,7 @@ public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDis if(diff.compareTo(sum) <= 0) { D d3 = distanceQuery.distance(o_r, q); - D d_min = DistanceUtil.max(d3.minus(r_or), getDistanceFactory().nullDistance()); + D d_min = DistanceUtil.max(d3.minus(r_or), distanceQuery.nullDistance()); if(d_min.compareTo(d_k) <= 0) { pq.add(new GenericMTreeDistanceSearchCandidate<D>(d_min, ((DirectoryEntry)entry).getPageID(), o_r)); } @@ -126,8 +126,8 @@ public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDis MTreeEntry<D> entry = node.getEntry(i); DBID o_j = entry.getRoutingObjectID(); - D d1 = o_p != null ? distanceQuery.distance(o_p, q) : getDistanceFactory().nullDistance(); - D d2 = o_p != null ? distanceQuery.distance(o_j, o_p) : getDistanceFactory().nullDistance(); + D d1 = o_p != null ? distanceQuery.distance(o_p, q) : distanceQuery.nullDistance(); + D d2 = o_p != null ? distanceQuery.distance(o_j, o_p) : distanceQuery.nullDistance(); D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1); @@ -144,23 +144,23 @@ public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDis } @Override - public List<DistanceResultPair<D>> getKNNForObject(O obj, int k) { + public KNNResult<D> getKNNForObject(O obj, int k) { if(k < 1) { throw new IllegalArgumentException("At least one object has to be requested!"); } final KNNHeap<D> knnList = new KNNHeap<D>(k, distanceQuery.getDistanceFactory().infiniteDistance()); doKNNQuery(obj, knnList); - return knnList.toSortedArrayList(); + return knnList.toKNNList(); } @Override - public List<DistanceResultPair<D>> getKNNForDBID(DBID id, int k) { + public KNNResult<D> getKNNForDBID(DBID id, int k) { return getKNNForObject(relation.get(id), k); } @Override - public List<List<DistanceResultPair<D>>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { // TODO: implement throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET); } 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 5854df8a..8536cc52 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -80,8 +80,8 @@ public class MetricalIndexRangeQuery<O, D extends Distance<D>> extends AbstractD DBID o_r = entry.getRoutingObjectID(); D r_or = entry.getCoveringRadius(); - D d1 = o_p != null ? distanceQuery.distance(o_p, q) : getDistanceFactory().nullDistance(); - D d2 = o_p != null ? entry.getParentDistance() : getDistanceFactory().nullDistance(); + D d1 = o_p != null ? distanceQuery.distance(o_p, q) : distanceQuery.nullDistance(); + D d2 = o_p != null ? entry.getParentDistance() : distanceQuery.nullDistance(); // o_p != null ? distanceFunction.distance(o_r, o_p) :/ distanceFunction.nullDistance(); D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1); @@ -104,8 +104,8 @@ public class MetricalIndexRangeQuery<O, D extends Distance<D>> extends AbstractD MTreeEntry<D> entry = node.getEntry(i); DBID o_j = entry.getRoutingObjectID(); - D d1 = o_p != null ? distanceQuery.distance(o_p, q) : getDistanceFactory().nullDistance(); - D d2 = o_p != null ? distanceQuery.distance(o_j, o_p) : getDistanceFactory().nullDistance(); + D d1 = o_p != null ? distanceQuery.distance(o_p, q) : distanceQuery.nullDistance(); + D d2 = o_p != null ? distanceQuery.distance(o_j, o_p) : distanceQuery.nullDistance(); D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1); @@ -138,8 +138,8 @@ public class MetricalIndexRangeQuery<O, D extends Distance<D>> extends AbstractD DBID o_r = entry.getRoutingObjectID(); D r_or = entry.getCoveringRadius(); - D d1 = o_p != null ? distanceQuery.distance(o_p, q) : getDistanceFactory().nullDistance(); - D d2 = o_p != null ? entry.getParentDistance() : getDistanceFactory().nullDistance(); + D d1 = o_p != null ? distanceQuery.distance(o_p, q) : distanceQuery.nullDistance(); + D d2 = o_p != null ? entry.getParentDistance() : distanceQuery.nullDistance(); // o_p != null ? distanceFunction.distance(o_r, o_p) : distanceFunction.nullDistance(); D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1); @@ -160,8 +160,8 @@ public class MetricalIndexRangeQuery<O, D extends Distance<D>> extends AbstractD MTreeEntry<D> entry = node.getEntry(i); DBID o_j = entry.getRoutingObjectID(); - D d1 = o_p != null ? distanceQuery.distance(o_p, q) : getDistanceFactory().nullDistance(); - D d2 = o_p != null ? distanceQuery.distance(o_j, o_p) : getDistanceFactory().nullDistance(); + D d1 = o_p != null ? distanceQuery.distance(o_p, q) : distanceQuery.nullDistance(); + D d2 = o_p != null ? distanceQuery.distance(o_j, o_p) : distanceQuery.nullDistance(); D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1); 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 38641128..370f26ad 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) 2011 + Copyright (C) 2012 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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/package-info.java index 9fa70aab..fa7e6248 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) 2011 +Copyright (C) 2012 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/split/Assignments.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/Assignments.java index c639f37e..5cb6c794 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/Assignments.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/Assignments.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 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/split/MLBDistSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MLBDistSplit.java index dc322960..f4da4a1a 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MLBDistSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MLBDistSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 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/split/MRadSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MRadSplit.java index c78367ed..5d6c985c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MRadSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MRadSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 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/split/MTreeSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MTreeSplit.java index a5fcb349..f9a3c248 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MTreeSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MTreeSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 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/split/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/package-info.java index 66ead37c..ed13ae73 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/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) 2011 +Copyright (C) 2012 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 bcfbd4a1..2ca4396c 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) 2011 +Copyright (C) 2012 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 40adc7c4..3ba785f2 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) 2011 +Copyright (C) 2012 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 7b1b4a03..699c8290 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) 2011 + Copyright (C) 2012 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 index 7338bdd1..dd764990 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericDistanceSearchCandidate.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericDistanceSearchCandidate.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) 2011 + Copyright (C) 2012 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/GenericMTreeDistanceSearchCandidate.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericMTreeDistanceSearchCandidate.java index b9d8ef46..e7fc0b19 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) 2011 + Copyright (C) 2012 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 2eb1d284..5b8f56f6 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) 2011 +Copyright (C) 2012 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 cf83a1a2..9833e5b5 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -27,7 +27,8 @@ import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; -import de.lmu.ifi.dbs.elki.data.HyperBoundingBox; +import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; import de.lmu.ifi.dbs.elki.index.tree.AbstractDirectoryEntry; /** @@ -45,7 +46,7 @@ public class SpatialDirectoryEntry extends AbstractDirectoryEntry implements Spa /** * The minimum bounding rectangle of the underlying spatial node. */ - private HyperBoundingBox mbr; + private ModifiableHyperBoundingBox mbr; /** * Empty constructor for serialization purposes. @@ -60,7 +61,7 @@ public class SpatialDirectoryEntry extends AbstractDirectoryEntry implements Spa * @param id the unique id of the underlying spatial node * @param mbr the minimum bounding rectangle of the underlying spatial node */ - public SpatialDirectoryEntry(int id, HyperBoundingBox mbr) { + public SpatialDirectoryEntry(int id, ModifiableHyperBoundingBox mbr) { super(id); this.mbr = mbr; } @@ -89,11 +90,20 @@ public class SpatialDirectoryEntry extends AbstractDirectoryEntry implements Spa } /** + * Test whether this entry already has an MBR. + * + * @return True when an MBR exists. + */ + public boolean hasMBR() { + return (this.mbr != null); + } + + /** * Sets the MBR of this entry. * * @param mbr the MBR to be set */ - public void setMBR(HyperBoundingBox mbr) { + public void setMBR(ModifiableHyperBoundingBox mbr) { this.mbr = mbr; } @@ -122,7 +132,17 @@ public class SpatialDirectoryEntry extends AbstractDirectoryEntry implements Spa @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { super.readExternal(in); - this.mbr = new HyperBoundingBox(); + this.mbr = new ModifiableHyperBoundingBox(); this.mbr.readExternal(in); } -} + + /** + * Extend the MBR of this node. + * + * @param responsibleMBR + * @return true when the MBR changed + */ + public boolean extendMBR(SpatialComparable responsibleMBR) { + return this.mbr.extend(responsibleMBR); + } +}
\ No newline at end of file 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 ffc96b40..c50a5ebf 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) 2011 + Copyright (C) 2012 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 1d0094dd..3b9eaa6b 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) 2011 + Copyright (C) 2012 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 2d0dd857..8bf25766 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) 2011 + Copyright (C) 2012 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.spatial; 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.index.tree.Node; /** @@ -38,6 +37,6 @@ import de.lmu.ifi.dbs.elki.index.tree.Node; * @param <N> Self reference * @param <E> Entry type */ -public interface SpatialNode<N extends SpatialNode<N, E>, E extends SpatialEntry> extends Node<E>, SpatialComparable { +public interface SpatialNode<N extends SpatialNode<N, E>, E extends SpatialEntry> extends Node<E> { // No additional methods. -} +}
\ No newline at end of file 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 57fb6932..f29680e7 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) 2011 + Copyright (C) 2012 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 c3cd20d3..0911a9c0 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) 2011 + Copyright (C) 2012 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 f7a747fe..fb5c67ee 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 @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2011 +Copyright (C) 2012 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 4fafe1bb..e50e0cb4 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -27,22 +27,17 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; +import java.util.BitSet; import java.util.List; -import java.util.Map; import java.util.Stack; import de.lmu.ifi.dbs.elki.data.HyperBoundingBox; +import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox; import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; 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.distancefunction.EuclideanDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; import de.lmu.ifi.dbs.elki.index.tree.BreadthFirstEnumeration; -import de.lmu.ifi.dbs.elki.index.tree.DistanceEntry; 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; @@ -51,16 +46,17 @@ 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.SpatialIndexTree; import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialPointLeafEntry; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk.BulkSplit; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.Enlargement; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.LeastOverlapInsertionStrategy; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.SplitStrategy; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.TopologicalSplitter; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.InsertionStrategy; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.LeastOverlapInsertionStrategy; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.LimitedReinsertOverflowTreatment; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.OverflowTreatment; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.SplitStrategy; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.TopologicalSplitter; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.NodeArrayAdapter; import de.lmu.ifi.dbs.elki.persistent.PageFile; import de.lmu.ifi.dbs.elki.persistent.PageFileUtil; import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; -import de.lmu.ifi.dbs.elki.utilities.pairs.Pair; /** * Abstract superclass for index structures based on a R*-Tree. @@ -87,13 +83,6 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E protected final static boolean extraIntegrityChecks = false; /** - * Contains a boolean for each level of this R*-Tree that indicates if there - * was already a reinsert operation in this level during the current insert / - * delete operation. - */ - protected final Map<Integer, Boolean> reinsertions = new HashMap<Integer, Boolean>(); - - /** * The height of this R*-Tree. */ protected int height; @@ -116,33 +105,88 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E /** * The split strategy */ - protected SplitStrategy<? super E> nodeSplitter = new TopologicalSplitter(); + protected SplitStrategy nodeSplitter = TopologicalSplitter.STATIC; /** * The insertion strategy to use */ - protected final InsertionStrategy insertionStrategy; + protected InsertionStrategy insertionStrategy = LeastOverlapInsertionStrategy.STATIC; + + /** + * Overflow treatment + */ + protected OverflowTreatment overflowTreatment = LimitedReinsertOverflowTreatment.RSTAR_OVERFLOW; + + /** + * Relative minimum fill + */ + protected double relativeMinFill = 0.4; /** * Constructor * * @param pagefile Page file - * @param bulkSplitter bulk load strategy - * @param insertionStrategy the strategy for finding the insertion candidate. */ - public AbstractRStarTree(PageFile<N> pagefile, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) { + public AbstractRStarTree(PageFile<N> pagefile) { super(pagefile); + } + + /** + * Set the bulk loading strategy + * + * @param bulkSplitter Bulk loading strategy + */ + public void setBulkStrategy(BulkSplit bulkSplitter) { this.bulkSplitter = bulkSplitter; + } + + /** + * Set the node splitting strategy. + * + * @param nodeSplitter the split strategy to set + */ + public void setNodeSplitStrategy(SplitStrategy nodeSplitter) { + if(nodeSplitter != null) { + this.nodeSplitter = nodeSplitter; + } + else { + getLogger().warning("Ignoring setNodeSplitStrategy(null)"); + } + } + + /** + * Set insertion strategy + * + * @param insertionStrategy the insertion strategy to set + */ + public void setInsertionStrategy(InsertionStrategy insertionStrategy) { if(insertionStrategy != null) { this.insertionStrategy = insertionStrategy; } else { - getLogger().warning("No insertion strategy given - falling back to " + LeastOverlapInsertionStrategy.class.getSimpleName()); - this.insertionStrategy = new LeastOverlapInsertionStrategy(); + getLogger().warning("Ignoring setInsertionStrategy(null)"); } } /** + * Set the overflow treatment strategy. + * + * @param overflowTreatment overflow treatment strategy + */ + public void setOverflowTreatment(OverflowTreatment overflowTreatment) { + this.overflowTreatment = overflowTreatment; + } + + /** + * Set the relative minimum fill. (Only supported before the tree was used!) + * + * @param relative Relative minimum fill + */ + public void setMinimumFill(double relative) { + this.relativeMinFill = relative; + } + + /** * Returns the path to the leaf entry in the specified subtree that represents * the data object with the specified mbr and id. * @@ -181,7 +225,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E if(!initialized) { initialize(leaf); } - reinsertions.clear(); + overflowTreatment.reinitialize(); preInsert(leaf); insertLeafEntry(leaf); @@ -200,7 +244,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E IndexTreePath<E> subtree = choosePath(getRootPath(), entry, 1); if(getLogger().isDebugging()) { - getLogger().debugFine("insertion-subtree " + subtree + "\n"); + getLogger().debugFine("insertion-subtree " + subtree); } N parent = getNode(subtree.getLastPathComponent().getEntry()); @@ -257,7 +301,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E N node = stack.pop(); if(node.isLeaf()) { for(int i = 0; i < node.getNumEntries(); i++) { - reinsertions.clear(); + overflowTreatment.reinitialize(); // Intended? this.insertLeafEntry(node.getEntry(i)); } } @@ -315,7 +359,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E int cap = 0; ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); - HyperBoundingBox hb = new HyperBoundingBox(new double[exampleLeaf.getDimensionality()], new double[exampleLeaf.getDimensionality()]); + ModifiableHyperBoundingBox hb = new ModifiableHyperBoundingBox(new double[exampleLeaf.getDimensionality()], new double[exampleLeaf.getDimensionality()]); SpatialDirectoryEntry sl = new SpatialDirectoryEntry(0, hb); while(baos.size() <= getPageSize()) { sl.writeExternal(oos); @@ -337,7 +381,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E } // minimum entries per directory node - dirMinimum = (int) Math.round((dirCapacity - 1) * 0.4); + dirMinimum = (int) Math.round((dirCapacity - 1) * relativeMinFill); if(dirMinimum < 2) { dirMinimum = 2; } @@ -351,7 +395,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E } // minimum entries per leaf node - leafMinimum = (int) Math.round((leafCapacity - 1) * 0.4); + leafMinimum = (int) Math.round((leafCapacity - 1) * relativeMinFill); if(leafMinimum < 2) { leafMinimum = 2; } @@ -376,33 +420,31 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E * @param objects the objects to be inserted * @return the array of leaf nodes containing the objects */ - protected List<N> createBulkLeafNodes(List<E> objects) { + protected List<E> createBulkLeafNodes(List<E> objects) { int minEntries = leafMinimum; int maxEntries = leafCapacity - 1; - - ArrayList<N> result = new ArrayList<N>(); + + ArrayList<E> result = new ArrayList<E>(); List<List<E>> partitions = bulkSplitter.partition(objects, minEntries, maxEntries); - + for(List<E> partition : partitions) { // create leaf node N leafNode = createNewLeafNode(); - result.add(leafNode); - + // insert data for(E o : partition) { leafNode.addLeafEntry(o); } - // write to file writeNode(leafNode); - + + result.add(createNewDirectoryEntry(leafNode)); + if(getLogger().isDebugging()) { - StringBuffer msg = new StringBuffer(); - msg.append("pageNo ").append(leafNode.getPageID()).append("\n"); - getLogger().debugFine(msg.toString()); + getLogger().debugFine("Created leaf page "+leafNode.getPageID()); } } - + if(getLogger().isDebugging()) { getLogger().debugFine("numDataPages = " + result.size()); } @@ -441,13 +483,6 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E abstract protected int computeHeight(); /** - * Clears the reinsertions. - */ - protected void clearReinsertions() { - reinsertions.clear(); - } - - /** * Returns true if in the specified node an overflow occurred, false * otherwise. * @@ -486,7 +521,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E protected IndexTreePath<E> createNewRoot(final N oldRoot, final N newNode) { N root = createNewDirectoryNode(); writeNode(root); - + // switch the ids oldRoot.setPageID(root.getPageID()); if(!oldRoot.isLeaf()) { @@ -495,24 +530,24 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E writeNode(node); } } - + root.setPageID(getRootID()); E oldRootEntry = createNewDirectoryEntry(oldRoot); E newNodeEntry = createNewDirectoryEntry(newNode); root.addDirectoryEntry(oldRootEntry); root.addDirectoryEntry(newNodeEntry); - + writeNode(root); writeNode(oldRoot); writeNode(newNode); if(getLogger().isDebugging()) { String msg = "Create new Root: ID=" + root.getPageID(); - msg += "\nchild1 " + oldRoot + " " + new HyperBoundingBox(oldRoot) + " " + new HyperBoundingBox(oldRootEntry); - msg += "\nchild2 " + newNode + " " + new HyperBoundingBox(newNode) + " " + new HyperBoundingBox(newNodeEntry); + msg += "\nchild1 " + oldRoot + " " + new HyperBoundingBox(oldRootEntry); + msg += "\nchild2 " + newNode + " " + new HyperBoundingBox(newNodeEntry); msg += "\n"; getLogger().debugFine(msg); } - + return new IndexTreePath<E>(new TreeIndexPathComponent<E>(getRootEntry(), null)); } @@ -591,10 +626,11 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E } N childNode = getNode(node.getEntry(0)); + int num = insertionStrategy.choose(node, NodeArrayAdapter.STATIC, mbr, height, subtree.getPathCount()); + TreeIndexPathComponent<E> comp = new TreeIndexPathComponent<E>(node.getEntry(num), num); // children are leafs if(childNode.isLeaf()) { if(height - subtree.getPathCount() == level) { - TreeIndexPathComponent<E> comp = insertionStrategy.findInsertChild(node, mbr); return subtree.pathByAddingChild(comp); } else { @@ -603,7 +639,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E } // children are directory nodes else { - IndexTreePath<E> newSubtree = subtree.pathByAddingChild(getLeastEnlargement(node, mbr)); + IndexTreePath<E> newSubtree = subtree.pathByAddingChild(comp); // desired level is reached if(height - subtree.getPathCount() == level) { return newSubtree; @@ -615,34 +651,6 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E } /** - * Returns the path information of the entry of the specified node with the - * least enlargement if the given mbr would be inserted into. - * - * @param node the node which children have to be tested - * @param mbr the mbr of the node to be inserted - * @return the path information of the entry with the least enlargement if the - * given mbr would be inserted into - */ - private TreeIndexPathComponent<E> getLeastEnlargement(N node, SpatialComparable mbr) { - Enlargement<E> min = null; - - for(int i = 0; i < node.getNumEntries(); i++) { - E entry = node.getEntry(i); - double volume = SpatialUtil.volume(entry); - HyperBoundingBox newMBR = SpatialUtil.union(entry, mbr); - double inc = SpatialUtil.volume(newMBR) - volume; - Enlargement<E> enlargement = new Enlargement<E>(new TreeIndexPathComponent<E>(entry, i), volume, inc, 0); - - if(min == null || min.compareTo(enlargement) > 0) { - min = enlargement; - } - } - - assert min != null; - return min.getPathComponent(); - } - - /** * Treatment of overflow in the specified node: if the node is not the root * node and this is the first call of overflowTreatment in the given level * during insertion the specified node will be reinserted, otherwise the node @@ -654,23 +662,10 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E * reinsertion */ private N overflowTreatment(N node, IndexTreePath<E> path) { - int level = height - path.getPathCount() + 1; - Boolean reInsert = reinsertions.get(level); - - // there was still no reinsert operation at this level - if(node.getPageID() != 0 && (reInsert == null || !reInsert)) { - reinsertions.put(level, true); - if(getLogger().isDebugging()) { - getLogger().debugFine("REINSERT " + reinsertions + "\n"); - } - reInsert(node, level, path); + if(overflowTreatment.handleOverflow(this, node, path)) { return null; } - - // there was already a reinsert operation at this level - else { - return split(node); - } + return split(node); } /** @@ -682,7 +677,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E private N split(N node) { // choose the split dimension and the split point int minimum = node.isLeaf() ? leafMinimum : dirMinimum; - Pair<List<E>, List<E>> split = nodeSplitter.split(node.getEntries(), minimum); + BitSet split = nodeSplitter.split(node, NodeArrayAdapter.STATIC, minimum); // New node final N newNode; @@ -693,22 +688,12 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E newNode = createNewDirectoryNode(); } // do the split - node.deleteAllEntries(); - node.splitTo(newNode, split.first, split.second); + node.splitByMask(newNode, split); // write changes to file writeNode(node); writeNode(newNode); - // if(getLogger().isDebugging()) { - // StringBuffer msg = new StringBuffer(); - // msg.append("Split Node ").append(node.getPageID()).append(" (").append(getClass()).append(")\n"); - // msg.append(" splitAxis ").append(split.getSplitAxis()).append("\n"); - // msg.append(" splitPoint ").append(split.getSplitPoint()).append("\n"); - // msg.append(" newNode ").append(newNode.getPageID()).append("\n"); - // getLogger().debugFine(msg.toString()); - // } - return newNode; } @@ -716,29 +701,20 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E * Reinserts the specified node at the specified level. * * @param node the node to be reinserted - * @param level the level of the node * @param path the path to the node + * @param offs the nodes indexes to reinsert */ - @SuppressWarnings("unchecked") - protected void reInsert(N node, int level, IndexTreePath<E> path) { - EuclideanDistanceFunction distFunction = EuclideanDistanceFunction.STATIC; - DistanceEntry<DoubleDistance, E>[] reInsertEntries = new DistanceEntry[node.getNumEntries()]; + public void reInsert(N node, IndexTreePath<E> path, int[] offs) { + final int level = height - (path.getPathCount() - 1); - // compute the center distances of entries to the node and sort it - // in decreasing order to their distances - for(int i = 0; i < node.getNumEntries(); i++) { - E entry = node.getEntry(i); - DoubleDistance dist = distFunction.centerDistance(node, entry); - reInsertEntries[i] = new DistanceEntry<DoubleDistance, E>(entry, dist, i); + BitSet remove = new BitSet(); + List<E> reInsertEntries = new ArrayList<E>(offs.length); + for(int i = 0; i < offs.length; i++) { + reInsertEntries.add(node.getEntry(offs[i])); + remove.set(offs[i]); } - Arrays.sort(reInsertEntries, Collections.reverseOrder()); - - // define, how many entries will be reinserted - int start = (int) (0.3 * node.getNumEntries()); - - // initialize the reinsertion operation: move the remaining entries - // forward - node.initReInsert(start, reInsertEntries); + // Remove the entries we reinsert + node.removeMask(remove); writeNode(node); // and adapt the mbrs @@ -747,26 +723,30 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E while(childPath.getParentPath() != null) { N parent = getNode(childPath.getParentPath().getLastPathComponent().getEntry()); int indexOfChild = childPath.getLastPathComponent().getIndex(); - child.adjustEntry(parent.getEntry(indexOfChild)); - writeNode(parent); - childPath = childPath.getParentPath(); - child = parent; + if(child.adjustEntry(parent.getEntry(indexOfChild))) { + writeNode(parent); + childPath = childPath.getParentPath(); + child = parent; + } + else { + break; + // TODO: stop writing when MBR didn't change! + } } // reinsert the first entries - for(int i = 0; i < start; i++) { - DistanceEntry<DoubleDistance, E> re = reInsertEntries[i]; + for(E entry : reInsertEntries) { if(node.isLeaf()) { if(getLogger().isDebugging()) { - getLogger().debugFine("reinsert " + re.getEntry()); + getLogger().debug("reinsert " + entry); } - insertLeafEntry(re.getEntry()); + insertLeafEntry(entry); } else { if(getLogger().isDebugging()) { - getLogger().debugFine("reinsert " + re.getEntry() + " at " + level); + getLogger().debug("reinsert " + entry + " at " + level); } - insertDirectoryEntry(re.getEntry(), level); + insertDirectoryEntry(entry, level); } } } @@ -778,7 +758,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E */ protected void adjustTree(IndexTreePath<E> subtree) { if(getLogger().isDebugging()) { - getLogger().debugFine("Adjust tree " + subtree + "\n"); + getLogger().debugFine("Adjust tree " + subtree); } // get the root of the subtree @@ -826,11 +806,13 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E if(!isRoot(node)) { N parent = getNode(subtree.getParentPath().getLastPathComponent().getEntry()); E entry = parent.getEntry(subtree.getLastPathComponent().getIndex()); - lastInsertedEntry = node.adjustEntryIncremental(entry, lastInsertedEntry); - // node.adjustEntry(parent.getEntry(index)); - // write changes in parent to file - writeNode(parent); - adjustTree(subtree.getParentPath()); + boolean changed = node.adjustEntryIncremental(entry, lastInsertedEntry); + if(changed) { + // node.adjustEntry(parent.getEntry(index)); + // write changes in parent to file + writeNode(parent); + adjustTree(subtree.getParentPath()); + } } // root level is reached else { @@ -896,12 +878,12 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E @Override public final List<E> getLeaves() { List<E> result = new ArrayList<E>(); - + if(height == 1) { result.add(getRootEntry()); return result; } - + getLeafNodes(getRoot(), result, height); return result; } @@ -949,11 +931,11 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E int leafNodes = 0; int objects = 0; int levels = 0; - + if(initialized) { N node = getRoot(); - int dim = node.getDimensionality(); - + int dim = getRootEntry().getDimensionality(); + while(!node.isLeaf()) { if(node.getNumEntries() > 0) { E entry = node.getEntry(0); @@ -961,7 +943,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E levels++; } } - + BreadthFirstEnumeration<N, E> enumeration = new BreadthFirstEnumeration<N, E>(this, getRootPath()); while(enumeration.hasMoreElements()) { IndexTreePath<E> indexPath = enumeration.nextElement(); @@ -988,7 +970,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E else { result.append(getClass().getName()).append(" is empty!\n"); } - + return result.toString(); } }
\ No newline at end of file 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 5a0b9975..e2bb3abb 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,12 +29,18 @@ import de.lmu.ifi.dbs.elki.data.type.TypeUtil; import de.lmu.ifi.dbs.elki.index.Index; import de.lmu.ifi.dbs.elki.index.tree.TreeIndexFactory; import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk.BulkSplit; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.LeastOverlapInsertionStrategy; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.CombinedInsertionStrategy; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.InsertionStrategy; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.LimitedReinsertOverflowTreatment; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.OverflowTreatment; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.SplitStrategy; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.TopologicalSplitter; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.IntervalConstraint; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.IntervalConstraint.IntervalBoundary; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassParameter; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; /** @@ -57,11 +63,26 @@ public abstract class AbstractRStarTreeFactory<O extends NumberVector<O, ?>, N e public static OptionID INSERTION_STRATEGY_ID = OptionID.getOrCreateOptionID("rtree.insertionstrategy", "The strategy to use for object insertion."); /** + * Split strategy parameter. Optional. + */ + public static OptionID SPLIT_STRATEGY_ID = OptionID.getOrCreateOptionID("rtree.splitstrategy", "The strategy to use for node splitting."); + + /** * Parameter for bulk strategy */ public static final OptionID BULK_SPLIT_ID = OptionID.getOrCreateOptionID("spatial.bulkstrategy", "The class to perform the bulk split with."); /** + * Parameter for the relative minimum fill. + */ + public static final OptionID MINIMUM_FILL_ID = OptionID.getOrCreateOptionID("rtree.minimum-fill", "Minimum relative fill required for data pages."); + + /** + * Overflow treatment. + */ + public static OptionID OVERFLOW_STRATEGY_ID = OptionID.getOrCreateOptionID("rtree.overflowtreatment", "The strategy to use for handling overflows."); + + /** * Strategy to find the insertion node with. */ protected InsertionStrategy insertionStrategy; @@ -72,6 +93,21 @@ public abstract class AbstractRStarTreeFactory<O extends NumberVector<O, ?>, N e protected BulkSplit bulkSplitter; /** + * The strategy for splitting nodes + */ + protected SplitStrategy nodeSplitter; + + /** + * Overflow treatment strategy + */ + protected OverflowTreatment overflowTreatment; + + /** + * Relative minimum fill + */ + protected double minimumFill; + + /** * Constructor. * * @param fileName @@ -79,11 +115,17 @@ public abstract class AbstractRStarTreeFactory<O extends NumberVector<O, ?>, N e * @param cacheSize * @param bulkSplitter the strategy to use for bulk splitting * @param insertionStrategy the strategy to find the insertion child + * @param nodeSplitter the strategy to use for splitting nodes + * @param overflowTreatment the strategy to use for overflow treatment + * @param minimumFill the relative minimum fill */ - public AbstractRStarTreeFactory(String fileName, int pageSize, long cacheSize, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) { + public AbstractRStarTreeFactory(String fileName, int pageSize, long cacheSize, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy, SplitStrategy nodeSplitter, OverflowTreatment overflowTreatment, double minimumFill) { super(fileName, pageSize, cacheSize); this.insertionStrategy = insertionStrategy; this.bulkSplitter = bulkSplitter; + this.nodeSplitter = nodeSplitter; + this.overflowTreatment = overflowTreatment; + this.minimumFill = minimumFill; } @Override @@ -99,18 +141,51 @@ public abstract class AbstractRStarTreeFactory<O extends NumberVector<O, ?>, N e * @apiviz.exclude */ public static abstract class Parameterizer<O extends NumberVector<O, ?>> extends TreeIndexFactory.Parameterizer<O> { + /** + * Insertion strategy + */ + protected InsertionStrategy insertionStrategy = null; + + /** + * The strategy for splitting nodes + */ + protected SplitStrategy nodeSplitter = null; + + /** + * Bulk loading strategy + */ protected BulkSplit bulkSplitter = null; - protected InsertionStrategy insertionStrategy = null; + /** + * Overflow treatment strategy + */ + protected OverflowTreatment overflowTreatment = null; + + /** + * Relative minimum fill + */ + protected double minimumFill; @Override protected void makeOptions(Parameterization config) { super.makeOptions(config); - configBulkLoad(config); - ClassParameter<InsertionStrategy> insertionStrategyP = new ClassParameter<InsertionStrategy>(INSERTION_STRATEGY_ID, InsertionStrategy.class, LeastOverlapInsertionStrategy.class); + ObjectParameter<InsertionStrategy> insertionStrategyP = new ObjectParameter<InsertionStrategy>(INSERTION_STRATEGY_ID, InsertionStrategy.class, CombinedInsertionStrategy.class); if(config.grab(insertionStrategyP)) { insertionStrategy = insertionStrategyP.instantiateClass(config); } + ObjectParameter<SplitStrategy> splitStrategyP = new ObjectParameter<SplitStrategy>(SPLIT_STRATEGY_ID, SplitStrategy.class, TopologicalSplitter.class); + if(config.grab(splitStrategyP)) { + nodeSplitter = splitStrategyP.instantiateClass(config); + } + DoubleParameter minimumFillP = new DoubleParameter(MINIMUM_FILL_ID, new IntervalConstraint(0.0, IntervalBoundary.OPEN, 0.5, IntervalBoundary.OPEN), 0.4); + if (config.grab(minimumFillP)) { + minimumFill = minimumFillP.getValue(); + } + ObjectParameter<OverflowTreatment> overflowP = new ObjectParameter<OverflowTreatment>(OVERFLOW_STRATEGY_ID, OverflowTreatment.class, LimitedReinsertOverflowTreatment.class); + if(config.grab(overflowP)) { + overflowTreatment = overflowP.instantiateClass(config); + } + configBulkLoad(config); } /** 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 330d5aa7..46e3003e 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,11 +29,10 @@ import java.io.ObjectOutput; import java.util.logging.Logger; import de.lmu.ifi.dbs.elki.data.HyperBoundingBox; +import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox; 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.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.tree.AbstractNode; -import de.lmu.ifi.dbs.elki.index.tree.DistanceEntry; 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.SpatialNode; @@ -67,56 +66,22 @@ public abstract class AbstractRStarTreeNode<N extends AbstractRStarTreeNode<N, E super(capacity, isLeaf, eclass); } - @Override - public double getMin(int dimension) { - double min = getEntry(0).getMin(dimension); - for(int i = 1; i < getNumEntries(); i++) { - min = Math.min(min, getEntry(i).getMin(dimension)); - } - return min; - } - - @Override - public double getMax(int dimension) { - double max = getEntry(0).getMax(dimension); - for(int i = 1; i < getNumEntries(); i++) { - max = Math.min(max, getEntry(i).getMax(dimension)); - } - return max; - } - /** * Recomputing the MBR is rather expensive. * * @return MBR */ - public HyperBoundingBox computeMBR() { + public ModifiableHyperBoundingBox computeMBR() { E firstEntry = getEntry(0); if(firstEntry == null) { return null; } - int dim = firstEntry.getDimensionality(); // Note: we deliberately get a cloned copy here, since we will modify it. - double[] min = SpatialUtil.getMin(firstEntry); - double[] max = SpatialUtil.getMax(firstEntry); - - for(int i = 1; i < getNumEntries(); i++) { - SpatialComparable mbr = getEntry(i); - for(int d = 1; d <= dim; d++) { - if(min[d - 1] > mbr.getMin(d)) { - min[d - 1] = mbr.getMin(d); - } - if(max[d - 1] < mbr.getMax(d)) { - max[d - 1] = mbr.getMax(d); - } - } + ModifiableHyperBoundingBox mbr = new ModifiableHyperBoundingBox(firstEntry); + for(int i = 1; i < numEntries; i++) { + mbr.extend(getEntry(i)); } - return new HyperBoundingBox(min, max); - } - - @Override - public int getDimensionality() { - return getEntry(0).getDimensionality(); + return mbr; } /** @@ -124,8 +89,31 @@ public abstract class AbstractRStarTreeNode<N extends AbstractRStarTreeNode<N, E * * @param entry the entry representing this node */ - public void adjustEntry(E entry) { - ((SpatialDirectoryEntry)entry).setMBR(computeMBR()); + public boolean adjustEntry(E entry) { + final SpatialDirectoryEntry se = (SpatialDirectoryEntry) entry; + final ModifiableHyperBoundingBox mbr = computeMBR(); + boolean changed = false; + if(se.hasMBR()) { + final int dim = se.getDimensionality(); + // Test for changes + for(int i = 1; i <= dim; i++) { + if(Math.abs(se.getMin(i) - mbr.getMin(i)) > Float.MIN_NORMAL) { + changed = true; + break; + } + if(Math.abs(se.getMax(i) - mbr.getMax(i)) > Float.MIN_NORMAL) { + changed = true; + break; + } + } + } + else { // No preexisting MBR. + changed = true; + } + if(changed) { + se.setMBR(mbr); + } + return changed; } /** @@ -135,33 +123,10 @@ public abstract class AbstractRStarTreeNode<N extends AbstractRStarTreeNode<N, E * @param entry the entry representing this node * @param responsibleMBR the MBR of the object or node which is responsible * for the call of the method - * @return the MBR of the new Node - */ - public E adjustEntryIncremental(E entry, SpatialComparable responsibleMBR) { - ((SpatialDirectoryEntry)entry).setMBR(SpatialUtil.union(entry, responsibleMBR)); - return entry; - } - - /** - * * Initializes a reinsert operation. Deletes all entries in this node and - * adds all entries from start index on to this node's children. - * - * @param start the start index of the entries that will be reinserted - * @param reInsertEntries the array of entries to be reinserted + * @return true when the entry has changed */ - protected <D extends Distance<D>> void initReInsert(int start, DistanceEntry<D, E>[] reInsertEntries) { - deleteAllEntries(); - - if(isLeaf()) { - for(int i = start; i < reInsertEntries.length; i++) { - addLeafEntry(reInsertEntries[i].getEntry()); - } - } - else { - for(int i = start; i < reInsertEntries.length; i++) { - addDirectoryEntry(reInsertEntries[i].getEntry()); - } - } + public boolean adjustEntryIncremental(E entry, SpatialComparable responsibleMBR) { + return ((SpatialDirectoryEntry) entry).extendMBR(responsibleMBR); } /** 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 20ae3826..41882ce2 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,13 +26,9 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants; import java.util.ArrayList; import java.util.List; -import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; 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.bulk.BulkSplit; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy; import de.lmu.ifi.dbs.elki.persistent.PageFile; -import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; /** * Abstract superclass for all non-flat R*-Tree variants. @@ -47,11 +43,9 @@ public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E * Constructor. * * @param pagefile Page file - * @param bulkSplitter bulk load strategy - * @param insertionStrategy the strategy to find the child to insert to */ - public NonFlatRStarTree(PageFile<N> pagefile, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) { - super(pagefile, bulkSplitter, insertionStrategy); + public NonFlatRStarTree(PageFile<N> pagefile) { + super(pagefile); } /** @@ -128,7 +122,7 @@ public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E StringBuffer msg = getLogger().isDebuggingFine() ? new StringBuffer() : null; - // Tiny tree that fit into a single page + // Tiny tree that fits into a single page if(spatialObjects.size() <= leafCapacity) { N root = createNewLeafNode(); root.setPageID(getRootID()); @@ -146,7 +140,7 @@ public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E writeNode(root); // create leaf nodes - List<N> nodes = createBulkLeafNodes(spatialObjects); + List<E> nodes = createBulkLeafNodes(spatialObjects); int numNodes = nodes.size(); if(msg != null) { @@ -156,13 +150,13 @@ public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E // create directory nodes while(nodes.size() > (dirCapacity - 1)) { - nodes = createDirectoryNodes(nodes); + nodes = createBulkDirectoryNodes(nodes); numNodes += nodes.size(); setHeight(getHeight() + 1); } // create root - createRoot(root, new ArrayList<N>(nodes)); + createRoot(root, nodes); numNodes++; setHeight(getHeight() + 1); if(msg != null) { @@ -182,30 +176,26 @@ public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E * @param nodes the nodes to be inserted * @return the directory nodes containing the nodes */ - private List<N> createDirectoryNodes(List<N> nodes) { + private List<E> createBulkDirectoryNodes(List<E> nodes) { int minEntries = dirMinimum; int maxEntries = dirCapacity - 1; - ArrayList<N> result = new ArrayList<N>(); - List<List<N>> partitions = bulkSplitter.partition(nodes, minEntries, maxEntries); + ArrayList<E> result = new ArrayList<E>(); + List<List<E>> partitions = bulkSplitter.partition(nodes, minEntries, maxEntries); - for(List<N> partition : partitions) { + for(List<E> partition : partitions) { // create node N dirNode = createNewDirectoryNode(); - writeNode(dirNode); - result.add(dirNode); - // insert nodes - for(N o : partition) { - dirNode.addDirectoryEntry(createNewDirectoryEntry(o)); + for(E o : partition) { + dirNode.addDirectoryEntry(o); } - // write to file writeNode(dirNode); + + result.add(createNewDirectoryEntry(dirNode)); if(getLogger().isDebuggingFiner()) { - StringBuffer msg = new StringBuffer(); - msg.append("\npageNo ").append(dirNode.getPageID()); - getLogger().debugFiner(msg.toString() + "\n"); + getLogger().debugFiner("Directory page no: "+dirNode.getPageID()); } } @@ -221,17 +211,14 @@ public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E * @param objects the spatial objects to be inserted * @return the root node */ - @SuppressWarnings("unchecked") - private N createRoot(N root, List<? extends SpatialComparable> objects) { + private N createRoot(N root, List<E> objects) { // insert data - for(SpatialComparable object : objects) { - if(object instanceof SpatialEntry) { - E entry = (E) object; + for(E entry : objects) { + if (entry.isLeafEntry()) { root.addLeafEntry(entry); - throw new AbortException("Unexpected spatial comparable encountered."); } else { - root.addDirectoryEntry(createNewDirectoryEntry((N) object)); + root.addDirectoryEntry(entry); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/ZCurveBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/ZCurveBulkSplit.java deleted file mode 100644 index 61e07960..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/ZCurveBulkSplit.java +++ /dev/null @@ -1,184 +0,0 @@ -package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk; - -/* - This file is part of ELKI: - Environment for Developing KDD-Applications Supported by Index-Structures - - Copyright (C) 2011 - 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.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; -import de.lmu.ifi.dbs.elki.logging.Logging; -import de.lmu.ifi.dbs.elki.math.spacefillingcurves.ZCurve; - -/** - * Bulk split that orders object by their Z curve position, then splits them - * into pages accordingly. - * - * @author Elke Achtert - */ -public class ZCurveBulkSplit extends AbstractBulkSplit { - /** - * Logger. - */ - private static final Logging logger = Logging.getLogger(ZCurveBulkSplit.class); - - /** - * Constructor - */ - public ZCurveBulkSplit() { - // Nothing to do - } - - /** - * Partitions the specified feature vectors - * - * @param spatialObjects the spatial objects to be partitioned - * @param minEntries the minimum number of entries in a partition - * @param maxEntries the maximum number of entries in a partition - * @param <N> object type - * @return the partition of the specified spatial objects - */ - @Override - public <N extends SpatialComparable> List<List<N>> partition(List<N> spatialObjects, int minEntries, int maxEntries) { - List<List<N>> partitions = new ArrayList<List<N>>(); - List<N> objects = new ArrayList<N>(spatialObjects); - - // one dimensional special case - if(spatialObjects.size() > 0 && spatialObjects.get(0).getDimensionality() == 1) { - // TODO: move this Comparator into shared code. - Collections.sort(objects, new Comparator<SpatialComparable>() { - @Override - public int compare(SpatialComparable o1, SpatialComparable o2) { - return Double.compare(o1.getMin(1), o2.getMin(1)); - } - }); - - // build partitions - // reinitialize array with correct size. Array will not use more space - // than necessary. - int numberPartitions = (int) Math.ceil(1d * spatialObjects.size() / maxEntries); - partitions = new ArrayList<List<N>>(numberPartitions); - List<N> onePartition = null; - for(N o : objects) { - if(onePartition == null || onePartition.size() >= maxEntries) { - onePartition = new ArrayList<N>(maxEntries); - partitions.add(onePartition); - } - onePartition.add(o); - } - - // okay, check last partition for underfill - // only check if there is more than 1 partition - if(partitions.size() > 1) { - List<N> last = partitions.get(partitions.size() - 1); - List<N> nextToLast = partitions.get(partitions.size() - 2); - while(last.size() < minEntries) { - last.add(0, nextToLast.remove(nextToLast.size() - 1)); - } - } - return partitions; - } - - // get z-values - List<double[]> valuesList = new ArrayList<double[]>(); - for(SpatialComparable o : spatialObjects) { - double[] values = new double[o.getDimensionality()]; - for(int d = 0; d < o.getDimensionality(); d++) { - values[d] = o.getMin(d + 1); - } - valuesList.add(values); - } - if(logger.isDebugging()) { - logger.debugFine(valuesList.toString()); - } - List<byte[]> zValuesList = ZCurve.zValues(valuesList); - - // map z-values - final Map<SpatialComparable, byte[]> zValues = new HashMap<SpatialComparable, byte[]>(); - for(int i = 0; i < spatialObjects.size(); i++) { - SpatialComparable o = spatialObjects.get(i); - byte[] zValue = zValuesList.get(i); - zValues.put(o, zValue); - } - - // create a comparator - Comparator<SpatialComparable> comparator = new Comparator<SpatialComparable>() { - @Override - public int compare(SpatialComparable o1, SpatialComparable o2) { - byte[] z1 = zValues.get(o1); - byte[] z2 = zValues.get(o2); - - for(int i = 0; i < z1.length; i++) { - byte z1_i = z1[i]; - byte z2_i = z2[i]; - if(z1_i < z2_i) { - return -1; - } - else if(z1_i > z2_i) { - return +1; - } - } - if(o1 instanceof Comparable) { - try { - @SuppressWarnings("unchecked") - final Comparable<Object> comparable = (Comparable<Object>) o1; - return comparable.compareTo(o2); - } - catch(ClassCastException e) { - // ignore - } - } - return 0; - } - }; - Collections.sort(objects, comparator); - - // insert into partition - while(objects.size() > 0) { - StringBuffer msg = new StringBuffer(); - int splitPoint = chooseBulkSplitPoint(objects.size(), minEntries, maxEntries); - List<N> partition1 = new ArrayList<N>(); - for(int i = 0; i < splitPoint; i++) { - N o = objects.remove(0); - partition1.add(o); - } - partitions.add(partition1); - - // copy array - if(logger.isDebugging()) { - msg.append("\ncurrent partition " + partition1); - msg.append("\nremaining objects # ").append(objects.size()); - logger.debugFine(msg.toString()); - } - } - - if(logger.isDebugging()) { - logger.debugFine("partitions " + partitions); - } - return partitions; - } -} 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 a620ff62..10f25ec0 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) 2011 + Copyright (C) 2012 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.deliclu; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.data.HyperBoundingBox; +import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox; import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialDirectoryEntry; /** @@ -64,7 +64,7 @@ public class DeLiCluDirectoryEntry extends SpatialDirectoryEntry implements DeLi * @param hasHandled indicates if this entry has handled nodes * @param hasUnhandled indicates if this entry has unhandled nodes */ - public DeLiCluDirectoryEntry(int id, HyperBoundingBox mbr, boolean hasHandled, boolean hasUnhandled) { + public DeLiCluDirectoryEntry(int id, ModifiableHyperBoundingBox mbr, boolean hasHandled, boolean hasUnhandled) { super(id, mbr); this.hasHandled = hasHandled; this.hasUnhandled = hasUnhandled; 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 3dbde624..19cf8a32 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) 2011 + Copyright (C) 2012 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 b2ec9f9a..c7cfc493 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) 2011 + Copyright (C) 2012 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/DeLiCluNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluNode.java index 689507cb..bf993c01 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -88,13 +88,14 @@ public class DeLiCluNode extends AbstractRStarTreeNode<DeLiCluNode, DeLiCluEntry } @Override - public void adjustEntry(DeLiCluEntry entry) { - super.adjustEntry(entry); + public boolean adjustEntry(DeLiCluEntry entry) { + boolean changed = super.adjustEntry(entry); // adjust hasHandled and hasUnhandled flag boolean hasHandled = hasHandled(); boolean hasUnhandled = hasUnhandled(); entry.setHasHandled(hasHandled); entry.setHasUnhandled(hasUnhandled); + return changed; } /** 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 ac873815..6f4f782d 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -31,8 +31,6 @@ import de.lmu.ifi.dbs.elki.index.tree.BreadthFirstEnumeration; import de.lmu.ifi.dbs.elki.index.tree.Entry; import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.NonFlatRStarTree; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk.BulkSplit; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.persistent.PageFile; @@ -61,11 +59,9 @@ public class DeLiCluTree extends NonFlatRStarTree<DeLiCluNode, DeLiCluEntry> { * Constructor. * * @param pagefile Page file - * @param bulkSplitter bulk load strategy - * @param insertionStrategy the strategy to find the insertion child */ - public DeLiCluTree(PageFile<DeLiCluNode> pagefile, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) { - super(pagefile, bulkSplitter, insertionStrategy); + public DeLiCluTree(PageFile<DeLiCluNode> pagefile) { + super(pagefile); } /** 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 dd9532a2..3f9627a9 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,8 +26,10 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu; 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.rstarvariants.AbstractRStarTreeFactory; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk.BulkSplit; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.InsertionStrategy; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.OverflowTreatment; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.SplitStrategy; import de.lmu.ifi.dbs.elki.persistent.PageFile; /** @@ -49,15 +51,24 @@ public class DeLiCluTreeFactory<O extends NumberVector<O, ?>> extends AbstractRS * @param cacheSize * @param bulkSplitter Bulk loading strategy * @param insertionStrategy the strategy to find the insertion child + * @param nodeSplitter the strategy for splitting nodes. + * @param overflowTreatment the strategy to use for overflow treatment + * @param minimumFill the relative minimum fill */ - public DeLiCluTreeFactory(String fileName, int pageSize, long cacheSize, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) { - super(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy); + public DeLiCluTreeFactory(String fileName, int pageSize, long cacheSize, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy, SplitStrategy nodeSplitter, OverflowTreatment overflowTreatment, double minimumFill) { + super(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy, nodeSplitter, overflowTreatment, minimumFill); } @Override public DeLiCluTreeIndex<O> instantiate(Relation<O> relation) { PageFile<DeLiCluNode> pagefile = makePageFile(getNodeClass()); - return new DeLiCluTreeIndex<O>(relation, pagefile, bulkSplitter, insertionStrategy); + DeLiCluTreeIndex<O> index = new DeLiCluTreeIndex<O>(relation, pagefile); + index.setBulkStrategy(bulkSplitter); + index.setInsertionStrategy(insertionStrategy); + index.setNodeSplitStrategy(nodeSplitter); + index.setOverflowTreatment(overflowTreatment); + index.setMinimumFill(minimumFill); + return index; } protected Class<DeLiCluNode> getNodeClass() { @@ -74,7 +85,7 @@ public class DeLiCluTreeFactory<O extends NumberVector<O, ?>> extends AbstractRS public static class Parameterizer<O extends NumberVector<O, ?>> extends AbstractRStarTreeFactory.Parameterizer<O> { @Override protected DeLiCluTreeFactory<O> makeInstance() { - return new DeLiCluTreeFactory<O>(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy); + return new DeLiCluTreeFactory<O>(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy, nodeSplitter, overflowTreatment, minimumFill); } } }
\ No newline at end of file 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 062ddfb2..dd523ef8 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -39,9 +39,7 @@ 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.TreeIndexPathComponent; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk.BulkSplit; import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query.RStarTreeUtil; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.persistent.PageFile; import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; @@ -64,11 +62,9 @@ public class DeLiCluTreeIndex<O extends NumberVector<?, ?>> extends DeLiCluTree * * @param relation Relation to index * @param pagefile Page file - * @param bulkSplitter bulk load strategy - * @param insertionStrategy the strategy to find the insertion child */ - public DeLiCluTreeIndex(Relation<O> relation, PageFile<DeLiCluNode> pagefile, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) { - super(pagefile, bulkSplitter, insertionStrategy); + public DeLiCluTreeIndex(Relation<O> relation, PageFile<DeLiCluNode> pagefile) { + super(pagefile); this.relation = relation; this.initialize(); } 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 8ebaab8c..b6c0af9b 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) 2011 +Copyright (C) 2012 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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/package-info.java index e658ebf5..2774fbe1 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) 2011 +Copyright (C) 2012 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/DoubleDistanceRStarTreeKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeKNNQuery.java index 7d39c08f..9174dc94 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/DoubleDistanceRStarTreeKNNQuery.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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -36,10 +36,10 @@ 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.DBIDs; import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs; -import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.database.query.DoubleDistanceResultPair; 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.KNNResult; import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry; @@ -50,16 +50,24 @@ 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.Heap; import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap; -import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap; +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 AbstractRStarTree * @apiviz.uses SpatialPrimitiveDoubleDistanceFunction */ +@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> { /** * The index to use @@ -93,7 +101,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend * @param knnList the knn list containing the result */ protected void doKNNQuery(O object, KNNHeap<DoubleDistance> knnList) { - final Heap<DoubleDistanceSearchCandidate> pq = new UpdatableHeap<DoubleDistanceSearchCandidate>(); + final Heap<DoubleDistanceSearchCandidate> pq = new Heap<DoubleDistanceSearchCandidate>(Math.min(knnList.getK() * 2, 20)); // push root pq.add(new DoubleDistanceSearchCandidate(0.0, tree.getRootID())); @@ -106,32 +114,42 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend if(pqNode.mindist > maxDist) { return; } + maxDist = expandNode(object, knnList, pq, maxDist, pqNode.nodeID); + } + } - AbstractRStarTreeNode<?, ?> node = tree.getNode(pqNode.nodeID); - // data node - if(node.isLeaf()) { - for(int i = 0; i < node.getNumEntries(); i++) { - SpatialEntry entry = node.getEntry(i); - double distance = distanceFunction.doubleMinDist(entry, object); - tree.distanceCalcs++; - if(distance <= maxDist) { - knnList.add(new DoubleDistanceResultPair(distance, ((LeafEntry) entry).getDBID())); - maxDist = knnList.getKNNDistance().doubleValue(); - } + private double expandNode(O object, KNNHeap<DoubleDistance> knnList, final Heap<DoubleDistanceSearchCandidate> pq, double maxDist, final Integer nodeID) { + AbstractRStarTreeNode<?, ?> node = tree.getNode(nodeID); + // data node + if(node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { + SpatialEntry entry = node.getEntry(i); + double distance = distanceFunction.doubleMinDist(entry, object); + tree.distanceCalcs++; + if(distance <= maxDist) { + knnList.add(new DoubleDistanceResultPair(distance, ((LeafEntry) entry).getDBID())); + maxDist = knnList.getKNNDistance().doubleValue(); } } - // directory node - else { - for(int i = 0; i < node.getNumEntries(); i++) { - SpatialEntry entry = node.getEntry(i); - double distance = distanceFunction.doubleMinDist(entry, object); - tree.distanceCalcs++; + } + // directory node + else { + for(int i = 0; i < node.getNumEntries(); i++) { + SpatialEntry entry = node.getEntry(i); + double distance = distanceFunction.doubleMinDist(entry, object); + tree.distanceCalcs++; + // Greedy expand, bypassing the queue + if(distance <= 0) { + expandNode(object, knnList, pq, maxDist, ((DirectoryEntry) entry).getPageID()); + } + else { if(distance <= maxDist) { - pq.add(new DoubleDistanceSearchCandidate(distance, ((DirectoryEntry)entry).getPageID())); + pq.add(new DoubleDistanceSearchCandidate(distance, ((DirectoryEntry) entry).getPageID())); } } } } + return maxDist; } /** @@ -161,7 +179,9 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend } else { ModifiableDBIDs ids = DBIDUtil.newArray(knnLists.size()); - ids.addAll(knnLists.keySet()); + for(DBID id : knnLists.keySet()) { + ids.add(id); + } List<DoubleDistanceEntry> entries = getSortedEntries(node, ids); for(DoubleDistanceEntry distEntry : entries) { double minDist = distEntry.distance; @@ -171,7 +191,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend if(minDist <= knn_q_maxDist) { SpatialEntry entry = distEntry.entry; - AbstractRStarTreeNode<?, ?> child = tree.getNode(((DirectoryEntry)entry).getPageID()); + AbstractRStarTreeNode<?, ?> child = tree.getNode(((DirectoryEntry) entry).getPageID()); batchNN(child, knnLists); break; } @@ -210,7 +230,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend * Optimized double distance entry implementation. * * @author Erich Schubert - * + * * @apiviz.hidden */ class DoubleDistanceEntry implements Comparable<DoubleDistanceEntry> { @@ -226,7 +246,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend /** * Constructor. - * + * * @param entry Entry * @param distance Distance */ @@ -242,23 +262,23 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend } @Override - public List<DistanceResultPair<DoubleDistance>> getKNNForObject(O obj, int k) { + public KNNResult<DoubleDistance> getKNNForObject(O obj, int k) { if(k < 1) { throw new IllegalArgumentException("At least one enumeration has to be requested!"); } final KNNHeap<DoubleDistance> knnList = new KNNHeap<DoubleDistance>(k, distanceFunction.getDistanceFactory().infiniteDistance()); doKNNQuery(obj, knnList); - return knnList.toSortedArrayList(); + return knnList.toKNNList(); } @Override - public List<DistanceResultPair<DoubleDistance>> getKNNForDBID(DBID id, int k) { + public KNNResult<DoubleDistance> getKNNForDBID(DBID id, int k) { return getKNNForObject(relation.get(id), k); } @Override - public List<List<DistanceResultPair<DoubleDistance>>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + public List<KNNResult<DoubleDistance>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { if(k < 1) { throw new IllegalArgumentException("At least one enumeration has to be requested!"); } @@ -271,9 +291,9 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend batchNN(tree.getRoot(), knnLists); - List<List<DistanceResultPair<DoubleDistance>>> result = new ArrayList<List<DistanceResultPair<DoubleDistance>>>(); + List<KNNResult<DoubleDistance>> result = new ArrayList<KNNResult<DoubleDistance>>(); for(DBID id : ids) { - result.add(knnLists.get(id).toSortedArrayList()); + result.add(knnLists.get(id).toKNNList()); } return result; } @@ -283,9 +303,4 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend AbstractRStarTreeNode<?, ?> root = tree.getRoot(); batchNN(root, heaps); } - - @Override - public DoubleDistance getDistanceFactory() { - return distanceQuery.getDistanceFactory(); - } }
\ No newline at end of file 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/DoubleDistanceRStarTreeRangeQuery.java index 96d1e8c5..069db6d4 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/DoubleDistanceRStarTreeRangeQuery.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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -41,16 +41,25 @@ import de.lmu.ifi.dbs.elki.index.tree.query.DoubleDistanceSearchCandidate; 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.Heap; +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 SpatialPrimitiveDoubleDistanceFunction */ -//TODO: add bulk range queries. +@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> { /** * The index to use 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 index be3ed994..5129f5ca 100644 --- 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 @@ -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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -36,9 +36,9 @@ 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.DBIDs; import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs; -import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; 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.database.query.knn.KNNResult; 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; @@ -51,16 +51,24 @@ 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.Heap; import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap; -import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap; +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 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 @@ -93,7 +101,7 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis * @param knnList the knn list containing the result */ protected void doKNNQuery(O object, KNNHeap<D> knnList) { - final Heap<GenericDistanceSearchCandidate<D>> pq = new UpdatableHeap<GenericDistanceSearchCandidate<D>>(); + final Heap<GenericDistanceSearchCandidate<D>> pq = new Heap<GenericDistanceSearchCandidate<D>>(Math.min(knnList.getK() * 2, 20)); // push root pq.add(new GenericDistanceSearchCandidate<D>(distanceFunction.getDistanceFactory().nullDistance(), tree.getRootID())); @@ -106,32 +114,42 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis if(pqNode.mindist.compareTo(maxDist) > 0) { return; } + maxDist = expandNode(object, knnList, pq, maxDist, pqNode.nodeID); + } + } - AbstractRStarTreeNode<?, ?> node = tree.getNode(pqNode.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.distanceCalcs++; - if(distance.compareTo(maxDist) <= 0) { - knnList.add(distance, ((LeafEntry) entry).getDBID()); - maxDist = knnList.getKNNDistance(); - } + private D expandNode(O object, KNNHeap<D> knnList, final Heap<GenericDistanceSearchCandidate<D>> pq, D maxDist, final Integer 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.distanceCalcs++; + if(distance.compareTo(maxDist) <= 0) { + knnList.add(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.distanceCalcs++; + } + // directory node + else { + for(int i = 0; i < node.getNumEntries(); i++) { + SpatialEntry entry = node.getEntry(i); + D distance = distanceFunction.minDist(entry, object); + tree.distanceCalcs++; + // 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<D>(distance, ((DirectoryEntry)entry).getPageID())); + pq.add(new GenericDistanceSearchCandidate<D>(distance, ((DirectoryEntry) entry).getPageID())); } } } } + return maxDist; } /** @@ -160,7 +178,9 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis } else { ModifiableDBIDs ids = DBIDUtil.newArray(knnLists.size()); - ids.addAll(knnLists.keySet()); + for(DBID id : knnLists.keySet()) { + ids.add(id); + } List<DistanceEntry<D, SpatialEntry>> entries = getSortedEntries(node, ids); for(DistanceEntry<D, SpatialEntry> distEntry : entries) { D minDist = distEntry.getDistance(); @@ -170,7 +190,7 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis if(minDist.compareTo(knn_q_maxDist) <= 0) { SpatialEntry entry = distEntry.getEntry(); - AbstractRStarTreeNode<?, ?> child = tree.getNode(((DirectoryEntry)entry).getPageID()); + AbstractRStarTreeNode<?, ?> child = tree.getNode(((DirectoryEntry) entry).getPageID()); batchNN(child, knnLists); break; } @@ -211,23 +231,23 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis } @Override - public List<DistanceResultPair<D>> getKNNForObject(O obj, int k) { + public KNNResult<D> getKNNForObject(O obj, int k) { if(k < 1) { throw new IllegalArgumentException("At least one enumeration has to be requested!"); } final KNNHeap<D> knnList = new KNNHeap<D>(k, distanceFunction.getDistanceFactory().infiniteDistance()); doKNNQuery(obj, knnList); - return knnList.toSortedArrayList(); + return knnList.toKNNList(); } @Override - public List<DistanceResultPair<D>> getKNNForDBID(DBID id, int k) { + public KNNResult<D> getKNNForDBID(DBID id, int k) { return getKNNForObject(relation.get(id), k); } @Override - public List<List<DistanceResultPair<D>>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { if(k < 1) { throw new IllegalArgumentException("At least one enumeration has to be requested!"); } @@ -239,15 +259,10 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis batchNN(tree.getRoot(), knnLists); - List<List<DistanceResultPair<D>>> result = new ArrayList<List<DistanceResultPair<D>>>(); + List<KNNResult<D>> result = new ArrayList<KNNResult<D>>(); for(DBID id : ids) { - result.add(knnLists.get(id).toSortedArrayList()); + result.add(knnLists.get(id).toKNNList()); } return result; } - - @Override - public D getDistanceFactory() { - return distanceQuery.getDistanceFactory(); - } }
\ No newline at end of file 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 index c4d68828..d2086cb1 100644 --- 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 @@ -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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -41,16 +41,25 @@ 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.Heap; +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 */ -// TODO: add bulk range queries. +@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 @@ -69,7 +78,7 @@ public class GenericRStarTreeRangeQuery<O extends SpatialComparable, D extends D * @param distanceQuery Distance query to use */ public GenericRStarTreeRangeQuery(AbstractRStarTree<?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery) { - super( distanceQuery); + super(distanceQuery); this.tree = tree; this.distanceFunction = distanceQuery.getDistanceFunction(); } 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 8e4b36e6..477e3a36 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) 2011 + Copyright (C) 2012 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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/package-info.java index fffaa6bf..0b47cab0 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) 2011 +Copyright (C) 2012 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/RStarTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTree.java index 4d208e46..53b32c6b 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,8 +26,6 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar; 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.NonFlatRStarTree; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk.BulkSplit; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.persistent.PageFile; import de.lmu.ifi.dbs.elki.utilities.documentation.Description; @@ -56,11 +54,9 @@ public class RStarTree extends NonFlatRStarTree<RStarTreeNode, SpatialEntry> { * Constructor. * * @param pagefile Page file - * @param bulkSplitter bulk load strategy - * @param insertionStrategy the strategy to find the insertion child */ - public RStarTree(PageFile<RStarTreeNode> pagefile, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) { - super(pagefile, bulkSplitter, insertionStrategy); + public RStarTree(PageFile<RStarTreeNode> pagefile) { + super(pagefile); } @Override 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 f8da714c..79aac0bd 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -27,8 +27,10 @@ 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.bulk.BulkSplit; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.InsertionStrategy; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.OverflowTreatment; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.SplitStrategy; import de.lmu.ifi.dbs.elki.persistent.PageFile; /** @@ -50,15 +52,24 @@ public class RStarTreeFactory<O extends NumberVector<O, ?>> extends AbstractRSta * @param cacheSize * @param bulkSplitter Bulk loading strategy * @param insertionStrategy the strategy to find the insertion child + * @param nodeSplitter the strategy for splitting nodes. + * @param overflowTreatment the strategy to use for overflow treatment + * @param minimumFill the relative minimum fill */ - public RStarTreeFactory(String fileName, int pageSize, long cacheSize, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) { - super(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy); + public RStarTreeFactory(String fileName, int pageSize, long cacheSize, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy, SplitStrategy nodeSplitter, OverflowTreatment overflowTreatment, double minimumFill) { + super(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy, nodeSplitter, overflowTreatment, minimumFill); } @Override public RStarTreeIndex<O> instantiate(Relation<O> relation) { PageFile<RStarTreeNode> pagefile = makePageFile(getNodeClass()); - return new RStarTreeIndex<O>(relation, pagefile, bulkSplitter, insertionStrategy); + RStarTreeIndex<O> index = new RStarTreeIndex<O>(relation, pagefile); + index.setBulkStrategy(bulkSplitter); + index.setInsertionStrategy(insertionStrategy); + index.setNodeSplitStrategy(nodeSplitter); + index.setOverflowTreatment(overflowTreatment); + index.setMinimumFill(minimumFill); + return index; } protected Class<RStarTreeNode> getNodeClass() { @@ -75,7 +86,7 @@ public class RStarTreeFactory<O extends NumberVector<O, ?>> extends AbstractRSta public static class Parameterizer<O extends NumberVector<O, ?>> extends AbstractRStarTreeFactory.Parameterizer<O> { @Override protected RStarTreeFactory<O> makeInstance() { - return new RStarTreeFactory<O>(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy); + return new RStarTreeFactory<O>(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy, nodeSplitter, overflowTreatment, minimumFill); } } }
\ No newline at end of file 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 30286ca9..46ef2628 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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -40,9 +40,7 @@ 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.bulk.BulkSplit; import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query.RStarTreeUtil; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.persistent.PageFile; @@ -69,11 +67,9 @@ public class RStarTreeIndex<O extends NumberVector<?, ?>> extends RStarTree impl * * @param relation Relation to index * @param pagefile Page file - * @param bulkSplitter bulk load strategy - * @param insertionStrategy the strategy to find the insertion child */ - public RStarTreeIndex(Relation<O> relation, PageFile<RStarTreeNode> pagefile, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) { - super(pagefile, bulkSplitter, insertionStrategy); + public RStarTreeIndex(Relation<O> relation, PageFile<RStarTreeNode> pagefile) { + super(pagefile); this.relation = relation; this.initialize(); } 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 248ddfc5..b51d191a 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) 2011 + Copyright (C) 2012 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 7bfd1b9a..e15569c5 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) 2011 +Copyright (C) 2012 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/bulk/AbstractBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AbstractBulkSplit.java index 999fa019..4a0304f1 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/AbstractBulkSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AbstractBulkSplit.java @@ -1,10 +1,13 @@ -package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk; +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk; + +import java.util.ArrayList; +import java.util.List; /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,14 +26,12 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; - /** * Encapsulates the required parameters for a bulk split of a spatial index. * * @author Elke Achtert */ -public abstract class AbstractBulkSplit implements BulkSplit, Parameterizable { +public abstract class AbstractBulkSplit implements BulkSplit { /** * Constructor */ @@ -61,4 +62,30 @@ public abstract class AbstractBulkSplit implements BulkSplit, Parameterizable { return maxEntries; } } + + /** + * Perform the trivial partitioning of the given list. + * + * @param objects Objects to partition + * @param minEntries Minimum number of objects per page + * @param maxEntries Maximum number of objects per page. + * @return List with partitions + */ + protected <T> List<List<T>> trivialPartition(List<T> objects, int minEntries, int maxEntries) { + // build partitions + final int size = objects.size(); + final int numberPartitions = (int) Math.ceil(((double) size) / maxEntries); + List<List<T>> partitions = new ArrayList<List<T>>(numberPartitions); + int start = 0; + for(int pnum = 0; pnum < numberPartitions; pnum++) { + int end = (int) ((pnum + 1.) * size / numberPartitions); + if(pnum == numberPartitions - 1) { + end = size; + } + assert ((end - start) >= minEntries && (end - start) <= maxEntries); + partitions.add(objects.subList(start, end)); + start = end; + } + return partitions; + } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/BulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java index 23c0f077..1eb88f7c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/BulkSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java @@ -1,10 +1,10 @@ -package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk; +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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,13 +26,14 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.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 { +public interface BulkSplit extends Parameterizable { /** * 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 new file mode 100644 index 00000000..308c70cb --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/FileOrderBulkSplit.java @@ -0,0 +1,67 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +import java.util.List; + +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; + +/** + * Trivial bulk loading - assumes that the file has been appropriately sorted + * before. + * + * @author Erich Schubert + */ +public class FileOrderBulkSplit extends AbstractBulkSplit { + /** + * Static instance + */ + public static final FileOrderBulkSplit STATIC = new FileOrderBulkSplit(); + + /** + * Constructor. + */ + protected FileOrderBulkSplit() { + super(); + } + + @Override + public <T extends SpatialComparable> List<List<T>> partition(List<T> spatialObjects, int minEntries, int maxEntries) { + return trivialPartition(spatialObjects, minEntries, maxEntries); + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + @Override + protected FileOrderBulkSplit makeInstance() { + return FileOrderBulkSplit.STATIC; + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/MaxExtensionBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java index 0a830aab..90a8b622 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/MaxExtensionBulkSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java @@ -1,10 +1,10 @@ -package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk; +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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -31,6 +31,7 @@ import java.util.List; import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.SpatialComparator; import de.lmu.ifi.dbs.elki.logging.Logging; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; /** * Split strategy for bulk-loading a spatial tree where the split axes are the @@ -45,6 +46,11 @@ public class MaxExtensionBulkSplit extends AbstractBulkSplit { * Logger. */ private static final Logging logger = Logging.getLogger(MaxExtensionBulkSplit.class); + + /** + * Static instance + */ + public static final MaxExtensionBulkSplit STATIC = new MaxExtensionBulkSplit(); /** * Constructor @@ -146,4 +152,18 @@ public class MaxExtensionBulkSplit extends AbstractBulkSplit { } return splitAxis; } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + @Override + protected MaxExtensionBulkSplit makeInstance() { + return MaxExtensionBulkSplit.STATIC; + } + } }
\ No newline at end of file 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 new file mode 100644 index 00000000..b99ae01e --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/OneDimSortBulkSplit.java @@ -0,0 +1,86 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; + +/** + * Simple bulk loading strategy by sorting the data along the first dimension. + * + * This is also known as Nearest-X, and attributed to: + * <p> + * Roussopoulos, N. and Leifker, D.:<br /> + * Direct spatial search on pictorial databases using packed R-trees<br /> + * In: ACM SIGMOD Record 14-4 + * </p> + * + * @author Erich Schubert + */ +@Reference(authors = "Roussopoulos, N. and Leifker, D.", title = "Direct spatial search on pictorial databases using packed R-trees", booktitle = "ACM SIGMOD Record 14-4", url = "http://dx.doi.org/10.1145/971699.318900") +public class OneDimSortBulkSplit extends AbstractBulkSplit { + /** + * Static instance + */ + public static final AbstractBulkSplit STATIC = new OneDimSortBulkSplit(); + + /** + * Constructor. + */ + protected OneDimSortBulkSplit() { + super(); + } + + @Override + public <T extends SpatialComparable> List<List<T>> partition(List<T> spatialObjects, int minEntries, int maxEntries) { + // Sort by first dimension + Collections.sort(spatialObjects, new Comparator<SpatialComparable>() { + @Override + public int compare(SpatialComparable o1, SpatialComparable o2) { + double min1 = (o1.getMax(1) + o1.getMin(1)) / 2; + double min2 = (o2.getMax(1) + o2.getMin(1)) / 2; + return Double.compare(min1, min2); + } + }); + return trivialPartition(spatialObjects, minEntries, maxEntries); + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + @Override + protected AbstractBulkSplit makeInstance() { + return OneDimSortBulkSplit.STATIC; + } + } +}
\ No newline at end of file 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 new file mode 100644 index 00000000..28e96da6 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SortTileRecursiveBulkSplit.java @@ -0,0 +1,115 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect; +import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; + +/** + * Sort-Tile-Recursive aims at tiling the data space with a grid-like structure + * for partitioning the dataset into the required number of buckets. + * + * Reference: + * <p> + * Leutenegger, S.T. and Lopez, M.A. and Edgington, J.:<br /> + * STR: A simple and efficient algorithm for R-tree packing<br /> + * In: Proc. 13th International Conference on Data Engineering, 1997 + * </p> + * + * @author Erich Schubert + */ +@Reference(authors = "Leutenegger, S.T. and Lopez, M.A. and Edgington, J.", title = "STR: A simple and efficient algorithm for R-tree packing", booktitle = "Proc. 13th International Conference on Data Engineering, 1997", url = "http://dx.doi.org/10.1109/ICDE.1997.582015") +public class SortTileRecursiveBulkSplit extends AbstractBulkSplit { + @Override + public <T extends SpatialComparable> List<List<T>> partition(List<T> spatialObjects, int minEntries, int maxEntries) { + final int dims = spatialObjects.get(0).getDimensionality(); + final int p = (int) Math.ceil(spatialObjects.size() / (double) maxEntries); + List<List<T>> ret = new ArrayList<List<T>>(p); + strPartition(spatialObjects, 0, spatialObjects.size(), 0, dims, maxEntries, new Compare<T>(), ret); + return ret; + } + + /** + * Recursively partition. + * + * @param objs Object list + * @param start Subinterval start + * @param end Subinteval end + * @param depth Iteration depth (must be less than dimensionality!) + * @param dims Total number of dimensions + * @param maxEntries Maximum page size + * @param c Comparison helper + * @param ret Output list + */ + protected <T extends SpatialComparable> void strPartition(List<T> objs, int start, int end, int depth, int dims, int maxEntries, Compare<T> c, List<List<T>> ret) { + c.dim = depth + 1; + final int p = (int) Math.ceil((end - start) / (double) maxEntries); + final int s = (int) Math.ceil(Math.pow(p, 1.0 / (dims - depth))); + + final double len = end - start; // double intentional! + for(int i = 0; i < s; i++) { + // We don't completely sort, but only ensure the quantile is invariant. + int s2 = start + (int) ((i * len) / s); + int e2 = start + (int) (((i + 1) * len) / s); + // LoggingUtil.warning("STR " + dim + " s2:" + s2 + " e2:" + e2); + if(e2 < end) { + QuickSelect.quickSelect(objs, c, s2, end, e2); + } + if(depth + 1 == dims) { + ret.add(objs.subList(s2, e2)); + } + else { + // Descend + strPartition(objs, s2, e2, depth + 1, dims, maxEntries, c, ret); + } + } + } + + /** + * Comparison helper. + * + * @apiviz.exclude + * + * @author Erich Schubert + * + * @param <T> Type + */ + private static class Compare<T extends SpatialComparable> implements Comparator<T> { + /** + * Current dimension + */ + public int dim; + + @Override + public int compare(T o1, T o2) { + final double v1 = o1.getMin(dim) + o1.getMax(dim); + final double v2 = o2.getMin(dim) + o2.getMax(dim); + return Double.compare(v1, v2); + } + } +}
\ No newline at end of file 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 new file mode 100644 index 00000000..9c3a41a1 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SpatialSortBulkSplit.java @@ -0,0 +1,107 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +import java.util.List; + +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.math.spacefillingcurves.SpatialSorter; +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.parameterization.Parameterization; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; + +/** + * Bulk loading by spatially sorting the objects, then partitioning the sorted + * list appropriately. + * + * Based conceptually on: + * <p> + * On packing R-trees<br/> + * Kamel, I. and Faloutsos, C.<br/> + * Proc. 2of the second international conference on Information and knowledge + * management + * </p> + * + * @apiviz.composedOf SpatialSorter + * + * @author Erich Schubert + */ +@Reference(title = "On packing R-trees", authors = "Kamel, I. and Faloutsos, C.", booktitle = "Proc. 2of the second international conference on Information and knowledge management", url = "http://dx.doi.org/10.1145/170088.170403") +public class SpatialSortBulkSplit extends AbstractBulkSplit { + /** + * Sorting class + */ + final SpatialSorter sorter; + + /** + * Constructor. + * + * @param sorter Sorting strategy + */ + protected SpatialSortBulkSplit(SpatialSorter sorter) { + super(); + this.sorter = sorter; + } + + @Override + public <T extends SpatialComparable> List<List<T>> partition(List<T> spatialObjects, int minEntries, int maxEntries) { + sorter.sort(spatialObjects); + return super.trivialPartition(spatialObjects, minEntries, maxEntries); + } + + /** + * Parametization class + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + /** + * Option ID for spatial sorting + */ + public static final OptionID SORTER_ID = OptionID.getOrCreateOptionID("rtree.bulk.spatial-sort", "Strategy for spatial sorting in bulk loading."); + + /** + * Sorting class + */ + SpatialSorter sorter; + + @Override + protected void makeOptions(Parameterization config) { + super.makeOptions(config); + + ObjectParameter<SpatialSorter> sorterP = new ObjectParameter<SpatialSorter>(SORTER_ID, SpatialSorter.class); + if(config.grab(sorterP)) { + sorter = sorterP.instantiateClass(config); + } + } + + @Override + protected SpatialSortBulkSplit makeInstance() { + return new SpatialSortBulkSplit(sorter); + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/package-info.java index ab849373..0d01ba83 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/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) 2011 +Copyright (C) 2012 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.tree.spatial.rstarvariants.bulk;
\ No newline at end of file +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk;
\ No newline at end of file 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 new file mode 100644 index 00000000..418e92c5 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/ApproximativeLeastOverlapInsertionStrategy.java @@ -0,0 +1,168 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.Collections; + +import de.lmu.ifi.dbs.elki.data.HyperBoundingBox; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; +import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter; +import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TopBoundedHeap; +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.GreaterConstraint; +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.DoubleIntPair; + +/** + * The choose subtree method proposed by the R*-Tree with slightly better + * performance for large leaf sizes (linear approximation). + * + * <p> + * N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger:<br /> + * The R*-tree: an efficient and robust access method for points and rectangles<br /> + * in: Proceedings of the 1990 ACM SIGMOD International Conference on Management + * of Data, Atlantic City, NJ, May 23-25, 1990 + * </p> + * + * @author Erich Schubert + * @author Franz Graf + * @author Marisa Petri + */ +@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 ApproximativeLeastOverlapInsertionStrategy extends LeastOverlapInsertionStrategy { + /** + * Number of candidates to consider + */ + private int numCandidates = 32; + + /** + * Constructor. + */ + public ApproximativeLeastOverlapInsertionStrategy(int candidates) { + super(); + this.numCandidates = candidates; + } + + @Override + public <A> int choose(A options, ArrayAdapter<? extends SpatialComparable, A> getter, SpatialComparable obj, int height, int depth) { + final int size = getter.size(options); + assert (size > 0) : "Choose from empty set?"; + if(size <= numCandidates) { + // Skip building the heap. + return super.choose(options, getter, obj, height, depth); + } + + // Heap of candidates + TopBoundedHeap<DoubleIntPair> candidates = new TopBoundedHeap<DoubleIntPair>(numCandidates, Collections.reverseOrder()); + for(int i = 0; i < size; i++) { + // Existing object and extended rectangle: + SpatialComparable entry = getter.get(options, i); + HyperBoundingBox mbr = SpatialUtil.union(entry, obj); + // Area increase + final double inc_area = SpatialUtil.volume(mbr) - SpatialUtil.volume(entry); + candidates.add(new DoubleIntPair(inc_area, i)); + } + + // R*-Tree: overlap increase for leaves. + int best = -1; + double least_overlap = Double.POSITIVE_INFINITY; + double least_areainc = Double.POSITIVE_INFINITY; + double least_area = Double.POSITIVE_INFINITY; + // least overlap increase, on reduced candidate set: + while(!candidates.isEmpty()) { + DoubleIntPair pair = candidates.poll(); + final double inc_area = pair.first; + + // Existing object and extended rectangle: + SpatialComparable entry = getter.get(options, pair.second); + HyperBoundingBox mbr = SpatialUtil.union(entry, obj); + // Compute relative overlap increase. + double overlap_wout = 0.0; + double overlap_with = 0.0; + for(int k = 0; k < size; k++) { + if(pair.second != k) { + SpatialComparable other = getter.get(options, k); + overlap_wout += SpatialUtil.relativeOverlap(entry, other); + overlap_with += SpatialUtil.relativeOverlap(mbr, other); + } + } + double inc_overlap = overlap_with - overlap_wout; + if(inc_overlap < least_overlap) { + final double area = SpatialUtil.volume(entry); + // Volume increase and overlap increase: + least_overlap = inc_overlap; + least_areainc = inc_area; + least_area = area; + best = pair.second; + } + else if(inc_overlap == least_overlap) { + final double area = SpatialUtil.volume(entry); + if(inc_area < least_areainc || (inc_area == least_areainc && area < least_area)) { + least_overlap = inc_overlap; + least_areainc = inc_area; + least_area = area; + best = pair.second; + } + } + } + assert (best > -1) : "No split found? Volume outside of double precision?"; + return best; + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + /** + * Fast-insertion parameter. Optional. + */ + public static OptionID INSERTION_CANDIDATES_ID = OptionID.getOrCreateOptionID("rtree.insertion-candidates", "defines how many children are tested for finding the child generating the least overlap when inserting an object."); + + /** + * The number of candidates to use + */ + int numCandidates = 32; + + @Override + protected void makeOptions(Parameterization config) { + super.makeOptions(config); + IntParameter insertionCandidatesP = new IntParameter(INSERTION_CANDIDATES_ID, new GreaterConstraint(0), numCandidates); + if(config.grab(insertionCandidatesP)) { + numCandidates = insertionCandidatesP.getValue(); + } + } + + @Override + protected ApproximativeLeastOverlapInsertionStrategy makeInstance() { + return new ApproximativeLeastOverlapInsertionStrategy(numCandidates); + } + } +}
\ No newline at end of file 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 new file mode 100644 index 00000000..c90d99b2 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/CombinedInsertionStrategy.java @@ -0,0 +1,127 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +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.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.ClassParameter; + +/** + * Use two different insertion strategies for directory and leaf nodes. + * + * Using two different strategies was likely first suggested in: + * <p> + * N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger:<br /> + * The R*-tree: an efficient and robust access method for points and rectangles<br /> + * in: Proceedings of the 1990 ACM SIGMOD International Conference on Management + * of Data, Atlantic City, NJ, May 23-25, 1990 + * </p> + * + * @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") +public class CombinedInsertionStrategy implements InsertionStrategy { + /** + * Strategy when inserting into directory nodes + */ + InsertionStrategy dirStrategy; + + /** + * Strategy when inserting into leaf nodes. + */ + InsertionStrategy leafStrategy; + + /** + * Constructor. + * + * @param dirStrategy Strategy for directory nodes + * @param leafStrategy Strategy for leaf nodes + */ + public CombinedInsertionStrategy(InsertionStrategy dirStrategy, InsertionStrategy leafStrategy) { + super(); + this.dirStrategy = dirStrategy; + this.leafStrategy = leafStrategy; + } + + @Override + public <A> int choose(A options, ArrayAdapter<? extends SpatialComparable, A> getter, SpatialComparable obj, int height, int depth) { + if(depth + 1 >= height) { + return leafStrategy.choose(options, getter, obj, height, depth); + } + else { + return dirStrategy.choose(options, getter, obj, height, depth); + } + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + /** + * Insertion strategy for directory nodes. + */ + public static final OptionID DIR_STRATEGY_ID = OptionID.getOrCreateOptionID("rtree.insert-directory", "Insertion strategy for directory nodes."); + + /** + * Insertion strategy for leaf nodes. + */ + public static final OptionID LEAF_STRATEGY_ID = OptionID.getOrCreateOptionID("rtree.insert-leaf", "Insertion strategy for leaf nodes."); + + /** + * Strategy when inserting into directory nodes + */ + InsertionStrategy dirStrategy; + + /** + * Strategy when inserting into leaf nodes. + */ + InsertionStrategy leafStrategy; + + @Override + protected void makeOptions(Parameterization config) { + super.makeOptions(config); + ClassParameter<InsertionStrategy> dirP = new ClassParameter<InsertionStrategy>(DIR_STRATEGY_ID, InsertionStrategy.class, LeastEnlargementWithAreaInsertionStrategy.class); + if(config.grab(dirP)) { + dirStrategy = dirP.instantiateClass(config); + } + + ClassParameter<InsertionStrategy> leafP = new ClassParameter<InsertionStrategy>(LEAF_STRATEGY_ID, InsertionStrategy.class, LeastOverlapInsertionStrategy.class); + if(config.grab(leafP)) { + leafStrategy = leafP.instantiateClass(config); + } + } + + @Override + protected CombinedInsertionStrategy makeInstance() { + return new CombinedInsertionStrategy(dirStrategy, leafStrategy); + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/InsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java index 32f841b9..96294514 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/InsertionStrategy.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java @@ -1,10 +1,9 @@ -package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util; - +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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,26 +23,24 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util; */ import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; -import de.lmu.ifi.dbs.elki.index.tree.Node; -import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent; -import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; +import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter; import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; /** - * Interface for implementing insertion strategies, i.e. in which path of the - * tree to insert the new element. + * RTree insertion strategy interface. * * @author Erich Schubert */ public interface InsertionStrategy extends Parameterizable { /** - * Find the child to insert into. + * Choose insertion rectangle. * - * @param <N> Node type - * @param <E> Entry type - * @param node Node to use - * @param mbr MBR of entry to insert - * @return Entry to insert into + * @param options Options to choose from + * @param getter Array adapter for options + * @param obj Insertion object + * @param height Tree height + * @param depth Insertion depth (depth == height - 1 indicates leaf level) + * @return Subtree index in array. */ - public <N extends Node<E>, E extends SpatialEntry> TreeIndexPathComponent<E> findInsertChild(N node, SpatialComparable mbr); -} + public <A> int choose(A options, ArrayAdapter<? extends SpatialComparable, A> getter, SpatialComparable obj, int height, int depth); +}
\ No newline at end of file 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 new file mode 100644 index 00000000..eb211cb6 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementInsertionStrategy.java @@ -0,0 +1,89 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; +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.optionhandling.AbstractParameterizer; + +/** + * The default R-Tree insertion strategy: find rectangle with least volume + * enlargement. + * + * <p> + * Antonin Guttman:<br/> + * R-Trees: A Dynamic Index Structure For Spatial Searching<br /> + * in Proceedings of the 1984 ACM SIGMOD international conference on Management + * of data. + * </p> + * + * @author Erich Schubert + */ +@Reference(authors = "Antonin Guttman", title = "R-Trees: A Dynamic Index Structure For Spatial Searching", booktitle = "Proceedings of the 1984 ACM SIGMOD international conference on Management of data", url = "http://dx.doi.org/10.1145/971697.602266") +public class LeastEnlargementInsertionStrategy implements InsertionStrategy { + /** + * Static instance. + */ + public static final LeastEnlargementInsertionStrategy STATIC = new LeastEnlargementInsertionStrategy(); + + /** + * Constructor. + */ + public LeastEnlargementInsertionStrategy() { + super(); + } + + @Override + public <A> int choose(A options, ArrayAdapter<? extends SpatialComparable, A> getter, SpatialComparable obj, int height, int depth) { + final int size = getter.size(options); + assert (size > 0) : "Choose from empty set?"; + double leastEnlargement = Double.POSITIVE_INFINITY; + int best = -1; + for(int i = 0; i < size; i++) { + SpatialComparable entry = getter.get(options, i); + double enlargement = SpatialUtil.enlargement(entry, obj); + if(enlargement < leastEnlargement) { + leastEnlargement = enlargement; + best = i; + } + } + assert (best > -1); + return best; + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + @Override + protected LeastEnlargementInsertionStrategy makeInstance() { + return LeastEnlargementInsertionStrategy.STATIC; + } + } +}
\ No newline at end of file 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 new file mode 100644 index 00000000..977a132b --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementWithAreaInsertionStrategy.java @@ -0,0 +1,102 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; +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.optionhandling.AbstractParameterizer; + +/** + * A slight modification of the default R-Tree insertion strategy: find + * rectangle with least volume enlargement, but choose least area on ties. + * + * Proposed for non-leaf entries in: + * <p> + * N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger:<br /> + * The R*-tree: an efficient and robust access method for points and rectangles<br /> + * in: Proceedings of the 1990 ACM SIGMOD International Conference on Management + * of Data, Atlantic City, NJ, May 23-25, 1990 + * </p> + * + * @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") +public class LeastEnlargementWithAreaInsertionStrategy implements InsertionStrategy { + /** + * Static instance. + */ + public static final LeastEnlargementWithAreaInsertionStrategy STATIC = new LeastEnlargementWithAreaInsertionStrategy(); + + /** + * Constructor. + */ + public LeastEnlargementWithAreaInsertionStrategy() { + super(); + } + + @Override + public <A> int choose(A options, ArrayAdapter<? extends SpatialComparable, A> getter, SpatialComparable obj, int height, int depth) { + final int size = getter.size(options); + assert (size > 0) : "Choose from empty set?"; + // As in R-Tree, with a slight modification for ties + double leastEnlargement = Double.POSITIVE_INFINITY; + double minArea = -1; + int best = -1; + for(int i = 0; i < size; i++) { + SpatialComparable entry = getter.get(options, i); + double enlargement = SpatialUtil.enlargement(entry, obj); + if(enlargement < leastEnlargement) { + leastEnlargement = enlargement; + best = i; + minArea = SpatialUtil.volume(entry); + } + else if(enlargement == leastEnlargement) { + final double area = SpatialUtil.volume(entry); + if(area < minArea) { + // Tie handling proposed by R*: + best = i; + minArea = area; + } + } + } + assert (best > -1); + return best; + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + @Override + protected LeastEnlargementWithAreaInsertionStrategy makeInstance() { + return LeastEnlargementWithAreaInsertionStrategy.STATIC; + } + } +}
\ No newline at end of file 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 new file mode 100644 index 00000000..2eba8912 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastOverlapInsertionStrategy.java @@ -0,0 +1,120 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.data.HyperBoundingBox; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; +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.optionhandling.AbstractParameterizer; + +/** + * The choose subtree method proposed by the R*-Tree for leaf nodes. + * + * <p> + * N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger:<br /> + * The R*-tree: an efficient and robust access method for points and rectangles<br /> + * in: Proceedings of the 1990 ACM SIGMOD International Conference on Management + * of Data, Atlantic City, NJ, May 23-25, 1990 + * </p> + * + * @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") +public class LeastOverlapInsertionStrategy implements InsertionStrategy { + /** + * Static instance. + */ + public static final LeastOverlapInsertionStrategy STATIC = new LeastOverlapInsertionStrategy(); + + /** + * Constructor. + */ + public LeastOverlapInsertionStrategy() { + super(); + } + + @Override + public <A> int choose(A options, ArrayAdapter<? extends SpatialComparable, A> getter, SpatialComparable obj, int height, int depth) { + final int size = getter.size(options); + assert (size > 0) : "Choose from empty set?"; + // R*-Tree: overlap increase for leaves. + int best = -1; + double least_overlap = Double.POSITIVE_INFINITY; + double least_areainc = Double.POSITIVE_INFINITY; + double least_area = Double.POSITIVE_INFINITY; + // least overlap increase, on reduced candidate set: + for(int i = 0; i < size; i++) { + // Existing object and extended rectangle: + SpatialComparable entry = getter.get(options, i); + HyperBoundingBox mbr = SpatialUtil.union(entry, obj); + // Compute relative overlap increase. + double overlap_wout = 0.0; + double overlap_with = 0.0; + for(int k = 0; k < size; k++) { + if(i != k) { + SpatialComparable other = getter.get(options, k); + overlap_wout += SpatialUtil.relativeOverlap(entry, other); + overlap_with += SpatialUtil.relativeOverlap(mbr, other); + } + } + double inc_overlap = overlap_with - overlap_wout; + if(inc_overlap < least_overlap) { + final double area = SpatialUtil.volume(entry); + final double inc_area = SpatialUtil.volume(mbr) - area; + // Volume increase and overlap increase: + least_overlap = inc_overlap; + least_areainc = inc_area; + least_area = area; + best = i; + } + else if(inc_overlap == least_overlap) { + final double area = SpatialUtil.volume(entry); + final double inc_area = SpatialUtil.volume(mbr) - area; + if(inc_area < least_areainc || (inc_area == least_areainc && area < least_area)) { + least_overlap = inc_overlap; + least_areainc = inc_area; + least_area = area; + best = i; + } + } + } + assert (best > -1) : "No split found? Volume outside of double precision?"; + return best; + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + @Override + protected LeastOverlapInsertionStrategy makeInstance() { + return LeastOverlapInsertionStrategy.STATIC; + } + } +}
\ No newline at end of file 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 new file mode 100644 index 00000000..ad54e1e1 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/package-info.java @@ -0,0 +1,26 @@ +/** + * <p>Insertion strategies for R-Trees</p> + */ +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert;
\ No newline at end of file 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 new file mode 100644 index 00000000..2532f351 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/LimitedReinsertOverflowTreatment.java @@ -0,0 +1,135 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.BitSet; + +import de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction; +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.rstarvariants.AbstractRStarTree; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeNode; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert.CloseReinsert; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert.ReinsertStrategy; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.NodeArrayAdapter; +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.parameterization.Parameterization; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; + +/** + * Limited reinsertions, as proposed by the R*-Tree: For each real insert, allow + * reinsertions to happen only once per level. + * + * @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") +public class LimitedReinsertOverflowTreatment implements OverflowTreatment { + /** + * Default insert strategy used by R*-tree + */ + public static final LimitedReinsertOverflowTreatment RSTAR_OVERFLOW = new LimitedReinsertOverflowTreatment(new CloseReinsert(0.3, SquaredEuclideanDistanceFunction.STATIC)); + + /** + * Bitset to keep track of levels a reinsert has been performed at. + */ + private BitSet reinsertions = new BitSet(); + + /** + * Strategy for the actual reinsertions + */ + private final ReinsertStrategy reinsertStrategy; + + /** + * Constructor. + * + * @param reinsertStrategy Reinsertion strategy + */ + public LimitedReinsertOverflowTreatment(ReinsertStrategy reinsertStrategy) { + super(); + this.reinsertStrategy = reinsertStrategy; + } + + @Override + public <N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> boolean handleOverflow(AbstractRStarTree<N, E> tree, N node, IndexTreePath<E> path) { + final int level = /* tree.getHeight() - */(path.getPathCount() - 1); + // No reinsertions at root level + if(path.getPathCount() == 1) { + return false; + } + // Earlier reinsertions at the same level + if(reinsertions.get(level)) { + return false; + } + + reinsertions.set(level); + final E entry = path.getLastPathComponent().getEntry(); + assert (!entry.isLeafEntry()) : "Unexpected leaf entry"; + int[] cands = reinsertStrategy.computeReinserts(node, NodeArrayAdapter.STATIC, entry); + if(cands == null || cands.length == 0) { + return false; + } + tree.reInsert(node, path, cands); + return true; + } + + @Override + public void reinitialize() { + reinsertions.clear(); + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + /** + * Fast-insertion parameter. Optional. + */ + public static OptionID REINSERT_STRATEGY_ID = OptionID.getOrCreateOptionID("rtree.reinsertion-strategy", "The strategy to select candidates for reinsertion."); + + /** + * The actual reinsertion strategy + */ + ReinsertStrategy reinsertStrategy = null; + + @Override + protected void makeOptions(Parameterization config) { + super.makeOptions(config); + ObjectParameter<ReinsertStrategy> strategyP = new ObjectParameter<ReinsertStrategy>(REINSERT_STRATEGY_ID, ReinsertStrategy.class, CloseReinsert.class); + if(config.grab(strategyP)) { + reinsertStrategy = strategyP.instantiateClass(config); + } + } + + @Override + protected LimitedReinsertOverflowTreatment makeInstance() { + return new LimitedReinsertOverflowTreatment(reinsertStrategy); + } + } +}
\ No newline at end of file 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 new file mode 100644 index 00000000..87d09038 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/OverflowTreatment.java @@ -0,0 +1,53 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.index.tree.IndexTreePath; +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; + +/** + * Reinsertion strategy to resolve overflows in the RStarTree. + * + * @author Erich Schubert + */ +public interface OverflowTreatment { + /** + * Reinitialize the reinsertion treatment (for a new primary insertion). + */ + public void reinitialize(); + + /** + * Handle overflow in the given node. + * + * @param <N> Node + * @param <E> Entry + * @param tree Tree + * @param node Node + * @param path Path + * @return true when already handled (e.g. by reinserting) + */ + <N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> boolean handleOverflow(AbstractRStarTree<N, E> tree, N node, IndexTreePath<E> path); +}
\ No newline at end of file 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 new file mode 100644 index 00000000..cfbcf6a9 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/SplitOnlyOverflowTreatment.java @@ -0,0 +1,73 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.index.tree.IndexTreePath; +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.optionhandling.AbstractParameterizer; + +/** + * Always split, as in the original R-Tree + * + * @author Erich Schubert + */ +public class SplitOnlyOverflowTreatment implements OverflowTreatment { + /** + * Static instance + */ + public static final SplitOnlyOverflowTreatment STATIC = new SplitOnlyOverflowTreatment(); + + /** + * Constructor + */ + public SplitOnlyOverflowTreatment() { + super(); + } + + @Override + public <N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> boolean handleOverflow(AbstractRStarTree<N, E> tree, N node, IndexTreePath<E> path) { + return false; + } + + @Override + public void reinitialize() { + // Nothing to do + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + @Override + protected SplitOnlyOverflowTreatment makeInstance() { + return SplitOnlyOverflowTreatment.STATIC; + } + } +}
\ No newline at end of file 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 new file mode 100644 index 00000000..30899736 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/package-info.java @@ -0,0 +1,26 @@ +/** + * <p>Overflow treatment strategies for R-Trees</p> + */ +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow;
\ No newline at end of file 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 new file mode 100644 index 00000000..41e2eb0b --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/package-info.java @@ -0,0 +1,26 @@ +/** + * <p>Various strategies for R-Trees and variants.</p> + */ +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies;
\ No newline at end of file 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 new file mode 100644 index 00000000..e0277606 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/AbstractPartialReinsert.java @@ -0,0 +1,105 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction; +import de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction; +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.IntervalConstraint; +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.ObjectParameter; + +/** + * Abstract base class for reinsertion strategies that have a "relative amount" + * parameter to partially reinsert entries. + * + * @author Erich Schubert + */ +public abstract class AbstractPartialReinsert implements ReinsertStrategy { + /** + * Amount of entries to reinsert + */ + protected double reinsertAmount = 0.3; + + /** + * Distance function to use for measuring + */ + SpatialPrimitiveDoubleDistanceFunction<?> distanceFunction; + + /** + * Constructor. + * + * @param reinsertAmount Relative amount of objects to reinsert. + * @param distanceFunction Distance function to use + */ + public AbstractPartialReinsert(double reinsertAmount, SpatialPrimitiveDoubleDistanceFunction<?> distanceFunction) { + super(); + this.reinsertAmount = reinsertAmount; + this.distanceFunction = distanceFunction; + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static abstract class Parameterizer extends AbstractParameterizer { + /** + * Reinsertion share + */ + public static OptionID REINSERT_AMOUNT_ID = OptionID.getOrCreateOptionID("rtree.reinsertion-amount", "The amount of entries to reinsert."); + + /** + * Reinsertion share + */ + public static OptionID REINSERT_DISTANCE_ID = OptionID.getOrCreateOptionID("rtree.reinsertion-distancce", "The distance function to compute reinsertion candidates by."); + + /** + * The actual reinsertion strategy + */ + double reinsertAmount = 0.3; + + /** + * Distance function to use for measuring + */ + SpatialPrimitiveDoubleDistanceFunction<?> distanceFunction; + + @Override + protected void makeOptions(Parameterization config) { + super.makeOptions(config); + DoubleParameter reinsertAmountP = new DoubleParameter(REINSERT_AMOUNT_ID, new IntervalConstraint(0.0, IntervalConstraint.IntervalBoundary.OPEN, 0.5, IntervalConstraint.IntervalBoundary.OPEN), 0.3); + if(config.grab(reinsertAmountP)) { + reinsertAmount = reinsertAmountP.getValue(); + } + ObjectParameter<SpatialPrimitiveDoubleDistanceFunction<?>> distanceP = new ObjectParameter<SpatialPrimitiveDoubleDistanceFunction<?>>(REINSERT_DISTANCE_ID, SpatialPrimitiveDoubleDistanceFunction.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 new file mode 100644 index 00000000..12a4ed0f --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/CloseReinsert.java @@ -0,0 +1,88 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert; + +import java.util.Arrays; +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.utilities.datastructures.arraylike.ArrayAdapter; +import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Reinsert objects on page overflow, starting with close objects first (even + * when they will likely be inserted into the same page again!) + * + * The strategy preferred by the R*-Tree + * + * @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") +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) { + 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)); + for(int i = 0; i < order.length; i++) { + double distance = distanceFunction.doubleMinDist(new DoubleVector(SpatialUtil.centroid(getter.get(entries, i))), centroid); + order[i] = new DoubleIntPair(distance, i); + } + Arrays.sort(order, Collections.reverseOrder()); + + int num = (int) (reinsertAmount * order.length); + int[] re = new int[num]; + for(int i = 0; i < num; i++) { + re[i] = order[num - 1 - i].second; + } + return re; + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractPartialReinsert.Parameterizer { + @Override + protected Object makeInstance() { + return new CloseReinsert(reinsertAmount, distanceFunction); + } + } +}
\ No newline at end of file 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 new file mode 100644 index 00000000..771f56fb --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/FarReinsert.java @@ -0,0 +1,88 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert; + +import java.util.Arrays; +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.utilities.datastructures.arraylike.ArrayAdapter; +import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Reinsert objects on page overflow, starting with farther objects first (even + * when they will likely be inserted into the same page again!) + * + * Alternative strategy mentioned in the R*-tree + * + * @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") +public class FarReinsert extends AbstractPartialReinsert { + /** + * Constructor. + * + * @param reinsertAmount Amount to reinsert + * @param distanceFunction Distance function + */ + public FarReinsert(double reinsertAmount, SpatialPrimitiveDoubleDistanceFunction<?> 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)); + for(int i = 0; i < order.length; i++) { + double distance = distanceFunction.doubleMinDist(new DoubleVector(SpatialUtil.centroid(getter.get(entries, i))), centroid); + order[i] = new DoubleIntPair(distance, i); + } + Arrays.sort(order, Collections.reverseOrder()); + + int num = (int) (reinsertAmount * order.length); + int[] re = new int[num]; + for(int i = 0; i < num; i++) { + re[i] = order[i].second; + } + return re; + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractPartialReinsert.Parameterizer { + @Override + protected Object makeInstance() { + return new CloseReinsert(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 new file mode 100644 index 00000000..cba96367 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/ReinsertStrategy.java @@ -0,0 +1,44 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter; + +/** + * Reinsertion strategy to resolve overflows in the RStarTree. + * + * @author Erich Schubert + */ +public interface ReinsertStrategy { + /** + * Perform reinsertions. + * + * @param entries Entries in overflowing node + * @param getter Adapter for the entries array + * @param page Spatial extend of the page + * @return index of pages to reinsert. + */ + public <A> int[] computeReinserts(A entries, ArrayAdapter<? extends SpatialComparable, ? super A> getter, SpatialComparable page); +} 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 new file mode 100644 index 00000000..f6a6f6e9 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/package-info.java @@ -0,0 +1,26 @@ +/** + * <p>Reinsertion strategies for R-Trees</p> + */ +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert;
\ No newline at end of file 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 new file mode 100644 index 00000000..e59fe10e --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/AngTanLinearSplit.java @@ -0,0 +1,193 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.BitSet; +import java.util.Random; + +import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; +import de.lmu.ifi.dbs.elki.logging.Logging; +import de.lmu.ifi.dbs.elki.utilities.Util; +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.exceptions.AbortException; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; + +/** + * Line-time complexity split proposed by Ang and Tan. + * + * This split strategy tries to minimize overlap only, which can however + * degenerate to "slices". + * + * <p> + * C. H. Ang and T. C. Tan:<br /> + * New linear node splitting algorithm for R-trees<br /> + * In: Proceedings of the 5th International Symposium on Advances in Spatial + * Databases + * </p> + * + * @author Erich Schubert + */ +@Reference(authors = "C. H. Ang and T. C. Tan", title = "New linear node splitting algorithm for R-trees", booktitle = "Proceedings of the 5th International Symposium on Advances in Spatial Databases", url = "http://dx.doi.org/10.1007/3-540-63238-7_38") +public class AngTanLinearSplit implements SplitStrategy { + /** + * Logger class + */ + private static final Logging logger = Logging.getLogger(AngTanLinearSplit.class); + + /** + * Static instance. + */ + public static final AngTanLinearSplit STATIC = new AngTanLinearSplit(); + + @Override + public <E extends SpatialComparable, A> BitSet split(A entries, ArrayAdapter<E, A> getter, int minEntries) { + final int num = getter.size(entries); + // We need the overall MBR for computing edge preferences + ModifiableHyperBoundingBox total = new ModifiableHyperBoundingBox(getter.get(entries, 0)); + { + for(int i = 1; i < num; i++) { + total.extend(getter.get(entries, i)); + } + } + final int dim = total.getDimensionality(); + // Prepare the axis lists (we use bitsets) + BitSet[] closer = new BitSet[dim]; + { + for(int d = 0; d < dim; d++) { + closer[d] = new BitSet(); + } + for(int i = 0; i < num; i++) { + E e = getter.get(entries, i); + for(int d = 1; d <= dim; d++) { + double low = e.getMin(d) - total.getMin(d); + double hig = total.getMax(d) - e.getMax(d); + if(low >= hig) { + closer[d - 1].set(i); + } + } + } + } + // Find the most even split + { + int axis = -1; + int bestcard = Integer.MAX_VALUE; + BitSet bestset = null; + double bestover = Double.NaN; + for(int d = 0; d < dim; d++) { + BitSet cand = closer[d]; + int card = cand.cardinality(); + card = Math.max(card, num - card); + if(card == num) { + continue; + } + if(card < bestcard) { + axis = d + 1; + bestcard = card; + bestset = cand; + bestover = Double.NaN; + } + else if(card == bestcard) { + // Tie handling + if(Double.isNaN(bestover)) { + bestover = computeOverlap(entries, getter, bestset); + } + double overlap = computeOverlap(entries, getter, cand); + if(overlap < bestover) { + axis = d + 1; + bestcard = card; + bestset = cand; + bestover = overlap; + } + else if(overlap == bestover) { + double bestlen = total.getMax(axis) - total.getMin(axis); + double candlen = total.getMax(d + 1) - total.getMin(d + 1); + if(candlen < bestlen) { + axis = d + 1; + bestcard = card; + bestset = cand; + bestover = overlap; + } + } + } + } + if(bestset == null) { + logger.warning("No Ang-Tan-Split found. Probably all points are the same? Returning random split."); + return Util.randomBitSet(num / 2, num, new Random()); + } + return bestset; + } + } + + /** + * Compute overlap of assignment + * + * @param entries Entries + * @param getter Entry accessor + * @param assign Assignment + * @return Overlap amount + */ + protected <E extends SpatialComparable, A> double computeOverlap(A entries, ArrayAdapter<E, A> getter, BitSet assign) { + ModifiableHyperBoundingBox mbr1 = null, mbr2 = null; + for(int i = 0; i < getter.size(entries); i++) { + E e = getter.get(entries, i); + if(assign.get(i)) { + if(mbr1 == null) { + mbr1 = new ModifiableHyperBoundingBox(e); + } + else { + mbr1.extend(e); + } + } + else { + if(mbr2 == null) { + mbr2 = new ModifiableHyperBoundingBox(e); + } + else { + mbr2.extend(e); + } + } + } + if(mbr1 == null || mbr2 == null) { + throw new AbortException("Invalid state in split: one of the sets is empty."); + } + return SpatialUtil.overlap(mbr1, mbr2); + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + @Override + protected AngTanLinearSplit makeInstance() { + return AngTanLinearSplit.STATIC; + } + } +}
\ No newline at end of file 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 new file mode 100644 index 00000000..7401fbe5 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/GreeneSplit.java @@ -0,0 +1,158 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.Arrays; +import java.util.BitSet; + +import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; +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.optionhandling.AbstractParameterizer; +import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair; + +/** + * Quadratic-time complexity split as used by Diane Greene for the R-Tree. + * + * Seed selection is quadratic, distribution is O(n log n). + * + * This contains a slight modification to improve performance with point data: + * with points as seeds, the normalized separation is always 1, so we choose the + * raw separation then. + * + * <p> + * Diane Greene:<br /> + * An implementation and performance analysis of spatial data access methods<br /> + * In: Proceedings of the Fifth International Conference on Data Engineering + * </p> + * + * @author Erich Schubert + */ +@Reference(authors = "Diane Greene", title = "An implementation and performance analysis of spatial data access methods", booktitle = "Proceedings of the Fifth International Conference on Data Engineering", url = "http://dx.doi.org/10.1109/ICDE.1989.47268") +public class GreeneSplit implements SplitStrategy { + /** + * Static instance. + */ + public static final GreeneSplit STATIC = new GreeneSplit(); + + @Override + public <E extends SpatialComparable, A> BitSet split(A entries, ArrayAdapter<E, A> getter, int minEntries) { + final int num = getter.size(entries); + // Choose axis by best normalized separation + int axis = -1; + { + // PickSeeds - find the two most distant rectangles + double worst = Double.NEGATIVE_INFINITY; + int w1 = 0, w2 = 0; + + // Compute individual areas + double[] areas = new double[num]; + for(int e1 = 0; e1 < num - 1; e1++) { + final E e1i = getter.get(entries, e1); + areas[e1] = SpatialUtil.volume(e1i); + } + // Compute area increase + for(int e1 = 0; e1 < num - 1; e1++) { + final E e1i = getter.get(entries, e1); + for(int e2 = e1 + 1; e2 < num; e2++) { + final E e2i = getter.get(entries, e2); + final double areaJ = SpatialUtil.volumeUnion(e1i, e2i); + final double d = areaJ - areas[e1] - areas[e2]; + if(d > worst) { + worst = d; + w1 = e1; + w2 = e2; + } + } + } + // Data to keep + // Initial mbrs and areas + E m1 = getter.get(entries, w1); + E m2 = getter.get(entries, w2); + + double bestsep = Double.NEGATIVE_INFINITY; + double bestsep2 = Double.NEGATIVE_INFINITY; + for(int d = 1; d <= m1.getDimensionality(); d++) { + final double s1 = m1.getMin(d) - m2.getMax(d); + final double s2 = m2.getMin(d) - m1.getMax(d); + final double sm = Math.max(s1, s2); + final double no = Math.max(m1.getMax(d), m2.getMax(d)) - Math.min(m1.getMin(d), m2.getMin(d)); + final double sep = sm / no; + if(sep > bestsep || (sep == bestsep && sm > bestsep2)) { + bestsep = sep; + bestsep2 = sm; + axis = d; + } + } + } + // Sort by minimum value + DoubleIntPair[] data = new DoubleIntPair[num]; + for(int i = 0; i < num; i++) { + data[i] = new DoubleIntPair(getter.get(entries, i).getMin(axis), i); + } + Arrays.sort(data); + // Object assignment + final BitSet assignment = new BitSet(num); + final int half = (num + 1) / 2; + // Put the first half into second node + for(int i = 0; i < half; i++) { + assignment.set(data[i].second); + } + // Tie handling + if(num % 2 == 0) { + // We need to compute the bounding boxes + ModifiableHyperBoundingBox mbr1 = new ModifiableHyperBoundingBox(getter.get(entries, data[0].second)); + for(int i = 1; i < half; i++) { + mbr1.extend(getter.get(entries, data[i].second)); + } + ModifiableHyperBoundingBox mbr2 = new ModifiableHyperBoundingBox(getter.get(entries, data[num - 1].second)); + for(int i = half + 1; i < num - 1; i++) { + mbr2.extend(getter.get(entries, data[i].second)); + } + E e = getter.get(entries, data[half].second); + double inc1 = SpatialUtil.volumeUnion(mbr1, e) - SpatialUtil.volume(mbr1); + double inc2 = SpatialUtil.volumeUnion(mbr2, e) - SpatialUtil.volume(mbr2); + if(inc1 < inc2) { + assignment.set(data[half].second); + } + } + return assignment; + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + @Override + protected GreeneSplit makeInstance() { + return GreeneSplit.STATIC; + } + } +}
\ No newline at end of file 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 new file mode 100644 index 00000000..296f6b3b --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeLinearSplit.java @@ -0,0 +1,219 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.BitSet; + +import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; +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.optionhandling.AbstractParameterizer; + +/** + * Linear-time complexity greedy split as used by the original R-Tree. + * + * <p> + * Antonin Guttman:<br/> + * R-Trees: A Dynamic Index Structure For Spatial Searching<br /> + * in Proceedings of the 1984 ACM SIGMOD international conference on Management + * of data. + * </p> + * + * @author Erich Schubert + */ +@Reference(authors = "Antonin Guttman", title = "R-Trees: A Dynamic Index Structure For Spatial Searching", booktitle = "Proceedings of the 1984 ACM SIGMOD international conference on Management of data", url = "http://dx.doi.org/10.1145/971697.602266") +public class RTreeLinearSplit implements SplitStrategy { + /** + * Static instance. + */ + public static final RTreeLinearSplit STATIC = new RTreeLinearSplit(); + + @Override + public <E extends SpatialComparable, A> BitSet split(A entries, ArrayAdapter<E, A> getter, int minEntries) { + final int num = getter.size(entries); + // Object assignment, and processed objects + BitSet assignment = new BitSet(num); + BitSet assigned = new BitSet(num); + // MBRs and Areas of current assignments + ModifiableHyperBoundingBox mbr1, mbr2; + double area1 = 0, area2 = 0; + // LinearPickSeeds - find worst pair + { + final int dim = getter.get(entries, 0).getDimensionality(); + // Best candidates + double bestsep = Double.NEGATIVE_INFINITY; + int w1 = -1, w2 = -1; + // LPS1: find extreme rectangles + for(int d = 1; d <= dim; d++) { + // We need to find two candidates each, in case of el==eh! + double minlow = Double.POSITIVE_INFINITY; + double maxlow = Double.NEGATIVE_INFINITY, maxlow2 = Double.NEGATIVE_INFINITY; + double minhig = Double.POSITIVE_INFINITY, minhig2 = Double.POSITIVE_INFINITY; + double maxhig = Double.NEGATIVE_INFINITY; + int el = -1, el2 = -1; + int eh = -1, eh2 = -1; + for(int i = 0; i < num; i++) { + E ei = getter.get(entries, i); + final double low = ei.getMin(d); + final double hig = ei.getMax(d); + minlow = Math.min(minlow, low); + maxhig = Math.max(maxhig, hig); + if(low >= maxlow) { + maxlow2 = maxlow; + maxlow = low; + el2 = el; + el = i; + } + else if(low > maxlow2) { + maxlow2 = low; + el2 = i; + } + if(hig <= minhig) { + minhig2 = minhig; + minhig = hig; + eh2 = eh; + eh = i; + } + else if(hig < minhig2) { + minhig2 = hig; + eh2 = i; + } + } + // Compute normalized separation + final double normsep; + if(el != eh) { + normsep = minhig - maxlow / (maxhig - minlow); + } + else { + // Resolve tie. + double normsep1 = minhig - maxlow2 / (maxhig - minlow); + double normsep2 = minhig2 - maxlow / (maxhig - minlow); + if(normsep1 > normsep2) { + el = el2; + normsep = normsep1; + } + else { + eh = eh2; + normsep = normsep2; + } + } + assert (eh != -1 && el != -1 && (eh != el)); + if(normsep > bestsep) { + bestsep = normsep; + w1 = el; + w2 = eh; + } + } + + // Data to keep + // Mark both as used + assigned.set(w1); + assigned.set(w2); + // Assign second to second set + assignment.set(w2); + // Initial mbrs and areas + final E w1i = getter.get(entries, w1); + final E w2i = getter.get(entries, w2); + area1 = SpatialUtil.volume(w1i); + area2 = SpatialUtil.volume(w2i); + mbr1 = new ModifiableHyperBoundingBox(w1i); + mbr2 = new ModifiableHyperBoundingBox(w2i); + } + // Second phase, QS2+QS3 + { + int in1 = 1, in2 = 1; + int remaining = num - 2; + // Choose any element, for example the next. + for(int next = assigned.nextClearBit(0); remaining > 0 && next < num; next = assigned.nextClearBit(next + 1)) { + // Shortcut when minEntries must be fulfilled + if(in1 + remaining <= minEntries) { + // No need to updated assigned, no changes to assignment. + break; + } + if(in2 + remaining <= minEntries) { + // Mark unassigned for second. + // Don't bother to update assigned, though + for(; next < num; next = assigned.nextClearBit(next + 1)) { + assignment.set(next); + } + break; + } + // PickNext + boolean preferSecond = false; + + // Cost of putting object into both mbrs + final E next_i = getter.get(entries, next); + final double d1 = SpatialUtil.volumeUnion(mbr1, next_i) - area1; + final double d2 = SpatialUtil.volumeUnion(mbr2, next_i) - area2; + // Prefer smaller increase + preferSecond = (d2 < d1); + // QS3: tie handling + if(d1 == d2) { + // Prefer smaller area + if(area1 != area2) { + preferSecond = (area2 < area1); + } + else { + // Prefer smaller group size + preferSecond = (in2 < in1); + } + } + // Mark as used. + assigned.set(next); + remaining--; + // Assign + if(!preferSecond) { + in1++; + mbr1.extend(next_i); + area1 = SpatialUtil.volume(mbr1); + } + else { + in2++; + assignment.set(next); + mbr2.extend(next_i); + area2 = SpatialUtil.volume(mbr2); + } + // Loop from QS2 + } + // Note: "assigned" and "remaining" likely not updated! + } + return assignment; + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + @Override + protected RTreeLinearSplit makeInstance() { + return RTreeLinearSplit.STATIC; + } + } +}
\ No newline at end of file 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 new file mode 100644 index 00000000..8f61771d --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeQuadraticSplit.java @@ -0,0 +1,183 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.BitSet; + +import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; +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.optionhandling.AbstractParameterizer; + +/** + * Quadratic-time complexity greedy split as used by the original R-Tree. + * + * <p> + * Antonin Guttman:<br/> + * R-Trees: A Dynamic Index Structure For Spatial Searching<br /> + * in Proceedings of the 1984 ACM SIGMOD international conference on Management + * of data. + * </p> + * + * @author Erich Schubert + */ +@Reference(authors = "Antonin Guttman", title = "R-Trees: A Dynamic Index Structure For Spatial Searching", booktitle = "Proceedings of the 1984 ACM SIGMOD international conference on Management of data", url = "http://dx.doi.org/10.1145/971697.602266") +public class RTreeQuadraticSplit implements SplitStrategy { + /** + * Static instance. + */ + public static final RTreeQuadraticSplit STATIC = new RTreeQuadraticSplit(); + + @Override + public <E extends SpatialComparable, A> BitSet split(A entries, ArrayAdapter<E, A> getter, int minEntries) { + final int num = getter.size(entries); + // Object assignment, and processed objects + BitSet assignment = new BitSet(num); + BitSet assigned = new BitSet(num); + // MBRs and Areas of current assignments + ModifiableHyperBoundingBox mbr1, mbr2; + double area1 = 0, area2 = 0; + // PickSeeds - find worst pair + { + double worst = Double.NEGATIVE_INFINITY; + int w1 = 0, w2 = 0; + + // Compute individual areas + double[] areas = new double[num]; + for(int e1 = 0; e1 < num - 1; e1++) { + final E e1i = getter.get(entries, e1); + areas[e1] = SpatialUtil.volume(e1i); + } + // Compute area increase + for(int e1 = 0; e1 < num - 1; e1++) { + final E e1i = getter.get(entries, e1); + for(int e2 = e1 + 1; e2 < num; e2++) { + final E e2i = getter.get(entries, e2); + final double areaJ = SpatialUtil.volumeUnion(e1i, e2i); + final double d = areaJ - areas[e1] - areas[e2]; + if(d > worst) { + worst = d; + w1 = e1; + w2 = e2; + } + } + } + // Data to keep + // Mark both as used + assigned.set(w1); + assigned.set(w2); + // Assign second to second set + assignment.set(w2); + // Initial mbrs and areas + area1 = areas[w1]; + area2 = areas[w2]; + mbr1 = new ModifiableHyperBoundingBox(getter.get(entries, w1)); + mbr2 = new ModifiableHyperBoundingBox(getter.get(entries, w2)); + } + // Second phase, QS2+QS3 + { + int in1 = 1, in2 = 1; + int remaining = num - 2; + while(remaining > 0) { + // Shortcut when minEntries must be fulfilled + if(in1 + remaining <= minEntries) { + // No need to updated assigned, no changes to assignment. + break; + } + if(in2 + remaining <= minEntries) { + // Mark unassigned for second. + // Don't bother to update assigned, though + for(int pos = assigned.nextClearBit(0); pos < num; pos = assigned.nextClearBit(pos + 1)) { + assignment.set(pos); + } + break; + } + // PickNext + double greatestPreference = Double.NEGATIVE_INFINITY; + int best = -1; + E best_i = null; + boolean preferSecond = false; + for(int pos = assigned.nextClearBit(0); pos < num; pos = assigned.nextClearBit(pos + 1)) { + // Cost of putting object into both mbrs + final E pos_i = getter.get(entries, pos); + final double d1 = SpatialUtil.volumeUnion(mbr1, pos_i) - area1; + final double d2 = SpatialUtil.volumeUnion(mbr2, pos_i) - area2; + // Preference + final double preference = Math.abs(d1 - d2); + if(preference > greatestPreference) { + greatestPreference = preference; + best = pos; + best_i = pos_i; + // Prefer smaller increase + preferSecond = (d2 < d1); + } + } + // QS3: tie handling + if(greatestPreference == 0) { + // Prefer smaller area + if(area1 != area2) { + preferSecond = (area2 < area1); + } + else { + // Prefer smaller group size + preferSecond = (in2 < in1); + } + } + // Mark as used. + assigned.set(best); + remaining--; + if(!preferSecond) { + in1++; + mbr1.extend(best_i); + area1 = SpatialUtil.volume(mbr1); + } + else { + in2++; + assignment.set(best); + mbr2.extend(best_i); + area2 = SpatialUtil.volume(mbr2); + } + // Loop from QS2 + } + // Note: "assigned" and "remaining" likely not updated! + } + return assignment; + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + @Override + protected RTreeQuadraticSplit makeInstance() { + return RTreeQuadraticSplit.STATIC; + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SplitStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java index 272dcbc6..658a63da 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SplitStrategy.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java @@ -1,10 +1,10 @@ -package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util; +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) 2011 + Copyright (C) 2012 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,25 +23,25 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.List; +import java.util.BitSet; -import de.lmu.ifi.dbs.elki.utilities.pairs.Pair; +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 - * - * @param <B> Base type that can be processed by this strategy */ -public interface SplitStrategy<B> { +public interface SplitStrategy extends Parameterizable { /** * Split a page * - * @param <E> Actual data type * @param entries Entries to split + * @param getter Adapter for the entries array * @param minEntries Minimum number of entries in each part - * @return Pair containing the two sets of objects + * @return BitSet containing the assignment. */ - public <E extends B> Pair<List<E>, List<E>> split(List<E> entries, int minEntries); -} + public <E extends SpatialComparable, A> BitSet split(A entries, ArrayAdapter<E, A> getter, int minEntries); +}
\ No newline at end of file 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 new file mode 100644 index 00000000..1789ab22 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/TopologicalSplitter.java @@ -0,0 +1,309 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.Arrays; +import java.util.BitSet; + +import de.lmu.ifi.dbs.elki.data.HyperBoundingBox; +import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; +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.optionhandling.AbstractParameterizer; +import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair; + +/** + * Encapsulates the required parameters for a topological split of a R*-Tree. + * + * @author Elke Achtert + * + * @apiviz.has Split + */ +@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 TopologicalSplitter implements SplitStrategy { + /** + * Static instance. + */ + public static final TopologicalSplitter STATIC = new TopologicalSplitter(); + + /** + * constructor. + */ + public TopologicalSplitter() { + // Nothing to do. + } + + @Override + public <E extends SpatialComparable, A> BitSet split(A entries, ArrayAdapter<E, A> getter, int minEntries) { + Split<A, E> split = new Split<A, E>(entries, getter); + split.chooseSplitAxis(minEntries); + split.chooseSplitPoint(minEntries); + + assert (split.splitPoint < split.size) : "Invalid split produced. Size: " + getter.size(entries) + " minEntries: " + minEntries + " split.size: " + split.size; + BitSet assignment = new BitSet(split.size); + for(int i = split.splitPoint; i < split.size; i++) { + assignment.set(split.bestSorting[i].second); + } + return assignment; + } + + /** + * Internal data for an actual split. + * + * @author Erich Schubert + * + * @param <E> Actual entry type + */ + private class Split<A, E extends SpatialComparable> { + /** + * The index of the split point. + */ + int splitPoint = -1; + + /** + * Indicates whether the sorting according to maximal or to minimal value + * has been used for choosing the split axis and split point. + */ + DoubleIntPair[] bestSorting; + + /** + * The entries sorted according to their max values of their MBRs. + */ + DoubleIntPair[] maxSorting; + + /** + * The entries sorted according to their min values of their MBRs. + */ + DoubleIntPair[] minSorting; + + /** + * The entries we process. + */ + private A entries; + + /** + * The getter class for the entries + */ + private ArrayAdapter<E, A> getter; + + /** + * List size + */ + private int size; + + /** + * Dimensionality + */ + private int dimensionality; + + /** + * Constructor. + */ + public Split(A entries, ArrayAdapter<E, A> getter) { + this.entries = entries; + this.getter = getter; + this.size = getter.size(entries); + this.dimensionality = getter.get(entries, 0).getDimensionality(); + initMinMaxArrays(); + } + + /** + * Chooses a split axis. + * + * @param minEntries number of minimum entries in the node to be split + */ + void chooseSplitAxis(int minEntries) { + // best value for the surface + double minSurface = Double.MAX_VALUE; + int splitAxis = -1; + + for(int d = 1; d <= dimensionality; d++) { + double sumOfAllMargins = 0; + fillAndSort(d); + + // Note: this has a somewhat surprising evaluation order. + // We compute the sum as in the original paper: + // it says "sum of all margin-values". + // Except that we don't match them as you would do in a split, but + // Iterate over all possible splits from both sides (as well as min and + // max) in parallel, since union can be computed incrementally. + ModifiableHyperBoundingBox mbr_min_left = new ModifiableHyperBoundingBox(get(minSorting[0])); + ModifiableHyperBoundingBox mbr_min_right = new ModifiableHyperBoundingBox(get(minSorting[size - 1])); + ModifiableHyperBoundingBox mbr_max_left = new ModifiableHyperBoundingBox(get(maxSorting[0])); + ModifiableHyperBoundingBox mbr_max_right = new ModifiableHyperBoundingBox(get(maxSorting[size - 1])); + + for(int k = 1; k < size - minEntries; k++) { + mbr_min_left.extend(get(minSorting[k])); + mbr_min_right.extend(get(minSorting[size - 1 - k])); + mbr_max_left.extend(get(maxSorting[k])); + mbr_max_right.extend(get(maxSorting[size - 1 - k])); + if(k >= minEntries - 1) { + // Yes, build the sum. This value is solely used for finding the + // preferred split axis! + // Note that mbr_min_left and mbr_max_left do not add up to a + // complete split, but when the sum is complete, it will also + // include their proper counterpart. + sumOfAllMargins += SpatialUtil.perimeter(mbr_min_left) + SpatialUtil.perimeter(mbr_min_right) + SpatialUtil.perimeter(mbr_max_left) + SpatialUtil.perimeter(mbr_max_right); + } + } + if(sumOfAllMargins < minSurface) { + splitAxis = d; + minSurface = sumOfAllMargins; + } + } + if(splitAxis != dimensionality) { + fillAndSort(splitAxis); + } + } + + /** + * Init the arrays we use + */ + protected void initMinMaxArrays() { + maxSorting = new DoubleIntPair[size]; + minSorting = new DoubleIntPair[size]; + // Prefill + for(int j = 0; j < size; j++) { + minSorting[j] = new DoubleIntPair(0, -1); + maxSorting[j] = new DoubleIntPair(0, -1); + } + } + + /** + * Fill the array with the dimension projection needed for sorting. + * + * @param dim Relevant dimension. + */ + protected void fillAndSort(final int dim) { + // sort the entries according to their minimal and according to their + // maximal value in the current dimension. + for(int j = 0; j < size; j++) { + E e = get(j); + minSorting[j].first = e.getMin(dim); + minSorting[j].second = j; + maxSorting[j].first = e.getMax(dim); + maxSorting[j].second = j; + } + Arrays.sort(minSorting); + Arrays.sort(maxSorting); + } + + /** + * Chooses a split axis. + * + * @param minEntries number of minimum entries in the node to be split + */ + void chooseSplitPoint(int minEntries) { + // the split point (first set to minimum entries in the node) + splitPoint = size; + // best value for the overlap + double minOverlap = Double.POSITIVE_INFINITY; + // the volume of mbr1 and mbr2 + double volume = Double.POSITIVE_INFINITY; + // indicates whether the sorting according to maximal or to minimal value + // is best for the split axis + bestSorting = null; + + assert (size - 2 * minEntries > 0) : "Cannot split underfull nodes."; + // test the sorting with respect to the minimal values + { + ModifiableHyperBoundingBox mbr1 = mbr(minSorting, 0, minEntries - 1); + for(int i = 0; i <= size - 2 * minEntries; i++) { + mbr1.extend(getter.get(entries, minSorting[minEntries + i - 1].second)); + HyperBoundingBox mbr2 = mbr(minSorting, minEntries + i, size); + double currentOverlap = SpatialUtil.relativeOverlap(mbr1, mbr2); + if(currentOverlap <= minOverlap) { + double vol = SpatialUtil.volume(mbr1) + SpatialUtil.volume(mbr2); + if(currentOverlap < minOverlap || vol < volume) { + minOverlap = currentOverlap; + volume = vol; + splitPoint = minEntries + i; + bestSorting = minSorting; + } + } + } + } + // test the sorting with respect to the maximal values + { + ModifiableHyperBoundingBox mbr1 = mbr(maxSorting, 0, minEntries - 1); + for(int i = 0; i <= size - 2 * minEntries; i++) { + mbr1.extend(getter.get(entries, maxSorting[minEntries + i - 1].second)); + HyperBoundingBox mbr2 = mbr(maxSorting, minEntries + i, size); + double currentOverlap = SpatialUtil.relativeOverlap(mbr1, mbr2); + if(currentOverlap <= minOverlap) { + double vol = SpatialUtil.volume(mbr1) + SpatialUtil.volume(mbr2); + if(currentOverlap < minOverlap || vol < volume) { + minOverlap = currentOverlap; + volume = vol; + splitPoint = minEntries + i; + bestSorting = maxSorting; + } + } + } + } + assert (splitPoint < size) : "No split found? Volume outside of double precision?"; + } + + private E get(int off) { + return getter.get(entries, off); + } + + private E get(DoubleIntPair pair) { + return getter.get(entries, pair.second); + } + + /** + * Computes and returns the mbr of the specified nodes, only the nodes + * between from and to index are considered. + * + * @param sorting the array of nodes + * @param from the start index + * @param to the end index + * @return the mbr of the specified nodes + */ + private ModifiableHyperBoundingBox mbr(final DoubleIntPair[] sorting, final int from, final int to) { + ModifiableHyperBoundingBox mbr = new ModifiableHyperBoundingBox(get(sorting[from])); + for(int i = from + 1; i < to; i++) { + mbr.extend(get(sorting[i])); + } + return mbr; + } + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + @Override + protected TopologicalSplitter makeInstance() { + return TopologicalSplitter.STATIC; + } + } +}
\ No newline at end of file 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 new file mode 100644 index 00000000..9e8291be --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/package-info.java @@ -0,0 +1,26 @@ +/** + * <p>Splitting strategies for R-Trees</p> + */ +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split;
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/ApproximateLeastOverlapInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/ApproximateLeastOverlapInsertionStrategy.java deleted file mode 100644 index 1e9afdca..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/ApproximateLeastOverlapInsertionStrategy.java +++ /dev/null @@ -1,150 +0,0 @@ -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) 2011 - 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.Collections; - -import de.lmu.ifi.dbs.elki.data.HyperBoundingBox; -import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; -import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; -import de.lmu.ifi.dbs.elki.index.tree.Node; -import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent; -import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; -import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TopBoundedHeap; -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.GreaterConstraint; -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.FCPair; - -/** - * Insertion strategy that exhaustively tests all childs for the least overlap - * when inserting. - * - * @author Elke Achtert - * @author Franz Graf - * @author Marisa Petri - */ -public class ApproximateLeastOverlapInsertionStrategy implements InsertionStrategy { - /** - * Defines how many children are tested for finding the child generating the - * least overlap when inserting an object. Default 0 means all children - */ - private int insertionCandidates = 0; - - /** - * Constructor. s - * - * @param insertionCandidates Number of children to test. - */ - public ApproximateLeastOverlapInsertionStrategy(int insertionCandidates) { - super(); - this.insertionCandidates = insertionCandidates; - } - - /** - * Returns the path information of the entry of the specified node which needs - * least overlap enlargement if the given mbr would be inserted into. - * - * @param node the node of which the children should be tested - * @param mbr the mbr to be inserted into the children - * @return the path information of the entry which needs least overlap - * enlargement if the given mbr would be inserted into - */ - @Override - public <N extends Node<E>, E extends SpatialEntry> TreeIndexPathComponent<E> findInsertChild(N node, SpatialComparable mbr) { - Enlargement<E> min = null; - - TopBoundedHeap<FCPair<Double, E>> entriesToTest = new TopBoundedHeap<FCPair<Double, E>>(insertionCandidates, Collections.reverseOrder()); - for(int i = 0; i < node.getNumEntries(); i++) { - E entry_i = node.getEntry(i); - HyperBoundingBox newMBR = SpatialUtil.unionTolerant(mbr, entry_i); - double volume = /* entry_i.getMBR() == null ? 0 : */SpatialUtil.volume(entry_i); - double inc_volume = SpatialUtil.volume(newMBR) - volume; - entriesToTest.add(new FCPair<Double, E>(inc_volume, entry_i)); - } - - while(!entriesToTest.isEmpty()) { - E entry_i = entriesToTest.poll().getSecond(); - int index = -1; - HyperBoundingBox newMBR = SpatialUtil.unionTolerant(mbr, entry_i); - - double currOverlap = 0; - double newOverlap = 0; - for(int k = 0; k < node.getNumEntries(); k++) { - E entry_k = node.getEntry(k); - if(entry_i != entry_k) { - currOverlap += SpatialUtil.relativeOverlap(entry_i, entry_k); - newOverlap += SpatialUtil.relativeOverlap(newMBR, entry_k); - } - else { - index = k; - } - } - - double volume = /* entry_i.getMBR() == null ? 0 : */SpatialUtil.volume(entry_i); - double inc_volume = SpatialUtil.volume(newMBR) - volume; - double inc_overlap = newOverlap - currOverlap; - Enlargement<E> enlargement = new Enlargement<E>(new TreeIndexPathComponent<E>(entry_i, index), volume, inc_volume, inc_overlap); - - if(min == null || min.compareTo(enlargement) > 0) { - min = enlargement; - } - } - - assert min != null; - return min.getPathComponent(); - } - - /** - * Parameterization class. - * - * @author Erich Schubert - * - * @apiviz.exclude - */ - public static class Parameterizer extends AbstractParameterizer { - /** - * Fast-insertion parameter. Optional. - */ - public static OptionID INSERTION_CANDIDATES_ID = OptionID.getOrCreateOptionID("rtree.insertion-candidates", "defines how many children are tested for finding the child generating the least overlap when inserting an object."); - - int insertionCandidates = 0; - - @Override - protected void makeOptions(Parameterization config) { - super.makeOptions(config); - IntParameter insertionCandidatesP = new IntParameter(INSERTION_CANDIDATES_ID, new GreaterConstraint(0)); - if(config.grab(insertionCandidatesP)) { - insertionCandidates = insertionCandidatesP.getValue(); - } - } - - @Override - protected ApproximateLeastOverlapInsertionStrategy makeInstance() { - return new ApproximateLeastOverlapInsertionStrategy(insertionCandidates); - } - } -}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/Enlargement.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/Enlargement.java deleted file mode 100644 index 79c8c0ef..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/Enlargement.java +++ /dev/null @@ -1,119 +0,0 @@ -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) 2011 - 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.DirectoryEntry; -import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent; -import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; - -/** - * Encapsulates the parameters for enlargement of nodes after insertion of new - * objects. - * - * @author Elke Achtert - * @param <E> Entry type - */ -public class Enlargement<E extends SpatialEntry> implements Comparable<Enlargement<E>> { - /** - * The path information of the entry representing the node. - */ - private TreeIndexPathComponent<E> pathComponent; - - /** - * The volume of the node's MBR. - */ - private double volume; - - /** - * The increment of the volume. - */ - private double volInc; - - /** - * The increment of the overlap. - */ - private double overlapInc; - - /** - * Creates an new Enlargement object with the specified parameters. - * - * @param pathComponent the path information of the entry representing the - * node - * @param volume the volume of the node's MBR - * @param volInc the increment of the volume - * @param overlapInc the increment of the overlap - */ - public Enlargement(TreeIndexPathComponent<E> pathComponent, double volume, double volInc, double overlapInc) { - this.pathComponent = pathComponent; - this.volume = volume; - this.volInc = volInc; - this.overlapInc = overlapInc; - } - - /** - * Compares this Enlargement with the specified Enlargement. First the - * increment of the overlap will be compared. If both are equal the increment - * of the volume will be compared. If also both are equal the volumes of both - * nodes will be compared. If both are equal the ids of the nodes will be - * compared. - * - * @param other the Enlargement to be compared. - * @return a negative integer, zero, or a positive integer as this Enlargement - * is less than, equal to, or greater than the specified Enlargement. - */ - @Override - public int compareTo(Enlargement<E> other) { - if(this.overlapInc < other.overlapInc) { - return -1; - } - if(this.overlapInc > other.overlapInc) { - return +1; - } - - if(this.volInc < other.volInc) { - return -1; - } - if(this.volInc > other.volInc) { - return +1; - } - - if(this.volume < other.volume) { - return -1; - } - if(this.volume > other.volume) { - return +1; - } - - return ((DirectoryEntry)this.pathComponent.getEntry()).getPageID() - ((DirectoryEntry)other.pathComponent.getEntry()).getPageID(); - } - - /** - * Returns the path information of the entry representing the node. - * - * @return the path information of the entry representing the node - */ - public TreeIndexPathComponent<E> getPathComponent() { - return pathComponent; - } -}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/LeastOverlapInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/LeastOverlapInsertionStrategy.java deleted file mode 100644 index 90f0c91b..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/LeastOverlapInsertionStrategy.java +++ /dev/null @@ -1,87 +0,0 @@ -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) 2011 - 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.HyperBoundingBox; -import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; -import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; -import de.lmu.ifi.dbs.elki.index.tree.Node; -import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent; -import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; - -/** - * Insertion strategy that exhaustively tests all childs for the least overlap - * when inserting. - * - * @author Elke Achtert - */ -public class LeastOverlapInsertionStrategy implements InsertionStrategy { - /** - * Constructor. - */ - public LeastOverlapInsertionStrategy() { - super(); - } - - /** - * Returns the path information of the entry of the specified node which needs - * least overlap enlargement if the given mbr would be inserted into. - * - * @param node the node of which the children should be tested - * @param mbr the mbr to be inserted into the children - * @return the path information of the entry which needs least overlap - * enlargement if the given mbr would be inserted into - */ - @Override - public <N extends Node<E>, E extends SpatialEntry> TreeIndexPathComponent<E> findInsertChild(N node, SpatialComparable mbr) { - Enlargement<E> min = null; - - for(int i = 0; i < node.getNumEntries(); i++) { - E entry_i = node.getEntry(i); - HyperBoundingBox newMBR = SpatialUtil.unionTolerant(mbr, entry_i); - - double currOverlap = 0; - double newOverlap = 0; - for(int k = 0; k < node.getNumEntries(); k++) { - if(i != k) { - E entry_k = node.getEntry(k); - currOverlap += SpatialUtil.relativeOverlap(entry_i, entry_k); - newOverlap += SpatialUtil.relativeOverlap(newMBR, entry_k); - } - } - - double volume = /* entry_i.getMBR() == null ? 0 : */SpatialUtil.volume(entry_i); - double inc_volume = SpatialUtil.volume(newMBR) - volume; - double inc_overlap = newOverlap - currOverlap; - Enlargement<E> enlargement = new Enlargement<E>(new TreeIndexPathComponent<E>(entry_i, i), volume, inc_volume, inc_overlap); - - if(min == null || min.compareTo(enlargement) > 0) { - min = enlargement; - } - } - - assert min != null; - return min.getPathComponent(); - } -} 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 new file mode 100644 index 00000000..3bf35d9d --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/NodeArrayAdapter.java @@ -0,0 +1,58 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.index.tree.AbstractNode; +import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; +import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter; + +/** + * Access the entries of a node as array-like. + * + * @author Erich Schubert + */ +public class NodeArrayAdapter implements ArrayAdapter<SpatialEntry, AbstractNode<? extends SpatialEntry>> { + /** + * Static adapter. + */ + public static NodeArrayAdapter STATIC = new NodeArrayAdapter(); + + /** + * Constructor. + */ + protected NodeArrayAdapter() { + super(); + // TODO Auto-generated constructor stub + } + + @Override + public int size(AbstractNode<? extends SpatialEntry> array) { + return array.getNumEntries(); + } + + @Override + public SpatialEntry get(AbstractNode<? extends SpatialEntry> array, int off) throws IndexOutOfBoundsException { + return array.getEntry(off); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SpatialComparator.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SpatialComparator.java index fe3f322b..2f1ea9b1 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SpatialComparator.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SpatialComparator.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) 2011 + Copyright (C) 2012 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/TopologicalSplitter.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/TopologicalSplitter.java deleted file mode 100644 index 011e56ab..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/TopologicalSplitter.java +++ /dev/null @@ -1,270 +0,0 @@ -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) 2011 - 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.List; - -import de.lmu.ifi.dbs.elki.data.HyperBoundingBox; -import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; -import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; -import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; -import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; -import de.lmu.ifi.dbs.elki.utilities.pairs.Pair; - -/** - * Encapsulates the required parameters for a topological split of a R*-Tree. - * - * @author Elke Achtert - * - * @apiviz.has Split - * @apiviz.uses SpatialComparator - */ -@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 TopologicalSplitter implements SplitStrategy<SpatialEntry> { - /** - * constructor. - */ - public TopologicalSplitter() { - // Nothing to do. - } - - @Override - public <E extends SpatialEntry> Pair<List<E>, List<E>> split(List<E> entries, int minEntries) { - Split<E> split = new Split<E>(); - split.chooseSplitAxis(entries, minEntries); - split.chooseSplitPoint(minEntries); - int splitpoint = split.getSplitPoint(); - List<E> sorted = split.getBestSorting(); - - return new Pair<List<E>, List<E>>(sorted.subList(0, splitpoint), sorted.subList(splitpoint, sorted.size())); - } - - /** - * Internal data for an actual split. - * - * @author Erich Schubert - * - * @param <E> Actual entry type - */ - private class Split<E extends SpatialEntry> { - /** - * The split axis. - */ - int splitAxis = 0; - - /** - * The index of the split point. - */ - int splitPoint = -1; - - /** - * Indicates whether the sorting according to maximal or to minimal value - * has been used for choosing the split axis and split point. - */ - int bestSorting; - - /** - * The entries sorted according to their max values of their MBRs. - */ - List<E> maxSorting; - - /** - * The entries sorted according to their min values of their MBRs. - */ - List<E> minSorting; - - /** - * Constructor. - */ - public Split() { - // Initialized by calling chooseSplitAxis. - } - - /** - * Chooses a split axis. - * - * @param entries the entries to be split - * @param minEntries number of minimum entries in the node to be split - */ - void chooseSplitAxis(List<E> entries, int minEntries) { - int dim = entries.get(0).getDimensionality(); - - maxSorting = new ArrayList<E>(entries); - minSorting = new ArrayList<E>(entries); - - // best value for the surface - double minSurface = Double.MAX_VALUE; - // comparator used by sort method - - for(int i = 1; i <= dim; i++) { - double sumOfAllMargins = 0; - // sort the entries according to their minimal and according to their - // maximal value - final SpatialComparator compMin = new SpatialComparator(i, SpatialComparator.MIN); - Collections.sort(minSorting, compMin); - final SpatialComparator compMax = new SpatialComparator(i, SpatialComparator.MAX); - Collections.sort(maxSorting, compMax); - - SpatialComparable mbr_min_left = minSorting.get(0); - SpatialComparable mbr_min_right = minSorting.get(minSorting.size() - 1); - SpatialComparable mbr_max_left = maxSorting.get(0); - SpatialComparable mbr_max_right = maxSorting.get(maxSorting.size() - 1); - - for(int k = 1; k < entries.size() - minEntries; k++) { - mbr_min_left = SpatialUtil.union(mbr_min_left, minSorting.get(k)); - mbr_min_right = SpatialUtil.union(mbr_min_right, minSorting.get(minSorting.size() - 1 - k)); - mbr_max_left = SpatialUtil.union(mbr_max_left, maxSorting.get(k)); - mbr_max_right = SpatialUtil.union(mbr_max_right, maxSorting.get(maxSorting.size() - 1 - k)); - if(k >= minEntries - 1) { - // Yes, build the sum. This value is solely used for finding the - // split axis! - // Compare with the original paper, "sum of all margin-values". - // Note that mbr_min_left and mbr_max_left do not add up to a - // complete split, but when the sum is complete, it will also - // include their proper counterpart. - sumOfAllMargins += SpatialUtil.perimeter(mbr_min_left) + SpatialUtil.perimeter(mbr_min_right) + SpatialUtil.perimeter(mbr_max_left) + SpatialUtil.perimeter(mbr_max_right); - } - } - if(sumOfAllMargins < minSurface) { - splitAxis = i; - minSurface = sumOfAllMargins; - } - } - } - - /** - * Chooses a split axis. - * - * @param minEntries number of minimum entries in the node to be split - */ - void chooseSplitPoint(int minEntries) { - // numEntries - int numEntries = maxSorting.size(); - // sort upper and lower in the right dimension - final SpatialComparator compMin = new SpatialComparator(splitAxis, SpatialComparator.MIN); - Collections.sort(minSorting, compMin); - final SpatialComparator compMax = new SpatialComparator(splitAxis, SpatialComparator.MAX); - Collections.sort(maxSorting, compMax); - - // the split point (first set to minimum entries in the node) - splitPoint = minEntries; - // best value for the overlap - double minOverlap = Double.MAX_VALUE; - // the volume of mbr1 and mbr2 - double volume = 0.0; - // indicates whether the sorting according to maximal or to minimal value - // is - // best for the split axis - bestSorting = -1; - - for(int i = 0; i <= numEntries - 2 * minEntries; i++) { - // test the sorting with respect to the minimal values - HyperBoundingBox mbr1 = mbr(minSorting, 0, minEntries + i); - HyperBoundingBox mbr2 = mbr(minSorting, minEntries + i, numEntries); - double currentOverlap = SpatialUtil.relativeOverlap(mbr1, mbr2); - double vol1 = SpatialUtil.volume(mbr1); - double vol2 = SpatialUtil.volume(mbr2); - if(currentOverlap < minOverlap || (currentOverlap == minOverlap && (vol1 + vol2) < volume)) { - minOverlap = currentOverlap; - splitPoint = minEntries + i; - bestSorting = SpatialComparator.MIN; - volume = vol1 + vol2; - } - // test the sorting with respect to the maximal values - mbr1 = mbr(maxSorting, 0, minEntries + i); - mbr2 = mbr(maxSorting, minEntries + i, numEntries); - currentOverlap = SpatialUtil.relativeOverlap(mbr1, mbr2); - vol1 = SpatialUtil.volume(mbr1); - vol2 = SpatialUtil.volume(mbr2); - if(currentOverlap < minOverlap || (currentOverlap == minOverlap && (vol1 + vol2) < volume)) { - minOverlap = currentOverlap; - splitPoint = minEntries + i; - bestSorting = SpatialComparator.MAX; - volume = vol1 + vol2; - } - } - } - - /** - * Computes and returns the mbr of the specified nodes, only the nodes - * between from and to index are considered. - * - * @param entries the array of nodes - * @param from the start index - * @param to the end index - * @return the mbr of the specified nodes - */ - private HyperBoundingBox mbr(final List<E> entries, final int from, final int to) { - double[] min = new double[entries.get(from).getDimensionality()]; - double[] max = new double[entries.get(from).getDimensionality()]; - - for(int d = 1; d <= min.length; d++) { - min[d - 1] = entries.get(from).getMin(d); - max[d - 1] = entries.get(from).getMax(d); - } - - for(int i = from + 1; i < to; i++) { - SpatialComparable currMBR = entries.get(i); - for(int d = 1; d <= min.length; d++) { - if(min[d - 1] > currMBR.getMin(d)) { - min[d - 1] = currMBR.getMin(d); - } - if(max[d - 1] < currMBR.getMax(d)) { - max[d - 1] = currMBR.getMax(d); - } - } - } - return new HyperBoundingBox(min, max); - } - - /** - * Returns the split point. - * - * @return the split point - */ - public int getSplitPoint() { - return splitPoint; - } - - /** - * Returns whether the sorting according to maximal or to minimal value has - * been used for choosing the split axis and split point. - * - * @return The sorting to use - */ - public List<E> getBestSorting() { - if(bestSorting == SpatialComparator.MIN) { - return minSorting; - } - if(bestSorting == SpatialComparator.MAX) { - return maxSorting; - } - else { - throw new IllegalStateException("split.bestSort is undefined: " + bestSorting); - } - } - } -} 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 382faeb3..10991028 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) 2011 +Copyright (C) 2012 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/VAFile.java b/src/de/lmu/ifi/dbs/elki/index/vafile/VAFile.java new file mode 100644 index 00000000..c426c1d6 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/vafile/VAFile.java @@ -0,0 +1,518 @@ +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
+ 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.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+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.DBID;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
+import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
+import de.lmu.ifi.dbs.elki.database.query.DoubleDistanceResultPair;
+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.KNNResult;
+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.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;
+import de.lmu.ifi.dbs.elki.index.RangeIndex;
+import de.lmu.ifi.dbs.elki.index.tree.TreeIndexFactory;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TopBoundedHeap;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+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.constraints.GreaterConstraint;
+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)
+ *
+ * Reference:
+ * <p>
+ * Weber, R. and Blott, S.<br>
+ * An approximation based data structure for similarity search<br />
+ * in: Report TR1997b, ETH Zentrum, Zurich, Switzerland
+ * </p>
+ *
+ * @author Thomas Bernecker
+ * @author Erich Schubert
+ */
+@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> {
+ /**
+ * Logging class
+ */
+ private static final Logging log = Logging.getLogger(VAFile.class);
+
+ /**
+ * Approximation index
+ */
+ private List<VectorApproximation> vectorApprox;
+
+ /**
+ * Number of partitions.
+ */
+ private int partitions;
+
+ /**
+ * Quantile grid we use
+ */
+ private double[][] splitPositions;
+
+ /**
+ * Page size, for estimating the VA file size
+ */
+ int pageSize;
+
+ /**
+ * Number of scans we performed.
+ */
+ int scans;
+
+ /**
+ * Constructor.
+ *
+ * @param pageSize Page size of simulated index
+ * @param relation Relation to index
+ * @param partitions Number of partitions for each dimension.
+ */
+ public VAFile(int pageSize, Relation<V> relation, int partitions) {
+ super(relation);
+ this.partitions = partitions;
+ this.pageSize = pageSize;
+ this.scans = 0;
+ this.vectorApprox = new ArrayList<VectorApproximation>();
+ }
+
+ @Override
+ protected void initialize(Relation<V> relation, DBIDs ids) {
+ setPartitions(relation);
+ for(DBID id : relation.getDBIDs()) {
+ vectorApprox.add(calculateApproximation(id, relation.get(id)));
+ }
+ }
+
+ /**
+ * Initialize the data set grid by computing quantiles.
+ *
+ * @param relation Data relation
+ * @throws IllegalArgumentException
+ */
+ public void setPartitions(Relation<V> relation) throws IllegalArgumentException {
+ if((Math.log(partitions) / Math.log(2)) != (int) (Math.log(partitions) / Math.log(2))) {
+ throw new IllegalArgumentException("Number of partitions must be a power of 2!");
+ }
+
+ final int dimensions = DatabaseUtil.dimensionality(relation);
+ final int size = relation.size();
+ splitPositions = new double[dimensions][partitions + 1];
+
+ for(int d = 0; d < dimensions; d++) {
+ double[] tempdata = new double[size];
+ int j = 0;
+ for(DBID id : relation.iterDBIDs()) {
+ tempdata[j] = relation.get(id).doubleValue(d + 1);
+ j += 1;
+ }
+ Arrays.sort(tempdata);
+
+ for(int b = 0; b < partitions; b++) {
+ int start = (int) (b * size / (double) partitions);
+ splitPositions[d][b] = tempdata[start];
+ }
+ // make sure that last object will be included
+ splitPositions[d][partitions] = tempdata[size - 1] + 0.000001;
+ }
+ }
+
+ /**
+ * Calculate the VA file position given the existing borders.
+ *
+ * @param id Object ID
+ * @param dv Data vector
+ * @return Vector approximation
+ */
+ public VectorApproximation calculateApproximation(DBID id, V dv) {
+ int approximation[] = new int[dv.getDimensionality()];
+ for(int d = 0; d < splitPositions.length; d++) {
+ final double val = dv.doubleValue(d + 1);
+ final int lastBorderIndex = splitPositions[d].length - 1;
+
+ // Value is below data grid
+ if(val < splitPositions[d][0]) {
+ approximation[d] = 0;
+ if(id != null) {
+ log.warning("Vector outside of VAFile grid!");
+ }
+ } // Value is above data grid
+ else if(val > splitPositions[d][lastBorderIndex]) {
+ approximation[d] = lastBorderIndex - 1;
+ if(id != null) {
+ log.warning("Vector outside of VAFile grid!");
+ }
+ } // normal case
+ else {
+ // Search grid position
+ int pos = Arrays.binarySearch(splitPositions[d], val);
+ pos = (pos >= 0) ? pos : ((-pos) - 2);
+ approximation[d] = pos;
+ }
+ }
+ return new VectorApproximation(id, approximation);
+ }
+
+ @Override
+ public long getReadOperations() {
+ return getRandomReadOnly() + getScannedPages();
+ }
+
+ /**
+ * Get the number of random read operations only.
+ *
+ * @return Random read operations.
+ */
+ public long getRandomReadOnly() {
+ return super.getReadOperations();
+ }
+
+ /**
+ * Get the number of scanned bytes.
+ *
+ * @return Numebr of scanned bytes.
+ */
+ public long getScannedPages() {
+ int vacapacity = pageSize / VectorApproximation.byteOnDisk(splitPositions.length, partitions);
+ int vasize = (int) Math.ceil((vectorApprox.size()) / (1.0 * vacapacity));
+ return vasize * scans;
+ }
+
+ @Override
+ public long getWriteOperations() {
+ return -1;
+ }
+
+ @Override
+ public void resetPageAccess() {
+ super.resetPageAccess();
+ scans = 0;
+ // FIXME: writes
+ }
+
+ @Override
+ public String getLongName() {
+ return "VA-file index";
+ }
+
+ @Override
+ public String getShortName() {
+ return "va-file";
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <D extends Distance<D>> KNNQuery<V, D> getKNNQuery(DistanceQuery<V, D> distanceQuery, Object... hints) {
+ for(Object hint : hints) {
+ if(hint == DatabaseQuery.HINT_BULK) {
+ // FIXME: support bulk?
+ return null;
+ }
+ }
+ 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;
+ }
+ // 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();
+ 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;
+ }
+ // Not supported.
+ return null;
+ }
+
+ /**
+ * Range query for this index.
+ *
+ * @author Erich Schubert
+ */
+ class VAFileRangeQuery extends AbstractRefiningIndex<V>.AbstractRangeQuery<DoubleDistance> {
+ /**
+ * LP Norm p parameter.
+ */
+ final double p;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceQuery Distance query object
+ * @param p LP norm p
+ */
+
+ public VAFileRangeQuery(DistanceQuery<V, DoubleDistance> distanceQuery, double p) {
+ super(distanceQuery);
+ this.p = p;
+ }
+
+ @Override
+ public List<DistanceResultPair<DoubleDistance>> getRangeForObject(V query, DoubleDistance range) {
+ final double eps = range.doubleValue();
+ // generate query approximation and lookup table
+ VectorApproximation queryApprox = calculateApproximation(null, query);
+
+ // Approximative distance function
+ VALPNormDistance vadist = new VALPNormDistance(p, splitPositions, query, queryApprox);
+
+ // Count a VA file scan
+ scans += 1;
+
+ List<DistanceResultPair<DoubleDistance>> result = new ArrayList<DistanceResultPair<DoubleDistance>>();
+ // Approximation step
+ for(int i = 0; i < vectorApprox.size(); i++) {
+ VectorApproximation va = vectorApprox.get(i);
+ double minDist = vadist.getMinDist(va);
+
+ if(minDist > eps) {
+ continue;
+ }
+
+ // TODO: we don't need to refine always (maxDist < eps), if we are
+ // interested in the DBID only! But this needs an API change.
+
+ // refine the next element
+ final double dist = refine(va.id, query).doubleValue();
+ if(dist <= eps) {
+ result.add(new DoubleDistanceResultPair(dist, va.id));
+ }
+ }
+ Collections.sort(result);
+ return result;
+ }
+ }
+
+ /**
+ * KNN query for this index.
+ *
+ * @author Erich Schubert
+ */
+ class VAFileKNNQuery extends AbstractRefiningIndex<V>.AbstractKNNQuery<DoubleDistance> {
+ /**
+ * LP Norm p parameter.
+ */
+ final double p;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceQuery Distance query object
+ * @param p LP norm p
+ */
+ public VAFileKNNQuery(DistanceQuery<V, DoubleDistance> distanceQuery, double p) {
+ super(distanceQuery);
+ this.p = p;
+ }
+
+ @Override
+ public KNNResult<DoubleDistance> getKNNForObject(V query, int k) {
+ // generate query approximation and lookup table
+ VectorApproximation queryApprox = calculateApproximation(null, query);
+
+ // Approximative distance function
+ VALPNormDistance vadist = new VALPNormDistance(p, splitPositions, query, queryApprox);
+
+ // Heap for the kth smallest maximum distance
+ Heap<Double> minMaxHeap = new TopBoundedHeap<Double>(k, Collections.reverseOrder());
+ double minMaxDist = Double.POSITIVE_INFINITY;
+ // Candidates with minDist <= kth maxDist
+ ArrayList<DoubleObjPair<DBID>> candidates = new ArrayList<DoubleObjPair<DBID>>(vectorApprox.size());
+
+ // Count a VA file scan
+ scans += 1;
+
+ // Approximation step
+ for(int i = 0; i < vectorApprox.size(); i++) {
+ VectorApproximation va = vectorApprox.get(i);
+ double minDist = vadist.getMinDist(va);
+ double maxDist = vadist.getMaxDist(va);
+
+ // Skip excess candidate generation:
+ if(minDist > minMaxDist) {
+ continue;
+ }
+ candidates.add(new DoubleObjPair<DBID>(minDist, va.id));
+
+ // Update candidate pruning heap
+ minMaxHeap.add(maxDist);
+ if(minMaxHeap.size() >= k) {
+ minMaxDist = minMaxHeap.peek();
+ }
+ }
+ // sort candidates by lower bound (minDist)
+ Collections.sort(candidates);
+
+ // refinement step
+ KNNHeap<DoubleDistance> result = new KNNHeap<DoubleDistance>(k);
+
+ // log.fine("candidates size " + candidates.size());
+ // retrieve accurate distances
+ for(DoubleObjPair<DBID> va : candidates) {
+ // Stop when we are sure to have all elements
+ if(result.size() >= k) {
+ double kDist = result.getKNNDistance().doubleValue();
+ if(va.first > kDist) {
+ break;
+ }
+ }
+
+ // refine the next element
+ final double dist = refine(va.second, query).doubleValue();
+ result.add(new DoubleDistanceResultPair(dist, va.second));
+ }
+ if(log.isDebuggingFinest()) {
+ log.finest("query = (" + query + ")");
+ log.finest("database: " + vectorApprox.size() + ", candidates: " + candidates.size() + ", results: " + result.size());
+ }
+
+ return result.toKNNList();
+ }
+ }
+
+ /**
+ * Index factory class
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ */
+ public static class Factory<V extends NumberVector<?, ?>> implements IndexFactory<V, VAFile<V>> {
+ /**
+ * Number of partitions to use in each dimension.
+ *
+ * <pre>
+ * -vafile.partitions 8
+ * </pre>
+ */
+ public static final OptionID PARTITIONS_ID = OptionID.getOrCreateOptionID("vafile.partitions", "Number of partitions to use in each dimension.");
+
+ /**
+ * Page size
+ */
+ int pagesize = 1;
+
+ /**
+ * Number of partitions
+ */
+ int numpart = 2;
+
+ /**
+ * Constructor.
+ *
+ * @param pagesize Page size
+ * @param numpart Number of partitions
+ */
+ public Factory(int pagesize, int numpart) {
+ super();
+ this.pagesize = pagesize;
+ this.numpart = numpart;
+ }
+
+ @Override
+ public VAFile<V> instantiate(Relation<V> relation) {
+ return new VAFile<V>(pagesize, relation, numpart);
+ }
+
+ @Override
+ public TypeInformation getInputTypeRestriction() {
+ return TypeUtil.NUMBER_VECTOR_FIELD;
+ }
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Page size
+ */
+ int pagesize = 1;
+
+ /**
+ * Number of partitions
+ */
+ int numpart = 2;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ IntParameter pagesizeP = new IntParameter(TreeIndexFactory.PAGE_SIZE_ID, new GreaterConstraint(0), 1024);
+ if(config.grab(pagesizeP)) {
+ pagesize = pagesizeP.getValue();
+ }
+ IntParameter partitionsP = new IntParameter(Factory.PARTITIONS_ID, new GreaterConstraint(2));
+ if(config.grab(partitionsP)) {
+ numpart = partitionsP.getValue();
+ }
+ }
+
+ @Override
+ protected Factory<?> makeInstance() {
+ return new Factory<NumberVector<?, ?>>(pagesize, numpart);
+ }
+ }
+ }
+}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java b/src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java new file mode 100644 index 00000000..77815c97 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java @@ -0,0 +1,169 @@ +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) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.data.NumberVector; + +/** + * Lp-Norm distance function for partially computed objects + * + * @author Erich Schubert + */ +public class VALPNormDistance { + /** + * Value of 1/p for lP norm + */ + private final double onebyp; + + /** + * Lookup table for grid cells + */ + private double[][] lookup; + + /** + * Approximation of the query vector + */ + private VectorApproximation queryApprox; + + /** + * Constructor. + * + * @param p Value of p + * @param splitPositions Split positions + * @param query Query vector + * @param queryApprox + */ + public VALPNormDistance(double p, double[][] splitPositions, NumberVector<?, ?> query, VectorApproximation queryApprox) { + super(); + this.onebyp = 1.0 / p; + this.queryApprox = queryApprox; + initializeLookupTable(splitPositions, query, p); + } + + /** + * Get the minimum distance contribution of a single dimension + * + * @param dimension Dimension + * @param vp Vector position + * @return Increment + */ + public double getPartialMinDist(int dimension, int vp) { + final int qp = queryApprox.getApproximation(dimension); + if(vp < qp) { + return lookup[dimension][vp + 1]; + } + else if(vp > qp) { + return lookup[dimension][vp]; + } + else { + return 0.0; + } + } + + /** + * Get the minimum distance to approximated vector vec + * + * @param vec Vector approximation + * @return Minimum distance + */ + public double getMinDist(VectorApproximation vec) { + final int dim = lookup.length; + double minDist = 0; + for(int d = 0; d < dim; d++) { + final int vp = vec.getApproximation(d); + minDist += getPartialMinDist(d, vp); + } + return Math.pow(minDist, onebyp); + } + + /** + * Get the maximum distance contribution of a single dimension + * + * @param dimension Dimension + * @param vp Vector position + * @return Increment + */ + public double getPartialMaxDist(int dimension, int vp) { + final int qp = queryApprox.getApproximation(dimension); + if(vp < qp) { + return lookup[dimension][vp]; + } + else if(vp > qp) { + return lookup[dimension][vp + 1]; + } + else { + return Math.max(lookup[dimension][vp], lookup[dimension][vp + 1]); + } + } + + /** + * Get the maximum distance. + * + * @param vec Approximation vector + * @return Maximum distance of the vector + */ + public double getMaxDist(VectorApproximation vec) { + final int dim = lookup.length; + double maxDist = 0; + for(int d = 0; d < dim; d++) { + final int vp = vec.getApproximation(d); + maxDist += getPartialMaxDist(d, vp); + } + return Math.pow(maxDist, onebyp); + } + + /** + * Get the maximum distance. + * + * @param dimension Dimension + * @return Maximum distance in the given dimension + */ + public double getPartialMaxMaxDist(int dimension) { + double[] data = lookup[dimension]; + double max = data[0]; + for(int i = 1; i < data.length; i++) { + max = Math.max(max, data[i]); + } + return max; + } + + /** + * Initialize the lookup table + * + * @param splitPositions Split positions + * @param query Query vector + * @param p 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]; + for(int d = 0; d < dimensions; d++) { + final double val = query.doubleValue(d + 1); + for(int i = 0; i < bordercount; i++) { + lookup[d][i] = Math.pow(splitPositions[d][i] - val, p); + } + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/vafile/VectorApproximation.java b/src/de/lmu/ifi/dbs/elki/index/vafile/VectorApproximation.java new file mode 100644 index 00000000..4b170eb8 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/vafile/VectorApproximation.java @@ -0,0 +1,103 @@ +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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team +
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version. +
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details. +
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+
+/**
+ * Object in a VA approximation.
+ *
+ * @author Thomas Bernecker
+ * @author Erich Schubert
+ */
+public class VectorApproximation {
+ /**
+ * approximation (va cell ids)
+ */
+ int[] approximation;
+
+ /**
+ * Object represented by this approximation
+ */
+ protected DBID id;
+
+ /**
+ * Constructor.
+ *
+ * @param id Object represented (may be <code>null</code> for query objects)
+ * @param approximation Approximation
+ */
+ public VectorApproximation(DBID id, int[] approximation) {
+ super();
+ this.id = id;
+ this.approximation = approximation;
+ }
+
+ /**
+ * @return the id
+ */
+ public DBID getId() {
+ return id;
+ }
+
+ /**
+ * Get the dimensionality
+ *
+ * @return Dimensionality
+ */
+ public int getDimensionality() {
+ return approximation.length;
+ }
+
+ /**
+ * Get the VA approximation
+ *
+ * @param dim Dimension
+ * @return Bin number
+ */
+ public int getApproximation(int dim) {
+ return approximation[dim];
+ }
+
+ @Override
+ public String toString() {
+ return id + " (" + Arrays.toString(approximation) + ")";
+ }
+
+ /**
+ * Computes IO costs (in bytes) needed for reading the candidates. For one
+ * object, log2(numberOfPartitions) bits have to be read per dimension.
+ *
+ * @param numberOfDimensions the number of relevant dimensions
+ * @param numberOfPartitions the number of relevant partitions
+ * @return the cost values (in bytes)
+ */
+ //nicht gleich in bytes umwandeln, sonst rundungsfehler erst nachdem *anzahl objekte
+ public static int byteOnDisk(int numberOfDimensions, int numberOfPartitions) {
+ //(partition*dimension+id) alles in Bit 32bit für 4 byte id
+ return (int) (Math.ceil(numberOfDimensions * ((Math.log(numberOfPartitions) / Math.log(2)))+32) /8);
+ }
+}
\ No newline at end of file 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 new file mode 100644 index 00000000..f38b1dca --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/vafile/package-info.java @@ -0,0 +1,27 @@ +/** + * <p>Vector Approximation File</p> + */ +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +// TODO: add projected VA files, allow different binning and projection strategies. +package de.lmu.ifi.dbs.elki.index.vafile;
\ No newline at end of file |