Example #1
0
  public Queue<List<Double>> findNeighbors(int k, List<Double> point) {

    Queue<List<Double>> pointsN = getPointsQueue(point);
    Queue<BallNode> ballsQueueQ = getBallsQueue(point);
    ballsQueueQ.add(root);

    while (!ballsQueueQ.isEmpty()) {
      BallNode ballS = ballsQueueQ.poll();
      if (pointsN.size() >= k) {
        if (ballS.distanceTo(point) > distance(pointsN.peek(), point)) {
          return pointsN;
        }
      }
      if (ballS.isLeaf()) {
        for (List<Double> p : ballS.points.getData()) {
          pointsN.add(p);
        }
        while (pointsN.size() > k) {
          pointsN.poll();
        }
      } else {
        ballsQueueQ.add(ballS.left);
        ballsQueueQ.add(ballS.right);
      }
    }
    return pointsN;
  }
 /**
  * Builds a ball tree middle out.
  *
  * @return The root node of the tree.
  * @throws Exception If there is problem building the tree.
  */
 public BallNode buildTree() throws Exception {
   m_NumNodes = m_MaxDepth = m_NumLeaves = 0;
   if (rootRadius == -1) {
     rootRadius =
         BallNode.calcRadius(
             m_InstList,
             m_Instances,
             BallNode.calcCentroidPivot(m_InstList, m_Instances),
             m_DistanceFunction);
   }
   BallNode root = buildTreeMiddleOut(0, m_Instances.numInstances() - 1);
   return root;
 }
 /**
  * Applies the middle out build procedure to the leaves of the tree. The leaf nodes should be the
  * ones that were created by createAnchorsHierarchy(). The process continues recursively for the
  * leaves created for each leaf of the given tree until for some leaf node <= m_MaxInstancesInLeaf
  * instances remain in the leaf.
  *
  * @param node The root of the tree.
  * @throws Exception If there is some problem in building the tree leaves.
  */
 protected void buildLeavesMiddleOut(BallNode node) throws Exception {
   if (node.m_Left != null && node.m_Right != null) { // if an internal node
     buildLeavesMiddleOut(node.m_Left);
     buildLeavesMiddleOut(node.m_Right);
   } else if (node.m_Left != null || node.m_Right != null) {
     throw new Exception("Invalid leaf assignment. Please check code");
   } else { // if node is a leaf
     BallNode n2 = buildTreeMiddleOut(node.m_Start, node.m_End);
     if (n2.m_Left != null && n2.m_Right != null) {
       node.m_Left = n2.m_Left;
       node.m_Right = n2.m_Right;
       buildLeavesMiddleOut(node);
       // the stopping condition in buildTreeMiddleOut will stop the recursion,
       // where it won't split a node at all, and we won't recurse here.
     } else if (n2.m_Left != null || n2.m_Right != null)
       throw new Exception("Invalid leaf assignment. Please check code");
   }
 }
  /**
   * Makes BallTreeNodes out of TempNodes.
   *
   * @param node The root TempNode
   * @param startidx The start of the portion of master index array the TempNodes are made from.
   * @param endidx The end of the portion of master index array the TempNodes are made from.
   * @param depth The depth in the tree where this root TempNode is made (needed when leaves of a
   *     tree deeper down are built middle out).
   * @return The root BallTreeNode.
   */
  protected BallNode makeBallTreeNodes(TempNode node, int startidx, int endidx, int depth) {
    BallNode ball = null;

    if (node.left != null && node.right != null) { // make an internal node
      ball = new BallNode(startidx, endidx, m_NumNodes, node.anchor, node.radius);
      m_NumNodes += 1;
      ball.m_Left =
          makeBallTreeNodes(
              node.left, startidx, startidx + node.left.points.length() - 1, depth + 1);
      ball.m_Right =
          makeBallTreeNodes(node.right, startidx + node.left.points.length(), endidx, depth + 1);
      m_MaxDepth++;
    } else { // make a leaf node
      ball = new BallNode(startidx, endidx, m_NumNodes, node.anchor, node.radius);
      m_NumNodes += 1;
      m_NumLeaves += 1;
    }
    return ball;
  }
  /**
   * Builds a ball tree middle out from the portion of the master index array given by supplied
   * start and end index.
   *
   * @param startIdx The start of the portion in master index array.
   * @param endIdx the end of the portion in master index array.
   * @return The root node of the built tree.
   * @throws Exception If there is some problem building the tree.
   */
  protected BallNode buildTreeMiddleOut(int startIdx, int endIdx) throws Exception {

    Instance pivot;
    double radius;
    Vector<TempNode> anchors;
    int numInsts = endIdx - startIdx + 1;
    int numAnchors = (int) Math.round(Math.sqrt(numInsts));

    // create anchor's hierarchy
    if (numAnchors > 1) {
      pivot = BallNode.calcCentroidPivot(startIdx, endIdx, m_InstList, m_Instances);
      radius =
          BallNode.calcRadius(startIdx, endIdx, m_InstList, m_Instances, pivot, m_DistanceFunction);
      if (numInsts <= m_MaxInstancesInLeaf
          || (rootRadius == 0
              ? true
              : radius / rootRadius
                  < m_MaxRelLeafRadius)) { // just make a leaf don't make anchors hierarchy
        BallNode node = new BallNode(startIdx, endIdx, m_NumNodes, pivot, radius);
        return node;
      }
      anchors = new Vector<TempNode>(numAnchors);
      createAnchorsHierarchy(anchors, numAnchors, startIdx, endIdx);

      BallNode node = mergeNodes(anchors, startIdx, endIdx);

      buildLeavesMiddleOut(node);

      return node;
    } // end anchors hierarchy
    else {
      BallNode node =
          new BallNode(
              startIdx,
              endIdx,
              m_NumNodes,
              (pivot = BallNode.calcCentroidPivot(startIdx, endIdx, m_InstList, m_Instances)),
              BallNode.calcRadius(
                  startIdx, endIdx, m_InstList, m_Instances, pivot, m_DistanceFunction));
      return node;
    }
  }
  /**
   * Returns an anchor point which is furthest from the mean point for a given set of points
   * (instances) (The anchor instance is chosen from the given set of points).
   *
   * @param startIdx The start index of the points for which anchor point is required.
   * @param endIdx The end index of the points for which anchor point is required.
   * @return The furthest point/instance from the mean of given set of points.
   */
  protected TempNode getFurthestFromMeanAnchor(int startIdx, int endIdx) {
    TempNode anchor = new TempNode();
    Instance centroid = BallNode.calcCentroidPivot(startIdx, endIdx, m_InstList, m_Instances);
    Instance temp;
    double tmpr;
    anchor.radius = Double.NEGATIVE_INFINITY;
    for (int i = startIdx; i <= endIdx; i++) {
      temp = m_Instances.instance(m_InstList[i]);
      tmpr = m_DistanceFunction.distance(centroid, temp);
      if (tmpr > anchor.radius) {
        anchor.idx = m_InstList[i];
        anchor.anchor = temp;
        anchor.radius = tmpr;
      }
    }

    setPoints(anchor, startIdx, endIdx, m_InstList);
    return anchor;
  }
Example #7
0
 public BallTree(Matrix points, int k) {
   root = BallNode.buildBallNode(points, k);
 }