RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType>:: RectangleTree( const RectangleTree& other, const bool deepCopy) : maxNumChildren(other.MaxNumChildren()), minNumChildren(other.MinNumChildren()), numChildren(other.NumChildren()), children(maxNumChildren + 1), parent(other.Parent()), begin(other.Begin()), count(other.Count()), maxLeafSize(other.MaxLeafSize()), minLeafSize(other.MinLeafSize()), bound(other.bound), splitHistory(other.SplitHistory()), parentDistance(other.ParentDistance()), dataset(new MatType(*other.dataset)), ownsDataset(true), points(other.Points()), localDataset(NULL) { if (deepCopy) { if (numChildren > 0) { for (size_t i = 0; i < numChildren; i++) { children[i] = new RectangleTree(*(other.Children()[i])); } } else { localDataset = new MatType(other.LocalDataset()); } } else { children = other.Children(); arma::mat& otherData = const_cast<arma::mat&>(other.LocalDataset()); localDataset = &otherData; } }
size_t RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType>::TreeDepth() const { int n = 1; RectangleTree* currentNode = const_cast<RectangleTree*> (this); while (!currentNode->IsLeaf()) { currentNode = currentNode->Children()[0]; n++; } return n; }
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType>:: CondenseTree(const arma::vec& point, std::vector<bool>& relevels, const bool usePoint) { // First delete the node if we need to. There's no point in shrinking the // bound first. if (IsLeaf() && count < minLeafSize && parent != NULL) { // We can't delete the root node. for (size_t i = 0; i < parent->NumChildren(); i++) { if (parent->Children()[i] == this) { // Decrement numChildren. parent->Children()[i] = parent->Children()[--parent->NumChildren()]; // We find the root and shrink bounds at the same time. bool stillShrinking = true; RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType>* root = parent; while (root->Parent() != NULL) { if (stillShrinking) stillShrinking = root->ShrinkBoundForBound(bound); root = root->Parent(); } if (stillShrinking) stillShrinking = root->ShrinkBoundForBound(bound); // Reinsert the points at the root node. for (size_t j = 0; j < count; j++) root->InsertPoint(points[j], relevels); // This will check the minFill of the parent. parent->CondenseTree(point, relevels, usePoint); // Now it should be safe to delete this node. SoftDelete(); return; } } // Control should never reach here. assert(false); } else if (!IsLeaf() && numChildren < minNumChildren) { if (parent != NULL) { // The normal case. We need to be careful with the root. for (size_t j = 0; j < parent->NumChildren(); j++) { if (parent->Children()[j] == this) { // Decrement numChildren. parent->Children()[j] = parent->Children()[--parent->NumChildren()]; size_t level = TreeDepth(); // We find the root and shrink bounds at the same time. bool stillShrinking = true; RectangleTree* root = parent; while (root->Parent() != NULL) { if (stillShrinking) stillShrinking = root->ShrinkBoundForBound(bound); root = root->Parent(); } if (stillShrinking) stillShrinking = root->ShrinkBoundForBound(bound); // Reinsert the nodes at the root node. for (size_t i = 0; i < numChildren; i++) root->InsertNode(children[i], level, relevels); // This will check the minFill of the point. parent->CondenseTree(point, relevels, usePoint); // Now it should be safe to delete this node. SoftDelete(); return; } } } else if (numChildren == 1) { // If there are multiple children, we can't do anything to the root. RectangleTree* child = children[0]; for (size_t i = 0; i < child->NumChildren(); i++) { children[i] = child->Children()[i]; children[i]->Parent() = this; } numChildren = child->NumChildren(); for (size_t i = 0; i < child->Count(); i++) { // In case the tree has a height of two. points[i] = child->Points()[i]; localDataset->col(i) = child->LocalDataset().col(i); } count = child->Count(); maxNumChildren = child->MaxNumChildren(); // Required for the X tree. child->SoftDelete(); return; } } // If we didn't delete it, shrink the bound if we need to. if (usePoint && ShrinkBoundForPoint(point) && parent != NULL) parent->CondenseTree(point, relevels, usePoint); else if (!usePoint && ShrinkBoundForBound(bound) && parent != NULL) parent->CondenseTree(point, relevels, usePoint); }