static int GetSplitPolicy(const TreeType& child, const size_t axis, const typename TreeType::ElemType cut) { if (child.AuxiliaryInfo().OuterBound()[axis].Hi() <= cut) return AssignToFirstTree; else if (child.AuxiliaryInfo().OuterBound()[axis].Lo() >= cut) return AssignToSecondTree; return SplitRequired; }
bool HilbertRTreeAuxiliaryInformation<TreeType, HilbertValueType>:: UpdateAuxiliaryInfo(TreeType* node) { if (node->IsLeaf()) // Should already be updated return true; TreeType* child = node->Children()[node->NumChildren() - 1]; if (hilbertValue.CompareWith(child->AuxiliaryInfo().hilbertValue()) < 0) { hilbertValue.Copy(node,child); return true; } return false; }
DiscreteHilbertValue<TreeElemType>:: DiscreteHilbertValue(const DiscreteHilbertValue& other, TreeType* tree, bool deepCopy) : localHilbertValues(NULL), ownsLocalHilbertValues(other.ownsLocalHilbertValues), numValues(other.NumValues()), valueToInsert(NULL), ownsValueToInsert(other.ownsValueToInsert) { if (deepCopy) { // Only leaf nodes own the localHilbertValues dataset. // Intermediate nodes store the pointer to the corresponding dataset. if (ownsLocalHilbertValues) localHilbertValues = new arma::Mat<HilbertElemType>( *other.LocalHilbertValues()); else localHilbertValues = NULL; // Only the root owns ownsValueToInsert. Other nodes the pointer. if (ownsValueToInsert) valueToInsert = new arma::Col<HilbertElemType>( *other.ValueToInsert()); else { assert(tree->Parent() != NULL); // Copy the pointer from the parent node. valueToInsert = const_cast<arma::Col<HilbertElemType>*> (tree->Parent()->AuxiliaryInfo().HilbertValue().ValueToInsert()); } if (tree->NumChildren() == 0) { // We have to update pointers to the localHilbertValues dataset in // intermediate nodes. TreeType* node = tree; while (node->Parent() != NULL) { if (node->Parent()->NumChildren() > 1) { const std::vector<TreeType*> parentChildren = node->AuxiliaryInfo().Children(node->Parent()); // If node is not the last child of its parent, we shouldn't copy // the localHilbertValues pointer. if (parentChildren[node->Parent()->NumChildren() - 2] == NULL) break; } node->Parent()->AuxiliaryInfo().HilbertValue().LocalHilbertValues() = localHilbertValues; node = node->Parent(); } } } else { localHilbertValues = const_cast<arma::Mat<HilbertElemType>*> (other.LocalHilbertValues()); valueToInsert = const_cast<arma::Col<HilbertElemType>*> (other.ValueToInsert()); } }
bool HilbertRTreeSplit<splitOrder>:: SplitNonLeafNode(TreeType* tree, std::vector<bool>& relevels) { // If we are splitting the root node, we need will do things differently so // that the constructor and other methods don't confuse the end user by giving // an address of another node. if (tree->Parent() == NULL) { // We actually want to copy this way. Pointers and everything. TreeType* copy = new TreeType(*tree, false); // Only the root node owns this variable. copy->AuxiliaryInfo().HilbertValue().OwnsValueToInsert() = false; copy->Parent() = tree; tree->NumChildren() = 0; tree->NullifyData(); tree->children[(tree->NumChildren())++] = copy; SplitNonLeafNode(copy, relevels); return true; } TreeType* parent = tree->Parent(); size_t iTree = 0; for (iTree = 0; parent->children[iTree] != tree; iTree++); // Try to find splitOrder cooperating siblings in order to redistribute // children among them and avoid split. size_t firstSibling, lastSibling; if (FindCooperatingSiblings(parent, iTree, firstSibling, lastSibling)) { RedistributeNodesEvenly(parent, firstSibling, lastSibling); return false; } // We can not find splitOrder cooperating siblings since they are all full. // We introduce new one instead. size_t iNewSibling = (iTree + splitOrder < parent->NumChildren() ? iTree + splitOrder : parent->NumChildren()); for (size_t i = parent->NumChildren(); i > iNewSibling ; i--) parent->children[i] = parent->children[i - 1]; parent->NumChildren()++; parent->children[iNewSibling] = new TreeType(parent); lastSibling = (iTree + splitOrder < parent->NumChildren() ? iTree + splitOrder : parent->NumChildren() - 1); firstSibling = (lastSibling > splitOrder ? lastSibling - splitOrder : 0); assert(lastSibling - firstSibling <= splitOrder); assert(firstSibling >= 0); assert(lastSibling < parent->NumChildren()); // Redistribute children among (splitOrder + 1) cooperating siblings evenly. RedistributeNodesEvenly(parent, firstSibling, lastSibling); if (parent->NumChildren() == parent->MaxNumChildren() + 1) SplitNonLeafNode(parent, relevels); return false; }
void HilbertRTreeSplit<splitOrder>:: RedistributePointsEvenly(TreeType* parent, const size_t firstSibling, const size_t lastSibling) { size_t numPoints = 0; size_t numPointsPerNode, numRestPoints; for (size_t i = firstSibling; i <= lastSibling; i++) numPoints += parent->Child(i).NumPoints(); numPointsPerNode = numPoints / (lastSibling - firstSibling + 1); numRestPoints = numPoints % (lastSibling - firstSibling + 1); std::vector<size_t> points(numPoints); // Copy children's points in order to redistribute them. size_t iPoint = 0; for (size_t i = firstSibling; i <= lastSibling; i++) { for (size_t j = 0; j < parent->Child(i).NumPoints(); j++) points[iPoint++] = parent->Child(i).Point(j); } iPoint = 0; for (size_t i = firstSibling; i <= lastSibling; i++) { // Since we redistribute points of a sibling we should recalculate the // bound. parent->Child(i).Bound().Clear(); size_t j; for (j = 0; j < numPointsPerNode; j++) { parent->Child(i).Bound() |= parent->Dataset().col(points[iPoint]); parent->Child(i).Point(j) = points[iPoint]; iPoint++; } if (numRestPoints > 0) { parent->Child(i).Bound() |= parent->Dataset().col(points[iPoint]); parent->Child(i).Point(j) = points[iPoint]; parent->Child(i).Count() = numPointsPerNode + 1; numRestPoints--; iPoint++; } else { parent->Child(i).Count() = numPointsPerNode; } parent->Child(i).numDescendants = parent->Child(i).Count(); assert(parent->Child(i).NumPoints() <= parent->Child(i).MaxLeafSize()); } // Fix the largest Hilbert values of the siblings. parent->AuxiliaryInfo().HilbertValue().RedistributeHilbertValues(parent, firstSibling, lastSibling); TreeType* root = parent; while (root != NULL) { root->AuxiliaryInfo().HilbertValue().UpdateLargestValue(root); root = root->Parent(); } }
/** * Create an auxiliary information object by copying from the other node. * * @param other The node from which the information will be copied. */ XTreeAuxiliaryInformation(const TreeType& other) : normalNodeMaxNumChildren( other.AuxiliaryInfo().NormalNodeMaxNumChildren()), splitHistory(other.AuxiliaryInfo().SplitHistory()) { };