From 48a8fe65f2280b5ddba2e046553bfc66c246366a Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 4 May 2012 00:12:44 +0000 Subject: [PATCH] Modify CoverTree API towards a more standard API. It can be used with NeighborSearch now... although it probably will fail miserably. --- src/mlpack/core/tree/cover_tree.hpp | 44 ++++++++++++++++++++++++ src/mlpack/core/tree/cover_tree_impl.hpp | 37 ++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/mlpack/core/tree/cover_tree.hpp b/src/mlpack/core/tree/cover_tree.hpp index a47e1c9734..14d6b8db8c 100644 --- a/src/mlpack/core/tree/cover_tree.hpp +++ b/src/mlpack/core/tree/cover_tree.hpp @@ -10,6 +10,7 @@ #include #include #include "first_point_is_root.hpp" +#include "traversers/single_tree_breadth_first_traverser.hpp" namespace mlpack { namespace tree { @@ -87,6 +88,8 @@ template, class CoverTree { public: + typedef arma::mat Mat; + /** * Create the cover tree with the given dataset and given expansion constant. * The dataset will not be modified during the building procedure (unlike @@ -144,11 +147,32 @@ class CoverTree */ ~CoverTree(); + //! Define this tree's preferred traverser. + template + struct PreferredTraverser + { + typedef SingleTreeBreadthFirstTraverser< + CoverTree, + RuleType + > Type; + }; + //! Get a reference to the dataset. const arma::mat& Dataset() const { return dataset; } //! Get the index of the point which this node represents. size_t Point() const { return point; } + //! For compatibility with other trees; the argument is ignored. + size_t Point(const size_t) const { return point; } + + // Fake + CoverTree* Left() const { return NULL; } + CoverTree* Right() const { return NULL; } + size_t Begin() const { return 0; } + size_t Count() const { return 0; } + size_t End() const { return 0; } + bool IsLeaf() const { return (children.size() == 0); } + size_t NumPoints() const { return 1; } //! Get a particular child node. const CoverTree& Child(const size_t index) const { return *children[index]; } @@ -168,6 +192,26 @@ class CoverTree //! Modify the expansion constant; don't do this, you'll break everything. double& ExpansionConstant() { return expansionConstant; } + //! Get the statistic for this node. + const StatisticType& Stat() const { return stat; } + //! Modify the statistic for this node. + StatisticType& Stat() { return stat; } + + //! Return the minimum distance to another node. + double MinDistance(const CoverTree* other) const; + + //! Return the minimum distance to another point. + double MinDistance(const arma::vec& other) const; + + //! Return the maximum distance to another node. + double MaxDistance(const CoverTree* other) const; + + //! Return the maximum distance to another point. + double MaxDistance(const arma::vec& other) const; + + //! Returns true: this tree does have self-children. + static bool HasSelfChildren() { return true; } + private: //! Reference to the matrix which this tree is built on. const arma::mat& dataset; diff --git a/src/mlpack/core/tree/cover_tree_impl.hpp b/src/mlpack/core/tree/cover_tree_impl.hpp index 216082f9f0..f009dd31b7 100644 --- a/src/mlpack/core/tree/cover_tree_impl.hpp +++ b/src/mlpack/core/tree/cover_tree_impl.hpp @@ -317,6 +317,43 @@ CoverTree::~CoverTree() delete children[i]; } +template +double CoverTree::MinDistance( + const CoverTree* other) const +{ + // Every cover tree node will contain points up to EC^(scale + 1) away. + return MetricType::Evaluate(dataset.col(point), + other->Dataset().col(other->Point())) - + std::pow(expansionConstant, scale + 1) - + std::pow(other->ExpansionConstant(), other->Scale() + 1); +} + +template +double CoverTree::MinDistance( + const arma::vec& other) const +{ + return MetricType::Evaluate(dataset.unsafe_col(point), other) - + std::pow(expansionConstant, scale + 1); +} + +template +double CoverTree::MaxDistance( + const CoverTree* other) const +{ + return MetricType::Evaluate(dataset.col(point), + other->Dataset().col(other->Point())) + + std::pow(expansionConstant, scale + 1) + + std::pow(other->ExpansionConstant(), other->Scale() + 1); +} + +template +double CoverTree::MaxDistance( + const arma::vec& other) const +{ + return MetricType::Evaluate(dataset.unsafe_col(point), other) + + std::pow(expansionConstant, scale + 1); +} + template size_t CoverTree::SplitNearFar( arma::Col& indices,