From 260f711f2cdf69880355fea905b2e44c2dfbf54b Mon Sep 17 00:00:00 2001 From: MarcosPividori Date: Thu, 28 Jul 2016 18:26:38 -0300 Subject: [PATCH] Add support for rvalue references when setting a given reference tree in NeighborSearch class. --- .../neighbor_search/neighbor_search.hpp | 46 +++++++++++++++++-- .../neighbor_search/neighbor_search_impl.hpp | 37 ++++++++++++++- .../methods/neighbor_search/ns_model_impl.hpp | 16 ++----- 3 files changed, 84 insertions(+), 15 deletions(-) diff --git a/src/mlpack/methods/neighbor_search/neighbor_search.hpp b/src/mlpack/methods/neighbor_search/neighbor_search.hpp index e3871f3024..f9806af70f 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search.hpp @@ -234,9 +234,10 @@ class NeighborSearch * * Deprecated. Will be removed in mlpack 3.0.0. * - * There is no copying of the data matrices in this constructor (because - * tree-building is not necessary), so this is the constructor to use when - * copies absolutely must be avoided. + * This method won't take ownership of the given tree. There is no copying of + * the data matrices in this constructor (because tree-building is not + * necessary), so this is the constructor to use when copies absolutely must + * be avoided. * * @note * Mapping the points of the matrix back to their original indices is not done @@ -256,6 +257,36 @@ class NeighborSearch const double epsilon = 0, const MetricType metric = MetricType()); + /** + * Initialize the NeighborSearch object with the given pre-constructed + * reference tree (this is the tree built on the points that will be + * searched). Optionally, choose to use single-tree mode. Naive mode is not + * available as an option for this constructor. Additionally, an instantiated + * distance metric can be given, for cases where the distance metric holds + * data. + * + * This method will take ownership of the given tree. There is no copying of + * the data matrices (because tree-building is not necessary), so this is the + * constructor to use when copies absolutely must be avoided. + * + * @note + * Mapping the points of the matrix back to their original indices is not done + * when this constructor is used, so if the tree type you are using maps + * points (like BinarySpaceTree), then you will have to perform the re-mapping + * manually. + * @endnote + * + * @param referenceTree Pre-built tree for reference points. + * @param singleMode Whether single-tree computation should be used (as + * opposed to dual-tree computation). + * @param epsilon Relative approximate error (non-negative). + * @param metric Instantiated distance metric. + */ + NeighborSearch(Tree&& referenceTree, + const bool singleMode = false, + const double epsilon = 0, + const MetricType metric = MetricType()); + /** * Create a NeighborSearch object without any reference data. If Search() is * called before a reference set is set with Train(), an exception will be @@ -308,6 +339,15 @@ class NeighborSearch */ void Train(Tree* referenceTree); + /** + * Set the reference tree to a new reference tree. + * + * This method will take ownership of the given tree. + * + * @param referenceTree Pre-built tree for reference points. + */ + void Train(Tree&& referenceTree); + /** * For each point in the query set, compute the nearest neighbors and store * the output in the given matrices. The matrices will be set to the size of diff --git a/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp b/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp index ac064183ae..24fa9b2bf5 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp @@ -314,6 +314,26 @@ SingleTreeTraversalType>::NeighborSearch(Tree* referenceTree, throw std::invalid_argument("epsilon must be non-negative"); } +// Construct the object. +template class TreeType, + template class DualTreeTraversalType, + template class SingleTreeTraversalType> +NeighborSearch::NeighborSearch(Tree&& referenceTree, + const bool singleMode, + const double epsilon, + const MetricType metric) : + NeighborSearch(new Tree(std::move(referenceTree)), singleMode, epsilon, + metric) +{ + treeOwner = true; +} + // Construct the object without a reference dataset. template::Train(Tree* referenceTree) throw std::invalid_argument("cannot train on given reference tree when " "naive search (without trees) is desired"); - if (treeOwner && referenceTree) + if (treeOwner && this->referenceTree) delete this->referenceTree; if (setOwner && referenceSet) delete this->referenceSet; @@ -491,6 +511,21 @@ DualTreeTraversalType, SingleTreeTraversalType>::Train(Tree* referenceTree) setOwner = false; } +template class TreeType, + template class DualTreeTraversalType, + template class SingleTreeTraversalType> +void NeighborSearch::Train(Tree&& referenceTree) +{ + Train(new Tree(std::move(referenceTree))); + treeOwner = true; +} + /** * Computes the best neighbors and stores them in resultingNeighbors and * distances. diff --git a/src/mlpack/methods/neighbor_search/ns_model_impl.hpp b/src/mlpack/methods/neighbor_search/ns_model_impl.hpp index 15917304f0..5c16bca9c4 100644 --- a/src/mlpack/methods/neighbor_search/ns_model_impl.hpp +++ b/src/mlpack/methods/neighbor_search/ns_model_impl.hpp @@ -176,11 +176,8 @@ void TrainVisitor::operator ()(SpillKNN* ns) const ns->Train(std::move(referenceSet)); else { - typename SpillKNN::Tree* tree = new typename SpillKNN::Tree( - std::move(referenceSet), tau, leafSize, rho); - ns->Train(tree); - // Give the model ownership of the tree. - ns->treeOwner = true; + typename SpillKNN::Tree tree(std::move(referenceSet), tau, leafSize, rho); + ns->Train(std::move(tree)); } } else @@ -197,13 +194,10 @@ void TrainVisitor::TrainLeaf(NSType* ns) const else { std::vector oldFromNewReferences; - typename NSType::Tree* tree = - new typename NSType::Tree(std::move(referenceSet), + typename NSType::Tree referenceTree(std::move(referenceSet), oldFromNewReferences, leafSize); - ns->Train(tree); - - // Give the model ownership of the tree and the mappings. - ns->treeOwner = true; + ns->Train(std::move(referenceTree)); + // Set the mappings. ns->oldFromNewReferences = std::move(oldFromNewReferences); } }