Search in sources :

Example 1 with SpatialEntry

use of de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry in project elki by elki-project.

the class RStarTreeIndex method insertAll.

/**
 * Inserts the specified objects into this index. If a bulk load mode is
 * implemented, the objects are inserted in one bulk.
 *
 * @param ids the objects to be inserted
 */
@Override
public void insertAll(DBIDs ids) {
    if (ids.isEmpty() || (ids.size() == 1)) {
        return;
    }
    // Make an example leaf
    if (canBulkLoad()) {
        List<SpatialEntry> leafs = new ArrayList<>(ids.size());
        for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
            leafs.add(createNewLeafEntry(iter));
        }
        bulkLoad(leafs);
    } else {
        for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
            insert(DBIDUtil.deref(iter));
        }
    }
    doExtraIntegrityChecks();
}
Also used : ArrayList(java.util.ArrayList) SpatialEntry(de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry) DBIDIter(de.lmu.ifi.dbs.elki.database.ids.DBIDIter)

Example 2 with SpatialEntry

use of de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry in project elki by elki-project.

the class AbstractXTree method createNewRoot.

/**
 * Creates a new root node that points to the two specified child nodes and
 * return the path to the new root.
 *
 * @param oldRoot the old root of this RTree
 * @param newNode the new split node
 * @param splitAxis the split axis used for the split causing this new root
 * @return the path to the new root node that points to the two specified
 *         child nodes
 */
protected IndexTreePath<SpatialEntry> createNewRoot(final N oldRoot, final N newNode, int splitAxis) {
    N root = createNewDirectoryNode();
    writeNode(root);
    // get split history
    SplitHistory sh = null;
    // TODO: see whether root entry is ALWAYS a directory entry .. it SHOULD!
    sh = ((XTreeDirectoryEntry) getRootEntry()).getSplitHistory();
    if (sh == null) {
        sh = new SplitHistory(getDimensionality());
    }
    sh.setDim(splitAxis);
    // switch the ids
    oldRoot.setPageID(root.getPageID());
    if (!oldRoot.isLeaf()) {
        // TODO: test whether this is neccessary
        for (int i = 0; i < oldRoot.getNumEntries(); i++) {
            N node = getNode(oldRoot.getEntry(i));
            writeNode(node);
        }
    }
    // adjust supernode id
    if (oldRoot.isSuperNode()) {
        supernodes.remove(new Long(getRootID()));
        supernodes.put(new Long(oldRoot.getPageID()), oldRoot);
    }
    root.setPageID(getRootID());
    SpatialEntry oldRootEntry = createNewDirectoryEntry(oldRoot);
    SpatialEntry newNodeEntry = createNewDirectoryEntry(newNode);
    ((SplitHistorySpatialEntry) oldRootEntry).setSplitHistory(sh);
    try {
        ((SplitHistorySpatialEntry) newNodeEntry).setSplitHistory((SplitHistory) sh.clone());
    } catch (CloneNotSupportedException e) {
        throw new RuntimeException("Clone of a split history should not throw an Exception", e);
    }
    root.addDirectoryEntry(oldRootEntry);
    root.addDirectoryEntry(newNodeEntry);
    writeNode(root);
    writeNode(oldRoot);
    writeNode(newNode);
    if (getLogger().isDebugging()) {
        getLogger().debugFine(// 
        new StringBuilder(1000).append("Create new Root: ID=").append(root.getPageID()).append("\nchild1 ").append(oldRoot).append(' ').append(// 
        new HyperBoundingBox(oldRootEntry)).append("\nchild2 ").append(newNode).append(' ').append(new HyperBoundingBox(newNodeEntry)));
    }
    // the root entry still needs to be set to the new root node's MBR
    return new IndexTreePath<>(null, getRootEntry(), 0);
}
Also used : IndexTreePath(de.lmu.ifi.dbs.elki.index.tree.IndexTreePath) ModifiableHyperBoundingBox(de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox) HyperBoundingBox(de.lmu.ifi.dbs.elki.data.HyperBoundingBox) SplitHistory(de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.xtree.util.SplitHistory) SpatialEntry(de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry)

Example 3 with SpatialEntry

use of de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry in project elki by elki-project.

the class AbstractXTree method toString.

/**
 * Returns a string representation of this XTree.
 *
 * @return a string representation of this XTree
 */
@Override
public String toString() {
    long dirNodes = 0;
    long superNodes = 0;
    long leafNodes = 0;
    long objects = 0;
    long maxSuperCapacity = -1;
    long minSuperCapacity = Long.MAX_VALUE;
    BigInteger totalCapacity = BigInteger.ZERO;
    int levels = 0;
    N node = getRoot();
    while (!node.isLeaf()) {
        if (node.getNumEntries() > 0) {
            SpatialEntry entry = node.getEntry(0);
            node = getNode(entry);
            levels++;
        }
    }
    BreadthFirstEnumeration<N, SpatialEntry> enumeration = new BreadthFirstEnumeration<>(this, getRootPath());
    while (enumeration.hasNext()) {
        IndexTreePath<SpatialEntry> indexPath = enumeration.next();
        SpatialEntry entry = indexPath.getEntry();
        if (entry instanceof LeafEntry) {
            objects++;
        } else {
            node = getNode(entry);
            if (node.isLeaf()) {
                leafNodes++;
            } else {
                if (node.isSuperNode()) {
                    superNodes++;
                    if (node.getCapacity() > maxSuperCapacity) {
                        maxSuperCapacity = node.getCapacity();
                    }
                    if (node.getCapacity() < minSuperCapacity) {
                        minSuperCapacity = node.getCapacity();
                    }
                } else {
                    dirNodes++;
                }
            }
            totalCapacity = totalCapacity.add(BigInteger.valueOf(node.getCapacity()));
        }
    }
    assert objects == num_elements : "objects=" + objects + ", size=" + num_elements;
    return // 
    new StringBuilder(10000).append(getClass().getName()).append(" has ").append((levels + 1)).append(" levels.\n").append(dirNodes).append(" Directory Nodes (max = ").append(dirCapacity - 1).append(", min = ").append(dirMinimum).append(// 
    ")\n").append(superNodes).append(" Supernodes (max = ").append(maxSuperCapacity - 1).append(", min = ").append(minSuperCapacity - 1).append(// 
    ")\n").append(leafNodes).append(" Data Nodes (max = ").append(leafCapacity - 1).append(", min = ").append(leafMinimum).append(// 
    ")\n").append(objects).append(' ').append(dimensionality).append(// 
    "-dim. points in the tree \n").append("min_fanout = ").append(settings.min_fanout).append(", max_overlap = ").append(settings.max_overlap).append((settings.overlap_type == Overlap.DATA_OVERLAP ? " data overlap" : " volume overlap")).append(// 
    ", \n").append("Storage Quota ").append(BigInteger.valueOf(objects + dirNodes + superNodes + leafNodes).multiply(BigInteger.valueOf(100)).divide(totalCapacity).toString()).append(// 
    "%\n").toString();
}
Also used : BreadthFirstEnumeration(de.lmu.ifi.dbs.elki.index.tree.BreadthFirstEnumeration) SpatialPointLeafEntry(de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialPointLeafEntry) LeafEntry(de.lmu.ifi.dbs.elki.index.tree.LeafEntry) BigInteger(java.math.BigInteger) SpatialEntry(de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry)

Example 4 with SpatialEntry

use of de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry in project elki by elki-project.

the class AbstractXTree method calculateOverlapIncrease.

/**
 * Celebrated by the Profiler as a lot faster than the previous variant: that
 * used to calculate all overlaps of the old MBR and the new MBR with all
 * other MBRs. Now: The overlaps are only calculated if necessary:<br>
 * <ul>
 * <li>the new MBR does not have to be tested on overlaps if the current
 * dimension has never changed</li>
 * <li>the old MBR does not have to be tested if the new MBR shows no overlaps
 * </li>
 * </ul>
 * Furthermore tries to avoid rounding errors arising from large value ranges
 * and / or larger dimensions. <br>
 * <br>
 * However: hardly any difference in real runtime!
 *
 * @param node Node
 * @param ei current entry
 * @param testMBR extended MBR of <code>ei</code>
 * @return
 */
private double calculateOverlapIncrease(N node, SpatialEntry ei, SpatialComparable testMBR) {
    ModifiableHyperBoundingBox eiMBR = new ModifiableHyperBoundingBox(ei);
    ModifiableHyperBoundingBox testMBRModifiable = new ModifiableHyperBoundingBox(testMBR);
    double[] lb = eiMBR.getMinRef();
    double[] ub = eiMBR.getMaxRef();
    double[] lbT = testMBRModifiable.getMinRef();
    double[] ubT = testMBRModifiable.getMaxRef();
    // next tested lower bounds
    double[] lbNext = null;
    // and upper bounds
    double[] ubNext = null;
    boolean[] dimensionChanged = new boolean[lb.length];
    for (int i = 0; i < dimensionChanged.length; i++) {
        if (lb[i] > lbT[i] || ub[i] < ubT[i]) {
            dimensionChanged[i] = true;
        }
    }
    double multiOverlapInc = 0, multiOverlapMult = 1, mOOld = 1, mONew = 1;
    // dimensional overlap
    double ol, olT;
    for (int j = 0; j < node.getNumEntries(); j++) {
        SpatialEntry ej = node.getEntry(j);
        if (getPageID(ej) != getPageID(ei)) {
            // is constant for a unchanged dimension
            multiOverlapMult = 1;
            // overlap for old MBR on changed dimensions
            mOOld = 1;
            // overlap on new MBR on changed dimension
            mONew = 1;
            ModifiableHyperBoundingBox ejMBR = new ModifiableHyperBoundingBox(ej);
            lbNext = ejMBR.getMinRef();
            ubNext = ejMBR.getMaxRef();
            for (int i = 0; i < dimensionChanged.length; i++) {
                if (dimensionChanged[i]) {
                    if (lbT[i] > ubNext[i] || ubT[i] < lbNext[i]) {
                        multiOverlapMult = 0;
                        // old MBR has no overlap either
                        break;
                    }
                    olT = (ubT[i] > ubNext[i] ? ubNext[i] : ubT[i]) - (lbT[i] < lbNext[i] ? lbNext[i] : lbT[i]);
                    mONew *= olT;
                    if (mOOld != 0) {
                        // else: no use in calculating overlap
                        ol = (ub[i] > ubNext[i] ? ubNext[i] : ub[i]) - (lb[i] < lbNext[i] ? lbNext[i] : lb[i]);
                        if (ol < 0) {
                            ol = 0;
                        }
                        mOOld *= ol;
                    }
                } else {
                    if (lb[i] > ubNext[i] || ub[i] < lbNext[i]) {
                        multiOverlapMult = 0;
                        break;
                    }
                    ol = (ub[i] > ubNext[i] ? ubNext[i] : ub[i]) - (lb[i] < lbNext[i] ? lbNext[i] : lb[i]);
                    multiOverlapMult *= ol;
                }
            }
            if (multiOverlapMult != 0) {
                multiOverlapInc += multiOverlapMult * (mONew - mOOld);
            }
        }
    }
    return multiOverlapInc;
}
Also used : ModifiableHyperBoundingBox(de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox) SpatialEntry(de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry)

Example 5 with SpatialEntry

use of de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry in project elki by elki-project.

the class AbstractXTreeNode method readExternal.

/**
 * Reads the id of this node, the numEntries and the entries array from the
 * specified stream. If the {@link #supernode} field is set, <code>this</code>
 * cannot be contained in <code>in</code>. Such a node has to be manually
 * filled using {@link #readSuperNode(ObjectInput, AbstractXTree)}.
 *
 * @param in the stream to read data from in order to restore the object
 * @throws java.io.IOException if I/O errors occur
 * @throws ClassNotFoundException If the class for an object being restored
 *         cannot be found.
 */
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    setPageID(in.readInt());
    isLeaf = in.readBoolean();
    supernode = in.readBoolean();
    numEntries = in.readInt();
    final int capacity = in.readInt();
    if (supernode) {
        // this node is a supernode and is yet to be filled
        capacity_to_be_filled = capacity;
        return;
    }
    // entries = (E[]) java.lang.reflect.Array.newInstance(eclass, capacity);
    if (isLeaf()) {
        entries = (Entry[]) new SpatialPointLeafEntry[capacity];
    } else {
        entries = (Entry[]) new XTreeDirectoryEntry[capacity];
    }
    for (int i = 0; i < numEntries; i++) {
        SpatialEntry s = isLeaf() ? new SpatialPointLeafEntry() : new XTreeDirectoryEntry();
        s.readExternal(in);
        entries[i] = s;
    }
}
Also used : SpatialPointLeafEntry(de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialPointLeafEntry) Entry(de.lmu.ifi.dbs.elki.index.tree.Entry) SpatialDirectoryEntry(de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialDirectoryEntry) SpatialEntry(de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry) SpatialPointLeafEntry(de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialPointLeafEntry) SpatialEntry(de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry)

Aggregations

SpatialEntry (de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry)21 ModifiableHyperBoundingBox (de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox)5 ArrayList (java.util.ArrayList)5 HyperBoundingBox (de.lmu.ifi.dbs.elki.data.HyperBoundingBox)4 DBIDIter (de.lmu.ifi.dbs.elki.database.ids.DBIDIter)4 LeafEntry (de.lmu.ifi.dbs.elki.index.tree.LeafEntry)4 SpatialPointLeafEntry (de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialPointLeafEntry)4 SpatialDirectoryEntry (de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialDirectoryEntry)3 Database (de.lmu.ifi.dbs.elki.database.Database)2 SplitHistory (de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.xtree.util.SplitHistory)2 MeanVariance (de.lmu.ifi.dbs.elki.math.MeanVariance)2 DoubleVector (de.lmu.ifi.dbs.elki.data.DoubleVector)1 NumberVector (de.lmu.ifi.dbs.elki.data.NumberVector)1 SpatialComparable (de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable)1 StaticArrayDatabase (de.lmu.ifi.dbs.elki.database.StaticArrayDatabase)1 DBID (de.lmu.ifi.dbs.elki.database.ids.DBID)1 Relation (de.lmu.ifi.dbs.elki.database.relation.Relation)1 BreadthFirstEnumeration (de.lmu.ifi.dbs.elki.index.tree.BreadthFirstEnumeration)1 Entry (de.lmu.ifi.dbs.elki.index.tree.Entry)1 IndexTreePath (de.lmu.ifi.dbs.elki.index.tree.IndexTreePath)1