RectangleTree:NumDescendants() optimization

This commit is contained in:
Mikhail Lozhnikov
2016-06-29 14:10:49 +03:00
parent 8b86f4136c
commit fbded362ff
7 changed files with 80 additions and 11 deletions
@@ -231,10 +231,12 @@ RedistributeNodesEvenly(const TreeType *parent,
// Since we redistribute children of a sibling we should recalculate the
// bound.
parent->Child(i).Bound().Clear();
parent->Child(i).numDescendants = 0;
for (size_t j = 0; j < numChildrenPerNode; j++)
{
parent->Child(i).Bound() |= children[iChild]->Bound();
parent->Child(i).numDescendants += children[iChild]->numDescendants;
parent->Child(i).children[j] = children[iChild];
children[iChild]->Parent() = parent->children[i];
iChild++;
@@ -242,6 +244,7 @@ RedistributeNodesEvenly(const TreeType *parent,
if (numRestChildren > 0)
{
parent->Child(i).Bound() |= children[iChild]->Bound();
parent->Child(i).numDescendants += children[iChild]->numDescendants;
parent->Child(i).children[numChildrenPerNode] = children[iChild];
children[iChild]->Parent() = parent->children[i];
parent->Child(i).NumChildren() = numChildrenPerNode + 1;
@@ -313,6 +316,8 @@ RedistributePointsEvenly(TreeType* parent,
{
parent->Child(i).Count() = numPointsPerNode;
}
parent->Child(i).numDescendants = parent->Child(i).Count();
assert(parent->Child(i).NumPoints() <=
parent->Child(i).MaxLeafSize());
}
@@ -675,6 +675,7 @@ template<typename TreeType>
void RStarTreeSplit::InsertNodeIntoTree(TreeType* destTree, TreeType* srcNode)
{
destTree->Bound() |= srcNode->Bound();
destTree->numDescendants += srcNode->numDescendants;
destTree->children[destTree->NumChildren()++] = srcNode;
}
@@ -521,6 +521,7 @@ template<typename TreeType>
void RTreeSplit::InsertNodeIntoTree(TreeType* destTree, TreeType* srcNode)
{
destTree->Bound() |= srcNode->Bound();
destTree->numDescendants += srcNode->numDescendants;
destTree->children[destTree->NumChildren()++] = srcNode;
}
@@ -76,6 +76,8 @@ class RectangleTree
//! The number of points in the dataset contained in this node (and its
//! children).
size_t count;
//! The number of descendants of this node.
size_t numDescendants;
//! The max leaf size.
size_t maxLeafSize;
//! The minimum leaf size.
@@ -37,6 +37,7 @@ RectangleTree(const MatType& data,
parent(NULL),
begin(0),
count(0),
numDescendants(0),
maxLeafSize(maxLeafSize),
minLeafSize(minLeafSize),
bound(data.n_rows),
@@ -76,6 +77,7 @@ RectangleTree(MatType&& data,
parent(NULL),
begin(0),
count(0),
numDescendants(0),
maxLeafSize(maxLeafSize),
minLeafSize(minLeafSize),
bound(data.n_rows),
@@ -114,6 +116,7 @@ RectangleTree(
parent(parentNode),
begin(0),
count(0),
numDescendants(0),
maxLeafSize(parentNode->MaxLeafSize()),
minLeafSize(parentNode->MinLeafSize()),
bound(parentNode->Bound().Dim()),
@@ -148,6 +151,7 @@ RectangleTree(
parent(other.Parent()),
begin(other.Begin()),
count(other.Count()),
numDescendants(other.numDescendants),
maxLeafSize(other.MaxLeafSize()),
minLeafSize(other.MinLeafSize()),
bound(other.bound),
@@ -269,6 +273,8 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
// Expand the bound regardless of whether it is a leaf node.
bound |= dataset->col(point);
numDescendants++;
std::vector<bool> lvls(TreeDepth());
for (size_t i = 0; i < lvls.size(); i++)
lvls[i] = true;
@@ -306,6 +312,8 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
// Expand the bound regardless of whether it is a leaf node.
bound |= dataset->col(point);
numDescendants++;
// If this is a leaf node, we stop here and add the point.
if (numChildren == 0)
{
@@ -345,6 +353,7 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
{
// Expand the bound regardless of the level.
bound |= node->Bound();
numDescendants += node->numDescendants;
if (level == TreeDepth())
{
if (!auxiliaryInfo.HandleNodeInsertion(this, node, true))
@@ -395,6 +404,12 @@ bool RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
if (!auxiliaryInfo.HandlePointDeletion(this, i))
points[i] = points[--count];
RectangleTree* tree = this;
while (tree != NULL)
{
tree->numDescendants--;
tree = tree->Parent();
}
// This function wil ensure that minFill is satisfied.
CondenseTree(dataset->col(point), lvls, true);
return true;
@@ -433,6 +448,12 @@ bool RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
if (!auxiliaryInfo.HandlePointDeletion(this, i))
points[i] = points[--count];
RectangleTree* tree = this;
while (tree != NULL)
{
tree->numDescendants--;
tree = tree->Parent();
}
// This function will ensure that minFill is satisfied.
CondenseTree(dataset->col(point), relevels, true);
return true;
@@ -471,6 +492,12 @@ bool RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
{
children[i] = children[--numChildren]; // Decrement numChildren.
}
RectangleTree* tree = this;
while (tree != NULL)
{
tree->numDescendants -= node->numDescendants;
tree = tree->Parent();
}
CondenseTree(arma::vec(), relevels, false);
return true;
}
@@ -613,17 +640,7 @@ template<typename MetricType,
inline size_t RectangleTree<MetricType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>::NumDescendants() const
{
if (numChildren == 0)
{
return count;
}
else
{
size_t n = 0;
for (size_t i = 0; i < numChildren; i++)
n += children[i]->NumDescendants();
return n;
}
return numDescendants;
}
/**
@@ -763,6 +780,13 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
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)
@@ -817,6 +841,13 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
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)
@@ -1068,6 +1099,7 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
ar & CreateNVP(begin, "begin");
ar & CreateNVP(count, "count");
ar & CreateNVP(numDescendants, "numDescendants");
ar & CreateNVP(maxLeafSize, "maxLeafSize");
ar & CreateNVP(minLeafSize, "minLeafSize");
ar & CreateNVP(bound, "bound");
@@ -840,6 +840,7 @@ template<typename TreeType>
void XTreeSplit::InsertNodeIntoTree(TreeType* destTree, TreeType* srcNode)
{
destTree->Bound() |= srcNode->Bound();
destTree->numDescendants += srcNode->numDescendants;
destTree->children[destTree->NumChildren()] = srcNode;
destTree->NumChildren()++;
}
+27
View File
@@ -316,6 +316,28 @@ int GetMinLevel(const TreeType& tree)
return min;
}
/**
* A function to check that numDescendants values are set correctly.
*/
template<typename TreeType>
size_t CheckNumDescendants(const TreeType& tree)
{
if (tree.IsLeaf())
{
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), tree.Count());
return tree.Count();
}
size_t numDescendants = 0;
for (size_t i = 0; i < tree.NumChildren(); i++)
numDescendants += CheckNumDescendants(tree.Child(i));
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), numDescendants);
return numDescendants;
}
// A test to ensure that all leaf nodes are stored on the same level of the
// tree.
BOOST_AUTO_TEST_CASE(TreeBalance)
@@ -378,6 +400,7 @@ BOOST_AUTO_TEST_CASE(PointDeletion)
CheckContainment(tree);
CheckExactContainment(tree);
CheckNumDescendants(tree);
// Single-tree search.
NeighborSearch<NearestNeighborSort, metric::LMetric<2, true>, arma::mat,
@@ -460,6 +483,7 @@ BOOST_AUTO_TEST_CASE(PointDynamicAdd)
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), 1000 + numIter);
CheckContainment(tree);
CheckExactContainment(tree);
CheckNumDescendants(tree);
// Now we will compare the output of the R Tree vs the output of a naive
// search.
@@ -510,6 +534,7 @@ BOOST_AUTO_TEST_CASE(SingleTreeTraverserTest)
CheckContainment(rTree);
CheckExactContainment(rTree);
CheckHierarchy(rTree);
CheckNumDescendants(rTree);
knn1.Search(5, neighbors1, distances1);
@@ -552,6 +577,7 @@ BOOST_AUTO_TEST_CASE(XTreeTraverserTest)
CheckContainment(xTree);
CheckExactContainment(xTree);
CheckHierarchy(xTree);
CheckNumDescendants(xTree);
knn1.Search(5, neighbors1, distances1);
@@ -592,6 +618,7 @@ BOOST_AUTO_TEST_CASE(HilbertRTreeTraverserTest)
CheckContainment(hilbertRTree);
CheckExactContainment(hilbertRTree);
CheckHierarchy(hilbertRTree);
CheckNumDescendants(hilbertRTree);
knn1.Search(5, neighbors1, distances1);