RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType, AuxiliaryInformationType>:: RectangleTree(MatType&& data, const size_t maxLeafSize, const size_t minLeafSize, const size_t maxNumChildren, const size_t minNumChildren, const size_t firstDataIndex) : maxNumChildren(maxNumChildren), minNumChildren(minNumChildren), numChildren(0), children(maxNumChildren + 1), // Add one to make splitting the node simpler. parent(NULL), begin(0), count(0), numDescendants(0), maxLeafSize(maxLeafSize), minLeafSize(minLeafSize), bound(data.n_rows), parentDistance(0), dataset(new MatType(std::move(data))), ownsDataset(true), points(maxLeafSize + 1), // Add one to make splitting the node simpler. auxiliaryInfo(this) { stat = StatisticType(*this); // For now, just insert the points in order. RectangleTree* root = this; for (size_t i = firstDataIndex; i < dataset->n_cols; i++) root->InsertPoint(i); }
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType>:: RectangleTree(const MatType& data, const size_t maxLeafSize, const size_t minLeafSize, const size_t maxNumChildren, const size_t minNumChildren, const size_t firstDataIndex) : maxNumChildren(maxNumChildren), minNumChildren(minNumChildren), numChildren(0), children(maxNumChildren + 1), // Add one to make splitting the node simpler. parent(NULL), begin(0), count(0), maxLeafSize(maxLeafSize), minLeafSize(minLeafSize), bound(data.n_rows), splitHistory(bound.Dim()), parentDistance(0), dataset(new MatType(data)), ownsDataset(true), points(maxLeafSize + 1), // Add one to make splitting the node simpler. localDataset(new MatType(arma::zeros<MatType>(data.n_rows, maxLeafSize + 1))) { stat = StatisticType(*this); // For now, just insert the points in order. RectangleTree* root = this; for (size_t i = firstDataIndex; i < data.n_cols; i++) root->InsertPoint(i); }
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType, AuxiliaryInformationType>:: 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. if (!auxiliaryInfo.HandleNodeRemoval(parent, i)) { parent->children[i] = parent->children[--parent->NumChildren()]; } // 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); root = parent; while (root != NULL) { root->numDescendants -= numDescendants; root = root->Parent(); } stillShrinking = true; root = parent; while (root->Parent() != NULL) { if (stillShrinking) stillShrinking = root->AuxiliaryInfo().UpdateAuxiliaryInfo(root); root = root->Parent(); } if (stillShrinking) stillShrinking = root->AuxiliaryInfo().UpdateAuxiliaryInfo(root); // 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. if (!auxiliaryInfo.HandleNodeRemoval(parent,j)) { 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); root = parent; while (root != NULL) { root->numDescendants -= numDescendants; root = root->Parent(); } stillShrinking = true; root = parent; while (root->Parent() != NULL) { if (stillShrinking) stillShrinking = root->AuxiliaryInfo().UpdateAuxiliaryInfo(root); root = root->Parent(); } if (stillShrinking) stillShrinking = root->AuxiliaryInfo().UpdateAuxiliaryInfo(root); // 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]; // Required for the X tree. if (child->NumChildren() > maxNumChildren) { maxNumChildren = child->MaxNumChildren(); children.resize(maxNumChildren+1); } 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->Point(i); } auxiliaryInfo = child->AuxiliaryInfo(); count = child->Count(); child->SoftDelete(); return; } } // If we didn't delete it, shrink the bound if we need to. if (usePoint && (ShrinkBoundForPoint(point) || auxiliaryInfo.UpdateAuxiliaryInfo(this)) && parent != NULL) parent->CondenseTree(point, relevels, usePoint); else if (!usePoint && (ShrinkBoundForBound(bound) || auxiliaryInfo.UpdateAuxiliaryInfo(this)) && parent != NULL) parent->CondenseTree(point, relevels, usePoint); }