Package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split

Source Code of de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.RTreeLinearSplit$Parameterizer

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;
    }
  }
}
TOP

Related Classes of de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.RTreeLinearSplit$Parameterizer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.