[mlpack] 289/324: Point deletion bug fix.
Barak A. Pearlmutter
barak+git at cs.nuim.ie
Sun Aug 17 08:22:19 UTC 2014
This is an automated email from the git hooks/post-receive script.
bap pushed a commit to branch svn-trunk
in repository mlpack.
commit 15c50239784edfba98f0b739c713e1804d0a8766
Author: andrewmw94 <andrewmw94 at 9d5b8971-822b-0410-80eb-d18c1038ef23>
Date: Tue Aug 5 16:50:52 2014 +0000
Point deletion bug fix.
git-svn-id: http://svn.cc.gatech.edu/fastlab/mlpack/trunk@16973 9d5b8971-822b-0410-80eb-d18c1038ef23
---
.../tree/rectangle_tree/r_star_tree_split_impl.hpp | 3 +
.../tree/rectangle_tree/rectangle_tree_impl.hpp | 49 ++++++++----
src/mlpack/tests/rectangle_tree_test.cpp | 88 +++++++++++++++++++++-
3 files changed, 122 insertions(+), 18 deletions(-)
diff --git a/src/mlpack/core/tree/rectangle_tree/r_star_tree_split_impl.hpp b/src/mlpack/core/tree/rectangle_tree/r_star_tree_split_impl.hpp
index 26d6e1d..75d1e34 100644
--- a/src/mlpack/core/tree/rectangle_tree/r_star_tree_split_impl.hpp
+++ b/src/mlpack/core/tree/rectangle_tree/r_star_tree_split_impl.hpp
@@ -88,6 +88,7 @@ void RStarTreeSplit<DescentType, StatisticType, MatType>::SplitLeafNode(
// }
return;
}
+
int bestOverlapIndexOnBestAxis = 0;
int bestAreaIndexOnBestAxis = 0;
@@ -261,6 +262,7 @@ bool RStarTreeSplit<DescentType, StatisticType, MatType>::SplitNonLeafNode(
return true;
}
+
// If we haven't yet reinserted on this level, we try doing so now.
if(relevels[tree->TreeDepth()]) {
relevels[tree->TreeDepth()] = false;
@@ -319,6 +321,7 @@ bool RStarTreeSplit<DescentType, StatisticType, MatType>::SplitNonLeafNode(
return false;
}
+
int bestOverlapIndexOnBestAxis = 0;
int bestAreaIndexOnBestAxis = 0;
diff --git a/src/mlpack/core/tree/rectangle_tree/rectangle_tree_impl.hpp b/src/mlpack/core/tree/rectangle_tree/rectangle_tree_impl.hpp
index 44d95d8..b344876 100644
--- a/src/mlpack/core/tree/rectangle_tree/rectangle_tree_impl.hpp
+++ b/src/mlpack/core/tree/rectangle_tree/rectangle_tree_impl.hpp
@@ -523,16 +523,23 @@ void RectangleTree<SplitType, DescentType, StatisticType, MatType>::CondenseTree
{
// 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++) {
+
+for (size_t i = 0; i < parent->NumChildren(); i++) {
if (parent->Children()[i] == this) {
parent->Children()[i] = parent->Children()[--parent->NumChildren()]; // decrement numChildren
- parent->ShrinkBoundForBound(bound); // We want to do this before reinserting points.
-
- // Reinsert the points at the root node.
+
+ // We find the root and shrink bounds at the same time.
+ bool stillShrinking = true;
RectangleTree<SplitType, DescentType, StatisticType, MatType>* root = parent;
- while (root->Parent() != NULL)
+ 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);
}
@@ -546,19 +553,25 @@ void RectangleTree<SplitType, DescentType, StatisticType, MatType>::CondenseTree
// Control should never reach here.
assert(true == 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) {
parent->Children()[j] = parent->Children()[--parent->NumChildren()]; // decrement numChildren
- parent->ShrinkBoundForBound(bound); // We want to do this before reinserting nodes.
-
size_t level = TreeDepth();
- // Reinsert the nodes at the root node.
- RectangleTree<SplitType, DescentType, StatisticType, MatType>* root = this;
- while (root->Parent() != NULL)
+
+ // We find the root and shrink bounds at the same time.
+ bool stillShrinking = true;
+ RectangleTree<SplitType, DescentType, StatisticType, MatType>* root = parent;
+ while (root->Parent() != NULL) {
+ if(stillShrinking)
+ stillShrinking = root->ShrinkBoundForBound(bound);
root = root->Parent();
- for (size_t i = 0; i < numChildren; i++)
+ }
+ 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);
parent->CondenseTree(point, relevels, usePoint); // This will check the MinFill of the parent.
@@ -579,6 +592,7 @@ void RectangleTree<SplitType, DescentType, StatisticType, MatType>::CondenseTree
}
count = child->Count();
child->SoftDelete();
+ return;
}
}
@@ -629,20 +643,23 @@ bool RectangleTree<SplitType, DescentType, StatisticType, MatType>::ShrinkBoundF
}
}
} else {
- for (size_t i = 0; i < point.n_elem; i++) {
+ for (size_t i = 0; i < bound.Dim(); i++) {
if (bound[i].Lo() == point[i]) {
double min = DBL_MAX;
- double max = -1 * DBL_MAX;
for (size_t j = 0; j < numChildren; j++) {
if (children[j]->Bound()[i].Lo() < min)
min = children[j]->Bound()[i].Lo();
- if (children[j]->Bound()[i].Hi() > max)
- max = children[j]->Bound()[i].Hi();
}
if (bound[i].Lo() < min) {
shrunk = true;
bound[i].Lo() = min;
}
+ } else if(bound[i].Hi() == point[i]) {
+ double max = -1 * DBL_MAX;
+ for (size_t j = 0; j < numChildren; j++) {
+ if (children[j]->Bound()[i].Hi() > max)
+ max = children[j]->Bound()[i].Hi();
+ }
if (bound[i].Hi() > max) {
shrunk = true;
bound[i].Hi() = max;
diff --git a/src/mlpack/tests/rectangle_tree_test.cpp b/src/mlpack/tests/rectangle_tree_test.cpp
index 1755864..e8a3223 100644
--- a/src/mlpack/tests/rectangle_tree_test.cpp
+++ b/src/mlpack/tests/rectangle_tree_test.cpp
@@ -143,6 +143,87 @@ void checkContainment(const RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeu
return;
}
+/**
+ * A function to check that containment is as tight as possible.
+ */
+void checkExactContainment(const RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat>& tree) {
+ if(tree.NumChildren() == 0) {
+ for(size_t i = 0; i < tree.Bound().Dim(); i++) {
+ double min = DBL_MAX;
+ double max = -1.0 * DBL_MAX;
+ for(size_t j = 0; j < tree.Count(); j++) {
+ if(tree.LocalDataset().col(j)[i] < min)
+ min = tree.LocalDataset().col(j)[i];
+ if(tree.LocalDataset().col(j)[i] > max)
+ max = tree.LocalDataset().col(j)[i];
+ }
+ BOOST_REQUIRE_EQUAL(max, tree.Bound()[i].Hi());
+ BOOST_REQUIRE_EQUAL(min, tree.Bound()[i].Lo());
+ }
+ } else {
+ for(size_t i = 0; i < tree.Bound().Dim(); i++) {
+ double min = DBL_MAX;
+ double max = -1.0 * DBL_MAX;
+ for(size_t j = 0; j < tree.NumChildren(); j++) {
+ if(tree.Child(j).Bound()[i].Lo() < min)
+ min = tree.Child(j).Bound()[i].Lo();
+ if(tree.Child(j).Bound()[i].Hi() > max)
+ max = tree.Child(j).Bound()[i].Hi();
+ }
+
+ if(max != tree.Bound()[i].Hi())
+ std::cout<<"error max"<<std::endl<<std::endl<<std::endl<<tree.ToString()<<std::endl<<std::endl;
+ if(min != tree.Bound()[i].Lo())
+ std::cout<<"error min"<<std::endl;
+ BOOST_REQUIRE_EQUAL(max, tree.Bound()[i].Hi());
+ BOOST_REQUIRE_EQUAL(min, tree.Bound()[i].Lo());
+ }
+ for(size_t i = 0; i < tree.NumChildren(); i++)
+ checkExactContainment(tree.Child(i));
+ }
+}
+
+/**
+ * A function to check that containment is as tight as possible.
+ */
+void checkExactContainment(const RectangleTree<tree::RStarTreeSplit<tree::RStarTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
+ tree::RStarTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat>& tree) {
+ if(tree.NumChildren() == 0) {
+ for(size_t i = 0; i < tree.Bound().Dim(); i++) {
+ double min = DBL_MAX;
+ double max = -1.0 * DBL_MAX;
+ for(size_t j = 0; j < tree.Count(); j++) {
+ if(tree.LocalDataset().col(j)[i] < min)
+ min = tree.LocalDataset().col(j)[i];
+ if(tree.LocalDataset().col(j)[i] > max)
+ max = tree.LocalDataset().col(j)[i];
+ }
+ BOOST_REQUIRE_EQUAL(max, tree.Bound()[i].Hi());
+ BOOST_REQUIRE_EQUAL(min, tree.Bound()[i].Lo());
+ }
+ } else {
+ for(size_t i = 0; i < tree.Bound().Dim(); i++) {
+ double min = DBL_MAX;
+ double max = -1.0 * DBL_MAX;
+ for(size_t j = 0; j < tree.NumChildren(); j++) {
+ if(tree.Child(j).Bound()[i].Lo() < min)
+ min = tree.Child(j).Bound()[i].Lo();
+ if(tree.Child(j).Bound()[i].Hi() > max)
+ max = tree.Child(j).Bound()[i].Hi();
+ }
+ BOOST_REQUIRE_EQUAL(max, tree.Bound()[i].Hi());
+ BOOST_REQUIRE_EQUAL(min, tree.Bound()[i].Lo());
+ }
+ for(size_t i = 0; i < tree.NumChildren(); i++)
+ checkExactContainment(tree.Child(i));
+ }
+}
+
// Test to see if the bounds of the tree are correct. (Cover all bounds and points
// beneath this node of the tree).
BOOST_AUTO_TEST_CASE(RectangleTreeContainmentTest) {
@@ -154,6 +235,7 @@ BOOST_AUTO_TEST_CASE(RectangleTreeContainmentTest) {
NeighborSearchStat<NearestNeighborSort>,
arma::mat> tree(dataset, 20, 6, 5, 2, 0);
checkContainment(tree);
+ checkExactContainment(tree);
}
/**
@@ -308,7 +390,7 @@ BOOST_AUTO_TEST_CASE(PointDeletion) {
for (int i = 0; i < numIter; i++) {
tree.DeletePoint(999 - i);
- }
+ }
// Do a few sanity checks. Ensure each point is unique, the tree has the correct
// number of points, the tree has legal containment, and the tree's data is in sync.
@@ -330,6 +412,7 @@ BOOST_AUTO_TEST_CASE(PointDeletion) {
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), 1000 - numIter);
checkContainment(tree);
checkSync(tree);
+ checkExactContainment(tree);
mlpack::neighbor::NeighborSearch<NearestNeighborSort, metric::LMetric<2, true>,
RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
@@ -407,6 +490,7 @@ BOOST_AUTO_TEST_CASE(PointDynamicAdd) {
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), 1000 + numIter);
checkContainment(tree);
checkSync(tree);
+ checkExactContainment(tree);
// Now we will compare the output of the R Tree vs the output of a naive search.
arma::Mat<size_t> neighbors1;
@@ -510,7 +594,7 @@ BOOST_AUTO_TEST_CASE(SingleTreeTraverserTest) {
BOOST_REQUIRE_EQUAL(RTree.NumDescendants(), 1000);
checkSync(RTree);
checkContainment(RTree);
-
+ checkExactContainment(RTree);
allknn1.Search(5, neighbors1, distances1);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/mlpack.git
More information about the debian-science-commits
mailing list