[mlpack] 191/324: point deletion. bug fix. more detailed test.
Barak A. Pearlmutter
barak+git at cs.nuim.ie
Sun Aug 17 08:22:09 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 1314d5f1e4cbbf29a2e90ced5137124be9ba05b0
Author: andrewmw94 <andrewmw94 at 9d5b8971-822b-0410-80eb-d18c1038ef23>
Date: Wed Jul 16 21:07:26 2014 +0000
point deletion. bug fix. more detailed test.
git-svn-id: http://svn.cc.gatech.edu/fastlab/mlpack/trunk@16833 9d5b8971-822b-0410-80eb-d18c1038ef23
---
.../core/tree/rectangle_tree/r_tree_split_impl.hpp | 396 ++++++++++-----------
.../core/tree/rectangle_tree/rectangle_tree.hpp | 2 +-
.../tree/rectangle_tree/rectangle_tree_impl.hpp | 84 +++--
src/mlpack/tests/rectangle_tree_test.cpp | 201 ++++++-----
4 files changed, 346 insertions(+), 337 deletions(-)
diff --git a/src/mlpack/core/tree/rectangle_tree/r_tree_split_impl.hpp b/src/mlpack/core/tree/rectangle_tree/r_tree_split_impl.hpp
index fc04839..2e43bd4 100644
--- a/src/mlpack/core/tree/rectangle_tree/r_tree_split_impl.hpp
+++ b/src/mlpack/core/tree/rectangle_tree/r_tree_split_impl.hpp
@@ -8,11 +8,12 @@
#define __MLPACK_CORE_TREE_RECTANGLE_TREE_R_TREE_SPLIT_IMPL_HPP
#include "r_tree_split.hpp"
+#include "rectangle_tree.hpp"
#include <mlpack/core/math/range.hpp>
namespace mlpack {
namespace tree {
-
+
/**
* We call GetPointSeeds to get the two points which will be the initial points in the new nodes
* We then call AssignPointDestNode to assign the remaining points to the two new nodes.
@@ -20,16 +21,16 @@ namespace tree {
* if necessary.
*/
template<typename DescentType,
- typename StatisticType,
- typename MatType>
+typename StatisticType,
+typename MatType>
void RTreeSplit<DescentType, StatisticType, MatType>::SplitLeafNode(
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* tree)
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* tree)
{
// 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) {
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* copy =
- new RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>(*tree); // We actually want to copy this way. Pointers and everything.
+ if (tree->Parent() == NULL) {
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* copy =
+ new RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>(*tree); // We actually want to copy this way. Pointers and everything.
copy->Parent() = tree;
tree->Count() = 0;
tree->NullifyData();
@@ -38,50 +39,50 @@ void RTreeSplit<DescentType, StatisticType, MatType>::SplitLeafNode(
RTreeSplit<DescentType, StatisticType, MatType>::SplitLeafNode(copy);
return;
}
- assert(tree->Parent()->NumChildren() < tree->Parent()->MaxNumChildren());
-
+ assert(tree->Parent()->NumChildren() < tree->Parent()->MaxNumChildren());
+
// Use the quadratic split method from: Guttman "R-Trees: A Dynamic Index Structure for
// Spatial Searching" It is simplified since we don't handle rectangles, only points.
// We assume that the tree uses Euclidean Distance.
int i = 0;
int j = 0;
GetPointSeeds(*tree, &i, &j);
-
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType> *treeOne = new
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>(tree->Parent());
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType> *treeTwo = new
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>(tree->Parent());
-
+
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType> *treeOne = new
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>(tree->Parent());
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType> *treeTwo = new
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>(tree->Parent());
+
// This will assign the ith and jth point appropriately.
AssignPointDestNode(tree, treeOne, treeTwo, i, j);
-
+
//Remove this node and insert treeOne and treeTwo
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* par = tree->Parent();
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* par = tree->Parent();
int index = 0;
- for(int i = 0; i < par->NumChildren(); i++) {
- if(par->Child(i) == tree) {
+ for (int i = 0; i < par->NumChildren(); i++) {
+ if (par->Child(i) == tree) {
index = i;
break;
}
}
par->Child(index) = treeOne;
par->Child(par->NumChildren()++) = treeTwo;
-
+
// we only add one at a time, so we should only need to test for equality
// just in case, we use an assert.
assert(par->NumChildren() <= par->MaxNumChildren());
- if(par->NumChildren() == par->MaxNumChildren()) {
+ if (par->NumChildren() == par->MaxNumChildren()) {
SplitNonLeafNode(par);
}
-
+
assert(treeOne->Parent()->NumChildren() < treeOne->MaxNumChildren());
assert(treeOne->Parent()->NumChildren() >= treeOne->MinNumChildren());
assert(treeTwo->Parent()->NumChildren() < treeTwo->MaxNumChildren());
assert(treeTwo->Parent()->NumChildren() >= treeTwo->MinNumChildren());
-
+
// We need to delete this carefully since references to points are used.
tree->SoftDelete();
-
+
return;
}
@@ -93,16 +94,16 @@ void RTreeSplit<DescentType, StatisticType, MatType>::SplitLeafNode(
* higher up the tree because they were already updated if necessary.
*/
template<typename DescentType,
- typename StatisticType,
- typename MatType>
+typename StatisticType,
+typename MatType>
bool RTreeSplit<DescentType, StatisticType, MatType>::SplitNonLeafNode(
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* tree)
-{
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* tree)
+{
// 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) {
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* copy =
- new RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>(*tree); // We actually want to copy this way. Pointers and everything.
+ if (tree->Parent() == NULL) {
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* copy =
+ new RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>(*tree); // We actually want to copy this way. Pointers and everything.
copy->Parent() = tree;
tree->NumChildren() = 0;
tree->NullifyData();
@@ -114,25 +115,22 @@ bool RTreeSplit<DescentType, StatisticType, MatType>::SplitNonLeafNode(
int i = 0;
int j = 0;
GetBoundSeeds(*tree, &i, &j);
-
- if(i == j)
- std::cout << i << ", " << j << "; " << tree->NumChildren() << std::endl;
assert(i != j);
-
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* treeOne = new
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>(tree->Parent());
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* treeTwo = new
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>(tree->Parent());
+
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* treeOne = new
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>(tree->Parent());
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* treeTwo = new
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>(tree->Parent());
// This will assign the ith and jth rectangles appropriately.
AssignNodeDestNode(tree, treeOne, treeTwo, i, j);
//Remove this node and insert treeOne and treeTwo
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* par = tree->Parent();
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* par = tree->Parent();
int index = -1;
- for(int i = 0; i < par->NumChildren(); i++) {
- if(par->Child(i) == tree) {
+ for (int i = 0; i < par->NumChildren(); i++) {
+ if (par->Child(i) == tree) {
index = i;
break;
}
@@ -140,38 +138,38 @@ bool RTreeSplit<DescentType, StatisticType, MatType>::SplitNonLeafNode(
assert(index != -1);
par->Child(index) = treeOne;
par->Child(par->NumChildren()++) = treeTwo;
-
- for(int i = 0; i < par->NumChildren(); i++) {
- if(par->Child(i) == tree) {
+
+ for (int i = 0; i < par->NumChildren(); i++) {
+ if (par->Child(i) == tree) {
assert(par->Child(i) != tree);
}
}
-
+
// we only add one at a time, so should only need to test for equality
// just in case, we use an assert.
assert(par->NumChildren() <= par->MaxNumChildren());
- if(par->NumChildren() == par->MaxNumChildren()) {
+ if (par->NumChildren() == par->MaxNumChildren()) {
SplitNonLeafNode(par);
}
-
+
// We have to update the children of each of these new nodes so that they record the
// correct parent.
- for(int i = 0; i < treeOne->NumChildren(); i++) {
+ for (int i = 0; i < treeOne->NumChildren(); i++) {
treeOne->Child(i)->Parent() = treeOne;
}
- for(int i = 0; i < treeTwo->NumChildren(); i++) {
+ for (int i = 0; i < treeTwo->NumChildren(); i++) {
treeTwo->Child(i)->Parent() = treeTwo;
}
-
+
assert(treeOne->NumChildren() < treeOne->MaxNumChildren());
assert(treeTwo->NumChildren() < treeTwo->MaxNumChildren());
- assert(treeOne->Parent()->NumChildren() < treeOne->MaxNumChildren());
+ assert(treeOne->Parent()->NumChildren() < treeOne->MaxNumChildren());
// Because we now have pointers to the information stored under this tree,
// we need to delete this node carefully.
tree->SoftDelete(); //currently does nothing but leak memory.
-
+
return false;
}
@@ -180,12 +178,12 @@ bool RTreeSplit<DescentType, StatisticType, MatType>::SplitNonLeafNode(
* The indices of these points will be stored in iRet and jRet.
*/
template<typename DescentType,
- typename StatisticType,
- typename MatType>
+typename StatisticType,
+typename MatType>
void RTreeSplit<DescentType, StatisticType, MatType>::GetPointSeeds(
- const RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>& tree,
- int* iRet,
- int* jRet)
+ const RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>& tree,
+ int* iRet,
+ int* jRet)
{
// Here we want to find the pair of points that it is worst to place in the same
// node. Because we are just using points, we will simply choose the two that would
@@ -193,16 +191,16 @@ void RTreeSplit<DescentType, StatisticType, MatType>::GetPointSeeds(
double worstPairScore = -1.0;
int worstI = 0;
int worstJ = 0;
- for(int i = 0; i < tree.Count(); i++) {
- for(int j = i+1; j < tree.Count(); j++) {
+ for (int i = 0; i < tree.Count(); i++) {
+ for (int j = i + 1; j < tree.Count(); j++) {
double score = 1.0;
- for(int k = 0; k < tree.Bound().Dim(); k++) {
- score *= std::abs(tree.LocalDataset().at(k, i) - tree.LocalDataset().at(k, j)); // Points (in the dataset) are stored by column, but this function takes (row, col).
+ for (int k = 0; k < tree.Bound().Dim(); k++) {
+ score *= std::abs(tree.LocalDataset().at(k, i) - tree.LocalDataset().at(k, j)); // Points (in the dataset) are stored by column, but this function takes (row, col).
}
- if(score > worstPairScore) {
- worstPairScore = score;
- worstI = i;
- worstJ = j;
+ if (score > worstPairScore) {
+ worstPairScore = score;
+ worstI = i;
+ worstJ = j;
}
}
}
@@ -217,27 +215,27 @@ void RTreeSplit<DescentType, StatisticType, MatType>::GetPointSeeds(
* The indices of the bounds will be stored in iRet and jRet.
*/
template<typename DescentType,
- typename StatisticType,
- typename MatType>
+typename StatisticType,
+typename MatType>
void RTreeSplit<DescentType, StatisticType, MatType>::GetBoundSeeds(
- const RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>& tree,
- int* iRet,
- int* jRet)
+ const RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>& tree,
+ int* iRet,
+ int* jRet)
{
double worstPairScore = -1.0;
int worstI = 0;
int worstJ = 0;
- for(int i = 0; i < tree.NumChildren(); i++) {
- for(int j = i+1; j < tree.NumChildren(); j++) {
+ for (int i = 0; i < tree.NumChildren(); i++) {
+ for (int j = i + 1; j < tree.NumChildren(); j++) {
double score = 1.0;
- for(int k = 0; k < tree.Bound().Dim(); k++) {
- score *= std::max(tree.Child(i)->Bound()[k].Hi(), tree.Child(j)->Bound()[k].Hi()) -
- std::min(tree.Child(i)->Bound()[k].Lo(), tree.Child(j)->Bound()[k].Lo());
+ for (int k = 0; k < tree.Bound().Dim(); k++) {
+ score *= std::max(tree.Child(i)->Bound()[k].Hi(), tree.Child(j)->Bound()[k].Hi()) -
+ std::min(tree.Child(i)->Bound()[k].Lo(), tree.Child(j)->Bound()[k].Lo());
}
- if(score > worstPairScore) {
- worstPairScore = score;
- worstI = i;
- worstJ = j;
+ if (score > worstPairScore) {
+ worstPairScore = score;
+ worstI = i;
+ worstJ = j;
}
}
}
@@ -248,18 +246,18 @@ void RTreeSplit<DescentType, StatisticType, MatType>::GetBoundSeeds(
}
template<typename DescentType,
- typename StatisticType,
- typename MatType>
+typename StatisticType,
+typename MatType>
void RTreeSplit<DescentType, StatisticType, MatType>::AssignPointDestNode(
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* oldTree,
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* treeOne,
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* treeTwo,
- const int intI,
- const int intJ)
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* oldTree,
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* treeOne,
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* treeTwo,
+ const int intI,
+ const int intJ)
{
-
+
int end = oldTree->Count();
-
+
assert(end > 1); // If this isn't true, the tree is really weird.
// Restart the point counts since we are going to move them.
@@ -269,17 +267,21 @@ void RTreeSplit<DescentType, StatisticType, MatType>::AssignPointDestNode(
treeOne->InsertPoint(oldTree->Points()[intI]);
treeTwo->InsertPoint(oldTree->Points()[intJ]);
-
+
// If intJ is the last point in the tree, we need to switch the order so that we remove the correct points.
- if(intI > intJ) {
+ if (intI > intJ) {
oldTree->Points()[intI] = oldTree->Points()[--end]; // decrement end
+ oldTree->LocalDataset()[intI] = oldTree->LocalDataset()[end];
oldTree->Points()[intJ] = oldTree->Points()[--end]; // decrement end
+ oldTree->LocalDataset()[intJ] = oldTree->LocalDataset()[end];
} else {
oldTree->Points()[intJ] = oldTree->Points()[--end]; // decrement end
+ oldTree->LocalDataset()[intJ] = oldTree->LocalDataset()[end];
oldTree->Points()[intI] = oldTree->Points()[--end]; // decrement end
+ oldTree->LocalDataset()[intI] = oldTree->LocalDataset()[end];
}
-
-
+
+
int numAssignedOne = 1;
int numAssignedTwo = 1;
@@ -287,77 +289,76 @@ void RTreeSplit<DescentType, StatisticType, MatType>::AssignPointDestNode(
// increase of volume when added to one of the rectangles. We then add it to that
// rectangle. We stop when we run out of points or when all of the remaining points
// need to be assigned to the same rectangle to satisfy the minimum fill requirement.
-
+
// The below is safe because if end decreases and the right hand side of the second part of the conjunction changes
// on the same iteration, we added the point to the node with fewer points anyways.
- while(end > 0 && end > oldTree->MinLeafSize() - std::min(numAssignedOne, numAssignedTwo)) {
+ while (end > 0 && end > oldTree->MinLeafSize() - std::min(numAssignedOne, numAssignedTwo)) {
int bestIndex = 0;
double bestScore = DBL_MAX;
int bestRect = 1;
// Calculate the increase in volume for assigning this point to each rectangle.
-
+
// First, calculate the starting volume.
double volOne = 1.0;
double volTwo = 1.0;
- for(int i = 0; i < oldTree->Bound().Dim(); i++) {
+ for (int i = 0; i < oldTree->Bound().Dim(); i++) {
volOne *= treeOne->Bound()[i].Width();
volTwo *= treeTwo->Bound()[i].Width();
}
// Find the point that, when assigned to one of the two new rectangles, minimizes the increase
// in volume.
- for(int index = 0; index < end; index++) {
+ for (int index = 0; index < end; index++) {
double newVolOne = 1.0;
double newVolTwo = 1.0;
- for(int i = 0; i < oldTree->Bound().Dim(); i++) {
- double c = oldTree->LocalDataset().col(index)[i];
- newVolOne *= treeOne->Bound()[i].Contains(c) ? treeOne->Bound()[i].Width() :
- (c < treeOne->Bound()[i].Lo() ? (treeOne->Bound()[i].Hi() - c) : (c - treeOne->Bound()[i].Lo()));
- newVolTwo *= treeTwo->Bound()[i].Contains(c) ? treeTwo->Bound()[i].Width() :
- (c < treeTwo->Bound()[i].Lo() ? (treeTwo->Bound()[i].Hi() - c) : (c - treeTwo->Bound()[i].Lo()));
+ for (int i = 0; i < oldTree->Bound().Dim(); i++) {
+ double c = oldTree->LocalDataset().col(index)[i];
+ newVolOne *= treeOne->Bound()[i].Contains(c) ? treeOne->Bound()[i].Width() :
+ (c < treeOne->Bound()[i].Lo() ? (treeOne->Bound()[i].Hi() - c) : (c - treeOne->Bound()[i].Lo()));
+ newVolTwo *= treeTwo->Bound()[i].Contains(c) ? treeTwo->Bound()[i].Width() :
+ (c < treeTwo->Bound()[i].Lo() ? (treeTwo->Bound()[i].Hi() - c) : (c - treeTwo->Bound()[i].Lo()));
}
-
+
// Choose the rectangle that requires the lesser increase in volume.
- if((newVolOne - volOne) < (newVolTwo - volTwo)) {
- if(newVolOne - volOne < bestScore) {
- bestScore = newVolOne - volOne;
- bestIndex = index;
- bestRect = 1;
- }
+ if ((newVolOne - volOne) < (newVolTwo - volTwo)) {
+ if (newVolOne - volOne < bestScore) {
+ bestScore = newVolOne - volOne;
+ bestIndex = index;
+ bestRect = 1;
+ }
} else {
- if(newVolTwo - volTwo < bestScore) {
- bestScore = newVolTwo - volTwo;
- bestIndex = index;
- bestRect = 2;
- }
+ if (newVolTwo - volTwo < bestScore) {
+ bestScore = newVolTwo - volTwo;
+ bestIndex = index;
+ bestRect = 2;
+ }
}
}
// Assign the point that causes the least increase in volume
// to the appropriate rectangle.
- if(bestRect == 1) {
+ if (bestRect == 1) {
treeOne->InsertPoint(oldTree->Points()[bestIndex]);
numAssignedOne++;
- }
- else {
+ } else {
treeTwo->InsertPoint(oldTree->Points()[bestIndex]);
- numAssignedTwo++;
+ numAssignedTwo++;
}
oldTree->Points()[bestIndex] = oldTree->Points()[--end]; // decrement end.
oldTree->LocalDataset().col(bestIndex) = oldTree->LocalDataset().col(end);
}
-
+
// See if we need to satisfy the minimum fill.
- if(end > 0) {
- if(numAssignedOne < numAssignedTwo) {
- for(int i = 0; i < end; i++) {
+ if (end > 0) {
+ if (numAssignedOne < numAssignedTwo) {
+ for (int i = 0; i < end; i++) {
treeOne->InsertPoint(oldTree->Points()[i]);
}
} else {
- for(int i = 0; i < end; i++) {
+ for (int i = 0; i < end; i++) {
treeTwo->InsertPoint(oldTree->Points()[i]);
}
}
@@ -365,32 +366,32 @@ void RTreeSplit<DescentType, StatisticType, MatType>::AssignPointDestNode(
}
template<typename DescentType,
- typename StatisticType,
- typename MatType>
+typename StatisticType,
+typename MatType>
void RTreeSplit<DescentType, StatisticType, MatType>::AssignNodeDestNode(
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* oldTree,
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* treeOne,
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* treeTwo,
- const int intI,
- const int intJ)
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* oldTree,
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* treeOne,
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* treeTwo,
+ const int intI,
+ const int intJ)
{
-
+
int end = oldTree->NumChildren();
assert(end > 1); // If this isn't true, the tree is really weird.
assert(intI != intJ);
-
- for(int i = 0; i < oldTree->NumChildren(); i++) {
- for(int j = i+1; j < oldTree->NumChildren(); j++) {
+
+ for (int i = 0; i < oldTree->NumChildren(); i++) {
+ for (int j = i + 1; j < oldTree->NumChildren(); j++) {
assert(oldTree->Child(i) != oldTree->Child(j));
}
}
-
+
insertNodeIntoTree(treeOne, oldTree->Child(intI));
insertNodeIntoTree(treeTwo, oldTree->Child(intJ));
-
+
// If intJ is the last node in the tree, we need to switch the order so that we remove the correct nodes.
- if(intI > intJ) {
+ if (intI > intJ) {
oldTree->Child(intI) = oldTree->Child(--end); // decrement end
oldTree->Child(intJ) = oldTree->Child(--end); // decrement end
} else {
@@ -400,29 +401,29 @@ void RTreeSplit<DescentType, StatisticType, MatType>::AssignNodeDestNode(
assert(treeOne->NumChildren() == 1);
assert(treeTwo->NumChildren() == 1);
-
- for(int i = 0; i < end; i++) {
- for(int j = i+1; j < end; j++) {
+
+ for (int i = 0; i < end; i++) {
+ for (int j = i + 1; j < end; j++) {
assert(oldTree->Child(i) != oldTree->Child(j));
}
}
-
- for(int i = 0; i < end; i++) {
- assert(oldTree->Child(i) != treeOne->Child(0));
+
+ for (int i = 0; i < end; i++) {
+ assert(oldTree->Child(i) != treeOne->Child(0));
}
-
- for(int i = 0; i < end; i++) {
- assert(oldTree->Child(i) != treeTwo->Child(0));
+
+ for (int i = 0; i < end; i++) {
+ assert(oldTree->Child(i) != treeTwo->Child(0));
}
-
-
+
+
int numAssignTreeOne = 1;
int numAssignTreeTwo = 1;
// In each iteration, we go through all of the nodes and find the one that causes the least
// increase of volume when added to one of the two new rectangles. We then add it to that
// rectangle.
- while(end > 0 && end > oldTree->MinNumChildren() - std::min(numAssignTreeOne, numAssignTreeTwo)) {
+ while (end > 0 && end > oldTree->MinNumChildren() - std::min(numAssignTreeOne, numAssignTreeTwo)) {
int bestIndex = 0;
double bestScore = DBL_MAX;
int bestRect = 0;
@@ -430,94 +431,93 @@ void RTreeSplit<DescentType, StatisticType, MatType>::AssignNodeDestNode(
// Calculate the increase in volume for assigning this node to each of the new rectangles.
double volOne = 1.0;
double volTwo = 1.0;
- for(int i = 0; i < oldTree->Bound().Dim(); i++) {
+ for (int i = 0; i < oldTree->Bound().Dim(); i++) {
volOne *= treeOne->Bound()[i].Width();
volTwo *= treeTwo->Bound()[i].Width();
}
- for(int index = 0; index < end; index++) {
+ for (int index = 0; index < end; index++) {
double newVolOne = 1.0;
double newVolTwo = 1.0;
- for(int i = 0; i < oldTree->Bound().Dim(); i++) {
- // For each of the new rectangles, find the width in this dimension if we add the rectangle at index to
- // the new rectangle.
- math::Range range = oldTree->Child(index)->Bound()[i];
- newVolOne *= treeOne->Bound()[i].Contains(range) ? treeOne->Bound()[i].Width() :
- (range.Contains(treeOne->Bound()[i]) ? range.Width() : (range.Lo() < treeOne->Bound()[i].Lo() ? (treeOne->Bound()[i].Hi() - range.Lo()) :
- (range.Hi() - treeOne->Bound()[i].Lo())));
- newVolTwo *= treeTwo->Bound()[i].Contains(range) ? treeTwo->Bound()[i].Width() :
- (range.Contains(treeTwo->Bound()[i]) ? range.Width() : (range.Lo() < treeTwo->Bound()[i].Lo() ? (treeTwo->Bound()[i].Hi() - range.Lo()) :
- (range.Hi() - treeTwo->Bound()[i].Lo())));
+ for (int i = 0; i < oldTree->Bound().Dim(); i++) {
+ // For each of the new rectangles, find the width in this dimension if we add the rectangle at index to
+ // the new rectangle.
+ math::Range range = oldTree->Child(index)->Bound()[i];
+ newVolOne *= treeOne->Bound()[i].Contains(range) ? treeOne->Bound()[i].Width() :
+ (range.Contains(treeOne->Bound()[i]) ? range.Width() : (range.Lo() < treeOne->Bound()[i].Lo() ? (treeOne->Bound()[i].Hi() - range.Lo()) :
+ (range.Hi() - treeOne->Bound()[i].Lo())));
+ newVolTwo *= treeTwo->Bound()[i].Contains(range) ? treeTwo->Bound()[i].Width() :
+ (range.Contains(treeTwo->Bound()[i]) ? range.Width() : (range.Lo() < treeTwo->Bound()[i].Lo() ? (treeTwo->Bound()[i].Hi() - range.Lo()) :
+ (range.Hi() - treeTwo->Bound()[i].Lo())));
}
-
+
// Choose the rectangle that requires the lesser increase in volume.
- if((newVolOne - volOne) < (newVolTwo - volTwo)) {
- if(newVolOne - volOne < bestScore) {
- bestScore = newVolOne - volOne;
- bestIndex = index;
- bestRect = 1;
- }
+ if ((newVolOne - volOne) < (newVolTwo - volTwo)) {
+ if (newVolOne - volOne < bestScore) {
+ bestScore = newVolOne - volOne;
+ bestIndex = index;
+ bestRect = 1;
+ }
} else {
- if(newVolTwo - volTwo < bestScore) {
- bestScore = newVolTwo - volTwo;
- bestIndex = index;
- bestRect = 2;
- }
+ if (newVolTwo - volTwo < bestScore) {
+ bestScore = newVolTwo - volTwo;
+ bestIndex = index;
+ bestRect = 2;
+ }
}
}
// Assign the rectangle that causes the least increase in volume
// to the appropriate rectangle.
- if(bestRect == 1) {
+ if (bestRect == 1) {
insertNodeIntoTree(treeOne, oldTree->Child(bestIndex));
- numAssignTreeOne++;
- }
- else {
+ numAssignTreeOne++;
+ } else {
insertNodeIntoTree(treeTwo, oldTree->Child(bestIndex));
- numAssignTreeTwo++;
+ numAssignTreeTwo++;
}
oldTree->Child(bestIndex) = oldTree->Child(--end); // Decrement end.
}
// See if we need to satisfy the minimum fill.
- if(end > 0) {
- if(numAssignTreeOne < numAssignTreeTwo) {
- for(int i = 0; i < end; i++) {
+ if (end > 0) {
+ if (numAssignTreeOne < numAssignTreeTwo) {
+ for (int i = 0; i < end; i++) {
insertNodeIntoTree(treeOne, oldTree->Child(i));
- numAssignTreeOne++;
+ numAssignTreeOne++;
}
} else {
- for(int i = 0; i < end; i++) {
+ for (int i = 0; i < end; i++) {
insertNodeIntoTree(treeTwo, oldTree->Child(i));
- numAssignTreeTwo++;
+ numAssignTreeTwo++;
}
}
}
-
- for(int i = 0; i < treeOne->NumChildren(); i++) {
- for(int j = i+1; j < treeOne->NumChildren(); j++) {
+
+ for (int i = 0; i < treeOne->NumChildren(); i++) {
+ for (int j = i + 1; j < treeOne->NumChildren(); j++) {
assert(treeOne->Child(i) != treeOne->Child(j));
}
}
- for(int i = 0; i < treeTwo->NumChildren(); i++) {
- for(int j = i+1; j < treeTwo->NumChildren(); j++) {
+ for (int i = 0; i < treeTwo->NumChildren(); i++) {
+ for (int j = i + 1; j < treeTwo->NumChildren(); j++) {
assert(treeTwo->Child(i) != treeTwo->Child(j));
}
}
assert(treeOne->NumChildren() == numAssignTreeOne);
assert(treeTwo->NumChildren() == numAssignTreeTwo);
- assert(numAssignTreeOne+numAssignTreeTwo == 5);
+ assert(numAssignTreeOne + numAssignTreeTwo == 5);
}
/**
- * Insert a node into another node. Expanding the bounds and updating the numberOfChildren.
- */
+ * Insert a node into another node. Expanding the bounds and updating the numberOfChildren.
+ */
template<typename DescentType,
- typename StatisticType,
- typename MatType>
+typename StatisticType,
+typename MatType>
void RTreeSplit<DescentType, StatisticType, MatType>::insertNodeIntoTree(
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* destTree,
- RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* srcNode)
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* destTree,
+ RectangleTree<RTreeSplit<DescentType, StatisticType, MatType>, DescentType, StatisticType, MatType>* srcNode)
{
destTree->Bound() |= srcNode->Bound();
destTree->Child(destTree->NumChildren()++) = srcNode;
diff --git a/src/mlpack/core/tree/rectangle_tree/rectangle_tree.hpp b/src/mlpack/core/tree/rectangle_tree/rectangle_tree.hpp
index 56f6a5e..f3dea79 100644
--- a/src/mlpack/core/tree/rectangle_tree/rectangle_tree.hpp
+++ b/src/mlpack/core/tree/rectangle_tree/rectangle_tree.hpp
@@ -115,7 +115,7 @@ class RectangleTree
*
* @param parentNode The parent of the node that is being constructed.
*/
- RectangleTree(RectangleTree<SplitType, DescentType, StatisticType, MatType>* parentNode);
+ explicit RectangleTree(RectangleTree<SplitType, DescentType, StatisticType, MatType>* parentNode);
//TODO implement the oldFromNew stuff if applicable.
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 adf1b89..67cebf3 100644
--- a/src/mlpack/core/tree/rectangle_tree/rectangle_tree_impl.hpp
+++ b/src/mlpack/core/tree/rectangle_tree/rectangle_tree_impl.hpp
@@ -147,8 +147,8 @@ InsertPoint(const size_t point)
// If this is a leaf node, we stop here and add the point.
if (numChildren == 0) {
- points[count++] = point;
localDataset->col(count) = dataset.col(point);
+ points[count++] = point;
SplitNode();
return;
}
@@ -174,7 +174,6 @@ DeletePoint(const size_t point)
if (points[i] == point) {
localDataset->col(i) = localDataset->col(--count); // decrement count
points[i] = points[count];
- std::cout << count << std::endl;
CondenseTree(dataset.col(point)); // This function will ensure that minFill is satisfied.
return true;
}
@@ -380,6 +379,7 @@ typename StatisticType,
typename MatType>
void RectangleTree<SplitType, DescentType, StatisticType, MatType>::CondenseTree(const arma::vec& point)
{
+
// 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++) {
@@ -405,6 +405,7 @@ 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) {
@@ -430,17 +431,20 @@ void RectangleTree<SplitType, DescentType, StatisticType, MatType>::CondenseTree
for (size_t i = 0; i < child->NumChildren(); i++) {
children[i] = child->Children()[i];
}
+ 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();
child->SoftDelete();
}
}
// If we didn't delete it, shrink the bound if we need to.
- if (ShrinkBoundForPoint(point))
+ if (ShrinkBoundForPoint(point) && parent != NULL) {
parent->CondenseTree(point);
+ }
}
@@ -455,47 +459,52 @@ bool RectangleTree<SplitType, DescentType, StatisticType, MatType>::ShrinkBoundF
{
bool shrunk = false;
if (IsLeaf()) {
- 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;
for (size_t j = 0; j < count; j++) {
if (localDataset->col(j)[i] < min)
min = localDataset->col(j)[i];
}
- if (bound[i].Lo() < min)
+ if (bound[i].Lo() < min) {
shrunk = true;
- bound[i].Lo() = min;
+ bound[i].Lo() = min;
+ } else if(min < bound[i].Lo()) {
+ assert(true == false); // we have a problem.
+ }
} else if (bound[i].Hi() == point[i]) {
double max = -1 * DBL_MAX;
for (size_t j = 0; j < count; j++) {
if (localDataset->col(j)[i] > max)
max = localDataset->col(j)[i];
}
- if (bound[i].Hi() > max)
+ if (bound[i].Hi() > max) {
shrunk = true;
- bound[i].Hi() = max;
+ bound[i].Hi() = max;
+ } else if(max > bound[i].Hi()) {
+ assert(true == false); // we have a problem.
+ }
}
}
} else {
for (size_t i = 0; i < point.n_elem; 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 (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)
+ if (bound[i].Lo() < min) {
+ shrunk = true;
+ bound[i].Lo() = min;
+ }
+ if (bound[i].Hi() > max) {
shrunk = true;
- bound[i].Hi() = max;
+ bound[i].Hi() = max;
+ }
}
}
}
@@ -524,7 +533,8 @@ bool RectangleTree<SplitType, DescentType, StatisticType, MatType>::ShrinkBoundF
double sum2 = 0;
for (size_t i = 0; i < bound.Dim(); i++)
sum2 += bound[i].Width();
- return sum == sum2;
+
+ return sum != sum2;
}
/**
@@ -562,25 +572,25 @@ std::string RectangleTree<SplitType, DescentType, StatisticType, MatType>::ToStr
{
std::ostringstream convert;
convert << "RectangleTree [" << this << "]" << std::endl;
- convert << " First point: " << begin << std::endl;
- convert << " Number of descendants: " << numChildren << std::endl;
- convert << " Number of points: " << count << std::endl;
- convert << " Bound: " << std::endl;
- convert << mlpack::util::Indent(bound.ToString(), 2);
- convert << " Statistic: " << std::endl;
- //convert << mlpack::util::Indent(stat.ToString(), 2);
- convert << " Max leaf size: " << maxLeafSize << std::endl;
- convert << " Min leaf size: " << minLeafSize << std::endl;
- convert << " Max num of children: " << maxNumChildren << std::endl;
- convert << " Min num of children: " << minNumChildren << std::endl;
- convert << " Parent address: " << parent << std::endl;
-
- // How many levels should we print? This will print 3 levels (counting the root).
- if (parent == NULL || parent->Parent() == NULL) {
- for (int i = 0; i < numChildren; i++) {
- convert << children[i]->ToString();
- }
- }
+// convert << " First point: " << begin << std::endl;
+// convert << " Number of descendants: " << numChildren << std::endl;
+// convert << " Number of points: " << count << std::endl;
+// convert << " Bound: " << std::endl;
+// convert << mlpack::util::Indent(bound.ToString(), 2);
+// convert << " Statistic: " << std::endl;
+// //convert << mlpack::util::Indent(stat.ToString(), 2);
+// convert << " Max leaf size: " << maxLeafSize << std::endl;
+// convert << " Min leaf size: " << minLeafSize << std::endl;
+// convert << " Max num of children: " << maxNumChildren << std::endl;
+// convert << " Min num of children: " << minNumChildren << std::endl;
+// convert << " Parent address: " << parent << std::endl;
+//
+// // How many levels should we print? This will print 3 levels (counting the root).
+// if (parent == NULL || parent->Parent() == NULL) {
+// for (int i = 0; i < numChildren; i++) {
+// convert << children[i]->ToString();
+// }
+// }
return convert.str();
}
diff --git a/src/mlpack/tests/rectangle_tree_test.cpp b/src/mlpack/tests/rectangle_tree_test.cpp
index 47d046d..3903d0b 100644
--- a/src/mlpack/tests/rectangle_tree_test.cpp
+++ b/src/mlpack/tests/rectangle_tree_test.cpp
@@ -1,4 +1,4 @@
-
+
/**
* @file tree_traits_test.cpp
* @author Andrew Wells
@@ -27,132 +27,128 @@ BOOST_AUTO_TEST_SUITE(RectangleTreeTest);
// will cause bizarre problems.
// Test the traits on RectangleTrees.
-BOOST_AUTO_TEST_CASE(RectangeTreeTraitsTest)
-{
+
+BOOST_AUTO_TEST_CASE(RectangeTreeTraitsTest) {
// Children may be overlapping.
bool b = TreeTraits<RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
- tree::RTreeDescentHeuristic,
- NeighborSearchStat<NearestNeighborSort>,
- arma::mat> >::HasOverlappingChildren;
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat> >::HasOverlappingChildren;
BOOST_REQUIRE_EQUAL(b, true);
-
+
// Points are not contained in multiple levels.
b = TreeTraits<RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
- tree::RTreeDescentHeuristic,
- NeighborSearchStat<NearestNeighborSort>,
- arma::mat> >::HasSelfChildren;
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat> >::HasSelfChildren;
BOOST_REQUIRE_EQUAL(b, false);
}
-BOOST_AUTO_TEST_CASE(RectangleTreeConstructionCountTest)
-{
+BOOST_AUTO_TEST_CASE(RectangleTreeConstructionCountTest) {
arma::mat dataset;
dataset.randu(3, 1000); // 1000 points in 3 dimensions.
-
+
RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
- tree::RTreeDescentHeuristic,
- NeighborSearchStat<NearestNeighborSort>,
- arma::mat> tree(dataset, 20, 6, 5, 2, 0);
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat> tree(dataset, 20, 6, 5, 2, 0);
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), 1000);
}
std::vector<arma::vec*> getAllPointsInTree(const RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
- tree::RTreeDescentHeuristic,
- NeighborSearchStat<NearestNeighborSort>,
- arma::mat>& tree)
-{
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat>& tree) {
std::vector<arma::vec*> vec;
- if(tree.NumChildren() > 0) {
- for(size_t i = 0; i < tree.NumChildren(); i++) {
- std::vector<arma::vec*> tmp = getAllPointsInTree(*(tree.Children()[i]));
+ if (tree.NumChildren() > 0) {
+ for (size_t i = 0; i < tree.NumChildren(); i++) {
+ std::vector<arma::vec*> tmp = getAllPointsInTree(*(tree.Child(i)));
vec.insert(vec.begin(), tmp.begin(), tmp.end());
}
} else {
- for(size_t i = 0; i < tree.Count(); i++) {
- arma::vec* c = new arma::vec(tree.Dataset().col(tree.Points()[i]));
+ for (size_t i = 0; i < tree.Count(); i++) {
+ arma::vec* c = new arma::vec(tree.Dataset().col(tree.Points()[i]));
vec.push_back(c);
}
}
return vec;
}
-BOOST_AUTO_TEST_CASE(RectangleTreeConstructionRepeatTest)
-{
+BOOST_AUTO_TEST_CASE(RectangleTreeConstructionRepeatTest) {
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
-
+
RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
- tree::RTreeDescentHeuristic,
- NeighborSearchStat<NearestNeighborSort>,
- arma::mat> tree(dataset, 20, 6, 5, 2, 0);
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat> tree(dataset, 20, 6, 5, 2, 0);
std::vector<arma::vec*> allPoints = getAllPointsInTree(tree);
- for(size_t i = 0; i < allPoints.size(); i++) {
- for(size_t j = i+1; j < allPoints.size(); j++) {
+ for (size_t i = 0; i < allPoints.size(); i++) {
+ for (size_t j = i + 1; j < allPoints.size(); j++) {
arma::vec v1 = *(allPoints[i]);
arma::vec v2 = *(allPoints[j]);
bool same = true;
- for(size_t k = 0; k < v1.n_rows; k++) {
- same &= (v1[k] == v2[k]);
+ for (size_t k = 0; k < v1.n_rows; k++) {
+ same &= (v1[k] == v2[k]);
}
assert(same != true);
}
}
- for(size_t i = 0; i < allPoints.size(); i++) {
+ for (size_t i = 0; i < allPoints.size(); i++) {
delete allPoints[i];
}
}
bool checkContainment(const RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
- tree::RTreeDescentHeuristic,
- NeighborSearchStat<NearestNeighborSort>,
- arma::mat>& tree)
-{
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat>& tree) {
bool passed = true;
- if(tree.NumChildren() == 0) {
- for(size_t i = 0; i < tree.Count(); i++) {
+ if (tree.NumChildren() == 0) {
+ for (size_t i = 0; i < tree.Count(); i++) {
passed &= tree.Bound().Contains(tree.Dataset().unsafe_col(tree.Points()[i]));
}
} else {
- for(size_t i = 0; i < tree.NumChildren(); i++) {
+ for (size_t i = 0; i < tree.NumChildren(); i++) {
bool p1 = true;
- for(size_t j = 0; j < tree.Bound().Dim(); j++) {
- p1 &= tree.Bound()[j].Contains(tree.Children()[i]->Bound()[j]);
+ for (size_t j = 0; j < tree.Bound().Dim(); j++) {
+ p1 &= tree.Bound()[j].Contains(tree.Children()[i]->Bound()[j]);
}
passed &= p1;
- passed &= checkContainment(*(tree.Children()[i]));
+ passed &= checkContainment(*(tree.Child(i)));
}
- }
+ }
return passed;
}
-BOOST_AUTO_TEST_CASE(RectangleTreeContainmentTest)
-{
+BOOST_AUTO_TEST_CASE(RectangleTreeContainmentTest) {
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
-
+
RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
- tree::RTreeDescentHeuristic,
- NeighborSearchStat<NearestNeighborSort>,
- arma::mat> tree(dataset, 20, 6, 5, 2, 0);
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat> tree(dataset, 20, 6, 5, 2, 0);
assert(checkContainment(tree) == true);
}
bool checkSync(const RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
- tree::RTreeDescentHeuristic,
- NeighborSearchStat<NearestNeighborSort>,
- arma::mat>& tree) {
- if(tree.IsLeaf()) {
- for(size_t i = 0; i < tree.Count(); i++) {
- for(size_t j = 0; j < tree.LocalDataset().n_rows; j++) {
- if(tree.LocalDataset().col(i)[j] != tree.Dataset().col(tree.Points()[i])[j])
- return false;
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat>& tree) {
+ if (tree.IsLeaf()) {
+ for (size_t i = 0; i < tree.Count(); i++) {
+ for (size_t j = 0; j < tree.LocalDataset().n_rows; j++) {
+ if (tree.LocalDataset().col(i)[j] != tree.Dataset().col(tree.Points()[i])[j]) {
+ return false;
+ }
}
}
} else {
- for(size_t i = 0; i < tree.NumChildren(); i++) {
- if(!checkSync(tree.Children()[i]))
- return false;
+ for (size_t i = 0; i < tree.NumChildren(); i++) {
+ if (!checkSync(*tree.Child(i)))
+ return false;
}
}
return true;
@@ -161,11 +157,11 @@ bool checkSync(const RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic,
BOOST_AUTO_TEST_CASE(TreeLocalDatasetInSync) {
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
-
+
RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
- tree::RTreeDescentHeuristic,
- NeighborSearchStat<NearestNeighborSort>,
- arma::mat> tree(dataset, 20, 6, 5, 2, 0);
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat> tree(dataset, 20, 6, 5, 2, 0);
assert(checkSync(tree) == true);
}
@@ -174,64 +170,67 @@ BOOST_AUTO_TEST_CASE(PointDeletion) {
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
const int numIter = 50;
-
+
RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
- tree::RTreeDescentHeuristic,
- NeighborSearchStat<NearestNeighborSort>,
- arma::mat> tree(dataset, 20, 6, 5, 2, 0);
- for(int i = 0; i < numIter; i++) {
- tree.DeletePoint(i);
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat> tree(dataset, 20, 6, 5, 2, 0);
+
+ for (int i = 0; i < numIter; i++) {
+ tree.DeletePoint(i);
}
- std::cout << tree.NumDescendants() << std::endl;
- assert(tree.NumDescendants() == 1000-numIter);
-
- mlpack::neighbor::NeighborSearch<NearestNeighborSort, metric::LMetric<2, true>,
- RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
- tree::RTreeDescentHeuristic,
- NeighborSearchStat<NearestNeighborSort>,
- arma::mat> > allknn1(&tree,
- dataset, true);
-
+ assert(tree.NumDescendants() == 1000 - numIter);
+ assert(checkContainment(tree) == true);
+ assert(checkSync(tree) == true);
+
+ mlpack::neighbor::NeighborSearch<NearestNeighborSort, metric::LMetric<2, true>,
+ RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat> > allknn1(&tree,
+ dataset, true);
+
arma::Mat<size_t> neighbors;
arma::mat distances;
allknn1.Search(5, neighbors, distances);
- for(int i = 0; i < numIter; i++)
+ for (int i = 0; i < numIter; i++)
assert(distances.at(0, i) > 0);
-
+
+ assert(checkContainment(tree) == true);
+
}
-BOOST_AUTO_TEST_CASE(SingleTreeTraverserTest)
-{
+BOOST_AUTO_TEST_CASE(SingleTreeTraverserTest) {
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
arma::Mat<size_t> neighbors1;
arma::mat distances1;
arma::Mat<size_t> neighbors2;
arma::mat distances2;
-
+
RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
- tree::RTreeDescentHeuristic,
- NeighborSearchStat<NearestNeighborSort>,
- arma::mat> RTree(dataset, 20, 6, 5, 2, 0);
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat> RTree(dataset, 20, 6, 5, 2, 0);
// nearest neighbor search with the R tree.
mlpack::neighbor::NeighborSearch<NearestNeighborSort, metric::LMetric<2, true>,
- RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
- tree::RTreeDescentHeuristic,
- NeighborSearchStat<NearestNeighborSort>,
- arma::mat> > allknn1(&RTree,
- dataset, true);
-
+ RectangleTree<tree::RTreeSplit<tree::RTreeDescentHeuristic, NeighborSearchStat<NearestNeighborSort>, arma::mat>,
+ tree::RTreeDescentHeuristic,
+ NeighborSearchStat<NearestNeighborSort>,
+ arma::mat> > allknn1(&RTree,
+ dataset, true);
+
allknn1.Search(5, neighbors1, distances1);
// nearest neighbor search the naive way.
mlpack::neighbor::AllkNN allknn2(dataset,
- true, true);
+ true, true);
allknn2.Search(5, neighbors2, distances2);
-
- for(size_t i = 0; i < neighbors1.size(); i++) {
+
+ for (size_t i = 0; i < neighbors1.size(); i++) {
assert(neighbors1[i] == neighbors2[i]);
assert(distances1[i] == distances2[i]);
}
--
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