From 9af1b7902f124156516113dcaf7a92faa1af00a4 Mon Sep 17 00:00:00 2001 From: Dongryeol Lee Date: Tue, 22 Jan 2008 01:12:11 +0000 Subject: [PATCH] Another pass in doxygen-style documentations --- fastlib/u/dongryel/kde/dataset_scaler.h | 18 ++ fastlib/u/dongryel/kde/fft_kde.h | 77 +++--- fastlib/u/dongryel/kde/fgt_kde.h | 225 +++++++++--------- fastlib/u/dongryel/kde/kde.h | 171 +++++++++---- fastlib/u/dongryel/kde/kde_main.cc | 18 +- fastlib/u/dongryel/kde/naive_kde.h | 115 ++++++++- .../series_expansion/farfield_expansion.h | 2 +- .../series_expansion/local_expansion.h | 2 +- .../mult_farfield_expansion.h | 2 +- .../series_expansion/mult_local_expansion.h | 2 +- 10 files changed, 421 insertions(+), 211 deletions(-) diff --git a/fastlib/u/dongryel/kde/dataset_scaler.h b/fastlib/u/dongryel/kde/dataset_scaler.h index f20ba6ea6b..3930ca48e1 100644 --- a/fastlib/u/dongryel/kde/dataset_scaler.h +++ b/fastlib/u/dongryel/kde/dataset_scaler.h @@ -12,10 +12,28 @@ #include +/** @brief A static class providing utilities for scaling the query + * and the reference datasets. + * + * Example use: + * + * @code + * DatasetScaler::ScaleDataByMinMax(qset, rset, queries_equal_references); + * @endcode + */ class DatasetScaler { public: + /** @brief Scale the given query and the reference datasets to fit + * in the unit hypercube $[0,1]^D$ where $D$ is the common + * dimensionality of the two datasets. + * + * @param qset The column-oriented query set. + * @param rset The column-oriented reference set. + * @param queries_equal_references The boolean flag that tells whether + * the queries equal the references. + */ static void ScaleDataByMinMax(Matrix &qset, Matrix &rset, bool queries_equal_references) { diff --git a/fastlib/u/dongryel/kde/fft_kde.h b/fastlib/u/dongryel/kde/fft_kde.h index 4d13630001..3f8f2e8e1d 100644 --- a/fastlib/u/dongryel/kde/fft_kde.h +++ b/fastlib/u/dongryel/kde/fft_kde.h @@ -24,25 +24,24 @@ #include -/** - * A computation class for FFT based kernel density estimation +/** @brief A computation class for FFT based kernel density estimation * - * This class is only inteded to compute once per instantiation. + * This class is only inteded to compute once per instantiation. * - * Example use: + * Example use: * - * @code - * FFTKde fft_kde; - * struct datanode* fft_kde_module; - * Vector results; + * @code + * FFTKde fft_kde; + * struct datanode* fft_kde_module; + * Vector results; * - * fft_kde_module = fx_submodule(NULL, "kde", "fft_kde_module"); - * fft_kde.Init(queries, references, fft_kde_module); - * fft_kde.Compute(); + * fft_kde_module = fx_submodule(NULL, "kde", "fft_kde_module"); + * fft_kde.Init(queries, references, fft_kde_module); + * fft_kde.Compute(); * - * // important to make sure that you don't call Init on results! - * fft_kde.get_density_estimates(&results); - * @endcode + * // important to make sure that you don't call Init on results! + * fft_kde.get_density_estimates(&results); + * @endcode */ class FFTKde { @@ -50,6 +49,18 @@ class FFTKde { private: + ////////// Private Class Definitions ////////// + + /** @brief Complex number - composed of real and imaginary parts */ + struct complex { + + /** @brief Real part */ + double real; + + /** @brief Imaginary part */ + double imag; + }; + ////////// Private Member Variables ////////// /** pointer to the module holding the relevant parameters */ @@ -685,27 +696,21 @@ class FFTKde { public: - /** complex number - composed of real and imaginary parts */ - struct complex { - - /** real part */ - double real; - - /** imaginary part */ - double imag; - }; - ////////// Constructor/Destructor ////////// - /** constructor - does not do anything */ + /** @brief Constructor - does not do anything */ FFTKde() {} - /** destructor - does not do anything */ + /** @brief Destructor - does not do anything */ ~FFTKde() {} ////////// Getters/Setters ////////// - /** get the density estimate */ + /** @brief Get the density estimates. + * + * @param results An uninitialized vector which will be initialized with + * the computed density estimates. + */ void get_density_estimates(Vector *results) { results->Init(densities_.length()); @@ -714,8 +719,12 @@ class FFTKde { } } - /** Initialize the FFT KDE object with the query and the reference - * datasets with the parameter lists. + /** @brief Initialize the FFT KDE object with the query and the + * reference datasets with the parameter lists. + * + * @param qset The column-oriented query dataset. + * @param rset The column-oriented reference dataset. + * @param module_in The module containing the parameters for execution. */ void Init(Matrix &qset, Matrix &rset, struct datanode *module_in) { @@ -757,8 +766,7 @@ class FFTKde { printf("FFT KDE initialization completed...\n"); } - /** - * Compute density estimates using FFT after initialization + /** @brief Compute density estimates using FFT after initialization */ void Compute() { @@ -814,7 +822,12 @@ class FFTKde { printf("FFT KDE completed...\n"); } - /** Print out the computed density values to the user-directed stream + /** @brief Output KDE results to a stream + * + * If the user provided "--fft_kde_output=" argument, then the + * output will be directed to a file whose name is provided after + * the equality sign. Otherwise, it will be provided to the + * screen. */ void PrintDebug() { diff --git a/fastlib/u/dongryel/kde/fgt_kde.h b/fastlib/u/dongryel/kde/fgt_kde.h index 7ba4df52aa..f825fb816c 100644 --- a/fastlib/u/dongryel/kde/fgt_kde.h +++ b/fastlib/u/dongryel/kde/fgt_kde.h @@ -29,25 +29,24 @@ #include "u/dongryel/series_expansion/mult_series_expansion_aux.h" -/** - * A computation class for FGT based kernel density estimation +/** @brief A computation class for FGT based kernel density estimation * - * This class is only inteded to compute once per instantiation. + * This class is only inteded to compute once per instantiation. * - * Example use: + * Example use: * - * @code - * FGTKde fgt_kde; - * struct datanode* fgt_kde_module; - * Vector results; + * @code + * FGTKde fgt_kde; + * struct datanode* fgt_kde_module; + * Vector results; * - * fgt_kde_module = fx_submodule(NULL, "kde", "fgt_kde_module"); - * fgt_kde.Init(queries, references, fgt_kde_module); - * fgt_kde.Compute(); + * fgt_kde_module = fx_submodule(NULL, "kde", "fgt_kde_module"); + * fgt_kde.Init(queries, references, fgt_kde_module); + * fgt_kde.Compute(); * - * // important to make sure that you don't call Init on results! - * fgt_kde.get_density_estimates(&results); - * @endcode + * // important to make sure that you don't call Init on results! + * fgt_kde.get_density_estimates(&results); + * @endcode */ class FGTKde { @@ -77,9 +76,91 @@ class FGTKde { /** precomputed constants */ MultSeriesExpansionAux msea_; + + ////////// Private Member Functions ////////// - /* returns the index in a single-dim array, for the given coords in a - * d-dim array, with n[i] elements in the ith dimension + void FastGaussTransformPreprocess(double *interaction_radius, + ArrayList &nsides, + Vector &sidelengths, Vector &mincoords, + int *nboxes, int *nterms) { + + // Compute the interaction radius. + double bandwidth = sqrt(kernel_.bandwidth_sq()); + *interaction_radius = sqrt(-2.0 * kernel_.bandwidth_sq() * log(tau_)); + + int di, n, num_rows = rset_.n_cols(); + int dim = rset_.n_rows(); + + // Discretize the grid space into boxes. + Vector maxcoords; + maxcoords.Init(dim); + maxcoords.SetAll(-DBL_MAX); + double boxside = -1.0; + *nboxes = 1; + + for(di = 0; di < dim; di++) { + mincoords[di] = DBL_MAX; + } + + for(n = 0; n < num_rows; n++) { + for(di = 0; di < dim; di++) { + if(mincoords[di] > rset_.get(di, n)) { + mincoords[di] = rset_.get(di, n); + } + if(maxcoords[di] < rset_.get(di, n)) { + maxcoords[di] = rset_.get(di, n); + } + } + } + + // Figure out how many boxes lie along each direction. + for(di = 0; di < dim; di++) { + + nsides[di] = (int) + ((maxcoords[di] - mincoords[di]) / bandwidth + 1); + + (*nboxes) = (*nboxes) * nsides[di]; + double tmp = (maxcoords[di] - mincoords[di]) / + (nsides[di] * 2 * bandwidth); + + if(tmp > boxside) { + boxside = tmp; + } + + sidelengths[di] = (maxcoords[di] - mincoords[di]) / + ((double) nsides[di]); + + } + + int ip = 0; + double two_r = 2.0 * boxside; + double one_minus_two_r = 1.0 - two_r; + double ret = 1.0 / pow(one_minus_two_r * one_minus_two_r, dim); + double factorialvalue = 1.0; + double r_raised_to_p_alpha = 1.0; + double first_factor, second_factor; + double ret2; + + do { + ip++; + factorialvalue *= ip; + + r_raised_to_p_alpha *= two_r; + first_factor = 1.0 - r_raised_to_p_alpha; + first_factor *= first_factor; + second_factor = r_raised_to_p_alpha * (2.0 - r_raised_to_p_alpha) + / sqrt(factorialvalue); + + ret2 = ret * (pow((first_factor + second_factor), dim) - + pow(first_factor, dim)); + + } while(ret2 > tau_); + + *nterms = ip; + } + + /* Returns the index in a single-dim array, for the given coords in + * a d-dim array, with n[i] elements in the ith dimension */ int multi_dim_index_in_single_array(ArrayList &coords, ArrayList &n) { @@ -866,15 +947,19 @@ class FGTKde { ////////// Constructor/Destructor ////////// - /** constructor */ + /** @brief Constructor that does not do anything. */ FGTKde() {} - /** destructor */ + /** @brief Destructor that does not do anything. */ ~FGTKde() {} ////////// Getters/Setters ////////// - /** get the density estimate */ + /** @brief Get the density estimates. + * + * @param results An uninitialized vector which will be initialized + * with the computed density estimates. + */ void get_density_estimates(Vector *results) { results->Init(densities_.length()); @@ -885,7 +970,13 @@ class FGTKde { ///////// Initialization and computation ////////// - /** initialize with the given query and the reference datasets */ + /** @brief Initialize with the given query and the reference + * datasets. + * + * @param qset The column-oriented query dataset. + * @param rset The column-oriented reference dataset. + * @param module_in The module holding the parameters for execution. + */ void Init(Matrix &qset, Matrix &rset, struct datanode *module_in) { // initialize with the incoming module holding the paramters @@ -904,92 +995,7 @@ class FGTKde { tau_ = fx_param_double(module_, "absolute_error", 0.1); } - void FastGaussTransformPreprocess(double *interaction_radius, - ArrayList &nsides, - Vector &sidelengths, Vector &mincoords, - int *nboxes, int *nterms) { - - // Compute the interaction radius. - double bandwidth = sqrt(kernel_.bandwidth_sq()); - *interaction_radius = sqrt(-2.0 * kernel_.bandwidth_sq() * log(tau_)); - - int di, n, num_rows = rset_.n_cols(); - int dim = rset_.n_rows(); - - /** - * Discretize the grid space into boxes. - */ - Vector maxcoords; - maxcoords.Init(dim); - maxcoords.SetAll(-DBL_MAX); - double boxside = -1.0; - *nboxes = 1; - - for(di = 0; di < dim; di++) { - mincoords[di] = DBL_MAX; - } - - for(n = 0; n < num_rows; n++) { - for(di = 0; di < dim; di++) { - if(mincoords[di] > rset_.get(di, n)) { - mincoords[di] = rset_.get(di, n); - } - if(maxcoords[di] < rset_.get(di, n)) { - maxcoords[di] = rset_.get(di, n); - } - } - } - - /** - * Figure out how many boxes lie along each direction. - */ - for(di = 0; di < dim; di++) { - - nsides[di] = (int) - ((maxcoords[di] - mincoords[di]) / bandwidth + 1); - - (*nboxes) = (*nboxes) * nsides[di]; - double tmp = (maxcoords[di] - mincoords[di]) / - (nsides[di] * 2 * bandwidth); - - if(tmp > boxside) { - boxside = tmp; - } - - sidelengths[di] = (maxcoords[di] - mincoords[di]) / - ((double) nsides[di]); - - } - - int ip = 0; - double two_r = 2.0 * boxside; - double one_minus_two_r = 1.0 - two_r; - double ret = 1.0 / pow(one_minus_two_r * one_minus_two_r, dim); - double factorialvalue = 1.0; - double r_raised_to_p_alpha = 1.0; - double first_factor, second_factor; - double ret2; - - do { - ip++; - factorialvalue *= ip; - - r_raised_to_p_alpha *= two_r; - first_factor = 1.0 - r_raised_to_p_alpha; - first_factor *= first_factor; - second_factor = r_raised_to_p_alpha * (2.0 - r_raised_to_p_alpha) - / sqrt(factorialvalue); - - ret2 = ret * (pow((first_factor + second_factor), dim) - - pow(first_factor, dim)); - - } while(ret2 > tau_); - - *nterms = ip; - } - - /** - * Compute KDE estimates using fast Gauss transform. + /** @brief Compute KDE estimates using fast Gauss transform. */ void Compute() { @@ -1059,6 +1065,13 @@ class FGTKde { printf("FGT KDE completed...\n"); } + /** @brief Output KDE results to a stream + * + * If the user provided "--fgt_kde_output=" argument, then the + * output will be directed to a file whose name is provided after + * the equality sign. Otherwise, it will be provided to the + * screen. + */ void PrintDebug() { FILE *stream = stdout; diff --git a/fastlib/u/dongryel/kde/kde.h b/fastlib/u/dongryel/kde/kde.h index 2b40661398..73ea8c2b7b 100644 --- a/fastlib/u/dongryel/kde/kde.h +++ b/fastlib/u/dongryel/kde/kde.h @@ -69,29 +69,28 @@ #include "u/dongryel/series_expansion/mult_local_expansion.h" #include "u/dongryel/series_expansion/kernel_aux.h" -/** - * A computation class for dual-tree based kernel density estimation +/** @brief A computation class for dual-tree based kernel density + * estimation. * - * This class builds trees for input query and reference sets on Init. - * The KDE computation is then performed by calling Compute + * This class builds trees for input query and reference sets on Init. + * The KDE computation is then performed by calling Compute. * - * This class is only intended to compute once per instantiation. + * This class is only intended to compute once per instantiation. * - * Example use: + * Example use: * - * @code - * FastKde fast_kde; - * struct datanode* kde_module; - * Vector results; + * @code + * FastKde fast_kde; + * struct datanode* kde_module; + * Vector results; * - * kde_module = fx_submodule(NULL, "kde", "kde_module"); - * fast_kde.Init(queries, references, queries_equal_references, - * kde_module); - * fast_kde.Compute(); - * - * // important to make sure that you don't call Init on results! - * fast_kde.get_density_estimates(&results); - * @endcode + * kde_module = fx_submodule(NULL, "kde", "kde_module"); + * fast_kde.Init(queries, references, queries_equal_references, + * kde_module); + * + * // important to make sure that you don't call Init on results! + * fast_kde.Compute(&results); + * @endcode */ template class FastKde { @@ -103,32 +102,36 @@ class FastKde { // forward declaration of KdeStat class class KdeStat; - /** our tree type using the KdeStat */ + /** @brief our tree type using the KdeStat */ typedef BinarySpaceTree, Matrix, KdeStat > Tree; - /** parameter class */ + /** @brief Defines the parameter class object for holding the + * essential parameters necessary for KDE computations. + */ class Param { public: - /** series expansion auxililary object */ + /** @brief Series expansion auxililary object */ TKernelAux ka_; - /** the dimensionality of the datasets */ + /** @brief The dimensionality of the datasets */ index_t dimension_; - /** number of query points */ + /** @brief The number of query points */ index_t query_count_; - /** number of reference points */ + /** @brief The number of reference points */ index_t reference_count_; - /** the global relative error allowed */ + /** @brief The global relative error allowed */ double relative_error_; - /** the bandwidth */ + /** @brief The bandwidth */ double bandwidth_; - /** multiply the unnormalized sum by this to get the density estimate */ + /** @brief The constant to multiply the unnormalized sum by this + * to get the density estimate + */ double mul_constant_; OT_DEF_BASIC(Param) { @@ -142,8 +145,9 @@ class FastKde { } public: - /** - * Initializes parameters from a data node + /** @brief Initializes parameters from a data node + * + * @param module module holding the parameters for KDE computation */ void Init(datanode *module) { @@ -156,6 +160,13 @@ class FastKde { dimension_ = reference_count_ = query_count_ = -1; } + /** @brief Finalizes the parameter object initialization by setting the + * dimensionality and computing the normalization constant and + * initializing the series expansion object. + * + * @param module module holding the parameters for KDE computation + * @param dimension the dimensionality of the dataset + */ void FinalizeInit(datanode *module, int dimension) { dimension_ = dimension; @@ -194,13 +205,32 @@ class FastKde { } }; - /** coarse result on a region */ + /** @brief Defines the class object for holding a coarse + * approximated result accumulated on a query node region + */ class QPostponed { public: + /** @brief The change in lower and upper densities that must be + * propagated downwards. + */ DRange d_density_range_; + + /** @brief The total amount finite-difference based pruning that must be + * incorporated into the density estimate of each query point under + * the query node. + */ DRange finite_diff_range_; + + /** @brief The total amount of error used in approximation for all + * query points that must be propagated downwards. + */ double used_error_; + + /** @brief The number of reference points that were taken care of + * for all query points under this node; this information + * must be propagated downwards. + */ int n_pruned_; OT_DEF_BASIC(QPostponed) { @@ -212,7 +242,10 @@ class FastKde { public: - /** initialize postponed information to zero */ + /** @brief Initialize postponed information to zero + * + * @param param global parameter object + */ void Init(const Param& param) { d_density_range_.Init(0, 0); finite_diff_range_.Init(0, 0); @@ -440,29 +473,31 @@ class FastKde { Init(); } - /** constructor - does not do anything */ + /** @brief constructor - does not do anything + */ KdeStat() { } - /** destructor - does not do anything */ + /** @brief destructor - does not do anything + */ ~KdeStat() {} }; ////////// Private Member Variables ////////// - /** module used to pass parameters into the FastKde object */ + /** @brief module used to pass parameters into the FastKde object */ struct datanode *module_; - /** parameter list */ + /** @brief parameter list */ Param parameters_; - /** query dataset */ + /** @brief query dataset */ Matrix qset_; - /** query tree */ + /** @brief query tree */ Tree *qroot_; - /** reference dataset */ + /** @brief reference dataset */ Matrix rset_; /** reference tree */ @@ -811,10 +846,12 @@ class FastKde { } // handling the case in which the extrinsic pruning fails } - /** - * pre-processing step - this wouldn't be necessary if the core - * fastlib supported a Init function for Stat objects that take - * more arguments. + /** @brief Pre-processing step that traverse the tree and + * initializes series expansion objects and computes + * far-field coefficients bottomup. + * + * @param node The current node - initially called with the root of + * the query/reference tree. */ void PreProcess(Tree *node) { @@ -849,7 +886,13 @@ class FastKde { } } - /** post processing step */ + /** @brief Post processing step that traverses the query tree in a + * pre-order and propagates left-over approximations on each + * node downwards. + * + * @param qnode The current query node - initialially called with the root + * of the query tree. + */ void PostProcess(Tree *qnode) { // for leaf query node, incorporate the postponed info and normalize @@ -885,7 +928,7 @@ class FastKde { ////////// Constructor/Destructor ////////// - /** constructor */ + /** @brief Constructor that does not do anything. */ FastKde() { qroot_ = NULL; rroot_ = NULL; @@ -893,7 +936,7 @@ class FastKde { DEBUG_POISON_PTR(module_); } - /** destructor */ + /** @brief Destructor which deletes constructed trees and frees memory. */ ~FastKde() { if(qroot_ != rroot_ ) { delete qroot_; @@ -906,7 +949,11 @@ class FastKde { ////////// Getters/Setters ////////// - /** get the density estimate */ + /** @brief Get the density estimate + * + * @param results An uninitialized vector which will be initialized + * with the computed density estimates. + */ void get_density_estimates(Vector *results) { results->Init(q_results_.size()); @@ -917,8 +964,12 @@ class FastKde { ////////// User-level functions ////////// - /** computes KDE after the initialization function is called */ - void Compute() { + /** @brief Computes KDE after the initialization function is called + * + * @param results An uninitialized vector which will be initialized + * with the computed density estimates. + */ + void Compute(Vector *results) { num_finite_difference_prunes_ = num_farfield_to_local_prunes_ = num_farfield_prunes_ = num_local_prunes_ = 0; @@ -971,6 +1022,10 @@ class FastKde { q_results_[i].n_pruned_ = tmp_q_results[i].n_pruned_; } + // retrieve density estimate results + get_density_estimates(results); + + // output some useful statistics printf("\nFast KDE completed...\n"); printf("Finite difference prunes: %d\n", num_finite_difference_prunes_); printf("F2L prunes: %d\n", num_farfield_to_local_prunes_); @@ -978,7 +1033,17 @@ class FastKde { printf("L prunes: %d\n", num_local_prunes_); } - /** initialize query and reference sets and construct trees */ + /** @brief Initialize query and reference sets and construct + * trees. + * + * @param queries The column-oriented matrix holding the query + * points. + * @param references The column-oriented matrix holding + * the reference points. + * @param queries_equal_references The boolean flag that tells whether + * the queries equal the references. + * @param module_in The FastExec holding the essential parameters. + */ void Init(Matrix &queries, Matrix &references, bool queries_equal_references, struct datanode *module_in) { @@ -1033,7 +1098,13 @@ class FastKde { parameters_.FinalizeInit(fx_root, rset_.n_rows()); } - /** Output KDE results to a stream */ + /** @brief Output KDE results to a stream + * + * If the user provided "--fast_kde_output=" argument, then the + * output will be directed to a file whose name is provided after + * the equality sign. Otherwise, it will be provided to the + * screen. + */ void PrintDebug() { FILE *stream = stdout; diff --git a/fastlib/u/dongryel/kde/kde_main.cc b/fastlib/u/dongryel/kde/kde_main.cc index b848dc198e..0d62d9a697 100644 --- a/fastlib/u/dongryel/kde/kde_main.cc +++ b/fastlib/u/dongryel/kde/kde_main.cc @@ -69,8 +69,8 @@ * --kde/do_naive flag is not present. * * 10. kde/relative_error (optional): relative error criterion for the - * fast algorithm; default value is 0.1 (10 % relative error for all - * query density estimates). + * fast algorithm; default value is 0.1 (10 percent relative error for + * all query density estimates). */ int main(int argc, char *argv[]) { @@ -130,13 +130,11 @@ int main(int argc, char *argv[]) { FastKde fast_kde; fast_kde.Init(queries, references, queries_equal_references, kde_module); - fast_kde.Compute(); + fast_kde.Compute(&fast_kde_results); if(fx_param_exists(kde_module, "fast_kde_output")) { fast_kde.PrintDebug(); } - - fast_kde.get_density_estimates(&fast_kde_results); } // otherwise do O(D^p) expansion @@ -146,13 +144,11 @@ int main(int argc, char *argv[]) { FastKde fast_kde; fast_kde.Init(queries, references, queries_equal_references, kde_module); - fast_kde.Compute(); + fast_kde.Compute(&fast_kde_results); if(fx_param_exists(kde_module, "fast_kde_output")) { fast_kde.PrintDebug(); } - - fast_kde.get_density_estimates(&fast_kde_results); } if(do_naive) { @@ -169,14 +165,14 @@ int main(int argc, char *argv[]) { } else if(!strcmp(fx_param_str(kde_module, "kernel", "epan"), "epan")) { FastKde fast_kde; + Vector fast_kde_results; + fast_kde.Init(queries, references, queries_equal_references, kde_module); - fast_kde.Compute(); + fast_kde.Compute(&fast_kde_results); if(fx_param_exists(kde_module, "fast_kde_output")) { fast_kde.PrintDebug(); } - Vector fast_kde_results; - fast_kde.get_density_estimates(&fast_kde_results); if(do_naive) { NaiveKde naive_kde; diff --git a/fastlib/u/dongryel/kde/naive_kde.h b/fastlib/u/dongryel/kde/naive_kde.h index 255119b5e9..d811f7ff82 100644 --- a/fastlib/u/dongryel/kde/naive_kde.h +++ b/fastlib/u/dongryel/kde/naive_kde.h @@ -9,38 +9,114 @@ #ifndef NAIVE_KDE_H #define NAIVE_KDE_H +/** @brief A templatized class for computing the KDE naively. + * + * This class is only intended to compute once per instantiation. + * + * Example use: + * + * @code + * NaiveKde naive_kde; + * struct datanode* kde_module; + * Vector results; + * + * kde_module = fx_submodule(NULL, "kde", "kde_module"); + * naive_kde.Init(queries, references, kde_module); + * + * // important to make sure that you don't call Init on results! + * naive_kde.Compute(&results); + * @endcode + */ template class NaiveKde { FORBID_ACCIDENTAL_COPIES(NaiveKde); private: - - /** pointer to the module */ + + ////////// Private Member Variables ////////// + + /** @brief Pointer to the module holding the parameters. */ struct datanode *module_; - /** query dataset */ + /** @brief The column-oriented query dataset. */ Matrix qset_; - /** reference dataset */ + /** @brief The column-oriented reference dataset. */ Matrix rset_; - /** kernel */ + /** @brief The kernel function. */ TKernel kernel_; - /** computed densities */ + /** @brief The computed densities. */ Vector densities_; public: - /** constructor - does not do anything */ + ////////// Constructor/Destructor ////////// + + /** @brief Constructor - does not do anything */ NaiveKde() { } - /** destructor - does not do anything */ + /** @brief Destructor - does not do anything */ ~NaiveKde() { } + ////////// Getters/Setters ////////// + + /** @brief Get the density estimate + * + * @param results An uninitialized vector which will be initialized + * with the computed density estimates. + */ + void get_density_estimates(Vector *results) { + results->Init(densities_.length()); + + for(index_t i = 0; i < densities_.length(); i++) { + (*results)[i] = densities_[i]; + } + } + + ////////// User-level Functions ////////// + + /** @brief Compute kernel density estimates naively after intialization + * + * @param results An uninitialized vector which will be initialized + * with the computed density estimates. + */ + void Compute(Vector *results) { + + printf("\nStarting naive KDE...\n"); + fx_timer_start(module_, "naive_kde_compute"); + + // compute unnormalized sum + for(index_t q = 0; q < qset_.n_cols(); q++) { + + const double *q_col = qset_.GetColumnPtr(q); + for(index_t r = 0; r < rset_.n_cols(); r++) { + const double *r_col = rset_.GetColumnPtr(r); + double dsqd = la::DistanceSqEuclidean(qset_.n_rows(), q_col, r_col); + + densities_[q] += kernel_.EvalUnnormOnSq(dsqd); + } + } + + // then normalize it + double norm_const = kernel_.CalcNormConstant(qset_.n_rows()) * + rset_.n_cols(); + for(index_t q = 0; q < qset_.n_cols(); q++) { + densities_[q] /= norm_const; + } + fx_timer_stop(module_, "naive_kde_compute"); + printf("\nNaive KDE completed...\n"); + + // retrieve density estimates + get_density_estimates(results); + } + + /** @brief Compute kernel density estimates naively after intialization + */ void Compute() { printf("\nStarting naive KDE...\n"); @@ -68,6 +144,13 @@ class NaiveKde { printf("\nNaive KDE completed...\n"); } + /** @brief Initialize the naive KDE algorithm object with the query and the + * reference datasets and the parameter list. + * + * @param qset The column-oriented query dataset. + * @param rset The column-oriented reference dataset. + * @param module_in The module holding the parameters. + */ void Init(Matrix &qset, Matrix &rset, struct datanode *module_in) { // set the datanode module to be the incoming one @@ -85,6 +168,13 @@ class NaiveKde { densities_.SetZero(); } + /** @brief Output KDE results to a stream + * + * If the user provided "--naive_kde_output=" argument, then the + * output will be directed to a file whose name is provided after + * the equality sign. Otherwise, it will be provided to the + * screen. + */ void PrintDebug() { FILE *stream = stdout; @@ -103,6 +193,15 @@ class NaiveKde { } } + /** @brief Computes the maximum relative error for the approximated + * density estimates. + * + * The maximum relative error is output after the program finishes + * the run under /maximum_relative_error_for_fast_KDE/ + * + * @param density_estimates The vector holding approximated density + * estimates. + */ void ComputeMaximumRelativeError(const Vector &density_estimates) { double max_rel_err = 0; diff --git a/fastlib/u/dongryel/series_expansion/farfield_expansion.h b/fastlib/u/dongryel/series_expansion/farfield_expansion.h index d007820b88..ca101dcdb5 100644 --- a/fastlib/u/dongryel/series_expansion/farfield_expansion.h +++ b/fastlib/u/dongryel/series_expansion/farfield_expansion.h @@ -6,7 +6,7 @@ * for an arbitrary kernel function. * * @author Dongryeol Lee (dongryel) - * @bugs No known bugs. + * @bug No known bugs. */ #ifndef FARFIELD_EXPANSION diff --git a/fastlib/u/dongryel/series_expansion/local_expansion.h b/fastlib/u/dongryel/series_expansion/local_expansion.h index 4f9d7354c5..8880c3dad2 100644 --- a/fastlib/u/dongryel/series_expansion/local_expansion.h +++ b/fastlib/u/dongryel/series_expansion/local_expansion.h @@ -6,7 +6,7 @@ * an arbitrary kernel function. * * @author Dongryeol Lee (dongryel) - * @bugs No known bugs. + * @bug No known bugs. */ #ifndef LOCAL_EXPANSION diff --git a/fastlib/u/dongryel/series_expansion/mult_farfield_expansion.h b/fastlib/u/dongryel/series_expansion/mult_farfield_expansion.h index 11ebb6e820..614ac48826 100644 --- a/fastlib/u/dongryel/series_expansion/mult_farfield_expansion.h +++ b/fastlib/u/dongryel/series_expansion/mult_farfield_expansion.h @@ -6,7 +6,7 @@ * for a arbitrary multiplicative kernel function. * * @author Dongryeol Lee (dongryel) - * @bugs No known bugs. + * @bug No known bugs. */ #ifndef MULT_FARFIELD_EXPANSION diff --git a/fastlib/u/dongryel/series_expansion/mult_local_expansion.h b/fastlib/u/dongryel/series_expansion/mult_local_expansion.h index 5dbe252b4e..cbc007423e 100644 --- a/fastlib/u/dongryel/series_expansion/mult_local_expansion.h +++ b/fastlib/u/dongryel/series_expansion/mult_local_expansion.h @@ -6,7 +6,7 @@ * for a arbitrary multiplicative kernel function. * * @author Dongryeol Lee (dongryel) - * @bugs No known bugs. + * @bug No known bugs. */ #ifndef MULT_LOCAL_EXPANSION