Fixed comments.

Removed RecursiveHilbertValue.
Added a template parameter splitOrder.
This commit is contained in:
Mikhail Lozhnikov
2016-06-23 23:04:35 +03:00
parent f9127cea62
commit 64525dea5a
15 changed files with 170 additions and 775 deletions
-2
View File
@@ -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
-1
View File
@@ -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"
@@ -139,11 +139,21 @@ class DiscreteHilbertValue
*/
template<typename TreeType>
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<typename TreeType>
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<typename TreeType>
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<HilbertElemType>* LocalDataset() const
{ return localDataset; }
const arma::Mat<HilbertElemType>* LocalHilbertValues() const
{ return localHilbertValues; }
//! Modify the dataset
arma::Mat<HilbertElemType>*& LocalDataset() { return localDataset; }
arma::Mat<HilbertElemType>*& LocalHilbertValues()
{ return localHilbertValues; }
//! Modify the valueToInsert
arma::Col<HilbertElemType>* 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<HilbertElemType>* 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<HilbertElemType>* 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<HilbertElemType>* 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<HilbertElemType>* valueToInsert;
//! Indicates that the node owns the valueToInsert.
bool ownsValueToInsert;
public:
template<typename Archive>
@@ -15,8 +15,8 @@ namespace tree /** Trees and tree-building procedures. */ {
template<typename TreeElemType>
DiscreteHilbertValue<TreeElemType>::DiscreteHilbertValue() :
localDataset(NULL),
ownsLocalDataset(false),
localHilbertValues(NULL),
ownsLocalHilbertValues(false),
numValues(0),
valueToInsert(NULL),
ownsValueToInsert(false)
@@ -27,8 +27,8 @@ DiscreteHilbertValue<TreeElemType>::DiscreteHilbertValue() :
template<typename TreeElemType>
DiscreteHilbertValue<TreeElemType>::~DiscreteHilbertValue()
{
if (ownsLocalDataset)
delete localDataset;
if (ownsLocalHilbertValues)
delete localHilbertValues;
if (ownsValueToInsert)
delete valueToInsert;
}
@@ -36,8 +36,8 @@ DiscreteHilbertValue<TreeElemType>::~DiscreteHilbertValue()
template<typename TreeElemType>
template<typename TreeType>
DiscreteHilbertValue<TreeElemType>::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<TreeElemType>::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<HilbertElemType>(tree->Dataset().n_rows,
localHilbertValues = new arma::Mat<HilbertElemType>(tree->Dataset().n_rows,
tree->MaxLeafSize() + 1);
}
@@ -65,8 +65,8 @@ DiscreteHilbertValue<TreeElemType>::DiscreteHilbertValue(const TreeType* tree) :
template<typename TreeElemType>
DiscreteHilbertValue<TreeElemType>::
DiscreteHilbertValue(const DiscreteHilbertValue& other) :
localDataset(const_cast<arma::Mat<HilbertElemType>*>(other.LocalDataset())),
ownsLocalDataset(other.ownsLocalDataset),
localHilbertValues(const_cast<arma::Mat<HilbertElemType>*>(other.LocalHilbertValues())),
ownsLocalHilbertValues(other.ownsLocalHilbertValues),
numValues(other.NumValues()),
valueToInsert(const_cast<arma::Col<HilbertElemType>*>(other.ValueToInsert())),
ownsValueToInsert(false)
@@ -216,15 +216,15 @@ int DiscreteHilbertValue<TreeElemType>::
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<typename TreeElemType>
@@ -242,10 +242,10 @@ CompareWith(const VecType& pt,
{
arma::Col<HilbertElemType> 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<typename TreeElemType>
@@ -254,10 +254,10 @@ int DiscreteHilbertValue<TreeElemType>::
CompareWithCachedPoint(const VecType& ,
typename boost::enable_if<IsVector<VecType>>*) const
{
if (!HasValue())
if (numValues == 0)
return -1;
return CompareValues(localDataset->col(numValues - 1),*valueToInsert);
return CompareValues(localHilbertValues->col(numValues - 1),*valueToInsert);
}
template<typename TreeElemType>
@@ -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<TreeElemType>::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<typename TreeElemType>
template<typename TreeType>
void DiscreteHilbertValue<TreeElemType>::Copy(TreeType* dst, TreeType* src)
DiscreteHilbertValue<TreeElemType>& DiscreteHilbertValue<TreeElemType>::
operator = (const DiscreteHilbertValue& val)
{
DiscreteHilbertValue<TreeElemType> &dstVal = dst->AuxiliaryInfo().HilbertValue();
DiscreteHilbertValue<TreeElemType> &srcVal = src->AuxiliaryInfo().HilbertValue();
localHilbertValues = const_cast<arma::Mat<HilbertElemType>* >
(val.LocalHilbertValues());
ownsLocalHilbertValues = false;
numValues = val.NumValues();
dst.LocalDataset() = src.LocalDataset();
dst.NumValues() = src.NumValues();
return *this;
}
template<typename TreeElemType>
void DiscreteHilbertValue<TreeElemType>::NullifyData()
{
ownsLocalDataset = false;
ownsLocalHilbertValues = false;
}
template<typename TreeElemType>
@@ -376,7 +377,7 @@ void DiscreteHilbertValue<TreeElemType>::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<TreeElemType>::UpdateLargestValue(TreeType* node)
template<typename TreeElemType>
template<typename TreeType>
void DiscreteHilbertValue<TreeElemType>::
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<HilbertElemType> tmp(localDataset->n_rows,numPoints);
arma::Mat<HilbertElemType> 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<typename TreeElemType>
bool DiscreteHilbertValue<TreeElemType>::HasValue() const
{
return numValues > 0;
}
template<typename TreeElemType>
template<typename Archive>
void DiscreteHilbertValue<TreeElemType>::
@@ -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");
@@ -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.
@@ -40,14 +40,6 @@ HilbertRTreeAuxiliaryInformation(const HilbertRTreeAuxiliaryInformation& other)
{
};
template<typename TreeType,
template<typename> class HilbertValueType>
HilbertRTreeAuxiliaryInformation<TreeType, HilbertValueType>::
~HilbertRTreeAuxiliaryInformation()
{
}
template<typename TreeType,
template<typename> class HilbertValueType>
@@ -158,14 +150,6 @@ UpdateAuxiliaryInfo(TreeType* node)
return false;
}
template<typename TreeType,
template<typename> class HilbertValueType>
void HilbertRTreeAuxiliaryInformation<TreeType, HilbertValueType>::
Copy(TreeType* dst, TreeType* src)
{
hilbertValue.Copy(dst,src);
}
template<typename TreeType,
template<typename> class HilbertValueType>
void HilbertRTreeAuxiliaryInformation<TreeType, HilbertValueType>::
@@ -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<size_t splitOrder = 2>
class HilbertRTreeSplit
{
public:
@@ -14,8 +14,9 @@
namespace mlpack {
namespace tree {
template<size_t splitOrder>
template<typename TreeType>
void HilbertRTreeSplit::
void HilbertRTreeSplit<splitOrder>::
SplitLeafNode(TreeType* tree, std::vector<bool>& relevels)
{
// If we are splitting the root node, we need will do things differently so
@@ -30,7 +31,7 @@ SplitLeafNode(TreeType* tree, std::vector<bool>& 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<bool>& relevels)
RedistributePointsEvenly(parent, firstSibling, lastSibling);
if (parent->NumChildren() == parent->MaxNumChildren() + 1)
HilbertRTreeSplit::SplitNonLeafNode(parent, relevels);
SplitNonLeafNode(parent, relevels);
}
template<size_t splitOrder>
template<typename TreeType>
bool HilbertRTreeSplit::
bool HilbertRTreeSplit<splitOrder>::
SplitNonLeafNode(TreeType* tree,std::vector<bool>& relevels)
{
// If we are splitting the root node, we need will do things differently so
@@ -93,7 +95,7 @@ SplitNonLeafNode(TreeType* tree,std::vector<bool>& 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<bool>& relevels)
RedistributeNodesEvenly(parent, firstSibling, lastSibling);
if (parent->NumChildren() == parent->MaxNumChildren() + 1)
HilbertRTreeSplit::SplitNonLeafNode(parent, relevels);
SplitNonLeafNode(parent, relevels);
return false;
}
template<size_t splitOrder>
template<typename TreeType>
bool HilbertRTreeSplit::FindCooperatingSiblings(TreeType *parent, size_t iTree,
bool HilbertRTreeSplit<splitOrder>::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<size_t splitOrder>
template<typename TreeType>
void HilbertRTreeSplit::
void HilbertRTreeSplit<splitOrder>::
RedistributeNodesEvenly(const TreeType *parent,
size_t firstSibling, size_t lastSibling)
{
@@ -254,8 +258,9 @@ RedistributeNodesEvenly(const TreeType *parent,
}
}
template<size_t splitOrder>
template<typename TreeType>
void HilbertRTreeSplit::
void HilbertRTreeSplit<splitOrder>::
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;
@@ -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()
{ }
@@ -881,7 +881,7 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
points[i] = child->Points()[i];
}
auxiliaryInfo.Copy(this,child);
auxiliaryInfo = child->AuxiliaryInfo();
count = child->Count();
child->SoftDelete();
@@ -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 <mlpack/core.hpp>
namespace mlpack {
namespace tree /** Trees and tree-building procedures. */ {
constexpr int recursionDepth = 500;
template<typename TreeElemType>
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<typename TreeType>
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<TreeElemType> Lo;
//! High bound
arma::Col<TreeElemType> Hi;
//! Permutation of axes
std::vector<size_t> permutation;
//! Indicates that the axis should be inverted
std::vector<bool> inversion;
//! Indicates that the result should be inverted
arma::Col<TreeElemType> center;
arma::Col<TreeElemType> vec;
std::vector<int> bits;
std::vector<int> 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<TreeElemType>::lowest();
Hi[i] = std::numeric_limits<TreeElemType>::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<typename VecType1, typename VecType2>
static int ComparePoints(const VecType1& pt1, const VecType2& pt2,
typename boost::enable_if<IsVector<VecType1>>* = 0,
typename boost::enable_if<IsVector<VecType2>>* = 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<typename VecType>
int CompareWith(const VecType& point,
typename boost::enable_if<IsVector<VecType>>* = 0) const;
template<typename VecType>
int CompareWithCachedPoint(const VecType& point,
typename boost::enable_if<IsVector<VecType>>* = 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<typename TreeType, typename VecType>
size_t InsertPoint(TreeType* node, const VecType& point,
typename boost::enable_if<IsVector<VecType>>* = 0);
/**
* Update the largest Hilbert value of the node.
* @param node The node being inserted.
*/
template<typename TreeType>
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<typename TreeType>
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<typename TreeType>
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<typename TreeType>
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<typename TreeType>
void UpdateLargestValue(TreeType* node);
template<typename TreeType>
void UpdateHilbertValues(TreeType* parent, size_t firstSibling,
size_t lastSibling);
//! Return the largest Hilbert value
const arma::Col<TreeElemType>* LargestValue() const { return largestValue; }
//! Modify the largest Hilbert value
arma::Col<TreeElemType>*& LargestValue() { return largestValue; }
private:
//! The point that has the largest Hilbert value.
arma::Col<TreeElemType>* 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<typename VecType1, typename VecType2>
static int ComparePoints(const VecType1& pt1, const VecType2& pt2,
CompareStruct& comp, typename boost::enable_if<IsVector<VecType1>>* = 0,
typename boost::enable_if<IsVector<VecType2>>* = 0);
public:
template<typename Archive>
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
@@ -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<typename TreeElemType>
RecursiveHilbertValue<TreeElemType>::RecursiveHilbertValue() :
largestValue(NULL),
ownsLargestValue(false),
hasLargestValue(false)
{
}
template<typename TreeElemType>
template<typename TreeType>
RecursiveHilbertValue<TreeElemType>::
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<TreeElemType>(tree->Dataset().n_rows);
}
}
template<typename TreeElemType>
RecursiveHilbertValue<TreeElemType>::
RecursiveHilbertValue(const RecursiveHilbertValue& other) :
largestValue(const_cast<arma::Col<TreeElemType>*>(other.LargestValue())),
ownsLargestValue(other.ownsLargestValue),
hasLargestValue(other.hasLargestValue)
{
}
template<typename TreeElemType>
RecursiveHilbertValue<TreeElemType>::~RecursiveHilbertValue()
{
if (ownsLargestValue)
delete largestValue;
}
template<typename TreeElemType>
template<typename VecType1, typename VecType2>
int RecursiveHilbertValue<TreeElemType>::
ComparePoints(const VecType1& pt1, const VecType2& pt2,
typename boost::enable_if<IsVector<VecType1>>*,
typename boost::enable_if<IsVector<VecType2>>* )
{
size_t dim = pt1.n_rows;
CompareStruct comp(dim);
return ComparePoints(pt1, pt2, comp);
};
template<typename TreeElemType>
int RecursiveHilbertValue<TreeElemType>::
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<typename TreeElemType>
int RecursiveHilbertValue<TreeElemType>::
CompareWith(const RecursiveHilbertValue& val) const
{
if (!hasLargestValue)
return -1;
return CompareValues(*this, val);
}
template<typename TreeElemType>
template<typename VecType>
int RecursiveHilbertValue<TreeElemType>::
CompareWith(const VecType& point,
typename boost::enable_if<IsVector<VecType>>* ) const
{
if (!hasLargestValue)
return -1;
return ComparePoints(*largestValue, point);
}
template<typename TreeElemType>
template<typename VecType>
int RecursiveHilbertValue<TreeElemType>::
CompareWithCachedPoint(const VecType& point,
typename boost::enable_if<IsVector<VecType>>* ) const
{
return CompareWith(point);
}
template<typename TreeElemType>
template<typename VecType1, typename VecType2>
int RecursiveHilbertValue<TreeElemType>::
ComparePoints(const VecType1& pt1, const VecType2& pt2,
CompareStruct& comp, typename boost::enable_if<IsVector<VecType1>>*,
typename boost::enable_if<IsVector<VecType2>>* )
{
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<typename TreeElemType>
template<typename TreeType, typename VecType>
size_t RecursiveHilbertValue<TreeElemType>::
InsertPoint(TreeType* node, const VecType& point,
typename boost::enable_if<IsVector<VecType>>* )
{
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<typename TreeElemType>
template<typename TreeType>
void RecursiveHilbertValue<TreeElemType>::InsertNode(TreeType* node)
{
if (CompareWith(node->AuxiliaryInfo().HilbertValue()) < 0)
{
largestValue = node->AuxiliaryInfo().HilbertValue().LargestValue();
hasLargestValue = true;
}
}
template<typename TreeElemType>
template<typename TreeType>
void RecursiveHilbertValue<TreeElemType>::
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<typename TreeElemType>
template<typename TreeType>
void RecursiveHilbertValue<TreeElemType>::
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<typename TreeElemType>
template<typename TreeType>
void RecursiveHilbertValue<TreeElemType>::Copy(TreeType* dst, TreeType* src)
{
dst->AuxiliaryInfo().HilbertValue().LargestValue() =
src->AuxiliaryInfo().HilbertValue().LargestValue();
dst->AuxiliaryInfo().HilbertValue().hasLargestValue =
src->AuxiliaryInfo().HilbertValue().hasLargestValue;
}
template<typename TreeElemType>
void RecursiveHilbertValue<TreeElemType>::NullifyData()
{
ownsLargestValue = false;
}
template<typename TreeElemType>
template<typename TreeType>
void RecursiveHilbertValue<TreeElemType>::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<typename TreeElemType>
template<typename TreeType>
void RecursiveHilbertValue<TreeElemType>::
UpdateHilbertValues(TreeType* parent, size_t firstSibling, size_t lastSibling)
{
for (size_t i = firstSibling; i<= lastSibling; i++)
{
RecursiveHilbertValue<TreeElemType> &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<typename TreeElemType>
template<typename Archive>
void RecursiveHilbertValue<TreeElemType>::
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
@@ -119,26 +119,14 @@ using XTree = RectangleTree<MetricType,
* @see @ref trees, RTree, DiscreteHilbertRTree
*/
template<typename TreeType>
using RecursiveHilbertRTreeAuxiliaryInformation =
HilbertRTreeAuxiliaryInformation<TreeType,RecursiveHilbertValue>;
template<typename MetricType, typename StatisticType, typename MatType>
using RecursiveHilbertRTree = RectangleTree<MetricType,
StatisticType,
MatType,
HilbertRTreeSplit,
HilbertRTreeDescentHeuristic,
RecursiveHilbertRTreeAuxiliaryInformation>;
template<typename TreeType>
using DiscreteHilbertRTreeAuxiliaryInformation =
HilbertRTreeAuxiliaryInformation<TreeType,DiscreteHilbertValue>;
template<typename MetricType, typename StatisticType, typename MatType>
using DiscreteHilbertRTree = RectangleTree<MetricType,
using HilbertRTree = RectangleTree<MetricType,
StatisticType,
MatType,
HilbertRTreeSplit,
HilbertRTreeSplit<2>,
HilbertRTreeDescentHeuristic,
DiscreteHilbertRTreeAuxiliaryInformation>;
@@ -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()
{ }
+7 -65
View File
@@ -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<size_t> neighbors2;
arma::mat distances2;
typedef DiscreteHilbertRTree<EuclideanDistance,
typedef HilbertRTree<EuclideanDistance,
NeighborSearchStat<NearestNeighborSort>,arma::mat> TreeType;
TreeType hilbertRTree(dataset, 20, 6, 5, 2, 0);
// Nearest neighbor search with the Hilbert R tree.
NeighborSearch<NearestNeighborSort, metric::LMetric<2, true>, 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<size_t> neighbors1;
arma::mat distances1;
arma::Mat<size_t> neighbors2;
arma::mat distances2;
typedef RecursiveHilbertRTree<EuclideanDistance,
NeighborSearchStat<NearestNeighborSort>,arma::mat> TreeType;
TreeType hilbertRTree(dataset, 20, 6, 5, 2, 0);
// Nearest neighbor search with the Hilbert R tree.
NeighborSearch<NearestNeighborSort, metric::LMetric<2, true>, 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<typename TreeType>
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<EuclideanDistance,
typedef HilbertRTree<EuclideanDistance,
NeighborSearchStat<NearestNeighborSort>,arma::mat> TreeType;
TreeType hilbertRTree(dataset, 20, 6, 5, 2, 0);
@@ -719,7 +675,7 @@ void CheckDiscreteHilbertValueSync(const TreeType* tree)
arma::Col<HilbertElemType> 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<EuclideanDistance,
typedef HilbertRTree<EuclideanDistance,
NeighborSearchStat<NearestNeighborSort>,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<EuclideanDistance,
NeighborSearchStat<NearestNeighborSort>,arma::mat> TreeType;
TreeType hilbertRTree(dataset, 20, 6, 5, 2, 0);
CheckHilbertOrdering(&hilbertRTree);
}
*/
BOOST_AUTO_TEST_CASE(DiscreteHilbertValueTest)
{
arma::vec point01(1);