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 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 . */ import java.util.ArrayList; 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.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.KNNIndex; import de.lmu.ifi.dbs.elki.index.RKNNIndex; import de.lmu.ifi.dbs.elki.index.RangeIndex; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTreeUnified; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MetricalIndexKNNQuery; 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.KNNHeap; import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages; public class MkMaxTreeIndex> extends MkMaxTree implements RangeIndex, KNNIndex, RKNNIndex { private Relation relation; /** * Constructor. * * @param relation Relation * @param pagefile Page file * @param distanceQuery Distance query * @param distanceFunction Distance function * @param k_max Maximum value for k */ public MkMaxTreeIndex(Relation relation, PageFile> pagefile, DistanceQuery distanceQuery, DistanceFunction distanceFunction, int k_max) { super(pagefile, distanceQuery, distanceFunction, k_max); this.relation = relation; this.initialize(); } /** * @return a new MkMaxLeafEntry representing the specified data object */ protected MkMaxLeafEntry createNewLeafEntry(DBID id, @SuppressWarnings("unused") O object, D parentDistance) { KNNHeap knnList = new KNNHeap(getKmax() - 1); doKNNQuery(id, knnList); D knnDistance = knnList.getMaximumDistance(); return new MkMaxLeafEntry(id, parentDistance, knnDistance); } @Override public void insert(DBID id) { insert(createNewLeafEntry(id, relation.get(id), getDistanceFactory().undefinedDistance()), false); } @Override public void insertAll(DBIDs ids) { List> objs = new ArrayList>(ids.size()); for(DBID id : ids) { final O object = relation.get(id); objs.add(createNewLeafEntry(id, object, getDistanceFactory().undefinedDistance())); } insertAll(objs); } /** * Throws an UnsupportedOperationException since deletion of objects is not * yet supported by an M-Tree. * * @throws UnsupportedOperationException thrown, since deletions aren't * implemented yet. */ @SuppressWarnings("unused") @Override public final boolean delete(DBID id) { throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET); } /** * Throws an UnsupportedOperationException since deletion of objects is not * yet supported by an M-Tree. * * @throws UnsupportedOperationException thrown, since deletions aren't * implemented yet. */ @SuppressWarnings("unused") @Override public void deleteAll(DBIDs ids) { throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET); } @SuppressWarnings("unchecked") @Override public > KNNQuery getKNNQuery(DistanceQuery distanceQuery, Object... hints) { // Query on the relation we index if(distanceQuery.getRelation() != relation) { return null; } DistanceFunction distanceFunction = distanceQuery.getDistanceFunction(); if(!this.distanceFunction.equals(distanceFunction)) { if(getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); } return null; } // Bulk is not yet supported for(Object hint : hints) { if(hint == DatabaseQuery.HINT_BULK) { return null; } } AbstractMTree idx = (AbstractMTree) this; DistanceQuery dq = distanceFunction.instantiate(relation); return new MetricalIndexKNNQuery(idx, dq); } @SuppressWarnings("unchecked") @Override public > RangeQuery getRangeQuery(DistanceQuery distanceQuery, Object... hints) { // Query on the relation we index if(distanceQuery.getRelation() != relation) { return null; } DistanceFunction distanceFunction = distanceQuery.getDistanceFunction(); if(!this.distanceFunction.equals(distanceFunction)) { if(getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); } return null; } // Bulk is not yet supported for(Object hint : hints) { if(hint == DatabaseQuery.HINT_BULK) { return null; } } AbstractMTree idx = (AbstractMTree) this; DistanceQuery dq = distanceFunction.instantiate(relation); return new MetricalIndexRangeQuery(idx, dq); } @SuppressWarnings("unchecked") @Override public > RKNNQuery getRKNNQuery(DistanceQuery distanceQuery, Object... hints) { DistanceFunction distanceFunction = distanceQuery.getDistanceFunction(); if(!this.getDistanceFunction().equals(distanceFunction)) { if(getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); } return null; } // Bulk is not yet supported for(Object hint : hints) { if(hint == DatabaseQuery.HINT_BULK) { return null; } } AbstractMkTreeUnified idx = (AbstractMkTreeUnified) this; DistanceQuery dq = distanceFunction.instantiate(relation); return new MkTreeRKNNQuery(idx, dq); } @Override public String getLongName() { return "MkMax-Tree"; } @Override public String getShortName() { return "mkmaxtree"; } }