Search in sources :

Example 6 with DoubleIntPair

use of de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair in project elki by elki-project.

the class GreeneSplit method split.

@Override
public <E extends SpatialComparable, A> long[] 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;
                }
            }
        }
        if (worst > 0) {
            // 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 = 0; 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;
                }
            }
        } else {
            // All objects are identical!
            final int half = (num + 1) >> 1;
            // Put the first half into second node
            return BitsUtil.ones(half);
        }
    }
    // 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 long[] assignment = BitsUtil.zero(num);
    final int half = (num + 1) >> 1;
    // Put the first half into second node
    for (int i = 0; i < half; i++) {
        BitsUtil.setI(assignment, 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) {
            BitsUtil.setI(assignment, data[half].second);
        }
    }
    return assignment;
}
Also used : DoubleIntPair(de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair) ModifiableHyperBoundingBox(de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox)

Example 7 with DoubleIntPair

use of de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair in project elki by elki-project.

the class ApproximativeLeastOverlapInsertionStrategy method choose.

@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<>(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;
}
Also used : TopBoundedHeap(de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TopBoundedHeap) SpatialComparable(de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable) DoubleIntPair(de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair) HyperBoundingBox(de.lmu.ifi.dbs.elki.data.HyperBoundingBox)

Example 8 with DoubleIntPair

use of de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair in project elki by elki-project.

the class MkMaxTree method preInsert.

/**
 * Adapts the knn distances before insertion of entry q.
 *
 * @param q the entry to be inserted
 * @param nodeEntry the entry representing the root of the current subtree
 * @param knns_q the knns of q
 */
private void preInsert(MkMaxEntry q, MkMaxEntry nodeEntry, KNNHeap knns_q) {
    if (LOG.isDebugging()) {
        LOG.debugFine("preInsert " + q + " - " + nodeEntry + "\n");
    }
    double knnDist_q = knns_q.getKNNDistance();
    MkMaxTreeNode<O> node = getNode(nodeEntry);
    double knnDist_node = 0.;
    // leaf node
    if (node.isLeaf()) {
        for (int i = 0; i < node.getNumEntries(); i++) {
            MkMaxEntry p = node.getEntry(i);
            double dist_pq = distance(p.getRoutingObjectID(), q.getRoutingObjectID());
            // ==> p becomes a knn-candidate
            if (dist_pq <= knnDist_q) {
                knns_q.insert(dist_pq, p.getRoutingObjectID());
                if (knns_q.size() >= getKmax()) {
                    knnDist_q = knns_q.getKNNDistance();
                    q.setKnnDistance(knnDist_q);
                }
            }
            // q becomes knn of p
            if (dist_pq <= p.getKnnDistance()) {
                KNNList knns_p = knnq.getKNNForDBID(p.getRoutingObjectID(), getKmax() - 1);
                if (knns_p.size() + 1 < getKmax()) {
                    p.setKnnDistance(Double.NaN);
                } else {
                    double knnDist_p = Math.max(dist_pq, knns_p.getKNNDistance());
                    p.setKnnDistance(knnDist_p);
                }
            }
            knnDist_node = Math.max(knnDist_node, p.getKnnDistance());
        }
    } else // directory node
    {
        List<DoubleIntPair> entries = getSortedEntries(node, q.getRoutingObjectID());
        for (DoubleIntPair distEntry : entries) {
            MkMaxEntry dirEntry = node.getEntry(distEntry.second);
            double entry_knnDist = dirEntry.getKnnDistance();
            if (distEntry.second < entry_knnDist || distEntry.second < knnDist_q) {
                preInsert(q, dirEntry, knns_q);
                knnDist_q = knns_q.getKNNDistance();
            }
            knnDist_node = Math.max(knnDist_node, dirEntry.getKnnDistance());
        }
    }
    if (LOG.isDebugging()) {
        LOG.debugFine(nodeEntry + "set knn dist " + knnDist_node);
    }
    nodeEntry.setKnnDistance(knnDist_node);
}
Also used : KNNList(de.lmu.ifi.dbs.elki.database.ids.KNNList) DoubleIntPair(de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair)

Aggregations

DoubleIntPair (de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair)8 HyperBoundingBox (de.lmu.ifi.dbs.elki.data.HyperBoundingBox)2 ModifiableHyperBoundingBox (de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox)2 SpatialComparable (de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable)2 TopBoundedHeap (de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TopBoundedHeap)2 ArrayList (java.util.ArrayList)2 DBIDArrayIter (de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter)1 KNNList (de.lmu.ifi.dbs.elki.database.ids.KNNList)1 Heap (de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap)1