Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify NSModel to use boost variant. #693

Merged
merged 6 commits into from Jun 20, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/mlpack/methods/neighbor_search/neighbor_search.hpp
Expand Up @@ -27,8 +27,7 @@ namespace neighbor /** Neighbor-search routines. These include
* searches. */ {

// Forward declaration.
template<typename SortPolicy>
class NSModel;
class TrainVisitor;

/**
* The NeighborSearch class is a template class for performing distance-based
Expand Down Expand Up @@ -308,7 +307,7 @@ class NeighborSearch
bool treeNeedsReset;

//! The NSModel class should have access to internal members.
friend class NSModel<SortPolicy>;
friend class TrainVisitor;
}; // class NeighborSearch

} // namespace neighbor
Expand Down
153 changes: 134 additions & 19 deletions src/mlpack/methods/neighbor_search/ns_model.hpp
Expand Up @@ -13,12 +13,24 @@
#include <mlpack/core/tree/binary_space_tree.hpp>
#include <mlpack/core/tree/cover_tree.hpp>
#include <mlpack/core/tree/rectangle_tree.hpp>

#include <boost/variant.hpp>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add 'variant' to the list of Boost libraries we require in the documentation and in the root CMakeLists.txt?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a header only library, so we don't need to include it in CMakeList.txt.
I can see that all boost dependencies mentioned in the README file: program_options, math_c99, unit_test_framework, and serialization, are not header only. Should I include variant there anyway? even if it is header only?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, it is header only. I am not sure if it is possible to have a Boost installation where some of the header-only libraries (but not all) are available; I haven't played with b2 (Boost's build system) enough recently to be sure. If it's possible to have a Boost installation with some of the header-only libraries omitted, then we should include variant in there; otherwise, I don't think it's necessary. But I'm not sure whether or not that's possible...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a quick search, it looks like there is no such option to omit some header files...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, looks like there is nothing special we need to do with our CMake configuration for this change then.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but we don't have to add boost::variant to required libraries?? Even if its header only we need to make sure the headers are present. Or is it the part of basic boost which is included in every boost package?? I mean if I install just boost::math in ubuntu with apt-get do I get boost::variant??

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see a note about this in boost's documentation: [ref]
"Other Packages
RedHat, Debian, and other distribution packagers supply Boost library packages, however you may need to adapt these instructions if you use third-party packages, because their creators usually choose to break Boost up into several packages, reorganize the directory structure of the Boost distribution, and/or rename the library binaries. If you have any trouble, we suggest using an official Boost distribution from SourceForge. "

I am not sure. But it looks like all partial packages depends on libboost-dev package, so they will finally include all headers files.
For example: libboost-program-options-dev --depends on--> libbooost-dev

#include "neighbor_search.hpp"

namespace mlpack {
namespace neighbor {

template<typename SortPolicy,
template<typename TreeMetricType,
typename TreeStatType,
typename TreeMatType> class TreeType>
using NSType = NeighborSearch<SortPolicy,
metric::EuclideanDistance,
arma::mat,
TreeType,
TreeType<metric::EuclideanDistance,
NeighborSearchStat<SortPolicy>,
arma::mat>::template DualTreeTraverser>;

template<typename SortPolicy>
struct NSModelName
{
Expand All @@ -37,6 +49,121 @@ struct NSModelName<FurthestNeighborSort>
static const std::string Name() { return "furthest_neighbor_search_model"; }
};

class SearchKVisitor : public boost::static_visitor<void>
{
private:
const size_t k;
arma::Mat<size_t>& neighbors;
arma::mat& distances;

public:
template<typename NSType>
void operator()(NSType *ns) const;

SearchKVisitor(const size_t k,
arma::Mat<size_t>& neighbors,
arma::mat& distances);
};

class SearchVisitor : public boost::static_visitor<void>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should change the name of this class and SearchKVisitor to BichromaticSearchVisitor and MonochromaticSearchVisitor, respectively, for clarity? I couldn't think of any shorter names to differentiate there, but maybe you have a better idea? The root of my concern is that Search and SearchK don't really describe the difference in what is going on.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I agree. I will change this.

{
private:
const arma::mat& querySet;
const size_t k;
arma::Mat<size_t>& neighbors;
arma::mat& distances;
const size_t leafSize;

template<typename NSType>
void SearchLeaf(NSType *ns) const;

public:
template<typename SortPolicy,
template<typename TreeMetricType,
typename TreeStatType,
typename TreeMatType> class TreeType>
void operator()(NSType<SortPolicy,TreeType> *ns) const;

template<typename SortPolicy>
void operator()(NSType<SortPolicy,tree::KDTree> *ns) const;

template<typename SortPolicy>
void operator()(NSType<SortPolicy,tree::BallTree> *ns) const;

SearchVisitor(const arma::mat& querySet,
const size_t k,
arma::Mat<size_t>& neighbors,
arma::mat& distances,
const size_t leafSize);
};

class TrainVisitor : public boost::static_visitor<void>
{
private:
arma::mat&& referenceSet;
size_t leafSize;

template<typename NSType>
void TrainLeaf(NSType* ns) const;

public:
template<typename SortPolicy,
template<typename TreeMetricType,
typename TreeStatType,
typename TreeMatType> class TreeType>
void operator()(NSType<SortPolicy,TreeType> *ns) const;

template<typename SortPolicy>
void operator()(NSType<SortPolicy,tree::KDTree> *ns) const;

template<typename SortPolicy>
void operator()(NSType<SortPolicy,tree::BallTree> *ns) const;

TrainVisitor(arma::mat&& referenceSet, const size_t leafSize);
};

class SingleModeVisitor : public boost::static_visitor<bool&>
{
public:
template<typename NSType>
bool& operator()(NSType *ns) const;
};

class NaiveVisitor : public boost::static_visitor<bool&>
{
public:
template<typename NSType>
bool& operator()(NSType *ns) const;
};

class ReferenceSetVisitor : public boost::static_visitor<const arma::mat&>
{
public:
template<typename NSType>
const arma::mat& operator()(NSType *ns) const;
};

class DeleteVisitor : public boost::static_visitor<void>
{
public:
template<typename NSType>
void operator()(NSType *ns) const;
};

template<typename Archive>
class SerializeVisitor : public boost::static_visitor<void>
{
private:
Archive& ar;
const std::string& name;

public:
template<typename NSType>
void operator()(NSType *ns) const;

SerializeVisitor(Archive& ar, const std::string& name);
};

template<typename SortPolicy>
class NSModel
{
Expand All @@ -59,24 +186,12 @@ class NSModel
bool randomBasis;
arma::mat q;

template<template<typename TreeMetricType,
typename TreeStatType,
typename TreeMatType> class TreeType>
using NSType = NeighborSearch<SortPolicy,
metric::EuclideanDistance,
arma::mat,
TreeType,
TreeType<metric::EuclideanDistance,
NeighborSearchStat<SortPolicy>,
arma::mat>::template DualTreeTraverser>;

// Only one of these pointers will be non-NULL.
NSType<tree::KDTree>* kdTreeNS;
NSType<tree::StandardCoverTree>* coverTreeNS;
NSType<tree::RTree>* rTreeNS;
NSType<tree::RStarTree>* rStarTreeNS;
NSType<tree::BallTree>* ballTreeNS;
NSType<tree::XTree>* xTreeNS;
boost::variant<NSType<SortPolicy, tree::KDTree>*,
NSType<SortPolicy, tree::StandardCoverTree>*,
NSType<SortPolicy, tree::RTree>*,
NSType<SortPolicy, tree::RStarTree>*,
NSType<SortPolicy, tree::BallTree>*,
NSType<SortPolicy, tree::XTree>*> nSearch;

public:
/**
Expand Down