/** * 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; } }
/** * 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; }
/** * 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; }