From 2ddadcc3f26a264e9a16eb940bfbe9183b8cdde8 Mon Sep 17 00:00:00 2001 From: Dongryeol Lee Date: Sun, 9 Mar 2008 00:32:12 +0000 Subject: [PATCH] Separated out the naive algorithm into a separate file. Now algorithms are templatized for different primitive types --- fastlib2/mlpack/range_search/build.py | 4 +- fastlib2/mlpack/range_search/data_aux.h | 41 ++++++ .../range_search/naive_ortho_range_search.h | 129 +++++++++++++++++ .../mlpack/range_search/ortho_range_search.h | 136 ++---------------- .../range_search/ortho_range_search_main.cc | 12 +- fastlib2/mlpack/range_search/range_reader.h | 7 +- 6 files changed, 199 insertions(+), 130 deletions(-) create mode 100644 fastlib2/mlpack/range_search/data_aux.h create mode 100644 fastlib2/mlpack/range_search/naive_ortho_range_search.h diff --git a/fastlib2/mlpack/range_search/build.py b/fastlib2/mlpack/range_search/build.py index f1195f51ea..45ee5cf2fe 100644 --- a/fastlib2/mlpack/range_search/build.py +++ b/fastlib2/mlpack/range_search/build.py @@ -2,7 +2,9 @@ librule( name = "ortho_range_search", sources = [], - headers = ["ortho_range_search.h", + headers = ["data_aux.h", + "naive_ortho_range_search.h", + "ortho_range_search.h", "range_reader.h"], deplibs = ["fastlib:fastlib_int"] ) diff --git a/fastlib2/mlpack/range_search/data_aux.h b/fastlib2/mlpack/range_search/data_aux.h new file mode 100644 index 0000000000..95bc5c863e --- /dev/null +++ b/fastlib2/mlpack/range_search/data_aux.h @@ -0,0 +1,41 @@ +#ifndef DATA_AUX_H +#define DATA_AUX_H + +#include "fastlib/fastlib.h" + +namespace data_aux { + + /** + * Loads a matrix from a file. + * + * This supports any type the Dataset class supports with the + * InitFromFile function: CSV and ARFF. + * + * @code + * Matrix A; + * data::Load("foo.csv", &A); + * @endcode + * + * @param fname the file name to load + * @param matrix a pointer to an uninitialized matrix to load + */ + template + static success_t Load(const char *fname, GenMatrix *matrix) { + Matrix tmp_matrix; + success_t result = data::Load(fname, &tmp_matrix); + + // Allocate the matrix that is to be returned and copy all + // entries. + matrix->Init(tmp_matrix.n_rows(), tmp_matrix.n_cols()); + for(index_t c = 0; c < tmp_matrix.n_cols(); c++) { + for(index_t r = 0; r < tmp_matrix.n_rows(); r++) { + matrix->set(r, c, STATIC_CAST(T, tmp_matrix.get(r, c))); + } + } + + return result; + } + +}; + +#endif diff --git a/fastlib2/mlpack/range_search/naive_ortho_range_search.h b/fastlib2/mlpack/range_search/naive_ortho_range_search.h new file mode 100644 index 0000000000..d7610a3a7f --- /dev/null +++ b/fastlib2/mlpack/range_search/naive_ortho_range_search.h @@ -0,0 +1,129 @@ +/** @file naive_ortho_range_search.h + * + * This file contains an implementation of a naive algorithm for + * orthogonal range search. + * + * @author Dongryeol Lee (dongryel) + */ + +#ifndef NAIVE_ORTHO_RANGE_SEARCH_H +#define NAIVE_ORTHO_RANGE_SEARCH_H + +#include "range_reader.h" +#include "fastlib/fastlib.h" + + +/** @brief Naive orthogonal range search class. + * + * @code + * NaiveOrthoRangeSearch search; + * search.Init(dataset); + * search.Compute(low_coord_limits, high_coord_limits); + * + * ArrayList naive_search_results; + * + * // Make sure that the vector is uninitialized before passing. + * search.get_results(&naive_search_results); + * @endcode + */ +template +class NaiveOrthoRangeSearch { + + // This class object cannot be copied! + FORBID_ACCIDENTAL_COPIES(NaiveOrthoRangeSearch); + + private: + + /** @brief The i-th position of this array tells whether the i-th + * point is in the specified orthogonal range. + */ + ArrayList in_range_; + + /** @brief The dataset. + */ + GenMatrix data_; + + public: + + ////////// Constructor/Destructor ////////// + + /** @brief Constructor which does not do anything. + */ + NaiveOrthoRangeSearch() {} + + /** @brief Destructor which does not do anything. + */ + ~NaiveOrthoRangeSearch() {} + + ////////// Getters/Setters ////////// + + /** @brief Retrieve the result of the search. + * + * @param results An uninitialized vector which will have the boolean + * results representing the search results. + */ + void get_results(ArrayList *results) const { + results->Init(in_range_.size()); + + for(index_t i = 0; i < in_range_.size(); i++) { + (*results)[i] = in_range_[i]; + } + } + + ////////// User-level Functions ////////// + + /** @brief Initialize the computation object. + * + * @param data The data used for orthogonal range search. + */ + void Init(const GenMatrix &data) { + + // copy the incoming data + data_.Copy(data); + + // re-initialize boolean flag + in_range_.Init(data_.n_cols()); + for(index_t i = 0; i < data_.n_cols(); i++) { + in_range_[i] = false; + } + } + + /** @brief The main computation of naive orthogonal range search. + * + * @param low_coord_limits The lower coordinate range of the search window. + * @param high_coord_limits The upper coordinate range of the search + * window. + */ + void Compute(const GenVector &low_coord_limits, + const GenVector &high_coord_limits) { + + // Start the search. + fx_timer_start(NULL, "naive_search"); + for(index_t i = 0; i < data_.n_cols(); i++) { + + GenVector pt; + bool flag = true; + data_.MakeColumnVector(i, &pt); + + // Determine which one of the two cases we have: EXCLUDE, SUBSUME + // first the EXCLUDE case: when dist is above the upper bound distance + // of this dimension, or dist is below the lower bound distance of + // this dimension + for(index_t d = 0; d < data_.n_rows(); d++) { + if(pt[d] < low_coord_limits[d] || pt[d] > high_coord_limits[d]) { + flag = false; + break; + } + } + in_range_[i] = flag; + } + fx_timer_stop(NULL, "naive_search"); + + // Search is now finished. + + } + +}; + + +#endif diff --git a/fastlib2/mlpack/range_search/ortho_range_search.h b/fastlib2/mlpack/range_search/ortho_range_search.h index c7f1cb9d4b..8cac3d7496 100644 --- a/fastlib2/mlpack/range_search/ortho_range_search.h +++ b/fastlib2/mlpack/range_search/ortho_range_search.h @@ -1,7 +1,7 @@ /** @file ortho_range_search.h * - * This file contains an implementation of a tree-based and a naive - * algorithm for orthogonal range search. + * This file contains an implementation of a tree-based algorithm for + * orthogonal range search. * * @author Dongryeol Lee (dongryel) */ @@ -11,115 +11,6 @@ #include "range_reader.h" #include "fastlib/fastlib.h" -/** @brief Naive orthogonal range search class. - * - * @code - * NaiveOrthoRangeSearch search; - * search.Init(dataset); - * search.Compute(low_coord_limits, high_coord_limits); - * - * Vector naive_search_results; - * - * // Make sure that the vector is uninitialized before passing. - * search.get_results(&naive_search_results); - * @endcode - */ -class NaiveOrthoRangeSearch { - - // This class object cannot be copied! - FORBID_ACCIDENTAL_COPIES(NaiveOrthoRangeSearch); - - private: - - /** @brief The i-th position of this array tells whether the i-th - * point is in the specified orthogonal range. - */ - ArrayList in_range_; - - /** @brief The dataset. - */ - Matrix data_; - - public: - - ////////// Constructor/Destructor ////////// - - /** @brief Constructor which does not do anything. - */ - NaiveOrthoRangeSearch() {} - - /** @brief Destructor which does not do anything. - */ - ~NaiveOrthoRangeSearch() {} - - ////////// Getters/Setters ////////// - - /** @brief Retrieve the result of the search. - * - * @param results An uninitialized vector which will have the boolean - * results representing the search results. - */ - void get_results(ArrayList *results) const { - results->Init(in_range_.size()); - - for(index_t i = 0; i < in_range_.size(); i++) { - (*results)[i] = in_range_[i]; - } - } - - ////////// User-level Functions ////////// - - /** @brief Initialize the computation object. - * - * @param data The data used for orthogonal range search. - */ - void Init(Matrix &data) { - - // copy the incoming data - data_.Copy(data); - - // re-initialize boolean flag - in_range_.Init(data_.n_cols()); - for(index_t i = 0; i < data_.n_cols(); i++) { - in_range_[i] = false; - } - } - - /** @brief The main computation of naive orthogonal range search. - * - * @param low_coord_limits The lower coordinate range of the search window. - * @param high_coord_limits The upper coordinate range of the search - * window. - */ - void Compute(Vector &low_coord_limits, Vector &high_coord_limits) { - - // Start the search. - fx_timer_start(NULL, "naive_search"); - for(index_t i = 0; i < data_.n_cols(); i++) { - - Vector pt; - bool flag = true; - data_.MakeColumnVector(i, &pt); - - // Determine which one of the two cases we have: EXCLUDE, SUBSUME - // first the EXCLUDE case: when dist is above the upper bound distance - // of this dimension, or dist is below the lower bound distance of - // this dimension - for(index_t d = 0; d < data_.n_rows(); d++) { - if(pt[d] < low_coord_limits[d] || pt[d] > high_coord_limits[d]) { - flag = false; - break; - } - } - in_range_[i] = flag; - } - fx_timer_stop(NULL, "naive_search"); - - // Search is now finished. - - } - -}; /** @brief Faster orthogonal range search class using a tree. * @@ -134,6 +25,7 @@ class NaiveOrthoRangeSearch { * search.get_results(&search_results); * @endcode */ +template class OrthoRangeSearch { // This class object cannot be copied! @@ -188,7 +80,8 @@ class OrthoRangeSearch { * @param high_coord_limits The upper coordinate range of the search * window. */ - void Compute(Vector &low_coord_limits, Vector &high_coord_limits) { + void Compute(const GenVector &low_coord_limits, + const GenVector &high_coord_limits) { fx_timer_start(NULL, "tree_range_search"); ortho_range_search(root_, 0, low_coord_limits, high_coord_limits); @@ -258,7 +151,8 @@ class OrthoRangeSearch { * If not NULL, the tree is loaded from the * file whose name is given as the argument. */ - void Init(Matrix &dataset, bool make_copy, const char *load_tree_file_name) { + void Init(GenMatrix &dataset, bool make_copy, + const char *load_tree_file_name) { int leaflen = fx_param_int(NULL, "leaflen", 20); @@ -295,7 +189,7 @@ class OrthoRangeSearch { private: /** @brief This defines the type of the tree used in this algorithm. */ - typedef BinarySpaceTree, Matrix> Tree; + typedef BinarySpaceTree, GenMatrix > Tree; /** @brief Flag determining a prune */ enum PruneStatus {SUBSUME, INCONCLUSIVE, EXCLUDE}; @@ -303,7 +197,7 @@ class OrthoRangeSearch { ////////// Private Member Variables ////////// /** @brief Pointer to the dataset */ - Matrix data_; + GenMatrix data_; /** @brief Buffer for loading up old_from_new mapping. */ ArrayList *old_from_new_buffer_; @@ -367,11 +261,11 @@ class OrthoRangeSearch { printf("Tree has been loaded...\n"); // apply permutation to the dataset - Matrix tmp_data; + GenMatrix tmp_data; tmp_data.Init(data_.n_rows(), data_.n_cols()); for(index_t i = 0; i < data_.n_cols(); i++) { - Vector source, dest; + GenVector source, dest; data_.MakeColumnVector(i, &source); tmp_data.MakeColumnVector(new_from_old_[i], &dest); dest.CopyValues(source); @@ -388,8 +282,8 @@ class OrthoRangeSearch { * @param high_coord_limits The upper coordinate limits of the search. */ void ortho_slow_range_search(Tree *node, int start_dim, - const Vector &low_coord_limits, - const Vector &high_coord_limits) { + const GenVector &low_coord_limits, + const GenVector &high_coord_limits) { PruneStatus prune_flag; for(index_t row = node->begin(); row < node->end(); row++) { @@ -427,8 +321,8 @@ class OrthoRangeSearch { * window. */ void ortho_range_search(Tree *node, int start_dim, - const Vector &low_coord_limits, - const Vector &high_coord_limits) { + const GenVector &low_coord_limits, + const GenVector &high_coord_limits) { PruneStatus prune_flag = SUBSUME; diff --git a/fastlib2/mlpack/range_search/ortho_range_search_main.cc b/fastlib2/mlpack/range_search/ortho_range_search_main.cc index e17c3de5ad..0ddf3dfd0b 100644 --- a/fastlib2/mlpack/range_search/ortho_range_search_main.cc +++ b/fastlib2/mlpack/range_search/ortho_range_search_main.cc @@ -4,6 +4,8 @@ * * @author Dongryeol Lee (dongryel) */ +#include "data_aux.h" +#include "naive_ortho_range_search.h" #include "ortho_range_search.h" /** Main function which reads parameters and runs the orthogonal @@ -67,14 +69,14 @@ int main(int argc, char *argv[]) { const char* dataset_file_name = fx_param_str(NULL, "data", "data.ds"); // column-oriented dataset matrix. - Matrix dataset; + GenMatrix dataset; // data::Load inits a matrix with the contents of a .csv or .arff. - data::Load(dataset_file_name, &dataset); + data_aux::Load(dataset_file_name, &dataset); // Read the search range from the file. const char *range_data_file_name = fx_param_str(NULL, "range", "range.ds"); - Vector low_coord_limits, high_coord_limits; + GenVector low_coord_limits, high_coord_limits; RangeReader::ReadRangeData(&low_coord_limits, &high_coord_limits, dataset, range_data_file_name); @@ -92,7 +94,7 @@ int main(int argc, char *argv[]) { } // Declare fast tree-based orthogonal range search algorithm object. - OrthoRangeSearch fast_search; + OrthoRangeSearch fast_search; fast_search.Init(dataset, fx_param_exists(NULL, "do_naive"), load_tree_file_name); fast_search.Compute(low_coord_limits, high_coord_limits); @@ -108,7 +110,7 @@ int main(int argc, char *argv[]) { // if naive option is specified, do naive algorithm if(do_naive) { - NaiveOrthoRangeSearch search; + NaiveOrthoRangeSearch search; search.Init(dataset); search.Compute(low_coord_limits, high_coord_limits); ArrayList naive_search_results; diff --git a/fastlib2/mlpack/range_search/range_reader.h b/fastlib2/mlpack/range_search/range_reader.h index 6e496ddd0d..f8a753b804 100644 --- a/fastlib2/mlpack/range_search/range_reader.h +++ b/fastlib2/mlpack/range_search/range_reader.h @@ -39,9 +39,10 @@ class RangeReader { * rows of the text file to read in). * @param range_data_file_name The file to read the range data from. */ - static void ReadRangeData(Vector *low_coord_limits, - Vector *high_coord_limits, - Matrix &dataset, + template + static void ReadRangeData(GenVector *low_coord_limits, + GenVector *high_coord_limits, + GenMatrix &dataset, const char *range_data_file_name) { TextTokenizer tokenizer;