From 64525dea5a9e084331d00278d26bdfd82d8c166a Mon Sep 17 00:00:00 2001 From: Mikhail Lozhnikov Date: Thu, 23 Jun 2016 23:04:35 +0300 Subject: [PATCH] Fixed comments. Removed RecursiveHilbertValue. Added a template parameter splitOrder. --- src/mlpack/core/tree/CMakeLists.txt | 2 - src/mlpack/core/tree/rectangle_tree.hpp | 1 - .../rectangle_tree/discrete_hilbert_value.hpp | 57 ++- .../discrete_hilbert_value_impl.hpp | 94 +++-- .../hilbert_r_tree_auxiliary_information.hpp | 3 - ...bert_r_tree_auxiliary_information_impl.hpp | 16 - .../rectangle_tree/hilbert_r_tree_split.hpp | 2 +- .../hilbert_r_tree_split_impl.hpp | 25 +- .../no_auxiliary_information.hpp | 41 ++- .../rectangle_tree/rectangle_tree_impl.hpp | 2 +- .../recursive_hilbert_value.hpp | 219 ----------- .../recursive_hilbert_value_impl.hpp | 347 ------------------ .../core/tree/rectangle_tree/typedef.hpp | 16 +- .../x_tree_auxiliary_information.hpp | 48 ++- src/mlpack/tests/rectangle_tree_test.cpp | 72 +--- 15 files changed, 170 insertions(+), 775 deletions(-) delete mode 100644 src/mlpack/core/tree/rectangle_tree/recursive_hilbert_value.hpp delete mode 100644 src/mlpack/core/tree/rectangle_tree/recursive_hilbert_value_impl.hpp diff --git a/src/mlpack/core/tree/CMakeLists.txt b/src/mlpack/core/tree/CMakeLists.txt index 28415d528d..0399e84cda 100644 --- a/src/mlpack/core/tree/CMakeLists.txt +++ b/src/mlpack/core/tree/CMakeLists.txt @@ -59,8 +59,6 @@ set(SOURCES rectangle_tree/hilbert_r_tree_split_impl.hpp rectangle_tree/hilbert_r_tree_auxiliary_information.hpp rectangle_tree/hilbert_r_tree_auxiliary_information_impl.hpp - rectangle_tree/recursive_hilbert_value.hpp - rectangle_tree/recursive_hilbert_value_impl.hpp rectangle_tree/discrete_hilbert_value.hpp rectangle_tree/discrete_hilbert_value_impl.hpp statistic.hpp diff --git a/src/mlpack/core/tree/rectangle_tree.hpp b/src/mlpack/core/tree/rectangle_tree.hpp index de236ad40e..c2ff9bb44b 100644 --- a/src/mlpack/core/tree/rectangle_tree.hpp +++ b/src/mlpack/core/tree/rectangle_tree.hpp @@ -28,7 +28,6 @@ #include "rectangle_tree/hilbert_r_tree_descent_heuristic.hpp" #include "rectangle_tree/hilbert_r_tree_split.hpp" #include "rectangle_tree/hilbert_r_tree_auxiliary_information.hpp" -#include "rectangle_tree/recursive_hilbert_value.hpp" #include "rectangle_tree/discrete_hilbert_value.hpp" #include "rectangle_tree/typedef.hpp" diff --git a/src/mlpack/core/tree/rectangle_tree/discrete_hilbert_value.hpp b/src/mlpack/core/tree/rectangle_tree/discrete_hilbert_value.hpp index ab7f8a06ef..98eec7937e 100644 --- a/src/mlpack/core/tree/rectangle_tree/discrete_hilbert_value.hpp +++ b/src/mlpack/core/tree/rectangle_tree/discrete_hilbert_value.hpp @@ -139,11 +139,21 @@ class DiscreteHilbertValue */ template void Copy(TreeType* dst, TreeType* src); - + + /** + * Copy the local Hilbert value's pointer. + * @param val The DiscreteHilbertValue object from which the dataset + * will be copied. + */ + DiscreteHilbertValue& operator = (const DiscreteHilbertValue& val); + + /** + * Nullify the localHilbertValues pointer in order to prevent an invalid free. + */ void NullifyData(); /** - * Update the largest Hilbert value and the local dataset. + * Update the largest Hilbert value and the local Hilbert values of an intermediate node. * The children of the node (or the points that the node contains) should be * arranged according to their Hilbert values. * @param node The node in which the information should be updated. @@ -151,8 +161,16 @@ class DiscreteHilbertValue template void UpdateLargestValue(TreeType* node); + /** + * This method updates the largest Hilbert value of a leaf node and + * redistributes the Hilbert values of points according to their new position + * after the split algorithm. + * @param parent The parent of the node that was split. + * @param firstSibling The first cooperationg sibling. + * @param lastSibling The last cooperating sibling. + */ template - void UpdateHilbertValues(TreeType* parent, size_t firstSibling, + void RedistributeHilbertValues(TreeType* parent, size_t firstSibling, size_t lastSibling); /** @@ -182,11 +200,12 @@ class DiscreteHilbertValue { return numValues; } //! Return the local dataset - const arma::Mat* LocalDataset() const - { return localDataset; } + const arma::Mat* LocalHilbertValues() const + { return localHilbertValues; } //! Modify the dataset - arma::Mat*& LocalDataset() { return localDataset; } + arma::Mat*& LocalHilbertValues() + { return localHilbertValues; } //! Modify the valueToInsert arma::Col* ValueToInsert() { return valueToInsert; } @@ -198,21 +217,21 @@ class DiscreteHilbertValue private: //! The number of bits that we can store static constexpr size_t order = sizeof(HilbertElemType) * CHAR_BIT; - //! The local dataset - arma::Mat* localDataset; - //! Indicates that the node owns the local dataset - bool ownsLocalDataset; - //! The number of values in the local dataset + //! The local Hilbert values + arma::Mat* localHilbertValues; + //! Indicates that the node owns the localHilbertValues variable + bool ownsLocalHilbertValues; + //! The number of values in the localHilbertValues dataset size_t numValues; - //! The Hilbert value of the point that is being inserted - arma::Col* valueToInsert; - //! Indicates that the node owns the valueToInsert - bool ownsValueToInsert; - - /** - * Returns true if the node has the largest Hilbert value. + /** The Hilbert value of the point that is being inserted. + * The pointer is the same in all nodes. The value is updated in InsertPoint() + * if it is invoked at the root level. This variable helps to avoid + * multiple computation of the Hilbert value of a point in the insertion + * process. */ - bool HasValue() const; + arma::Col* valueToInsert; + //! Indicates that the node owns the valueToInsert. + bool ownsValueToInsert; public: template diff --git a/src/mlpack/core/tree/rectangle_tree/discrete_hilbert_value_impl.hpp b/src/mlpack/core/tree/rectangle_tree/discrete_hilbert_value_impl.hpp index a9b47836cb..bf3cd27c72 100644 --- a/src/mlpack/core/tree/rectangle_tree/discrete_hilbert_value_impl.hpp +++ b/src/mlpack/core/tree/rectangle_tree/discrete_hilbert_value_impl.hpp @@ -15,8 +15,8 @@ namespace tree /** Trees and tree-building procedures. */ { template DiscreteHilbertValue::DiscreteHilbertValue() : - localDataset(NULL), - ownsLocalDataset(false), + localHilbertValues(NULL), + ownsLocalHilbertValues(false), numValues(0), valueToInsert(NULL), ownsValueToInsert(false) @@ -27,8 +27,8 @@ DiscreteHilbertValue::DiscreteHilbertValue() : template DiscreteHilbertValue::~DiscreteHilbertValue() { - if (ownsLocalDataset) - delete localDataset; + if (ownsLocalHilbertValues) + delete localHilbertValues; if (ownsValueToInsert) delete valueToInsert; } @@ -36,8 +36,8 @@ DiscreteHilbertValue::~DiscreteHilbertValue() template template DiscreteHilbertValue::DiscreteHilbertValue(const TreeType* tree) : - localDataset(NULL), - ownsLocalDataset(false), + localHilbertValues(NULL), + ownsLocalHilbertValues(false), numValues(0), valueToInsert(tree->Parent() ? tree->Parent()->AuxiliaryInfo().HilbertValue().ValueToInsert() : @@ -46,17 +46,17 @@ DiscreteHilbertValue::DiscreteHilbertValue(const TreeType* tree) : { // Calculate the Hilbert value for all points if (!tree->Parent()) // This is the root node - ownsLocalDataset = true; + ownsLocalHilbertValues = true; else if (tree->Parent()->Children()[0]->IsLeaf()) { // This is a leaf node assert(tree->Parent()->NumChildren() > 0); - ownsLocalDataset = true; + ownsLocalHilbertValues = true; } - if (ownsLocalDataset) + if (ownsLocalHilbertValues) { - localDataset = new arma::Mat(tree->Dataset().n_rows, + localHilbertValues = new arma::Mat(tree->Dataset().n_rows, tree->MaxLeafSize() + 1); } @@ -65,8 +65,8 @@ DiscreteHilbertValue::DiscreteHilbertValue(const TreeType* tree) : template DiscreteHilbertValue:: DiscreteHilbertValue(const DiscreteHilbertValue& other) : - localDataset(const_cast*>(other.LocalDataset())), - ownsLocalDataset(other.ownsLocalDataset), + localHilbertValues(const_cast*>(other.LocalHilbertValues())), + ownsLocalHilbertValues(other.ownsLocalHilbertValues), numValues(other.NumValues()), valueToInsert(const_cast*>(other.ValueToInsert())), ownsValueToInsert(false) @@ -216,15 +216,15 @@ int DiscreteHilbertValue:: CompareValues(const DiscreteHilbertValue& val1, const DiscreteHilbertValue& val2) { - if (val1.HasValue() && !val2.HasValue()) + if (val1.NumValues() > 0 && val2.NumValues() == 0) return 1; - else if (!val1.HasValue() && val2.HasValue()) + else if (val1.NumValues() == 0 && val2.NumValues() > 0) return -1; - else if (!val1.HasValue() && !val2.HasValue()) + else if (val1.NumValues() == 0 && val2.NumValues() == 0) return 0; - return CompareValues(val1.LocalDataset()->col(val1.NumValues() - 1), - val2.LocalDataset()->col(val2.NumValues() - 1)); + return CompareValues(val1.LocalHilbertValues()->col(val1.NumValues() - 1), + val2.LocalHilbertValues()->col(val2.NumValues() - 1)); } template @@ -242,10 +242,10 @@ CompareWith(const VecType& pt, { arma::Col val = CalculateValue(pt); - if (!HasValue()) + if (numValues == 0) return -1; - return CompareValues(localDataset->col(numValues - 1),val); + return CompareValues(localHilbertValues->col(numValues - 1),val); } template @@ -254,10 +254,10 @@ int DiscreteHilbertValue:: CompareWithCachedPoint(const VecType& , typename boost::enable_if>*) const { - if (!HasValue()) + if (numValues == 0) return -1; - return CompareValues(localDataset->col(numValues - 1),*valueToInsert); + return CompareValues(localHilbertValues->col(numValues - 1),*valueToInsert); } template @@ -275,13 +275,13 @@ InsertPoint(TreeType *node, const VecType& pt, { // Find an appropriate place for (i = 0; i < numValues; i++) - if (CompareValues(localDataset->col(i), *valueToInsert) > 0) + if (CompareValues(localHilbertValues->col(i), *valueToInsert) > 0) break; for (size_t j = numValues; j > i; j--) - localDataset->col(j) = localDataset->col(j-1); + localHilbertValues->col(j) = localHilbertValues->col(j-1); - localDataset->col(i) = *valueToInsert; + localHilbertValues->col(i) = *valueToInsert; numValues++; // Propogate changes of the largest Hilbert value downward TreeType* root = node->Parent(); @@ -306,7 +306,7 @@ void DiscreteHilbertValue::InsertNode(TreeType* node) if (CompareWith(node,val) < 0) { - localDataset = val.LocalDataset(); + localHilbertValues = val.LocalHilbertValues(); numValues = val.NumValues(); } } @@ -319,7 +319,7 @@ DeletePoint(TreeType* node, const size_t localIndex) // Delete the Hilbert value from the local dataset for (size_t i = numValues - 1; i > localIndex; i--) - localDataset->col(i-1) = localDataset->col(i); + localHilbertValues->col(i-1) = localHilbertValues->col(i); numValues--; } @@ -331,7 +331,7 @@ RemoveNode(TreeType* node, const size_t nodeIndex) { if (node->NumChildren() <= 1) { - localDataset = NULL; + localHilbertValues = NULL; numValues = 0; return; } @@ -342,31 +342,32 @@ RemoveNode(TreeType* node, const size_t nodeIndex) if (child->AuxiliaryInfo.HilbertValue().NumValues() != 0) { numValues = child->AuxiliaryInfo.HilbertValue().NumValues(); - localDataset = child->AuxiliaryInfo.HilbertValue().LocalDataset(); + localHilbertValues = child->AuxiliaryInfo.HilbertValue().LocalHilbertValues(); } else { - localDataset = NULL; + localHilbertValues = NULL; numValues = 0; } } } template -template -void DiscreteHilbertValue::Copy(TreeType* dst, TreeType* src) +DiscreteHilbertValue& DiscreteHilbertValue:: +operator = (const DiscreteHilbertValue& val) { - DiscreteHilbertValue &dstVal = dst->AuxiliaryInfo().HilbertValue(); - DiscreteHilbertValue &srcVal = src->AuxiliaryInfo().HilbertValue(); + localHilbertValues = const_cast* > + (val.LocalHilbertValues()); + ownsLocalHilbertValues = false; + numValues = val.NumValues(); - dst.LocalDataset() = src.LocalDataset(); - dst.NumValues() = src.NumValues(); + return *this; } template void DiscreteHilbertValue::NullifyData() { - ownsLocalDataset = false; + ownsLocalHilbertValues = false; } template @@ -376,7 +377,7 @@ void DiscreteHilbertValue::UpdateLargestValue(TreeType* node) if (!node->IsLeaf()) { // Update the largest Hilbert value - localDataset = node->Children()[node->NumChildren()-1]->AuxiliaryInfo().HilbertValue().LocalDataset(); + localHilbertValues = node->Children()[node->NumChildren()-1]->AuxiliaryInfo().HilbertValue().LocalHilbertValues(); numValues = node->Children()[node->NumChildren()-1]->AuxiliaryInfo().HilbertValue().NumValues(); } } @@ -384,7 +385,7 @@ void DiscreteHilbertValue::UpdateLargestValue(TreeType* node) template template void DiscreteHilbertValue:: -UpdateHilbertValues(TreeType* parent, size_t firstSibling, size_t lastSibling) +RedistributeHilbertValues(TreeType* parent, size_t firstSibling, size_t lastSibling) { // We should update the local dataset if points were redistributed @@ -394,7 +395,7 @@ UpdateHilbertValues(TreeType* parent, size_t firstSibling, size_t lastSibling) numPoints += parent->Children()[i]->NumPoints(); // Copy the local datasets - arma::Mat tmp(localDataset->n_rows,numPoints); + arma::Mat tmp(localHilbertValues->n_rows,numPoints); size_t iPoint = 0; for (size_t i = firstSibling; i<= lastSibling; i++) @@ -404,7 +405,7 @@ UpdateHilbertValues(TreeType* parent, size_t firstSibling, size_t lastSibling) for (size_t j = 0; j < value.NumValues(); j++) { - tmp.col(iPoint) = value.LocalDataset()->col(j); + tmp.col(iPoint) = value.LocalHilbertValues()->col(j); iPoint++; } } @@ -420,7 +421,7 @@ UpdateHilbertValues(TreeType* parent, size_t firstSibling, size_t lastSibling) for (size_t j = 0; j < parent->Children()[i]->NumPoints(); j++) { - value.LocalDataset()->col(j) = tmp.col(iPoint); + value.LocalHilbertValues()->col(j) = tmp.col(iPoint); iPoint++; } value.NumValues() = parent->Children()[i]->NumPoints(); @@ -430,13 +431,6 @@ UpdateHilbertValues(TreeType* parent, size_t firstSibling, size_t lastSibling) } - -template -bool DiscreteHilbertValue::HasValue() const -{ - return numValues > 0; -} - template template void DiscreteHilbertValue:: @@ -444,8 +438,8 @@ Serialize(Archive& ar, const unsigned int /* version */) { using data::CreateNVP; - ar & CreateNVP(localDataset, "localDataset"); - ar & CreateNVP(ownsLocalDataset, "ownsLocalDataset"); + ar & CreateNVP(localHilbertValues, "localHilbertValues"); + ar & CreateNVP(ownsLocalHilbertValues, "ownsLocalHilbertValues"); ar & CreateNVP(numValues, "numValues"); ar & CreateNVP(valueToInsert, "valueToInsert"); ar & CreateNVP(ownsValueToInsert, "ownsValueToInsert"); diff --git a/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_auxiliary_information.hpp b/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_auxiliary_information.hpp index be18a1c215..a51a0ebd69 100644 --- a/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_auxiliary_information.hpp +++ b/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_auxiliary_information.hpp @@ -34,9 +34,6 @@ class HilbertRTreeAuxiliaryInformation */ HilbertRTreeAuxiliaryInformation(const HilbertRTreeAuxiliaryInformation& other); - //! Free memory - ~HilbertRTreeAuxiliaryInformation(); - /** * The Hilbert R tree requires to insert points according to their * Hilbert value. This method should take care of it. diff --git a/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_auxiliary_information_impl.hpp b/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_auxiliary_information_impl.hpp index 507388e45d..3e5e5f3fb0 100644 --- a/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_auxiliary_information_impl.hpp +++ b/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_auxiliary_information_impl.hpp @@ -40,14 +40,6 @@ HilbertRTreeAuxiliaryInformation(const HilbertRTreeAuxiliaryInformation& other) { }; - -template class HilbertValueType> -HilbertRTreeAuxiliaryInformation:: -~HilbertRTreeAuxiliaryInformation() -{ - -} template class HilbertValueType> @@ -158,14 +150,6 @@ UpdateAuxiliaryInfo(TreeType* node) return false; } -template class HilbertValueType> -void HilbertRTreeAuxiliaryInformation:: -Copy(TreeType* dst, TreeType* src) -{ - hilbertValue.Copy(dst,src); -} - template class HilbertValueType> void HilbertRTreeAuxiliaryInformation:: diff --git a/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_split.hpp b/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_split.hpp index f830c134ba..5ffdda5e3b 100644 --- a/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_split.hpp +++ b/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_split.hpp @@ -17,8 +17,8 @@ namespace tree /** Trees and tree-building procedures. */ { * The order of the splitting policy. The Hilbert R tree splits a node * on overflow, turnung splitOrder node to (splitOrder+1) nodes. */ -constexpr int splitOrder = 2; +template class HilbertRTreeSplit { public: diff --git a/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_split_impl.hpp b/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_split_impl.hpp index fd39961094..8fff710382 100644 --- a/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_split_impl.hpp +++ b/src/mlpack/core/tree/rectangle_tree/hilbert_r_tree_split_impl.hpp @@ -14,8 +14,9 @@ namespace mlpack { namespace tree { +template template -void HilbertRTreeSplit:: +void HilbertRTreeSplit:: SplitLeafNode(TreeType* tree, std::vector& relevels) { // If we are splitting the root node, we need will do things differently so @@ -30,7 +31,7 @@ SplitLeafNode(TreeType* tree, std::vector& relevels) tree->NullifyData(); // Because this was a leaf node, numChildren must be 0. tree->Children()[(tree->NumChildren())++] = copy; - HilbertRTreeSplit::SplitLeafNode(copy, relevels); + SplitLeafNode(copy, relevels); return; } @@ -72,12 +73,13 @@ SplitLeafNode(TreeType* tree, std::vector& relevels) RedistributePointsEvenly(parent, firstSibling, lastSibling); if (parent->NumChildren() == parent->MaxNumChildren() + 1) - HilbertRTreeSplit::SplitNonLeafNode(parent, relevels); + SplitNonLeafNode(parent, relevels); } +template template -bool HilbertRTreeSplit:: +bool HilbertRTreeSplit:: SplitNonLeafNode(TreeType* tree,std::vector& relevels) { // If we are splitting the root node, we need will do things differently so @@ -93,7 +95,7 @@ SplitNonLeafNode(TreeType* tree,std::vector& relevels) tree->NullifyData(); tree->Children()[(tree->NumChildren())++] = copy; - HilbertRTreeSplit::SplitNonLeafNode(copy, relevels); + SplitNonLeafNode(copy, relevels); return true; } @@ -137,12 +139,13 @@ SplitNonLeafNode(TreeType* tree,std::vector& relevels) RedistributeNodesEvenly(parent, firstSibling, lastSibling); if (parent->NumChildren() == parent->MaxNumChildren() + 1) - HilbertRTreeSplit::SplitNonLeafNode(parent, relevels); + SplitNonLeafNode(parent, relevels); return false; } +template template -bool HilbertRTreeSplit::FindCooperatingSiblings(TreeType *parent, size_t iTree, +bool HilbertRTreeSplit::FindCooperatingSiblings(TreeType *parent, size_t iTree, size_t &firstSibling, size_t &lastSibling) { size_t start = (iTree > splitOrder-1 ? iTree - splitOrder + 1 : 0); @@ -192,8 +195,9 @@ bool HilbertRTreeSplit::FindCooperatingSiblings(TreeType *parent, size_t iTree, return true; } +template template -void HilbertRTreeSplit:: +void HilbertRTreeSplit:: RedistributeNodesEvenly(const TreeType *parent, size_t firstSibling, size_t lastSibling) { @@ -254,8 +258,9 @@ RedistributeNodesEvenly(const TreeType *parent, } } +template template -void HilbertRTreeSplit:: +void HilbertRTreeSplit:: RedistributePointsEvenly(TreeType *parent, size_t firstSibling, size_t lastSibling) { @@ -308,7 +313,7 @@ RedistributePointsEvenly(TreeType *parent, parent->Children()[i]->MaxLeafSize()); } // Fix the largest Hilbert values of the siblings. - parent->AuxiliaryInfo().HilbertValue().UpdateHilbertValues(parent, firstSibling, lastSibling); + parent->AuxiliaryInfo().HilbertValue().RedistributeHilbertValues(parent, firstSibling, lastSibling); TreeType* root = parent; diff --git a/src/mlpack/core/tree/rectangle_tree/no_auxiliary_information.hpp b/src/mlpack/core/tree/rectangle_tree/no_auxiliary_information.hpp index ac37908b2f..8f6a34c8ae 100644 --- a/src/mlpack/core/tree/rectangle_tree/no_auxiliary_information.hpp +++ b/src/mlpack/core/tree/rectangle_tree/no_auxiliary_information.hpp @@ -21,7 +21,12 @@ class NoAuxiliaryInformation /** * Some tree types require to save some properties at the insertion process. - * This method should return false if it does not handle the process. + * This method allows the auxiliary information the option of manipulating + * the tree in order to perform the insertion process. If the auxiliary + * information does that, then the method should return true; if the method + * returns false the RectangleTree performs its default behavior. + * @param node The node in which the point is being inserted. + * @param point The global number of the point being inserted. */ bool HandlePointInsertion(TreeType* , const size_t) { @@ -30,7 +35,14 @@ class NoAuxiliaryInformation /** * Some tree types require to save some properties at the insertion process. - * This method should return false if it does not handle the process. + * This method allows the auxiliary information the option of manipulating + * the tree in order to perform the insertion process. If the auxiliary + * information does that, then the method should return true; if the method + * returns false the RectangleTree performs its default behavior. + * @param node The node in which the nodeToInsert is being inserted. + * @param nodeToInsert The node being inserted. + * @param insertionLevel The level of the tree at which the nodeToInsert + * should be inserted. */ bool HandleNodeInsertion(TreeType* , TreeType* ,bool) { @@ -39,7 +51,12 @@ class NoAuxiliaryInformation /** * Some tree types require to save some properties at the deletion process. - * This method should return false if it does not handle the process. + * This method allows the auxiliary information the option of manipulating + * the tree in order to perform the deletion process. If the auxiliary + * information does that, then the method should return true; if the method + * returns false the RectangleTree performs its default behavior. + * @param node The node from which the point is being deleted. + * @param localIndex The local index of the point being deleted. */ bool HandlePointDeletion(TreeType* , const size_t) { @@ -48,7 +65,12 @@ class NoAuxiliaryInformation /** * Some tree types require to save some properties at the deletion process. - * This method should return false if it does not handle the process. + * This method allows the auxiliary information the option of manipulating + * the tree in order to perform the deletion process. If the auxiliary + * information does that, then the method should return true; if the method + * returns false the RectangleTree performs its default behavior. + * @param node The node from which the node is being deleted. + * @param nodeIndex The local index of the node being deleted. */ bool HandleNodeRemoval(TreeType* , const size_t) { @@ -56,8 +78,10 @@ class NoAuxiliaryInformation } /** - * Some tree types require to propagate the information downward. - * This method should return false if this is not the case. + * Some tree types require to propagate the information upward. + * This method should return false if this is not the case. If true is + * returned, the update will be propogated upward. + * @param node The node in which the auxiliary information being update. */ bool UpdateAuxiliaryInfo(TreeType* ) { @@ -65,11 +89,8 @@ class NoAuxiliaryInformation } /** - * Nothing to copy. + * Nullify the auxiliary information in order to prevent an invalid free. */ - void Copy(TreeType* , TreeType* ) - { } - void NullifyData() { } 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 c11d62c136..836752b7d3 100644 --- a/src/mlpack/core/tree/rectangle_tree/rectangle_tree_impl.hpp +++ b/src/mlpack/core/tree/rectangle_tree/rectangle_tree_impl.hpp @@ -881,7 +881,7 @@ void RectangleTreePoints()[i]; } - auxiliaryInfo.Copy(this,child); + auxiliaryInfo = child->AuxiliaryInfo(); count = child->Count(); child->SoftDelete(); diff --git a/src/mlpack/core/tree/rectangle_tree/recursive_hilbert_value.hpp b/src/mlpack/core/tree/rectangle_tree/recursive_hilbert_value.hpp deleted file mode 100644 index 09f0403cb3..0000000000 --- a/src/mlpack/core/tree/rectangle_tree/recursive_hilbert_value.hpp +++ /dev/null @@ -1,219 +0,0 @@ -/** - * @file recursive_hilbert_value.hpp - * @author Mikhail Lozhnikov - * - * Defintion of the RecursiveHilbertValue class, a class that measures - * ordering of points recursively. - */ -#ifndef MLPACK_CORE_TREE_RECTANGLE_TREE_RECURSIVE_HILBERT_VALUE_HPP -#define MLPACK_CORE_TREE_RECTANGLE_TREE_RECURSIVE_HILBERT_VALUE_HPP - -#include - -namespace mlpack { -namespace tree /** Trees and tree-building procedures. */ { - -constexpr int recursionDepth = 500; - -template -class RecursiveHilbertValue -{ - public: - //! Default constructor - RecursiveHilbertValue(); - - /** - * Construct this for the node tree. If the node is the root this method - * computes the Hilbert value for each point in the tree's dataset. - * @param node The node that stores this Hilbert value. - */ - template - RecursiveHilbertValue(const TreeType* tree); - - /** - * Create a Hilbert value object by copying from another one. - * @param other The Hilbert value object from which the value will be copied. - */ - RecursiveHilbertValue(const RecursiveHilbertValue& other); - - ~RecursiveHilbertValue(); - - //! This struct is designed in order to facilitate the recursion. - typedef struct tagCompareStruct - { - //! Lower bound - arma::Col Lo; - //! High bound - arma::Col Hi; - //! Permutation of axes - std::vector permutation; - //! Indicates that the axis should be inverted - std::vector inversion; - //! Indicates that the result should be inverted - arma::Col center; - arma::Col vec; - std::vector bits; - std::vector bits2; - bool invertResult; - int recursionLevel; - - - tagCompareStruct(size_t dim) : - Lo(dim), - Hi(dim), - permutation(dim), - inversion(dim), - center(dim), - vec(dim), - bits(dim), - bits2(dim), - invertResult(false), - recursionLevel(0) - { - for (size_t i = 0; i < dim; i++) - { - Lo[i] = std::numeric_limits::lowest(); - Hi[i] = std::numeric_limits::max(); - permutation[i] = i; - inversion[i] = false; - } - } - } CompareStruct; - - /** - * Compare two points. It returns 1 if the first point is greater than - * the second one, -1 if the first point is less than the second one and - * 0 if the Hilbert values of the points are equal. - * @param pt1 The first point. - * @param pt2 The second point. - */ - template - static int ComparePoints(const VecType1& pt1, const VecType2& pt2, - typename boost::enable_if>* = 0, - typename boost::enable_if>* = 0); - - /** - * Compare two Hilbert values. It returns 1 if the first value is greater than - * the second one, -1 if the first value is less than the second one and - * 0 if the values are equal. - * @param val1 The first Hilbert value. - * @param val2 The second Hilbert value. - */ - - static int CompareValues(const RecursiveHilbertValue& val1, - const RecursiveHilbertValue& val2); - - /** - * Compare the largest Hilbert value of the node with the val value. - * It returns 1 if the value of the node is greater than val, - * -1 if the value of the node is less than val and - * 0 if the values are equal. - * @param val The Hilbert value to compare with. - */ - int CompareWith(const RecursiveHilbertValue& val) const; - - /** - * Compare the largest Hilbert value of the node with the Hilbert value - * of the point. It returns 1 if the value of the node is greater than - * the value of the point, -1 if the value of the node is less than - * the value of the point and 0 if the values are equal. - * @param point The point to compare with. - */ - template - int CompareWith(const VecType& point, - typename boost::enable_if>* = 0) const; - - template - int CompareWithCachedPoint(const VecType& point, - typename boost::enable_if>* = 0) const; - - - /** - * Update the largest Hilbert value of the node. - * @param node The node in which the point is being inserted. - * @param point The number of the point being inserted. - */ - template - size_t InsertPoint(TreeType* node, const VecType& point, - typename boost::enable_if>* = 0); - - /** - * Update the largest Hilbert value of the node. - * @param node The node being inserted. - */ - template - void InsertNode(TreeType* node); - - /** - * Update the largest Hilbert value of the node. - * @param node The node from which another node is being deleted. - * @param nodeIndex The number of the node being deleted. - */ - template - void DeletePoint(TreeType* node, const size_t localIndex); - - /** - * Update the largest Hilbert value of the node. - * @param node The node from which another node is being deleted. - * @param nodeIndex The number of the node being deleted. - */ - template - void RemoveNode(TreeType* node, const size_t nodeIndex); - - - /** - * Copy the largest Hilbert value. - * @param dst The node to which the information is being copied. - * @param src The node from which the information is being copied. - */ - template - void Copy(TreeType* dst, TreeType* src); - - void NullifyData(); - - /** - * Update the largest Hilbert value. - * @param node The node in which the information should be updated. - */ - template - void UpdateLargestValue(TreeType* node); - - template - void UpdateHilbertValues(TreeType* parent, size_t firstSibling, - size_t lastSibling); - - //! Return the largest Hilbert value - const arma::Col* LargestValue() const { return largestValue; } - - //! Modify the largest Hilbert value - arma::Col*& LargestValue() { return largestValue; } - - private: - //! The point that has the largest Hilbert value. - arma::Col* largestValue; - bool ownsLargestValue; - bool hasLargestValue; - - /** - * Compare two points. It returns 1 if the first point is greater than - * the second one, -1 if the first point is less than the second one and - * 0 if the Hilbert values of the points are equal. - * @param pt1 The first point. - * @param pt2 The second point. - * @param comp An object of CompareStruct. - */ - template - static int ComparePoints(const VecType1& pt1, const VecType2& pt2, - CompareStruct& comp, typename boost::enable_if>* = 0, - typename boost::enable_if>* = 0); - public: - template - void Serialize(Archive& ar, const unsigned int /* version */); -}; -} // namespace tree -} // namespace mlpack - -// Include implementation -#include "recursive_hilbert_value_impl.hpp" - -#endif // MLPACK_CORE_TREE_RECTANGLE_TREE_RECURSIVE_HILBERT_VALUE_HPP diff --git a/src/mlpack/core/tree/rectangle_tree/recursive_hilbert_value_impl.hpp b/src/mlpack/core/tree/rectangle_tree/recursive_hilbert_value_impl.hpp deleted file mode 100644 index 1b744cb902..0000000000 --- a/src/mlpack/core/tree/rectangle_tree/recursive_hilbert_value_impl.hpp +++ /dev/null @@ -1,347 +0,0 @@ -/** - * @file recursive_hilbert_value_impl.hpp - * @author Mikhail Lozhnikov - * - * Implementation of the RecursiveHilbertValue class, a class that measures - * ordering of points recursively. - */ -#ifndef MLPACK_CORE_TREE_RECTANGLE_TREE_RECURSIVE_HILBERT_VALUE_IMPL_HPP -#define MLPACK_CORE_TREE_RECTANGLE_TREE_RECURSIVE_HILBERT_VALUE_IMPL_HPP - -namespace mlpack { -namespace tree /** Trees and tree-building procedures. */ { - -template -RecursiveHilbertValue::RecursiveHilbertValue() : - largestValue(NULL), - ownsLargestValue(false), - hasLargestValue(false) -{ - -} - -template -template -RecursiveHilbertValue:: -RecursiveHilbertValue(const TreeType* tree) : - largestValue(NULL), - ownsLargestValue(false), - hasLargestValue(false) -{ - if (!tree->Parent()) // This is the root node - ownsLargestValue = true; - else if (tree->Parent()->Children()[0]->IsLeaf()) - { - // This is a leaf node - assert(tree->Parent()->NumChildren() > 0); - ownsLargestValue = true; - } - - if (ownsLargestValue) - { - largestValue = new arma::Col(tree->Dataset().n_rows); - } -} - -template -RecursiveHilbertValue:: -RecursiveHilbertValue(const RecursiveHilbertValue& other) : - largestValue(const_cast*>(other.LargestValue())), - ownsLargestValue(other.ownsLargestValue), - hasLargestValue(other.hasLargestValue) -{ - -} - -template -RecursiveHilbertValue::~RecursiveHilbertValue() -{ - if (ownsLargestValue) - delete largestValue; -} - -template -template -int RecursiveHilbertValue:: -ComparePoints(const VecType1& pt1, const VecType2& pt2, - typename boost::enable_if>*, - typename boost::enable_if>* ) -{ - size_t dim = pt1.n_rows; - CompareStruct comp(dim); - - return ComparePoints(pt1, pt2, comp); -}; - -template -int RecursiveHilbertValue:: -CompareValues(const RecursiveHilbertValue& val1, - const RecursiveHilbertValue& val2) -{ - if (!val1.hasLargestValue && val2.hasLargestValue) - return -1; - else if (val1.hasLargestValue && !val2.hasLargestValue) - return 1; - else if (!val1.hasLargestValue && !val2.hasLargestValue) - return 0; - - return ComparePoints(*val1.LargestValue(), - *val2.LargestValue()); -} - -template -int RecursiveHilbertValue:: -CompareWith(const RecursiveHilbertValue& val) const -{ - if (!hasLargestValue) - return -1; - return CompareValues(*this, val); -} - -template -template -int RecursiveHilbertValue:: -CompareWith(const VecType& point, - typename boost::enable_if>* ) const -{ - if (!hasLargestValue) - return -1; - return ComparePoints(*largestValue, point); -} - -template -template -int RecursiveHilbertValue:: -CompareWithCachedPoint(const VecType& point, - typename boost::enable_if>* ) const -{ - return CompareWith(point); -} - -template -template -int RecursiveHilbertValue:: -ComparePoints(const VecType1& pt1, const VecType2& pt2, - CompareStruct& comp, typename boost::enable_if>*, - typename boost::enable_if>* ) - -{ - comp.center = comp.Hi * 0.5; - comp.vec = comp.Lo * 0.5; - - comp.center += comp.vec; - - // Get bits in order to use the Gray code - for (size_t i = 0; i < pt1.n_rows; i++) - { - size_t j = comp.permutation[i]; - comp.bits[i] = (pt1(j) > comp.center(j) && !comp.inversion[j]) || - (pt1(j) <= comp.center(j) && !comp.inversion[j]); - - comp.bits2[i] = (pt2(j) > comp.center(j) && !comp.inversion[j]) || - (pt2(j) <= comp.center(j) && !comp.inversion[j]); - } - - // Gray encode - for (size_t i = 1; i < pt1.n_rows; i++) - { - comp.bits[i] ^= comp.bits[i-1]; - comp.bits2[i] ^= comp.bits2[i-1]; - } - - if (comp.invertResult) - { - for (size_t i = 0; i < pt1.n_rows; i++) - { - comp.bits[i] = !comp.bits[i]; - comp.bits2[i] = !comp.bits2[i]; - } - } - - for (size_t i = 0; i < pt1.n_rows; i++) - { - if (comp.bits[i] < comp.bits2[i]) - return -1; - if (comp.bits[i] > comp.bits2[i]) - return 1; - } - - if (comp.recursionLevel >= recursionDepth) - return 0; - - comp.recursionLevel++; - - if (comp.bits[pt1.n_rows-1]) - comp.invertResult = !comp.invertResult; - - // Since the Hilbert curve is continuous we should permutate and intend - // coordinate axes depending on the position of the point - for (size_t i = 0; i < pt1.n_rows; i++) - { - size_t j = comp.permutation[i]; - size_t j0 = comp.permutation[0]; - if ((pt1(j) > comp.center(j) && !comp.inversion[j]) || - (pt1(j) <= comp.center(j) && !comp.inversion[j])) - comp.inversion[j0] = !comp.inversion[j0]; - else - { - size_t tmp; - tmp = comp.permutation[0]; - comp.permutation[0] = comp.permutation[i]; - comp.permutation[i] = tmp; - } - } - - // Choose an appropriate subhypercube - for (size_t i = 0; i < pt1.n_rows; i++) - { - if (pt1(i) > comp.center(i)) - comp.Lo(i) = comp.center(i); - else - comp.Hi(i) = comp.center(i); - } - - return ComparePoints(pt1, pt2, comp); -} - -template -template -size_t RecursiveHilbertValue:: -InsertPoint(TreeType* node, const VecType& point, - typename boost::enable_if>* ) -{ - if (node->IsLeaf()) - { - size_t i; - - for (i = 0; i < node->NumPoints(); i++) - if (ComparePoints(node->Dataset().col(node->Point(i)), point) > 0) - break; - if (i == node->NumPoints()) - *largestValue = point; - - hasLargestValue = true; - - // Propogate changes of the largest Hilbert value downward - TreeType* root = node->Parent(); - - while (root != NULL) - { - root->AuxiliaryInfo().HilbertValue().LargestValue() = largestValue; - root->AuxiliaryInfo().HilbertValue().hasLargestValue = true; - - root = root->Parent(); - } - - return i; - } - - return 0; -} - - -template -template -void RecursiveHilbertValue::InsertNode(TreeType* node) -{ - if (CompareWith(node->AuxiliaryInfo().HilbertValue()) < 0) - { - largestValue = node->AuxiliaryInfo().HilbertValue().LargestValue(); - hasLargestValue = true; - } -} - -template -template -void RecursiveHilbertValue:: -DeletePoint(TreeType* node, const size_t localIndex) -{ - if (node->NumPoints() <= 1) - { - hasLargestValue = false; - return; - } - if (localIndex + 1 == node->NumPoints()) - *largestValue = node->Dataset()[node->Point(localIndex-1)]; - -} - -template -template -void RecursiveHilbertValue:: -RemoveNode(TreeType* node, const size_t nodeIndex) -{ - if (node->NumChildren() <= 1) - { - hasLargestValue = false; - return; - } - if (nodeIndex + 1 == node->NumChildren()) - largestValue = node->Children()[nodeIndex-1]->AuxiliaryInfo.HilbertValue().LargestValue(); - -} - -template -template -void RecursiveHilbertValue::Copy(TreeType* dst, TreeType* src) -{ - dst->AuxiliaryInfo().HilbertValue().LargestValue() = - src->AuxiliaryInfo().HilbertValue().LargestValue(); - dst->AuxiliaryInfo().HilbertValue().hasLargestValue = - src->AuxiliaryInfo().HilbertValue().hasLargestValue; -} - -template -void RecursiveHilbertValue::NullifyData() -{ - ownsLargestValue = false; -} - -template -template -void RecursiveHilbertValue::UpdateLargestValue(TreeType* node) -{ - if (!node->IsLeaf()) - { - largestValue = (node->NumChildren() > 0 ? - node->Children()[node->NumChildren() - 1]->AuxiliaryInfo().HilbertValue().LargestValue() : NULL); - hasLargestValue = (node->NumChildren() > 0 ? - node->Children()[node->NumChildren() - 1]->AuxiliaryInfo().HilbertValue().hasLargestValue : false); - } -} - -template -template -void RecursiveHilbertValue:: -UpdateHilbertValues(TreeType* parent, size_t firstSibling, size_t lastSibling) -{ - for (size_t i = firstSibling; i<= lastSibling; i++) - { - RecursiveHilbertValue &value = - parent->Children()[i]->AuxiliaryInfo().HilbertValue(); - - assert(parent->Children()[i]->NumPoints() > 0); - - TreeType *child = parent->Children()[i]; - *value.LargestValue() = child->Dataset().col(child->Point(child->NumPoints() - 1)); - value.hasLargestValue = true; - } - -} - -template -template -void RecursiveHilbertValue:: -Serialize(Archive& ar, const unsigned int /* version */) -{ - using data::CreateNVP; - - ar & CreateNVP(largestValue, "largestValue"); - ar & CreateNVP(ownsLargestValue, "ownsLargestValue"); - ar & CreateNVP(hasLargestValue, "hasLargestValue"); -} - -} // namespace tree -} // namespace mlpack - -#endif //MLPACK_CORE_TREE_RECTANGLE_TREE_RECURSIVE_HILBERT_VALUE_IMPL_HPP diff --git a/src/mlpack/core/tree/rectangle_tree/typedef.hpp b/src/mlpack/core/tree/rectangle_tree/typedef.hpp index c16b4181f0..6557b36143 100644 --- a/src/mlpack/core/tree/rectangle_tree/typedef.hpp +++ b/src/mlpack/core/tree/rectangle_tree/typedef.hpp @@ -119,26 +119,14 @@ using XTree = RectangleTree -using RecursiveHilbertRTreeAuxiliaryInformation = - HilbertRTreeAuxiliaryInformation; - -template -using RecursiveHilbertRTree = RectangleTree; - -template using DiscreteHilbertRTreeAuxiliaryInformation = HilbertRTreeAuxiliaryInformation; template -using DiscreteHilbertRTree = RectangleTree, HilbertRTreeDescentHeuristic, DiscreteHilbertRTreeAuxiliaryInformation>; diff --git a/src/mlpack/core/tree/rectangle_tree/x_tree_auxiliary_information.hpp b/src/mlpack/core/tree/rectangle_tree/x_tree_auxiliary_information.hpp index a95bfe1821..ebfdd90506 100644 --- a/src/mlpack/core/tree/rectangle_tree/x_tree_auxiliary_information.hpp +++ b/src/mlpack/core/tree/rectangle_tree/x_tree_auxiliary_information.hpp @@ -43,7 +43,12 @@ class XTreeAuxiliaryInformation /** * Some tree types require to save some properties at the insertion process. - * This method should return false if it does not handle the process. + * This method allows the auxiliary information the option of manipulating + * the tree in order to perform the insertion process. If the auxiliary + * information does that, then the method should return true; if the method + * returns false the RectangleTree performs its default behavior. + * @param node The node in which the point is being inserted. + * @param point The global number of the point being inserted. */ bool HandlePointInsertion(TreeType* , const size_t) { @@ -52,7 +57,14 @@ class XTreeAuxiliaryInformation /** * Some tree types require to save some properties at the insertion process. - * This method should return false if it does not handle the process. + * This method allows the auxiliary information the option of manipulating + * the tree in order to perform the insertion process. If the auxiliary + * information does that, then the method should return true; if the method + * returns false the RectangleTree performs its default behavior. + * @param node The node in which the nodeToInsert is being inserted. + * @param nodeToInsert The node being inserted. + * @param insertionLevel The level of the tree at which the nodeToInsert + * should be inserted. */ bool HandleNodeInsertion(TreeType* , TreeType *,bool) { @@ -61,7 +73,12 @@ class XTreeAuxiliaryInformation /** * Some tree types require to save some properties at the deletion process. - * This method should return false if it does not handle the process. + * This method allows the auxiliary information the option of manipulating + * the tree in order to perform the deletion process. If the auxiliary + * information does that, then the method should return true; if the method + * returns false the RectangleTree performs its default behavior. + * @param node The node from which the point is being deleted. + * @param localIndex The local index of the point being deleted. */ bool HandlePointDeletion(TreeType* , const size_t) { @@ -70,7 +87,12 @@ class XTreeAuxiliaryInformation /** * Some tree types require to save some properties at the deletion process. - * This method should return false if it does not handle the process. + * This method allows the auxiliary information the option of manipulating + * the tree in order to perform the deletion process. If the auxiliary + * information does that, then the method should return true; if the method + * returns false the RectangleTree performs its default behavior. + * @param node The node from which the node is being deleted. + * @param nodeIndex The local index of the node being deleted. */ bool HandleNodeRemoval(TreeType* , const size_t) { @@ -78,8 +100,10 @@ class XTreeAuxiliaryInformation } /** - * Some tree types require to propagate the information downward. - * This method should return false if this is not the case. + * Some tree types require to propagate the information upward. + * This method should return false if this is not the case. If true is + * returned, the update will be propogated upward. + * @param node The node in which the auxiliary information being update. */ bool UpdateAuxiliaryInfo(TreeType* ) { @@ -87,18 +111,8 @@ class XTreeAuxiliaryInformation } /** - * Copy the auxiliary information from one node to another. - * @param dst The node to which the information being copied. - * @param src The node from which the information being copied. + * Nullify the auxiliary information in order to prevent an invalid free. */ - void Copy(TreeType* dst,TreeType* src) - { - dst->AuxiliaryInfo().NormalNodeMaxNumChildren() = - src->AuxiliaryInfo().NormalNodeMaxNumChildren(); - - dst->AuxiliaryInfo().SplitHistory() = src->AuxiliaryInfo().SplitHistory(); - } - void NullifyData() { } diff --git a/src/mlpack/tests/rectangle_tree_test.cpp b/src/mlpack/tests/rectangle_tree_test.cpp index ec85aeb7e5..e165a75c05 100644 --- a/src/mlpack/tests/rectangle_tree_test.cpp +++ b/src/mlpack/tests/rectangle_tree_test.cpp @@ -570,7 +570,7 @@ BOOST_AUTO_TEST_CASE(XTreeTraverserTest) } } -BOOST_AUTO_TEST_CASE(DiscreteHilbertRTreeTraverserTest) +BOOST_AUTO_TEST_CASE(HilbertRTreeTraverserTest) { arma::mat dataset; @@ -582,14 +582,14 @@ BOOST_AUTO_TEST_CASE(DiscreteHilbertRTreeTraverserTest) arma::Mat neighbors2; arma::mat distances2; - typedef DiscreteHilbertRTree,arma::mat> TreeType; TreeType hilbertRTree(dataset, 20, 6, 5, 2, 0); // Nearest neighbor search with the Hilbert R tree. NeighborSearch, arma::mat, - DiscreteHilbertRTree > knn1(&hilbertRTree, true); + HilbertRTree > knn1(&hilbertRTree, true); BOOST_REQUIRE_EQUAL(hilbertRTree.NumDescendants(), numP); @@ -611,50 +611,6 @@ BOOST_AUTO_TEST_CASE(DiscreteHilbertRTreeTraverserTest) } } -/* -BOOST_AUTO_TEST_CASE(RecursiveHilbertRTreeTraverserTest) -{ - arma::mat dataset; - - const int numP = 1000; - - dataset.randu(8, numP); // 1000 points in 8 dimensions. - arma::Mat neighbors1; - arma::mat distances1; - arma::Mat neighbors2; - arma::mat distances2; - - typedef RecursiveHilbertRTree,arma::mat> TreeType; - TreeType hilbertRTree(dataset, 20, 6, 5, 2, 0); - - // Nearest neighbor search with the Hilbert R tree. - - NeighborSearch, arma::mat, - RecursiveHilbertRTree > knn1(&hilbertRTree, true); - - BOOST_REQUIRE_EQUAL(hilbertRTree.NumDescendants(), numP); - - CheckSync(hilbertRTree); - CheckContainment(hilbertRTree); - CheckExactContainment(hilbertRTree); - CheckHierarchy(hilbertRTree); - - knn1.Search(5, neighbors1, distances1); - - // Nearest neighbor search the naive way. - KNN knn2(dataset, true, true); - - knn2.Search(5, neighbors2, distances2); - - for (size_t i = 0; i < neighbors1.size(); i++) - { - BOOST_REQUIRE_EQUAL(neighbors1[i], neighbors2[i]); - BOOST_REQUIRE_EQUAL(distances1[i], distances2[i]); - } -} -*/ - template void CheckHilbertOrdering(TreeType* tree) { @@ -691,12 +647,12 @@ void CheckHilbertOrdering(TreeType* tree) } } -BOOST_AUTO_TEST_CASE(DiscreteHilbertOrderingTest) +BOOST_AUTO_TEST_CASE(HilbertRTreeOrderingTest) { arma::mat dataset; dataset.randu(8, 1000); // 1000 points in 8 dimensions. - typedef DiscreteHilbertRTree,arma::mat> TreeType; TreeType hilbertRTree(dataset, 20, 6, 5, 2, 0); @@ -719,7 +675,7 @@ void CheckDiscreteHilbertValueSync(const TreeType* tree) arma::Col pointValue = HilbertValue::CalculateValue(tree->Dataset().col(tree->Points()[i])); - int equal = HilbertValue::CompareValues(value.LocalDataset()->col(i), pointValue); + int equal = HilbertValue::CompareValues(value.LocalHilbertValues()->col(i), pointValue); BOOST_REQUIRE_EQUAL(equal, 0); } @@ -734,27 +690,13 @@ BOOST_AUTO_TEST_CASE(DiscreteHilbertValueSyncTest) arma::mat dataset; dataset.randu(8, 1000); // 1000 points in 8 dimensions. - typedef DiscreteHilbertRTree,arma::mat> TreeType; TreeType hilbertRTree(dataset, 20, 6, 5, 2, 0); CheckDiscreteHilbertValueSync(&hilbertRTree); } -/* -BOOST_AUTO_TEST_CASE(RecursiveHilbertOrderingTest) -{ - arma::mat dataset; - dataset.randu(8, 1000); // 1000 points in 8 dimensions. - - typedef RecursiveHilbertRTree,arma::mat> TreeType; - TreeType hilbertRTree(dataset, 20, 6, 5, 2, 0); - - CheckHilbertOrdering(&hilbertRTree); -} -*/ - BOOST_AUTO_TEST_CASE(DiscreteHilbertValueTest) { arma::vec point01(1);