diff --git a/doc/developer/distances.md b/doc/developer/distances.md new file mode 100644 index 0000000000..232cdeba7a --- /dev/null +++ b/doc/developer/distances.md @@ -0,0 +1,111 @@ +# The DistanceType policy in mlpack + +Many machine learning methods operate with some sort of distance metric, and +often, this distance metric can be any arbitrary distance metric. For instance, +consider the problem of nearest neighbor search; one can find the nearest +neighbor of a point with respect to the standard Euclidean distance, or the +Manhattan (city-block) distance. The actual search techniques, though, remain +the same. And this is true of many machine learning methods: the specific +distance metric that is used can be any valid distance metric. + +mlpack algorithms, when relevant, allow the use of an arbitrary metric via the +use of the `DistanceType` template parameter. Any distance metric passed as a +`DistanceType` template parameter will need to have + + - an `Evaluate()` function + - a default constructor. + +The signature of the `Evaluate()` function is straightforward: + +```c++ +template +double Evaluate(const VecTypeA& a, const VecTypeB& b); +``` + +The function takes two vector arguments, `a` and `b`, and returns a `double` +that is the evaluation of the distance metric between the two arguments. So, +for a particular distance metric `d`, the `Evaluate()` function should return +`d(a, b)`. + +The arguments `a` and `b`, of types `VecTypeA` and `VecTypeB`, respectively, +will be an Armadillo-like vector type (usually `arma::vec`, `arma::sp_vec`, or +similar). In general it should be valid to assume that `VecTypeA` is a class +with the same API as `arma::vec`. + +Note that for distance metrics that do not hold any state, the `Evaluate()` +method can be marked as `static`. + +Overall, the `DistanceType` template policy is quite simple (much like the +[KernelType policy](kernels.md)). Below is an example distance metric class, +which implements the L2 distance: + +```c++ +class ExampleDistance +{ + // Default constructor is required. + ExampleDistance() { } + + // The example metric holds no state, so we can mark Evaluate() as static. + template + static double Evaluate(const VecTypeA& a, const VecTypeB& b) + { + // Return the L2 norm of the difference between the points, which is the + // same as the L2 distance. + return arma::norm(a - b); + } +}; +``` + +Then, this distance metric can easily be used inside of other mlpack algorithms. +For example, the code below runs range search on a random dataset with the +`ExampleDistance`, by instantiating a `RangeSearch` object that uses the +`ExampleDistance`. Then, the number of results are printed. The `RangeSearch` +class takes three template parameters: `DistanceType`, `MatType`, and +`TreeType`. (All three have defaults, so we will just leave `MatType` and +`TreeType` to their defaults.) + +```c++ +#include +#include "example_distance.hpp" // A file that contains ExampleDistance. + +using namespace mlpack; +using namespace std; + +int main() +{ + // Create a random dataset with 10 dimensions and 5000 points. + arma::mat data = arma::randu(10, 5000); + + // Instantiate the RangeSearch object with the ExampleDistance. + RangeSearch rs(data); + + // These vectors will store the results. + vector> neighbors; + vector> distances; + + // Create a random 10-dimensional query point. + arma::vec query = arma::randu(10); + + // Find those points with distance (according to ExampleDistance) between 1 + // and 2 from the query point. + rs.Search(query, Range(1.0, 2.0), neighbors, distances); + + // Now, print the number of points inside the desired range. We know that + // neighbors and distances will have length 1, since there was only one query + // point. + cout << neighbors[0].size() << " points within the range [1.0, 2.0] of the " + << "query point!" << endl; +} +``` + +mlpack comes with a number of pre-written distance metrics that satisfy the +`DistanceType` policy: + + + + - `ManhattanDistance` + - `EuclideanDistance` + - `ChebyshevDistance` + - `MahalanobisDistance` + - `LMetric` (for arbitrary L-metrics) + - `IPMetric` (requires a [KernelType](kernels.md) parameter) diff --git a/doc/developer/kernels.md b/doc/developer/kernels.md index 09aa23c39a..8d0ff6603d 100644 --- a/doc/developer/kernels.md +++ b/doc/developer/kernels.md @@ -16,7 +16,7 @@ including mlpack implements a number of kernel methods and, accordingly, each of these methods allows arbitrary kernels to be used via the `KernelType` template -parameter. Like the [MetricType policy](metrics.md), the requirements are +parameter. Like the [DistanceType policy](distances.md), the requirements are quite simple: a class implementing the `KernelType` policy must have - an `Evaluate()` function @@ -42,7 +42,7 @@ Note that for kernels that do not hold any state, the `Evaluate()` method can be marked as `static`. Overall, the `KernelType` template policy is quite simple (much like the -[MetricType policy](metrics.md)). Below is an example kernel class, which +[DistanceType policy](distances.md)). Below is an example kernel class, which outputs `1` if the vectors are close and `0` otherwise. ```c++ @@ -149,4 +149,4 @@ These kernels (or a custom kernel) may be used in a variety of mlpack methods: - `KernelPCA` - kernel principal components analysis - `FastMKS` - fast max-kernel search - `NystroemMethod` - the Nystroem method for sampling - - `IPMetric` - a metric built on a kernel + - `IPMetric` - a distance metric built on a kernel diff --git a/doc/developer/metrics.md b/doc/developer/metrics.md deleted file mode 100644 index 4a6ec5bc6a..0000000000 --- a/doc/developer/metrics.md +++ /dev/null @@ -1,108 +0,0 @@ -# The MetricType policy in mlpack - -Many machine learning methods operate with some sort of metric, and often, this -metric can be any arbitrary metric. For instance, consider the problem of -nearest neighbor search; one can find the nearest neighbor of a point with -respect to the standard Euclidean distance, or the Manhattan (city-block) -distance. The actual search techniques, though, remain the same. And this is -true of many machine learning methods: the specific metric that is used can be -any valid metric. - -mlpack algorithms, when relevant, allow the use of an arbitrary metric via the -use of the `MetricType` template parameter. Any metric passed as a `MetricType` -template parameter will need to have - - - an `Evaluate()` function - - a default constructor. - -The signature of the `Evaluate()` function is straightforward: - -```c++ -template -double Evaluate(const VecTypeA& a, const VecTypeB& b); -``` - -The function takes two vector arguments, `a` and `b`, and returns a `double` -that is the evaluation of the metric between the two arguments. So, for a -particular metric `d`, the `Evaluate()` function should return `d(a, b)`. - -The arguments `a` and `b`, of types `VecTypeA` and `VecTypeB`, respectively, -will be an Armadillo-like vector type (usually `arma::vec`, `arma::sp_vec`, or -similar). In general it should be valid to assume that `VecTypeA` is a class -with the same API as `arma::vec`. - -Note that for metrics that do not hold any state, the `Evaluate()` method can -be marked as `static`. - -Overall, the `MetricType` template policy is quite simple (much like the -[KernelType policy](kernels.md)). Below is an example metric class, which -implements the L2 distance: - -```c++ -class ExampleMetric -{ - // Default constructor is required. - ExampleMetric() { } - - // The example metric holds no state, so we can mark Evaluate() as static. - template - static double Evaluate(const VecTypeA& a, const VecTypeB& b) - { - // Return the L2 norm of the difference between the points, which is the - // same as the L2 distance. - return arma::norm(a - b); - } -}; -``` - -Then, this metric can easily be used inside of other mlpack algorithms. For -example, the code below runs range search on a random dataset with the -`ExampleKernel`, by instantiating a `RangeSearch` object that uses the -`ExampleKernel`. Then, the number of results are printed. The `RangeSearch` -class takes three template parameters: `MetricType`, `MatType`, and `TreeType`. -(All three have defaults, so we will just leave `MatType` and `TreeType` to -their defaults.) - -```c++ -#include -#include "example_metric.hpp" // A file that contains ExampleKernel. - -using namespace mlpack; -using namespace std; - -int main() -{ - // Create a random dataset with 10 dimensions and 5000 points. - arma::mat data = arma::randu(10, 5000); - - // Instantiate the RangeSearch object with the ExampleKernel. - RangeSearch rs(data); - - // These vectors will store the results. - vector> neighbors; - vector> distances; - - // Create a random 10-dimensional query point. - arma::vec query = arma::randu(10); - - // Find those points with distance (according to ExampleMetric) between 1 and - // 2 from the query point. - rs.Search(query, Range(1.0, 2.0), neighbors, distances); - - // Now, print the number of points inside the desired range. We know that - // neighbors and distances will have length 1, since there was only one query - // point. - cout << neighbors[0].size() << " points within the range [1.0, 2.0] of the " - << "query point!" << endl; -} -``` - -mlpack comes with a number of pre-written metrics that satisfy the `MetricType` -policy: - - - `ManhattanDistance` - - `EuclideanDistance` - - `ChebyshevDistance` - - `MahalanobisDistance` - - `LMetric` (for arbitrary L-metrics) - - `IPMetric` (requires a [KernelType](kernels.md) parameter) diff --git a/doc/developer/trees.md b/doc/developer/trees.md index 3fd8bf80d4..e36507474e 100644 --- a/doc/developer/trees.md +++ b/doc/developer/trees.md @@ -89,10 +89,10 @@ parameters, and trees are no exception. In order to ease usage of high-level mlpack algorithms, each `TreeType` itself must be a template class taking three parameters: - - `MetricType` -- the underlying metric that the tree will be built on (see -[the MetricType policy documentation](metrics.md)) - - `StatisticType` -- holds any auxiliary information that individual -algorithms may need + - `DistanceType` -- the underlying distance metric that the tree will be built + on (see [the DistanceType policy documentation](distances.md)) + - `StatisticType` -- holds any auxiliary information that individual algorithms + may need - `MatType` -- the type of the matrix used to represent the data The reason that these three template parameters are necessary is so that each @@ -101,11 +101,11 @@ simplify the required syntax for instantiating mlpack algorithms. By using template template parameters, a user needs only to write ```c++ -// The RangeSearch class takes a MetricType and a TreeType template parameter. +// The RangeSearch class takes a DistanceType and a TreeType template parameter. // This code instantiates RangeSearch with the ManhattanDistance and a // QuadTree. Note that the QuadTree itself is a template, and takes a -// MetricType, StatisticType, and MatType, just like the policy requires. +// DistanceType, StatisticType, and MatType, just like the policy requires. // This example ignores the constructor parameters, for the sake of simplicity. RangeSearch rs(...); @@ -124,17 +124,18 @@ RangeSearch -using MeanSplitKDTree = BinarySpaceTree +using MeanSplitKDTree = BinarySpaceTree - MeanSplit>; + HRectBound + MeanSplit>; ``` Now, the `MeanSplitKDTree` class has only three template parameters and can be @@ -188,7 +189,7 @@ afterwards.) ```c++ // The three template parameters will be supplied by the user, and are detailed // in the previous section. -template class ExampleTree @@ -199,12 +200,12 @@ class ExampleTree ////////////////////// // This batch constructor does not modify the dataset, and builds the entire - // tree using a default-constructed MetricType. + // tree using a default-constructed DistanceType. ExampleTree(const MatType& data); // This batch constructor does not modify the dataset, and builds the entire - // tree using the given MetricType. - ExampleTree(const MatType& data, MetricType& metric); + // tree using the given DistanceType. + ExampleTree(const MatType& data, DistanceType& distance); // Initialize the tree from a given cereal archive. SFINAE (the // second argument) is necessary to ensure that the archive is loading, not @@ -224,8 +225,8 @@ class ExampleTree // Get the dataset that the tree is built on. const MatType& Dataset(); - // Get the metric that the tree is built with. - MetricType& Metric(); + // Get the distance metric that the tree is built with. + DistanceType& Distance(); // Get/modify the StatisticType for this node. StatisticType& Stat(); @@ -364,8 +365,8 @@ a few important points about the implications of this API: Making this all work requires a protected constructor (part of the API) and generally makes it impossible to hold references instead of pointers internally, because if a tree is loaded from a file then it must own the - dataset it is built on and the metric it uses (this also means that a - destructor must exist for freeing these resources). + dataset it is built on and the distance metric it uses (this also means that + a destructor must exist for freeing these resources). Now, we can consider each part of the API more rigorously. @@ -378,24 +379,25 @@ This section is divided into five parts, detailing each of the parts of the API An earlier section discussed the three different template parameters that are required by the `TreeType` policy. -The [MetricType policy](metrics.md) provides one method that will be useful for -tree building and other operations: +The [DistanceType policy](distances.md) provides one method that will be useful +for tree building and other operations: ```c++ -// This function is required by the MetricType policy. -// Evaluate the metric between two points (which may be of different types). +// This function is required by the DistanceType policy. +// Evaluate the distance metric between two points (which may be of different +// types). template double Evaluate(const VecTypeA& a, const VecTypeB& b); ``` -Note that this method is not necessarily static, so a `MetricType` object should -be held internally and its `Evaluate()` method should be called whenever the -distance between two points is required. *It is generally a bad idea to +Note that this method is not necessarily static, so a `DistanceType` object +should be held internally and its `Evaluate()` method should be called whenever +the distance between two points is required. *It is generally a bad idea to hardcode any distance calculation in your tree.* This will make the tree unable -to generalize to arbitrary metrics. If your tree must depend on certain -assumptions holding about the metric (i.e. the metric is a Euclidean metric), -then make that clear in the documentation of the tree, so users do not try to -use the tree with an inappropriate metric. +to generalize to arbitrary distance metrics. If your tree must depend on +certain assumptions holding about the distance metric (i.e. the distance metric +is a Euclidean metric), then make that clear in the documentation of the tree, +so users do not try to use the tree with an inappropriate distance metric. The second template parameter, `StatisticType`, is for auxiliary information that is required by certain algorithms. For instance, consider an algorithm @@ -437,20 +439,20 @@ The first two constructors are variations of the same idea: ```c++ // This batch constructor does not modify the dataset, and builds the entire -// tree using a default-constructed MetricType. +// tree using a default-constructed DistanceType. ExampleTree(const MatType& data); // This batch constructor does not modify the dataset, and builds the entire -// tree using the given MetricType. -ExampleTree(const MatType& data, MetricType& metric); +// tree using the given DistanceType. +ExampleTree(const MatType& data, DistanceType& distance); ``` All that is required here is that a constructor is available that takes a -dataset and optionally an instantiated metric. If no metric is provided, then -it should be assumed that the `MetricType` class has a default constructor and -a default-constructed metric should be used. The constructor *must* return a -valid, fully-constructed, ready-to-use tree that satisfies the definition -of *space tree* that was given earlier in the document. +dataset and optionally an instantiated distance metric. If no distance metric +is provided, then it should be assumed that the `DistanceType` class has a +default constructor and a default-constructed distance metric should be used. +The constructor *must* return a valid, fully-constructed, ready-to-use tree that +satisfies the definition of *space tree* that was given earlier in the document. The third constructor requires the tree to be initializable from a `cereal` archive: @@ -494,9 +496,9 @@ template ExampleTree(MatType&& data); ``` -(and another overload that takes an instantiated metric), and then the user can -use `std::move()` to build the tree without copying the data matrix, although -the data matrix will be modified: +(and another overload that takes an instantiated distance metric), and then the +user can use `std::move()` to build the tree without copying the data matrix, +although the data matrix will be modified: ```c++ ExampleTree exTree(std::move(dataset)); @@ -520,13 +522,13 @@ must store a pointer to the dataset (this is not the only option, but it is the most obvious option). ```c++ -// Get the metric that the tree is built with. -MetricType& Metric(); +// Get the distance metric that the tree is built with. +DistanceType& Distance(); ``` -Each node must also store an instantiated metric or a pointer to one (note that -this is required even for metrics that have no state and have a `static` -`Evaluate()` function). +Each node must also store an instantiated distance metric or a pointer to one +(note that this is required even for metrics that have no state and have a +`static` `Evaluate()` function). ```c++ // Get/modify the StatisticType for this node. @@ -704,7 +706,7 @@ which could be calculated as below: double trueMinDist = DBL_MAX; for (size_t i = 0; i < node.NumDescendants(); ++i) { - const double dist = node.Metric().Evaluate(vec, + const double dist = node.Distance().Evaluate(vec, node.Dataset().col(node.Descendant(i))); if (dist < trueMinDist) trueMinDist = dist; @@ -716,16 +718,16 @@ for (size_t i = 0; i < node.NumDescendants(); ++i) Often the bounding shape of a node will allow a quick calculation that will make a reasonable bound. For instance, if the node's bounding shape is a ball with radius `r` and center `ctr`, the calculation is simply -`(node.Metric().Evaluate(vec, ctr) - r)`. Usually a good `MinDistance()` or +`(node.Distance().Evaluate(vec, ctr) - r)`. Usually a good `MinDistance()` or `MaxDistance()` function will make only one call to the `Evaluate()` function of -the metric. +the distance metric. The `RangeDistance()` function allows a way for both bounds to be calculated at once. It is possible to implement this as a call to `MinDistance()` followed by -a call to `MaxDistance()`, but this may incur more metric `Evaluate()` calls -than necessary. Often calculating both bounds at once can be more efficient and -can be done with fewer `Evaluate()` calls than calling both `MinDistance()` and -`MaxDistance()`. +a call to `MaxDistance()`, but this may incur more distance metric `Evaluate()` +calls than necessary. Often calculating both bounds at once can be more +efficient and can be done with fewer `Evaluate()` calls than calling both +`MinDistance()` and `MaxDistance()`. ### Serialization @@ -799,16 +801,16 @@ class TreeTraits }; ``` -An example specialization for the `:KDTree` class is given below. Note that +An example specialization for the `KDTree` class is given below. Note that `KDTree` is itself a template class (like every class satisfying the `TreeType` policy), so we are specializing to a template parameter. ```c++ -template template<> -class TreeTraits> +class TreeTraits> { public: // The regions represented by the two children of a node may not overlap. diff --git a/doc/index.md b/doc/index.md index 5213640c42..607a2ae214 100644 --- a/doc/index.md +++ b/doc/index.md @@ -170,7 +170,7 @@ Throughout the codebase, mlpack uses some common template parameter policies. These are documented below. * [The `ElemType` policy](developer/elemtype.md): element types for data - * [The `MetricType` policy](developer/metrics.md): distance metrics + * [The `DistanceType` policy](developer/distances.md): distance metrics * [The `KernelType` policy](developer/kernels.md): kernel functions * [The `TreeType` policy](developer/trees.md): space trees (ball trees, KD-trees, etc.) diff --git a/doc/tutorials/kmeans.md b/doc/tutorials/kmeans.md index afbcdb6ca5..e9bc4112ab 100644 --- a/doc/tutorials/kmeans.md +++ b/doc/tutorials/kmeans.md @@ -414,7 +414,7 @@ The `KMeans<>` class also takes three template parameters, which can be modified to change the behavior of the k-means algorithm. There are three template parameters: - - `MetricType`: controls the distance metric used for clustering (by default, + - `DistanceType`: controls the distance metric used for clustering (by default, the squared Euclidean distance is used) - `InitialPartitionPolicy`: the method by which initial clusters are set; by default, `SampleInitialization` is used @@ -445,42 +445,42 @@ how to modify them. Most machine learning algorithms in mlpack support modifying the distance metric, and `KMeans<>` is no exception. Similar to `NeighborSearch` (see the -"MetricType policy class" section in the +"DistanceType policy class" section in the [NeighborSearch tutorial](neighbor_search.md)), any of mlpack's metric classes (found in `mlpack/core/metrics/`) can be given as an argument. The `LMetric` class is a good example implementation. -A class fulfilling the [MetricType policy](../developer/metrics.md) must +A class fulfilling the [DistanceType policy](../developer/distances.md) must provide the following two functions: ```c++ // Empty constructor is required. -MetricType(); +DistanceType(); // Compute the distance between two points. template double Evaluate(const VecType& a, const VecType& b); ``` -Most of the standard metrics that could be used are stateless and therefore the -`Evaluate()` method is implemented statically. However, there are metrics, such -as the Mahalanobis distance (`MahalanobisDistance`), that store state. To this -end, an instantiated `MetricType` object is stored within the `KMeans` class. -The example below shows how to pass an instantiated `MahalanobisDistance` in the -constructor. +Most of the standard distance metrics that could be used are stateless and +therefore the `Evaluate()` method is implemented statically. However, there are +metrics, such as the Mahalanobis distance (`MahalanobisDistance`), that store +state. To this end, an instantiated `DistanceType` object is stored within the +`KMeans` class. The example below shows how to pass an instantiated +`MahalanobisDistance` in the constructor. ```c++ // The initialized Mahalanobis distance. extern MahalanobisDistance distance; // We keep the default arguments for the maximum number of iterations, but pass -// our instantiated metric. +// our instantiated distance metric. KMeans k(1000, distance); ``` -***Note***: While the `MetricType` policy only requires two methods, one of +***Note***: While the `DistanceType` policy only requires two methods, one of which is an empty constructor, more can always be added. `MahalanobisDistance` -also has constructors with parameters, because it is a stateful metric. +also has constructors with parameters, because it is a stateful distance metric. ### Changing the initial partitioning strategy used for k-means @@ -546,7 +546,7 @@ not work very well for most settings. See the documentation for If the `Cluster()` method returns point assignments instead of centroids, then valid initial assignments must be returned for every point in the dataset. -As with the `MetricType` template parameter, an initialized +As with the `DistanceType` template parameter, an initialized `InitialPartitionPolicy` can be passed to the constructor of `KMeans` as a fourth argument. @@ -603,12 +603,12 @@ the `LloydStepType` policy: Note that the `LloydStepType` policy is itself a template template parameter, and must accept two template parameters of its own: - - `MetricType`: the type of metric to use + - `DistanceType`: the type of distance metric to use - `MatType`: the type of data matrix to use The `LloydStepType` policy also mandates three functions: - - a constructor: `LloydStepType(const MatType& dataset, MetricType& metric);` + - a constructor: `LloydStepType(const MatType& dataset, DistanceType& distance);` - an `Iterate()` function: ```c++ diff --git a/doc/tutorials/neighbor_search.md b/doc/tutorials/neighbor_search.md index 153acf93ed..b0a64d1516 100644 --- a/doc/tutorials/neighbor_search.md +++ b/doc/tutorials/neighbor_search.md @@ -296,13 +296,13 @@ arguments: ```c++ template< typename SortPolicy = NearestNeighborSort, - typename MetricType = EuclideanDistance, + typename DistanceType = EuclideanDistance, typename MatType = arma::mat, - template class TreeType = KDTree, template class TraversalType = - TreeType, + TreeType, MatType>::template DualTreeTraverser> > class NeighborSearch; @@ -341,29 +341,29 @@ The `FurthestNeighborSort` class is another implementation, which is used to create the `KFN` typedef class, which finds the furthest neighbors, as opposed to the nearest neighbors. -## `MetricType` policy class +## `DistanceType` policy class -The `MetricType` policy class allows the neighbor search to take place in any +The `DistanceType` policy class allows the neighbor search to take place in any arbitrary metric space. The `LMetric` class is a good example implementation. -A `MetricType` class must provide the following functions: +A `DistanceType` class must provide the following functions: ```c++ // Empty constructor is required. -MetricType(); +DistanceType(); // Compute the distance between two points. template double Evaluate(const VecType& a, const VecType& b); ``` -Internally, the `NeighborSearch` class keeps an instantiated `MetricType` class -(which can be given in the constructor). This is useful for a metric like the -Mahalanobis distance (`MahalanobisDistance`), which must store state (the -covariance matrix). Therefore, you can write a non-static MetricType class and -use it seamlessly with `NeighborSearch`. +Internally, the `NeighborSearch` class keeps an instantiated `DistanceType` class +(which can be given in the constructor). This is useful for a distance metric +like the Mahalanobis distance (`MahalanobisDistance`), which must store state +(the covariance matrix). Therefore, you can write a non-static DistanceType +class and use it seamlessly with `NeighborSearch`. -For more information on the `MetricType` policy, see the [documentation for -`MetricType`](../developer/metrics.md). +For more information on the `DistanceType` policy, see the [documentation for +`DistanceType`](../developer/distances.md). ### `MatType` policy class diff --git a/doc/tutorials/range_search.md b/doc/tutorials/range_search.md index 42fa5b6526..f4435ad825 100644 --- a/doc/tutorials/range_search.md +++ b/doc/tutorials/range_search.md @@ -311,9 +311,9 @@ Similar to the [`NeighborSearch` class](neighbor_search.md), the `RangeSearch` class is very extensible, having the following template arguments: ```c++ -template class TreeType = KDTree> class RangeSearch; @@ -322,29 +322,29 @@ class RangeSearch; By choosing different components for each of these template classes, a very arbitrary range searching object can be constructed. -### `MetricType` policy class +### `DistanceType` policy class -The `MetricType` policy class allows the range search to take place in any +The `DistanceType` policy class allows the range search to take place in any arbitrary metric space. The `LMetric` class is a good example implementation. -A `MetricType` class must provide the following functions: +A `DistanceType` class must provide the following functions: ```c++ // Empty constructor is required. -MetricType(); +DistanceType(); // Compute the distance between two points. template double Evaluate(const VecType& a, const VecType& b); ``` -Internally, the `RangeSearch` class keeps an instantiated `MetricType` class -(which can be given in the constructor). This is useful for a metric like the -Mahalanobis distance (`MahalanobisDistance`), which must store state (the -covariance matrix). Therefore, you can write a non-static `MetricType` class -and use it seamlessly with `RangeSearch`. +Internally, the `RangeSearch` class keeps an instantiated `DistanceType` class +(which can be given in the constructor). This is useful for a distance metric +like the Mahalanobis distance (`MahalanobisDistance`), which must store state +(the covariance matrix). Therefore, you can write a non-static `DistanceType` +class and use it seamlessly with `RangeSearch`. -See also the [documentation for the `MetricType` -policy](../developer/metrics.md). +See also the +[documentation for the `DistanceType` policy](../developer/distances.md). ### `MatType` policy class diff --git a/doc/user/core.md b/doc/user/core.md index 5df879afb9..1f92685c0e 100644 --- a/doc/user/core.md +++ b/doc/user/core.md @@ -6,8 +6,8 @@ classes, each of which are documented on this page. * [Core math utilities](#core-math-utilities): utility classes for mathematical purposes + * [Distances](#distances): distance metrics for geometric algorithms * [Distributions](#distributions): probability distributions - * [Metrics](#metrics): distance metrics for geometric algorithms * [Kernels](#kernels): Mercer kernels for kernel-based algorithms ## Core math utilities @@ -851,6 +851,432 @@ std::cout << "with label " << shuffledLabels[0] << " and weight " --- +## Distances + +mlpack includes a number of distance metrics for its distance-based techniques. +These all implement the [same API](../developer/distances.md), providing one +`Evaluate()` method, and can be used with a variety of different techniques, +including: + + + + * [`NeighborSearch`](/src/mlpack/methods/neighbor_search/neighbor_search.hpp) + * [`RangeSearch`](/src/mlpack/methods/range_search/range_search.hpp) + * [`LMNN`](/src/mlpack/methods/lmnn/lmnn.hpp) + * [`EMST`](/src/mlpack/methods/emst/emst.hpp) + * [`NCA`](/src/mlpack/methods/nca/nca.hpp) + * [`RANN`](/src/mlpack/methods/rann/rann.hpp) + * [`KMeans`](/src/mlpack/methods/kmeans/kmeans.hpp) + +Supported metrics: + + * [`LMetric`](#lmetric): generalized L-metric/Lp-metric, including + Manhattan/Euclidean/Chebyshev distances + * [`IoUDistance`](#ioudistance): intersection-over-union distance + * [`IPMetric`](#ipmetric): inner product metric (e.g. induced + metric over a [Mercer kernel](#kernels)) + * [`MahalanobisDistance`](#mahalanobisdistance): weighted Euclidean distance + with weights specified by a covariance matrix + * [Implement a custom metric](../developer/distances.md) + +### `LMetric` + +The `LMetric` template class implements a [generalized +L-metric](https://en.wikipedia.org/wiki/Lp_space#Definition) +(L1-metric, L2-metric, etc.). The class has two template parameters: + +``` +LMetric +``` + + * `Power` is an `int` representing the type of the metric; e.g., `2` would + represent the L2-metric (Euclidean distance). + - `Power` must be `1` or greater. + - If `Power` is `INT_MAX`, the metric is the L-infinity distance (Chebyshev + distance). + + * `TakeRoot` is a `bool` (default `true`) indicating whether the root of the + distance should be taken. + - If set to `false`, the metric will no longer satisfy the triangle + inequality. + +--- + +Several convenient typedefs are available: + + * `ManhattanDistance` (defined as `LMetric<1>`) + * `EuclideanDistance` (defined as `LMetric<2>`) + * `SquaredEuclideanDistance` (defined as `LMetric<2, false>`) + * `ChebyshevDistance` (defined as `LMetric`) + +--- + +The static `Evaluate()` method can be used to compute the distance between two +vectors. + +*Note:* The vectors given to `Evaluate()` can have any type so long as the type +implements the Armadillo API (e.g. `arma::fvec`, `arma::sp_fvec`, etc.). + +--- + +*Example usage:* + +```c++ +// Create two vectors: [0, 1.0, 5.0] and [1.0, 3.0, 5.0]. +arma::vec a("0.0 1.0 5.0"); +arma::vec b("1.0 3.0 5.0"); + +const double d1 = mlpack::ManhattanDistance::Evaluate(a, b); // d1 = 3.0 +const double d2 = mlpack::EuclideanDistance::Evaluate(a, b); // d2 = 2.24 +const double d3 = mlpack::SquaredEuclideanDistance::Evaluate(a, b); // d3 = 5.0 +const double d4 = mlpack::ChebyshevDistance::Evaluate(a, b); // d4 = 2.0 +const double d5 = mlpack::LMetric<4>::Evaluate(a, b); // d5 = 2.03 +const double d6 = mlpack::LMetric<3, false>::Evaluate(a, b); // d6 = 9.0 + +std::cout << "Manhattan distance: " << d1 << "." << std::endl; +std::cout << "Euclidean distance: " << d2 << "." << std::endl; +std::cout << "Squared Euclidean distance: " << d3 << "." << std::endl; +std::cout << "Chebyshev distance: " << d4 << "." << std::endl; +std::cout << "L4-distance: " << d5 << "." << std::endl; +std::cout << "Cubed L3-distance: " << d6 << "." << std::endl; + +// Compute the distance between two random 10-dimensional vectors in a matrix. +arma::mat m(10, 100, arma::fill::randu); + +const double d7 = mlpack::EuclideanDistance::Evaluate(m.col(0), m.col(7)); + +std::cout << std::endl; +std::cout << "Distance between two random vectors: " << d7 << "." << std::endl; +std::cout << std::endl; + +// Compute the distance between two 32-bit precision `float` vectors. +arma::fvec fa("0.0 1.0 5.0"); +arma::fvec fb("1.0 3.0 5.0"); + +const double d8 = mlpack::EuclideanDistance::Evaluate(fa, fb); // d8 = 2.236 + +std::cout << "Euclidean distance (fvec): " << d8 << "." << std::endl; +``` + +--- + +### `IoUDistance` + +The `IoUDistance` class implements the intersection-over-union distance metric, +a measure of the overlap between two bounding boxes related to the +[Jaccard index](https://en.wikipedia.org/wiki/Jaccard_index). + +For two bounding boxes, the `IoUDistance` is computed as `1 - (area of +intersection / area of union)`. If the bounding boxes overlap completely, the +distance is 0; if they do not overlap at all, the distance is 1. + +--- + +The class has a boolean template parameter `UseCoordinates` that controls how +bounding boxes are specified. + + * `IoUDistance<>` (or `IoUDistance`) expects bounding boxes to be + provided to the `Evaluate()` as four-element vectors of the form + `[x0, y0, h, w]`, where: + - `(x0, y0)` is the lower left corner of the bounding box, + - `h` is the height of the bounding box, and + - `w` is the width of the bounding box. + + * `IoUDistance` expects bounding boxes to be provided to the `Evaluate()` + as four-element vectors of the form `[x0, y0, x1, y1]`, where: + - `(x0, y0)` is the lower left corner of the bounding box, and + - `(x1, y1)` is the upper right corner of the bounding box. + +--- + +The static `Evaluate()` method can be used to compute the IoU distance between +two bounding boxes. + +If either input vector does not have four elements, an exception will be thrown. + +*Note:* The vectors given to `Evaluate()` can have any type so long as the type +implements the Armadillo API (e.g. `arma::vec`, `arma::fvec`, etc.). The use of +sparse objects is not recommended to represent bounding boxes (as they are in +general not sparse). + +--- + +*Example usage:* + +```c++ +// Create three bounding boxes by representing the lower left and size. +arma::vec bb1("0.0 0.0 3.0 5.0"); // Lower left at (0, 0), height=3, width=5. +arma::vec bb2("2.0 2.0 5.0 2.0"); // Lower left at (2, 2), height=5, width=2. +arma::vec bb3("1.0 1.0 1.5 1.0"); // Lower left at (1, 1), height=1.5, width=1. + +// Represent the same three bounding boxes in lower left/upper right form. +arma::vec bb1Coord("0.0 0.0 5.0 3.0"); // Upper right is (5, 3). +arma::vec bb2Coord("2.0 2.0 4.0 7.0"); // Upper right is (4, 7). +arma::vec bb3Coord("1.0 1.0 2.0 2.5"); // Upper right is (2, 2.5). + +// Compute the distance between each of the bounding boxes using the +// height/width representation. +const double d1 = mlpack::IoUDistance<>::Evaluate(bb1, bb2); +const double d2 = mlpack::IoUDistance<>::Evaluate(bb2, bb3); +const double d3 = mlpack::IoUDistance<>::Evaluate(bb1, bb3); + +std::cout << "IoUDistance with width/height bounding box representations:" + << std::endl; +std::cout << " - ll=(0, 0), h=3, w=5 and ll=(2, 2), h=5, w=2: " << d1 + << "." << std::endl; +std::cout << " - ll=(0, 0), h=3, w=5 and ll=(1, 1), h=1.5, w=1: " << d3 + << "." << std::endl; +std::cout << " - ll=(2, 2), h=5, w=2 and ll=(1, 1), h=1.5, w=1: " << d2 + << "." << std::endl; + +// Now compute the same distances with the other representation. +const double d1Coord = mlpack::IoUDistance::Evaluate(bb1Coord, bb2Coord); +const double d2Coord = mlpack::IoUDistance::Evaluate(bb2Coord, bb3Coord); +const double d3Coord = mlpack::IoUDistance::Evaluate(bb1Coord, bb3Coord); + +std::cout << "IoUDistance with two-coordinate bounding box representations:" + << std::endl; +std::cout << "(same bounding boxes as above)" << std::endl; +std::cout << " - ll=(0, 0), ur=(5, 3) and ll=(2, 2), ur=(4, 7): " << d1Coord + << "." << std::endl; +std::cout << " - ll=(0, 0), ur=(5, 3) and ll=(1, 1), ur=(2, 2.5): " << d3Coord + << "." << std::endl; +std::cout << " - ll=(2, 2), ur=(4, 7) and ll=(1, 1), ur=(2, 2.5): " << d2Coord + << "." << std::endl; +``` + +--- + +### `IPMetric` + +The `IPMetric` class implements the distance metric induced by the +given [`KernelType`](#kernels). This computes distances in +[kernel space](https://en.wikipedia.org/wiki/Kernel_method#Mathematics:_the_kernel_trick). +Using the fact that a kernel `k(x, y)` (represented by `KernelType`) implements +an inner product in kernel space, the `IPMetric` distance is defined as + +``` +d(x, y) = sqrt(k(x, x) + k(y, y) - 2 k(x, y)). +``` + +The template parameter `KernelType` can be any of mlpack's [kernels](#kernels), +or a [custom kernel](#implement-a-custom-kernel). + +This metric is used by the [FastMKS](/src/mlpack/methods/fastmks/fastmks.hpp) +method (fast max-kernel search). + +--- + +#### Constructors and properties + + * `d = IPMetric()` + - Construct a new `IPMetric` using a default-constructed `KernelType`. + - A default constructor for `KernelType` must be available (e.g. `k = + KernelType()`). + + * `d = IPMetric(kernel)` + - Construct a new `IPMetric` using the given `kernel` (a `KernelType` + object). + - `kernel` is not copied; ensure that `kernel` does not go out of scope while + `d` is in use. + + * `d = IPMetric(other)` + - Copy constructor: create a new `IPMetric` from the given `IPMetric` + `other`. + - This copies the internally-held `KernelType`. + + * The copy operator (`d = other;`) will also copy the internally-held + `KernelType`. + + * The internally-held `KernelType` can be accessed with `d.Kernel()`. + +--- + +#### Distance evaluation + + * `d.Evaluate(x1, x2)` + - Evaluate and return the distance in kernel space between two vectors `x1` + and `x2`. + - `x1` and `x2` should be vector types that implement the Armadillo API (e.g. + `arma::vec`, `arma::sp_vec`, etc.). + - `x1` and `x2` must be valid inputs to the `Evaluate()` function of the + given `KernelType`. + +--- + +*Example usage:* + +```c++ +// Create a few random points. +arma::vec x1(3, arma::fill::randu); +arma::vec x2(3, arma::fill::randu); +arma::vec x3(3, arma::fill::randu); + +// Create a metric on the Epanechnikov kernel. +mlpack::EpanechnikovKernel ek(1.5 /* bandwidth */); +mlpack::IPMetric ip1(ek); + +// Compute distances in kernel space, and compare with kernel evaluations. +std::cout << "x1: " << x1.t(); +std::cout << "x2: " << x2.t(); +std::cout << "x3: " << x3.t(); +std::cout << std::endl; + +std::cout << " ek(x1, x2): " << ek.Evaluate(x1, x2) << "." << std::endl; +std::cout << " ip(x1, x2): " << ip1.Evaluate(x1, x2) << "." << std::endl; +std::cout << std::endl; + +std::cout << " ek(x2, x3): " << ek.Evaluate(x2, x3) << "." << std::endl; +std::cout << " ip(x2, x3): " << ip1.Evaluate(x2, x3) << "." << std::endl; +std::cout << std::endl; + +std::cout << " ek(x1, x3): " << ek.Evaluate(x1, x3) << "." << std::endl; +std::cout << " ip(x1, x3): " << ip1.Evaluate(x1, x3) << "." << std::endl; +std::cout << std::endl; + +// Now create a metric on the LinearKernel. +// This one is a bit of a trick! For the LinearKernel, the induced metric is +// exactly the Euclidean distance. +mlpack::IPMetric ip2; + +std::cout << " Euclidean distance between x1/x2: " + << mlpack::EuclideanDistance::Evaluate(x1, x2) << "." << std::endl; +std::cout << " IPMetric between x1/x2: " + << ip2.Evaluate(x1, x2) << "." << std::endl; + +// Compute the kernel space distance between two floating-point vectors. +arma::fvec fx1(10, arma::fill::randu); +arma::fvec fx2(10, arma::fill::randu); + +std::cout << "IPMetric result between two random " + << "10-dimensional 32-bit floating point vectors:" << std::endl; +std::cout << " " << ip1.Evaluate(fx1, fx2) << "." << std::endl; +``` + +--- + +### `MahalanobisDistance` + +The `MahalanobisDistance` class implements the weighted Euclidean distance known +as the +[Mahalanobis distance](https://en.wikipedia.org/wiki/Mahalanobis_distance). +This distance requires an inverse covariance matrix `Q` that controls the +weighting of individual dimensions in the distance calculation. The metric is +defined as: + +``` +d_Q(x, y) = sqrt((x - y)^T Q (x - y)) +``` + +The class has two template parameters: + +``` +MahalanobisDistance +``` + + * When `TakeRoot` is manually specified as `false`, the `sqrt()` is omitted. + This is slightly faster, but will cause the distance to no longer satisfy the + triangle inequality. + + * `MatType` is the matrix type used to represent `Q`, and should be a matrix + type satisfying the Armadillo API (e.g. `arma::mat`, `arma::fmat`). + +***Notes:*** + + - Many descriptions of the Mahalanobis distance use the term `C^-1` instead of + `Q` as used here. Ensure that the given `Q` matrix is the inverted + covariance (you can use, e.g., + [`arma::pinv()`](https://arma.sourceforge.net/docs.html#pinv)). + + - Instead of using `MahalanobisDistance` directly as a distance metric for + mlpack machine learning algorithms, it can often be faster to simply multiply + the dataset by the equivalent transformation implied by `Q` and then use that + modified dataset with the Euclidean distance directly. See the example usage + below. + +--- + +#### Constructors and properties + + * `md = MahalanobisDistance()` + - Create a `MahalanobisDistance` object without initializing the inverse + covariance `Q`. + - Call `Q()` to set the matrix before calling `Evaluate()`. + + * `md = MahalanobisDistance(dimensionality)` + - Create a `MahalanobisDistance` where `Q` is the identity matrix of the + given `dimensionality`. + - This distance metric will be equivalent to the Euclidean distance. + + * `md = MahalanobisDistance(matQ)` + - Create a `MahalanobisDistance` with the given `Q` matrix. + - `matQ` must be positive definite and symmetric. + + * `md.Q()` + - Access or modify the `Q` matrix. + - For instance, to set the `Q` matrix, `md.Q() = myCustomQ;` can be used. + - The `Q` matrix must be positive definite and symmetric. + +--- + +#### Distance evaluation + + * `md.Evaluate(x1, x2)` + - Evaluate and return the Mahalanobis distance between two vectors `x1` and + `x2`. + - `x1` and `x2` should be vector types with element type equivalent to the + element type of `MatType` (e.g. `arma::vec`, `arma::fvec`, etc.). + +--- + +*Example usage:* + +```c++ +// Create random 10-dimensional data. +arma::mat dataset(10, 100, arma::fill::randu); + +// Create a positive-definite Q matrix by using a weighting matrix W such that +// Q = W^T W. +arma::mat W(10, 10, arma::fill::randu); +arma::mat Q = W.t() * W; + +// Create a MahalanobisDistance object with the given Q. +mlpack::MahalanobisDistance md(std::move(Q)); + +std::cout << "Mahalanobis distance between points 3 and 4: " + << md.Evaluate(dataset.col(3), dataset.col(4)) << "." << std::endl; + +// Now compare the Mahalanobis distance with the Euclidean distance on the +// dataset transformed with W. (They are the same!) +arma::mat transformedDataset = W * dataset; +std::cout << "Mahalanobis distance between points 2 and 71: " + << md.Evaluate(dataset.col(2), dataset.col(71)) << "." << std::endl; +std::cout << "Euclidean distance between transformed points 2 and 71: " + << mlpack::EuclideanDistance::Evaluate(transformedDataset.col(2), + transformedDataset.col(71)) + << "." << std::endl; + +// Create a Mahalanobis distance for 32-bit floating point data. +arma::fmat floatDataset(20, 100, arma::fill::randn); + +// Use a random diagonal matrix as Q. +arma::fmat fQ = arma::diagmat(arma::randu(20)); + +mlpack::MahalanobisDistance fmd; +fmd.Q() = std::move(fQ); + +const double d1 = fmd.Evaluate(floatDataset.col(3), floatDataset.col(5)); +const double d2 = fmd.Evaluate(floatDataset.col(11), floatDataset.col(31)); + +std::cout << "Squared Mahalanobis distance on 32-bit floating point data:" + << std::endl; +std::cout << " - Points 3 and 5: " << d1 << "." << std::endl; +std::cout << " - Points 11 and 31: " << d2 << "." << std::endl; +``` + +--- + ## Distributions @@ -1130,108 +1556,6 @@ std::cout << "Average probability is: " << arma::mean(probabilities) << "." << std::endl; ``` -## Metrics - -mlpack includes a number of distance metrics for its distance-based techniques. -These all implement the [same API](../developer/metrics.md), providing one -`Evaluate()` method, and can be used with a variety of different techniques, -including: - - - - * [`NeighborSearch`](/src/mlpack/methods/neighbor_search/neighbor_search.hpp) - * [`RangeSearch`](/src/mlpack/methods/range_search/range_search.hpp) - * [`LMNN`](/src/mlpack/methods/lmnn/lmnn.hpp) - * [`EMST`](/src/mlpack/methods/emst/emst.hpp) - * [`NCA`](/src/mlpack/methods/nca/nca.hpp) - * [`RANN`](/src/mlpack/methods/rann/rann.hpp) - * [`KMeans`](/src/mlpack/methods/kmeans/kmeans.hpp) - -Supported metrics: - - * [`LMetric`](#lmetric): generalized L-metric/Lp-metric, including - Manhattan/Euclidean/Chebyshev distances - * [Implement a custom metric](../developer/metrics.md) - -### `LMetric` - -The `LMetric` template class implements a [generalized -L-metric](https://en.wikipedia.org/wiki/Lp_space#Definition) -(L1-metric, L2-metric, etc.). The class has two template parameters: - -``` -LMetric -``` - - * `Power` is an `int` representing the type of the metric; e.g., `2` would - represent the L2-metric (Euclidean distance). - - `Power` must be `1` or greater. - - If `Power` is `INT_MAX`, the metric is the L-infinity distance (Chebyshev - distance). - - * `TakeRoot` is a `bool` (default `true`) indicating whether the root of the - distance should be taken. - - If set to `false`, the metric will no longer satisfy the triangle - inequality. - ---- - -Several convenient typedefs are available: - - * `ManhattanDistance` (defined as `LMetric<1>`) - * `EuclideanDistance` (defined as `LMetric<2>`) - * `SquaredEuclideanDistance` (defined as `LMetric<2, false>`) - * `ChebyshevDistance` (defined as `LMetric`) - ---- - -The static `Evaluate()` method can be used to compute the distance between two -vectors. - -*Note:* The vectors given to `Evaluate()` can have any type so long as the type -implements the Armadillo API (e.g. `arma::fvec`, `arma::sp_fvec`, etc.). - ---- - -*Example usage:* - -```c++ -// Create two vectors: [0, 1.0, 5.0] and [1.0, 3.0, 5.0]. -arma::vec a("0.0 1.0 5.0"); -arma::vec b("1.0 3.0 5.0"); - -const double d1 = mlpack::ManhattanDistance::Evaluate(a, b); // d1 = 3.0 -const double d2 = mlpack::EuclideanDistance::Evaluate(a, b); // d2 = 2.24 -const double d3 = mlpack::SquaredEuclideanDistance::Evaluate(a, b); // d3 = 5.0 -const double d4 = mlpack::ChebyshevDistance::Evaluate(a, b); // d4 = 2.0 -const double d5 = mlpack::LMetric<4>::Evaluate(a, b); // d5 = 2.03 -const double d6 = mlpack::LMetric<3, false>::Evaluate(a, b); // d6 = 9.0 - -std::cout << "Manhattan distance: " << d1 << "." << std::endl; -std::cout << "Euclidean distance: " << d2 << "." << std::endl; -std::cout << "Squared Euclidean distance: " << d3 << "." << std::endl; -std::cout << "Chebyshev distance: " << d4 << "." << std::endl; -std::cout << "L4-distance: " << d5 << "." << std::endl; -std::cout << "Cubed L3-distance: " << d6 << "." << std::endl; - -// Compute the distance between two random 10-dimensional vectors in a matrix. -arma::mat m(10, 100, arma::fill::randu); - -const double d7 = mlpack::EuclideanDistance::Evaluate(m.col(0), m.col(7)); - -std::cout << std::endl; -std::cout << "Distance between two random vectors: " << d7 << "." << std::endl; -std::cout << std::endl; - -// Compute the distance between two 32-bit precision `float` vectors. -arma::fvec fa("0.0 1.0 5.0"); -arma::fvec fb("1.0 3.0 5.0"); - -const double d8 = mlpack::EuclideanDistance::Evaluate(fa, fb); // d8 = 2.236 - -std::cout << "Euclidean distance (fvec): " << d8 << "." << std::endl; -``` - ## Kernels mlpack includes a number of Mercer kernels for its kernel-based techniques. diff --git a/src/mlpack/core.hpp b/src/mlpack/core.hpp index 98c651bfda..5984668113 100644 --- a/src/mlpack/core.hpp +++ b/src/mlpack/core.hpp @@ -50,7 +50,8 @@ #include #endif -#include +#include +#include #include #include #include diff --git a/src/mlpack/core/cv/metrics/facilities.hpp b/src/mlpack/core/cv/metrics/facilities.hpp index 0d55cf2827..46025d0ce9 100644 --- a/src/mlpack/core/cv/metrics/facilities.hpp +++ b/src/mlpack/core/cv/metrics/facilities.hpp @@ -14,7 +14,7 @@ #define MLPACK_CORE_CV_METRICS_FACILITIES_HPP #include -#include +#include namespace mlpack { @@ -24,16 +24,16 @@ namespace mlpack { * @param data Column-major matrix. * @param metric Distance metric to be used. */ -template +template DataType PairwiseDistances(const DataType& data, - const Metric& metric) + const DistanceType& distance) { DataType distances = DataType(data.n_cols, data.n_cols, arma::fill::none); for (size_t i = 0; i < data.n_cols; i++) { for (size_t j = 0; j < i; j++) { - distances(i, j) = metric.Evaluate(data.col(i), data.col(j)); + distances(i, j) = distance.Evaluate(data.col(i), data.col(j)); distances(j, i) = distances(i, j); } } diff --git a/src/mlpack/core/metrics/ip_metric.hpp b/src/mlpack/core/distances/ip_metric.hpp similarity index 94% rename from src/mlpack/core/metrics/ip_metric.hpp rename to src/mlpack/core/distances/ip_metric.hpp index 828f9dbcb2..bef252cdf8 100644 --- a/src/mlpack/core/metrics/ip_metric.hpp +++ b/src/mlpack/core/distances/ip_metric.hpp @@ -1,5 +1,5 @@ /** - * @file core/metrics/ip_metric.hpp + * @file core/distances/ip_metric.hpp * @author Ryan Curtin * * Inner product induced metric. If given a kernel function, this gives the @@ -10,8 +10,8 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ -#ifndef MLPACK_METHODS_FASTMKS_IP_METRIC_HPP -#define MLPACK_METHODS_FASTMKS_IP_METRIC_HPP +#ifndef MLPACK_CORE_DISTANCES_IP_METRIC_HPP +#define MLPACK_CORE_DISTANCES_IP_METRIC_HPP namespace mlpack { diff --git a/src/mlpack/core/metrics/ip_metric_impl.hpp b/src/mlpack/core/distances/ip_metric_impl.hpp similarity index 93% rename from src/mlpack/core/metrics/ip_metric_impl.hpp rename to src/mlpack/core/distances/ip_metric_impl.hpp index 412ef61909..486953064d 100644 --- a/src/mlpack/core/metrics/ip_metric_impl.hpp +++ b/src/mlpack/core/distances/ip_metric_impl.hpp @@ -1,5 +1,5 @@ /** - * @file core/metrics/ip_metric_impl.hpp + * @file core/distances/ip_metric_impl.hpp * @author Ryan Curtin * * Implementation of the IPMetric. @@ -9,13 +9,13 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ -#ifndef MLPACK_METHODS_FASTMKS_IP_METRIC_IMPL_HPP -#define MLPACK_METHODS_FASTMKS_IP_METRIC_IMPL_HPP +#ifndef MLPACK_CORE_DISTANCES_IP_METRIC_IMPL_HPP +#define MLPACK_CORE_DISTANCES_IP_METRIC_IMPL_HPP // In case it hasn't been included yet. #include "ip_metric.hpp" -#include +#include #include namespace mlpack { diff --git a/src/mlpack/core/metrics/lmetric.hpp b/src/mlpack/core/distances/lmetric.hpp similarity index 96% rename from src/mlpack/core/metrics/lmetric.hpp rename to src/mlpack/core/distances/lmetric.hpp index f80c462f41..a15c24713f 100644 --- a/src/mlpack/core/metrics/lmetric.hpp +++ b/src/mlpack/core/distances/lmetric.hpp @@ -1,5 +1,5 @@ /** - * @file core/metrics/lmetric.hpp + * @file core/distances/lmetric.hpp * @author Ryan Curtin * * Generalized L-metric, allowing both squared distances to be returned as well @@ -12,8 +12,8 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ -#ifndef MLPACK_CORE_METRICS_LMETRIC_HPP -#define MLPACK_CORE_METRICS_LMETRIC_HPP +#ifndef MLPACK_CORE_DISTANCES_LMETRIC_HPP +#define MLPACK_CORE_DISTANCES_LMETRIC_HPP #include diff --git a/src/mlpack/core/metrics/lmetric_impl.hpp b/src/mlpack/core/distances/lmetric_impl.hpp similarity index 95% rename from src/mlpack/core/metrics/lmetric_impl.hpp rename to src/mlpack/core/distances/lmetric_impl.hpp index 9705227844..9987192cdf 100644 --- a/src/mlpack/core/metrics/lmetric_impl.hpp +++ b/src/mlpack/core/distances/lmetric_impl.hpp @@ -1,5 +1,5 @@ /** - * @file core/metrics/lmetric_impl.hpp + * @file core/distances/lmetric_impl.hpp * @author Ryan Curtin * * Implementation of template specializations of LMetric class. @@ -9,8 +9,8 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ -#ifndef MLPACK_CORE_METRICS_LMETRIC_IMPL_HPP -#define MLPACK_CORE_METRICS_LMETRIC_IMPL_HPP +#ifndef MLPACK_CORE_DISTANCES_LMETRIC_IMPL_HPP +#define MLPACK_CORE_DISTANCES_LMETRIC_IMPL_HPP // In case it hasn't been included. #include "lmetric.hpp" diff --git a/src/mlpack/core/metrics/mahalanobis_distance.hpp b/src/mlpack/core/distances/mahalanobis_distance.hpp similarity index 53% rename from src/mlpack/core/metrics/mahalanobis_distance.hpp rename to src/mlpack/core/distances/mahalanobis_distance.hpp index ffc3efad4d..39f8eb413a 100644 --- a/src/mlpack/core/metrics/mahalanobis_distance.hpp +++ b/src/mlpack/core/distances/mahalanobis_distance.hpp @@ -1,5 +1,5 @@ /** - * @file core/metrics/mahalanobis_distance.hpp + * @file core/distances/mahalanobis_distance.hpp * @author Ryan Curtin * * The Mahalanobis distance. @@ -9,8 +9,8 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ -#ifndef MLPACK_CORE_METRICS_MAHALANOBIS_DISTANCE_HPP -#define MLPACK_CORE_METRICS_MAHALANOBIS_DISTANCE_HPP +#ifndef MLPACK_CORE_DISTANCES_MAHALANOBIS_DISTANCE_HPP +#define MLPACK_CORE_DISTANCES_MAHALANOBIS_DISTANCE_HPP #include @@ -18,21 +18,21 @@ namespace mlpack { /** * The Mahalanobis distance, which is essentially a stretched Euclidean - * distance. Given a square covariance matrix @f$ Q @f$ of size @f$ d @f$ x - * @f$ d @f$, where @f$ d @f$ is the dimensionality of the points it will be - * evaluating, and given two vectors @f$ x @f$ and @f$ y @f$ also of + * distance. Given a square inverse covariance matrix @f$ Q @f$ of size @f$ d + * @f$ x @f$ d @f$, where @f$ d @f$ is the dimensionality of the points it will + * be evaluating, and given two vectors @f$ x @f$ and @f$ y @f$ also of * dimensionality @f$ d @f$, * * @f[ * d(x, y) = \sqrt{(x - y)^T Q (x - y)} * @f] * - * where Q is the covariance matrix. + * where Q is the inverse covariance matrix. * - * Because each evaluation multiplies (x_1 - x_2) by the covariance matrix, it - * is typically much quicker to use an LMetric and simply stretch the actual - * dataset itself before performing any evaluations. However, this class is - * provided for convenience. + * Because each evaluation multiplies (x_1 - x_2) by the inverse covariance + * matrix, it is typically much quicker to use an LMetric and simply stretch the + * actual dataset itself before performing any evaluations. However, this class + * is provided for convenience. * * If you wish to use the KNN class or other tree-based algorithms with this * distance, it is recommended to instead stretch the dataset first, by @@ -55,13 +55,15 @@ namespace mlpack { * not satisfy the triangle inequality and may not be usable for methods that * expect a true metric. */ -template +template class MahalanobisDistance { public: + typedef typename GetColType::type VecType; + /** - * Initialize the Mahalanobis distance with the empty matrix as covariance. - * Don't call Evaluate() until you set the covariance with Covariance()! + * Initialize the Mahalanobis distance with the empty matrix as Q. + * Don't call Evaluate() until you set the Q matrix with Q()! */ MahalanobisDistance() { } @@ -69,25 +71,24 @@ class MahalanobisDistance * Initialize the Mahalanobis distance with the identity matrix of the given * dimensionality. * - * @param dimensionality Dimesnsionality of the covariance matrix. + * @param dimensionality Dimensionality of the Q matrix. */ MahalanobisDistance(const size_t dimensionality) : - covariance(arma::eye(dimensionality, dimensionality)) { } + q(arma::eye(dimensionality, dimensionality)) { } /** - * Initialize the Mahalanobis distance with the given covariance matrix. The - * given covariance matrix will be copied (this is not optimal). + * Initialize the Mahalanobis distance with the given Q matrix. The given Q + * matrix will be copied (this is not optimal). * - * @param covariance The covariance matrix to use for this distance. + * @param matQ The Q matrix to use for this distance. */ - MahalanobisDistance(arma::mat covariance) : - covariance(std::move(covariance)) { } + MahalanobisDistance(MatType matQ) : q(std::move(matQ)) { } /** * Evaluate the distance between the two given points using this Mahalanobis - * distance. If the covariance matrix has not been set (i.e. if you used the - * empty constructor and did not later modify the covariance matrix), calling - * this method will probably result in a crash. + * distance. If the Q matrix has not been set (i.e. if you used the empty + * constructor and did not later modify the Q matrix), calling this method + * will throw an exception. * * @param a First vector. * @param b Second vector. @@ -95,31 +96,32 @@ class MahalanobisDistance template double Evaluate(const VecTypeA& a, const VecTypeB& b); - /** - * Access the covariance matrix. - * - * @return Constant reference to the covariance matrix. - */ - const arma::mat& Covariance() const { return covariance; } + // Access the Q matrix. + [[deprecated("Will be removed in mlpack 5.0.0. Use Q() instead")]] + const MatType& Covariance() const { return q; } + // Modify the Q matrix. + [[deprecated("Will be removed in mlpack 5.0.0. Use Q() instead")]] + MatType& Covariance() { return q; } - /** - * Modify the covariance matrix. - * - * @return Reference to the covariance matrix. - */ - arma::mat& Covariance() { return covariance; } + // Access the Q matrix. + const MatType& Q() const { return q; } + // Modify the Q matrix. + MatType& Q() { return q; } //! Serialize the Mahalanobis distance. template void serialize(Archive& ar, const uint32_t version); private: - //! The covariance matrix associated with this distance. - arma::mat covariance; + //! The inverse covariance matrix associated with this distance. + MatType q; }; } // namespace mlpack +CEREAL_TEMPLATE_CLASS_VERSION((bool TakeRoot, typename MatType), + (mlpack::MahalanobisDistance), (1)); + #include "mahalanobis_distance_impl.hpp" #endif diff --git a/src/mlpack/core/distances/mahalanobis_distance_impl.hpp b/src/mlpack/core/distances/mahalanobis_distance_impl.hpp new file mode 100644 index 0000000000..f91c4b5041 --- /dev/null +++ b/src/mlpack/core/distances/mahalanobis_distance_impl.hpp @@ -0,0 +1,66 @@ +/** + * @file core/distances/mahalanobis_distance_impl.hpp + * @author Ryan Curtin + * + * Implementation of the Mahalanobis distance. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#ifndef MLPACK_CORE_DISTANCES_MAHALANOBIS_DISTANCE_IMPL_HPP +#define MLPACK_CORE_DISTANCES_MAHALANOBIS_DISTANCE_IMPL_HPP + +#include "mahalanobis_distance.hpp" + +namespace mlpack { + +/** + * Specialization for non-rooted case. + */ +template +template +double MahalanobisDistance::Evaluate( + const VecTypeA& a, const VecTypeB& b) +{ + // Check if Q matrix has been initialized. + if (q.n_rows != a.n_elem) + { + std::ostringstream oss; + oss << "MahalanobisDistance::Evaluate(): given vector dimensionality (" + << a.n_elem << ") does not match Q dimensionality (" << q.n_rows + << ")!"; + throw std::runtime_error(oss.str()); + } + + VecType m = (a - b); + if (TakeRoot == true) + return std::sqrt(as_scalar(m.t() * q * m)); + else + return as_scalar(m.t() * q * m); // 1x1 +} + +// Serialize the Mahalanobis distance. +template +template +void MahalanobisDistance::serialize( + Archive& ar, const uint32_t version) +{ + if (Archive::is_loading::value && version == 0) + { + // Older versions of MahalanobisDistance always serialized as an arma::mat + // named "covariance". + arma::mat qTmp; + ar(cereal::make_nvp("covariance", qTmp)); + q = arma::conv_to::from(qTmp); + } + else + { + ar(CEREAL_NVP(q)); + } +} + +} // namespace mlpack + +#endif diff --git a/src/mlpack/core/dists/diagonal_gaussian_distribution.hpp b/src/mlpack/core/distributions/diagonal_gaussian_distribution.hpp similarity index 98% rename from src/mlpack/core/dists/diagonal_gaussian_distribution.hpp rename to src/mlpack/core/distributions/diagonal_gaussian_distribution.hpp index 819ec5d06f..b604366084 100644 --- a/src/mlpack/core/dists/diagonal_gaussian_distribution.hpp +++ b/src/mlpack/core/distributions/diagonal_gaussian_distribution.hpp @@ -1,5 +1,5 @@ /** - * @file core/dists/diagonal_gaussian_distribution.hpp + * @file core/distributions/diagonal_gaussian_distribution.hpp * @author Kim SangYeon * * Implementation of the Gaussian distribution with diagonal covariance. diff --git a/src/mlpack/core/dists/diagonal_gaussian_distribution_impl.hpp b/src/mlpack/core/distributions/diagonal_gaussian_distribution_impl.hpp similarity index 98% rename from src/mlpack/core/dists/diagonal_gaussian_distribution_impl.hpp rename to src/mlpack/core/distributions/diagonal_gaussian_distribution_impl.hpp index 6978e20093..1cf0763229 100644 --- a/src/mlpack/core/dists/diagonal_gaussian_distribution_impl.hpp +++ b/src/mlpack/core/distributions/diagonal_gaussian_distribution_impl.hpp @@ -1,5 +1,5 @@ /** - * @file core/dists/diagonal_gaussian_distribution_impl.hpp + * @file core/distributions/diagonal_gaussian_distribution_impl.hpp * @author Kim SangYeon * * Implementation of Gaussian distribution class with diagonal covariance. diff --git a/src/mlpack/core/dists/discrete_distribution.hpp b/src/mlpack/core/distributions/discrete_distribution.hpp similarity index 99% rename from src/mlpack/core/dists/discrete_distribution.hpp rename to src/mlpack/core/distributions/discrete_distribution.hpp index 2d483847a5..f447316834 100644 --- a/src/mlpack/core/dists/discrete_distribution.hpp +++ b/src/mlpack/core/distributions/discrete_distribution.hpp @@ -1,5 +1,5 @@ /** - * @file core/dists/discrete_distribution.hpp + * @file core/distributions/discrete_distribution.hpp * @author Ryan Curtin * @author Rohan Raj * diff --git a/src/mlpack/core/dists/discrete_distribution_impl.hpp b/src/mlpack/core/distributions/discrete_distribution_impl.hpp similarity index 98% rename from src/mlpack/core/dists/discrete_distribution_impl.hpp rename to src/mlpack/core/distributions/discrete_distribution_impl.hpp index 19a35e4b45..4643d61d03 100644 --- a/src/mlpack/core/dists/discrete_distribution_impl.hpp +++ b/src/mlpack/core/distributions/discrete_distribution_impl.hpp @@ -1,5 +1,5 @@ /** - * @file core/dists/discrete_distribution_impl.hpp + * @file core/distributions/discrete_distribution_impl.hpp * @author Ryan Curtin * @author Rohan Raj * diff --git a/src/mlpack/core/dists/dists.hpp b/src/mlpack/core/distributions/distributions.hpp similarity index 80% rename from src/mlpack/core/dists/dists.hpp rename to src/mlpack/core/distributions/distributions.hpp index b8e837183d..ab594c1a32 100644 --- a/src/mlpack/core/dists/dists.hpp +++ b/src/mlpack/core/distributions/distributions.hpp @@ -1,5 +1,5 @@ /** - * @file core/dists/dists.hpp + * @file core/distributions/distributions.hpp * @author Ryan Curtin * * Convenience include for all distributions. @@ -9,8 +9,8 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ -#ifndef MLPACK_CORE_DISTS_DISTS_HPP -#define MLPACK_CORE_DISTS_DISTS_HPP +#ifndef MLPACK_CORE_DISTRIBUTIONS_DISTRIBUTIONS_HPP +#define MLPACK_CORE_DISTRIBUTIONS_DISTRIBUTIONS_HPP #include "diagonal_gaussian_distribution.hpp" #include "discrete_distribution.hpp" diff --git a/src/mlpack/core/dists/gamma_distribution.hpp b/src/mlpack/core/distributions/gamma_distribution.hpp similarity index 99% rename from src/mlpack/core/dists/gamma_distribution.hpp rename to src/mlpack/core/distributions/gamma_distribution.hpp index 91a511e2a7..607fa81994 100644 --- a/src/mlpack/core/dists/gamma_distribution.hpp +++ b/src/mlpack/core/distributions/gamma_distribution.hpp @@ -1,5 +1,5 @@ /** - * @file core/dists/gamma_distribution.hpp + * @file core/distributions/gamma_distribution.hpp * @author Yannis Mentekidis * @author Rohan Raj * diff --git a/src/mlpack/core/dists/gamma_distribution_impl.hpp b/src/mlpack/core/distributions/gamma_distribution_impl.hpp similarity index 99% rename from src/mlpack/core/dists/gamma_distribution_impl.hpp rename to src/mlpack/core/distributions/gamma_distribution_impl.hpp index 15c4a668f3..87c02d068e 100644 --- a/src/mlpack/core/dists/gamma_distribution_impl.hpp +++ b/src/mlpack/core/distributions/gamma_distribution_impl.hpp @@ -1,5 +1,5 @@ /** - * @file core/dists/gamma_distribution_impl.hpp + * @file core/distributions/gamma_distribution_impl.hpp * @author Yannis Mentekidis * @author Rohan Raj * diff --git a/src/mlpack/core/dists/gaussian_distribution.hpp b/src/mlpack/core/distributions/gaussian_distribution.hpp similarity index 99% rename from src/mlpack/core/dists/gaussian_distribution.hpp rename to src/mlpack/core/distributions/gaussian_distribution.hpp index d5231a76ca..0f48ec4808 100644 --- a/src/mlpack/core/dists/gaussian_distribution.hpp +++ b/src/mlpack/core/distributions/gaussian_distribution.hpp @@ -1,5 +1,5 @@ /** - * @file core/dists/gaussian_distribution.hpp + * @file core/distributions/gaussian_distribution.hpp * @author Ryan Curtin * @author Michael Fox * diff --git a/src/mlpack/core/dists/gaussian_distribution_impl.hpp b/src/mlpack/core/distributions/gaussian_distribution_impl.hpp similarity index 98% rename from src/mlpack/core/dists/gaussian_distribution_impl.hpp rename to src/mlpack/core/distributions/gaussian_distribution_impl.hpp index 0304ea131b..9a618179c7 100644 --- a/src/mlpack/core/dists/gaussian_distribution_impl.hpp +++ b/src/mlpack/core/distributions/gaussian_distribution_impl.hpp @@ -1,5 +1,5 @@ /** - * @file core/dists/gaussian_distribution_impl.hpp + * @file core/distributions/gaussian_distribution_impl.hpp * @author Ryan Curtin * @author Michael Fox * diff --git a/src/mlpack/core/dists/laplace_distribution.hpp b/src/mlpack/core/distributions/laplace_distribution.hpp similarity index 99% rename from src/mlpack/core/dists/laplace_distribution.hpp rename to src/mlpack/core/distributions/laplace_distribution.hpp index 2ebafd92f0..0d5f9f61e7 100644 --- a/src/mlpack/core/dists/laplace_distribution.hpp +++ b/src/mlpack/core/distributions/laplace_distribution.hpp @@ -1,5 +1,5 @@ /* - * @file core/dists/laplace_distribution.hpp + * @file core/distributions/laplace_distribution.hpp * @author Zhihao Lou * @author Rohan Raj * @@ -10,7 +10,6 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ - #ifndef MLPACK_CORE_DISTRIBUTIONS_LAPLACE_DISTRIBUTION_HPP #define MLPACK_CORE_DISTRIBUTIONS_LAPLACE_DISTRIBUTION_HPP diff --git a/src/mlpack/core/dists/laplace_distribution_impl.hpp b/src/mlpack/core/distributions/laplace_distribution_impl.hpp similarity index 98% rename from src/mlpack/core/dists/laplace_distribution_impl.hpp rename to src/mlpack/core/distributions/laplace_distribution_impl.hpp index 80a794117a..4e9ed2da57 100644 --- a/src/mlpack/core/dists/laplace_distribution_impl.hpp +++ b/src/mlpack/core/distributions/laplace_distribution_impl.hpp @@ -1,5 +1,5 @@ /* - * @file core/dists/laplace_distribution_impl.hpp + * @file core/distributions/laplace_distribution_impl.hpp * @author Zhihao Lou * @author Rohan Raj * diff --git a/src/mlpack/core/dists/regression_distribution.hpp b/src/mlpack/core/distributions/regression_distribution.hpp similarity index 94% rename from src/mlpack/core/dists/regression_distribution.hpp rename to src/mlpack/core/distributions/regression_distribution.hpp index 703bffd7c0..654aedcb6a 100644 --- a/src/mlpack/core/dists/regression_distribution.hpp +++ b/src/mlpack/core/distributions/regression_distribution.hpp @@ -1,5 +1,5 @@ /** - * @file core/dists/regression_distribution.hpp + * @file core/distributions/regression_distribution.hpp * @author Michael Fox * * Implementation of conditional Gaussian distribution for HMM regression @@ -10,11 +10,11 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ -#ifndef MLPACK_CORE_DISTS_REGRESSION_DISTRIBUTION_HPP -#define MLPACK_CORE_DISTS_REGRESSION_DISTRIBUTION_HPP +#ifndef MLPACK_CORE_DISTRIBUTIONS_REGRESSION_DISTRIBUTION_HPP +#define MLPACK_CORE_DISTRIBUTIONS_REGRESSION_DISTRIBUTION_HPP #include -#include +#include #include namespace mlpack { diff --git a/src/mlpack/core/dists/regression_distribution_impl.hpp b/src/mlpack/core/distributions/regression_distribution_impl.hpp similarity index 90% rename from src/mlpack/core/dists/regression_distribution_impl.hpp rename to src/mlpack/core/distributions/regression_distribution_impl.hpp index c1c9edde34..f49a6a5e4d 100644 --- a/src/mlpack/core/dists/regression_distribution_impl.hpp +++ b/src/mlpack/core/distributions/regression_distribution_impl.hpp @@ -1,5 +1,5 @@ /** - * @file core/dists/regression_distribution_impl.hpp + * @file core/distributions/regression_distribution_impl.hpp * @author Michael Fox * * Implementation of conditional Gaussian distribution for HMM regression @@ -10,8 +10,8 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ -#ifndef MLPACK_CORE_DISTS_REGRESSION_DISTRIBUTION_IMPL_HPP -#define MLPACK_CORE_DISTS_REGRESSION_DISTRIBUTION_IMPL_HPP +#ifndef MLPACK_CORE_DISTRIBUTIONS_REGRESSION_DISTRIBUTION_IMPL_HPP +#define MLPACK_CORE_DISTRIBUTIONS_REGRESSION_DISTRIBUTION_IMPL_HPP #include "regression_distribution.hpp" diff --git a/src/mlpack/core/kernels/cauchy_kernel.hpp b/src/mlpack/core/kernels/cauchy_kernel.hpp index d9f3376c3d..7ad9912517 100644 --- a/src/mlpack/core/kernels/cauchy_kernel.hpp +++ b/src/mlpack/core/kernels/cauchy_kernel.hpp @@ -13,7 +13,7 @@ #define MLPACK_CORE_KERNELS_CAUCHY_KERNEL_HPP #include -#include +#include #include namespace mlpack { diff --git a/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp b/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp index c8894bba2e..2c7c4da14c 100644 --- a/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp +++ b/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp @@ -16,7 +16,7 @@ #include "epanechnikov_kernel.hpp" #include -#include +#include namespace mlpack { diff --git a/src/mlpack/core/kernels/gaussian_kernel.hpp b/src/mlpack/core/kernels/gaussian_kernel.hpp index 9837be94e9..d5eb8da3d0 100644 --- a/src/mlpack/core/kernels/gaussian_kernel.hpp +++ b/src/mlpack/core/kernels/gaussian_kernel.hpp @@ -15,7 +15,7 @@ #define MLPACK_CORE_KERNELS_GAUSSIAN_KERNEL_HPP #include -#include +#include #include namespace mlpack { diff --git a/src/mlpack/core/kernels/triangular_kernel.hpp b/src/mlpack/core/kernels/triangular_kernel.hpp index 639e5fb9f0..ac2d14ed43 100644 --- a/src/mlpack/core/kernels/triangular_kernel.hpp +++ b/src/mlpack/core/kernels/triangular_kernel.hpp @@ -13,7 +13,7 @@ #define MLPACK_CORE_KERNELS_TRIANGULAR_KERNEL_HPP #include -#include +#include namespace mlpack { diff --git a/src/mlpack/core/metrics/iou_metric.hpp b/src/mlpack/core/metrics/iou_metric.hpp index f6e5b3fcc1..d495a5d7e8 100644 --- a/src/mlpack/core/metrics/iou_metric.hpp +++ b/src/mlpack/core/metrics/iou_metric.hpp @@ -13,6 +13,7 @@ */ #ifndef MLPACK_CORE_METRICS_IOU_HPP #define MLPACK_CORE_METRICS_IOU_HPP + #include namespace mlpack { @@ -29,21 +30,15 @@ namespace mlpack { * Where x0 and y0 are bottom left bounding box coordinates and h, w are * height and width of the bounding box. * - * @tparam useCoordinates Toggles between the two representation of bounding box. - * If true, each value in vector represents a coordinate - * in the formate x0, y0, x1, y1. Else the bounding box is - * represented as x0, y0, h, w. + * @tparam useCoordinates Toggles between the two representation of bounding + * box. If true, each value in vector represents a coordinate in the + * format x0, y0, x1, y1. Else the bounding box is represented as x0, y0, + * h, w. */ template class IoU { public: - //! Default constructor required to satisfy the Metric policy. - IoU() - { - // Nothing to do here. - } - /** * Computes the Intersection over Union metric between of two * bounding boxes having pattern bx, by, h, w. diff --git a/src/mlpack/core/metrics/mahalanobis_distance_impl.hpp b/src/mlpack/core/metrics/mahalanobis_distance_impl.hpp deleted file mode 100644 index 5787921a75..0000000000 --- a/src/mlpack/core/metrics/mahalanobis_distance_impl.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file core/metrics/mahalanobis_distance_impl.hpp - * @author Ryan Curtin - * - * Implementation of the Mahalanobis distance. - * - * mlpack is free software; you may redistribute it and/or modify it under the - * terms of the 3-clause BSD license. You should have received a copy of the - * 3-clause BSD license along with mlpack. If not, see - * http://www.opensource.org/licenses/BSD-3-Clause for more information. - */ -#ifndef MLPACK_CORE_METRICS_MAHALANOBIS_DISTANCE_IMPL_HPP -#define MLPACK_CORE_METRICS_MAHALANOBIS_DISTANCE_IMPL_HPP - -#include "mahalanobis_distance.hpp" - -namespace mlpack { - -/** - * Specialization for non-rooted case. - */ -template<> -template -double MahalanobisDistance::Evaluate(const VecTypeA& a, - const VecTypeB& b) -{ - arma::vec m = (a - b); - arma::mat out = trans(m) * covariance * m; // 1x1 - return out[0]; -} -/** - * Specialization for rooted case. This requires one extra evaluation of - * sqrt(). - */ -template<> -template -double MahalanobisDistance::Evaluate(const VecTypeA& a, - const VecTypeB& b) -{ - // Check if covariance matrix has been initialized. - if (covariance.n_rows == 0) - covariance = arma::eye(a.n_elem, a.n_elem); - - arma::vec m = (a - b); - arma::mat out = trans(m) * covariance * m; // 1x1; - return std::sqrt(out[0]); -} - -// Serialize the Mahalanobis distance. -template -template -void MahalanobisDistance::serialize(Archive& ar, - const uint32_t /* version */) -{ - ar(CEREAL_NVP(covariance)); -} - -} // namespace mlpack - -#endif diff --git a/src/mlpack/core/metrics/metrics.hpp b/src/mlpack/core/metrics/metrics.hpp index 3acd3e792f..1b527362df 100644 --- a/src/mlpack/core/metrics/metrics.hpp +++ b/src/mlpack/core/metrics/metrics.hpp @@ -2,8 +2,10 @@ * @file core/metrics/metrics.hpp * @author Ryan Curtin * - * Include all distance metrics implemented by mlpack. Note that these are not - * performance metrics for models---see core/cv/metrics/metrics.hpp instead. + * Include all performance metrics and scoring functions implemented by mlpack. + * For distance metrics (e.g. distances in metric spaces that satisfy the + * triangle inequality and formal definition of distance metric), see + * core/distances/ instead. * * mlpack is free software; you may redistribute it and/or modify it under the * terms of the 3-clause BSD license. You should have received a copy of the @@ -15,9 +17,6 @@ #include "bleu.hpp" // Technically this should go somewhere else... #include "iou_metric.hpp" -#include "ip_metric.hpp" -#include "lmetric.hpp" -#include "mahalanobis_distance.hpp" #include "non_maximal_suppression.hpp" #endif diff --git a/src/mlpack/core/tree/ballbound.hpp b/src/mlpack/core/tree/ballbound.hpp index 28c0d3cf42..0f1f8f9636 100644 --- a/src/mlpack/core/tree/ballbound.hpp +++ b/src/mlpack/core/tree/ballbound.hpp @@ -13,20 +13,20 @@ #define MLPACK_CORE_TREE_BALLBOUND_HPP #include -#include +#include #include "bound_traits.hpp" namespace mlpack { /** * Ball bound encloses a set of points at a specific distance (radius) from a - * specific point (center). MetricType is the custom metric type that defaults - * to the Euclidean (L2) distance. + * specific point (center). DistanceType is the custom distance metric type that + * defaults to the Euclidean (L2) distance. * - * @tparam MetricType metric type used in the distance measure. + * @tparam DistanceType distance metric type used in the distance measure. * @tparam VecType Type of vector (arma::vec or arma::sp_vec or similar). */ -template, +template, typename VecType = arma::vec> class BallBound { @@ -42,15 +42,15 @@ class BallBound //! The center of the ball bound. VecType center; //! The metric used in this bound. - MetricType* metric; + DistanceType* distance; /** - * To know whether this object allocated memory to the metric member + * To know whether this object allocated memory to the distance metric member * variable. This will be true except in the copy constructor and the * overloaded assignment operator. We need this to know whether we should - * delete the metric member variable in the destructor. + * delete the distance metric member variable in the destructor. */ - bool ownsMetric; + bool ownsDistance; public: //! Empty Constructor. @@ -199,9 +199,16 @@ class BallBound ElemType Diameter() const { return 2 * radius; } //! Returns the distance metric used in this bound. - const MetricType& Metric() const { return *metric; } + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + const DistanceType& Metric() const { return *distance; } //! Modify the distance metric used in this bound. - MetricType& Metric() { return *metric; } + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + DistanceType& Metric() { return *distance; } + + //! Returns the distance metric used in this bound. + const DistanceType& Distance() const { return *distance; } + //! Modify the distance metric used in this bound. + DistanceType& Distance() { return *distance; } //! Serialize the bound. template @@ -209,8 +216,8 @@ class BallBound }; //! A specialization of BoundTraits for this bound type. -template -struct BoundTraits> +template +struct BoundTraits> { //! These bounds are potentially loose in some dimensions. const static bool HasTightBounds = false; diff --git a/src/mlpack/core/tree/ballbound_impl.hpp b/src/mlpack/core/tree/ballbound_impl.hpp index dbd52d0643..8098d326c0 100644 --- a/src/mlpack/core/tree/ballbound_impl.hpp +++ b/src/mlpack/core/tree/ballbound_impl.hpp @@ -2,7 +2,7 @@ * @file core/tree/ballbound_impl.hpp * * Bounds that are useful for binary space partitioning trees. - * Implementation of BallBound ball bound metric policy class. + * Implementation of BallBound ball bound policy class. * * mlpack is free software; you may redistribute it and/or modify it under the * terms of the 3-clause BSD license. You should have received a copy of the @@ -20,11 +20,11 @@ namespace mlpack { //! Empty Constructor. -template -BallBound::BallBound() : +template +BallBound::BallBound() : radius(std::numeric_limits::lowest()), - metric(new MetricType()), - ownsMetric(true) + distance(new DistanceType()), + ownsDistance(true) { /* Nothing to do. */ } /** @@ -32,12 +32,12 @@ BallBound::BallBound() : * * @param dimension Dimensionality of ball bound. */ -template -BallBound::BallBound(const size_t dimension) : +template +BallBound::BallBound(const size_t dimension) : radius(std::numeric_limits::lowest()), center(dimension), - metric(new MetricType()), - ownsMetric(true) + distance(new DistanceType()), + ownsDistance(true) { /* Nothing to do. */ } /** @@ -46,86 +46,86 @@ BallBound::BallBound(const size_t dimension) : * @param radius Radius of ball bound. * @param center Center of ball bound. */ -template -BallBound::BallBound(const ElemType radius, +template +BallBound::BallBound(const ElemType radius, const VecType& center) : radius(radius), center(center), - metric(new MetricType()), - ownsMetric(true) + distance(new DistanceType()), + ownsDistance(true) { /* Nothing to do. */ } //! Copy Constructor. To prevent memory leaks. -template -BallBound::BallBound(const BallBound& other) : +template +BallBound::BallBound(const BallBound& other) : radius(other.radius), center(other.center), - metric(other.metric), - ownsMetric(false) + distance(other.distance), + ownsDistance(false) { /* Nothing to do. */ } //! For the same reason as the copy constructor: to prevent memory leaks. -template -BallBound& BallBound::operator=( +template +BallBound& BallBound::operator=( const BallBound& other) { if (this != &other) { radius = other.radius; center = other.center; - metric = other.metric; - ownsMetric = false; + distance = other.distance; + ownsDistance = false; } return *this; } //! Move constructor. -template -BallBound::BallBound(BallBound&& other) : +template +BallBound::BallBound(BallBound&& other) : radius(other.radius), center(other.center), - metric(other.metric), - ownsMetric(other.ownsMetric) + distance(other.distance), + ownsDistance(other.ownsDistance) { // Fix the other bound. other.radius = 0.0; other.center = VecType(); - other.metric = NULL; - other.ownsMetric = false; + other.distance = NULL; + other.ownsDistance = false; } //! Move assignment operator. -template -BallBound& BallBound::operator=( +template +BallBound& BallBound::operator=( BallBound&& other) { if (this != &other) { radius = other.radius; center = std::move(other.center); - metric = other.metric; - ownsMetric = other.ownsMetric; + distance = other.distance; + ownsDistance = other.ownsDistance; other.radius = 0.0; other.center = VecType(); - other.metric = nullptr; - other.ownsMetric = false; + other.distance = nullptr; + other.ownsDistance = false; } return *this; } //! Destructor to release allocated memory. -template -BallBound::~BallBound() +template +BallBound::~BallBound() { - if (ownsMetric) - delete metric; + if (ownsDistance) + delete distance; } //! Get the range in a certain dimension. -template -RangeType::ElemType> -BallBound::operator[](const size_t i) const +template +RangeType::ElemType> +BallBound::operator[](const size_t i) const { if (radius < 0) return Range(); @@ -136,44 +136,44 @@ BallBound::operator[](const size_t i) const /** * Determines if a point is within the bound. */ -template -bool BallBound::Contains(const VecType& point) const +template +bool BallBound::Contains(const VecType& point) const { if (radius < 0) return false; else - return metric->Evaluate(center, point) <= radius; + return distance->Evaluate(center, point) <= radius; } /** * Calculates minimum bound-to-point squared distance. */ -template +template template -typename BallBound::ElemType -BallBound::MinDistance( +typename BallBound::ElemType +BallBound::MinDistance( const OtherVecType& point, typename std::enable_if_t::value>* /* junk */) const { if (radius < 0) return std::numeric_limits::max(); else - return std::max(metric->Evaluate(point, center) - radius, (ElemType) 0.0); + return std::max(distance->Evaluate(point, center) - radius, (ElemType) 0.0); } /** * Calculates minimum bound-to-bound squared distance. */ -template -typename BallBound::ElemType -BallBound::MinDistance(const BallBound& other) +template +typename BallBound::ElemType +BallBound::MinDistance(const BallBound& other) const { if (radius < 0) return std::numeric_limits::max(); else { - const ElemType delta = metric->Evaluate(center, other.center) - radius - + const ElemType delta = distance->Evaluate(center, other.center) - radius - other.radius; return std::max(delta, (ElemType) 0.0); } @@ -182,31 +182,31 @@ BallBound::MinDistance(const BallBound& other) /** * Computes maximum distance. */ -template +template template -typename BallBound::ElemType -BallBound::MaxDistance( +typename BallBound::ElemType +BallBound::MaxDistance( const OtherVecType& point, typename std::enable_if_t::value>* /* junk */) const { if (radius < 0) return std::numeric_limits::max(); else - return metric->Evaluate(point, center) + radius; + return distance->Evaluate(point, center) + radius; } /** * Computes maximum distance. */ -template -typename BallBound::ElemType -BallBound::MaxDistance(const BallBound& other) +template +typename BallBound::ElemType +BallBound::MaxDistance(const BallBound& other) const { if (radius < 0) return std::numeric_limits::max(); else - return metric->Evaluate(other.center, center) + radius + other.radius; + return distance->Evaluate(other.center, center) + radius + other.radius; } /** @@ -214,10 +214,10 @@ BallBound::MaxDistance(const BallBound& other) * * Example: bound1.MinDistanceSq(other) for minimum squared distance. */ -template +template template -RangeType::ElemType> -BallBound::RangeDistance( +RangeType::ElemType> +BallBound::RangeDistance( const OtherVecType& point, typename std::enable_if_t::value>* /* junk */) const { @@ -226,14 +226,14 @@ BallBound::RangeDistance( std::numeric_limits::max()); else { - const ElemType dist = metric->Evaluate(center, point); + const ElemType dist = distance->Evaluate(center, point); return Range(std::max(dist - radius, (ElemType) 0.0), dist + radius); } } -template -RangeType::ElemType> -BallBound::RangeDistance( +template +RangeType::ElemType> +BallBound::RangeDistance( const BallBound& other) const { if (radius < 0) @@ -241,39 +241,22 @@ BallBound::RangeDistance( std::numeric_limits::max()); else { - const ElemType dist = metric->Evaluate(center, other.center); + const ElemType dist = distance->Evaluate(center, other.center); const ElemType sumradius = radius + other.radius; return Range(std::max(dist - sumradius, (ElemType) 0.0), dist + sumradius); } } -/** - * Expand the bound to include the given bound. - * -template -const BallBound& -BallBound::operator|=( - const BallBound& other) -{ - double dist = metric->Evaluate(center, other); - - // Now expand the radius as necessary. - if (dist > radius) - radius = dist; - - return *this; -}*/ - /** * Expand the bound to include the given point. Algorithm adapted from * Jack Ritter, "An Efficient Bounding Sphere" in Graphics Gems (1990). * The difference lies in the way we initialize the ball bound. The way we * expand the bound is same. */ -template +template template -const BallBound& -BallBound::operator|=(const MatType& data) +const BallBound& +BallBound::operator|=(const MatType& data) { if (radius < 0) { @@ -284,7 +267,7 @@ BallBound::operator|=(const MatType& data) // Now iteratively add points. for (size_t i = 0; i < data.n_cols; ++i) { - const ElemType dist = metric->Evaluate(center, (VecType) data.col(i)); + const ElemType dist = distance->Evaluate(center, (VecType) data.col(i)); // See if the new point lies outside the bound. if (dist > radius) @@ -301,9 +284,9 @@ BallBound::operator|=(const MatType& data) } //! Serialize the BallBound. -template +template template -void BallBound::serialize( +void BallBound::serialize( Archive& ar, const uint32_t /* version */) { @@ -312,13 +295,14 @@ void BallBound::serialize( if (cereal::is_loading()) { - // If we're loading, delete the local metric since we'll have a new one. - if (ownsMetric) - delete metric; + // If we're loading, delete the local distance metric since we'll have a new + // one. + if (ownsDistance) + delete distance; } - ar(CEREAL_POINTER(metric)); - ar(CEREAL_NVP(ownsMetric)); + ar(CEREAL_POINTER(distance)); + ar(CEREAL_NVP(ownsDistance)); } } // namespace mlpack diff --git a/src/mlpack/core/tree/binary_space_tree/binary_space_tree.hpp b/src/mlpack/core/tree/binary_space_tree/binary_space_tree.hpp index 8289e0179f..050f26e553 100644 --- a/src/mlpack/core/tree/binary_space_tree/binary_space_tree.hpp +++ b/src/mlpack/core/tree/binary_space_tree/binary_space_tree.hpp @@ -31,22 +31,22 @@ namespace mlpack { * This tree does take one runtime parameter in the constructor, which is the * max leaf size to be used. * - * @tparam MetricType The metric used for tree-building. The BoundType may - * place restrictions on the metrics that can be used. + * @tparam DistanceType The distance metric used for tree-building. The + * BoundType may place restrictions on the metrics that can be used. * @tparam StatisticType Extra data contained in the node. See statistic.hpp * for the necessary skeleton interface. * @tparam MatType The dataset class. * @tparam BoundType The bound used for each node. HRectBound, the default, - * requires that an LMetric<> is used for MetricType (so, EuclideanDistance, - * ManhattanDistance, etc.). + * requires that an LMetric<> is used for DistanceType (so, + * EuclideanDistance, ManhattanDistance, etc.). * @tparam SplitType The class that partitions the dataset/points at a * particular node into two parts. Its definition decides the way this split * is done. */ -template class BoundType = + template class BoundType = HRectBound, template class SplitType = MidpointSplit> @@ -58,7 +58,7 @@ class BinarySpaceTree //! The type of element held in MatType. typedef typename MatType::elem_type ElemType; - typedef SplitType, MatType> Split; + typedef SplitType, MatType> Split; private: //! The left child node. @@ -74,7 +74,7 @@ class BinarySpaceTree //! children). size_t count; //! The bound object for this node. - BoundType bound; + BoundType bound; //! Any extra data contained in the node. StatisticType stat; //! The distance from the centroid of this node to the centroid of the parent. @@ -210,7 +210,7 @@ class BinarySpaceTree BinarySpaceTree(BinarySpaceTree* parent, const size_t begin, const size_t count, - SplitType, MatType>& splitter, + SplitType, MatType>& splitter, const size_t maxLeafSize = 20); /** @@ -236,7 +236,7 @@ class BinarySpaceTree const size_t begin, const size_t count, std::vector& oldFromNew, - SplitType, MatType>& splitter, + SplitType, MatType>& splitter, const size_t maxLeafSize = 20); /** @@ -266,7 +266,7 @@ class BinarySpaceTree const size_t count, std::vector& oldFromNew, std::vector& newFromOld, - SplitType, MatType>& splitter, + SplitType, MatType>& splitter, const size_t maxLeafSize = 20); /** @@ -315,9 +315,9 @@ class BinarySpaceTree ~BinarySpaceTree(); //! Return the bound object for this node. - const BoundType& Bound() const { return bound; } + const BoundType& Bound() const { return bound; } //! Return the bound object for this node. - BoundType& Bound() { return bound; } + BoundType& Bound() { return bound; } //! Return the statistic object for this node. const StatisticType& Stat() const { return stat; } @@ -348,7 +348,11 @@ class BinarySpaceTree MatType& Dataset() { return *dataset; } //! Get the metric that the tree uses. - MetricType Metric() const { return MetricType(); } + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + DistanceType Metric() const { return DistanceType(); } + + //! Get the metric that the tree uses. + DistanceType Distance() const { return DistanceType(); } //! Return the number of children in this node. size_t NumChildren() const; @@ -514,7 +518,7 @@ class BinarySpaceTree * @param splitter Instantiated SplitType object. */ void SplitNode(const size_t maxLeafSize, - SplitType, MatType>& splitter); + SplitType, MatType>& splitter); /** * Splits the current node, assigning its left and right children recursively. @@ -526,7 +530,7 @@ class BinarySpaceTree */ void SplitNode(std::vector& oldFromNew, const size_t maxLeafSize, - SplitType, MatType>& splitter); + SplitType, MatType>& splitter); /** * Update the bound of the current node. This method does not take into @@ -543,7 +547,7 @@ class BinarySpaceTree * * @param boundToUpdate The bound to update. */ - void UpdateBound(HollowBallBound& boundToUpdate); + void UpdateBound(HollowBallBound& boundToUpdate); protected: /** diff --git a/src/mlpack/core/tree/binary_space_tree/binary_space_tree_impl.hpp b/src/mlpack/core/tree/binary_space_tree/binary_space_tree_impl.hpp index da5bd3d3ba..7859364462 100644 --- a/src/mlpack/core/tree/binary_space_tree/binary_space_tree_impl.hpp +++ b/src/mlpack/core/tree/binary_space_tree/binary_space_tree_impl.hpp @@ -21,13 +21,13 @@ namespace mlpack { // Each of these overloads is kept as a separate function to keep the overhead // from the two std::vectors out, if possible. -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree:: +BinarySpaceTree:: BinarySpaceTree( const MatType& data, const size_t maxLeafSize) : @@ -41,20 +41,20 @@ BinarySpaceTree( dataset(new MatType(data)) // Copies the dataset. { // Do the actual splitting of this node. - SplitType, MatType> splitter; + SplitType, MatType> splitter; SplitNode(maxLeafSize, splitter); // Create the statistic depending on if we are a leaf or not. stat = StatisticType(*this); } -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree:: +BinarySpaceTree:: BinarySpaceTree( const MatType& data, std::vector& oldFromNew, @@ -74,20 +74,20 @@ BinarySpaceTree( oldFromNew[i] = i; // Fill with unharmed indices. // Now do the actual splitting. - SplitType, MatType> splitter; + SplitType, MatType> splitter; SplitNode(oldFromNew, maxLeafSize, splitter); // Create the statistic depending on if we are a leaf or not. stat = StatisticType(*this); } -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree:: +BinarySpaceTree:: BinarySpaceTree( const MatType& data, std::vector& oldFromNew, @@ -108,7 +108,7 @@ BinarySpaceTree( oldFromNew[i] = i; // Fill with unharmed indices. // Now do the actual splitting. - SplitType, MatType> splitter; + SplitType, MatType> splitter; SplitNode(oldFromNew, maxLeafSize, splitter); // Create the statistic depending on if we are a leaf or not. @@ -120,13 +120,13 @@ BinarySpaceTree( newFromOld[oldFromNew[i]] = i; } -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree:: +BinarySpaceTree:: BinarySpaceTree(MatType&& data, const size_t maxLeafSize) : left(NULL), right(NULL), @@ -138,20 +138,20 @@ BinarySpaceTree(MatType&& data, const size_t maxLeafSize) : dataset(new MatType(std::move(data))) { // Do the actual splitting of this node. - SplitType, MatType> splitter; + SplitType, MatType> splitter; SplitNode(maxLeafSize, splitter); // Create the statistic depending on if we are a leaf or not. stat = StatisticType(*this); } -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree:: +BinarySpaceTree:: BinarySpaceTree( MatType&& data, std::vector& oldFromNew, @@ -171,20 +171,20 @@ BinarySpaceTree( oldFromNew[i] = i; // Fill with unharmed indices. // Now do the actual splitting. - SplitType, MatType> splitter; + SplitType, MatType> splitter; SplitNode(oldFromNew, maxLeafSize, splitter); // Create the statistic depending on if we are a leaf or not. stat = StatisticType(*this); } -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree:: +BinarySpaceTree:: BinarySpaceTree( MatType&& data, std::vector& oldFromNew, @@ -205,7 +205,7 @@ BinarySpaceTree( oldFromNew[i] = i; // Fill with unharmed indices. // Now do the actual splitting. - SplitType, MatType> splitter; + SplitType, MatType> splitter; SplitNode(oldFromNew, maxLeafSize, splitter); // Create the statistic depending on if we are a leaf or not. @@ -217,18 +217,18 @@ BinarySpaceTree( newFromOld[oldFromNew[i]] = i; } -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree:: +BinarySpaceTree:: BinarySpaceTree( BinarySpaceTree* parent, const size_t begin, const size_t count, - SplitType, MatType>& splitter, + SplitType, MatType>& splitter, const size_t maxLeafSize) : left(NULL), right(NULL), @@ -245,19 +245,19 @@ BinarySpaceTree( stat = StatisticType(*this); } -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree:: +BinarySpaceTree:: BinarySpaceTree( BinarySpaceTree* parent, const size_t begin, const size_t count, std::vector& oldFromNew, - SplitType, MatType>& splitter, + SplitType, MatType>& splitter, const size_t maxLeafSize) : left(NULL), right(NULL), @@ -278,20 +278,20 @@ BinarySpaceTree( stat = StatisticType(*this); } -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree:: +BinarySpaceTree:: BinarySpaceTree( BinarySpaceTree* parent, const size_t begin, const size_t count, std::vector& oldFromNew, std::vector& newFromOld, - SplitType, MatType>& splitter, + SplitType, MatType>& splitter, const size_t maxLeafSize) : left(NULL), right(NULL), @@ -321,13 +321,13 @@ BinarySpaceTree( * Create a binary space tree by copying the other tree. Be careful! This can * take a long time and use a lot of memory. */ -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree:: +BinarySpaceTree:: BinarySpaceTree( const BinarySpaceTree& other) : left(NULL), @@ -381,14 +381,14 @@ BinarySpaceTree( /** * Copy assignment operator: copy the given other tree. */ -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree& -BinarySpaceTree:: +BinarySpaceTree& +BinarySpaceTree:: operator=(const BinarySpaceTree& other) { // Return if it's the same tree. @@ -453,14 +453,14 @@ operator=(const BinarySpaceTree& other) /** * Move assignment operator: take ownership of the given tree. */ -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree& -BinarySpaceTree:: +BinarySpaceTree& +BinarySpaceTree:: operator=(BinarySpaceTree&& other) { // Return if it's the same tree. @@ -501,13 +501,13 @@ operator=(BinarySpaceTree&& other) /** * Move constructor. */ -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree:: +BinarySpaceTree:: BinarySpaceTree(BinarySpaceTree&& other) : left(other.left), right(other.right), @@ -543,14 +543,14 @@ BinarySpaceTree(BinarySpaceTree&& other) : /** * Initialize the tree from an archive. */ -template class BoundType, + template class BoundType, template class SplitType> template -BinarySpaceTree:: +BinarySpaceTree:: BinarySpaceTree( Archive& ar, const typename std::enable_if_t()>*) : @@ -566,13 +566,13 @@ BinarySpaceTree( * destructors in turn. This will invalidate any pointers or references to any * nodes which are children of this one. */ -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree:: +BinarySpaceTree:: ~BinarySpaceTree() { delete left; @@ -583,13 +583,13 @@ BinarySpaceTree:: delete dataset; } -template class BoundType, + template class BoundType, template class SplitType> -inline bool BinarySpaceTree::IsLeaf() const { return !left; @@ -598,13 +598,13 @@ inline bool BinarySpaceTree class BoundType, + template class BoundType, template class SplitType> -inline size_t BinarySpaceTree::NumChildren() const { if (left && right) @@ -619,14 +619,14 @@ inline size_t BinarySpaceTree class BoundType, + template class BoundType, template class SplitType> template -size_t BinarySpaceTree::GetNearestChild( const VecType& point, typename std::enable_if_t::value>*) @@ -643,14 +643,14 @@ size_t BinarySpaceTree class BoundType, + template class BoundType, template class SplitType> template -size_t BinarySpaceTree::GetFurthestChild( const VecType& point, typename std::enable_if_t::value>*) @@ -667,13 +667,13 @@ size_t BinarySpaceTree class BoundType, + template class BoundType, template class SplitType> -size_t BinarySpaceTree::GetNearestChild(const BinarySpaceTree& queryNode) { if (IsLeaf() || !left || !right) @@ -692,13 +692,13 @@ size_t BinarySpaceTree class BoundType, + template class BoundType, template class SplitType> -size_t BinarySpaceTree::GetFurthestChild(const BinarySpaceTree& queryNode) { if (IsLeaf() || !left || !right) @@ -717,16 +717,16 @@ size_t BinarySpaceTree class BoundType, + template class BoundType, template class SplitType> inline -typename BinarySpaceTree::ElemType -BinarySpaceTree::FurthestPointDistance() const { if (!IsLeaf()) @@ -743,32 +743,32 @@ BinarySpaceTree class BoundType, + template class BoundType, template class SplitType> inline -typename BinarySpaceTree::ElemType -BinarySpaceTree::FurthestDescendantDistance() const { return furthestDescendantDistance; } //! Return the minimum distance from the center to any bound edge. -template class BoundType, + template class BoundType, template class SplitType> inline -typename BinarySpaceTree::ElemType -BinarySpaceTree::MinimumBoundDistance() const { return bound.MinWidth() / 2.0; @@ -777,15 +777,15 @@ BinarySpaceTree class BoundType, + template class BoundType, template class SplitType> -inline BinarySpaceTree& - BinarySpaceTree::Child(const size_t child) const { if (child == 0) @@ -797,13 +797,13 @@ inline BinarySpaceTree class BoundType, + template class BoundType, template class SplitType> -inline size_t BinarySpaceTree::NumPoints() const { if (left) @@ -815,13 +815,13 @@ inline size_t BinarySpaceTree class BoundType, + template class BoundType, template class SplitType> -inline size_t BinarySpaceTree::NumDescendants() const { return count; @@ -830,13 +830,13 @@ inline size_t BinarySpaceTree class BoundType, + template class BoundType, template class SplitType> -inline size_t BinarySpaceTree::Descendant(const size_t index) const { return (begin + index); @@ -845,27 +845,28 @@ inline size_t BinarySpaceTree class BoundType, + template class BoundType, template class SplitType> -inline size_t BinarySpaceTree::Point(const size_t index) const { return (begin + index); } -template class BoundType, + template class BoundType, template class SplitType> -void BinarySpaceTree:: +void +BinarySpaceTree:: SplitNode(const size_t maxLeafSize, - SplitType, MatType>& splitter) + SplitType, MatType>& splitter) { // We need to expand the bounds of this node properly. UpdateBound(bound); @@ -914,25 +915,26 @@ void BinarySpaceTree:: left->Center(leftCenter); right->Center(rightCenter); - const ElemType leftParentDistance = bound.Metric().Evaluate(center, + const ElemType leftParentDistance = bound.Distance().Evaluate(center, leftCenter); - const ElemType rightParentDistance = bound.Metric().Evaluate(center, + const ElemType rightParentDistance = bound.Distance().Evaluate(center, rightCenter); left->ParentDistance() = leftParentDistance; right->ParentDistance() = rightParentDistance; } -template class BoundType, + template class BoundType, template class SplitType> -void BinarySpaceTree:: +void +BinarySpaceTree:: SplitNode(std::vector& oldFromNew, const size_t maxLeafSize, - SplitType, MatType>& splitter) + SplitType, MatType>& splitter) { // We need to expand the bounds of this node properly. UpdateBound(bound); @@ -982,37 +984,39 @@ SplitNode(std::vector& oldFromNew, left->Center(leftCenter); right->Center(rightCenter); - const ElemType leftParentDistance = bound.Metric().Evaluate(center, + const ElemType leftParentDistance = bound.Distance().Evaluate(center, leftCenter); - const ElemType rightParentDistance = bound.Metric().Evaluate(center, + const ElemType rightParentDistance = bound.Distance().Evaluate(center, rightCenter); left->ParentDistance() = leftParentDistance; right->ParentDistance() = rightParentDistance; } -template class BoundType, + template class BoundType, template class SplitType> template -void BinarySpaceTree:: +void +BinarySpaceTree:: UpdateBound(BoundType2& boundToUpdate) { if (count > 0) boundToUpdate |= dataset->cols(begin, begin + count - 1); } -template class BoundType, + template class BoundType, template class SplitType> -void BinarySpaceTree:: -UpdateBound(HollowBallBound& boundToUpdate) +void +BinarySpaceTree:: +UpdateBound(HollowBallBound& boundToUpdate) { if (!parent) { @@ -1032,13 +1036,13 @@ UpdateBound(HollowBallBound& boundToUpdate) } // Default constructor (private), for cereal. -template class BoundType, + template class BoundType, template class SplitType> -BinarySpaceTree:: +BinarySpaceTree:: BinarySpaceTree() : left(NULL), right(NULL), @@ -1056,14 +1060,15 @@ BinarySpaceTree:: /** * Serialize the tree. */ -template class BoundType, + template class BoundType, template class SplitType> template -void BinarySpaceTree:: +void +BinarySpaceTree:: serialize(Archive& ar, const uint32_t /* version */) { // If we're loading, and we have children, they need to be deleted. diff --git a/src/mlpack/core/tree/binary_space_tree/breadth_first_dual_tree_traverser.hpp b/src/mlpack/core/tree/binary_space_tree/breadth_first_dual_tree_traverser.hpp index 42b128a6c0..937cb965f1 100644 --- a/src/mlpack/core/tree/binary_space_tree/breadth_first_dual_tree_traverser.hpp +++ b/src/mlpack/core/tree/binary_space_tree/breadth_first_dual_tree_traverser.hpp @@ -32,14 +32,14 @@ struct QueueFrame TraversalInfoType traversalInfo; }; -template class BoundType, + template class BoundType, template class SplitType> template -class BinarySpaceTree::BreadthFirstDualTreeTraverser { public: diff --git a/src/mlpack/core/tree/binary_space_tree/breadth_first_dual_tree_traverser_impl.hpp b/src/mlpack/core/tree/binary_space_tree/breadth_first_dual_tree_traverser_impl.hpp index 2e790271a8..7b598eab6d 100644 --- a/src/mlpack/core/tree/binary_space_tree/breadth_first_dual_tree_traverser_impl.hpp +++ b/src/mlpack/core/tree/binary_space_tree/breadth_first_dual_tree_traverser_impl.hpp @@ -19,14 +19,14 @@ namespace mlpack { -template class BoundType, + template class BoundType, template class SplitType> template -BinarySpaceTree:: +BinarySpaceTree:: BreadthFirstDualTreeTraverser::BreadthFirstDualTreeTraverser( RuleType& rule) : rule(rule), @@ -47,18 +47,19 @@ bool operator<(const QueueFrame& a, return false; } -template class BoundType, + template class BoundType, template class SplitType> template -void BinarySpaceTree:: +void +BinarySpaceTree:: BreadthFirstDualTreeTraverser::Traverse( - BinarySpaceTree& + BinarySpaceTree& queryRoot, - BinarySpaceTree& + BinarySpaceTree& referenceRoot) { // Increment the visit counter. @@ -87,16 +88,16 @@ BreadthFirstDualTreeTraverser::Traverse( Traverse(queryRoot, queue); } -template class BoundType, + template class BoundType, template class SplitType> template -void BinarySpaceTree:: +void BinarySpaceTree:: BreadthFirstDualTreeTraverser::Traverse( - BinarySpaceTree& + BinarySpaceTree& queryNode, std::priority_queue& referenceQueue) { diff --git a/src/mlpack/core/tree/binary_space_tree/dual_tree_traverser.hpp b/src/mlpack/core/tree/binary_space_tree/dual_tree_traverser.hpp index 71d5613963..fc42d5f15b 100644 --- a/src/mlpack/core/tree/binary_space_tree/dual_tree_traverser.hpp +++ b/src/mlpack/core/tree/binary_space_tree/dual_tree_traverser.hpp @@ -21,14 +21,14 @@ namespace mlpack { -template class BoundType, + template class BoundType, template class SplitType> template -class BinarySpaceTree::DualTreeTraverser { public: diff --git a/src/mlpack/core/tree/binary_space_tree/dual_tree_traverser_impl.hpp b/src/mlpack/core/tree/binary_space_tree/dual_tree_traverser_impl.hpp index 894706d3a4..ec030e133d 100644 --- a/src/mlpack/core/tree/binary_space_tree/dual_tree_traverser_impl.hpp +++ b/src/mlpack/core/tree/binary_space_tree/dual_tree_traverser_impl.hpp @@ -19,14 +19,14 @@ namespace mlpack { -template class BoundType, + template class BoundType, template class SplitType> template -BinarySpaceTree:: +BinarySpaceTree:: DualTreeTraverser::DualTreeTraverser(RuleType& rule) : rule(rule), numPrunes(0), @@ -35,18 +35,19 @@ DualTreeTraverser::DualTreeTraverser(RuleType& rule) : numBaseCases(0) { /* Nothing to do. */ } -template class BoundType, + template class BoundType, template class SplitType> template -void BinarySpaceTree:: +void +BinarySpaceTree:: DualTreeTraverser::Traverse( - BinarySpaceTree& + BinarySpaceTree& queryNode, - BinarySpaceTree& + BinarySpaceTree& referenceNode) { // Increment the visit counter. diff --git a/src/mlpack/core/tree/binary_space_tree/single_tree_traverser.hpp b/src/mlpack/core/tree/binary_space_tree/single_tree_traverser.hpp index 198b9f9ece..1fe477c907 100644 --- a/src/mlpack/core/tree/binary_space_tree/single_tree_traverser.hpp +++ b/src/mlpack/core/tree/binary_space_tree/single_tree_traverser.hpp @@ -20,14 +20,14 @@ namespace mlpack { -template class BoundType, + template class BoundType, template class SplitType> template -class BinarySpaceTree::SingleTreeTraverser { public: diff --git a/src/mlpack/core/tree/binary_space_tree/single_tree_traverser_impl.hpp b/src/mlpack/core/tree/binary_space_tree/single_tree_traverser_impl.hpp index d8c2daaf83..cb164d8e39 100644 --- a/src/mlpack/core/tree/binary_space_tree/single_tree_traverser_impl.hpp +++ b/src/mlpack/core/tree/binary_space_tree/single_tree_traverser_impl.hpp @@ -21,30 +21,31 @@ namespace mlpack { -template class BoundType, + template class BoundType, template class SplitType> template -BinarySpaceTree:: +BinarySpaceTree:: SingleTreeTraverser::SingleTreeTraverser(RuleType& rule) : rule(rule), numPrunes(0) { /* Nothing to do. */ } -template class BoundType, + template class BoundType, template class SplitType> template -void BinarySpaceTree:: +void +BinarySpaceTree:: SingleTreeTraverser::Traverse( const size_t queryIndex, - BinarySpaceTree& + BinarySpaceTree& referenceNode) { // If we are a leaf, run the base case as necessary. diff --git a/src/mlpack/core/tree/binary_space_tree/traits.hpp b/src/mlpack/core/tree/binary_space_tree/traits.hpp index bf6640927d..623cddf5c3 100644 --- a/src/mlpack/core/tree/binary_space_tree/traits.hpp +++ b/src/mlpack/core/tree/binary_space_tree/traits.hpp @@ -23,14 +23,14 @@ namespace mlpack { * help write tree-independent (but still optimized) tree-based algorithms. See * mlpack/core/tree/tree_traits.hpp for more information. */ -template class BoundType, + template class BoundType, template class SplitType> -class TreeTraits> +class TreeTraits> { public: /** @@ -77,12 +77,12 @@ class TreeTraits class BoundType> -class TreeTraits> + template class BoundType> +class TreeTraits> { public: /** @@ -127,11 +127,11 @@ class TreeTraits class BoundType> -class TreeTraits class BoundType> +class TreeTraits> { public: @@ -178,13 +178,13 @@ class TreeTraits class SplitType> -class TreeTraits> +class TreeTraits> { public: static const bool HasOverlappingChildren = true; @@ -202,13 +202,13 @@ class TreeTraits class SplitType> -class TreeTraits> +class TreeTraits> { public: static const bool HasOverlappingChildren = true; @@ -226,13 +226,13 @@ class TreeTraits class SplitType> -class TreeTraits> +class TreeTraits> { public: static const bool HasOverlappingChildren = true; diff --git a/src/mlpack/core/tree/binary_space_tree/typedef.hpp b/src/mlpack/core/tree/binary_space_tree/typedef.hpp index a89c9005a9..2a4638ddf9 100644 --- a/src/mlpack/core/tree/binary_space_tree/typedef.hpp +++ b/src/mlpack/core/tree/binary_space_tree/typedef.hpp @@ -54,8 +54,8 @@ namespace mlpack { * * @see @ref trees, BinarySpaceTree, MeanSplitKDTree */ -template -using KDTree = BinarySpaceTree +using KDTree = BinarySpaceTree -using MeanSplitKDTree = BinarySpaceTree +using MeanSplitKDTree = BinarySpaceTree -using BallTree = BinarySpaceTree +using BallTree = BinarySpaceTree -using MeanSplitBallTree = BinarySpaceTree +using MeanSplitBallTree = BinarySpaceTree using VPTreeSplit = VantagePointSplit; -template -using VPTree = BinarySpaceTree +using VPTree = BinarySpaceTree -using MaxRPTree = BinarySpaceTree +using MaxRPTree = BinarySpaceTree -using RPTree = BinarySpaceTree +using RPTree = BinarySpaceTree -using UBTree = BinarySpaceTree +using UBTree = BinarySpaceTree vantagePoint; //! The median distance according to which the node will be split. ElemType mu; - //! An instance of the MetricType class. - const MetricType* metric; + //! An instance of the DistanceType class. + const DistanceType* distance; SplitInfo() : mu(0), - metric(NULL) + distance(NULL) { } template - SplitInfo(const MetricType& metric, const VecType& vantagePoint, + SplitInfo(const DistanceType& distance, const VecType& vantagePoint, ElemType mu) : vantagePoint(vantagePoint), mu(mu), - metric(&metric) + distance(&distance) { } }; @@ -135,7 +135,7 @@ class VantagePointSplit static bool AssignToLeftNode(const VecType& point, const SplitInfo& splitInfo) { - return (splitInfo.metric->Evaluate(splitInfo.vantagePoint, point) < + return (splitInfo.distance->Evaluate(splitInfo.vantagePoint, point) < splitInfo.mu); } @@ -148,7 +148,7 @@ class VantagePointSplit * second moment and selects the point with the largest moment. Each random * point belongs to the node. * - * @param metric The metric used by the tree. + * @param distance The distance metric used by the tree. * @param data The dataset used by the tree. * @param begin Index of the starting point in the dataset that belongs to * this node. @@ -157,7 +157,7 @@ class VantagePointSplit * @param mu The median value of distance form the vantage point to * a number of random points. */ - static void SelectVantagePoint(const MetricType& metric, + static void SelectVantagePoint(const DistanceType& distance, const MatType& data, const size_t begin, const size_t count, diff --git a/src/mlpack/core/tree/binary_space_tree/vantage_point_split_impl.hpp b/src/mlpack/core/tree/binary_space_tree/vantage_point_split_impl.hpp index 58404dbaef..d19dcb1f18 100644 --- a/src/mlpack/core/tree/binary_space_tree/vantage_point_split_impl.hpp +++ b/src/mlpack/core/tree/binary_space_tree/vantage_point_split_impl.hpp @@ -27,20 +27,21 @@ SplitNode(const BoundType& bound, MatType& data, const size_t begin, size_t vantagePointIndex = 0; // Find the best vantage point. - SelectVantagePoint(bound.Metric(), data, begin, count, vantagePointIndex, mu); + SelectVantagePoint(bound.Distance(), data, begin, count, vantagePointIndex, + mu); // If all points are equal, we can't split. if (mu == 0) return false; - splitInfo = SplitInfo(bound.Metric(), data.col(vantagePointIndex), mu); + splitInfo = SplitInfo(bound.Distance(), data.col(vantagePointIndex), mu); return true; } template void VantagePointSplit:: -SelectVantagePoint(const MetricType& metric, const MatType& data, +SelectVantagePoint(const DistanceType& distance, const MatType& data, const size_t begin, const size_t count, size_t& vantagePoint, ElemType& mu) { arma::Col distances(MaxNumSamples); @@ -74,7 +75,7 @@ SelectVantagePoint(const MetricType& metric, const MatType& data, distances.set_size(samples.n_elem); for (size_t j = 0; j < samples.n_elem; ++j) - distances[j] = metric.Evaluate(data.col(vantagePointCandidates[i]), + distances[j] = distance.Evaluate(data.col(vantagePointCandidates[i]), data.col(samples[j])); const ElemType spread = sum(distances % distances) / samples.n_elem; diff --git a/src/mlpack/core/tree/bounds.hpp b/src/mlpack/core/tree/bounds.hpp index 460a69e4cd..03b085bf1b 100644 --- a/src/mlpack/core/tree/bounds.hpp +++ b/src/mlpack/core/tree/bounds.hpp @@ -13,7 +13,7 @@ #define MLPACK_CORE_TREE_BOUNDS_HPP #include -#include +#include #include "bound_traits.hpp" #include "hrectbound.hpp" diff --git a/src/mlpack/core/tree/cellbound.hpp b/src/mlpack/core/tree/cellbound.hpp index 39b5b57ef9..a66a1486c2 100644 --- a/src/mlpack/core/tree/cellbound.hpp +++ b/src/mlpack/core/tree/cellbound.hpp @@ -36,7 +36,7 @@ #include #include -#include +#include #include "bound_traits.hpp" #include "address.hpp" @@ -69,7 +69,7 @@ namespace mlpack { * } * @endcode */ -template, +template, typename ElemType = double> class CellBound { @@ -143,10 +143,17 @@ class CellBound //! Modify the minimum width of the bound. ElemType& MinWidth() { return minWidth; } - //! Get the metric associated with this bound. - const MetricType& Metric() const { return metric; } - //! Modify the metric associated with this bound. - MetricType& Metric() { return metric; } + //! Get the distance metric associated with this bound. + [[deprecated("Will be removed in 5.0.0; use Distance()")]] + const DistanceType& Metric() const { return distance; } + //! Modify the distance metric associated with this bound. + [[deprecated("Will be removed in 5.0.0; use Distance()")]] + DistanceType& Metric() { return distance; } + + //! Get the distance metric associated with this bound. + const DistanceType& Distance() const { return distance; } + //! Modify the distance metric associated with this bound. + DistanceType& Distance() { return distance; } /** * Calculates the center of the range, placing it into the given vector. @@ -274,8 +281,8 @@ class CellBound arma::Col hiAddress; //! The minimal width of the outer rectangle. ElemType minWidth; - //! The instantiated metric (likely has size 0). - MetricType metric; + //! The instantiated distance metric (likely has size 0). + DistanceType distance; /** * Add a subrectangle to the bound. @@ -312,8 +319,8 @@ class CellBound }; // A specialization of BoundTraits for this class. -template -struct BoundTraits> +template +struct BoundTraits> { //! These bounds are always tight for each dimension. const static bool HasTightBounds = true; diff --git a/src/mlpack/core/tree/cellbound_impl.hpp b/src/mlpack/core/tree/cellbound_impl.hpp index e226f6d7c6..24d289a72d 100644 --- a/src/mlpack/core/tree/cellbound_impl.hpp +++ b/src/mlpack/core/tree/cellbound_impl.hpp @@ -23,8 +23,8 @@ namespace mlpack { /** * Empty constructor. */ -template -inline CellBound::CellBound() : +template +inline CellBound::CellBound() : dim(0), bounds(NULL), loBound(arma::Mat()), @@ -39,8 +39,8 @@ inline CellBound::CellBound() : * Initializes to specified dimensionality with each dimension the empty * set. */ -template -inline CellBound::CellBound(const size_t dimension) : +template +inline CellBound::CellBound(const size_t dimension) : dim(dimension), bounds(new RangeType[dim]), loBound(arma::Mat(dim, maxNumBounds)), @@ -60,9 +60,9 @@ inline CellBound::CellBound(const size_t dimension) : /** * Copy constructor necessary to prevent memory leaks. */ -template -inline CellBound::CellBound( - const CellBound& other) : +template +inline CellBound::CellBound( + const CellBound& other) : dim(other.Dim()), bounds(new RangeType[dim]), loBound(other.loBound), @@ -80,11 +80,11 @@ inline CellBound::CellBound( /** * Same as the copy constructor. */ -template +template inline CellBound< - MetricType, - ElemType>& CellBound::operator=( - const CellBound& other) + DistanceType, + ElemType>& CellBound::operator=( + const CellBound& other) { if (this == &other) return *this; @@ -116,9 +116,9 @@ inline CellBound< /** * Move constructor: take possession of another bound's information. */ -template -inline CellBound::CellBound( - CellBound&& other) : +template +inline CellBound::CellBound( + CellBound&& other) : dim(other.dim), bounds(other.bounds), loBound(std::move(other.loBound)), @@ -137,8 +137,8 @@ inline CellBound::CellBound( /** * Destructor: clean up memory. */ -template -inline CellBound::~CellBound() +template +inline CellBound::~CellBound() { if (bounds) delete[] bounds; @@ -147,8 +147,8 @@ inline CellBound::~CellBound() /** * Resets all dimensions to the empty set. */ -template -inline void CellBound::Clear() +template +inline void CellBound::Clear() { for (size_t k = 0; k < dim; ++k) { @@ -166,8 +166,8 @@ inline void CellBound::Clear() * * @param centroid Vector which the centroid will be written to. */ -template -inline void CellBound::Center( +template +inline void CellBound::Center( arma::Col& center) const { // Set size correctly if necessary. @@ -178,9 +178,9 @@ inline void CellBound::Center( center(i) = bounds[i].Mid(); } -template +template template -void CellBound::AddBound( +void CellBound::AddBound( const arma::Col& loCorner, const arma::Col& hiCorner, const MatType& data) @@ -223,9 +223,9 @@ void CellBound::AddBound( } -template +template template -void CellBound::InitHighBound(size_t numEqualBits, +void CellBound::InitHighBound(size_t numEqualBits, const MatType& data) { arma::Col tmpHiAddress(hiAddress); @@ -312,9 +312,9 @@ void CellBound::InitHighBound(size_t numEqualBits, } } -template +template template -void CellBound::InitLowerBound(size_t numEqualBits, +void CellBound::InitLowerBound(size_t numEqualBits, const MatType& data) { arma::Col tmpHiAddress(loAddress); @@ -402,9 +402,9 @@ void CellBound::InitLowerBound(size_t numEqualBits, } } -template +template template -void CellBound::UpdateAddressBounds(const MatType& data) +void CellBound::UpdateAddressBounds(const MatType& data) { numBounds = 0; @@ -470,9 +470,9 @@ void CellBound::UpdateAddressBounds(const MatType& data) /** * Calculates minimum bound-to-point squared distance. */ -template +template template -inline ElemType CellBound::MinDistance( +inline ElemType CellBound::MinDistance( const VecType& point, typename std::enable_if_t::value>* /* junk */) const { @@ -495,9 +495,9 @@ inline ElemType CellBound::MinDistance( // each's absolute value to itself and then sum those two, our // result is the non negative half of the equation times two; // then we raise to power Power. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) sum += lower + std::fabs(lower) + higher + std::fabs(higher); - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) { ElemType dist = lower + std::fabs(lower) + higher + std::fabs(higher); sum += dist * dist; @@ -505,7 +505,7 @@ inline ElemType CellBound::MinDistance( else { sum += std::pow((lower + std::fabs(lower)) + - (higher + std::fabs(higher)), (ElemType) MetricType::Power); + (higher + std::fabs(higher)), (ElemType) DistanceType::Power); } if (sum >= minSum) @@ -520,30 +520,30 @@ inline ElemType CellBound::MinDistance( // to be); then cancel out the constant of 2 (which may have been squared now) // that was introduced earlier. The compiler should optimize out the if // statement entirely. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) return minSum * 0.5; - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) { - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) return (ElemType) std::sqrt(minSum) * 0.5; else return minSum * 0.25; } else { - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) return (ElemType) std::pow((double) minSum, - 1.0 / (double) MetricType::Power) / 2.0; + 1.0 / (double) DistanceType::Power) / 2.0; else - return minSum / std::pow(2.0, MetricType::Power); + return minSum / std::pow(2.0, DistanceType::Power); } } /** * Calculates minimum bound-to-bound squared distance. */ -template -ElemType CellBound::MinDistance(const CellBound& other) +template +ElemType CellBound::MinDistance(const CellBound& other) const { Log::Assert(dim == other.dim); @@ -565,9 +565,9 @@ ElemType CellBound::MinDistance(const CellBound& other) // (x * 2)^2 / 4 = x^2 // The compiler should optimize out this if statement entirely. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) sum += (lower + std::fabs(lower)) + (higher + std::fabs(higher)); - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) { ElemType dist = lower + std::fabs(lower) + higher + std::fabs(higher); sum += dist * dist; @@ -575,7 +575,7 @@ ElemType CellBound::MinDistance(const CellBound& other) else { sum += std::pow((lower + std::fabs(lower)) + - (higher + std::fabs(higher)), (ElemType) MetricType::Power); + (higher + std::fabs(higher)), (ElemType) DistanceType::Power); } if (sum >= minSum) @@ -587,31 +587,31 @@ ElemType CellBound::MinDistance(const CellBound& other) } // The compiler should optimize out this if statement entirely. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) return minSum * 0.5; - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) { - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) return (ElemType) std::sqrt(minSum) * 0.5; else return minSum * 0.25; } else { - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) return (ElemType) std::pow((double) minSum, - 1.0 / (double) MetricType::Power) / 2.0; + 1.0 / (double) DistanceType::Power) / 2.0; else - return minSum / std::pow(2.0, MetricType::Power); + return minSum / std::pow(2.0, DistanceType::Power); } } /** * Calculates maximum bound-to-point squared distance. */ -template +template template -inline ElemType CellBound::MaxDistance( +inline ElemType CellBound::MaxDistance( const VecType& point, typename std::enable_if_t::value>* /* junk */) const { @@ -627,12 +627,12 @@ inline ElemType CellBound::MaxDistance( ElemType v = std::max(fabs(point[d] - loBound(d, i)), fabs(hiBound(d, i) - point[d])); - if (MetricType::Power == 1) + if (DistanceType::Power == 1) sum += v; // v is non-negative. - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) sum += v * v; else - sum += std::pow(v, (ElemType) MetricType::Power); + sum += std::pow(v, (ElemType) DistanceType::Power); } if (sum > maxSum) @@ -640,15 +640,15 @@ inline ElemType CellBound::MaxDistance( } // The compiler should optimize out this if statement entirely. - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) { - if (MetricType::Power == 1) + if (DistanceType::Power == 1) return maxSum; - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) return (ElemType) std::sqrt(maxSum); else return (ElemType) std::pow((double) maxSum, 1.0 / - (double) MetricType::Power); + (double) DistanceType::Power); } return maxSum; @@ -657,8 +657,8 @@ inline ElemType CellBound::MaxDistance( /** * Computes maximum distance. */ -template -inline ElemType CellBound::MaxDistance( +template +inline ElemType CellBound::MaxDistance( const CellBound& other) const { @@ -677,12 +677,12 @@ inline ElemType CellBound::MaxDistance( fabs(hiBound(d, i) - other.loBound(d, j))); // The compiler should optimize out this if statement entirely. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) sum += v; // v is non-negative. - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) sum += v * v; else - sum += std::pow(v, (ElemType) MetricType::Power); + sum += std::pow(v, (ElemType) DistanceType::Power); } if (sum > maxSum) @@ -690,15 +690,15 @@ inline ElemType CellBound::MaxDistance( } // The compiler should optimize out this if statement entirely. - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) { - if (MetricType::Power == 1) + if (DistanceType::Power == 1) return maxSum; - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) return (ElemType) std::sqrt(maxSum); else return (ElemType) std::pow((double) maxSum, 1.0 / - (double) MetricType::Power); + (double) DistanceType::Power); } return maxSum; @@ -707,9 +707,9 @@ inline ElemType CellBound::MaxDistance( /** * Calculates minimum and maximum bound-to-bound squared distance. */ -template +template inline RangeType -CellBound::RangeDistance( +CellBound::RangeDistance( const CellBound& other) const { ElemType minLoSum = std::numeric_limits::max(); @@ -741,20 +741,20 @@ CellBound::RangeDistance( } // The compiler should optimize out this if statement entirely. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) { loSum += vLo; // vLo is non-negative. hiSum += vHi; // vHi is non-negative. } - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) { loSum += vLo * vLo; hiSum += vHi * vHi; } else { - loSum += std::pow(vLo, (ElemType) MetricType::Power); - hiSum += std::pow(vHi, (ElemType) MetricType::Power); + loSum += std::pow(vLo, (ElemType) DistanceType::Power); + hiSum += std::pow(vHi, (ElemType) DistanceType::Power); } } @@ -764,20 +764,20 @@ CellBound::RangeDistance( maxHiSum = hiSum; } - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) { - if (MetricType::Power == 1) + if (DistanceType::Power == 1) return RangeType(minLoSum, maxHiSum); - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) return RangeType((ElemType) std::sqrt(minLoSum), (ElemType) std::sqrt(maxHiSum)); else { return RangeType( (ElemType) std::pow((double) minLoSum, 1.0 / - (double) MetricType::Power), + (double) DistanceType::Power), (ElemType) std::pow((double) maxHiSum, 1.0 / - (double) MetricType::Power)); + (double) DistanceType::Power)); } } @@ -787,10 +787,10 @@ CellBound::RangeDistance( /** * Calculates minimum and maximum bound-to-point squared distance. */ -template +template template inline RangeType -CellBound::RangeDistance( +CellBound::RangeDistance( const VecType& point, typename std::enable_if_t::value>* /* junk */) const { @@ -830,20 +830,20 @@ CellBound::RangeDistance( } // The compiler should optimize out this if statement entirely. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) { loSum += vLo; // vLo is non-negative. hiSum += vHi; // vHi is non-negative. } - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) { loSum += vLo * vLo; hiSum += vHi * vHi; } else { - loSum += std::pow(vLo, (ElemType) MetricType::Power); - hiSum += std::pow(vHi, (ElemType) MetricType::Power); + loSum += std::pow(vLo, (ElemType) DistanceType::Power); + hiSum += std::pow(vHi, (ElemType) DistanceType::Power); } } if (loSum < minLoSum) @@ -852,20 +852,20 @@ CellBound::RangeDistance( maxHiSum = hiSum; } - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) { - if (MetricType::Power == 1) + if (DistanceType::Power == 1) return RangeType(minLoSum, maxHiSum); - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) return RangeType((ElemType) std::sqrt(minLoSum), (ElemType) std::sqrt(maxHiSum)); else { return RangeType( (ElemType) std::pow((double) minLoSum, 1.0 / - (double) MetricType::Power), + (double) DistanceType::Power), (ElemType) std::pow((double) maxHiSum, 1.0 / - (double) MetricType::Power)); + (double) DistanceType::Power)); } } @@ -875,10 +875,10 @@ CellBound::RangeDistance( /** * Expands this region to include a new point. */ -template +template template -inline CellBound& -CellBound::operator|=(const MatType& data) +inline CellBound& +CellBound::operator|=(const MatType& data) { Log::Assert(data.n_rows == dim); @@ -905,9 +905,9 @@ CellBound::operator|=(const MatType& data) /** * Expands this region to encompass another bound. */ -template -inline CellBound& -CellBound::operator|=(const CellBound& other) +template +inline CellBound& +CellBound::operator|=(const CellBound& other) { assert(other.dim == dim); @@ -943,9 +943,9 @@ CellBound::operator|=(const CellBound& other) /** * Determines if a point is within this bound. */ -template +template template -inline bool CellBound::Contains( +inline bool CellBound::Contains( const VecType& point) const { for (size_t i = 0; i < point.n_elem; ++i) @@ -968,24 +968,24 @@ inline bool CellBound::Contains( /** * Returns the diameter of the hyperrectangle (that is, the longest diagonal). */ -template -inline ElemType CellBound::Diameter() const +template +inline ElemType CellBound::Diameter() const { ElemType d = 0; for (size_t i = 0; i < dim; ++i) d += std::pow(bounds[i].Hi() - bounds[i].Lo(), - (ElemType) MetricType::Power); + (ElemType) DistanceType::Power); - if (MetricType::TakeRoot) - return (ElemType) std::pow((double) d, 1.0 / (double) MetricType::Power); + if (DistanceType::TakeRoot) + return (ElemType) std::pow((double) d, 1.0 / (double) DistanceType::Power); return d; } //! Serialize the bound object. -template +template template -void CellBound::serialize( +void CellBound::serialize( Archive& ar, const uint32_t /* version */) { @@ -996,7 +996,7 @@ void CellBound::serialize( ar(CEREAL_NVP(numBounds)); ar(CEREAL_NVP(loAddress)); ar(CEREAL_NVP(hiAddress)); - ar(CEREAL_NVP(metric)); + ar(CEREAL_NVP(distance)); } } // namespace mlpack diff --git a/src/mlpack/core/tree/cover_tree/cover_tree.hpp b/src/mlpack/core/tree/cover_tree/cover_tree.hpp index 0833aceb5b..13c6813a18 100644 --- a/src/mlpack/core/tree/cover_tree/cover_tree.hpp +++ b/src/mlpack/core/tree/cover_tree/cover_tree.hpp @@ -78,20 +78,20 @@ namespace mlpack { * } * @endcode * - * The CoverTree class offers three template parameters; a custom metric type - * can be used with MetricType (this class defaults to the L2-squared metric). - * The root node's point can be chosen with the RootPointPolicy; by default, the - * FirstPointIsRoot policy is used, meaning the first point in the dataset is - * used. The StatisticType policy allows you to define statistics which can be - * gathered during the creation of the tree. + * The CoverTree class offers three template parameters; a custom distance + * metric type can be used with DistanceType (this class defaults to the + * L2-squared metric). The root node's point can be chosen with the + * RootPointPolicy; by default, the FirstPointIsRoot policy is used, meaning the + * first point in the dataset is used. The StatisticType policy allows you to + * define statistics which can be gathered during the creation of the tree. * - * @tparam MetricType Metric type to use during tree construction. + * @tparam DistanceType Metric type to use during tree construction. * @tparam RootPointPolicy Determines which point to use as the root node. * @tparam StatisticType Statistic to be used during tree creation. * @tparam MatType Type of matrix to build the tree on (generally mat or * sp_mat). */ -template, +template, typename StatisticType = EmptyStatistic, typename MatType = arma::mat, typename RootPointPolicy = FirstPointIsRoot> @@ -112,23 +112,23 @@ class CoverTree * * @param dataset Reference to the dataset to build a tree on. * @param base Base to use during tree building (default 2.0). - * @param metric Metric to use (default NULL). + * @param distance Distance metric to use (default NULL). */ CoverTree(const MatType& dataset, const ElemType base = 2.0, - MetricType* metric = NULL); + DistanceType* distance = NULL); /** * Create the cover tree with the given dataset and the given instantiated - * metric. Optionally, set the base. The dataset will not be modified during - * the building procedure (unlike BinarySpaceTree). + * distance metric. Optionally, set the base. The dataset will not be + * modified during the building procedure (unlike BinarySpaceTree). * * @param dataset Reference to the dataset to build a tree on. - * @param metric Instantiated metric to use during tree building. + * @param distance Instantiated distance metric to use during tree building. * @param base Base to use during tree building (default 2.0). */ CoverTree(const MatType& dataset, - MetricType& metric, + DistanceType& distance, const ElemType base = 2.0); /** @@ -143,14 +143,15 @@ class CoverTree /** * Create the cover tree with the given dataset and the given instantiated - * metric, taking ownership of the dataset. Optionally, set the base. + * distance metric, taking ownership of the dataset. Optionally, set the + * base. * * @param dataset Reference to the dataset to build a tree on. - * @param metric Instantiated metric to use during tree building. + * @param distance Instantiated distance metric to use during tree building. * @param base Base to use during tree building (default 2.0). */ CoverTree(MatType&& dataset, - MetricType& metric, + DistanceType& distance, const ElemType base = 2.0); /** @@ -183,7 +184,7 @@ class CoverTree * @param farSetSize Size of the far set; may be modified (if this node uses * any points in the far set). * @param usedSetSize The number of points used will be added to this number. - * @param metric Metric to use (default NULL). + * @param distance Distance metric to use (default NULL). */ CoverTree(const MatType& dataset, const ElemType base, @@ -196,7 +197,7 @@ class CoverTree size_t nearSetSize, size_t& farSetSize, size_t& usedSetSize, - MetricType& metric = NULL); + DistanceType& distance = NULL); /** * Manually construct a cover tree node; no tree assembly is done in this @@ -212,7 +213,7 @@ class CoverTree * @param parent Parent node (NULL indicates no parent). * @param parentDistance Distance to parent node point. * @param furthestDescendantDistance Distance to furthest descendant point. - * @param metric Instantiated metric (optional). + * @param distance Instantiated distance metric (optional). */ CoverTree(const MatType& dataset, const ElemType base, @@ -221,7 +222,7 @@ class CoverTree CoverTree* parent, const ElemType parentDistance, const ElemType furthestDescendantDistance, - MetricType* metric = NULL); + DistanceType* distance = NULL); /** * Create a cover tree from another tree. Be careful! This may use a lot of @@ -429,8 +430,12 @@ class CoverTree center = arma::vec(dataset->col(point)); } - //! Get the instantiated metric. - MetricType& Metric() const { return *metric; } + //! Get the instantiated distance metric. + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + DistanceType& Metric() const { return *distance; } + + //! Get the instantiated distance metric. + DistanceType& Distance() const { return *distance; } private: //! Reference to the matrix which this tree is built on. @@ -453,12 +458,12 @@ class CoverTree ElemType parentDistance; //! Distance to the furthest descendant. ElemType furthestDescendantDistance; - //! Whether or not we need to destroy the metric in the destructor. - bool localMetric; + //! Whether or not we need to destroy the distance metric in the destructor. + bool localDistance; //! If true, we own the dataset and need to destroy it in the destructor. bool localDataset; - //! The metric used for this tree. - MetricType* metric; + //! The distance metric used for this tree. + DistanceType* distance; /** * Create the children for this node. diff --git a/src/mlpack/core/tree/cover_tree/cover_tree_impl.hpp b/src/mlpack/core/tree/cover_tree/cover_tree_impl.hpp index daf0299554..10d2e342ee 100644 --- a/src/mlpack/core/tree/cover_tree/cover_tree_impl.hpp +++ b/src/mlpack/core/tree/cover_tree/cover_tree_impl.hpp @@ -34,15 +34,15 @@ void BuildStatistics(TreeType* node) // Create the cover tree. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -CoverTree::CoverTree( +CoverTree::CoverTree( const MatType& dataset, const ElemType base, - MetricType* metric) : + DistanceType* distance) : dataset(&dataset), point(RootPointPolicy::ChooseRoot(dataset)), scale(INT_MAX), @@ -51,14 +51,15 @@ CoverTree::CoverTree( parent(NULL), parentDistance(0), furthestDescendantDistance(0), - localMetric(metric == NULL), + localDistance(distance == NULL), localDataset(false), - metric(metric), + distance(distance), distanceComps(0) { - // If we need to create a metric, do that. We'll just do it on the heap. - if (localMetric) - this->metric = new MetricType(); + // If we need to create a distance metric, do that. We'll just do it on the + // heap. + if (localDistance) + this->distance = new DistanceType(); // If there is only one point or zero points in the dataset... uh, we're done. // Technically, if the dataset has zero points, our node is not correct... @@ -134,14 +135,14 @@ CoverTree::CoverTree( } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -CoverTree::CoverTree( +CoverTree::CoverTree( const MatType& dataset, - MetricType& metric, + DistanceType& distance, const ElemType base) : dataset(&dataset), point(RootPointPolicy::ChooseRoot(dataset)), @@ -151,9 +152,9 @@ CoverTree::CoverTree( parent(NULL), parentDistance(0), furthestDescendantDistance(0), - localMetric(true), + localDistance(true), localDataset(false), - metric(new MetricType(metric)), + distance(new DistanceType(distance)), distanceComps(0) { // If there is only one point or zero points in the dataset... uh, we're done. @@ -230,12 +231,12 @@ CoverTree::CoverTree( } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -CoverTree::CoverTree( +CoverTree::CoverTree( MatType&& data, const ElemType base) : dataset(new MatType(std::move(data))), @@ -246,12 +247,12 @@ CoverTree::CoverTree( parent(NULL), parentDistance(0), furthestDescendantDistance(0), - localMetric(true), + localDistance(true), localDataset(true), distanceComps(0) { - // We need to create a metric. We'll just do it on the heap. - this->metric = new MetricType(); + // We need to create a distance metric. We'll just do it on the heap. + this->distance = new DistanceType(); // If there is only one point or zero points in the dataset... uh, we're done. // Technically, if the dataset has zero points, our node is not correct... @@ -327,14 +328,14 @@ CoverTree::CoverTree( } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -CoverTree::CoverTree( +CoverTree::CoverTree( MatType&& data, - MetricType& metric, + DistanceType& distance, const ElemType base) : dataset(new MatType(std::move(data))), point(RootPointPolicy::ChooseRoot(dataset)), @@ -344,9 +345,9 @@ CoverTree::CoverTree( parent(NULL), parentDistance(0), furthestDescendantDistance(0), - localMetric(true), + localDistance(true), localDataset(true), - metric(new MetricType(metric)), + distance(new DistanceType(distance)), distanceComps(0) { // If there is only one point or zero points in the dataset... uh, we're done. @@ -423,12 +424,12 @@ CoverTree::CoverTree( } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -CoverTree::CoverTree( +CoverTree::CoverTree( const MatType& dataset, const ElemType base, const size_t pointIndex, @@ -440,7 +441,7 @@ CoverTree::CoverTree( size_t nearSetSize, size_t& farSetSize, size_t& usedSetSize, - MetricType& metric) : + DistanceType& distance) : dataset(&dataset), point(pointIndex), scale(scale), @@ -449,9 +450,9 @@ CoverTree::CoverTree( parent(parent), parentDistance(parentDistance), furthestDescendantDistance(0), - localMetric(false), + localDistance(false), localDataset(false), - metric(&metric), + distance(&distance), distanceComps(0) { // If the size of the near set is 0, this is a leaf. @@ -468,12 +469,12 @@ CoverTree::CoverTree( // Manually create a cover tree node. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -CoverTree::CoverTree( +CoverTree::CoverTree( const MatType& dataset, const ElemType base, const size_t pointIndex, @@ -481,7 +482,7 @@ CoverTree::CoverTree( CoverTree* parent, const ElemType parentDistance, const ElemType furthestDescendantDistance, - MetricType* metric) : + DistanceType* distance) : dataset(&dataset), point(pointIndex), scale(scale), @@ -490,24 +491,24 @@ CoverTree::CoverTree( parent(parent), parentDistance(parentDistance), furthestDescendantDistance(furthestDescendantDistance), - localMetric(metric == NULL), + localDistance(distance == NULL), localDataset(false), - metric(metric), + distance(distance), distanceComps(0) { - // If necessary, create a local metric. - if (localMetric) - this->metric = new MetricType(); + // If necessary, create a local distance metric. + if (localDistance) + this->distance = new DistanceType(); } // Copy Constructor. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -CoverTree::CoverTree( +CoverTree::CoverTree( const CoverTree& other) : dataset((other.parent == NULL && other.localDataset) ? new MatType(*other.dataset) : other.dataset), @@ -519,9 +520,9 @@ CoverTree::CoverTree( parent(other.parent), parentDistance(other.parentDistance), furthestDescendantDistance(other.furthestDescendantDistance), - localMetric(other.localMetric), + localDistance(other.localDistance), localDataset(other.parent == NULL && other.localDataset), - metric((other.localMetric ? new MetricType() : other.metric)), + distance((other.localDistance ? new DistanceType() : other.distance)), distanceComps(0) { // Copy each child by hand. @@ -553,13 +554,13 @@ CoverTree::CoverTree( // Copy assignment operator: copy the given other tree. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -CoverTree& -CoverTree:: +CoverTree& +CoverTree:: operator=(const CoverTree& other) { if (this == &other) @@ -569,8 +570,8 @@ operator=(const CoverTree& other) if (localDataset) delete dataset; - if (localMetric) - delete metric; + if (localDistance) + delete distance; for (size_t i = 0; i < children.size(); ++i) delete children[i]; @@ -586,9 +587,9 @@ operator=(const CoverTree& other) parent = other.parent; parentDistance = other.parentDistance; furthestDescendantDistance = other.furthestDescendantDistance; - localMetric = other.localMetric; + localDistance = other.localDistance; localDataset = (other.parent == NULL && other.localDataset); - metric = (other.localMetric ? new MetricType() : other.metric); + distance = (other.localDistance ? new DistanceType() : other.distance); distanceComps = 0; // Copy each child by hand. @@ -622,12 +623,12 @@ operator=(const CoverTree& other) // Move Constructor. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -CoverTree::CoverTree( +CoverTree::CoverTree( CoverTree&& other) : dataset(other.dataset), point(other.point), @@ -639,9 +640,9 @@ CoverTree::CoverTree( parent(other.parent), parentDistance(other.parentDistance), furthestDescendantDistance(other.furthestDescendantDistance), - localMetric(other.localMetric), + localDistance(other.localDistance), localDataset(other.localDataset), - metric(other.metric), + distance(other.distance), distanceComps(other.distanceComps) { // Set proper parent pointer. @@ -656,20 +657,20 @@ CoverTree::CoverTree( other.parent = NULL; other.parentDistance = 0; other.furthestDescendantDistance = 0; - other.localMetric = false; + other.localDistance = false; other.localDataset = false; - other.metric = NULL; + other.distance = NULL; } // Move assignment operator: take ownership of the given tree. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -CoverTree& -CoverTree:: +CoverTree& +CoverTree:: operator=(CoverTree&& other) { if (this == &other) @@ -679,8 +680,8 @@ operator=(CoverTree&& other) if (localDataset) delete dataset; - if (localMetric) - delete metric; + if (localDistance) + delete distance; for (size_t i = 0; i < children.size(); ++i) delete children[i]; @@ -695,9 +696,9 @@ operator=(CoverTree&& other) parent = other.parent; parentDistance = other.parentDistance; furthestDescendantDistance = other.furthestDescendantDistance; - localMetric = other.localMetric; + localDistance = other.localDistance; localDataset = other.localDataset; - metric = other.metric; + distance = other.distance; distanceComps = other.distanceComps; // Set proper parent pointer. @@ -712,22 +713,22 @@ operator=(CoverTree&& other) other.parent = NULL; other.parentDistance = 0; other.furthestDescendantDistance = 0; - other.localMetric = false; + other.localDistance = false; other.localDataset = false; - other.metric = NULL; + other.distance = NULL; return *this; } // Construct from a cereal archive. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > template -CoverTree::CoverTree( +CoverTree::CoverTree( Archive& ar, const typename std::enable_if_t()>*) : CoverTree() // Create an empty CoverTree. @@ -738,20 +739,20 @@ CoverTree::CoverTree( template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -CoverTree::~CoverTree() +CoverTree::~CoverTree() { // Delete each child. for (size_t i = 0; i < children.size(); ++i) delete children[i]; - // Delete the local metric, if necessary. - if (localMetric) - delete metric; + // Delete the local distance metric, if necessary. + if (localDistance) + delete distance; // Delete the local dataset, if necessary. if (localDataset) @@ -760,13 +761,13 @@ CoverTree::~CoverTree() //! Return the number of descendant points. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > inline size_t -CoverTree:: +CoverTree:: NumDescendants() const { return numDescendants; @@ -774,13 +775,13 @@ CoverTree:: //! Return the index of a particular descendant point. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > inline size_t -CoverTree::Descendant( +CoverTree::Descendant( const size_t index) const { // The first descendant is the point contained within this node. @@ -808,12 +809,12 @@ CoverTree::Descendant( * Return the index of the nearest child node to the given query point. If * this is a leaf node, it will return NumChildren() (invalid index). */ -template template -size_t CoverTree:: +size_t CoverTree:: GetNearestChild(const VecType& point, typename std::enable_if_t::value>*) { @@ -838,12 +839,12 @@ size_t CoverTree:: * Return the index of the furthest child node to the given query point. If * this is a leaf node, it will return NumChildren() (invalid index). */ -template template -size_t CoverTree:: +size_t CoverTree:: GetFurthestChild(const VecType& point, typename std::enable_if_t::value>*) { @@ -868,11 +869,11 @@ size_t CoverTree:: * Return the index of the nearest child node to the given query node. If it * can't decide, it will return NumChildren() (invalid index). */ -template -size_t CoverTree:: +size_t CoverTree:: GetNearestChild(const CoverTree& queryNode) { if (IsLeaf()) @@ -896,11 +897,11 @@ size_t CoverTree:: * Return the index of the furthest child node to the given query node. If it * can't decide, it will return NumChildren() (invalid index). */ -template -size_t CoverTree:: +size_t CoverTree:: GetFurthestChild(const CoverTree& queryNode) { if (IsLeaf()) @@ -921,31 +922,31 @@ size_t CoverTree:: } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -typename CoverTree::ElemType -CoverTree:: +CoverTree:: MinDistance(const CoverTree& other) const { // Every cover tree node will contain points up to base^(scale + 1) away. - return std::max(metric->Evaluate(dataset->col(point), + return std::max(distance->Evaluate(dataset->col(point), other.Dataset().col(other.Point())) - furthestDescendantDistance - other.FurthestDescendantDistance(), 0.0); } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -typename CoverTree::ElemType -CoverTree:: +CoverTree:: MinDistance(const CoverTree& other, const ElemType distance) const { // We already have the distance as evaluated by the metric. @@ -954,59 +955,59 @@ CoverTree:: } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -typename CoverTree::ElemType -CoverTree:: +CoverTree:: MinDistance(const arma::vec& other) const { - return std::max(metric->Evaluate(dataset->col(point), other) - + return std::max(distance->Evaluate(dataset->col(point), other) - furthestDescendantDistance, 0.0); } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -typename CoverTree::ElemType -CoverTree:: +CoverTree:: MinDistance(const arma::vec& /* other */, const ElemType distance) const { return std::max(distance - furthestDescendantDistance, 0.0); } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -typename CoverTree::ElemType -CoverTree:: +CoverTree:: MaxDistance(const CoverTree& other) const { - return metric->Evaluate(dataset->col(point), + return distance->Evaluate(dataset->col(point), other.Dataset().col(other.Point())) + furthestDescendantDistance + other.FurthestDescendantDistance(); } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -typename CoverTree::ElemType -CoverTree:: +CoverTree:: MaxDistance(const CoverTree& other, const ElemType distance) const { // We already have the distance as evaluated by the metric. @@ -1015,29 +1016,29 @@ CoverTree:: } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -typename CoverTree::ElemType -CoverTree:: +CoverTree:: MaxDistance(const arma::vec& other) const { - return metric->Evaluate(dataset->col(point), other) + + return distance->Evaluate(dataset->col(point), other) + furthestDescendantDistance; } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -typename CoverTree::ElemType -CoverTree:: +CoverTree:: MaxDistance(const arma::vec& /* other */, const ElemType distance) const { return distance + furthestDescendantDistance; @@ -1045,23 +1046,23 @@ CoverTree:: //! Return the minimum and maximum distance to another node. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > RangeType::ElemType> -CoverTree:: + CoverTree::ElemType> +CoverTree:: RangeDistance(const CoverTree& other) const { - const ElemType distance = metric->Evaluate(dataset->col(point), + const ElemType dist = distance->Evaluate(dataset->col(point), other.Dataset().col(other.Point())); RangeType result; - result.Lo() = std::max(distance - furthestDescendantDistance - + result.Lo() = std::max(dist - furthestDescendantDistance - other.FurthestDescendantDistance(), 0.0); - result.Hi() = distance + furthestDescendantDistance + + result.Hi() = dist + furthestDescendantDistance + other.FurthestDescendantDistance(); return result; @@ -1070,14 +1071,14 @@ CoverTree:: //! Return the minimum and maximum distance to another node given that the //! point-to-point distance has already been calculated. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > RangeType::ElemType> -CoverTree:: + CoverTree::ElemType> +CoverTree:: RangeDistance(const CoverTree& other, const ElemType distance) const { @@ -1092,34 +1093,34 @@ CoverTree:: //! Return the minimum and maximum distance to another point. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > RangeType::ElemType> -CoverTree:: + CoverTree::ElemType> +CoverTree:: RangeDistance(const arma::vec& other) const { - const ElemType distance = metric->Evaluate(dataset->col(point), other); + const ElemType dist = distance->Evaluate(dataset->col(point), other); return RangeType( - std::max(distance - furthestDescendantDistance, 0.0), - distance + furthestDescendantDistance); + std::max(dist - furthestDescendantDistance, 0.0), + dist + furthestDescendantDistance); } //! Return the minimum and maximum distance to another point given that the //! point-to-point distance has already been calculated. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > RangeType::ElemType> -CoverTree:: + CoverTree::ElemType> +CoverTree:: RangeDistance(const arma::vec& /* other */, const ElemType distance) const { @@ -1130,13 +1131,13 @@ CoverTree:: //! For a newly initialized node, create children using the near and far set. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > inline void -CoverTree::CreateChildren( +CoverTree::CreateChildren( arma::Col& indices, arma::vec& distances, size_t nearSetSize, @@ -1159,7 +1160,7 @@ CoverTree::CreateChildren( // This should not modify farSetSize or usedSetSize. size_t tempSize = 0; children.push_back(new CoverTree(*dataset, base, point, INT_MIN, this, 0, - indices, distances, 0, tempSize, usedSetSize, *metric)); + indices, distances, 0, tempSize, usedSetSize, *distance)); distanceComps += children.back()->DistanceComps(); // Every point in the near set should be a leaf. @@ -1168,7 +1169,7 @@ CoverTree::CreateChildren( // farSetSize and usedSetSize will not be modified. children.push_back(new CoverTree(*dataset, base, indices[i], INT_MIN, this, distances[i], indices, distances, 0, tempSize, - usedSetSize, *metric)); + usedSetSize, *distance)); distanceComps += children.back()->DistanceComps(); usedSetSize++; } @@ -1200,7 +1201,7 @@ CoverTree::CreateChildren( size_t childUsedSetSize = 0; children.push_back(new CoverTree(*dataset, base, point, nextScale, this, 0, indices, distances, childNearSetSize, childFarSetSize, childUsedSetSize, - *metric)); + *distance)); // Don't double-count the self-child (so, subtract one). numDescendants += children[0]->NumDescendants(); @@ -1258,7 +1259,7 @@ CoverTree::CreateChildren( size_t childNearSetSize = 0; children.push_back(new CoverTree(*dataset, base, indices[0], nextScale, this, distances[0], indices, distances, childNearSetSize, farSetSize, - usedSetSize, *metric)); + usedSetSize, *distance)); distanceComps += children.back()->DistanceComps(); numDescendants += children.back()->NumDescendants(); @@ -1300,7 +1301,7 @@ CoverTree::CreateChildren( childUsedSetSize = 1; // Mark self point as used. children.push_back(new CoverTree(*dataset, base, indices[0], nextScale, this, distances[0], childIndices, childDistances, childNearSetSize, - childFarSetSize, childUsedSetSize, *metric)); + childFarSetSize, childUsedSetSize, *distance)); numDescendants += children.back()->NumDescendants(); // Remove any implicit nodes. @@ -1325,12 +1326,12 @@ CoverTree::CreateChildren( } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -size_t CoverTree:: +size_t CoverTree:: SplitNearFar(arma::Col& indices, arma::vec& distances, const ElemType bound, @@ -1383,12 +1384,12 @@ size_t CoverTree:: // Returns the maximum distance between points. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -void CoverTree:: +void CoverTree:: ComputeDistances(const size_t pointIndex, const arma::Col& indices, arma::vec& distances, @@ -1399,18 +1400,18 @@ void CoverTree:: distanceComps += pointSetSize; for (size_t i = 0; i < pointSetSize; ++i) { - distances[i] = metric->Evaluate(dataset->col(pointIndex), + distances[i] = distance->Evaluate(dataset->col(pointIndex), dataset->col(indices[i])); } } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -size_t CoverTree:: +size_t CoverTree:: SortPointSet(arma::Col& indices, arma::vec& distances, const size_t childFarSetSize, @@ -1470,12 +1471,12 @@ size_t CoverTree:: } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -void CoverTree:: +void CoverTree:: MoveToUsedSet(arma::Col& indices, arma::vec& distances, size_t& nearSetSize, @@ -1616,12 +1617,12 @@ void CoverTree:: } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -size_t CoverTree:: +size_t CoverTree:: PruneFarSet(arma::Col& indices, arma::vec& distances, const ElemType bound, @@ -1662,12 +1663,12 @@ size_t CoverTree:: * implicit nodes that have been created. */ template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -inline void CoverTree:: +inline void CoverTree:: RemoveNewImplicitNodes() { // If we created an implicit node, take its self-child instead (this could @@ -1697,12 +1698,12 @@ inline void CoverTree:: * Default constructor, only for use with cereal. */ template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > -CoverTree::CoverTree() : +CoverTree::CoverTree() : dataset(NULL), point(0), scale(INT_MIN), @@ -1711,9 +1712,9 @@ CoverTree::CoverTree() : parent(NULL), parentDistance(0.0), furthestDescendantDistance(0.0), - localMetric(false), + localDistance(false), localDataset(false), - metric(NULL), + distance(NULL), distanceComps(0) { // Nothing to do. @@ -1723,25 +1724,26 @@ CoverTree::CoverTree() : * Serialize to/from a cereal archive. */ template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > template -void CoverTree::serialize( +void +CoverTree::serialize( Archive& ar, const uint32_t /* version */) { // If we're loading, and we have children, they need to be deleted. We may - // also need to delete the local metric and dataset. + // also need to delete the local distance metric and dataset. if (cereal::is_loading()) { for (size_t i = 0; i < children.size(); ++i) delete children[i]; - if (localMetric && metric) - delete metric; + if (localDistance && distance) + delete distance; if (localDataset && dataset) delete dataset; @@ -1761,11 +1763,11 @@ void CoverTree::serialize( ar(CEREAL_NVP(numDescendants)); ar(CEREAL_NVP(parentDistance)); ar(CEREAL_NVP(furthestDescendantDistance)); - ar(CEREAL_POINTER(metric)); + ar(CEREAL_POINTER(distance)); if (cereal::is_loading() && !hasParent) { - localMetric = true; + localDistance = true; localDataset = true; } @@ -1777,7 +1779,7 @@ void CoverTree::serialize( // Look through each child individually. for (size_t i = 0; i < children.size(); ++i) { - children[i]->localMetric = false; + children[i]->localDistance = false; children[i]->localDataset = false; children[i]->Parent() = this; } diff --git a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp index ea68b74f21..1aac4441ab 100644 --- a/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp +++ b/src/mlpack/core/tree/cover_tree/dual_tree_traverser.hpp @@ -18,13 +18,13 @@ namespace mlpack { template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > template -class CoverTree:: +class CoverTree:: DualTreeTraverser { public: @@ -63,7 +63,7 @@ class CoverTree:: struct DualCoverTreeMapEntry { //! The node this entry refers to. - CoverTree* + CoverTree* referenceNode; //! The score of the node. double score; diff --git a/src/mlpack/core/tree/cover_tree/dual_tree_traverser_impl.hpp b/src/mlpack/core/tree/cover_tree/dual_tree_traverser_impl.hpp index 28310a7cd0..29fe300842 100644 --- a/src/mlpack/core/tree/cover_tree/dual_tree_traverser_impl.hpp +++ b/src/mlpack/core/tree/cover_tree/dual_tree_traverser_impl.hpp @@ -18,26 +18,26 @@ namespace mlpack { template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > template -CoverTree:: +CoverTree:: DualTreeTraverser::DualTreeTraverser(RuleType& rule) : rule(rule), numPrunes(0) { /* Nothing to do. */ } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > template -void CoverTree:: +void CoverTree:: DualTreeTraverser::Traverse(CoverTree& queryNode, CoverTree& referenceNode) { @@ -60,13 +60,13 @@ DualTreeTraverser::Traverse(CoverTree& queryNode, } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > template -void CoverTree:: +void CoverTree:: DualTreeTraverser::Traverse( CoverTree& queryNode, std::map, std::greater>& @@ -150,13 +150,13 @@ DualTreeTraverser::Traverse( } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > template -void CoverTree:: +void CoverTree:: DualTreeTraverser::PruneMap( CoverTree& queryNode, std::map, std::greater>& @@ -271,13 +271,13 @@ DualTreeTraverser::PruneMap( } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > template -void CoverTree:: +void CoverTree:: DualTreeTraverser::ReferenceRecursion( CoverTree& queryNode, std::map, std::greater>& diff --git a/src/mlpack/core/tree/cover_tree/single_tree_traverser.hpp b/src/mlpack/core/tree/cover_tree/single_tree_traverser.hpp index d02c5cca10..ee75385357 100644 --- a/src/mlpack/core/tree/cover_tree/single_tree_traverser.hpp +++ b/src/mlpack/core/tree/cover_tree/single_tree_traverser.hpp @@ -21,13 +21,13 @@ namespace mlpack { template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > template -class CoverTree:: +class CoverTree:: SingleTreeTraverser { public: diff --git a/src/mlpack/core/tree/cover_tree/single_tree_traverser_impl.hpp b/src/mlpack/core/tree/cover_tree/single_tree_traverser_impl.hpp index ff9b67db62..1db7d2676c 100644 --- a/src/mlpack/core/tree/cover_tree/single_tree_traverser_impl.hpp +++ b/src/mlpack/core/tree/cover_tree/single_tree_traverser_impl.hpp @@ -22,7 +22,7 @@ namespace mlpack { //! This is the structure the cover tree map will use for traversal. template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy @@ -30,7 +30,7 @@ template< struct CoverTreeMapEntry { //! The node this entry refers to. - CoverTree* node; + CoverTree* node; //! The score of the node. double score; //! The index of the parent node. @@ -46,34 +46,34 @@ struct CoverTreeMapEntry }; template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > template -CoverTree:: +CoverTree:: SingleTreeTraverser::SingleTreeTraverser(RuleType& rule) : rule(rule), numPrunes(0) { /* Nothing to do. */ } template< - typename MetricType, + typename DistanceType, typename StatisticType, typename MatType, typename RootPointPolicy > template -void CoverTree:: +void CoverTree:: SingleTreeTraverser::Traverse( const size_t queryIndex, CoverTree& referenceNode) { // This is a non-recursive implementation (which should be faster than a // recursive implementation). - typedef CoverTreeMapEntry - MapEntryType; + typedef CoverTreeMapEntry MapEntryType; // We will use this map as a priority queue. Each key represents the scale, // and then the vector is all the nodes in that scale which need to be diff --git a/src/mlpack/core/tree/cover_tree/traits.hpp b/src/mlpack/core/tree/cover_tree/traits.hpp index 5e79bf5ca9..3e93aefbf9 100644 --- a/src/mlpack/core/tree/cover_tree/traits.hpp +++ b/src/mlpack/core/tree/cover_tree/traits.hpp @@ -23,11 +23,12 @@ namespace mlpack { * tree-independent (but still optimized) tree-based algorithms. See * mlpack/core/tree/tree_traits.hpp for more information. */ -template -class TreeTraits> +class TreeTraits> { public: /** diff --git a/src/mlpack/core/tree/cover_tree/typedef.hpp b/src/mlpack/core/tree/cover_tree/typedef.hpp index 2b52126233..d0401f1a11 100644 --- a/src/mlpack/core/tree/cover_tree/typedef.hpp +++ b/src/mlpack/core/tree/cover_tree/typedef.hpp @@ -34,8 +34,8 @@ namespace mlpack { * * @see @ref trees, CoverTree */ -template -using StandardCoverTree = CoverTree +using StandardCoverTree = CoverTree; diff --git a/src/mlpack/core/tree/example_tree.hpp b/src/mlpack/core/tree/example_tree.hpp index 9ea5e9287a..b7a66b09b4 100644 --- a/src/mlpack/core/tree/example_tree.hpp +++ b/src/mlpack/core/tree/example_tree.hpp @@ -33,11 +33,12 @@ namespace mlpack { * in the order given below. More template parameters are fine, but they must * come after the first three. * - * @tparam MetricType This defines the space in which the tree will be built. - * For some trees, arbitrary metrics cannot be used, and a template - * metaprogramming approach should be used to issue a compile-time error if - * a metric cannot be used with a specific tree type. One example is the - * BinarySpaceTree tree type, which cannot work with the IPMetric class. + * @tparam DistanceType This defines the space in which the tree will be built. + * For some trees, arbitrary distance metrics cannot be used, and a + * template metaprogramming approach should be used to issue a compile-time + * error if a distance metric cannot be used with a specific tree type. + * One example is the BinarySpaceTree tree type, which cannot work with the + * IPMetric class. * @tparam StatisticType A tree node can hold a statistic, which is sometimes * useful for various dual-tree algorithms. The tree itself does not need * to know anything about how the statistic works, but it needs to hold a @@ -48,7 +49,7 @@ namespace mlpack { * matrix type. When the tree is written it should be assumed that MatType * has the same functionality as arma::mat. */ -template, +template, typename StatisticType = EmptyStatistic, typename MatType = arma::mat> class ExampleTree @@ -56,25 +57,27 @@ class ExampleTree public: /** * This constructor will build the tree given a dataset and an instantiated - * metric. Note that the parameter is a MatType& and not an arma::mat&. The - * dataset is not modified by the tree-building process (if it is, see the - * documentation for TreeTraits::RearrangesDataset for how to deal with that - * situation). The MetricType parameter is necessary even though some metrics - * do not hold any state. This is so that the tree does not have to worry - * about instantiating the metric (if the tree had to worry about this, this - * would almost certainly incur additional runtime complexity and a larger - * runtime size of the tree node objects, which is to be avoided). The metric - * can't be const, in case MetricType::Evaluate() is non-const. + * distance metric. Note that the parameter is a MatType& and not an + * arma::mat&. The dataset is not modified by the tree-building process (if + * it is, see the documentation for TreeTraits::RearrangesDataset for how to + * deal with that situation). The DistanceType parameter is necessary even + * though some distance metrics do not hold any state. This is so that the + * tree does not have to worry about instantiating the metric (if the tree had + * to worry about this, this would almost certainly incur additional runtime + * complexity and a larger runtime size of the tree node objects, which is to + * be avoided). The metric can't be const, in case DistanceType::Evaluate() + * is non-const. * * When this constructor is finished, the entire tree will be built and ready * to use. The constructor should call the constructor of the statistic for * each node that is built (see EmptyStatistic for more information). * * @param dataset The dataset that the tree will be built on. - * @param metric The instantiated metric to use to build the dataset. + * @param distance The instantiated distance metric to use to build the + * dataset. */ ExampleTree(const MatType& dataset, - MetricType& metric); + DistanceType& distance); //! Return the number of children of this node. size_t NumChildren() const; @@ -124,10 +127,10 @@ class ExampleTree //! Modify the statistic for this node. StatisticType& Stat(); - //! Get the instantiated metric for this node. - const MetricType& Metric() const; - //! Modify the instantiated metric for this node. - MetricType& Metric(); + //! Get the instantiated distance for this node. + const DistanceType& Distance() const; + //! Modify the instantiated distance for this node. + DistanceType& Distance(); /** * Return the minimum distance between this node and a point. It is not @@ -224,11 +227,11 @@ class ExampleTree /** * This member is just here so the ExampleTree compiles without warnings. It * is not required to be a member in every type of tree. Be aware that - * storing the metric as a member and not a reference may mean that for some - * metrics (such as MahalanobisDistance in high dimensionality) may incur lots - * of unnecessary matrix copying. + * storing the distance metric as a member and not a reference may mean that + * for some distance metrics (such as MahalanobisDistance in high + * dimensionality) may incur lots of unnecessary matrix copying. */ - MetricType& metric; + DistanceType& metric; }; } // namespace mlpack diff --git a/src/mlpack/core/tree/hollow_ball_bound.hpp b/src/mlpack/core/tree/hollow_ball_bound.hpp index 4843e98d5b..7de7041171 100644 --- a/src/mlpack/core/tree/hollow_ball_bound.hpp +++ b/src/mlpack/core/tree/hollow_ball_bound.hpp @@ -2,7 +2,7 @@ * @file core/tree/hollow_ball_bound.hpp * * Bounds that are useful for binary space partitioning trees. - * Interface to a ball bound that works in arbitrary metric spaces. + * Interface to a hollow ball bound that works in arbitrary metric spaces. * * mlpack is free software; you may redistribute it and/or modify it under the * terms of the 3-clause BSD license. You should have received a copy of the @@ -13,7 +13,7 @@ #define MLPACK_CORE_TREE_HOLLOW_BALL_BOUND_HPP #include -#include +#include #include "bound_traits.hpp" namespace mlpack { @@ -21,19 +21,19 @@ namespace mlpack { /** * Hollow ball bound encloses a set of points at a specific distance (radius) * from a specific point (center) except points at a specific distance from - * another point (the center of the hole). MetricType is the custom metric type - * that defaults to the Euclidean (L2) distance. + * another point (the center of the hole). DistanceType is the custom distance + * metric type that defaults to the Euclidean (L2) distance. * - * @tparam TMetricType metric type used in the distance measure. + * @tparam TDistanceType metric type used in the distance measure. * @tparam ElemType Type of element (float or double or similar). */ -template, +template, typename ElemType = double> class HollowBallBound { public: //! A public version of the metric type. - typedef TMetricType MetricType; + typedef TDistanceType DistanceType; private: //! The inner and the outer radii of the bound. @@ -42,16 +42,16 @@ class HollowBallBound arma::Col center; //! The center of the hollow. arma::Col hollowCenter; - //! The metric used in this bound. - MetricType* metric; + //! The distance metric used in this bound. + DistanceType* distance; /** - * To know whether this object allocated memory to the metric member + * To know whether this object allocated memory to the distance member * variable. This will be true except in the copy constructor and the * overloaded assignment operator. We need this to know whether we should - * delete the metric member variable in the destructor. + * delete the distance member variable in the destructor. */ - bool ownsMetric; + bool ownsDistance; public: //! Empty Constructor. @@ -228,9 +228,16 @@ class HollowBallBound ElemType Diameter() const { return 2 * radii.Hi(); } //! Returns the distance metric used in this bound. - const MetricType& Metric() const { return *metric; } + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + const DistanceType& Metric() const { return *distance; } //! Modify the distance metric used in this bound. - MetricType& Metric() { return *metric; } + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + DistanceType& Metric() { return *distance; } + + //! Returns the distance metric used in this bound. + const DistanceType& Distance() const { return *distance; } + //! Modify the distance metric used in this bound. + DistanceType& Distance() { return *distance; } //! Serialize the bound. template @@ -238,8 +245,8 @@ class HollowBallBound }; //! A specialization of BoundTraits for this bound type. -template -struct BoundTraits> +template +struct BoundTraits> { //! These bounds are potentially loose in some dimensions. const static bool HasTightBounds = false; diff --git a/src/mlpack/core/tree/hollow_ball_bound_impl.hpp b/src/mlpack/core/tree/hollow_ball_bound_impl.hpp index 1b14f3fbda..921d9c6d57 100644 --- a/src/mlpack/core/tree/hollow_ball_bound_impl.hpp +++ b/src/mlpack/core/tree/hollow_ball_bound_impl.hpp @@ -18,12 +18,12 @@ namespace mlpack { //! Empty Constructor. -template -HollowBallBound::HollowBallBound() : +template +HollowBallBound::HollowBallBound() : radii(std::numeric_limits::lowest(), std::numeric_limits::lowest()), - metric(new MetricType()), - ownsMetric(true) + distance(new DistanceType()), + ownsDistance(true) { /* Nothing to do. */ } /** @@ -31,15 +31,15 @@ HollowBallBound::HollowBallBound() : * * @param dimension Dimensionality of ball bound. */ -template -HollowBallBound:: +template +HollowBallBound:: HollowBallBound(const size_t dimension) : radii(std::numeric_limits::lowest(), std::numeric_limits::lowest()), center(dimension), hollowCenter(dimension), - metric(new MetricType()), - ownsMetric(true) + distance(new DistanceType()), + ownsDistance(true) { /* Nothing to do. */ } /** @@ -49,9 +49,9 @@ HollowBallBound(const size_t dimension) : * @param outerRadius Outer radius of hollow ball bound. * @param center Center of hollow ball bound. */ -template +template template -HollowBallBound:: +HollowBallBound:: HollowBallBound(const ElemType innerRadius, const ElemType outerRadius, const VecType& center) : @@ -59,62 +59,62 @@ HollowBallBound(const ElemType innerRadius, outerRadius), center(center), hollowCenter(center), - metric(new MetricType()), - ownsMetric(true) + distance(new DistanceType()), + ownsDistance(true) { /* Nothing to do. */ } //! Copy Constructor. To prevent memory leaks. -template -HollowBallBound::HollowBallBound( +template +HollowBallBound::HollowBallBound( const HollowBallBound& other) : radii(other.radii), center(other.center), hollowCenter(other.hollowCenter), - metric(other.metric), - ownsMetric(false) + distance(other.distance), + ownsDistance(false) { /* Nothing to do. */ } //! For the same reason as the copy constructor: to prevent memory leaks. -template -HollowBallBound& HollowBallBound:: +template +HollowBallBound& HollowBallBound:: operator=(const HollowBallBound& other) { if (this != &other) { - if (ownsMetric) - delete metric; + if (ownsDistance) + delete distance; radii = other.radii; center = other.center; hollowCenter = other.hollowCenter; - metric = other.metric; - ownsMetric = false; + distance = other.distance; + ownsDistance = false; } return *this; } //! Move constructor. -template -HollowBallBound::HollowBallBound( +template +HollowBallBound::HollowBallBound( HollowBallBound&& other) : radii(other.radii), center(std::move(other.center)), hollowCenter(std::move(other.hollowCenter)), - metric(other.metric), - ownsMetric(other.ownsMetric) + distance(other.distance), + ownsDistance(other.ownsDistance) { // Fix the other bound. other.radii.Hi() = 0.0; other.radii.Lo() = 0.0; other.center = arma::Col(); other.hollowCenter = arma::Col(); - other.metric = NULL; - other.ownsMetric = false; + other.distance = NULL; + other.ownsDistance = false; } //! Move assignment operator. -template -HollowBallBound& HollowBallBound:: +template +HollowBallBound& HollowBallBound:: operator=(HollowBallBound&& other) { if (this != &other) @@ -122,30 +122,30 @@ operator=(HollowBallBound&& other) radii = other.radii; center = std::move(other.center); hollowCenter = std::move(other.hollowCenter); - metric = other.metric; - ownsMetric = other.ownsMetric; + distance = other.distance; + ownsDistance = other.ownsDistance; other.radii.Hi() = 0.0; other.radii.Lo() = 0.0; other.center = arma::Col(); other.hollowCenter = arma::Col(); - other.metric = nullptr; - other.ownsMetric = false; + other.distance = nullptr; + other.ownsDistance = false; } return *this; } //! Destructor to release allocated memory. -template -HollowBallBound::~HollowBallBound() +template +HollowBallBound::~HollowBallBound() { - if (ownsMetric) - delete metric; + if (ownsDistance) + delete distance; } //! Get the range in a certain dimension. -template -RangeType HollowBallBound::operator[]( +template +RangeType HollowBallBound::operator[]( const size_t i) const { if (radii.Hi() < 0) @@ -157,21 +157,21 @@ RangeType HollowBallBound::operator[]( /** * Determines if a point is within the bound. */ -template +template template -bool HollowBallBound::Contains( +bool HollowBallBound::Contains( const VecType& point) const { if (radii.Hi() < 0) return false; else { - ElemType dist = metric->Evaluate(center, point); + ElemType dist = distance->Evaluate(center, point); if (dist > radii.Hi()) return false; // The point is situated outside the outer ball. // Check if the point is situated outside the hole. - dist = metric->Evaluate(hollowCenter, point); + dist = distance->Evaluate(hollowCenter, point); return (dist >= radii.Lo()); } @@ -180,18 +180,18 @@ bool HollowBallBound::Contains( /** * Determines if another bound is within this bound. */ -template -bool HollowBallBound::Contains( +template +bool HollowBallBound::Contains( const HollowBallBound& other) const { if (radii.Hi() < 0) return false; else { - const ElemType dist = metric->Evaluate(center, other.center); - const ElemType hollowCenterDist = metric->Evaluate(hollowCenter, + const ElemType dist = distance->Evaluate(center, other.center); + const ElemType hollowCenterDist = distance->Evaluate(hollowCenter, other.center); - const ElemType hollowHollowDist = metric->Evaluate(hollowCenter, + const ElemType hollowHollowDist = distance->Evaluate(hollowCenter, other.hollowCenter); // The outer ball of the second bound does not contain the hole of the first @@ -215,9 +215,9 @@ bool HollowBallBound::Contains( /** * Calculates minimum bound-to-point squared distance. */ -template +template template -ElemType HollowBallBound::MinDistance( +ElemType HollowBallBound::MinDistance( const VecType& point, typename std::enable_if_t::value>* /* junk */) const { @@ -225,14 +225,15 @@ ElemType HollowBallBound::MinDistance( return std::numeric_limits::max(); else { - const ElemType outerDistance = metric->Evaluate(point, center) - radii.Hi(); + const ElemType outerDistance = distance->Evaluate(point, center) - + radii.Hi(); if (outerDistance >= 0) return outerDistance; // The outer ball does not contain the point. // Check if the point is situated in the hole. const ElemType innerDistance = std::max(radii.Lo() - - metric->Evaluate(point, hollowCenter), (ElemType) 0.0); + distance->Evaluate(point, hollowCenter), (ElemType) 0.0); return innerDistance; } @@ -241,8 +242,8 @@ ElemType HollowBallBound::MinDistance( /** * Calculates minimum bound-to-bound squared distance. */ -template -ElemType HollowBallBound::MinDistance( +template +ElemType HollowBallBound::MinDistance( const HollowBallBound& other) const { @@ -250,7 +251,7 @@ ElemType HollowBallBound::MinDistance( return std::numeric_limits::max(); else { - const ElemType outerDistance = metric->Evaluate(center, other.center) - + const ElemType outerDistance = distance->Evaluate(center, other.center) - radii.Hi() - other.radii.Hi(); if (outerDistance >= 0) return outerDistance; // The outer hollows do not overlap. @@ -258,14 +259,14 @@ ElemType HollowBallBound::MinDistance( // Check if the hole of the second bound contains the outer ball of the // first bound. const ElemType innerDistance1 = other.radii.Lo() - - metric->Evaluate(center, other.hollowCenter) - radii.Hi(); + distance->Evaluate(center, other.hollowCenter) - radii.Hi(); if (innerDistance1 >= 0) return innerDistance1; // Check if the hole of the first bound contains the outer ball of the // second bound. const ElemType innerDistance2 = std::max(radii.Lo() - - metric->Evaluate(hollowCenter, other.center) - other.radii.Hi(), + distance->Evaluate(hollowCenter, other.center) - other.radii.Hi(), (ElemType) 0.0); return innerDistance2; @@ -275,30 +276,30 @@ ElemType HollowBallBound::MinDistance( /** * Computes maximum distance. */ -template +template template -ElemType HollowBallBound::MaxDistance( +ElemType HollowBallBound::MaxDistance( const VecType& point, typename std::enable_if_t::value>* /* junk */) const { if (radii.Hi() < 0) return std::numeric_limits::max(); else - return metric->Evaluate(point, center) + radii.Hi(); + return distance->Evaluate(point, center) + radii.Hi(); } /** * Computes maximum distance. */ -template -ElemType HollowBallBound::MaxDistance( +template +ElemType HollowBallBound::MaxDistance( const HollowBallBound& other) const { if (radii.Hi() < 0) return std::numeric_limits::max(); else - return metric->Evaluate(other.center, center) + radii.Hi() + + return distance->Evaluate(other.center, center) + radii.Hi() + other.radii.Hi(); } @@ -307,9 +308,9 @@ ElemType HollowBallBound::MaxDistance( * * Example: bound1.MinDistanceSq(other) for minimum squared distance. */ -template +template template -RangeType HollowBallBound::RangeDistance( +RangeType HollowBallBound::RangeDistance( const VecType& point, typename std::enable_if_t::value>* /* junk */) const { @@ -319,7 +320,7 @@ RangeType HollowBallBound::RangeDistance( else { RangeType range; - const ElemType dist = metric->Evaluate(point, center); + const ElemType dist = distance->Evaluate(point, center); if (dist >= radii.Hi()) // The outer ball does not contain the point. range.Lo() = dist - radii.Hi(); @@ -327,7 +328,7 @@ RangeType HollowBallBound::RangeDistance( { // Check if the point is situated in the hole. range.Lo() = std::max(radii.Lo() - - metric->Evaluate(point, hollowCenter), (ElemType) 0.0); + distance->Evaluate(point, hollowCenter), (ElemType) 0.0); } range.Hi() = dist + radii.Hi(); @@ -335,8 +336,8 @@ RangeType HollowBallBound::RangeDistance( } } -template -RangeType HollowBallBound::RangeDistance( +template +RangeType HollowBallBound::RangeDistance( const HollowBallBound& other) const { if (radii.Hi() < 0) @@ -346,7 +347,7 @@ RangeType HollowBallBound::RangeDistance( { RangeType range; - const ElemType dist = metric->Evaluate(center, other.center); + const ElemType dist = distance->Evaluate(center, other.center); const ElemType outerDistance = dist - radii.Hi() - other.radii.Hi(); if (outerDistance >= 0) @@ -354,7 +355,7 @@ RangeType HollowBallBound::RangeDistance( else { const ElemType innerDistance1 = other.radii.Lo() - - metric->Evaluate(center, other.hollowCenter) - radii.Hi(); + distance->Evaluate(center, other.hollowCenter) - radii.Hi(); // Check if the outer ball of the first bound is contained in the // hole of the second bound. if (innerDistance1 >= 0) @@ -364,7 +365,7 @@ RangeType HollowBallBound::RangeDistance( // Check if the outer ball of the second bound is contained in the // hole of the first bound. range.Lo() = std::max(radii.Lo() - - metric->Evaluate(hollowCenter, other.center) - other.radii.Hi(), + distance->Evaluate(hollowCenter, other.center) - other.radii.Hi(), (ElemType) 0.0); } } @@ -379,10 +380,10 @@ RangeType HollowBallBound::RangeDistance( * The difference lies in the way we initialize the ball bound. The way we * expand the bound is same. */ -template +template template -const HollowBallBound& -HollowBallBound::operator|=(const MatType& data) +const HollowBallBound& +HollowBallBound::operator|=(const MatType& data) { if (radii.Hi() < 0) { @@ -397,8 +398,8 @@ HollowBallBound::operator|=(const MatType& data) // Now iteratively add points. for (size_t i = 0; i < data.n_cols; ++i) { - const ElemType dist = metric->Evaluate(center, data.col(i)); - const ElemType hollowDist = metric->Evaluate(hollowCenter, data.col(i)); + const ElemType dist = distance->Evaluate(center, data.col(i)); + const ElemType hollowDist = distance->Evaluate(hollowCenter, data.col(i)); // See if the new point lies outside the bound. if (dist > radii.Hi()) @@ -419,9 +420,9 @@ HollowBallBound::operator|=(const MatType& data) /** * Expand the bound to include the given bound. */ -template -const HollowBallBound& -HollowBallBound::operator|=(const HollowBallBound& other) +template +const HollowBallBound& +HollowBallBound::operator|=(const HollowBallBound& other) { if (radii.Hi() < 0) { @@ -432,13 +433,13 @@ HollowBallBound::operator|=(const HollowBallBound& other) return *this; } - const ElemType dist = metric->Evaluate(center, other.center); + const ElemType dist = distance->Evaluate(center, other.center); // Check if the outer balls overlap. if (radii.Hi() < dist + other.radii.Hi()) radii.Hi() = dist + other.radii.Hi(); const ElemType innerDist = std::max(other.radii.Lo() - - metric->Evaluate(hollowCenter, other.hollowCenter), (ElemType) 0.0); + distance->Evaluate(hollowCenter, other.hollowCenter), (ElemType) 0.0); // Check if the hole of the first bound is not contained in the hole of the // second bound. if (radii.Lo() > innerDist) @@ -449,23 +450,23 @@ HollowBallBound::operator|=(const HollowBallBound& other) //! Serialize the BallBound. -template +template template -void HollowBallBound::serialize( +void HollowBallBound::serialize( Archive& ar, const uint32_t /* version */) { ar(CEREAL_NVP(radii)); ar(CEREAL_NVP(center)); ar(CEREAL_NVP(hollowCenter)); - ar(CEREAL_POINTER(metric)); + ar(CEREAL_POINTER(distance)); if (cereal::is_loading()) { - // If we're loading, delete the local metric since we'll have a new one. - if (ownsMetric) - delete metric; + // If we're loading, delete the local distance since we'll have a new one. + if (ownsDistance) + delete distance; - ownsMetric = true; + ownsDistance = true; } } diff --git a/src/mlpack/core/tree/hrectbound.hpp b/src/mlpack/core/tree/hrectbound.hpp index acb7d66576..9332c86add 100644 --- a/src/mlpack/core/tree/hrectbound.hpp +++ b/src/mlpack/core/tree/hrectbound.hpp @@ -16,14 +16,14 @@ #include #include -#include +#include #include "bound_traits.hpp" namespace mlpack { //! Utility struct where Value is true if and only if the argument is of type //! LMetric. -template +template struct IsLMetric { static const bool Value = false; @@ -41,15 +41,15 @@ struct IsLMetric> * with the LMetric class. Be sure to use the same template parameters for * LMetric as you do for HRectBound -- otherwise odd results may occur. * - * @tparam MetricType Type of metric to use; must be of type LMetric. + * @tparam DistanceType Type of distance metric to use; must be of type LMetric. * @tparam ElemType Element type (double/float/int/etc.). */ -template, +template, typename ElemType = double> class HRectBound { - // It is required that HRectBound have an LMetric as the given MetricType. - static_assert(IsLMetric::Value == true, + // It is required that HRectBound have an LMetric as the given DistanceType. + static_assert(IsLMetric::Value == true, "HRectBound can only be used with the LMetric<> metric type."); public: @@ -102,10 +102,17 @@ class HRectBound //! Modify the minimum width of the bound. ElemType& MinWidth() { return minWidth; } - //! Get the instantiated metric associated with the bound. - const MetricType& Metric() const { return metric; } - //! Modify the instantiated metric associated with the bound. - MetricType& Metric() { return metric; } + //! Get the instantiated distance metric associated with the bound. + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + const DistanceType& Metric() const { return distance; } + //! Modify the instantiated distance metric associated with the bound. + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + DistanceType& Metric() { return distance; } + + //! Get the instantiated distance metric associated with the bound. + const DistanceType& Distance() const { return distance; } + //! Modify the instantiated distance metric associated with the bound. + DistanceType& Distance() { return distance; } /** * Calculates the center of the range, placing it into the given vector. @@ -237,13 +244,13 @@ class HRectBound RangeType* bounds; //! Cached minimum width of bound. ElemType minWidth; - //! Instantiated metric (likely has size 0). - MetricType metric; + //! Instantiated distance metric (likely has size 0). + DistanceType distance; }; // A specialization of BoundTraits for this class. -template -struct BoundTraits> +template +struct BoundTraits> { //! These bounds are always tight for each dimension. const static bool HasTightBounds = true; diff --git a/src/mlpack/core/tree/hrectbound_impl.hpp b/src/mlpack/core/tree/hrectbound_impl.hpp index caec1ca5d2..d7c6187009 100644 --- a/src/mlpack/core/tree/hrectbound_impl.hpp +++ b/src/mlpack/core/tree/hrectbound_impl.hpp @@ -2,7 +2,6 @@ * @file core/tree/hrectbound_impl.hpp * * Implementation of hyper-rectangle bound policy class. - * Template parameter Power is the metric to use; use 2 for Euclidean (L2). * * mlpack is free software; you may redistribute it and/or modify it under the * terms of the 3-clause BSD license. You should have received a copy of the @@ -22,8 +21,8 @@ namespace mlpack { /** * Empty constructor. */ -template -inline HRectBound::HRectBound() : +template +inline HRectBound::HRectBound() : dim(0), bounds(NULL), minWidth(0) @@ -33,8 +32,8 @@ inline HRectBound::HRectBound() : * Initializes to specified dimensionality with each dimension the empty * set. */ -template -inline HRectBound::HRectBound(const size_t dimension) : +template +inline HRectBound::HRectBound(const size_t dimension) : dim(dimension), bounds(new RangeType[dim]), minWidth(0) @@ -43,9 +42,9 @@ inline HRectBound::HRectBound(const size_t dimension) : /** * Copy constructor necessary to prevent memory leaks. */ -template -inline HRectBound::HRectBound( - const HRectBound& other) : +template +inline HRectBound::HRectBound( + const HRectBound& other) : dim(other.Dim()), bounds(new RangeType[dim]), minWidth(other.MinWidth()) @@ -58,11 +57,11 @@ inline HRectBound::HRectBound( /** * Same as the copy constructor. */ -template +template inline HRectBound< - MetricType, - ElemType>& HRectBound::operator=(const HRectBound& other) + DistanceType, + ElemType>& HRectBound::operator=(const HRectBound& other) { if (this == &other) return *this; @@ -89,9 +88,9 @@ inline HRectBound< /** * Move constructor: take possession of another bound's information. */ -template -inline HRectBound::HRectBound( - HRectBound&& other) : +template +inline HRectBound::HRectBound( + HRectBound&& other) : dim(other.dim), bounds(other.bounds), minWidth(other.minWidth) @@ -105,10 +104,10 @@ inline HRectBound::HRectBound( /** * Move assignment operator. */ -template -inline HRectBound& -HRectBound::operator=( - HRectBound&& other) +template +inline HRectBound& +HRectBound::operator=( + HRectBound&& other) { if (this != &other) { @@ -125,8 +124,8 @@ HRectBound::operator=( /** * Destructor: clean up memory. */ -template -inline HRectBound::~HRectBound() +template +inline HRectBound::~HRectBound() { if (bounds) delete[] bounds; @@ -135,8 +134,8 @@ inline HRectBound::~HRectBound() /** * Resets all dimensions to the empty set. */ -template -inline void HRectBound::Clear() +template +inline void HRectBound::Clear() { for (size_t i = 0; i < dim; ++i) bounds[i] = RangeType(); @@ -148,8 +147,8 @@ inline void HRectBound::Clear() * * @param centroid Vector which the centroid will be written to. */ -template -inline void HRectBound::Center( +template +inline void HRectBound::Center( arma::Col& center) const { // Set size correctly if necessary. @@ -165,8 +164,8 @@ inline void HRectBound::Center( * * @return Volume of the hyperrectangle. */ -template -inline ElemType HRectBound::Volume() const +template +inline ElemType HRectBound::Volume() const { ElemType volume = 1.0; for (size_t i = 0; i < dim; ++i) @@ -183,9 +182,9 @@ inline ElemType HRectBound::Volume() const /** * Calculates minimum bound-to-point squared distance. */ -template +template template -inline ElemType HRectBound::MinDistance( +inline ElemType HRectBound::MinDistance( const VecType& point, typename std::enable_if_t::value>* /* junk */) const { @@ -202,9 +201,9 @@ inline ElemType HRectBound::MinDistance( // Since only one of 'lower' or 'higher' is negative, if we add each's // absolute value to itself and then sum those two, our result is the // nonnegative half of the equation times two; then we raise to power Power. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) sum += (lower + std::fabs(lower)) + (higher + std::fabs(higher)); - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) { ElemType dist = (lower + std::fabs(lower)) + (higher + std::fabs(higher)); sum += dist * dist; @@ -212,7 +211,7 @@ inline ElemType HRectBound::MinDistance( else { sum += std::pow((lower + std::fabs(lower)) + (higher + std::fabs(higher)), - (ElemType) MetricType::Power); + (ElemType) DistanceType::Power); } } @@ -220,30 +219,30 @@ inline ElemType HRectBound::MinDistance( // to be); then cancel out the constant of 2 (which may have been squared now) // that was introduced earlier. The compiler should optimize out the if // statement entirely. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) return sum * 0.5; - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) { - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) return (ElemType) std::sqrt(sum) * 0.5; else return sum * 0.25; } else { - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) return (ElemType) std::pow((double) sum, - 1.0 / (double) MetricType::Power) / 2.0; + 1.0 / (double) DistanceType::Power) / 2.0; else - return sum / std::pow(2.0, MetricType::Power); + return sum / std::pow(2.0, DistanceType::Power); } } /** * Calculates minimum bound-to-bound squared distance. */ -template -ElemType HRectBound::MinDistance(const HRectBound& other) +template +ElemType HRectBound::MinDistance(const HRectBound& other) const { Log::Assert(dim == other.dim); @@ -262,9 +261,9 @@ ElemType HRectBound::MinDistance(const HRectBound& other) // (x * 2)^2 / 4 = x^2 // The compiler should optimize out this if statement entirely. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) sum += (lower + std::fabs(lower)) + (higher + std::fabs(higher)); - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) { ElemType dist = (lower + std::fabs(lower)) + (higher + std::fabs(higher)); sum += dist * dist; @@ -272,7 +271,7 @@ ElemType HRectBound::MinDistance(const HRectBound& other) else { sum += std::pow((lower + std::fabs(lower)) + (higher + std::fabs(higher)), - (ElemType) MetricType::Power); + (ElemType) DistanceType::Power); } // Move bound pointers. @@ -281,31 +280,31 @@ ElemType HRectBound::MinDistance(const HRectBound& other) } // The compiler should optimize out this if statement entirely. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) return sum * 0.5; - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) { - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) return (ElemType) std::sqrt(sum) * 0.5; else return sum * 0.25; } else { - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) return (ElemType) std::pow((double) sum, - 1.0 / (double) MetricType::Power) / 2.0; + 1.0 / (double) DistanceType::Power) / 2.0; else - return sum / std::pow(2.0, MetricType::Power); + return sum / std::pow(2.0, DistanceType::Power); } } /** * Calculates maximum bound-to-point squared distance. */ -template +template template -inline ElemType HRectBound::MaxDistance( +inline ElemType HRectBound::MaxDistance( const VecType& point, typename std::enable_if_t::value>* /* junk */) const { @@ -319,24 +318,24 @@ inline ElemType HRectBound::MaxDistance( fabs(bounds[d].Hi() - point[d])); // The compiler should optimize out this if statement entirely. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) sum += v; // v is non-negative. - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) sum += v * v; else - sum += std::pow(v, (ElemType) MetricType::Power); + sum += std::pow(v, (ElemType) DistanceType::Power); } // The compiler should optimize out this if statement entirely. - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) { - if (MetricType::Power == 1) + if (DistanceType::Power == 1) return sum; - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) return (ElemType) std::sqrt(sum); else return (ElemType) std::pow((double) sum, 1.0 / - (double) MetricType::Power); + (double) DistanceType::Power); } else return sum; @@ -345,8 +344,8 @@ inline ElemType HRectBound::MaxDistance( /** * Computes maximum distance. */ -template -inline ElemType HRectBound::MaxDistance( +template +inline ElemType HRectBound::MaxDistance( const HRectBound& other) const { @@ -361,24 +360,24 @@ inline ElemType HRectBound::MaxDistance( fabs(bounds[d].Hi() - other.bounds[d].Lo())); // The compiler should optimize out this if statement entirely. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) sum += v; // v is non-negative. - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) sum += v * v; else - sum += std::pow(v, (ElemType) MetricType::Power); + sum += std::pow(v, (ElemType) DistanceType::Power); } // The compiler should optimize out this if statement entirely. - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) { - if (MetricType::Power == 1) + if (DistanceType::Power == 1) return sum; - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) return (ElemType) std::sqrt(sum); else return (ElemType) std::pow((double) sum, 1.0 / - (double) MetricType::Power); + (double) DistanceType::Power); } else return sum; @@ -387,9 +386,9 @@ inline ElemType HRectBound::MaxDistance( /** * Calculates minimum and maximum bound-to-bound squared distance. */ -template +template inline RangeType -HRectBound::RangeDistance( +HRectBound::RangeDistance( const HRectBound& other) const { ElemType loSum = 0; @@ -415,36 +414,36 @@ HRectBound::RangeDistance( } // The compiler should optimize out this if statement entirely. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) { loSum += vLo; // vLo is non-negative. hiSum += vHi; // vHi is non-negative. } - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) { loSum += vLo * vLo; hiSum += vHi * vHi; } else { - loSum += std::pow(vLo, (ElemType) MetricType::Power); - hiSum += std::pow(vHi, (ElemType) MetricType::Power); + loSum += std::pow(vLo, (ElemType) DistanceType::Power); + hiSum += std::pow(vHi, (ElemType) DistanceType::Power); } } - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) { - if (MetricType::Power == 1) + if (DistanceType::Power == 1) return RangeType(loSum, hiSum); - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) return RangeType((ElemType) std::sqrt(loSum), (ElemType) std::sqrt(hiSum)); else { return RangeType( - (ElemType) std::pow((double) loSum, 1.0 / (double) MetricType::Power), + (ElemType) std::pow((double) loSum, 1.0 / (double) DistanceType::Power), (ElemType) std::pow((double) hiSum, - 1.0 / (double) MetricType::Power)); + 1.0 / (double) DistanceType::Power)); } } else @@ -454,10 +453,10 @@ HRectBound::RangeDistance( /** * Calculates minimum and maximum bound-to-point squared distance. */ -template +template template inline RangeType -HRectBound::RangeDistance( +HRectBound::RangeDistance( const VecType& point, typename std::enable_if_t::value>* /* junk */) const { @@ -492,36 +491,36 @@ HRectBound::RangeDistance( } // The compiler should optimize out this if statement entirely. - if (MetricType::Power == 1) + if (DistanceType::Power == 1) { loSum += vLo; // vLo is non-negative. hiSum += vHi; // vHi is non-negative. } - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) { loSum += vLo * vLo; hiSum += vHi * vHi; } else { - loSum += std::pow(vLo, (ElemType) MetricType::Power); - hiSum += std::pow(vHi, (ElemType) MetricType::Power); + loSum += std::pow(vLo, (ElemType) DistanceType::Power); + hiSum += std::pow(vHi, (ElemType) DistanceType::Power); } } - if (MetricType::TakeRoot) + if (DistanceType::TakeRoot) { - if (MetricType::Power == 1) + if (DistanceType::Power == 1) return RangeType(loSum, hiSum); - else if (MetricType::Power == 2) + else if (DistanceType::Power == 2) return RangeType((ElemType) std::sqrt(loSum), (ElemType) std::sqrt(hiSum)); else { return RangeType( - (ElemType) std::pow((double) loSum, 1.0 / (double) MetricType::Power), + (ElemType) std::pow((double) loSum, 1.0 / (double) DistanceType::Power), (ElemType) std::pow((double) hiSum, - 1.0 / (double) MetricType::Power)); + 1.0 / (double) DistanceType::Power)); } } else @@ -531,10 +530,10 @@ HRectBound::RangeDistance( /** * Expands this region to include a new point. */ -template +template template -inline HRectBound& -HRectBound::operator|=(const MatType& data) +inline HRectBound& +HRectBound::operator|=(const MatType& data) { Log::Assert(data.n_rows == dim); @@ -556,9 +555,9 @@ HRectBound::operator|=(const MatType& data) /** * Expands this region to encompass another bound. */ -template -inline HRectBound& -HRectBound::operator|=(const HRectBound& other) +template +inline HRectBound& +HRectBound::operator|=(const HRectBound& other) { assert(other.dim == dim); @@ -577,9 +576,9 @@ HRectBound::operator|=(const HRectBound& other) /** * Determines if a point is within this bound. */ -template +template template -inline bool HRectBound::Contains( +inline bool HRectBound::Contains( const VecType& point) const { for (size_t i = 0; i < point.n_elem; ++i) @@ -594,8 +593,8 @@ inline bool HRectBound::Contains( /** * Determines if this bound partially contains a bound. */ -template -inline bool HRectBound::Contains( +template +inline bool HRectBound::Contains( const HRectBound& bound) const { for (size_t i = 0; i < dim; ++i) @@ -614,11 +613,11 @@ inline bool HRectBound::Contains( /** * Returns the intersection of this bound and another. */ -template -inline HRectBound -HRectBound::operator&(const HRectBound& bound) const +template +inline HRectBound +HRectBound::operator&(const HRectBound& bound) const { - HRectBound result(dim); + HRectBound result(dim); for (size_t k = 0; k < dim; ++k) { @@ -631,9 +630,9 @@ HRectBound::operator&(const HRectBound& bound) const /** * Intersects this bound with another. */ -template -inline HRectBound& -HRectBound::operator&=(const HRectBound& bound) +template +inline HRectBound& +HRectBound::operator&=(const HRectBound& bound) { for (size_t k = 0; k < dim; ++k) { @@ -646,8 +645,8 @@ HRectBound::operator&=(const HRectBound& bound) /** * Returns the volume of overlap of this bound and another. */ -template -inline ElemType HRectBound::Overlap( +template +inline ElemType HRectBound::Overlap( const HRectBound& bound) const { ElemType volume = 1.0; @@ -668,31 +667,31 @@ inline ElemType HRectBound::Overlap( /** * Returns the diameter of the hyperrectangle (that is, the longest diagonal). */ -template -inline ElemType HRectBound::Diameter() const +template +inline ElemType HRectBound::Diameter() const { ElemType d = 0; for (size_t i = 0; i < dim; ++i) d += std::pow(bounds[i].Hi() - bounds[i].Lo(), - (ElemType) MetricType::Power); + (ElemType) DistanceType::Power); - if (MetricType::TakeRoot) - return (ElemType) std::pow((double) d, 1.0 / (double) MetricType::Power); + if (DistanceType::TakeRoot) + return (ElemType) std::pow((double) d, 1.0 / (double) DistanceType::Power); else return d; } //! Serialize the bound object. -template +template template -void HRectBound::serialize( +void HRectBound::serialize( Archive& ar, const uint32_t /* version */) { // We can't serialize a raw array directly, so wrap it. ar(CEREAL_POINTER_ARRAY(bounds, dim)); ar(CEREAL_NVP(minWidth)); - ar(CEREAL_NVP(metric)); + ar(CEREAL_NVP(distance)); } } // namespace mlpack diff --git a/src/mlpack/core/tree/octree/dual_tree_traverser.hpp b/src/mlpack/core/tree/octree/dual_tree_traverser.hpp index 3f64be4873..a31d02ff84 100644 --- a/src/mlpack/core/tree/octree/dual_tree_traverser.hpp +++ b/src/mlpack/core/tree/octree/dual_tree_traverser.hpp @@ -17,11 +17,11 @@ namespace mlpack { -template template -class Octree::DualTreeTraverser +class Octree::DualTreeTraverser { public: /** diff --git a/src/mlpack/core/tree/octree/dual_tree_traverser_impl.hpp b/src/mlpack/core/tree/octree/dual_tree_traverser_impl.hpp index 799e8fd990..7175ead44b 100644 --- a/src/mlpack/core/tree/octree/dual_tree_traverser_impl.hpp +++ b/src/mlpack/core/tree/octree/dual_tree_traverser_impl.hpp @@ -17,9 +17,9 @@ namespace mlpack { -template +template template -Octree::DualTreeTraverser:: +Octree::DualTreeTraverser:: DualTreeTraverser(RuleType& rule) : rule(rule), numPrunes(0), @@ -30,9 +30,9 @@ Octree::DualTreeTraverser:: // Nothing to do. } -template +template template -void Octree::DualTreeTraverser:: +void Octree::DualTreeTraverser:: Traverse(Octree& queryNode, Octree& referenceNode) { // Increment the visit counter. diff --git a/src/mlpack/core/tree/octree/octree.hpp b/src/mlpack/core/tree/octree/octree.hpp index b394299bdc..f3a78ba764 100644 --- a/src/mlpack/core/tree/octree/octree.hpp +++ b/src/mlpack/core/tree/octree/octree.hpp @@ -18,7 +18,7 @@ namespace mlpack { -template class Octree @@ -49,7 +49,7 @@ class Octree size_t count; //! The minimum bounding rectangle of the points held in the node (and its //! children). - HRectBound bound; + HRectBound bound; //! The dataset. MatType* dataset; //! The parent (NULL if this node is the root). @@ -60,8 +60,8 @@ class Octree ElemType parentDistance; //! The distance to the furthest descendant, cached to speed things up. ElemType furthestDescendantDistance; - //! An instantiated metric. - MetricType metric; + //! An instantiated distance metric. + DistanceType distance; public: /** @@ -257,9 +257,9 @@ class Octree Octree*& Parent() { return parent; } //! Return the bound object for this node. - const HRectBound& Bound() const { return bound; } + const HRectBound& Bound() const { return bound; } //! Modify the bound object for this node. - HRectBound& Bound() { return bound; } + HRectBound& Bound() { return bound; } //! Return the statistic object for this node. const StatisticType& Stat() const { return stat; } @@ -269,8 +269,12 @@ class Octree //! Return the number of children in this node. size_t NumChildren() const; - //! Return the metric that this tree uses. - MetricType Metric() const { return MetricType(); } + //! Return the distance metric that this tree uses. + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + DistanceType Metric() const { return distance; } + + //! Return the distance metric that this tree uses. + DistanceType Distance() const { return distance; } /** * Return the index of the nearest child node to the given query point. If diff --git a/src/mlpack/core/tree/octree/octree_impl.hpp b/src/mlpack/core/tree/octree/octree_impl.hpp index 6bb8f9c134..9571df8684 100644 --- a/src/mlpack/core/tree/octree/octree_impl.hpp +++ b/src/mlpack/core/tree/octree/octree_impl.hpp @@ -19,8 +19,8 @@ namespace mlpack { //! Construct the tree. -template -Octree::Octree(const MatType& dataset, +template +Octree::Octree(const MatType& dataset, const size_t maxLeafSize) : begin(0), count(dataset.n_cols), @@ -55,8 +55,8 @@ Octree::Octree(const MatType& dataset, } //! Construct the tree. -template -Octree::Octree( +template +Octree::Octree( const MatType& dataset, std::vector& oldFromNew, const size_t maxLeafSize) : @@ -97,8 +97,8 @@ Octree::Octree( } //! Construct the tree. -template -Octree::Octree( +template +Octree::Octree( const MatType& dataset, std::vector& oldFromNew, std::vector& newFromOld, @@ -145,8 +145,8 @@ Octree::Octree( } //! Construct the tree. -template -Octree::Octree(MatType&& dataset, +template +Octree::Octree(MatType&& dataset, const size_t maxLeafSize) : begin(0), count(dataset.n_cols), @@ -181,8 +181,8 @@ Octree::Octree(MatType&& dataset, } //! Construct the tree. -template -Octree::Octree( +template +Octree::Octree( MatType&& dataset, std::vector& oldFromNew, const size_t maxLeafSize) : @@ -223,8 +223,8 @@ Octree::Octree( } //! Construct the tree. -template -Octree::Octree( +template +Octree::Octree( MatType&& dataset, std::vector& oldFromNew, std::vector& newFromOld, @@ -271,8 +271,8 @@ Octree::Octree( } //! Construct a child node. -template -Octree::Octree( +template +Octree::Octree( Octree* parent, const size_t begin, const size_t count, @@ -296,7 +296,7 @@ Octree::Octree( arma::vec trueCenter, parentCenter; bound.Center(trueCenter); parent->Bound().Center(parentCenter); - parentDistance = metric.Evaluate(trueCenter, parentCenter); + parentDistance = distance.Evaluate(trueCenter, parentCenter); furthestDescendantDistance = 0.5 * bound.Diameter(); @@ -305,8 +305,8 @@ Octree::Octree( } //! Construct a child node. -template -Octree::Octree( +template +Octree::Octree( Octree* parent, const size_t begin, const size_t count, @@ -331,7 +331,7 @@ Octree::Octree( arma::vec trueCenter, parentCenter; bound.Center(trueCenter); parent->Bound().Center(parentCenter); - parentDistance = metric.Evaluate(trueCenter, parentCenter); + parentDistance = distance.Evaluate(trueCenter, parentCenter); furthestDescendantDistance = 0.5 * bound.Diameter(); @@ -340,8 +340,8 @@ Octree::Octree( } //! Copy the given tree. -template -Octree::Octree(const Octree& other) : +template +Octree::Octree(const Octree& other) : begin(other.begin), count(other.count), bound(other.bound), @@ -350,7 +350,7 @@ Octree::Octree(const Octree& other) : stat(other.stat), parentDistance(other.parentDistance), furthestDescendantDistance(other.furthestDescendantDistance), - metric(other.metric) + distance(other.distance) { // If we have any children, we need to create them, and then ensure that their // parent links are set right. @@ -363,9 +363,9 @@ Octree::Octree(const Octree& other) : } //! Copy assignment operator: copy the given other tree. -template -Octree& -Octree:: +template +Octree& +Octree:: operator=(const Octree& other) { // Return if it's the same tree. @@ -386,7 +386,7 @@ operator=(const Octree& other) stat = other.stat; parentDistance = other.ParentDistance(); furthestDescendantDistance = other.FurthestDescendantDistance(); - metric = other.metric; + distance = other.distance; // If we have any children, we need to create them, and then ensure that their // parent links are set right. @@ -400,8 +400,8 @@ operator=(const Octree& other) } //! Move the given tree. -template -Octree::Octree(Octree&& other) : +template +Octree::Octree(Octree&& other) : children(std::move(other.children)), begin(other.begin), count(other.count), @@ -411,7 +411,7 @@ Octree::Octree(Octree&& other) : stat(std::move(other.stat)), parentDistance(other.parentDistance), furthestDescendantDistance(other.furthestDescendantDistance), - metric(std::move(other.metric)) + distance(std::move(other.distance)) { // Update the parent pointers of the direct children. for (size_t i = 0; i < children.size(); ++i) @@ -426,9 +426,9 @@ Octree::Octree(Octree&& other) : } //! Move assignment operator: take ownership of the given tree. -template -Octree& -Octree:: +template +Octree& +Octree:: operator=(Octree&& other) { // Return if it's the same tree. @@ -450,7 +450,7 @@ operator=(Octree&& other) stat = std::move(other.stat); parentDistance = other.ParentDistance(); furthestDescendantDistance = other.furthestDescendantDistance(); - metric = std::move(other.metric); + distance = std::move(other.distance); // Update the parent pointers of the direct children. for (size_t i = 0; i < children.size(); ++i) @@ -467,8 +467,8 @@ operator=(Octree&& other) return *this; } -template -Octree::Octree() : +template +Octree::Octree() : begin(0), count(0), bound(0), @@ -480,9 +480,9 @@ Octree::Octree() : // Nothing to do. } -template +template template -Octree::Octree( +Octree::Octree( Archive& ar, const typename std::enable_if_t()>*) : Octree() // Create an empty tree. @@ -491,8 +491,8 @@ Octree::Octree( ar(CEREAL_NVP(*this)); } -template -Octree::~Octree() +template +Octree::~Octree() { // Delete the dataset if we aren't the parent. if (!parent) @@ -504,15 +504,15 @@ Octree::~Octree() children.clear(); } -template -size_t Octree::NumChildren() const +template +size_t Octree::NumChildren() const { return children.size(); } -template +template template -size_t Octree::GetNearestChild( +size_t Octree::GetNearestChild( const VecType& point, typename std::enable_if_t::value>*) const { @@ -533,9 +533,9 @@ size_t Octree::GetNearestChild( return bestIndex; } -template +template template -size_t Octree::GetFurthestChild( +size_t Octree::GetFurthestChild( const VecType& point, typename std::enable_if_t::value>*) const { @@ -556,8 +556,8 @@ size_t Octree::GetFurthestChild( return bestIndex; } -template -size_t Octree::GetNearestChild( +template +size_t Octree::GetNearestChild( const Octree& queryNode) const { // It's possible that this could be improved by caching which children we have @@ -577,8 +577,8 @@ size_t Octree::GetNearestChild( return bestIndex; } -template -size_t Octree::GetFurthestChild( +template +size_t Octree::GetFurthestChild( const Octree& queryNode) const { // It's possible that this could be improved by caching which children we have @@ -598,9 +598,9 @@ size_t Octree::GetFurthestChild( return bestIndex; } -template -typename Octree::ElemType -Octree::FurthestPointDistance() +template +typename Octree::ElemType +Octree::FurthestPointDistance() const { // If we are not a leaf, then this distance is 0. Otherwise, return the @@ -608,85 +608,85 @@ Octree::FurthestPointDistance() return (children.size() > 0) ? 0.0 : furthestDescendantDistance; } -template -typename Octree::ElemType -Octree::FurthestDescendantDistance() const +template +typename Octree::ElemType +Octree::FurthestDescendantDistance() const { return furthestDescendantDistance; } -template -typename Octree::ElemType -Octree::MinimumBoundDistance() const +template +typename Octree::ElemType +Octree::MinimumBoundDistance() const { return bound.MinWidth() / 2.0; } -template -size_t Octree::NumPoints() const +template +size_t Octree::NumPoints() const { // We have no points unless we are a leaf; return (children.size() > 0) ? 0 : count; } -template -size_t Octree::NumDescendants() const +template +size_t Octree::NumDescendants() const { return count; } -template -size_t Octree::Descendant( +template +size_t Octree::Descendant( const size_t index) const { return begin + index; } -template -size_t Octree::Point(const size_t index) +template +size_t Octree::Point(const size_t index) const { return begin + index; } -template -typename Octree::ElemType -Octree::MinDistance(const Octree& other) +template +typename Octree::ElemType +Octree::MinDistance(const Octree& other) const { return bound.MinDistance(other.Bound()); } -template -typename Octree::ElemType -Octree::MaxDistance(const Octree& other) +template +typename Octree::ElemType +Octree::MaxDistance(const Octree& other) const { return bound.MaxDistance(other.Bound()); } -template -RangeType::ElemType> -Octree::RangeDistance(const Octree& other) +template +RangeType::ElemType> +Octree::RangeDistance(const Octree& other) const { return bound.RangeDistance(other.Bound()); } -template +template template -typename Octree::ElemType -Octree::MinDistance( +typename Octree::ElemType +Octree::MinDistance( const VecType& point, typename std::enable_if_t::value>*) const { return bound.MinDistance(point); } -template +template template -typename Octree::ElemType -Octree::MaxDistance( +typename Octree::ElemType +Octree::MaxDistance( const VecType& point, typename std::enable_if_t::value>*) const { @@ -694,10 +694,10 @@ Octree::MaxDistance( } -template +template template -RangeType::ElemType> -Octree::RangeDistance( +RangeType::ElemType> +Octree::RangeDistance( const VecType& point, typename std::enable_if_t::value>*) const { @@ -705,9 +705,9 @@ Octree::RangeDistance( } //! Serialize the tree. -template +template template -void Octree::serialize( +void Octree::serialize( Archive& ar, const uint32_t /* version */) { @@ -732,7 +732,7 @@ void Octree::serialize( ar(CEREAL_NVP(stat)); ar(CEREAL_NVP(parentDistance)); ar(CEREAL_NVP(furthestDescendantDistance)); - ar(CEREAL_NVP(metric)); + ar(CEREAL_NVP(distance)); ar(CEREAL_NVP(hasParent)); if (!hasParent) { @@ -770,8 +770,8 @@ void Octree::serialize( } //! Split the node. -template -void Octree::SplitNode( +template +void Octree::SplitNode( const arma::vec& center, const double width, const size_t maxLeafSize) @@ -871,8 +871,8 @@ void Octree::SplitNode( } //! Split the node, and store mappings. -template -void Octree::SplitNode( +template +void Octree::SplitNode( const arma::vec& center, const double width, std::vector& oldFromNew, diff --git a/src/mlpack/core/tree/octree/single_tree_traverser.hpp b/src/mlpack/core/tree/octree/single_tree_traverser.hpp index 9536d11a6f..0d8278a254 100644 --- a/src/mlpack/core/tree/octree/single_tree_traverser.hpp +++ b/src/mlpack/core/tree/octree/single_tree_traverser.hpp @@ -17,9 +17,9 @@ namespace mlpack { -template +template template -class Octree::SingleTreeTraverser +class Octree::SingleTreeTraverser { public: /** diff --git a/src/mlpack/core/tree/octree/single_tree_traverser_impl.hpp b/src/mlpack/core/tree/octree/single_tree_traverser_impl.hpp index cc77c4faec..e8c3029a2f 100644 --- a/src/mlpack/core/tree/octree/single_tree_traverser_impl.hpp +++ b/src/mlpack/core/tree/octree/single_tree_traverser_impl.hpp @@ -17,9 +17,9 @@ namespace mlpack { -template +template template -Octree::SingleTreeTraverser:: +Octree::SingleTreeTraverser:: SingleTreeTraverser(RuleType& rule) : rule(rule), numPrunes(0) @@ -27,9 +27,10 @@ Octree::SingleTreeTraverser:: // Nothing to do. } -template +template template -void Octree::SingleTreeTraverser:: +void +Octree::SingleTreeTraverser:: Traverse(const size_t queryIndex, Octree& referenceNode) { // If we are a leaf, run the base cases. diff --git a/src/mlpack/core/tree/octree/traits.hpp b/src/mlpack/core/tree/octree/traits.hpp index 3b99c1db95..cd32ca7914 100644 --- a/src/mlpack/core/tree/octree/traits.hpp +++ b/src/mlpack/core/tree/octree/traits.hpp @@ -22,10 +22,10 @@ namespace mlpack { * tree-independent (but still optimized) tree-based algorithms. See * mlpack/core/tree/tree_traits.hpp for more information. */ -template -class TreeTraits> +class TreeTraits> { public: /** diff --git a/src/mlpack/core/tree/rectangle_tree/dual_tree_traverser.hpp b/src/mlpack/core/tree/rectangle_tree/dual_tree_traverser.hpp index 5b0db9db88..f7f5a81d82 100644 --- a/src/mlpack/core/tree/rectangle_tree/dual_tree_traverser.hpp +++ b/src/mlpack/core/tree/rectangle_tree/dual_tree_traverser.hpp @@ -20,14 +20,14 @@ namespace mlpack { -template class AuxiliaryInformationType> template -class RectangleTree::DualTreeTraverser { public: diff --git a/src/mlpack/core/tree/rectangle_tree/dual_tree_traverser_impl.hpp b/src/mlpack/core/tree/rectangle_tree/dual_tree_traverser_impl.hpp index b054010aa8..e431d7d095 100644 --- a/src/mlpack/core/tree/rectangle_tree/dual_tree_traverser_impl.hpp +++ b/src/mlpack/core/tree/rectangle_tree/dual_tree_traverser_impl.hpp @@ -21,14 +21,14 @@ namespace mlpack { -template class AuxiliaryInformationType> template -RectangleTree:: DualTreeTraverser::DualTreeTraverser(RuleType& rule) : rule(rule), @@ -38,14 +38,14 @@ DualTreeTraverser::DualTreeTraverser(RuleType& rule) : numBaseCases(0) { /* Nothing to do */ } -template class AuxiliaryInformationType> template -void RectangleTree:: DualTreeTraverser::Traverse(RectangleTree& queryNode, RectangleTree& referenceNode) diff --git a/src/mlpack/core/tree/rectangle_tree/r_star_tree_split_impl.hpp b/src/mlpack/core/tree/rectangle_tree/r_star_tree_split_impl.hpp index 033886593f..6ada7dee23 100644 --- a/src/mlpack/core/tree/rectangle_tree/r_star_tree_split_impl.hpp +++ b/src/mlpack/core/tree/rectangle_tree/r_star_tree_split_impl.hpp @@ -51,7 +51,7 @@ size_t RStarTreeSplit::ReinsertPoints(TreeType* tree, tree->Bound().Center(center); for (size_t i = 0; i < sorted.size(); ++i) { - sorted[i].first = tree->Metric().Evaluate(center, + sorted[i].first = tree->Distance().Evaluate(center, tree->Dataset().col(tree->Point(i))); sorted[i].second = tree->Point(i); } diff --git a/src/mlpack/core/tree/rectangle_tree/rectangle_tree.hpp b/src/mlpack/core/tree/rectangle_tree/rectangle_tree.hpp index f0e974e954..8978bcb9ff 100644 --- a/src/mlpack/core/tree/rectangle_tree/rectangle_tree.hpp +++ b/src/mlpack/core/tree/rectangle_tree/rectangle_tree.hpp @@ -31,7 +31,7 @@ namespace mlpack { * * This tree does allow growth, so you can add and delete nodes from it. * - * @tparam MetricType This *must* be EuclideanDistance, but the template + * @tparam DistanceType This *must* be EuclideanDistance, but the template * parameter is required to satisfy the TreeType API. * @tparam StatisticType Extra data contained in the node. See statistic.hpp * for the necessary skeleton interface. @@ -43,7 +43,7 @@ namespace mlpack { * in the node. This information depends on the type of the RectangleTree. */ -template class RectangleTree { - // The metric *must* be the euclidean distance. - static_assert(std::is_same::value, - "RectangleTree: MetricType must be EuclideanDistance."); + // The distance metric *must* be the euclidean distance. + static_assert(std::is_same::value, + "RectangleTree: DistanceType must be EuclideanDistance."); public: //! So other classes can use TreeType::Mat. @@ -311,9 +311,9 @@ class RectangleTree RectangleTree* FindByBeginCount(size_t begin, size_t count); //! Return the bound object for this node. - const HRectBound& Bound() const { return bound; } + const HRectBound& Bound() const { return bound; } //! Modify the bound object for this node. - HRectBound& Bound() { return bound; } + HRectBound& Bound() { return bound; } //! Return the statistic object for this node. const StatisticType& Stat() const { return stat; } @@ -360,8 +360,12 @@ class RectangleTree //! Modify the dataset which the tree is built on. Be careful! MatType& Dataset() { return const_cast(*dataset); } - //! Get the metric which the tree uses. - MetricType Metric() const { return MetricType(); } + //! Get the distance metric which the tree uses. + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + DistanceType Metric() const { return DistanceType(); } + + //! Get the distance metric which the tree uses. + DistanceType Distance() const { return DistanceType(); } //! Get the centroid of the node and store it in the given vector. void Center(arma::vec& center) { bound.Center(center); } @@ -618,7 +622,7 @@ class RectangleTree * shrinking. * @return true if the bound needed to be changed, false if it did not. */ - bool ShrinkBoundForBound(const HRectBound& changedBound); + bool ShrinkBoundForBound(const HRectBound& changedBound); /** * Make an exact copy of this node, pointers and everything. diff --git a/src/mlpack/core/tree/rectangle_tree/rectangle_tree_impl.hpp b/src/mlpack/core/tree/rectangle_tree/rectangle_tree_impl.hpp index daea0e4b74..9d0253195d 100644 --- a/src/mlpack/core/tree/rectangle_tree/rectangle_tree_impl.hpp +++ b/src/mlpack/core/tree/rectangle_tree/rectangle_tree_impl.hpp @@ -20,13 +20,13 @@ namespace mlpack { // Build the statistics, bottom-up. -template class AuxiliaryInformationType> -void RectangleTree:: BuildStatistics(RectangleTree* node) { @@ -38,13 +38,13 @@ BuildStatistics(RectangleTree* node) node->Stat() = StatisticType(*node); } -template class AuxiliaryInformationType> -RectangleTree:: RectangleTree(const MatType& data, const size_t maxLeafSize, @@ -79,13 +79,13 @@ RectangleTree(const MatType& data, BuildStatistics(this); } -template class AuxiliaryInformationType> -RectangleTree:: RectangleTree(MatType&& data, const size_t maxLeafSize, @@ -120,16 +120,16 @@ RectangleTree(MatType&& data, BuildStatistics(this); } -template class AuxiliaryInformationType> -RectangleTree:: RectangleTree( - RectangleTree* parentNode, const size_t numMaxChildren) : maxNumChildren(numMaxChildren > 0 ? numMaxChildren : @@ -158,13 +158,13 @@ RectangleTree( * Create a rectangle tree by copying the other tree. Be careful! This can * take a long time and use a lot of memory. */ -template class AuxiliaryInformationType> -RectangleTree:: RectangleTree( const RectangleTree& other, @@ -205,13 +205,13 @@ RectangleTree( /** * Move constructor. */ -template class AuxiliaryInformationType> -RectangleTree:: RectangleTree(RectangleTree&& other) : maxNumChildren(other.MaxNumChildren()), @@ -264,15 +264,15 @@ RectangleTree(RectangleTree&& other) : /** * Copy assignment operator: copy the given other tree. */ -template class AuxiliaryInformationType> -RectangleTree& -RectangleTree:: operator=(const RectangleTree& other) { @@ -317,15 +317,15 @@ operator=(const RectangleTree& other) /** * Move assignment operator: take ownership of the given tree. */ -template class AuxiliaryInformationType> -RectangleTree& -RectangleTree:: operator=(RectangleTree&& other) { @@ -379,14 +379,14 @@ operator=(RectangleTree&& other) /** * Construct the tree from a cereal archive. */ -template class AuxiliaryInformationType> template -RectangleTree:: RectangleTree( Archive& ar, @@ -402,13 +402,13 @@ RectangleTree( * their destructors in turn. This will invalidate any pointers or references * to any nodes which are children of this one. */ -template class AuxiliaryInformationType> -RectangleTree:: ~RectangleTree() { @@ -423,13 +423,13 @@ RectangleTree class AuxiliaryInformationType> -void RectangleTree:: SoftDelete() { @@ -445,13 +445,13 @@ void RectangleTree class AuxiliaryInformationType> -void RectangleTree:: NullifyData() { @@ -462,13 +462,13 @@ void RectangleTree class AuxiliaryInformationType> -void RectangleTree:: InsertPoint(const size_t point) { @@ -499,13 +499,13 @@ void RectangleTree class AuxiliaryInformationType> -void RectangleTree:: InsertPoint(const size_t point, std::vector& relevels) { @@ -539,13 +539,13 @@ void RectangleTree class AuxiliaryInformationType> -void RectangleTree:: InsertNode(RectangleTree* node, const size_t level, @@ -575,13 +575,13 @@ void RectangleTree class AuxiliaryInformationType> -bool RectangleTree:: DeletePoint(const size_t point) { @@ -627,13 +627,13 @@ bool RectangleTree class AuxiliaryInformationType> -bool RectangleTree:: DeletePoint(const size_t point, std::vector& relevels) { @@ -672,13 +672,13 @@ bool RectangleTree class AuxiliaryInformationType> -bool RectangleTree:: RemoveNode(const RectangleTree* node, std::vector& relevels) { @@ -712,13 +712,13 @@ bool RectangleTree class AuxiliaryInformationType> -size_t RectangleTree::TreeSize() const { int n = 0; @@ -728,13 +728,13 @@ size_t RectangleTree class AuxiliaryInformationType> -size_t RectangleTree::TreeDepth() const { int n = 1; @@ -749,13 +749,13 @@ size_t RectangleTree class AuxiliaryInformationType> -inline bool RectangleTree::IsLeaf() const { return (numChildren == 0); @@ -765,14 +765,14 @@ inline bool RectangleTree class AuxiliaryInformationType> template -size_t RectangleTree::GetNearestChild( const VecType& point, typename std::enable_if_t::value>*) @@ -798,14 +798,14 @@ size_t RectangleTree class AuxiliaryInformationType> template -size_t RectangleTree::GetFurthestChild( const VecType& point, typename std::enable_if_t::value>*) @@ -831,13 +831,13 @@ size_t RectangleTree class AuxiliaryInformationType> -size_t RectangleTree::GetNearestChild(const RectangleTree& queryNode) { if (IsLeaf()) @@ -861,13 +861,13 @@ size_t RectangleTree class AuxiliaryInformationType> -size_t RectangleTree::GetFurthestChild(const RectangleTree& queryNode) { if (IsLeaf()) @@ -891,16 +891,16 @@ size_t RectangleTree class AuxiliaryInformationType> inline -typename RectangleTree::ElemType -RectangleTree::FurthestPointDistance() const { if (!IsLeaf()) @@ -917,16 +917,16 @@ RectangleTree class AuxiliaryInformationType> inline -typename RectangleTree::ElemType -RectangleTree::FurthestDescendantDistance() const { // Return the distance from the centroid to a corner of the bound. @@ -937,13 +937,13 @@ RectangleTree class AuxiliaryInformationType> -inline size_t RectangleTree::NumPoints() const { if (numChildren != 0) // This is not a leaf node. @@ -955,13 +955,13 @@ inline size_t RectangleTree class AuxiliaryInformationType> -inline size_t RectangleTree::NumDescendants() const { return numDescendants; @@ -970,13 +970,13 @@ inline size_t RectangleTree class AuxiliaryInformationType> -inline size_t RectangleTree::Descendant(const size_t index) const { // I think this may be inefficient... @@ -1004,13 +1004,13 @@ inline size_t RectangleTree class AuxiliaryInformationType> -void RectangleTree:: SplitNode(std::vector& relevels) { @@ -1036,13 +1036,13 @@ void RectangleTree class AuxiliaryInformationType> -RectangleTree:: RectangleTree() : maxNumChildren(0), // Try to give sensible defaults, but it shouldn't matter @@ -1065,13 +1065,13 @@ RectangleTree() : * Condense the tree. This shrinks the bounds and moves up the tree if * applicable. If a node goes below minimum fill, this code will deal with it. */ -template class AuxiliaryInformationType> -void RectangleTree:: CondenseTree(const arma::vec& point, std::vector& relevels, @@ -1249,13 +1249,13 @@ void RectangleTree class AuxiliaryInformationType> -bool RectangleTree:: ShrinkBoundForPoint(const arma::vec& point) { @@ -1347,15 +1347,15 @@ bool RectangleTree class AuxiliaryInformationType> -bool RectangleTree:: - ShrinkBoundForBound(const HRectBound& /* b */) + ShrinkBoundForBound(const HRectBound& /* b */) { // Using the sum is safe since none of the dimensions can increase. ElemType sum = 0; @@ -1383,14 +1383,14 @@ bool RectangleTree class AuxiliaryInformationType> template -void RectangleTree::serialize( Archive& ar, const uint32_t /* version */) diff --git a/src/mlpack/core/tree/rectangle_tree/single_tree_traverser.hpp b/src/mlpack/core/tree/rectangle_tree/single_tree_traverser.hpp index 60f82ef262..5f892078a7 100644 --- a/src/mlpack/core/tree/rectangle_tree/single_tree_traverser.hpp +++ b/src/mlpack/core/tree/rectangle_tree/single_tree_traverser.hpp @@ -20,14 +20,14 @@ namespace mlpack { -template class AuxiliaryInformationType> template -class RectangleTree::SingleTreeTraverser { public: diff --git a/src/mlpack/core/tree/rectangle_tree/single_tree_traverser_impl.hpp b/src/mlpack/core/tree/rectangle_tree/single_tree_traverser_impl.hpp index b1779383fd..98527e8e39 100644 --- a/src/mlpack/core/tree/rectangle_tree/single_tree_traverser_impl.hpp +++ b/src/mlpack/core/tree/rectangle_tree/single_tree_traverser_impl.hpp @@ -21,28 +21,28 @@ namespace mlpack { -template class AuxiliaryInformationType> template -RectangleTree:: SingleTreeTraverser::SingleTreeTraverser(RuleType& rule) : rule(rule), numPrunes(0) { /* Nothing to do */ } -template class AuxiliaryInformationType> template -void RectangleTree:: SingleTreeTraverser::Traverse( const size_t queryIndex, diff --git a/src/mlpack/core/tree/rectangle_tree/traits.hpp b/src/mlpack/core/tree/rectangle_tree/traits.hpp index cce1864825..caa1d4ee2f 100644 --- a/src/mlpack/core/tree/rectangle_tree/traits.hpp +++ b/src/mlpack/core/tree/rectangle_tree/traits.hpp @@ -22,13 +22,13 @@ namespace mlpack { * help write tree-independent (but still optimized) tree-based algorithms. See * mlpack/core/tree/tree_traits.hpp for more information. */ -template class AuxiliaryInformationType> -class TreeTraits> { public: @@ -75,14 +75,14 @@ class TreeTraits class SweepType, typename DescentType, template class AuxiliaryInformationType> -class TreeTraits -using RTree = RectangleTree +using RTree = RectangleTree -using RStarTree = RectangleTree +using RStarTree = RectangleTree -using XTree = RectangleTree +using XTree = RectangleTree using DiscreteHilbertRTreeAuxiliaryInformation = HilbertRTreeAuxiliaryInformation; -template -using HilbertRTree = RectangleTree +using HilbertRTree = RectangleTree, @@ -157,8 +157,8 @@ using HilbertRTree = RectangleTree -using RPlusTree = RectangleTree +using RPlusTree = RectangleTree -using RPlusPlusTree = RectangleTree +using RPlusPlusTree = RectangleTree -using AxisOrthogonalHyperplane = HyperplaneBase, +template +using AxisOrthogonalHyperplane = HyperplaneBase, AxisParallelProjVector>; /** * Hyperplane represents a general hyperplane (not necessarily axis-orthogonal). */ -template -using Hyperplane = HyperplaneBase, ProjVector>; +template +using Hyperplane = HyperplaneBase, ProjVector>; } // namespace mlpack diff --git a/src/mlpack/core/tree/space_split/mean_space_split.hpp b/src/mlpack/core/tree/space_split/mean_space_split.hpp index 04c11a2b23..26b0706376 100644 --- a/src/mlpack/core/tree/space_split/mean_space_split.hpp +++ b/src/mlpack/core/tree/space_split/mean_space_split.hpp @@ -18,7 +18,7 @@ namespace mlpack { -template +template class MeanSpaceSplit { public: diff --git a/src/mlpack/core/tree/space_split/mean_space_split_impl.hpp b/src/mlpack/core/tree/space_split/mean_space_split_impl.hpp index 941a3f8398..99cd91bd88 100644 --- a/src/mlpack/core/tree/space_split/mean_space_split_impl.hpp +++ b/src/mlpack/core/tree/space_split/mean_space_split_impl.hpp @@ -18,9 +18,9 @@ namespace mlpack { -template +template template -bool MeanSpaceSplit::SplitSpace( +bool MeanSpaceSplit::SplitSpace( const typename HyperplaneType::BoundType& bound, const MatType& data, const arma::Col& points, @@ -29,7 +29,7 @@ bool MeanSpaceSplit::SplitSpace( typename HyperplaneType::ProjVectorType projVector; double midValue; - if (!SpaceSplit::GetProjVector(bound, data, points, + if (!SpaceSplit::GetProjVector(bound, data, points, projVector, midValue)) return false; diff --git a/src/mlpack/core/tree/space_split/midpoint_space_split.hpp b/src/mlpack/core/tree/space_split/midpoint_space_split.hpp index e09a6343df..b4c897811b 100644 --- a/src/mlpack/core/tree/space_split/midpoint_space_split.hpp +++ b/src/mlpack/core/tree/space_split/midpoint_space_split.hpp @@ -18,7 +18,7 @@ namespace mlpack { -template +template class MidpointSpaceSplit { public: diff --git a/src/mlpack/core/tree/space_split/midpoint_space_split_impl.hpp b/src/mlpack/core/tree/space_split/midpoint_space_split_impl.hpp index 84221b4f40..9fe8aab3d9 100644 --- a/src/mlpack/core/tree/space_split/midpoint_space_split_impl.hpp +++ b/src/mlpack/core/tree/space_split/midpoint_space_split_impl.hpp @@ -18,9 +18,9 @@ namespace mlpack { -template +template template -bool MidpointSpaceSplit::SplitSpace( +bool MidpointSpaceSplit::SplitSpace( const typename HyperplaneType::BoundType& bound, const MatType& data, const arma::Col& points, @@ -29,7 +29,7 @@ bool MidpointSpaceSplit::SplitSpace( typename HyperplaneType::ProjVectorType projVector; double midValue; - if (!SpaceSplit::GetProjVector(bound, data, points, + if (!SpaceSplit::GetProjVector(bound, data, points, projVector, midValue)) return false; diff --git a/src/mlpack/core/tree/space_split/projection_vector.hpp b/src/mlpack/core/tree/space_split/projection_vector.hpp index 9a9f7f70db..ee2e3fea03 100644 --- a/src/mlpack/core/tree/space_split/projection_vector.hpp +++ b/src/mlpack/core/tree/space_split/projection_vector.hpp @@ -54,9 +54,9 @@ class AxisParallelProjVector * @param bound Bound to be projected. * @return Range of projected values. */ - template + template RangeType Project( - const HRectBound& bound) const + const HRectBound& bound) const { return bound[dim]; } @@ -67,9 +67,9 @@ class AxisParallelProjVector * @param bound Bound to be projected. * @return Range of projected values. */ - template + template RangeType Project( - const BallBound& bound) const + const BallBound& bound) const { return bound[dim]; } @@ -128,9 +128,9 @@ class ProjVector * @param bound Bound to be projected. * @return Range of projected values. */ - template + template RangeType Project( - const BallBound& bound) const + const BallBound& bound) const { typedef typename VecType::elem_type ElemType; const double center = Project(bound.Center()); diff --git a/src/mlpack/core/tree/space_split/space_split.hpp b/src/mlpack/core/tree/space_split/space_split.hpp index d7d4e3459a..c18c482007 100644 --- a/src/mlpack/core/tree/space_split/space_split.hpp +++ b/src/mlpack/core/tree/space_split/space_split.hpp @@ -18,7 +18,7 @@ namespace mlpack { -template +template class SpaceSplit { public: @@ -35,7 +35,7 @@ class SpaceSplit * @return Flag to determine if it is possible. */ static bool GetProjVector( - const HRectBound& bound, + const HRectBound& bound, const MatType& data, const arma::Col& points, AxisParallelProjVector& projVector, diff --git a/src/mlpack/core/tree/space_split/space_split_impl.hpp b/src/mlpack/core/tree/space_split/space_split_impl.hpp index be56c13ae9..80793f6498 100644 --- a/src/mlpack/core/tree/space_split/space_split_impl.hpp +++ b/src/mlpack/core/tree/space_split/space_split_impl.hpp @@ -17,9 +17,9 @@ namespace mlpack { -template -bool SpaceSplit::GetProjVector( - const HRectBound& bound, +template +bool SpaceSplit::GetProjVector( + const HRectBound& bound, const MatType& data, const arma::Col& /* points */, AxisParallelProjVector& projVector, @@ -50,25 +50,25 @@ bool SpaceSplit::GetProjVector( return true; } -template +template template -bool SpaceSplit::GetProjVector( +bool SpaceSplit::GetProjVector( const BoundType& /* bound */, const MatType& data, const arma::Col& points, ProjVector& projVector, double& midValue) { - MetricType metric; + DistanceType distance; // Efficiently estimate the farthest pair of points in the given set. size_t fst = points[rand() % points.n_elem]; size_t snd = points[0]; - double max = metric.Evaluate(data.col(fst), data.col(snd)); + double max = distance.Evaluate(data.col(fst), data.col(snd)); for (size_t i = 1; i < points.n_elem; ++i) { - double dist = metric.Evaluate(data.col(fst), data.col(points[i])); + double dist = distance.Evaluate(data.col(fst), data.col(points[i])); if (dist > max) { max = dist; @@ -80,7 +80,7 @@ bool SpaceSplit::GetProjVector( for (size_t i = 0; i < points.n_elem; ++i) { - double dist = metric.Evaluate(data.col(fst), data.col(points[i])); + double dist = distance.Evaluate(data.col(fst), data.col(points[i])); if (dist > max) { max = dist; diff --git a/src/mlpack/core/tree/spill_tree/is_spill_tree.hpp b/src/mlpack/core/tree/spill_tree/is_spill_tree.hpp index d97b0ccd67..202769968e 100644 --- a/src/mlpack/core/tree/spill_tree/is_spill_tree.hpp +++ b/src/mlpack/core/tree/spill_tree/is_spill_tree.hpp @@ -23,15 +23,15 @@ struct IsSpillTree }; // Specialization for SpillTree. -template + template class HyperplaneType, - template + template class SplitType> -struct IsSpillTree> +struct IsSpillTree> { static const bool value = true; }; diff --git a/src/mlpack/core/tree/spill_tree/spill_dual_tree_traverser.hpp b/src/mlpack/core/tree/spill_tree/spill_dual_tree_traverser.hpp index e1664af36b..3a4257b8dd 100644 --- a/src/mlpack/core/tree/spill_tree/spill_dual_tree_traverser.hpp +++ b/src/mlpack/core/tree/spill_tree/spill_dual_tree_traverser.hpp @@ -24,15 +24,15 @@ namespace mlpack { -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> template -class SpillTree:: - SpillDualTreeTraverser +class SpillTree::SpillDualTreeTraverser { public: /** diff --git a/src/mlpack/core/tree/spill_tree/spill_dual_tree_traverser_impl.hpp b/src/mlpack/core/tree/spill_tree/spill_dual_tree_traverser_impl.hpp index ecfaa91af2..03ae5ea267 100644 --- a/src/mlpack/core/tree/spill_tree/spill_dual_tree_traverser_impl.hpp +++ b/src/mlpack/core/tree/spill_tree/spill_dual_tree_traverser_impl.hpp @@ -20,14 +20,14 @@ namespace mlpack { -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> template -SpillTree:: +SpillTree:: SpillDualTreeTraverser::SpillDualTreeTraverser( RuleType& rule) : rule(rule), @@ -37,18 +37,19 @@ SpillDualTreeTraverser::SpillDualTreeTraverser( numBaseCases(0) { /* Nothing to do. */ } -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> template -void SpillTree:: +void +SpillTree:: SpillDualTreeTraverser::Traverse( - SpillTree& + SpillTree& queryNode, - SpillTree& + SpillTree& referenceNode, const bool bruteForce) { diff --git a/src/mlpack/core/tree/spill_tree/spill_single_tree_traverser.hpp b/src/mlpack/core/tree/spill_tree/spill_single_tree_traverser.hpp index 7308a78278..78969f3d4c 100644 --- a/src/mlpack/core/tree/spill_tree/spill_single_tree_traverser.hpp +++ b/src/mlpack/core/tree/spill_tree/spill_single_tree_traverser.hpp @@ -23,15 +23,15 @@ namespace mlpack { -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> template -class SpillTree:: - SpillSingleTreeTraverser +class SpillTree::SpillSingleTreeTraverser { public: /** diff --git a/src/mlpack/core/tree/spill_tree/spill_single_tree_traverser_impl.hpp b/src/mlpack/core/tree/spill_tree/spill_single_tree_traverser_impl.hpp index e8e3f684e8..f14b52ce3d 100644 --- a/src/mlpack/core/tree/spill_tree/spill_single_tree_traverser_impl.hpp +++ b/src/mlpack/core/tree/spill_tree/spill_single_tree_traverser_impl.hpp @@ -20,31 +20,32 @@ namespace mlpack { -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> template -SpillTree:: +SpillTree:: SpillSingleTreeTraverser::SpillSingleTreeTraverser( RuleType& rule) : rule(rule), numPrunes(0) { /* Nothing to do. */ } -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> template -void SpillTree:: +void +SpillTree:: SpillSingleTreeTraverser::Traverse( const size_t queryIndex, - SpillTree& + SpillTree& referenceNode, const bool bruteForce) { diff --git a/src/mlpack/core/tree/spill_tree/spill_tree.hpp b/src/mlpack/core/tree/spill_tree/spill_tree.hpp index b55b60ed55..de7a4eace8 100644 --- a/src/mlpack/core/tree/spill_tree/spill_tree.hpp +++ b/src/mlpack/core/tree/spill_tree/spill_tree.hpp @@ -53,7 +53,7 @@ namespace mlpack { * } * @endcode * - * @tparam MetricType The metric used for tree-building. + * @tparam DistanceType The distance metric used for tree-building. * @tparam StatisticType Extra data contained in the node. See statistic.hpp * for the necessary skeleton interface. * @tparam MatType The dataset class. @@ -62,12 +62,12 @@ namespace mlpack { * particular node into two parts. Its definition decides the way this split * is done. */ -template + template class HyperplaneType = AxisOrthogonalHyperplane, - template + template class SplitType = MidpointSpaceSplit> class SpillTree { @@ -77,7 +77,7 @@ class SpillTree //! The type of element held in MatType. typedef typename MatType::elem_type ElemType; //! The bound type. - typedef typename HyperplaneType::BoundType BoundType; + typedef typename HyperplaneType::BoundType BoundType; private: //! The left child node. @@ -95,7 +95,7 @@ class SpillTree //! Flag to distinguish overlapping nodes from non-overlapping nodes. bool overlappingNode; //! Splitting hyperplane represented by this node. - HyperplaneType hyperplane; + HyperplaneType hyperplane; //! The bound object for this node. BoundType bound; //! Any extra data contained in the node. @@ -274,10 +274,14 @@ class SpillTree bool Overlap() const { return overlappingNode; } //! Get the Hyperplane instance. - const HyperplaneType& Hyperplane() const { return hyperplane; } + const HyperplaneType& Hyperplane() const { return hyperplane; } - //! Get the metric that the tree uses. - MetricType Metric() const { return MetricType(); } + //! Get the distance metric that the tree uses. + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + DistanceType Metric() const { return DistanceType(); } + + //! Get the distance metric that the tree uses. + DistanceType Distance() const { return DistanceType(); } //! Return the number of children in this node. size_t NumChildren() const; diff --git a/src/mlpack/core/tree/spill_tree/spill_tree_impl.hpp b/src/mlpack/core/tree/spill_tree/spill_tree_impl.hpp index c1a40958c7..f6a6cfbab9 100644 --- a/src/mlpack/core/tree/spill_tree/spill_tree_impl.hpp +++ b/src/mlpack/core/tree/spill_tree/spill_tree_impl.hpp @@ -18,13 +18,13 @@ namespace mlpack { -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -SpillTree:: +SpillTree:: SpillTree( const MatType& data, const double tau, @@ -55,13 +55,13 @@ SpillTree( stat = StatisticType(*this); } -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -SpillTree:: +SpillTree:: SpillTree( MatType&& data, const double tau, @@ -92,13 +92,13 @@ SpillTree( stat = StatisticType(*this); } -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -SpillTree:: +SpillTree:: SpillTree( SpillTree* parent, arma::Col& points, @@ -127,13 +127,13 @@ SpillTree( * Create a hybrid spill tree by copying the other tree. Be careful! This can * take a long time and use a lot of memory. */ -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -SpillTree:: +SpillTree:: SpillTree(const SpillTree& other) : left(NULL), right(NULL), @@ -194,14 +194,14 @@ SpillTree(const SpillTree& other) : /** * Copy assignment operator: copy the given other tree. */ -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -SpillTree& -SpillTree:: +SpillTree& +SpillTree:: operator=(const SpillTree& other) { if (this == &other) @@ -276,13 +276,13 @@ operator=(const SpillTree& other) /** * Move constructor. */ -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -SpillTree:: +SpillTree:: SpillTree(SpillTree&& other) : left(other.left), right(other.right), @@ -321,14 +321,14 @@ SpillTree(SpillTree&& other) : /** * Move assignment operator: take ownership of the given tree. */ -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -SpillTree& -SpillTree:: +SpillTree& +SpillTree:: operator=(SpillTree&& other) { if (this == &other) @@ -381,14 +381,14 @@ operator=(SpillTree&& other) /** * Initialize the tree from an archive. */ -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> template -SpillTree:: +SpillTree:: SpillTree( Archive& ar, const typename std::enable_if_t()>*) : @@ -404,13 +404,13 @@ SpillTree( * destructors in turn. This will invalidate any pointers or references to any * nodes which are children of this one. */ -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -SpillTree:: +SpillTree:: ~SpillTree() { delete left; @@ -422,13 +422,13 @@ SpillTree:: delete dataset; } -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -inline bool SpillTree::IsLeaf() const { return !left; @@ -437,13 +437,13 @@ inline bool SpillTree class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -inline size_t SpillTree::NumChildren() const { if (left && right) @@ -460,14 +460,14 @@ inline size_t SpillTree class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> template -size_t SpillTree::GetNearestChild( const VecType& point, typename std::enable_if_t::value>*) @@ -486,14 +486,14 @@ size_t SpillTree class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> template -size_t SpillTree::GetFurthestChild( const VecType& point, typename std::enable_if_t::value>*) @@ -512,13 +512,13 @@ size_t SpillTree class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -size_t SpillTree::GetNearestChild(const SpillTree& queryNode) { if (IsLeaf() || !left || !right) @@ -538,13 +538,13 @@ size_t SpillTree class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -size_t SpillTree::GetFurthestChild(const SpillTree& queryNode) { if (IsLeaf() || !left || !right) @@ -562,15 +562,15 @@ size_t SpillTree class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -inline typename SpillTree::ElemType -SpillTree:: +SpillTree:: FurthestPointDistance() const { if (!IsLeaf()) @@ -587,30 +587,30 @@ SpillTree:: * furthest descendant distance may be less than what this method returns (but * it will never be greater than this). */ -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -inline typename SpillTree::ElemType -SpillTree:: +SpillTree:: FurthestDescendantDistance() const { return furthestDescendantDistance; } //! Return the minimum distance from the center to any bound edge. -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -inline typename SpillTree::ElemType -SpillTree:: +SpillTree:: MinimumBoundDistance() const { return bound.MinWidth() / 2.0; @@ -619,14 +619,14 @@ SpillTree:: /** * Return the specified child. */ -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -inline SpillTree& -SpillTree:: +inline SpillTree& +SpillTree:: Child(const size_t child) const { if (child == 0) @@ -638,13 +638,13 @@ SpillTree:: /** * Return the number of points contained in this node. */ -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -inline size_t SpillTree::NumPoints() const { if (IsLeaf()) @@ -655,13 +655,13 @@ inline size_t SpillTree class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -inline size_t SpillTree::NumDescendants() const { return count; @@ -670,13 +670,13 @@ inline size_t SpillTree class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -inline size_t SpillTree::Descendant(const size_t index) const { if (IsLeaf() || overlappingNode) @@ -694,13 +694,13 @@ inline size_t SpillTree class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -inline size_t SpillTree::Point(const size_t index) const { if (IsLeaf()) @@ -709,13 +709,13 @@ inline size_t SpillTree class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -void SpillTree:: +void SpillTree:: SplitNode(arma::Col& points, const size_t maxLeafSize, const double tau, @@ -736,7 +736,7 @@ void SpillTree:: return; // We can't split this. } - const bool split = SplitType::SplitSpace(bound, + const bool split = SplitType::SplitSpace(bound, *dataset, points, hyperplane); // The node may not be always split. For instance, if all the points are the // same, we can't split them. @@ -775,21 +775,21 @@ void SpillTree:: left->Center(leftCenter); right->Center(rightCenter); - const ElemType leftParentDistance = MetricType::Evaluate(center, leftCenter); - const ElemType rightParentDistance = MetricType::Evaluate(center, + const ElemType leftParentDistance = DistanceType::Evaluate(center, leftCenter); + const ElemType rightParentDistance = DistanceType::Evaluate(center, rightCenter); left->ParentDistance() = leftParentDistance; right->ParentDistance() = rightParentDistance; } -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -bool SpillTree:: +bool SpillTree:: SplitPoints(const double tau, const double rho, const arma::Col& points, @@ -869,13 +869,13 @@ bool SpillTree:: } // Default constructor (private), for cereal. -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -SpillTree:: +SpillTree:: SpillTree() : left(NULL), right(NULL), @@ -895,14 +895,14 @@ SpillTree:: /** * Serialize the tree. */ -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> template -void SpillTree:: +void SpillTree:: serialize(Archive& ar, const uint32_t /* version */) { // If we're loading, and we have children, they need to be deleted. diff --git a/src/mlpack/core/tree/spill_tree/traits.hpp b/src/mlpack/core/tree/spill_tree/traits.hpp index c8b476762d..a72427da3b 100644 --- a/src/mlpack/core/tree/spill_tree/traits.hpp +++ b/src/mlpack/core/tree/spill_tree/traits.hpp @@ -23,13 +23,13 @@ namespace mlpack { * tree-independent (but still optimized) tree-based algorithms. See * mlpack/core/tree/tree_traits.hpp for more information. */ -template class HyperplaneType, - template + template class HyperplaneType, + template class SplitType> -class TreeTraits> { public: diff --git a/src/mlpack/core/tree/spill_tree/typedef.hpp b/src/mlpack/core/tree/spill_tree/typedef.hpp index 331948647c..c0410c0131 100644 --- a/src/mlpack/core/tree/spill_tree/typedef.hpp +++ b/src/mlpack/core/tree/spill_tree/typedef.hpp @@ -53,8 +53,8 @@ namespace mlpack { * * @see @ref trees, SpillTree, MeanSPTree */ -template -using SPTree = SpillTree +using SPTree = SpillTree -using MeanSPTree = SpillTree +using MeanSPTree = SpillTree -using NonOrtSPTree = SpillTree +using NonOrtSPTree = SpillTree -using NonOrtMeanSPTree = SpillTree +using NonOrtMeanSPTree = SpillTree -#include +#include namespace mlpack { diff --git a/src/mlpack/methods/ann/augmented/tasks/copy.hpp b/src/mlpack/methods/ann/augmented/tasks/copy.hpp index 1aaca681de..29cd134e64 100644 --- a/src/mlpack/methods/ann/augmented/tasks/copy.hpp +++ b/src/mlpack/methods/ann/augmented/tasks/copy.hpp @@ -10,12 +10,11 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ - #ifndef MLPACK_METHODS_AUGMENTED_TASKS_COPY_HPP #define MLPACK_METHODS_AUGMENTED_TASKS_COPY_HPP #include -#include +#include namespace mlpack { diff --git a/src/mlpack/methods/cf/neighbor_search_policies/lmetric_search.hpp b/src/mlpack/methods/cf/neighbor_search_policies/lmetric_search.hpp index 84d1003b75..3355915cef 100644 --- a/src/mlpack/methods/cf/neighbor_search_policies/lmetric_search.hpp +++ b/src/mlpack/methods/cf/neighbor_search_policies/lmetric_search.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include namespace mlpack { diff --git a/src/mlpack/methods/emst/dtb.hpp b/src/mlpack/methods/emst/dtb.hpp index 2acec71958..1cefa02875 100644 --- a/src/mlpack/methods/emst/dtb.hpp +++ b/src/mlpack/methods/emst/dtb.hpp @@ -64,15 +64,15 @@ namespace mlpack { * More advanced usage of the class can use different types of trees, pass in an * already-built tree, or compute the MST using the O(n^2) naive algorithm. * - * @tparam MetricType The metric to use. + * @tparam DistanceType The distance metric to use. * @tparam MatType The type of data matrix to use. * @tparam TreeType Type of tree to use. This should follow the TreeType policy * API. */ template< - typename MetricType = EuclideanDistance, + typename DistanceType = EuclideanDistance, typename MatType = arma::mat, - template class TreeType = KDTree > @@ -80,7 +80,7 @@ class DualTreeBoruvka { public: //! Convenience typedef. - typedef TreeType Tree; + typedef TreeType Tree; private: //! Permutations of points during tree building. @@ -111,8 +111,8 @@ class DualTreeBoruvka //! Total distance of the tree. double totalDist; - //! The instantiated metric. - MetricType metric; + //! The instantiated distance metric. + DistanceType distance; //! For sorting the edge list after the computation. struct SortEdgesHelper @@ -130,11 +130,11 @@ class DualTreeBoruvka * * @param dataset Dataset to build a tree for. * @param naive Whether the computation should be done in O(n^2) naive mode. - * @param metric An optional instantiated metric to use. + * @param distance An optional instantiated distance metric to use. */ DualTreeBoruvka(const MatType& dataset, const bool naive = false, - const MetricType metric = MetricType()); + const DistanceType distance = DistanceType()); /** * Create the DualTreeBoruvka object with an already initialized tree. This @@ -150,10 +150,10 @@ class DualTreeBoruvka * is not done when this constructor is used. * * @param tree Pre-built tree. - * @param metric An optional instantiated metric to use. + * @param distance An optional instantiated distance metric to use. */ DualTreeBoruvka(Tree* tree, - const MetricType metric = MetricType()); + const DistanceType distance = DistanceType()); /** * Delete the tree, if it was created inside the object. diff --git a/src/mlpack/methods/emst/dtb_impl.hpp b/src/mlpack/methods/emst/dtb_impl.hpp index fe9e22261d..7c40c9fb30 100644 --- a/src/mlpack/methods/emst/dtb_impl.hpp +++ b/src/mlpack/methods/emst/dtb_impl.hpp @@ -21,22 +21,22 @@ namespace mlpack { * and initializes all of the member variables. */ template< - typename MetricType, + typename DistanceType, typename MatType, - template class TreeType> -DualTreeBoruvka::DualTreeBoruvka( +DualTreeBoruvka::DualTreeBoruvka( const MatType& dataset, const bool naive, - const MetricType metric) : + const DistanceType distance) : tree(naive ? NULL : BuildTree(dataset, oldFromNew)), data(naive ? dataset : tree->Dataset()), ownTree(!naive), naive(naive), connections(dataset.n_cols), totalDist(0.0), - metric(metric) + distance(distance) { edges.reserve(data.n_cols - 1); // Set size. @@ -47,21 +47,21 @@ DualTreeBoruvka::DualTreeBoruvka( } template< - typename MetricType, + typename DistanceType, typename MatType, - template class TreeType> -DualTreeBoruvka::DualTreeBoruvka( +DualTreeBoruvka::DualTreeBoruvka( Tree* tree, - const MetricType metric) : + const DistanceType distance) : tree(tree), data(tree->Dataset()), ownTree(false), naive(false), connections(data.n_cols), totalDist(0.0), - metric(metric) + distance(distance) { edges.reserve(data.n_cols - 1); // Fill with EdgePairs. @@ -72,12 +72,12 @@ DualTreeBoruvka::DualTreeBoruvka( } template< - typename MetricType, + typename DistanceType, typename MatType, - template class TreeType> -DualTreeBoruvka::~DualTreeBoruvka() +DualTreeBoruvka::~DualTreeBoruvka() { if (ownTree) delete tree; @@ -88,19 +88,19 @@ DualTreeBoruvka::~DualTreeBoruvka() * complete. */ template< - typename MetricType, + typename DistanceType, typename MatType, - template class TreeType> -void DualTreeBoruvka::ComputeMST( +void DualTreeBoruvka::ComputeMST( arma::mat& results) { totalDist = 0; // Reset distance. - typedef DTBRules RuleType; + typedef DTBRules RuleType; RuleType rules(data, connections, neighborsDistances, neighborsInComponent, - neighborsOutComponent, metric); + neighborsOutComponent, distance); while (edges.size() < (data.n_cols - 1)) { if (naive) @@ -138,12 +138,12 @@ void DualTreeBoruvka::ComputeMST( * Adds a single edge to the edge list */ template< - typename MetricType, + typename DistanceType, typename MatType, - template class TreeType> -void DualTreeBoruvka::AddEdge( +void DualTreeBoruvka::AddEdge( const size_t e1, const size_t e2, const double distance) @@ -161,12 +161,12 @@ void DualTreeBoruvka::AddEdge( * Adds all the edges found in one iteration to the list of neighbors. */ template< - typename MetricType, + typename DistanceType, typename MatType, - template class TreeType> -void DualTreeBoruvka::AddAllEdges() +void DualTreeBoruvka::AddAllEdges() { for (size_t i = 0; i < data.n_cols; ++i) { @@ -188,12 +188,12 @@ void DualTreeBoruvka::AddAllEdges() * Unpermute the edge list (if necessary) and output it to results. */ template< - typename MetricType, + typename DistanceType, typename MatType, - template class TreeType> -void DualTreeBoruvka::EmitResults( +void DualTreeBoruvka::EmitResults( arma::mat& results) { // Sort the edges. @@ -244,12 +244,12 @@ void DualTreeBoruvka::EmitResults( * distance and checks for fully connected nodes. */ template< - typename MetricType, + typename DistanceType, typename MatType, - template class TreeType> -void DualTreeBoruvka::CleanupHelper(Tree* tree) +void DualTreeBoruvka::CleanupHelper(Tree* tree) { // Reset the statistic information. tree->Stat().MaxNeighborDistance() = DBL_MAX; @@ -284,12 +284,12 @@ void DualTreeBoruvka::CleanupHelper(Tree* tree) * The values stored in the tree must be reset on each iteration. */ template< - typename MetricType, + typename DistanceType, typename MatType, - template class TreeType> -void DualTreeBoruvka::Cleanup() +void DualTreeBoruvka::Cleanup() { for (size_t i = 0; i < data.n_cols; ++i) neighborsDistances[i] = DBL_MAX; diff --git a/src/mlpack/methods/emst/dtb_rules.hpp b/src/mlpack/methods/emst/dtb_rules.hpp index 4352a3f5c6..c0564059be 100644 --- a/src/mlpack/methods/emst/dtb_rules.hpp +++ b/src/mlpack/methods/emst/dtb_rules.hpp @@ -18,7 +18,7 @@ namespace mlpack { -template +template class DTBRules { public: @@ -27,7 +27,7 @@ class DTBRules arma::vec& neighborsDistances, arma::Col& neighborsInComponent, arma::Col& neighborsOutComponent, - MetricType& metric); + DistanceType& distance); double BaseCase(const size_t queryIndex, const size_t referenceIndex); @@ -114,8 +114,8 @@ class DTBRules //! of the candidate edge. arma::Col& neighborsOutComponent; - //! The instantiated metric. - MetricType& metric; + //! The instantiated distance metric. + DistanceType& distance; /** * Update the bound for the given query node. diff --git a/src/mlpack/methods/emst/dtb_rules_impl.hpp b/src/mlpack/methods/emst/dtb_rules_impl.hpp index 0535d34329..624e60804e 100644 --- a/src/mlpack/methods/emst/dtb_rules_impl.hpp +++ b/src/mlpack/methods/emst/dtb_rules_impl.hpp @@ -14,30 +14,30 @@ namespace mlpack { -template -DTBRules:: +template +DTBRules:: DTBRules(const arma::mat& dataSet, UnionFind& connections, arma::vec& neighborsDistances, arma::Col& neighborsInComponent, arma::Col& neighborsOutComponent, - MetricType& metric) + DistanceType& distance) : dataSet(dataSet), connections(connections), neighborsDistances(neighborsDistances), neighborsInComponent(neighborsInComponent), neighborsOutComponent(neighborsOutComponent), - metric(metric), + distance(distance), baseCases(0), scores(0) { // Nothing else to do. } -template +template inline mlpack_force_inline -double DTBRules::BaseCase(const size_t queryIndex, +double DTBRules::BaseCase(const size_t queryIndex, const size_t referenceIndex) { // Check if the points are in the same component at this iteration. @@ -53,14 +53,14 @@ double DTBRules::BaseCase(const size_t queryIndex, if (queryComponentIndex != referenceComponentIndex) { ++baseCases; - double distance = metric.Evaluate(dataSet.col(queryIndex), - dataSet.col(referenceIndex)); + double dist = distance.Evaluate(dataSet.col(queryIndex), + dataSet.col(referenceIndex)); - if (distance < neighborsDistances[queryComponentIndex]) + if (dist < neighborsDistances[queryComponentIndex]) { Log::Assert(queryIndex != referenceIndex); - neighborsDistances[queryComponentIndex] = distance; + neighborsDistances[queryComponentIndex] = dist; neighborsInComponent[queryComponentIndex] = queryIndex; neighborsOutComponent[queryComponentIndex] = referenceIndex; } @@ -74,8 +74,8 @@ double DTBRules::BaseCase(const size_t queryIndex, return newUpperBound; } -template -double DTBRules::Score(const size_t queryIndex, +template +double DTBRules::Score(const size_t queryIndex, TreeType& referenceNode) { size_t queryComponentIndex = connections.Find(queryIndex); @@ -96,8 +96,8 @@ double DTBRules::Score(const size_t queryIndex, ? DBL_MAX : distance; } -template -double DTBRules::Rescore(const size_t queryIndex, +template +double DTBRules::Rescore(const size_t queryIndex, TreeType& /* referenceNode */, const double oldScore) { @@ -107,8 +107,8 @@ double DTBRules::Rescore(const size_t queryIndex, ? DBL_MAX : oldScore; } -template -double DTBRules::Score(TreeType& queryNode, +template +double DTBRules::Score(TreeType& queryNode, TreeType& referenceNode) { // If all the queries belong to the same component as all the references @@ -127,8 +127,8 @@ double DTBRules::Score(TreeType& queryNode, return (bound < distance) ? DBL_MAX : distance; } -template -double DTBRules::Rescore(TreeType& queryNode, +template +double DTBRules::Rescore(TreeType& queryNode, TreeType& /* referenceNode */, const double oldScore) const { @@ -138,8 +138,8 @@ double DTBRules::Rescore(TreeType& queryNode, // Calculate the bound for a given query node in its current state and update // it. -template -inline double DTBRules::CalculateBound( +template +inline double DTBRules::CalculateBound( TreeType& queryNode) const { double worstPointBound = -DBL_MAX; diff --git a/src/mlpack/methods/fastmks/fastmks.hpp b/src/mlpack/methods/fastmks/fastmks.hpp index cbc0faa9a8..300b75a289 100644 --- a/src/mlpack/methods/fastmks/fastmks.hpp +++ b/src/mlpack/methods/fastmks/fastmks.hpp @@ -53,7 +53,7 @@ namespace mlpack { template< typename KernelType, typename MatType = arma::mat, - template class TreeType = StandardCoverTree > @@ -134,9 +134,9 @@ class FastMKS /** * Create the FastMKS object with an already-initialized tree built on the - * reference points. Be sure that the tree is built with the metric type - * IPMetric. Optionally, whether or not to run single-tree search - * can be specified. Brute-force search is not available with this + * reference points. Be sure that the tree is built with the distance metric + * type IPMetric. Optionally, whether or not to run single-tree + * search can be specified. Brute-force search is not available with this * constructor since a tree is given (use one of the other constructors). * * @param referenceTree Tree built on reference data. @@ -178,8 +178,8 @@ class FastMKS /** * "Train" the FastMKS model on the given reference set and use the given - * kernel. This will just build a tree and replace the metric, if the current - * search mode is not naive mode. + * kernel. This will just build a tree and replace the distance metric, if + * the current search mode is not naive mode. * * @param referenceSet Set of reference points. * @param kernel Kernel to use for search. @@ -197,8 +197,9 @@ class FastMKS /** * "Train" the FastMKS model on the given reference set and use the given - * kernel. This will just build a tree and replace the metric, if the current - * search mode is not naive mode. This takes ownership of the reference set. + * kernel. This will just build a tree and replace the distance metric, if + * the current search mode is not naive mode. This takes ownership of the + * reference set. * * @param referenceSet Set of reference points. * @param kernel Kernel to use for search. @@ -284,10 +285,17 @@ class FastMKS arma::Mat& indices, arma::mat& products); - //! Get the inner-product metric induced by the given kernel. - const IPMetric& Metric() const { return metric; } - //! Modify the inner-product metric induced by the given kernel. - IPMetric& Metric() { return metric; } + //! Get the inner-product distance metric induced by the given kernel. + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + const IPMetric& Metric() const { return distance; } + //! Modify the inner-product distance metric induced by the given kernel. + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + IPMetric& Metric() { return distance; } + + //! Get the inner-product distance metric induced by the given kernel. + const IPMetric& Distance() const { return distance; } + //! Modify the inner-product distance metric induced by the given kernel. + IPMetric& Distance() { return distance; } //! Get whether or not single-tree search is used. bool SingleMode() const { return singleMode; } @@ -319,8 +327,9 @@ class FastMKS //! If true, naive (brute-force) search is used. bool naive; - //! The instantiated inner-product metric induced by the given kernel. - IPMetric metric; + //! The instantiated inner-product distance metric induced by the given + //! kernel. + IPMetric distance; //! Candidate represents a possible candidate point (value, index). typedef std::pair Candidate; diff --git a/src/mlpack/methods/fastmks/fastmks_impl.hpp b/src/mlpack/methods/fastmks/fastmks_impl.hpp index 452933075a..9e0a55f19f 100644 --- a/src/mlpack/methods/fastmks/fastmks_impl.hpp +++ b/src/mlpack/methods/fastmks/fastmks_impl.hpp @@ -22,7 +22,7 @@ namespace mlpack { // No data; create a model on an empty dataset. template class TreeType> FastMKS::FastMKS(const bool singleMode, @@ -41,7 +41,7 @@ FastMKS::FastMKS(const bool singleMode, // No instantiated kernel. template class TreeType> FastMKS::FastMKS( @@ -62,7 +62,7 @@ FastMKS::FastMKS( // Instantiated kernel. template class TreeType> FastMKS::FastMKS(const MatType& referenceSet, @@ -75,17 +75,17 @@ FastMKS::FastMKS(const MatType& referenceSet, setOwner(false), singleMode(singleMode), naive(naive), - metric(kernel) + distance(kernel) { // If necessary, the reference tree should be built. There is no query tree. if (!naive) - referenceTree = new Tree(referenceSet, metric); + referenceTree = new Tree(referenceSet, distance); } // No instantiated kernel. template class TreeType> FastMKS::FastMKS( @@ -109,7 +109,7 @@ FastMKS::FastMKS( // Instantiated kernel. template class TreeType> FastMKS::FastMKS(MatType&& referenceSet, @@ -122,12 +122,12 @@ FastMKS::FastMKS(MatType&& referenceSet, setOwner(naive), singleMode(singleMode), naive(naive), - metric(kernel) + distance(kernel) { // If necessary, the reference tree should be built. There is no query tree. if (!naive) { - referenceTree = new Tree(referenceSet, metric); + referenceTree = new Tree(referenceSet, distance); referenceSet = &referenceTree->Dataset(); } } @@ -135,7 +135,7 @@ FastMKS::FastMKS(MatType&& referenceSet, // One dataset, pre-built tree. template class TreeType> FastMKS::FastMKS(Tree* referenceTree, @@ -146,14 +146,14 @@ FastMKS::FastMKS(Tree* referenceTree, setOwner(false), singleMode(singleMode), naive(false), - metric(referenceTree->Metric()) + distance(referenceTree->Distance()) { // Nothing to do. } template class TreeType> FastMKS::FastMKS(const FastMKS& other) : @@ -163,7 +163,7 @@ FastMKS::FastMKS(const FastMKS& other) : setOwner(other.referenceTree == NULL), singleMode(other.singleMode), naive(other.naive), - metric(other.metric) + distance(other.distance) { // Set reference set correctly. if (referenceTree) @@ -174,7 +174,7 @@ FastMKS::FastMKS(const FastMKS& other) : template class TreeType> FastMKS::FastMKS(FastMKS&& other) : @@ -184,7 +184,7 @@ FastMKS::FastMKS(FastMKS&& other) : setOwner(other.setOwner), singleMode(other.singleMode), naive(other.naive), - metric(std::move(other.metric)) + distance(std::move(other.distance)) { // Clear information from the other. other.referenceSet = NULL; @@ -197,7 +197,7 @@ FastMKS::FastMKS(FastMKS&& other) : template class TreeType> FastMKS& @@ -235,7 +235,7 @@ FastMKS::operator=(const FastMKS& other) template class TreeType> FastMKS& @@ -249,7 +249,7 @@ FastMKS::operator=(FastMKS&& other) setOwner = other.setOwner; singleMode = other.singleMode; naive = other.naive; - metric = std::move(other.metric); + distance = std::move(other.distance); // Clear information from the other. other.referenceSet = nullptr; @@ -264,7 +264,7 @@ FastMKS::operator=(FastMKS&& other) template class TreeType> FastMKS::~FastMKS() @@ -278,7 +278,7 @@ FastMKS::~FastMKS() template class TreeType> void FastMKS::Train(const MatType& referenceSet) @@ -293,14 +293,14 @@ void FastMKS::Train(const MatType& referenceSet) { if (treeOwner && referenceTree) delete referenceTree; - referenceTree = new Tree(referenceSet, metric); + referenceTree = new Tree(referenceSet, distance); treeOwner = true; } } template class TreeType> void FastMKS::Train(const MatType& referenceSet, @@ -310,21 +310,21 @@ void FastMKS::Train(const MatType& referenceSet, delete this->referenceSet; this->referenceSet = &referenceSet; - this->metric = IPMetric(kernel); + this->distance = IPMetric(kernel); this->setOwner = false; if (!naive) { if (treeOwner && referenceTree) delete referenceTree; - referenceTree = new Tree(referenceSet, metric); + referenceTree = new Tree(referenceSet, distance); treeOwner = true; } } template class TreeType> void FastMKS::Train(MatType&& referenceSet) @@ -336,7 +336,7 @@ void FastMKS::Train(MatType&& referenceSet) { if (treeOwner && referenceTree) delete referenceTree; - referenceTree = new Tree(std::move(referenceSet), metric); + referenceTree = new Tree(std::move(referenceSet), distance); referenceSet = referenceTree->Dataset(); treeOwner = true; setOwner = false; @@ -350,7 +350,7 @@ void FastMKS::Train(MatType&& referenceSet) template class TreeType> void FastMKS::Train(MatType&& referenceSet, @@ -359,13 +359,13 @@ void FastMKS::Train(MatType&& referenceSet, if (setOwner) delete this->referenceSet; - this->metric = IPMetric(kernel); + this->distance = IPMetric(kernel); if (!naive) { if (treeOwner && referenceTree) delete referenceTree; - referenceTree = new Tree(std::move(referenceSet), metric); + referenceTree = new Tree(std::move(referenceSet), distance); treeOwner = true; setOwner = false; } @@ -378,7 +378,7 @@ void FastMKS::Train(MatType&& referenceSet, template class TreeType> void FastMKS::Train(Tree* tree) @@ -391,7 +391,7 @@ void FastMKS::Train(Tree* tree) delete this->referenceSet; this->referenceSet = &tree->Dataset(); - this->metric = IPMetric(tree->Metric().Kernel()); + this->distance = IPMetric(tree->Distance().Kernel()); this->setOwner = false; if (treeOwner && referenceTree) @@ -403,7 +403,7 @@ void FastMKS::Train(Tree* tree) template class TreeType> void FastMKS::Search( @@ -445,8 +445,8 @@ void FastMKS::Search( for (size_t r = 0; r < referenceSet->n_cols; ++r) { - const double eval = metric.Kernel().Evaluate(querySet.col(q), - referenceSet->col(r)); + const double eval = distance.Kernel().Evaluate(querySet.col(q), + referenceSet->col(r)); if (eval > pqueue.top().first) { @@ -473,7 +473,7 @@ void FastMKS::Search( // Create rules object (this will store the results). This constructor // precalculates each self-kernel value. typedef FastMKSRules RuleType; - RuleType rules(*referenceSet, querySet, k, metric.Kernel()); + RuleType rules(*referenceSet, querySet, k, distance.Kernel()); typename Tree::template SingleTreeTraverser traverser(rules); @@ -497,7 +497,7 @@ void FastMKS::Search( template class TreeType> void FastMKS::Search( @@ -534,7 +534,7 @@ void FastMKS::Search( kernels.set_size(k, queryTree->Dataset().n_cols); typedef FastMKSRules RuleType; - RuleType rules(*referenceSet, queryTree->Dataset(), k, metric.Kernel()); + RuleType rules(*referenceSet, queryTree->Dataset(), k, distance.Kernel()); typename Tree::template DualTreeTraverser traverser(rules); @@ -548,7 +548,7 @@ void FastMKS::Search( template class TreeType> void FastMKS::Search( @@ -575,7 +575,7 @@ void FastMKS::Search( if (q == r) continue; // Don't return the point as its own candidate. - const double eval = metric.Kernel().Evaluate(referenceSet->col(q), + const double eval = distance.Kernel().Evaluate(referenceSet->col(q), referenceSet->col(r)); if (eval > pqueue.top().first) @@ -603,7 +603,7 @@ void FastMKS::Search( // Create rules object (this will store the results). This constructor // precalculates each self-kernel value. typedef FastMKSRules RuleType; - RuleType rules(*referenceSet, *referenceSet, k, metric.Kernel()); + RuleType rules(*referenceSet, *referenceSet, k, distance.Kernel()); typename Tree::template SingleTreeTraverser traverser(rules); @@ -630,7 +630,7 @@ void FastMKS::Search( //! Serialize the model. template class TreeType> template @@ -654,7 +654,7 @@ void FastMKS::serialize( } ar(CEREAL_POINTER(const_cast(referenceSet))); - ar(CEREAL_NVP(metric)); + ar(CEREAL_NVP(distance)); } else { @@ -675,7 +675,7 @@ void FastMKS::serialize( delete referenceSet; referenceSet = &referenceTree->Dataset(); - metric = IPMetric(referenceTree->Metric().Kernel()); + distance = IPMetric(referenceTree->Distance().Kernel()); setOwner = false; } } diff --git a/src/mlpack/methods/fastmks/fastmks_stat.hpp b/src/mlpack/methods/fastmks/fastmks_stat.hpp index 1d9d7bfa3d..6a0b289ecb 100644 --- a/src/mlpack/methods/fastmks/fastmks_stat.hpp +++ b/src/mlpack/methods/fastmks/fastmks_stat.hpp @@ -61,7 +61,7 @@ class FastMKSStat } else { - selfKernel = std::sqrt(node.Metric().Kernel().Evaluate( + selfKernel = std::sqrt(node.Distance().Kernel().Evaluate( node.Dataset().col(node.Point(0)), node.Dataset().col(node.Point(0)))); } @@ -72,7 +72,7 @@ class FastMKSStat arma::vec center; node.Center(center); - selfKernel = std::sqrt(node.Metric().Kernel().Evaluate(center, center)); + selfKernel = std::sqrt(node.Distance().Kernel().Evaluate(center, center)); } } diff --git a/src/mlpack/methods/gmm/diagonal_gmm.hpp b/src/mlpack/methods/gmm/diagonal_gmm.hpp index 6f58c4437c..b44de7dfb3 100644 --- a/src/mlpack/methods/gmm/diagonal_gmm.hpp +++ b/src/mlpack/methods/gmm/diagonal_gmm.hpp @@ -10,12 +10,11 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ - #ifndef MLPACK_METHODS_GMM_DIAGONAL_GMM_HPP #define MLPACK_METHODS_GMM_DIAGONAL_GMM_HPP #include -#include +#include #include // This is the default fitting method class. diff --git a/src/mlpack/methods/gmm/em_fit.hpp b/src/mlpack/methods/gmm/em_fit.hpp index 7aa0ffda02..535889b559 100644 --- a/src/mlpack/methods/gmm/em_fit.hpp +++ b/src/mlpack/methods/gmm/em_fit.hpp @@ -15,7 +15,7 @@ #define MLPACK_METHODS_GMM_EM_FIT_HPP #include -#include +#include // Default clustering mechanism. #include diff --git a/src/mlpack/methods/kde/kde.hpp b/src/mlpack/methods/kde/kde.hpp index c2fa243cf7..9b13f9e767 100644 --- a/src/mlpack/methods/kde/kde.hpp +++ b/src/mlpack/methods/kde/kde.hpp @@ -63,28 +63,29 @@ struct KDEDefaultParams * dual-tree algorithm. Details about this algorithm are available in KDERules. * * @tparam KernelType Kernel function to use for KDE calculations. - * @tparam MetricType Metric to use for KDE calculations. + * @tparam DistanceType Metric to use for KDE calculations. * @tparam MatType Type of data to use. * @tparam TreeType Type of tree to use; must satisfy the TreeType policy API. * @tparam DualTreeTraversalType Type of dual-tree traversal to use. * @tparam SingleTreeTraversalType Type of single-tree traversal to use. */ template class TreeType = KDTree, template class DualTreeTraversalType = - TreeType::template DualTreeTraverser, + TreeType::template + DualTreeTraverser, template class SingleTreeTraversalType = - TreeType::template + TreeType::template SingleTreeTraverser> class KDE { public: //! Convenience typedef. - typedef TreeType Tree; + typedef TreeType Tree; /** * Initialize KDE object using custom instantiated Metric and Kernel objects. @@ -93,7 +94,7 @@ class KDE * @param absError Absolute error tolerance of the model. * @param kernel Instantiated kernel object. * @param mode Mode for the algorithm. - * @param metric Instantiated metric object. + * @param distance Instantiated distance metric object. * @param monteCarlo Whether to use Monte Carlo estimations when possible. * @param mcProb Probability of a Monte Carlo estimation to be bounded by * relative error tolerance. @@ -110,7 +111,7 @@ class KDE const double absError = KDEDefaultParams::absError, KernelType kernel = KernelType(), const KDEMode mode = KDEDefaultParams::mode, - MetricType metric = MetricType(), + DistanceType distance = DistanceType(), const bool monteCarlo = KDEDefaultParams::monteCarlo, const double mcProb = KDEDefaultParams::mcProb, const size_t initialSampleSize = KDEDefaultParams::initialSampleSize, @@ -226,11 +227,17 @@ class KDE //! Modify the kernel. KernelType& Kernel() { return kernel; } - //! Get the metric. - const MetricType& Metric() const { return metric; } + //! Get the distance metric. + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + const DistanceType& Metric() const { return distance; } + //! Modify the distance metric. + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + DistanceType& Metric() { return distance; } + //! Get the distance metric. + const DistanceType& Distance() const { return distance; } //! Modify the metric. - MetricType& Metric() { return metric; } + DistanceType& Distance() { return distance; } //! Get the reference tree. Tree* ReferenceTree() { return referenceTree; } @@ -298,8 +305,8 @@ class KDE //! Kernel. KernelType kernel; - //! Metric. - MetricType metric; + //! Distance metric. + DistanceType distance; //! Reference tree. Tree* referenceTree; diff --git a/src/mlpack/methods/kde/kde_impl.hpp b/src/mlpack/methods/kde/kde_impl.hpp index 9a0e6fe3b1..4bf4b939c0 100644 --- a/src/mlpack/methods/kde/kde_impl.hpp +++ b/src/mlpack/methods/kde/kde_impl.hpp @@ -16,15 +16,15 @@ namespace mlpack { template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> KDE class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> KDE:: KDE(const KDE& other) : kernel(KernelType(other.kernel)), - metric(MetricType(other.metric)), + distance(DistanceType(other.distance)), relError(other.relError), absError(other.absError), ownsReferenceTree(other.ownsReferenceTree), @@ -102,22 +102,22 @@ KDE(const KDE& other) : } template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> KDE:: KDE(KDE&& other) : kernel(std::move(other.kernel)), - metric(std::move(other.metric)), + distance(std::move(other.distance)), referenceTree(other.referenceTree), oldFromNewReferences(other.oldFromNewReferences), relError(other.relError), @@ -132,7 +132,7 @@ KDE(KDE&& other) : mcBreakCoef(other.mcBreakCoef) { other.kernel = std::move(KernelType()); - other.metric = std::move(MetricType()); + other.distance = std::move(DistanceType()); other.referenceTree = nullptr; other.oldFromNewReferences = nullptr; other.relError = KDEDefaultParams::relError; @@ -148,21 +148,21 @@ KDE(KDE&& other) : } template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> KDE& KDE class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> KDE& KDEkernel = std::move(other.kernel); - this->metric = std::move(other.metric); + this->distance = std::move(other.distance); this->referenceTree = std::move(other.referenceTree); this->oldFromNewReferences = std::move(other.oldFromNewReferences); this->relError = other.relError; @@ -258,15 +258,15 @@ operator=(KDE&& other) } template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> KDE class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> void KDE class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> void KDE* oldFromNewReferences) } template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> void KDE RuleType; + typedef KDERules RuleType; RuleType rules = RuleType(referenceTree->Dataset(), querySet, estimations, @@ -423,7 +423,7 @@ Evaluate(MatType querySet, arma::vec& estimations) initialSampleSize, mcEntryCoef, mcBreakCoef, - metric, + distance, kernel, monteCarlo, false); @@ -445,15 +445,15 @@ Evaluate(MatType querySet, arma::vec& estimations) } template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> void KDE RuleType; + typedef KDERules RuleType; RuleType rules = RuleType(referenceTree->Dataset(), queryTree->Dataset(), estimations, @@ -516,7 +516,7 @@ Evaluate(Tree* queryTree, initialSampleSize, mcEntryCoef, mcBreakCoef, - metric, + distance, kernel, monteCarlo, false); @@ -534,15 +534,15 @@ Evaluate(Tree* queryTree, } template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> void KDE RuleType; + typedef KDERules RuleType; RuleType rules = RuleType(referenceTree->Dataset(), referenceTree->Dataset(), estimations, @@ -580,7 +580,7 @@ Evaluate(arma::vec& estimations) initialSampleSize, mcEntryCoef, mcBreakCoef, - metric, + distance, kernel, monteCarlo, true); @@ -607,15 +607,15 @@ Evaluate(arma::vec& estimations) } template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> void KDE class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> void KDE class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> void KDE class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> void KDE class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> void KDE class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> template void KDE class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> void KDE class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> void KDE class TreeType> class KDEWrapper : public KDEWrapperBase diff --git a/src/mlpack/methods/kde/kde_model_impl.hpp b/src/mlpack/methods/kde/kde_model_impl.hpp index 3d7de82115..3bd45462f1 100644 --- a/src/mlpack/methods/kde/kde_model_impl.hpp +++ b/src/mlpack/methods/kde/kde_model_impl.hpp @@ -150,7 +150,7 @@ inline KDEModel::~KDEModel() delete kdeModel; } -template class TreeType> KDEWrapperBase* InitializeModelHelper(const KDEModel::KernelTypes kernelType, @@ -323,7 +323,7 @@ inline void KDEModel::MCBreakCoefficient(const double newBreakCoef) //! Train the model (build the tree). template class TreeType> void KDEWrapper::Train(util::Timers& timers, @@ -336,7 +336,7 @@ void KDEWrapper::Train(util::Timers& timers, //! Perform bichromatic KDE (i.e. KDE with a separate query set). template class TreeType> void KDEWrapper::Evaluate(util::Timers& timers, @@ -375,7 +375,7 @@ void KDEWrapper::Evaluate(util::Timers& timers, //! Perform monochromatic KDE (i.e. with the reference set as the query set). template class TreeType> void KDEWrapper::Evaluate(util::Timers& timers, @@ -393,7 +393,7 @@ void KDEWrapper::Evaluate(util::Timers& timers, timers.Stop("applying_normalizer"); } -template class TreeType, typename Archive> diff --git a/src/mlpack/methods/kde/kde_rules.hpp b/src/mlpack/methods/kde/kde_rules.hpp index dd038a04cf..671abbc478 100644 --- a/src/mlpack/methods/kde/kde_rules.hpp +++ b/src/mlpack/methods/kde/kde_rules.hpp @@ -21,7 +21,7 @@ namespace mlpack { * A dual-tree traversal Rules class for kernel density estimation. This * contains the Score() and BaseCase() implementations. */ -template +template class KDERules { public: @@ -38,7 +38,7 @@ class KDERules * @param initialSampleSize Initial size of the Monte Carlo samples. * @param mcAccessCoef Access coefficient for Monte Carlo estimations. * @param mcBreakCoef Break coefficient for Monte Carlo estimations. - * @param metric Instantiated metric. + * @param distance Instantiated distance metric. * @param kernel Instantiated kernel. * @param monteCarlo If true Monte Carlo estimations will be applied when * possible. @@ -54,7 +54,7 @@ class KDERules const size_t initialSampleSize, const double mcAccessCoef, const double mcBreakCoef, - MetricType& metric, + DistanceType& distance, KernelType& kernel, const bool monteCarlo, const bool sameSet); @@ -139,8 +139,8 @@ class KDERules //! is the limit before Monte Carlo estimation recurses. const double mcBreakCoef; - //! Instantiated metric. - MetricType& metric; + //! Instantiated distance metric. + DistanceType& distance; //! Instantiated kernel. KernelType& kernel; diff --git a/src/mlpack/methods/kde/kde_rules_impl.hpp b/src/mlpack/methods/kde/kde_rules_impl.hpp index 83b725708c..81aeb18658 100644 --- a/src/mlpack/methods/kde/kde_rules_impl.hpp +++ b/src/mlpack/methods/kde/kde_rules_impl.hpp @@ -21,8 +21,8 @@ namespace mlpack { -template -KDERules::KDERules( +template +KDERules::KDERules( const arma::mat& referenceSet, const arma::mat& querySet, arma::vec& densities, @@ -32,7 +32,7 @@ KDERules::KDERules( const size_t initialSampleSize, const double mcAccessCoef, const double mcBreakCoef, - MetricType& metric, + DistanceType& distance, KernelType& kernel, const bool monteCarlo, const bool sameSet) : @@ -45,7 +45,7 @@ KDERules::KDERules( initialSampleSize(initialSampleSize), mcAccessCoef(mcAccessCoef), mcBreakCoef(mcBreakCoef), - metric(metric), + distance(distance), kernel(kernel), monteCarlo(monteCarlo), sameSet(sameSet), @@ -64,9 +64,9 @@ KDERules::KDERules( } //! The base case. -template +template inline mlpack_force_inline -double KDERules::BaseCase( +double KDERules::BaseCase( const size_t queryIndex, const size_t referenceIndex) { @@ -80,9 +80,9 @@ double KDERules::BaseCase( return 0.0; // Calculations. - const double distance = metric.Evaluate(querySet.col(queryIndex), - referenceSet.col(referenceIndex)); - const double kernelValue = kernel.Evaluate(distance); + const double d = distance.Evaluate(querySet.col(queryIndex), + referenceSet.col(referenceIndex)); + const double kernelValue = kernel.Evaluate(d); densities(queryIndex) += kernelValue; // Update accumulated relative error tolerance for single-tree pruning. @@ -91,13 +91,13 @@ double KDERules::BaseCase( ++baseCases; lastQueryIndex = queryIndex; lastReferenceIndex = referenceIndex; - traversalInfo.LastBaseCase() = distance; - return distance; + traversalInfo.LastBaseCase() = d; + return d; } //! Single-tree scoring function. -template -inline double KDERules:: +template +inline double KDERules:: Score(const size_t queryIndex, TreeType& referenceNode) { // Auxiliary variables. @@ -290,8 +290,8 @@ Score(const size_t queryIndex, TreeType& referenceNode) return score; } -template -inline mlpack_force_inline double KDERules:: +template +inline mlpack_force_inline double KDERules:: Rescore(const size_t /* queryIndex */, TreeType& /* referenceNode */, const double oldScore) const @@ -301,8 +301,8 @@ Rescore(const size_t /* queryIndex */, } //! Dual-tree scoring function. -template -inline double KDERules:: +template +inline double KDERules:: Score(TreeType& queryNode, TreeType& referenceNode) { KDEStat& queryStat = queryNode.Stat(); @@ -513,8 +513,8 @@ Score(TreeType& queryNode, TreeType& referenceNode) } //! Dual-tree rescore. -template -inline mlpack_force_inline double KDERules:: +template +inline mlpack_force_inline double KDERules:: Rescore(TreeType& /*queryNode*/, TreeType& /*referenceNode*/, const double oldScore) const @@ -523,8 +523,8 @@ Rescore(TreeType& /*queryNode*/, return oldScore; } -template -inline mlpack_force_inline double KDERules:: +template +inline mlpack_force_inline double KDERules:: EvaluateKernel(const size_t queryIndex, const size_t referenceIndex) const { @@ -532,15 +532,15 @@ EvaluateKernel(const size_t queryIndex, referenceSet.unsafe_col(referenceIndex)); } -template -inline mlpack_force_inline double KDERules:: +template +inline mlpack_force_inline double KDERules:: EvaluateKernel(const arma::vec& query, const arma::vec& reference) const { - return kernel.Evaluate(metric.Evaluate(query, reference)); + return kernel.Evaluate(distance.Evaluate(query, reference)); } -template -inline mlpack_force_inline double KDERules:: +template +inline mlpack_force_inline double KDERules:: CalculateAlpha(TreeType* node) { KDEStat& stat = node->Stat(); diff --git a/src/mlpack/methods/kmeans/allow_empty_clusters.hpp b/src/mlpack/methods/kmeans/allow_empty_clusters.hpp index fc478ef4ed..856b8bf61c 100644 --- a/src/mlpack/methods/kmeans/allow_empty_clusters.hpp +++ b/src/mlpack/methods/kmeans/allow_empty_clusters.hpp @@ -39,19 +39,19 @@ class AllowEmptyClusters * @param newCentroids Centroids of each cluster (one per column) at the end * of the iteration. * @param * (clusterCounts) Number of points in each cluster. - * @param * (metric) The Metric to use. + * @param * (distance) The distance metric to use. * @param * (iteration) Number of iteration. * * @return Number of points changed (0). */ - template + template static inline mlpack_force_inline void EmptyCluster( const MatType& /* data */, const size_t emptyCluster, const arma::mat& oldCentroids, arma::mat& newCentroids, arma::Col& /* clusterCounts */, - MetricType& /* metric */, + DistanceType& /* distance */, const size_t /* iteration */) { // Take the last iteration's centroid. diff --git a/src/mlpack/methods/kmeans/dual_tree_kmeans.hpp b/src/mlpack/methods/kmeans/dual_tree_kmeans.hpp index 9ad786fe35..5897ff1b04 100644 --- a/src/mlpack/methods/kmeans/dual_tree_kmeans.hpp +++ b/src/mlpack/methods/kmeans/dual_tree_kmeans.hpp @@ -31,9 +31,9 @@ namespace mlpack { * and the number of iterations of the k-means algorithm will be few. */ template< - typename MetricType, + typename DistanceType, typename MatType, - template class TreeType = KDTree> @@ -41,19 +41,19 @@ class DualTreeKMeans { public: //! Convenience typedef. - typedef TreeType Tree; + typedef TreeType Tree; - template using NNSTreeType = - TreeType; + TreeType; /** * Construct the DualTreeKMeans object, which will construct a tree on the * points. */ - DualTreeKMeans(const MatType& dataset, MetricType& metric); + DualTreeKMeans(const MatType& dataset, DistanceType& distance); /** * Delete the tree constructed by the DualTreeKMeans object. @@ -84,8 +84,8 @@ class DualTreeKMeans Tree* tree; //! The dataset we are using. const MatType& dataset; - //! The metric. - MetricType metric; + //! The distance metric. + DistanceType distance; //! Track distance calculations. size_t distanceCalculations; @@ -159,13 +159,13 @@ void RestoreChildren(TreeType& node, //! A template typedef for the DualTreeKMeans algorithm with the default tree //! type (a kd-tree). -template -using DefaultDualTreeKMeans = DualTreeKMeans; +template +using DefaultDualTreeKMeans = DualTreeKMeans; //! A template typedef for the DualTreeKMeans algorithm with the cover tree //! type. -template -using CoverTreeDualTreeKMeans = DualTreeKMeans +using CoverTreeDualTreeKMeans = DualTreeKMeans; } // namespace mlpack diff --git a/src/mlpack/methods/kmeans/dual_tree_kmeans_impl.hpp b/src/mlpack/methods/kmeans/dual_tree_kmeans_impl.hpp index e9b08b4514..8181b49512 100644 --- a/src/mlpack/methods/kmeans/dual_tree_kmeans_impl.hpp +++ b/src/mlpack/methods/kmeans/dual_tree_kmeans_impl.hpp @@ -46,18 +46,18 @@ TreeType* BuildForcedLeafSizeTree( return new TreeType(std::forward(dataset)); } -template class TreeType> -DualTreeKMeans::DualTreeKMeans( +DualTreeKMeans::DualTreeKMeans( const MatType& dataset, - MetricType& metric) : + DistanceType& distance) : datasetOrig(dataset), tree(new Tree(const_cast(dataset))), dataset(tree->Dataset()), - metric(metric), + distance(distance), distanceCalculations(0), iteration(0), upperBounds(dataset.n_cols), @@ -76,24 +76,24 @@ DualTreeKMeans::DualTreeKMeans( lowerBounds.fill(DBL_MAX); } -template class TreeType> -DualTreeKMeans::~DualTreeKMeans() +DualTreeKMeans::~DualTreeKMeans() { if (tree) delete tree; } // Run a single iteration. -template class TreeType> -double DualTreeKMeans::Iterate( +double DualTreeKMeans::Iterate( const arma::mat& centroids, arma::mat& newCentroids, arma::Col& counts) @@ -107,7 +107,7 @@ double DualTreeKMeans::Iterate( // Find the nearest neighbors of each of the clusters. We have to make our // own TreeType, which is a little bit abuse, but we know for sure the // TreeStatType we have will work. - NeighborSearch + NeighborSearch nns(std::move(*centroidTree)); // Reset information in the tree, if we need to. @@ -145,9 +145,9 @@ double DualTreeKMeans::Iterate( // We won't use the KNN class here because we have our own set of rules. lastIterationCentroids = centroids; - typedef DualTreeKMeansRules RuleType; + typedef DualTreeKMeansRules RuleType; RuleType rules(nns.ReferenceTree().Dataset(), dataset, assignments, - upperBounds, lowerBounds, metric, prunedPoints, oldFromNewCentroids, + upperBounds, lowerBounds, distance, prunedPoints, oldFromNewCentroids, visited); typename Tree::template BreadthFirstDualTreeTraverser @@ -179,7 +179,7 @@ double DualTreeKMeans::Iterate( else { newCentroids.col(c) /= counts(c); - const double movement = metric.Evaluate(centroids.col(c), + const double movement = distance.Evaluate(centroids.col(c), newCentroids.col(c)); clusterDistances[c] = movement; residual += std::pow(movement, 2.0); @@ -197,12 +197,12 @@ double DualTreeKMeans::Iterate( return std::sqrt(residual); } -template class TreeType> -void DualTreeKMeans::UpdateTree( +void DualTreeKMeans::UpdateTree( Tree& node, const arma::mat& centroids, const double parentUpperBound, @@ -232,58 +232,6 @@ void DualTreeKMeans::UpdateTree( const double unadjustedLowerBound = node.Stat().LowerBound(); double adjustedLowerBound = adjustedParentLowerBound; - // Exhaustive lower bound check. Sigh. -/* - if (!prunedLastIteration) - { - for (size_t i = 0; i < node.NumDescendants(); ++i) - { - double closest = DBL_MAX; - double secondClosest = DBL_MAX; - arma::vec distances(centroids.n_cols); - for (size_t j = 0; j < centroids.n_cols; ++j) - { - const double dist = metric.Evaluate(dataset.col(node.Descendant(i)), - lastIterationCentroids.col(j)); - distances(j) = dist; - - if (dist < closest) - { - secondClosest = closest; - closest = dist; - } - else if (dist < secondClosest) - secondClosest = dist; - } - if (closest - 1e-10 > node.Stat().UpperBound()) - { - Log::Warn << distances.t(); - Log::Fatal << "Point " << node.Descendant(i) << " in " << node.Point(0) << -"c" << node.NumDescendants() << " invalidates upper bound " << -node.Stat().UpperBound() << " with closest cluster distance " << closest << -".\n"; - } - - if (node.NumChildren() == 0) - { - if (secondClosest + 1e-10 < std::min(lowerBounds[node.Descendant(i)], - node.Stat().LowerBound())) - { - Log::Warn << distances.t(); - Log::Warn << node; - Log::Fatal << "Point " << node.Descendant(i) << " in " << node.Point(0) << -"c" << node.NumDescendants() << " invalidates lower bound " << -std::min(lowerBounds[node.Descendant(i)], node.Stat().LowerBound()) << " (" << -lowerBounds[node.Descendant(i)] << ", " << node.Stat().LowerBound() << ") with " - << "second closest cluster distance " << secondClosest << ". cd " << -closest << "; pruned " << prunedPoints[node.Descendant(i)] << " visited " << -visited[node.Descendant(i)] << ".\n"; - } - } - } - } -*/ - if ((node.Stat().Pruned() == centroids.n_cols) && (node.Stat().Owner() < centroids.n_cols)) { @@ -389,8 +337,8 @@ visited[node.Descendant(i)] << ".\n"; else { // Attempt to tighten the bound. - upperBounds[index] = metric.Evaluate(dataset.col(index), - centroids.col(owner)); + upperBounds[index] = distance.Evaluate(dataset.col(index), + centroids.col(owner)); ++distanceCalculations; if (upperBounds[index] < pruningLowerBound) { @@ -462,12 +410,12 @@ visited[node.Descendant(i)] << ".\n"; } } -template class TreeType> -void DualTreeKMeans::ExtractCentroids( +void DualTreeKMeans::ExtractCentroids( Tree& node, arma::mat& newCentroids, arma::Col& newCounts, @@ -480,33 +428,6 @@ void DualTreeKMeans::ExtractCentroids( const size_t owner = node.Stat().Owner(); newCentroids.col(owner) += node.Stat().Centroid() * node.NumDescendants(); newCounts[owner] += node.NumDescendants(); - - // Perform the sanity check here. -/* - for (size_t i = 0; i < node.NumDescendants(); ++i) - { - const size_t index = node.Descendant(i); - arma::vec trueDistances(centroids.n_cols); - for (size_t j = 0; j < centroids.n_cols; ++j) - { - const double dist = metric.Evaluate(dataset.col(index), - centroids.col(j)); - trueDistances[j] = dist; - } - - arma::uword minIndex; - const double minDist = trueDistances.min(minIndex); - if (size_t(minIndex) != owner) - { - Log::Warn << node; - Log::Warn << trueDistances.t(); - Log::Fatal << "Point " << index << " of node " << node.Point(0) << "c" -<< node.NumDescendants() << " has true minimum cluster " << minIndex << " with " - << "distance " << minDist << " but node is pruned with upper bound " << -node.Stat().UpperBound() << " and owner " << node.Stat().Owner() << ".\n"; - } - } -*/ } else { @@ -519,33 +440,6 @@ node.Stat().UpperBound() << " and owner " << node.Stat().Owner() << ".\n"; const size_t owner = assignments[node.Point(i)]; newCentroids.col(owner) += dataset.col(node.Point(i)); ++newCounts[owner]; - -/* - const size_t index = node.Point(i); - arma::vec trueDistances(centroids.n_cols); - for (size_t j = 0; j < centroids.n_cols; ++j) - { - const double dist = metric.Evaluate(dataset.col(index), - centroids.col(j)); - trueDistances[j] = dist; - } - - arma::uword minIndex; - const double minDist = trueDistances.min(minIndex); - if (size_t(minIndex) != owner) - { - Log::Warn << node; - Log::Warn << trueDistances.t(); - Log::Fatal << "Point " << index << " of node " << node.Point(0) << "c" - << node.NumDescendants() << " has true minimum cluster " << minIndex << " with " - << "distance " << minDist << " but was assigned to cluster " << -assignments[node.Point(i)] << " with ub " << upperBounds[node.Point(i)] << -" and lb " << lowerBounds[node.Point(i)] << "; pp " << -(prunedPoints[node.Point(i)] ? "true" : "false") << ", visited " << -(visited[node.Point(i)] ? "true" -: "false") << ".\n"; - } -*/ } } @@ -555,12 +449,12 @@ assignments[node.Point(i)] << " with ub " << upperBounds[node.Point(i)] << } } -template class TreeType> -void DualTreeKMeans::CoalesceTree( +void DualTreeKMeans::CoalesceTree( Tree& node, const size_t child /* Which child are we? */) { @@ -604,12 +498,12 @@ void DualTreeKMeans::CoalesceTree( } } -template class TreeType> -void DualTreeKMeans::DecoalesceTree(Tree& node) +void DualTreeKMeans::DecoalesceTree(Tree& node) { node.Parent() = (Tree*) node.Stat().TrueParent(); RestoreChildren(node); diff --git a/src/mlpack/methods/kmeans/dual_tree_kmeans_rules.hpp b/src/mlpack/methods/kmeans/dual_tree_kmeans_rules.hpp index b237f0f088..47080c0396 100644 --- a/src/mlpack/methods/kmeans/dual_tree_kmeans_rules.hpp +++ b/src/mlpack/methods/kmeans/dual_tree_kmeans_rules.hpp @@ -18,7 +18,7 @@ namespace mlpack { -template +template class DualTreeKMeansRules { public: @@ -27,7 +27,7 @@ class DualTreeKMeansRules arma::Row& assignments, arma::vec& upperBounds, arma::vec& lowerBounds, - MetricType& metric, + DistanceType& distance, const std::vector& prunedPoints, const std::vector& oldFromNewCentroids, std::vector& visited); @@ -64,7 +64,7 @@ class DualTreeKMeansRules arma::Row& assignments; arma::vec& upperBounds; arma::vec& lowerBounds; - MetricType& metric; + DistanceType& distance; const std::vector& prunedPoints; diff --git a/src/mlpack/methods/kmeans/dual_tree_kmeans_rules_impl.hpp b/src/mlpack/methods/kmeans/dual_tree_kmeans_rules_impl.hpp index 6bdaa231c2..85dc8b6d12 100644 --- a/src/mlpack/methods/kmeans/dual_tree_kmeans_rules_impl.hpp +++ b/src/mlpack/methods/kmeans/dual_tree_kmeans_rules_impl.hpp @@ -16,14 +16,14 @@ namespace mlpack { -template -DualTreeKMeansRules::DualTreeKMeansRules( +template +DualTreeKMeansRules::DualTreeKMeansRules( const arma::mat& centroids, const arma::mat& dataset, arma::Row& assignments, arma::vec& upperBounds, arma::vec& lowerBounds, - MetricType& metric, + DistanceType& distance, const std::vector& prunedPoints, const std::vector& oldFromNewCentroids, std::vector& visited) : @@ -32,7 +32,7 @@ DualTreeKMeansRules::DualTreeKMeansRules( assignments(assignments), upperBounds(upperBounds), lowerBounds(lowerBounds), - metric(metric), + distance(distance), prunedPoints(prunedPoints), oldFromNewCentroids(oldFromNewCentroids), visited(visited), @@ -49,9 +49,9 @@ DualTreeKMeansRules::DualTreeKMeansRules( traversalInfo.LastReferenceNode() = (TreeType*) this; } -template +template inline mlpack_force_inline -double DualTreeKMeansRules::BaseCase( +double DualTreeKMeansRules::BaseCase( const size_t queryIndex, const size_t referenceIndex) { @@ -67,31 +67,31 @@ double DualTreeKMeansRules::BaseCase( // Calculate the distance. ++baseCases; - const double distance = metric.Evaluate(dataset.col(queryIndex), - centroids.col(referenceIndex)); + const double dist = distance.Evaluate(dataset.col(queryIndex), + centroids.col(referenceIndex)); - if (distance < upperBounds[queryIndex]) + if (dist < upperBounds[queryIndex]) { lowerBounds[queryIndex] = upperBounds[queryIndex]; - upperBounds[queryIndex] = distance; + upperBounds[queryIndex] = dist; assignments[queryIndex] = (TreeTraits::RearrangesDataset) ? oldFromNewCentroids[referenceIndex] : referenceIndex; } - else if (distance < lowerBounds[queryIndex]) + else if (dist < lowerBounds[queryIndex]) { - lowerBounds[queryIndex] = distance; + lowerBounds[queryIndex] = dist; } // Cache this information for the next time BaseCase() is called. lastQueryIndex = queryIndex; lastReferenceIndex = referenceIndex; - lastBaseCase = distance; + lastBaseCase = dist; - return distance; + return dist; } -template -inline double DualTreeKMeansRules::Score( +template +inline double DualTreeKMeansRules::Score( const size_t queryIndex, TreeType& /* referenceNode */) { @@ -104,8 +104,8 @@ inline double DualTreeKMeansRules::Score( return 0; } -template -inline double DualTreeKMeansRules::Score( +template +inline double DualTreeKMeansRules::Score( TreeType& queryNode, TreeType& referenceNode) { @@ -290,8 +290,8 @@ inline double DualTreeKMeansRules::Score( return score; } -template -inline double DualTreeKMeansRules::Rescore( +template +inline double DualTreeKMeansRules::Rescore( const size_t /* queryIndex */, TreeType& /* referenceNode */, const double oldScore) @@ -300,8 +300,8 @@ inline double DualTreeKMeansRules::Rescore( return oldScore; } -template -inline double DualTreeKMeansRules::Rescore( +template +inline double DualTreeKMeansRules::Rescore( TreeType& queryNode, TreeType& referenceNode, const double oldScore) diff --git a/src/mlpack/methods/kmeans/elkan_kmeans.hpp b/src/mlpack/methods/kmeans/elkan_kmeans.hpp index 3b4c78117f..f10463f54d 100644 --- a/src/mlpack/methods/kmeans/elkan_kmeans.hpp +++ b/src/mlpack/methods/kmeans/elkan_kmeans.hpp @@ -14,14 +14,14 @@ namespace mlpack { -template +template class ElkanKMeans { public: /** * Construct the ElkanKMeans object, which must store several sets of bounds. */ - ElkanKMeans(const MatType& dataset, MetricType& metric); + ElkanKMeans(const MatType& dataset, DistanceType& distance); /** * Run a single iteration of Elkan's algorithm, updating the given centroids @@ -40,8 +40,8 @@ class ElkanKMeans private: //! The dataset. const MatType& dataset; - //! The instantiated metric. - MetricType& metric; + //! The instantiated distance metric. + DistanceType& distance; //! Holds intra-cluster distances. arma::mat clusterDistances; diff --git a/src/mlpack/methods/kmeans/elkan_kmeans_impl.hpp b/src/mlpack/methods/kmeans/elkan_kmeans_impl.hpp index 227e61acc8..15b8c009df 100644 --- a/src/mlpack/methods/kmeans/elkan_kmeans_impl.hpp +++ b/src/mlpack/methods/kmeans/elkan_kmeans_impl.hpp @@ -17,21 +17,21 @@ namespace mlpack { -template -ElkanKMeans::ElkanKMeans(const MatType& dataset, - MetricType& metric) : +template +ElkanKMeans::ElkanKMeans(const MatType& dataset, + DistanceType& distance) : dataset(dataset), - metric(metric), + distance(distance), distanceCalculations(0) { // Nothing to do here. } // Run a single iteration of Elkan's algorithm for Lloyd iterations. -template -double ElkanKMeans::Iterate(const arma::mat& centroids, - arma::mat& newCentroids, - arma::Col& counts) +template +double ElkanKMeans::Iterate(const arma::mat& centroids, + arma::mat& newCentroids, + arma::Col& counts) { // Clear new centroids. newCentroids.zeros(centroids.n_rows, centroids.n_cols); @@ -66,11 +66,11 @@ double ElkanKMeans::Iterate(const arma::mat& centroids, { for (size_t j = i + 1; j < centroids.n_cols; ++j) { - const double distance = metric.Evaluate(centroids.col(i), - centroids.col(j)); + const double dist = distance.Evaluate(centroids.col(i), + centroids.col(j)); distanceCalculations++; - clusterDistances(i, j) = distance; - clusterDistances(j, i) = distance; + clusterDistances(i, j) = dist; + clusterDistances(j, i) = dist; } } @@ -110,7 +110,8 @@ double ElkanKMeans::Iterate(const arma::mat& centroids, if (mustRecalculate[i]) { mustRecalculate[i] = false; - dist = metric.Evaluate(dataset.col(i), centroids.col(assignments[i])); + dist = distance.Evaluate(dataset.col(i), + centroids.col(assignments[i])); lowerBounds(assignments[i], i) = dist; upperBounds(i) = dist; distanceCalculations++; @@ -132,8 +133,8 @@ double ElkanKMeans::Iterate(const arma::mat& centroids, dist > 0.5 * clusterDistances(assignments[i], c)) { // Compute d(x, c). If d(x, c) < d(x, c(x)) then assign c(x) = c. - const double pointDist = metric.Evaluate(dataset.col(i), - centroids.col(c)); + const double pointDist = distance.Evaluate(dataset.col(i), + centroids.col(c)); lowerBounds(c, i) = pointDist; distanceCalculations++; if (pointDist < dist) @@ -160,7 +161,7 @@ double ElkanKMeans::Iterate(const arma::mat& centroids, if (counts[c] > 0) newCentroids.col(c) /= counts[c]; - moveDistances(c) = metric.Evaluate(newCentroids.col(c), centroids.col(c)); + moveDistances(c) = distance.Evaluate(newCentroids.col(c), centroids.col(c)); cNorm += std::pow(moveDistances(c), 2.0); distanceCalculations++; } diff --git a/src/mlpack/methods/kmeans/hamerly_kmeans.hpp b/src/mlpack/methods/kmeans/hamerly_kmeans.hpp index c8a58c88ce..f972b491b4 100644 --- a/src/mlpack/methods/kmeans/hamerly_kmeans.hpp +++ b/src/mlpack/methods/kmeans/hamerly_kmeans.hpp @@ -14,7 +14,7 @@ namespace mlpack { -template +template class HamerlyKMeans { public: @@ -22,7 +22,7 @@ class HamerlyKMeans * Construct the HamerlyKMeans object, which must store several sets of * bounds. */ - HamerlyKMeans(const MatType& dataset, MetricType& metric); + HamerlyKMeans(const MatType& dataset, DistanceType& metric); /** * Run a single iteration of Hamerly's algorithm, updating the given centroids @@ -41,8 +41,8 @@ class HamerlyKMeans private: //! The dataset. const MatType& dataset; - //! The instantiated metric. - MetricType& metric; + //! The instantiated distance metric. + DistanceType& distance; //! Minimum cluster distances from each cluster. arma::vec minClusterDistances; diff --git a/src/mlpack/methods/kmeans/hamerly_kmeans_impl.hpp b/src/mlpack/methods/kmeans/hamerly_kmeans_impl.hpp index 199287fb65..9d07c64ae5 100644 --- a/src/mlpack/methods/kmeans/hamerly_kmeans_impl.hpp +++ b/src/mlpack/methods/kmeans/hamerly_kmeans_impl.hpp @@ -17,20 +17,20 @@ namespace mlpack { -template -HamerlyKMeans::HamerlyKMeans(const MatType& dataset, - MetricType& metric) : +template +HamerlyKMeans::HamerlyKMeans(const MatType& dataset, + DistanceType& distance) : dataset(dataset), - metric(metric), + distance(distance), distanceCalculations(0) { // Nothing to do. } -template -double HamerlyKMeans::Iterate(const arma::mat& centroids, - arma::mat& newCentroids, - arma::Col& counts) +template +double HamerlyKMeans::Iterate(const arma::mat& centroids, + arma::mat& newCentroids, + arma::Col& counts) { size_t hamerlyPruned = 0; @@ -54,8 +54,8 @@ double HamerlyKMeans::Iterate(const arma::mat& centroids, { for (size_t j = i + 1; j < centroids.n_cols; ++j) { - const double dist = metric.Evaluate(centroids.col(i), centroids.col(j)) / - 2.0; + const double dist = distance.Evaluate(centroids.col(i), + centroids.col(j)) / 2.0; ++distanceCalculations; // Update bounds, if this intra-cluster distance is smaller. @@ -81,8 +81,8 @@ double HamerlyKMeans::Iterate(const arma::mat& centroids, } // Tighten upper bound. - upperBounds(i) = metric.Evaluate(dataset.col(i), - centroids.col(assignments[i])); + upperBounds(i) = distance.Evaluate(dataset.col(i), + centroids.col(assignments[i])); ++distanceCalculations; // Second bound test. @@ -102,7 +102,7 @@ double HamerlyKMeans::Iterate(const arma::mat& centroids, if (c == assignments[i]) continue; - const double dist = metric.Evaluate(dataset.col(i), centroids.col(c)); + const double dist = distance.Evaluate(dataset.col(i), centroids.col(c)); // Is this a better cluster? At this point, upperBounds[i] = d(i, c(i)). if (dist < upperBounds(i)) @@ -138,8 +138,8 @@ double HamerlyKMeans::Iterate(const arma::mat& centroids, newCentroids.col(c) /= counts(c); // Calculate movement. - const double movement = metric.Evaluate(centroids.col(c), - newCentroids.col(c)); + const double movement = distance.Evaluate(centroids.col(c), + newCentroids.col(c)); centroidMovements(c) = movement; centroidMovement += std::pow(movement, 2.0); ++distanceCalculations; diff --git a/src/mlpack/methods/kmeans/kill_empty_clusters.hpp b/src/mlpack/methods/kmeans/kill_empty_clusters.hpp index 4c5d2de16d..375be190cd 100644 --- a/src/mlpack/methods/kmeans/kill_empty_clusters.hpp +++ b/src/mlpack/methods/kmeans/kill_empty_clusters.hpp @@ -39,19 +39,19 @@ class KillEmptyClusters * @param newCentroids Centroids of each cluster (one per column) at the end * of the iteration. * @param clusterCounts Number of points in each cluster. - * @param * (metric) The Metric to use. + * @param * (distance) The distance metric to use. * @param * (iteration) Number of iteration. * * @return Number of points changed (0). */ - template + template static inline mlpack_force_inline void EmptyCluster( const MatType& /* data */, const size_t emptyCluster, const arma::mat& /* oldCentroids */, arma::mat& newCentroids, arma::Col& clusterCounts, - MetricType& /* metric */, + DistanceType& /* distance */, const size_t /* iteration */) { // Remove the empty cluster. diff --git a/src/mlpack/methods/kmeans/kmeans.hpp b/src/mlpack/methods/kmeans/kmeans.hpp index 5f403257a5..104d2a6bde 100644 --- a/src/mlpack/methods/kmeans/kmeans.hpp +++ b/src/mlpack/methods/kmeans/kmeans.hpp @@ -58,7 +58,7 @@ namespace mlpack { * k.Cluster(data, 6, centroids); // 6 clusters. * @endcode * - * @tparam MetricType The distance metric to use for this KMeans; see LMetric + * @tparam DistanceType The distance metric to use for this KMeans; see LMetric * for an example. * @tparam InitialPartitionPolicy Initial partitioning policy; must implement a * default constructor and either 'void Cluster(const arma::mat&, const @@ -67,14 +67,14 @@ namespace mlpack { * @tparam EmptyClusterPolicy Policy for what to do on an empty cluster; must * implement a default constructor and 'void EmptyCluster(const arma::mat& * data, const size_t emptyCluster, const arma::mat& oldCentroids, - * arma::mat& newCentroids, arma::Col& counts, MetricType& metric, - * const size_t iteration)'. + * arma::mat& newCentroids, arma::Col& counts, + * DistanceType& distance, const size_t iteration)'. * @tparam LloydStepType Implementation of single Lloyd step to use. * * @see RandomPartition, SampleInitialization, RefinedStart, AllowEmptyClusters, * MaxVarianceNewCluster, NaiveKMeans, ElkanKMeans */ -template class LloydStepType = NaiveKMeans, @@ -88,15 +88,15 @@ class KMeans * * @param maxIterations Maximum number of iterations allowed before giving up * (0 is valid, but the algorithm may never terminate). - * @param metric Optional MetricType object; for when the metric has state - * it needs to store. + * @param distance Optional DistanceType object; for when the distance metric + * has state it needs to store. * @param partitioner Optional InitialPartitionPolicy object; for when a * specially initialized partitioning policy is required. * @param emptyClusterAction Optional EmptyClusterPolicy object; for when a * specially initialized empty cluster policy is required. */ KMeans(const size_t maxIterations = 1000, - const MetricType metric = MetricType(), + const DistanceType distance = DistanceType(), const InitialPartitionPolicy partitioner = InitialPartitionPolicy(), const EmptyClusterPolicy emptyClusterAction = EmptyClusterPolicy()); @@ -170,9 +170,16 @@ class KMeans size_t& MaxIterations() { return maxIterations; } //! Get the distance metric. - const MetricType& Metric() const { return metric; } + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + const DistanceType& Metric() const { return distance; } //! Modify the distance metric. - MetricType& Metric() { return metric; } + [[deprecated("Will be removed in mlpack 5.0.0; use Distance()")]] + DistanceType& Metric() { return distance; } + + //! Get the distance metric. + const DistanceType& Distance() const { return distance; } + //! Modify the distance metric. + DistanceType& Distance() { return distance; } //! Get the initial partitioning policy. const InitialPartitionPolicy& Partitioner() const { return partitioner; } @@ -193,7 +200,7 @@ class KMeans //! Maximum number of iterations before giving up. size_t maxIterations; //! Instantiated distance metric. - MetricType metric; + DistanceType distance; //! Instantiated initial partitioning policy. InitialPartitionPolicy partitioner; //! Instantiated empty cluster policy. diff --git a/src/mlpack/methods/kmeans/kmeans_impl.hpp b/src/mlpack/methods/kmeans/kmeans_impl.hpp index e5346686ca..6093b3ca7d 100644 --- a/src/mlpack/methods/kmeans/kmeans_impl.hpp +++ b/src/mlpack/methods/kmeans/kmeans_impl.hpp @@ -12,7 +12,7 @@ */ #include "kmeans.hpp" -#include +#include #include #include @@ -81,23 +81,23 @@ bool GetInitialAssignmentsOrCentroids( /** * Construct the K-Means object. */ -template class LloydStepType, typename MatType> KMeans< - MetricType, + DistanceType, InitialPartitionPolicy, EmptyClusterPolicy, LloydStepType, MatType>:: KMeans(const size_t maxIterations, - const MetricType metric, + const DistanceType distance, const InitialPartitionPolicy partitioner, const EmptyClusterPolicy emptyClusterAction) : maxIterations(maxIterations), - metric(metric), + distance(distance), partitioner(partitioner), emptyClusterAction(emptyClusterAction) { @@ -110,13 +110,13 @@ KMeans(const size_t maxIterations, * centroids too. If this is properly inlined, there shouldn't be any * performance penalty whatsoever. */ -template class LloydStepType, typename MatType> inline void KMeans< - MetricType, + DistanceType, InitialPartitionPolicy, EmptyClusterPolicy, LloydStepType, @@ -134,13 +134,13 @@ Cluster(const MatType& data, * Perform k-means clustering on the data, returning a list of cluster * assignments and the centroids of each cluster. */ -template class LloydStepType, typename MatType> void KMeans< - MetricType, + DistanceType, InitialPartitionPolicy, EmptyClusterPolicy, LloydStepType, @@ -200,7 +200,7 @@ Cluster(const MatType& data, size_t iteration = 0; - LloydStepType lloydStep(data, metric); + LloydStepType lloydStep(data, distance); arma::mat centroidsOther; double cNorm; @@ -222,10 +222,10 @@ Cluster(const MatType& data, Log::Info << "Cluster " << i << " is empty.\n"; if (iteration % 2 == 0) emptyClusterAction.EmptyCluster(data, i, centroids, centroidsOther, - counts, metric, iteration); + counts, distance, iteration); else emptyClusterAction.EmptyCluster(data, i, centroidsOther, centroids, - counts, metric, iteration); + counts, distance, iteration); } } @@ -260,13 +260,13 @@ Cluster(const MatType& data, * Perform k-means clustering on the data, returning a list of cluster * assignments and the centroids of each cluster. */ -template class LloydStepType, typename MatType> void KMeans< - MetricType, + DistanceType, InitialPartitionPolicy, EmptyClusterPolicy, LloydStepType, @@ -313,11 +313,11 @@ Cluster(const MatType& data, for (size_t j = 0; j < centroids.n_cols; ++j) { - const double distance = metric.Evaluate(data.col(i), centroids.col(j)); + const double dist = distance.Evaluate(data.col(i), centroids.col(j)); - if (distance < minDistance) + if (dist < minDistance) { - minDistance = distance; + minDistance = dist; closestCluster = j; } } @@ -327,20 +327,20 @@ Cluster(const MatType& data, } } -template class LloydStepType, typename MatType> template -void KMeans::serialize(Archive& ar, const uint32_t /* version */) { ar(CEREAL_NVP(maxIterations)); - ar(CEREAL_NVP(metric)); + ar(CEREAL_NVP(distance)); ar(CEREAL_NVP(partitioner)); ar(CEREAL_NVP(emptyClusterAction)); } diff --git a/src/mlpack/methods/kmeans/max_variance_new_cluster.hpp b/src/mlpack/methods/kmeans/max_variance_new_cluster.hpp index daf422aedd..5a4aa833cb 100644 --- a/src/mlpack/methods/kmeans/max_variance_new_cluster.hpp +++ b/src/mlpack/methods/kmeans/max_variance_new_cluster.hpp @@ -40,17 +40,17 @@ class MaxVarianceNewCluster * @param newCentroids Centroids of each cluster (one per column) at the end * of the iteration. * @param clusterCounts Number of points in each cluster. - * @param metric The Metric to use. + * @param distance The distance metric to use. * @param iteration Number of iteration. * */ - template + template void EmptyCluster(const MatType& data, const size_t emptyCluster, const arma::mat& oldCentroids, arma::mat& newCentroids, arma::Col& clusterCounts, - MetricType& metric, + DistanceType& distance, const size_t iteration); //! Serialize the object. @@ -66,11 +66,11 @@ class MaxVarianceNewCluster arma::Row assignments; //! Called when we are on a new iteration. - template + template void Precalculate(const MatType& data, const arma::mat& oldCentroids, arma::Col& clusterCounts, - MetricType& metric); + DistanceType& distance); }; } // namespace mlpack diff --git a/src/mlpack/methods/kmeans/max_variance_new_cluster_impl.hpp b/src/mlpack/methods/kmeans/max_variance_new_cluster_impl.hpp index 4f3a7fbdb7..c3a86845c5 100644 --- a/src/mlpack/methods/kmeans/max_variance_new_cluster_impl.hpp +++ b/src/mlpack/methods/kmeans/max_variance_new_cluster_impl.hpp @@ -20,18 +20,18 @@ namespace mlpack { /** * Take action about an empty cluster. */ -template +template void MaxVarianceNewCluster::EmptyCluster(const MatType& data, const size_t emptyCluster, const arma::mat& oldCentroids, arma::mat& newCentroids, arma::Col& clusterCounts, - MetricType& metric, + DistanceType& distance, const size_t iteration) { // If necessary, calculate the variances and assignments. if (iteration != this->iteration || assignments.n_elem != data.n_cols) - Precalculate(data, oldCentroids, clusterCounts, metric); + Precalculate(data, oldCentroids, clusterCounts, distance); this->iteration = iteration; // Now find the cluster with maximum variance. @@ -50,12 +50,12 @@ void MaxVarianceNewCluster::EmptyCluster(const MatType& data, { if (assignments[i] == maxVarCluster) { - const double distance = std::pow(metric.Evaluate(data.col(i), + const double dist = std::pow(distance.Evaluate(data.col(i), newCentroids.col(maxVarCluster)), 2.0); - if (distance > maxDistance) + if (dist > maxDistance) { - maxDistance = distance; + maxDistance = dist; furthestPoint = i; } } @@ -110,11 +110,11 @@ void MaxVarianceNewCluster::serialize(Archive& /* ar */, assignments.set_size(0); } -template +template void MaxVarianceNewCluster::Precalculate(const MatType& data, const arma::mat& oldCentroids, arma::Col& clusterCounts, - MetricType& metric) + DistanceType& distance) { // We have to calculate the variances of each cluster and the assignments of // each point. This is most easily done by iterating through the entire @@ -132,17 +132,17 @@ void MaxVarianceNewCluster::Precalculate(const MatType& data, for (size_t j = 0; j < oldCentroids.n_cols; ++j) { - const double distance = metric.Evaluate(data.col(i), oldCentroids.col(j)); + const double dist = distance.Evaluate(data.col(i), oldCentroids.col(j)); - if (distance < minDistance) + if (dist < minDistance) { - minDistance = distance; + minDistance = dist; closestCluster = j; } } assignments[i] = closestCluster; - variances[closestCluster] += std::pow(metric.Evaluate(data.col(i), + variances[closestCluster] += std::pow(distance.Evaluate(data.col(i), oldCentroids.col(closestCluster)), 2.0); } diff --git a/src/mlpack/methods/kmeans/naive_kmeans.hpp b/src/mlpack/methods/kmeans/naive_kmeans.hpp index 264adc465a..86a6f15921 100644 --- a/src/mlpack/methods/kmeans/naive_kmeans.hpp +++ b/src/mlpack/methods/kmeans/naive_kmeans.hpp @@ -25,20 +25,21 @@ namespace mlpack { * looking for the KMeans class instead of this one. This class is used by * KMeans as the actual implementation of the Lloyd iteration. * - * @param MetricType Type of metric used with this implementation. + * @param DistanceType Type of distance metric used with this implementation. * @param MatType Matrix type (arma::mat or arma::sp_mat). */ -template +template class NaiveKMeans { public: /** - * Construct the NaiveKMeans object with the given dataset and metric. + * Construct the NaiveKMeans object with the given dataset and distance + * metric. * * @param dataset Dataset. - * @param metric Instantiated metric. + * @param distance Instantiated distance metric. */ - NaiveKMeans(const MatType& dataset, MetricType& metric); + NaiveKMeans(const MatType& dataset, DistanceType& distance); /** * Run a single iteration of the Lloyd algorithm, updating the given centroids @@ -59,8 +60,8 @@ class NaiveKMeans private: //! The dataset. const MatType& dataset; - //! The instantiated metric. - MetricType& metric; + //! The instantiated distance metric. + DistanceType& distance; //! Number of distance calculations. size_t distanceCalculations; diff --git a/src/mlpack/methods/kmeans/naive_kmeans_impl.hpp b/src/mlpack/methods/kmeans/naive_kmeans_impl.hpp index 9636e2bd9d..17a9ff58bd 100644 --- a/src/mlpack/methods/kmeans/naive_kmeans_impl.hpp +++ b/src/mlpack/methods/kmeans/naive_kmeans_impl.hpp @@ -21,19 +21,19 @@ namespace mlpack { -template -NaiveKMeans::NaiveKMeans(const MatType& dataset, - MetricType& metric) : +template +NaiveKMeans::NaiveKMeans(const MatType& dataset, + DistanceType& distance) : dataset(dataset), - metric(metric), + distance(distance), distanceCalculations(0) { /* Nothing to do. */ } // Run a single iteration. -template -double NaiveKMeans::Iterate(const arma::mat& centroids, - arma::mat& newCentroids, - arma::Col& counts) +template +double NaiveKMeans::Iterate(const arma::mat& centroids, + arma::mat& newCentroids, + arma::Col& counts) { newCentroids.zeros(centroids.n_rows, centroids.n_cols); counts.zeros(centroids.n_cols); @@ -56,11 +56,11 @@ double NaiveKMeans::Iterate(const arma::mat& centroids, for (size_t j = 0; j < centroids.n_cols; ++j) { - const double distance = metric.Evaluate(dataset.col(i), + const double dist = distance.Evaluate(dataset.col(i), centroids.unsafe_col(j)); - if (distance < minDistance) + if (dist < minDistance) { - minDistance = distance; + minDistance = dist; closestCluster = j; } } @@ -90,7 +90,7 @@ double NaiveKMeans::Iterate(const arma::mat& centroids, double cNorm = 0.0; for (size_t i = 0; i < centroids.n_cols; ++i) { - cNorm += std::pow(metric.Evaluate(centroids.col(i), newCentroids.col(i)), + cNorm += std::pow(distance.Evaluate(centroids.col(i), newCentroids.col(i)), 2.0); } distanceCalculations += centroids.n_cols; diff --git a/src/mlpack/methods/kmeans/pelleg_moore_kmeans.hpp b/src/mlpack/methods/kmeans/pelleg_moore_kmeans.hpp index 20bfda990b..e7e4f9e444 100644 --- a/src/mlpack/methods/kmeans/pelleg_moore_kmeans.hpp +++ b/src/mlpack/methods/kmeans/pelleg_moore_kmeans.hpp @@ -37,14 +37,14 @@ namespace mlpack { * } * @endcode */ -template +template class PellegMooreKMeans { public: /** * Construct the PellegMooreKMeans object, which must construct a tree. */ - PellegMooreKMeans(const MatType& dataset, MetricType& metric); + PellegMooreKMeans(const MatType& dataset, DistanceType& distance); /** * Delete the tree constructed by the PellegMooreKMeans object. @@ -69,7 +69,7 @@ class PellegMooreKMeans size_t& DistanceCalculations() { return distanceCalculations; } //! Convenience typedef for the tree. - typedef KDTree TreeType; + typedef KDTree TreeType; private: //! The original dataset reference. @@ -78,8 +78,8 @@ class PellegMooreKMeans TreeType* tree; //! The dataset we are using. const MatType& dataset; - //! The metric. - MetricType& metric; + //! The distance metric. + DistanceType& distance; //! Track distance calculations. size_t distanceCalculations; diff --git a/src/mlpack/methods/kmeans/pelleg_moore_kmeans_impl.hpp b/src/mlpack/methods/kmeans/pelleg_moore_kmeans_impl.hpp index dfc8480fb1..b28fc214cd 100644 --- a/src/mlpack/methods/kmeans/pelleg_moore_kmeans_impl.hpp +++ b/src/mlpack/methods/kmeans/pelleg_moore_kmeans_impl.hpp @@ -18,29 +18,29 @@ namespace mlpack { -template -PellegMooreKMeans::PellegMooreKMeans( +template +PellegMooreKMeans::PellegMooreKMeans( const MatType& dataset, - MetricType& metric) : + DistanceType& distance) : datasetOrig(dataset), tree(new TreeType(const_cast(datasetOrig))), dataset(tree->Dataset()), - metric(metric), + distance(distance), distanceCalculations(0) { // Nothing to do. } -template -PellegMooreKMeans::~PellegMooreKMeans() +template +PellegMooreKMeans::~PellegMooreKMeans() { if (tree) delete tree; } // Run a single iteration. -template -double PellegMooreKMeans::Iterate( +template +double PellegMooreKMeans::Iterate( const arma::mat& centroids, arma::mat& newCentroids, arma::Col& counts) @@ -49,8 +49,8 @@ double PellegMooreKMeans::Iterate( counts.zeros(centroids.n_cols); // Create rules object. - typedef PellegMooreKMeansRules RulesType; - RulesType rules(dataset, centroids, newCentroids, counts, metric); + typedef PellegMooreKMeansRules RulesType; + RulesType rules(dataset, centroids, newCentroids, counts, distance); // Use single-tree traverser. typename TreeType::template SingleTreeTraverser traverser(rules); @@ -68,8 +68,8 @@ double PellegMooreKMeans::Iterate( if (counts[c] > 0) { newCentroids.col(c) /= counts(c); - residual += std::pow(metric.Evaluate(centroids.col(c), - newCentroids.col(c)), 2.0); + residual += std::pow(distance.Evaluate(centroids.col(c), + newCentroids.col(c)), 2.0); } } distanceCalculations += centroids.n_cols; diff --git a/src/mlpack/methods/kmeans/pelleg_moore_kmeans_rules.hpp b/src/mlpack/methods/kmeans/pelleg_moore_kmeans_rules.hpp index 5f959952d1..02375d7525 100644 --- a/src/mlpack/methods/kmeans/pelleg_moore_kmeans_rules.hpp +++ b/src/mlpack/methods/kmeans/pelleg_moore_kmeans_rules.hpp @@ -28,7 +28,7 @@ namespace mlpack { * this case we consider all clusters at once---so the query point is entirely * ignored during in BaseCase() and Score(). */ -template +template class PellegMooreKMeansRules { public: @@ -40,13 +40,13 @@ class PellegMooreKMeansRules * @param newCentroids New centroids after this iteration (output). * @param counts Current cluster counts, to be replaced with new cluster * counts. - * @param metric Instantiated metric. + * @param distance Instantiated distance metric. */ PellegMooreKMeansRules(const typename TreeType::Mat& dataset, const arma::mat& centroids, arma::mat& newCentroids, arma::Col& counts, - MetricType& metric); + DistanceType& distance); /** * The BaseCase() function for this single-tree algorithm does nothing. @@ -93,8 +93,8 @@ class PellegMooreKMeansRules arma::mat& newCentroids; //! The counts of points in each cluster. arma::Col& counts; - //! Instantiated metric. - MetricType& metric; + //! Instantiated distance metric. + DistanceType& distance; //! The number of O(d) distance calculations that have been performed. size_t distanceCalculations; diff --git a/src/mlpack/methods/kmeans/pelleg_moore_kmeans_rules_impl.hpp b/src/mlpack/methods/kmeans/pelleg_moore_kmeans_rules_impl.hpp index eef43e53f5..8cb0939002 100644 --- a/src/mlpack/methods/kmeans/pelleg_moore_kmeans_rules_impl.hpp +++ b/src/mlpack/methods/kmeans/pelleg_moore_kmeans_rules_impl.hpp @@ -19,34 +19,34 @@ namespace mlpack { -template -PellegMooreKMeansRules::PellegMooreKMeansRules( +template +PellegMooreKMeansRules::PellegMooreKMeansRules( const typename TreeType::Mat& dataset, const arma::mat& centroids, arma::mat& newCentroids, arma::Col& counts, - MetricType& metric) : + DistanceType& distance) : dataset(dataset), centroids(centroids), newCentroids(newCentroids), counts(counts), - metric(metric), + distance(distance), distanceCalculations(0) { // Nothing to do. } -template +template inline mlpack_force_inline -double PellegMooreKMeansRules::BaseCase( +double PellegMooreKMeansRules::BaseCase( const size_t /* queryIndex */, const size_t /* referenceIndex */) { return 0.0; } -template -double PellegMooreKMeansRules::Score( +template +double PellegMooreKMeansRules::Score( const size_t /* queryIndex */, TreeType& referenceNode) { @@ -107,9 +107,9 @@ double PellegMooreKMeansRules::Score( cornerPoint(d) = referenceNode.Bound()[d].Lo(); } - const double closestDist = metric.Evaluate(cornerPoint, + const double closestDist = distance.Evaluate(cornerPoint, centroids.col(closestCluster)); - const double otherDist = metric.Evaluate(cornerPoint, centroids.col(c)); + const double otherDist = distance.Evaluate(cornerPoint, centroids.col(c)); distanceCalculations += 3; // One for cornerPoint, then two distances. @@ -145,12 +145,12 @@ double PellegMooreKMeansRules::Score( ++distanceCalculations; // The reference index is the index of the data point. - const double distance = metric.Evaluate(centroids.col(c), + const double dist = distance.Evaluate(centroids.col(c), dataset.col(referenceNode.Point(i))); - if (distance < bestDistance) + if (dist < bestDistance) { - bestDistance = distance; + bestDistance = dist; bestCluster = c; } } @@ -165,8 +165,8 @@ double PellegMooreKMeansRules::Score( return 0.0; } -template -double PellegMooreKMeansRules::Rescore( +template +double PellegMooreKMeansRules::Rescore( const size_t /* queryIndex */, TreeType& /* referenceNode */, const double oldScore) diff --git a/src/mlpack/methods/lmnn/constraints.hpp b/src/mlpack/methods/lmnn/constraints.hpp index 56d8c824c6..082b8961ed 100644 --- a/src/mlpack/methods/lmnn/constraints.hpp +++ b/src/mlpack/methods/lmnn/constraints.hpp @@ -27,12 +27,12 @@ namespace mlpack { * data point) and Triplets() (Generates sets of {dataset, target neighbors, * impostors} tripltets.) */ -template +template class Constraints { public: //! Convenience typedef. - typedef NeighborSearch KNN; + typedef NeighborSearch KNN; /** * Constructor for creating a Constraints instance. diff --git a/src/mlpack/methods/lmnn/constraints_impl.hpp b/src/mlpack/methods/lmnn/constraints_impl.hpp index 3469884572..6aaa36219b 100644 --- a/src/mlpack/methods/lmnn/constraints_impl.hpp +++ b/src/mlpack/methods/lmnn/constraints_impl.hpp @@ -17,8 +17,8 @@ namespace mlpack { -template -Constraints::Constraints( +template +Constraints::Constraints( const arma::mat& /* dataset */, const arma::Row& labels, const size_t k) : @@ -36,8 +36,8 @@ Constraints::Constraints( } } -template -inline void Constraints::ReorderResults( +template +inline void Constraints::ReorderResults( const arma::mat& distances, arma::Mat& neighbors, const arma::vec& norms) @@ -77,8 +77,8 @@ inline void Constraints::ReorderResults( } // Calculates k similar labeled nearest neighbors. -template -void Constraints::TargetNeighbors(arma::Mat& outputMatrix, +template +void Constraints::TargetNeighbors(arma::Mat& outputMatrix, const arma::mat& dataset, const arma::Row& labels, const arma::vec& norms) @@ -114,8 +114,8 @@ void Constraints::TargetNeighbors(arma::Mat& outputMatrix, // Calculates k similar labeled nearest neighbors on a // batch of data points. -template -void Constraints::TargetNeighbors(arma::Mat& outputMatrix, +template +void Constraints::TargetNeighbors(arma::Mat& outputMatrix, const arma::mat& dataset, const arma::Row& labels, const arma::vec& norms, @@ -161,8 +161,8 @@ void Constraints::TargetNeighbors(arma::Mat& outputMatrix, } // Calculates k differently labeled nearest neighbors. -template -void Constraints::Impostors(arma::Mat& outputMatrix, +template +void Constraints::Impostors(arma::Mat& outputMatrix, const arma::mat& dataset, const arma::Row& labels, const arma::vec& norms) @@ -198,8 +198,8 @@ void Constraints::Impostors(arma::Mat& outputMatrix, // Calculates k differently labeled nearest neighbors. The function // writes back calculated neighbors & distances to passed matrices. -template -void Constraints::Impostors(arma::Mat& outputNeighbors, +template +void Constraints::Impostors(arma::Mat& outputNeighbors, arma::mat& outputDistance, const arma::mat& dataset, const arma::Row& labels, @@ -237,8 +237,8 @@ void Constraints::Impostors(arma::Mat& outputNeighbors, // Calculates k differently labeled nearest neighbors on a // batch of data points. -template -void Constraints::Impostors(arma::Mat& outputMatrix, +template +void Constraints::Impostors(arma::Mat& outputMatrix, const arma::mat& dataset, const arma::Row& labels, const arma::vec& norms, @@ -285,8 +285,8 @@ void Constraints::Impostors(arma::Mat& outputMatrix, // Calculates k differently labeled nearest neighbors & distances on a // batch of data points. -template -void Constraints::Impostors(arma::Mat& outputNeighbors, +template +void Constraints::Impostors(arma::Mat& outputNeighbors, arma::mat& outputDistance, const arma::mat& dataset, const arma::Row& labels, @@ -335,8 +335,8 @@ void Constraints::Impostors(arma::Mat& outputNeighbors, // Calculates k differently labeled nearest neighbors & distances over some // data points. -template -void Constraints::Impostors(arma::Mat& outputNeighbors, +template +void Constraints::Impostors(arma::Mat& outputNeighbors, arma::mat& outputDistance, const arma::mat& dataset, const arma::Row& labels, @@ -384,8 +384,8 @@ void Constraints::Impostors(arma::Mat& outputNeighbors, // Generates {data point, target neighbors, impostors} triplets using // TargetNeighbors() and Impostors(). -template -void Constraints::Triplets(arma::Mat& outputMatrix, +template +void Constraints::Triplets(arma::Mat& outputMatrix, const arma::mat& dataset, const arma::Row& labels, const arma::vec& norms) @@ -418,8 +418,8 @@ void Constraints::Triplets(arma::Mat& outputMatrix, } } -template -inline void Constraints::Precalculate( +template +inline void Constraints::Precalculate( const arma::Row& labels) { // Make sure the calculation is necessary. diff --git a/src/mlpack/methods/lmnn/lmnn.hpp b/src/mlpack/methods/lmnn/lmnn.hpp index 0aec0f3570..cc9f2e9d84 100644 --- a/src/mlpack/methods/lmnn/lmnn.hpp +++ b/src/mlpack/methods/lmnn/lmnn.hpp @@ -45,10 +45,10 @@ namespace mlpack { * } * @endcode * - * @tparam MetricType The type of metric to use for computation. + * @tparam DistanceType The type of distance metric to use for computation. * @tparam OptimizerType Optimizer to use for developing distance. */ -template class LMNN { @@ -61,12 +61,12 @@ class LMNN * @param dataset Input dataset. * @param labels Input dataset labels. * @param k Number of targets to consider. - * @param metric Type of metric used for computation. + * @param distance Type of distance metric used for computation. */ LMNN(const arma::mat& dataset, const arma::Row& labels, const size_t k, - const MetricType metric = MetricType()); + const DistanceType distance = DistanceType()); /** @@ -126,7 +126,7 @@ class LMNN size_t range; //! Metric to be used. - MetricType metric; + DistanceType distance; //! The optimizer to use. OptimizerType optimizer; diff --git a/src/mlpack/methods/lmnn/lmnn_function.hpp b/src/mlpack/methods/lmnn/lmnn_function.hpp index 441c186ef3..f35fcf8cd0 100644 --- a/src/mlpack/methods/lmnn/lmnn_function.hpp +++ b/src/mlpack/methods/lmnn/lmnn_function.hpp @@ -14,7 +14,7 @@ #define MLPACK_METHODS_LMNN_FUNCTION_HPP #include -#include +#include #include "constraints.hpp" @@ -32,16 +32,16 @@ namespace mlpack { * where x_n represents a point and A is the current scaling matrix. * * This class is more flexible than the original paper, allowing an arbitrary - * metric function to be used in place of || A x_i - A x_j ||^2, meaning that - * the squared Euclidean distance is not the only allowed metric for LMNN. - * However, that is probably the best way to use this class. + * distance metric function to be used in place of || A x_i - A x_j ||^2, + * meaning that the squared Euclidean distance is not the only allowed metric + * for LMNN. However, that is probably the best way to use this class. * * In addition to the standard Evaluate() and Gradient() functions which mlpack * optimizers use, overloads of Evaluate() and Gradient() are given which only * operate on one point in the dataset. This is useful for optimizers like * stochastic gradient descent (see ens::SGD). */ -template +template class LMNNFunction { public: @@ -53,14 +53,14 @@ class LMNNFunction * @param k Number of target neighbors to be used. * @param regularization Regularization value. * @param range Range after which impostors need to be recalculated. - * @param metric Type of metric used for computation. + * @param distance Type of distance metric used for computation. */ LMNNFunction(const arma::mat& dataset, const arma::Row& labels, size_t k, double regularization, size_t range, - MetricType metric = MetricType()); + DistanceType distance = DistanceType()); /** @@ -202,11 +202,11 @@ class LMNNFunction //! Initial impostors. arma::Mat impostors; //! Cache distance. Used to avoid repetive calculation. - arma::mat distance; + arma::mat distanceMat; //! Number of target neighbors. size_t k; - //! The instantiated metric. - MetricType metric; + //! The instantiated distance metric. + DistanceType distance; //! Regularization value. double regularization; //! Keep iterations count. @@ -214,7 +214,7 @@ class LMNNFunction //! Range after which impostors need to be recalculated. size_t range; //! Constraints Object. - Constraints constraint; + Constraints constraint; //! Holds pre-calculated cij. arma::mat pCij; //! Holds the norm of each data point. diff --git a/src/mlpack/methods/lmnn/lmnn_function_impl.hpp b/src/mlpack/methods/lmnn/lmnn_function_impl.hpp index 38f0d95e95..52228691f3 100644 --- a/src/mlpack/methods/lmnn/lmnn_function_impl.hpp +++ b/src/mlpack/methods/lmnn/lmnn_function_impl.hpp @@ -18,15 +18,15 @@ namespace mlpack { -template -LMNNFunction::LMNNFunction(const arma::mat& datasetIn, +template +LMNNFunction::LMNNFunction(const arma::mat& datasetIn, const arma::Row& labelsIn, size_t k, double regularization, size_t range, - MetricType metric) : + DistanceType distance) : k(k), - metric(metric), + distance(distance), regularization(regularization), iteration(0), range(range), @@ -71,7 +71,7 @@ LMNNFunction::LMNNFunction(const arma::mat& datasetIn, // Initialize target neighbors & impostors. targetNeighbors.set_size(k, dataset.n_cols); impostors.set_size(k, dataset.n_cols); - distance.set_size(k, dataset.n_cols); + distanceMat.set_size(k, dataset.n_cols); } else { @@ -81,7 +81,7 @@ LMNNFunction::LMNNFunction(const arma::mat& datasetIn, // Initialize target neighbors & impostors. targetNeighbors.set_size(k + 1, dataset.n_cols); impostors.set_size(k + 1, dataset.n_cols); - distance.set_size(k + 1, dataset.n_cols); + distanceMat.set_size(k + 1, dataset.n_cols); } constraint.TargetNeighbors(targetNeighbors, dataset, labels, norm); @@ -92,8 +92,8 @@ LMNNFunction::LMNNFunction(const arma::mat& datasetIn, } //! Shuffle the dataset. -template -void LMNNFunction::Shuffle() +template +void LMNNFunction::Shuffle() { arma::mat newDataset = dataset; arma::Mat newLabels = labels; @@ -126,8 +126,8 @@ void LMNNFunction::Shuffle() } // Update cache transformation matrices. -template -inline void LMNNFunction::UpdateCache( +template +inline void LMNNFunction::UpdateCache( const arma::mat& transformation, const size_t begin, const size_t batchSize) @@ -183,8 +183,8 @@ inline void LMNNFunction::UpdateCache( } // Calculate norm of change in transformation. -template -inline void LMNNFunction::TransDiff( +template +inline void LMNNFunction::TransDiff( std::map& transformationDiffs, const arma::mat& transformation, const size_t begin, @@ -209,12 +209,12 @@ inline void LMNNFunction::TransDiff( } //! Evaluate cost over whole dataset. -template -double LMNNFunction::Evaluate(const arma::mat& transformation) +template +double LMNNFunction::Evaluate(const arma::mat& transformation) { double cost = 0; - // Apply metric over dataset. + // Apply distance metric over dataset. transformedDataset = transformation * dataset; double transformationDiff = 0; @@ -234,27 +234,28 @@ double LMNNFunction::Evaluate(const arma::mat& transformation) for (size_t i = 0; i < dataset.n_cols; ++i) { if (transformationDiff * (2 * norm(i) + norm(impostors(k - 1, i)) + - norm(impostors(k, i))) > distance(k, i) - distance(k - 1, i)) + norm(impostors(k, i))) > distanceMat(k, i) - distanceMat(k - 1, i)) { points(numPoints++) = i; } } // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm, points, numPoints); } else { // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, transformedDataset, labels, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm); } } else if (iteration++ % range == 0) { // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, transformedDataset, labels, norm); + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, + norm); } for (size_t i = 0; i < dataset.n_cols; ++i) @@ -262,7 +263,7 @@ double LMNNFunction::Evaluate(const arma::mat& transformation) for (size_t j = 0; j < k ; ++j) { // Calculate cost due to distance between target neighbors & data point. - double eval = metric.Evaluate(transformedDataset.col(i), + double eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))); cost += (1 - regularization) * eval; } @@ -293,15 +294,15 @@ double LMNNFunction::Evaluate(const arma::mat& transformation) { if (iteration - 1 % range == 0) { - eval = metric.Evaluate(transformedDataset.col(i), + eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))) - - distance(l, i); + distanceMat(l, i); } else { - eval = metric.Evaluate(transformedDataset.col(i), + eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))) - - metric.Evaluate(transformedDataset.col(i), + distance.Evaluate(transformedDataset.col(i), transformedDataset.col(impostors(l, i))); } } @@ -337,8 +338,8 @@ double LMNNFunction::Evaluate(const arma::mat& transformation) } //! Calculate cost over batches. -template -double LMNNFunction::Evaluate(const arma::mat& transformation, +template +double LMNNFunction::Evaluate(const arma::mat& transformation, const size_t begin, const size_t batchSize) { @@ -348,7 +349,7 @@ double LMNNFunction::Evaluate(const arma::mat& transformation, std::map transformationDiffs; TransDiff(transformationDiffs, transformation, begin, batchSize); - // Apply metric over dataset. + // Apply distance metric over dataset. transformedDataset = transformation * dataset; if (impBounds && iteration++ % range == 0) @@ -362,7 +363,7 @@ double LMNNFunction::Evaluate(const arma::mat& transformation, { if (transformationDiffs[lastTransformationIndices[i]] * (2 * norm(i) + norm(impostors(k - 1, i)) + - norm(impostors(k, i))) > distance(k, i) - distance(k - 1, i)) + norm(impostors(k, i))) > distanceMat(k, i) - distanceMat(k - 1, i)) { points(numPoints++) = i; } @@ -374,13 +375,13 @@ double LMNNFunction::Evaluate(const arma::mat& transformation, } // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm, points, numPoints); } else if (iteration++ % range == 0) { // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, transformedDataset, labels, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm, begin, batchSize); } @@ -389,7 +390,7 @@ double LMNNFunction::Evaluate(const arma::mat& transformation, for (size_t j = 0; j < k ; ++j) { // Calculate cost due to distance between target neighbors & data point. - double eval = metric.Evaluate(transformedDataset.col(i), + double eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))); cost += (1 - regularization) * eval; } @@ -420,15 +421,15 @@ double LMNNFunction::Evaluate(const arma::mat& transformation, { if (iteration - 1 % range == 0) { - eval = metric.Evaluate(transformedDataset.col(i), + eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))) - - distance(l, i); + distanceMat(l, i); } else { - eval = metric.Evaluate(transformedDataset.col(i), + eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))) - - metric.Evaluate(transformedDataset.col(i), + distance.Evaluate(transformedDataset.col(i), transformedDataset.col(impostors(l, i))); } } @@ -466,12 +467,12 @@ double LMNNFunction::Evaluate(const arma::mat& transformation, } //! Compute gradient over whole dataset. -template +template template -void LMNNFunction::Gradient(const arma::mat& transformation, +void LMNNFunction::Gradient(const arma::mat& transformation, GradType& gradient) { - // Apply metric over dataset. + // Apply distance metric over dataset. transformedDataset = transformation * dataset; double transformationDiff = 0; @@ -488,27 +489,27 @@ void LMNNFunction::Gradient(const arma::mat& transformation, for (size_t i = 0; i < dataset.n_cols; ++i) { if (transformationDiff * (2 * norm(i) + norm(impostors(k - 1, i)) + - norm(impostors(k, i))) > distance(k, i) - distance(k - 1, i)) + norm(impostors(k, i))) > distanceMat(k, i) - distanceMat(k - 1, i)) { points(numPoints++) = i; } } // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm, points, numPoints); } else { // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, transformedDataset, labels, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm); } } else if (iteration++ % range == 0) { // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, transformedDataset, labels, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm); } @@ -547,15 +548,15 @@ void LMNNFunction::Gradient(const arma::mat& transformation, { if (iteration - 1 % range == 0) { - eval = metric.Evaluate(transformedDataset.col(i), + eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))) - - distance(l, i); + distanceMat(l, i); } else { - eval = metric.Evaluate(transformedDataset.col(i), + eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))) - - metric.Evaluate(transformedDataset.col(i), + distance.Evaluate(transformedDataset.col(i), transformedDataset.col(impostors(l, i))); } } @@ -597,14 +598,14 @@ void LMNNFunction::Gradient(const arma::mat& transformation, } //! Compute gradient over a batch of data points. -template +template template -void LMNNFunction::Gradient(const arma::mat& transformation, +void LMNNFunction::Gradient(const arma::mat& transformation, const size_t begin, GradType& gradient, const size_t batchSize) { - // Apply metric over dataset. + // Apply distance metric over dataset. transformedDataset = transformation * dataset; // Calculate norm of change in transformation. @@ -622,7 +623,7 @@ void LMNNFunction::Gradient(const arma::mat& transformation, { if (transformationDiffs[lastTransformationIndices[i]] * (2 * norm(i) + norm(impostors(k - 1, i)) + - norm(impostors(k, i))) > distance(k, i) - distance(k - 1, i)) + norm(impostors(k, i))) > distanceMat(k, i) - distanceMat(k - 1, i)) { points(numPoints++) = i; } @@ -634,13 +635,13 @@ void LMNNFunction::Gradient(const arma::mat& transformation, } // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm, points, numPoints); } else if (iteration++ % range == 0) { // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, transformedDataset, labels, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm, begin, batchSize); } @@ -683,15 +684,15 @@ void LMNNFunction::Gradient(const arma::mat& transformation, { if (iteration - 1 % range == 0) { - eval = metric.Evaluate(transformedDataset.col(i), + eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))) - - distance(l, i); + distanceMat(l, i); } else { - eval = metric.Evaluate(transformedDataset.col(i), + eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))) - - metric.Evaluate(transformedDataset.col(i), + distance.Evaluate(transformedDataset.col(i), transformedDataset.col(impostors(l, i))); } } @@ -735,15 +736,15 @@ void LMNNFunction::Gradient(const arma::mat& transformation, } //! Compute cost & gradient over whole dataset. -template +template template -double LMNNFunction::EvaluateWithGradient( +double LMNNFunction::EvaluateWithGradient( const arma::mat& transformation, GradType& gradient) { double cost = 0; - // Apply metric over dataset. + // Apply distance metric over dataset. transformedDataset = transformation * dataset; double transformationDiff = 0; @@ -763,27 +764,27 @@ double LMNNFunction::EvaluateWithGradient( for (size_t i = 0; i < dataset.n_cols; ++i) { if (transformationDiff * (2 * norm(i) + norm(impostors(k - 1, i)) + - norm(impostors(k, i))) > distance(k, i) - distance(k - 1, i)) + norm(impostors(k, i))) > distanceMat(k, i) - distanceMat(k - 1, i)) { points(numPoints++) = i; } } // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm, points, numPoints); } else { // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, transformedDataset, labels, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm); } } else if (iteration++ % range == 0) { // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, transformedDataset, labels, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm); } @@ -800,7 +801,7 @@ double LMNNFunction::EvaluateWithGradient( for (size_t j = 0; j < k ; ++j) { // Calculate cost due to distance between target neighbors & data point. - double eval = metric.Evaluate(transformedDataset.col(i), + double eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))); cost += (1 - regularization) * eval; } @@ -830,15 +831,15 @@ double LMNNFunction::EvaluateWithGradient( { if (iteration - 1 % range == 0) { - eval = metric.Evaluate(transformedDataset.col(i), + eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))) - - distance(l, i); + distanceMat(l, i); } else { - eval = metric.Evaluate(transformedDataset.col(i), + eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))) - - metric.Evaluate(transformedDataset.col(i), + distance.Evaluate(transformedDataset.col(i), transformedDataset.col(impostors(l, i))); } } @@ -876,9 +877,9 @@ double LMNNFunction::EvaluateWithGradient( } //! Compute cost & gradient over a batch of data points. -template +template template -double LMNNFunction::EvaluateWithGradient( +double LMNNFunction::EvaluateWithGradient( const arma::mat& transformation, const size_t begin, GradType& gradient, @@ -890,7 +891,7 @@ double LMNNFunction::EvaluateWithGradient( std::map transformationDiffs; TransDiff(transformationDiffs, transformation, begin, batchSize); - // Apply metric over dataset. + // Apply distance metric over dataset. transformedDataset = transformation * dataset; if (impBounds && iteration++ % range == 0) @@ -904,7 +905,7 @@ double LMNNFunction::EvaluateWithGradient( { if (transformationDiffs[lastTransformationIndices[i]] * (2 * norm(i) + norm(impostors(k - 1, i)) + - norm(impostors(k, i))) > distance(k, i) - distance(k - 1, i)) + norm(impostors(k, i))) > distanceMat(k, i) - distanceMat(k - 1, i)) { points(numPoints++) = i; } @@ -916,13 +917,13 @@ double LMNNFunction::EvaluateWithGradient( } // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm, points, numPoints); } else if (iteration++ % range == 0) { // Re-calculate impostors on transformed dataset. - constraint.Impostors(impostors, distance, transformedDataset, labels, + constraint.Impostors(impostors, distanceMat, transformedDataset, labels, norm, begin, batchSize); } @@ -936,7 +937,7 @@ double LMNNFunction::EvaluateWithGradient( for (size_t j = 0; j < k ; ++j) { // Calculate cost due to distance between target neighbors & data point. - double eval = metric.Evaluate(transformedDataset.col(i), + double eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))); cost += (1 - regularization) * eval; @@ -970,15 +971,15 @@ double LMNNFunction::EvaluateWithGradient( { if (iteration - 1 % range == 0) { - eval = metric.Evaluate(transformedDataset.col(i), + eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))) - - distance(l, i); + distanceMat(l, i); } else { - eval = metric.Evaluate(transformedDataset.col(i), + eval = distance.Evaluate(transformedDataset.col(i), transformedDataset.col(targetNeighbors(j, i))) - - metric.Evaluate(transformedDataset.col(i), + distance.Evaluate(transformedDataset.col(i), transformedDataset.col(impostors(l, i))); } } @@ -1015,8 +1016,8 @@ double LMNNFunction::EvaluateWithGradient( return cost; } -template -inline void LMNNFunction::Precalculate() +template +inline void LMNNFunction::Precalculate() { pCij.zeros(dataset.n_rows, dataset.n_rows); diff --git a/src/mlpack/methods/lmnn/lmnn_impl.hpp b/src/mlpack/methods/lmnn/lmnn_impl.hpp index d90a5ed26b..740a3a6c0c 100644 --- a/src/mlpack/methods/lmnn/lmnn_impl.hpp +++ b/src/mlpack/methods/lmnn/lmnn_impl.hpp @@ -21,26 +21,26 @@ namespace mlpack { * Takes in a reference to the dataset. Copies the data, initializes * all of the member variables and constraint object and generate constraints. */ -template -LMNN::LMNN(const arma::mat& dataset, +template +LMNN::LMNN(const arma::mat& dataset, const arma::Row& labels, const size_t k, - const MetricType metric) : + const DistanceType distance) : dataset(dataset), labels(labels), k(k), regularization(0.5), range(1), - metric(metric) + distance(distance) { /* nothing to do */ } -template +template template -void LMNN::LearnDistance(arma::mat& outputMatrix, +void LMNN::LearnDistance(arma::mat& outputMatrix, CallbackTypes&&... callbacks) { // LMNN objective function. - LMNNFunction objFunction(dataset, labels, k, + LMNNFunction objFunction(dataset, labels, k, regularization, range); // See if we were passed an initialized matrix. outputMatrix (L) must be diff --git a/src/mlpack/methods/mean_shift/mean_shift_impl.hpp b/src/mlpack/methods/mean_shift/mean_shift_impl.hpp index 42e0f2ce3e..b4eaf63107 100644 --- a/src/mlpack/methods/mean_shift/mean_shift_impl.hpp +++ b/src/mlpack/methods/mean_shift/mean_shift_impl.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include diff --git a/src/mlpack/methods/nca/nca.hpp b/src/mlpack/methods/nca/nca.hpp index e9fe437fee..7c68f6b918 100644 --- a/src/mlpack/methods/nca/nca.hpp +++ b/src/mlpack/methods/nca/nca.hpp @@ -41,7 +41,7 @@ namespace mlpack { * } * @endcode */ -template class NCA { @@ -53,11 +53,11 @@ class NCA * * @param dataset Input dataset. * @param labels Input dataset labels. - * @param metric Instantiated metric to use. + * @param distance Instantiated distance metric to use. */ NCA(const arma::mat& dataset, const arma::Row& labels, - MetricType metric = MetricType()); + DistanceType distance = DistanceType()); /** * Perform Neighborhood Components Analysis. The output distance learning @@ -90,10 +90,10 @@ class NCA const arma::Row& labels; //! Metric to be used. - MetricType metric; + DistanceType distance; //! The function to optimize. - SoftmaxErrorFunction errorFunction; + SoftmaxErrorFunction errorFunction; //! The optimizer to use. OptimizerType optimizer; diff --git a/src/mlpack/methods/nca/nca_impl.hpp b/src/mlpack/methods/nca/nca_impl.hpp index d0d87cccaf..c0b9dd7098 100644 --- a/src/mlpack/methods/nca/nca_impl.hpp +++ b/src/mlpack/methods/nca/nca_impl.hpp @@ -18,19 +18,19 @@ namespace mlpack { // Just set the internal matrix reference. -template -NCA::NCA(const arma::mat& dataset, +template +NCA::NCA(const arma::mat& dataset, const arma::Row& labels, - MetricType metric) : + DistanceType distance) : dataset(dataset), labels(labels), - metric(metric), - errorFunction(dataset, labels, metric) + distance(distance), + errorFunction(dataset, labels, distance) { /* Nothing to do. */ } -template +template template -void NCA::LearnDistance(arma::mat& outputMatrix, +void NCA::LearnDistance(arma::mat& outputMatrix, CallbackTypes&&... callbacks) { // See if we were passed an initialized matrix. diff --git a/src/mlpack/methods/nca/nca_softmax_error_function.hpp b/src/mlpack/methods/nca/nca_softmax_error_function.hpp index 58b37b676c..e4165c9c12 100644 --- a/src/mlpack/methods/nca/nca_softmax_error_function.hpp +++ b/src/mlpack/methods/nca/nca_softmax_error_function.hpp @@ -14,7 +14,7 @@ #define MLPACK_METHODS_NCA_NCA_SOFTMAX_ERROR_FUNCTION_HPP #include -#include +#include #include #include @@ -40,7 +40,7 @@ namespace mlpack { * operate on one point in the dataset. This is useful for optimizers like * stochastic gradient descent (see mlpack::optimization::SGD). */ -template +template class SoftmaxErrorFunction { public: @@ -56,7 +56,7 @@ class SoftmaxErrorFunction */ SoftmaxErrorFunction(const arma::mat& dataset, const arma::Row& labels, - MetricType metric = MetricType()); + DistanceType metric = DistanceType()); /** * Shuffle the dataset. @@ -138,7 +138,7 @@ class SoftmaxErrorFunction arma::Row labels; //! The instantiated metric. - MetricType metric; + DistanceType distance; //! Last coordinates. Used for the non-separable Evaluate() and Gradient(). arma::mat lastCoordinates; diff --git a/src/mlpack/methods/nca/nca_softmax_error_function_impl.hpp b/src/mlpack/methods/nca/nca_softmax_error_function_impl.hpp index b7a4cfac8e..666e64d4e2 100644 --- a/src/mlpack/methods/nca/nca_softmax_error_function_impl.hpp +++ b/src/mlpack/methods/nca/nca_softmax_error_function_impl.hpp @@ -20,12 +20,12 @@ namespace mlpack { // Initialize with the given kernel. -template -SoftmaxErrorFunction::SoftmaxErrorFunction( +template +SoftmaxErrorFunction::SoftmaxErrorFunction( const arma::mat& datasetIn, const arma::Row& labelsIn, - MetricType metric) : - metric(metric), + DistanceType distance) : + distance(distance), precalculated(false) { MakeAlias(dataset, datasetIn, datasetIn.n_rows, datasetIn.n_cols, 0, false); @@ -33,8 +33,8 @@ SoftmaxErrorFunction::SoftmaxErrorFunction( } //! Shuffle the dataset. -template -void SoftmaxErrorFunction::Shuffle() +template +void SoftmaxErrorFunction::Shuffle() { arma::mat newDataset; arma::Row newLabels; @@ -49,8 +49,8 @@ void SoftmaxErrorFunction::Shuffle() } //! The non-separable implementation, which uses Precalculate() to save time. -template -double SoftmaxErrorFunction::Evaluate(const arma::mat& coordinates) +template +double SoftmaxErrorFunction::Evaluate(const arma::mat& coordinates) { // Calculate the denominators and numerators, if necessary. Precalculate(coordinates); @@ -61,8 +61,8 @@ double SoftmaxErrorFunction::Evaluate(const arma::mat& coordinates) //! The separated objective function, which does not use Precalculate(), //! for a given batch size and from an initial index. -template -double SoftmaxErrorFunction::Evaluate(const arma::mat& coordinates, +template +double SoftmaxErrorFunction::Evaluate(const arma::mat& coordinates, const size_t begin, const size_t batchSize) { @@ -83,8 +83,8 @@ double SoftmaxErrorFunction::Evaluate(const arma::mat& coordinates, continue; // We want to evaluate exp(-D(A x_i, A x_k)). - double eval = std::exp(-metric.Evaluate(stretchedDataset.unsafe_col(i), - stretchedDataset.unsafe_col(k))); + double eval = std::exp(-distance.Evaluate( + stretchedDataset.unsafe_col(i), stretchedDataset.unsafe_col(k))); // If they are in the same class, update the numerator. if (labels[i] == labels[k]) @@ -108,8 +108,8 @@ double SoftmaxErrorFunction::Evaluate(const arma::mat& coordinates, } //! The non-separable implementation, where Precalculate() is used. -template -void SoftmaxErrorFunction::Gradient(const arma::mat& coordinates, +template +void SoftmaxErrorFunction::Gradient(const arma::mat& coordinates, arma::mat& gradient) { // Calculate the denominators and numerators, if necessary. @@ -134,8 +134,8 @@ void SoftmaxErrorFunction::Gradient(const arma::mat& coordinates, for (size_t k = (i + 1); k < stretchedDataset.n_cols; ++k) { // Calculate p_ik and p_ki first. - double eval = std::exp(-metric.Evaluate(stretchedDataset.unsafe_col(i), - stretchedDataset.unsafe_col(k))); + double eval = std::exp(-distance.Evaluate( + stretchedDataset.unsafe_col(i), stretchedDataset.unsafe_col(k))); double p_ik = 0, p_ki = 0; p_ik = eval / denominators(i); p_ki = eval / denominators(k); @@ -156,9 +156,9 @@ void SoftmaxErrorFunction::Gradient(const arma::mat& coordinates, } //! The separable implementation for a given batch size and an initial index. -template +template template -void SoftmaxErrorFunction::Gradient(const arma::mat& coordinates, +void SoftmaxErrorFunction::Gradient(const arma::mat& coordinates, const size_t begin, GradType& gradient, const size_t batchSize) @@ -189,8 +189,8 @@ void SoftmaxErrorFunction::Gradient(const arma::mat& coordinates, continue; // Calculate the numerator of p_ik. - double eval = std::exp(-metric.Evaluate(stretchedDataset.unsafe_col(i), - stretchedDataset.unsafe_col(k))); + double eval = std::exp(-distance.Evaluate( + stretchedDataset.unsafe_col(i), stretchedDataset.unsafe_col(k))); // If the points are in the same class, we must add to the second term of // the gradient as well as the numerator of p_i. We will divide by the @@ -231,14 +231,14 @@ void SoftmaxErrorFunction::Gradient(const arma::mat& coordinates, } } -template -const arma::mat SoftmaxErrorFunction::GetInitialPoint() const +template +const arma::mat SoftmaxErrorFunction::GetInitialPoint() const { return arma::eye(dataset.n_rows, dataset.n_rows); } -template -void SoftmaxErrorFunction::Precalculate( +template +void SoftmaxErrorFunction::Precalculate( const arma::mat& coordinates) { // Ensure it is the right size. @@ -270,8 +270,8 @@ void SoftmaxErrorFunction::Precalculate( for (size_t j = (i + 1); j < stretchedDataset.n_cols; ++j) { // Evaluate exp(-d(x_i, x_j)). - double eval = std::exp(-metric.Evaluate(stretchedDataset.unsafe_col(i), - stretchedDataset.unsafe_col(j))); + double eval = std::exp(-distance.Evaluate( + stretchedDataset.unsafe_col(i), stretchedDataset.unsafe_col(j))); // Add this to the denominators of both p_i and p_j: K(i, j) = K(j, i). denominators[i] += eval; diff --git a/src/mlpack/methods/neighbor_search/neighbor_search.hpp b/src/mlpack/methods/neighbor_search/neighbor_search.hpp index 558a4a300f..b8f61c0155 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search.hpp @@ -25,7 +25,7 @@ namespace mlpack { // Forward declaration. template class TreeType, template class DualTreeTraversalType, @@ -51,11 +51,11 @@ enum NeighborSearchMode * dataset is also used as the query dataset. * * The template parameters SortPolicy and Metric define the sort function used - * and the metric (distance function) used. More information on those classes - * can be found in the NearestNeighborSort class and the ExampleKernel class. + * and the distance metric used. More information on those classes can be found + * in the NearestNeighborSort class and the ExampleKernel class. * * @tparam SortPolicy The sort policy for distances; see NearestNeighborSort. - * @tparam MetricType The metric to use for computation. + * @tparam DistanceType The distance metric to use for computation. * @tparam MatType The type of data matrix. * @tparam TreeType The tree type to use; must adhere to the TreeType API. * @tparam DualTreeTraversalType The type of dual tree traversal to use @@ -64,24 +64,24 @@ enum NeighborSearchMode * (defaults to the tree's default traverser). */ template class TreeType = KDTree, template class DualTreeTraversalType = - TreeType, MatType>::template DualTreeTraverser, template class SingleTreeTraversalType = - TreeType, MatType>::template SingleTreeTraverser> class NeighborSearch { public: //! Convenience typedef. - typedef TreeType, MatType> Tree; + typedef TreeType, MatType> Tree; //! The type of element held in MatType. typedef typename MatType::elem_type ElemType; @@ -89,22 +89,22 @@ class NeighborSearch * Initialize the NeighborSearch object, passing a reference dataset (this is * the dataset which is searched). Optionally, perform the computation in * a different mode. An initialized distance metric can be given, for cases - * where the metric has internal data (i.e. the distance::MahalanobisDistance + * where the distance metric has internal data (i.e. the MahalanobisDistance * class). * * This method will move the matrices to internal copies, which are rearranged - * during tree-building. You can avoid creating an extra copy by pre-constructing - * the trees, passing std::move(yourReferenceSet). + * during tree-building. You can avoid creating an extra copy by + * pre-constructing the trees, passing std::move(yourReferenceSet). * * @param referenceSet Set of reference points. * @param mode Neighbor search mode. * @param epsilon Relative approximate error (non-negative). - * @param metric An optional instance of the MetricType class. + * @param distance An optional instance of the DistanceType class. */ NeighborSearch(MatType referenceSet, const NeighborSearchMode mode = DUAL_TREE_MODE, const double epsilon = 0, - const MetricType metric = MetricType()); + const DistanceType distance = DistanceType()); /** * Initialize the NeighborSearch object with a copy of the given @@ -114,9 +114,9 @@ class NeighborSearch * instantiated distance metric can be given, for cases where the distance * metric holds data. * - * This method will copy the given tree. When copies must absolutely be avoided, - * you can avoid this copy, while taking ownership of the given tree, by passing - * std::move(yourReferenceTree) + * This method will copy the given tree. When copies must absolutely be + * avoided, you can avoid this copy, while taking ownership of the given tree, + * by passing std::move(yourReferenceTree) * * @note * Mapping the points of the matrix back to their original indices is not done @@ -127,12 +127,12 @@ class NeighborSearch * @param referenceTree Pre-built tree for reference points. * @param mode Neighbor search mode. * @param epsilon Relative approximate error (non-negative). - * @param metric Instantiated distance metric. + * @param distance Instantiated distance metric. */ NeighborSearch(Tree referenceTree, const NeighborSearchMode mode = DUAL_TREE_MODE, const double epsilon = 0, - const MetricType metric = MetricType()); + const DistanceType distance = DistanceType()); /** * Create a NeighborSearch object without any reference data. If Search() is @@ -141,11 +141,11 @@ class NeighborSearch * * @param mode Neighbor search mode. * @param epsilon Relative approximate error (non-negative). - * @param metric Instantiated metric. + * @param distance Instantiated distance metric. */ NeighborSearch(const NeighborSearchMode mode = DUAL_TREE_MODE, const double epsilon = 0, - const MetricType metric = MetricType()); + const DistanceType distance = DistanceType()); /** * Construct the NeighborSearch object by copying the given NeighborSearch @@ -345,8 +345,8 @@ class NeighborSearch //! Indicates the relative error to be considered in approximate search. double epsilon; - //! Instantiation of metric. - MetricType metric; + //! Instantiation of distance metric. + DistanceType distance; //! The total number of base cases. size_t baseCases; diff --git a/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp b/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp index c528d23f04..c73b7855f0 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search_impl.hpp @@ -22,25 +22,25 @@ namespace mlpack { // Construct the object. template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> -NeighborSearch::NeighborSearch(MatType referenceSetIn, const NeighborSearchMode mode, const double epsilon, - const MetricType metric) : + const DistanceType distance) : referenceTree(mode == NAIVE_MODE ? NULL : BuildTree(std::move(referenceSetIn), oldFromNewReferences)), referenceSet(mode == NAIVE_MODE ? new MatType(std::move(referenceSetIn)) : &referenceTree->Dataset()), searchMode(mode), epsilon(epsilon), - metric(metric), + distance(distance), baseCases(0), scores(0), treeNeedsReset(false) @@ -51,23 +51,23 @@ SingleTreeTraversalType>::NeighborSearch(MatType referenceSetIn, // Construct the object. template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> -NeighborSearch::NeighborSearch(Tree referenceTree, const NeighborSearchMode mode, const double epsilon, - const MetricType metric) : + const DistanceType distance) : referenceTree(new Tree(std::move(referenceTree))), referenceSet(&this->referenceTree->Dataset()), searchMode(mode), epsilon(epsilon), - metric(metric), + distance(distance), baseCases(0), scores(0), treeNeedsReset(false) @@ -78,22 +78,22 @@ SingleTreeTraversalType>::NeighborSearch(Tree referenceTree, // Construct the object without a reference dataset. template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> -NeighborSearch::NeighborSearch(const NeighborSearchMode mode, const double epsilon, - const MetricType metric) : + const DistanceType distance) : referenceTree(NULL), referenceSet(mode == NAIVE_MODE ? new MatType() : NULL), // Empty matrix. searchMode(mode), epsilon(epsilon), - metric(metric), + distance(distance), baseCases(0), scores(0), treeNeedsReset(false) @@ -112,14 +112,14 @@ SingleTreeTraversalType>::NeighborSearch(const NeighborSearchMode mode, // Copy constructor. template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> -NeighborSearch::NeighborSearch(const NeighborSearch& other) : oldFromNewReferences(other.oldFromNewReferences), referenceTree(other.referenceTree ? new Tree(*other.referenceTree) : NULL), @@ -127,7 +127,7 @@ SingleTreeTraversalType>::NeighborSearch(const NeighborSearch& other) : new MatType(*other.referenceSet)), searchMode(other.searchMode), epsilon(other.epsilon), - metric(other.metric), + distance(other.distance), baseCases(other.baseCases), scores(other.scores), treeNeedsReset(false) @@ -137,21 +137,21 @@ SingleTreeTraversalType>::NeighborSearch(const NeighborSearch& other) : // Move constructor. template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> -NeighborSearch::NeighborSearch(NeighborSearch&& other) : oldFromNewReferences(std::move(other.oldFromNewReferences)), referenceTree(other.referenceTree), referenceSet(other.referenceSet), searchMode(other.searchMode), epsilon(other.epsilon), - metric(std::move(other.metric)), + distance(std::move(other.distance)), baseCases(other.baseCases), scores(other.scores), treeNeedsReset(other.treeNeedsReset) @@ -169,21 +169,21 @@ SingleTreeTraversalType>::NeighborSearch(NeighborSearch&& other) : // Copy operator. template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> NeighborSearch& NeighborSearch class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> NeighborSearch& NeighborSearch class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> -NeighborSearch::~NeighborSearch() { if (referenceTree) @@ -284,14 +284,14 @@ SingleTreeTraversalType>::~NeighborSearch() } template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> -void NeighborSearch::Train(MatType referenceSetIn) { // Clean up the old tree, if we built one. @@ -320,14 +320,14 @@ DualTreeTraversalType, SingleTreeTraversalType>::Train(MatType referenceSetIn) } template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> -void NeighborSearch::Train(Tree referenceTree) { if (searchMode == NAIVE_MODE) @@ -353,14 +353,14 @@ DualTreeTraversalType, SingleTreeTraversalType>::Train(Tree referenceTree) * distances. */ template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> -void NeighborSearch::Search( const MatType& querySet, const size_t k, @@ -404,14 +404,14 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( neighborPtr->set_size(k, querySet.n_cols); distancePtr->set_size(k, querySet.n_cols); - typedef NeighborSearchRules RuleType; + typedef NeighborSearchRules RuleType; switch (searchMode) { case NAIVE_MODE: { // Create the helper object for the tree traversal. - RuleType rules(*referenceSet, querySet, k, metric, epsilon); + RuleType rules(*referenceSet, querySet, k, distance, epsilon); // The naive brute-force traversal. for (size_t i = 0; i < querySet.n_cols; ++i) @@ -426,7 +426,7 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( case SINGLE_TREE_MODE: { // Create the helper object for the tree traversal. - RuleType rules(*referenceSet, querySet, k, metric, epsilon); + RuleType rules(*referenceSet, querySet, k, distance, epsilon); // Create the traverser. SingleTreeTraversalType traverser(rules); @@ -452,7 +452,7 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( Tree* queryTree = BuildTree(querySet, oldFromNewQueries); // Create the helper object for the tree traversal. - RuleType rules(*referenceSet, queryTree->Dataset(), k, metric, epsilon); + RuleType rules(*referenceSet, queryTree->Dataset(), k, distance, epsilon); // Create the traverser. DualTreeTraversalType traverser(rules); @@ -475,7 +475,7 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( case GREEDY_SINGLE_TREE_MODE: { // Create the helper object for the tree traversal. - RuleType rules(*referenceSet, querySet, k, metric); + RuleType rules(*referenceSet, querySet, k, distance); // Create the traverser. GreedySingleTreeTraverser traverser(rules); @@ -558,14 +558,14 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( } // Search() template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> -void NeighborSearch::Search( Tree& queryTree, const size_t k, @@ -602,8 +602,8 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( distances.set_size(k, querySet.n_cols); // Create the helper object for the traversal. - typedef NeighborSearchRules RuleType; - RuleType rules(*referenceSet, querySet, k, metric, epsilon, sameSet); + typedef NeighborSearchRules RuleType; + RuleType rules(*referenceSet, querySet, k, distance, epsilon, sameSet); // Create the traverser. DualTreeTraversalType traverser(rules); @@ -637,14 +637,14 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( } template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> -void NeighborSearch::Search( const size_t k, arma::Mat& neighbors, @@ -684,8 +684,8 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( distancePtr->set_size(k, referenceSet->n_cols); // Create the helper object for the traversal. - typedef NeighborSearchRules RuleType; - RuleType rules(*referenceSet, *referenceSet, k, metric, epsilon, + typedef NeighborSearchRules RuleType; + RuleType rules(*referenceSet, *referenceSet, k, distance, epsilon, true /* don't return the same point as nearest neighbor */); switch (searchMode) @@ -816,14 +816,14 @@ DualTreeTraversalType, SingleTreeTraversalType>::Search( //! Calculate the average relative error. template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> -double NeighborSearch::EffectiveError( arma::Mat& foundDistances, arma::Mat& realDistances) @@ -854,14 +854,14 @@ DualTreeTraversalType, SingleTreeTraversalType>::EffectiveError( //! Calculate the recall. template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> -double NeighborSearch::Recall( arma::Mat& foundNeighbors, arma::Mat& realNeighbors) @@ -885,15 +885,15 @@ DualTreeTraversalType, SingleTreeTraversalType>::Recall( //! Serialize the NeighborSearch model. template class TreeType, template class DualTreeTraversalType, template class SingleTreeTraversalType> template -void NeighborSearch::serialize( Archive& ar, const uint32_t /* version */) { @@ -912,7 +912,7 @@ DualTreeTraversalType, SingleTreeTraversalType>::serialize( } ar(CEREAL_POINTER(const_cast(referenceSet))); - ar(CEREAL_NVP(metric)); + ar(CEREAL_NVP(distance)); // If we are loading, set the tree to NULL and clean up memory if necessary. if (cereal::is_loading()) @@ -940,7 +940,7 @@ DualTreeTraversalType, SingleTreeTraversalType>::serialize( if (cereal::is_loading()) { referenceSet = &referenceTree->Dataset(); - metric = referenceTree->Metric(); // Get the metric from the tree. + distance = referenceTree->Distance(); // Get the distance from the tree. } } diff --git a/src/mlpack/methods/neighbor_search/neighbor_search_rules.hpp b/src/mlpack/methods/neighbor_search/neighbor_search_rules.hpp index 02577a4049..ef886663a7 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search_rules.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search_rules.hpp @@ -27,10 +27,10 @@ namespace mlpack { * policy. * * @tparam SortPolicy The sort policy for distances. - * @tparam MetricType The metric to use for computation. + * @tparam DistanceType The distance metric to use for computation. * @tparam TreeType The tree type to use; must adhere to the TreeType API. */ -template +template class NeighborSearchRules { public: @@ -44,7 +44,7 @@ class NeighborSearchRules * @param referenceSet Set of reference data. * @param querySet Set of query data. * @param k Number of neighbors to search for. - * @param metric Instantiated metric. + * @param distance Instantiated distance metric. * @param epsilon Relative approximate error. * @param sameSet If true, the query and reference set are taken to be the * same, and a query point will not return itself in the results. @@ -52,7 +52,7 @@ class NeighborSearchRules NeighborSearchRules(const typename TreeType::Mat& referenceSet, const typename TreeType::Mat& querySet, const size_t k, - MetricType& metric, + DistanceType& distance, const double epsilon = 0, const bool sameSet = false); @@ -191,8 +191,8 @@ class NeighborSearchRules //! Number of neighbors to search for. const size_t k; - //! The instantiated metric. - MetricType& metric; + //! The instantiated distance metric. + DistanceType& distance; //! Denotes whether or not the reference and query sets are the same. bool sameSet; diff --git a/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp b/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp index f754427dc2..24fa48c6d5 100644 --- a/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp +++ b/src/mlpack/methods/neighbor_search/neighbor_search_rules_impl.hpp @@ -18,18 +18,18 @@ namespace mlpack { -template -NeighborSearchRules::NeighborSearchRules( +template +NeighborSearchRules::NeighborSearchRules( const typename TreeType::Mat& referenceSet, const typename TreeType::Mat& querySet, const size_t k, - MetricType& metric, + DistanceType& distance, const double epsilon, const bool sameSet) : referenceSet(referenceSet), querySet(querySet), k(k), - metric(metric), + distance(distance), sameSet(sameSet), epsilon(epsilon), lastQueryIndex(querySet.n_cols), @@ -58,8 +58,8 @@ NeighborSearchRules::NeighborSearchRules( candidates.push_back(pqueue); } -template -void NeighborSearchRules::GetResults( +template +void NeighborSearchRules::GetResults( arma::Mat& neighbors, arma::Mat& distances) { @@ -78,9 +78,9 @@ void NeighborSearchRules::GetResults( } }; -template +template inline mlpack_force_inline // Must be inline so optimizations can happen. -double NeighborSearchRules:: +double NeighborSearchRules:: BaseCase(const size_t queryIndex, const size_t referenceIndex) { // If the datasets are the same, then this search is only using one dataset @@ -92,27 +92,27 @@ BaseCase(const size_t queryIndex, const size_t referenceIndex) if ((lastQueryIndex == queryIndex) && (lastReferenceIndex == referenceIndex)) return lastBaseCase; - double distance = metric.Evaluate(querySet.col(queryIndex), - referenceSet.col(referenceIndex)); + double dist = distance.Evaluate(querySet.col(queryIndex), + referenceSet.col(referenceIndex)); ++baseCases; - InsertNeighbor(queryIndex, referenceIndex, distance); + InsertNeighbor(queryIndex, referenceIndex, dist); // Cache this information for the next time BaseCase() is called. lastQueryIndex = queryIndex; lastReferenceIndex = referenceIndex; - lastBaseCase = distance; + lastBaseCase = dist; - return distance; + return dist; } -template -inline double NeighborSearchRules::Score( +template +inline double NeighborSearchRules::Score( const size_t queryIndex, TreeType& referenceNode) { ++scores; // Count number of Score() calls. - double distance; + double dist; if (TreeTraits::FirstPointIsCentroid) { // The first point in the tree is the centroid. So we can then calculate @@ -132,12 +132,12 @@ inline double NeighborSearchRules::Score( referenceNode.Stat().LastDistance() = baseCase; } - distance = SortPolicy::CombineBest(baseCase, + dist = SortPolicy::CombineBest(baseCase, referenceNode.FurthestDescendantDistance()); } else { - distance = SortPolicy::BestPointToNodeDistance(querySet.col(queryIndex), + dist = SortPolicy::BestPointToNodeDistance(querySet.col(queryIndex), &referenceNode); } @@ -145,28 +145,28 @@ inline double NeighborSearchRules::Score( double bestDistance = candidates[queryIndex].top().first; bestDistance = SortPolicy::Relax(bestDistance, epsilon); - return (SortPolicy::IsBetter(distance, bestDistance)) ? - SortPolicy::ConvertToScore(distance) : DBL_MAX; + return (SortPolicy::IsBetter(dist, bestDistance)) ? + SortPolicy::ConvertToScore(dist) : DBL_MAX; } -template -inline size_t NeighborSearchRules:: +template +inline size_t NeighborSearchRules:: GetBestChild(const size_t queryIndex, TreeType& referenceNode) { ++scores; return SortPolicy::GetBestChild(querySet.col(queryIndex), referenceNode); } -template -inline size_t NeighborSearchRules:: +template +inline size_t NeighborSearchRules:: GetBestChild(const TreeType& queryNode, TreeType& referenceNode) { ++scores; return SortPolicy::GetBestChild(queryNode, referenceNode); } -template -inline double NeighborSearchRules::Rescore( +template +inline double NeighborSearchRules::Rescore( const size_t queryIndex, TreeType& /* referenceNode */, const double oldScore) const @@ -175,17 +175,17 @@ inline double NeighborSearchRules::Rescore( if (oldScore == DBL_MAX) return oldScore; - const double distance = SortPolicy::ConvertToDistance(oldScore); + const double dist = SortPolicy::ConvertToDistance(oldScore); // Just check the score again against the distances. double bestDistance = candidates[queryIndex].top().first; bestDistance = SortPolicy::Relax(bestDistance, epsilon); - return (SortPolicy::IsBetter(distance, bestDistance)) ? oldScore : DBL_MAX; + return (SortPolicy::IsBetter(dist, bestDistance)) ? oldScore : DBL_MAX; } -template -inline double NeighborSearchRules::Score( +template +inline double NeighborSearchRules::Score( TreeType& queryNode, TreeType& referenceNode) { @@ -293,7 +293,7 @@ inline double NeighborSearchRules::Score( } } - double distance; + double dist; if (TreeTraits::FirstPointIsCentroid) { // The first point in the node is the centroid, so we can calculate the @@ -312,7 +312,7 @@ inline double NeighborSearchRules::Score( baseCase = BaseCase(queryNode.Point(0), referenceNode.Point(0)); } - distance = SortPolicy::CombineBest(baseCase, + dist = SortPolicy::CombineBest(baseCase, queryNode.FurthestDescendantDistance() + referenceNode.FurthestDescendantDistance()); @@ -324,17 +324,17 @@ inline double NeighborSearchRules::Score( } else { - distance = SortPolicy::BestNodeToNodeDistance(&queryNode, &referenceNode); + dist = SortPolicy::BestNodeToNodeDistance(&queryNode, &referenceNode); } - if (SortPolicy::IsBetter(distance, bestDistance)) + if (SortPolicy::IsBetter(dist, bestDistance)) { // Set traversal information. traversalInfo.LastQueryNode() = &queryNode; traversalInfo.LastReferenceNode() = &referenceNode; - traversalInfo.LastScore() = distance; + traversalInfo.LastScore() = dist; - return SortPolicy::ConvertToScore(distance); + return SortPolicy::ConvertToScore(dist); } else { @@ -345,8 +345,8 @@ inline double NeighborSearchRules::Score( } } -template -inline double NeighborSearchRules::Rescore( +template +inline double NeighborSearchRules::Rescore( TreeType& queryNode, TreeType& /* referenceNode */, const double oldScore) const @@ -354,18 +354,18 @@ inline double NeighborSearchRules::Rescore( if (oldScore == DBL_MAX || oldScore == 0.0) return oldScore; - const double distance = SortPolicy::ConvertToDistance(oldScore); + const double dist = SortPolicy::ConvertToDistance(oldScore); // Update our bound. const double bestDistance = CalculateBound(queryNode); - return (SortPolicy::IsBetter(distance, bestDistance)) ? oldScore : DBL_MAX; + return (SortPolicy::IsBetter(dist, bestDistance)) ? oldScore : DBL_MAX; } // Calculate the bound for a given query node in its current state and update // it. -template -inline double NeighborSearchRules:: +template +inline double NeighborSearchRules:: CalculateBound(TreeType& queryNode) const { // This is an adapted form of the B(N_q) function in the paper @@ -401,11 +401,11 @@ inline double NeighborSearchRules:: // Loop over points held in the node. for (size_t i = 0; i < queryNode.NumPoints(); ++i) { - const double distance = candidates[queryNode.Point(i)].top().first; - if (SortPolicy::IsBetter(worstDistance, distance)) - worstDistance = distance; - if (SortPolicy::IsBetter(distance, bestPointDistance)) - bestPointDistance = distance; + const double dist = candidates[queryNode.Point(i)].top().first; + if (SortPolicy::IsBetter(worstDistance, dist)) + worstDistance = dist; + if (SortPolicy::IsBetter(dist, bestPointDistance)) + bestPointDistance = dist; } double auxDistance = bestPointDistance; @@ -487,17 +487,17 @@ inline double NeighborSearchRules:: * * @param queryIndex Index of point whose neighbors we are inserting into. * @param neighbor Index of reference point which is being inserted. - * @param distance Distance from query point to reference point. + * @param dist Distance from query point to reference point. */ -template -inline void NeighborSearchRules:: +template +inline void NeighborSearchRules:: InsertNeighbor( const size_t queryIndex, const size_t neighbor, - const double distance) + const double dist) { CandidateList& pqueue = candidates[queryIndex]; - Candidate c = std::make_pair(distance, neighbor); + Candidate c = std::make_pair(dist, neighbor); if (CandidateCmp()(c, pqueue.top())) { diff --git a/src/mlpack/methods/neighbor_search/ns_model.hpp b/src/mlpack/methods/neighbor_search/ns_model.hpp index 62500a5a1d..cf5e9338c5 100644 --- a/src/mlpack/methods/neighbor_search/ns_model.hpp +++ b/src/mlpack/methods/neighbor_search/ns_model.hpp @@ -87,7 +87,7 @@ class NSWrapperBase * NSWrapper is a wrapper class for most NeighborSearch types. */ template class TreeType, template class DualTreeTraversalType = @@ -181,7 +181,7 @@ class NSWrapper : public NSWrapperBase * size into account. */ template class TreeType, template class DualTreeTraversalType = diff --git a/src/mlpack/methods/neighbor_search/ns_model_impl.hpp b/src/mlpack/methods/neighbor_search/ns_model_impl.hpp index cba91d8db3..c51f0c72a6 100644 --- a/src/mlpack/methods/neighbor_search/ns_model_impl.hpp +++ b/src/mlpack/methods/neighbor_search/ns_model_impl.hpp @@ -23,7 +23,7 @@ namespace mlpack { //! Train the model with the given options. For NSWrapper, we ignore the //! extra parameters. template class TreeType, template class DualTreeTraversalType, @@ -48,7 +48,7 @@ void NSWrapper< //! Perform bichromatic neighbor search (i.e. search with a separate query //! set). For NSWrapper, we ignore the extra parameters. template class TreeType, template class DualTreeTraversalType, @@ -85,7 +85,7 @@ void NSWrapper< //! Perform monochromatic neighbor search (i.e. use the reference set as the //! query set). template class TreeType, template class DualTreeTraversalType, @@ -105,7 +105,7 @@ void NSWrapper< //! Train a model with the given parameters. This overload uses leafSize but //! ignores the other parameters. template class TreeType, template class DualTreeTraversalType, @@ -138,7 +138,7 @@ void LeafSizeNSWrapper< //! Perform bichromatic search (e.g. search with a separate query set). This //! overload uses the leaf size, but ignores the other parameters. template class TreeType, template class DualTreeTraversalType, diff --git a/src/mlpack/methods/neighbor_search/typedef.hpp b/src/mlpack/methods/neighbor_search/typedef.hpp index fc0a7fe2d7..c66db6b026 100644 --- a/src/mlpack/methods/neighbor_search/typedef.hpp +++ b/src/mlpack/methods/neighbor_search/typedef.hpp @@ -17,7 +17,7 @@ // In case someone included this directly. #include "neighbor_search.hpp" -#include +#include #include "sort_policies/nearest_neighbor_sort.hpp" #include "sort_policies/furthest_neighbor_sort.hpp" @@ -43,7 +43,7 @@ typedef NeighborSearch KFN; * @tparam TreeType The tree type to use; must adhere to the TreeType API, * and implement Defeatist Traversers. */ -template class TreeType = SPTree> using DefeatistKNN = NeighborSearch< diff --git a/src/mlpack/methods/range_search/range_search.hpp b/src/mlpack/methods/range_search/range_search.hpp index d02b8705ff..7505d3fa15 100644 --- a/src/mlpack/methods/range_search/range_search.hpp +++ b/src/mlpack/methods/range_search/range_search.hpp @@ -14,14 +14,14 @@ #define MLPACK_METHODS_RANGE_SEARCH_RANGE_SEARCH_HPP #include -#include +#include #include #include "range_search_stat.hpp" namespace mlpack { //! Forward declaration. -template class TreeType> class LeafSizeRSWrapper; @@ -32,20 +32,20 @@ class LeafSizeRSWrapper; * algorithm; for more details on the actual algorithm, see the RangeSearchRules * class. * - * @tparam MetricType Metric to use for range search calculations. + * @tparam DistanceType Metric to use for range search calculations. * @tparam MatType Type of data to use. * @tparam TreeType Type of tree to use; must satisfy the TreeType policy API. */ -template class TreeType = KDTree> class RangeSearch { public: //! Convenience typedef. - typedef TreeType Tree; + typedef TreeType Tree; //! The type of Matrix. typedef MatType Mat; //! The type of element held in MatType. @@ -54,8 +54,8 @@ class RangeSearch /** * Initialize the RangeSearch object with a given reference dataset (this is * the dataset which is searched). Optionally, perform the computation in - * naive mode or single-tree mode. Additionally, an instantiated metric can be - * given, for cases where the distance metric holds data. + * naive mode or single-tree mode. Additionally, an instantiated distance + * metric can be given, for cases where the distance metric holds data. * * This method will move the matrices to internal copies, which are * rearranged during tree-building. You can avoid creating an extra copy by @@ -65,12 +65,12 @@ class RangeSearch * @param naive Whether the computation should be done in O(n^2) naive mode. * @param singleMode Whether single-tree computation should be used (as * opposed to dual-tree computation). - * @param metric Instantiated distance metric. + * @param distance Instantiated distance metric. */ RangeSearch(MatType referenceSet, const bool naive = false, const bool singleMode = false, - const MetricType metric = MetricType()); + const DistanceType distance = DistanceType()); /** * Initialize the RangeSearch object with the given pre-constructed reference @@ -92,11 +92,11 @@ class RangeSearch * @param referenceTree Pre-built tree for reference points. * @param singleMode Whether single-tree computation should be used (as * opposed to dual-tree computation). - * @param metric Instantiated distance metric. + * @param distance Instantiated distance metric. */ RangeSearch(Tree* referenceTree, const bool singleMode = false, - const MetricType metric = MetricType()); + const DistanceType distance = DistanceType()); /** * Initialize the RangeSearch object without any reference data. If the @@ -106,11 +106,11 @@ class RangeSearch * @param naive Whether to use naive search. * @param singleMode Whether single-tree computation should be used (as * opposed to dual-tree computation). - * @param metric Instantiated metric. + * @param distance Instantiated distance metric. */ RangeSearch(const bool naive = false, const bool singleMode = false, - const MetricType metric = MetricType()); + const DistanceType distance = DistanceType()); /** * Construct the RangeSearch model as a copy of the given model. Note that @@ -314,7 +314,7 @@ class RangeSearch bool singleMode; //! Instantiated distance metric. - MetricType metric; + DistanceType distance; //! The total number of base cases during the last search. size_t baseCases; diff --git a/src/mlpack/methods/range_search/range_search_impl.hpp b/src/mlpack/methods/range_search/range_search_impl.hpp index 90f748cbc9..4bda912806 100644 --- a/src/mlpack/methods/range_search/range_search_impl.hpp +++ b/src/mlpack/methods/range_search/range_search_impl.hpp @@ -20,16 +20,16 @@ namespace mlpack { -template class TreeType> -RangeSearch::RangeSearch( +RangeSearch::RangeSearch( MatType referenceSet, const bool naive, const bool singleMode, - const MetricType metric) : + const DistanceType distance) : referenceTree(naive ? NULL : BuildTree(std::move(referenceSet), oldFromNewReferences)), referenceSet(naive ? new MatType(std::move(referenceSet)) : @@ -37,49 +37,49 @@ RangeSearch::RangeSearch( treeOwner(!naive), naive(naive), singleMode(!naive && singleMode), - metric(metric), + distance(distance), baseCases(0), scores(0) { // Nothing to do. } -template class TreeType> -RangeSearch::RangeSearch( +RangeSearch::RangeSearch( Tree* referenceTree, const bool singleMode, - const MetricType metric) : + const DistanceType distance) : referenceTree(referenceTree), referenceSet(&referenceTree->Dataset()), treeOwner(false), naive(false), singleMode(singleMode), - metric(metric), + distance(distance), baseCases(0), scores(0) { // Nothing else to initialize. } -template class TreeType> -RangeSearch::RangeSearch( +RangeSearch::RangeSearch( const bool naive, const bool singleMode, - const MetricType metric) : + const DistanceType distance) : referenceTree(NULL), referenceSet(naive ? new MatType() : NULL), // Empty matrix. treeOwner(false), naive(naive), singleMode(singleMode), - metric(metric), + distance(distance), baseCases(0), scores(0) { @@ -93,12 +93,12 @@ RangeSearch::RangeSearch( } } -template class TreeType> -RangeSearch::RangeSearch( +RangeSearch::RangeSearch( const RangeSearch& other) : oldFromNewReferences(other.oldFromNewReferences), referenceTree(other.referenceTree ? new Tree(*other.referenceTree) : NULL), @@ -107,26 +107,26 @@ RangeSearch::RangeSearch( treeOwner(other.referenceTree), naive(other.naive), singleMode(other.singleMode), - metric(other.metric), + distance(other.distance), baseCases(other.baseCases), scores(other.scores) { // Nothing to do. } -template class TreeType> -RangeSearch::RangeSearch(RangeSearch&& other) : +RangeSearch::RangeSearch(RangeSearch&& other) : oldFromNewReferences(std::move(other.oldFromNewReferences)), referenceTree(other.referenceTree), referenceSet(other.referenceSet), treeOwner(other.treeOwner), naive(other.naive), singleMode(other.singleMode), - metric(std::move(other.metric)), + distance(std::move(other.distance)), baseCases(other.baseCases), scores(other.scores) { @@ -141,13 +141,13 @@ RangeSearch::RangeSearch(RangeSearch&& other) : other.scores = 0; } -template class TreeType> -RangeSearch& -RangeSearch::operator=(const RangeSearch& other) +RangeSearch& +RangeSearch::operator=(const RangeSearch& other) { if (this != &other) { @@ -159,20 +159,20 @@ RangeSearch::operator=(const RangeSearch& other) treeOwner = other.referenceTree; naive = other.naive; singleMode = other.singleMode; - metric = other.metric; + distance = other.distance; baseCases = other.baseCases; scores = other.scores; } return *this; } -template class TreeType> -RangeSearch& -RangeSearch::operator=(RangeSearch&& other) +RangeSearch& +RangeSearch::operator=(RangeSearch&& other) { if (this != &other) { @@ -189,7 +189,7 @@ RangeSearch::operator=(RangeSearch&& other) treeOwner = other.treeOwner; naive = other.naive; singleMode = other.singleMode; - metric = std::move(other.metric); + distance = std::move(other.distance); baseCases = other.baseCases; scores = other.scores; @@ -205,12 +205,12 @@ RangeSearch::operator=(RangeSearch&& other) return *this; } -template class TreeType> -RangeSearch::~RangeSearch() +RangeSearch::~RangeSearch() { if (treeOwner && referenceTree) delete referenceTree; @@ -218,12 +218,12 @@ RangeSearch::~RangeSearch() delete referenceSet; } -template class TreeType> -void RangeSearch::Train( +void RangeSearch::Train( MatType referenceSet) { // Clean up the old tree, if we built one. @@ -256,12 +256,12 @@ void RangeSearch::Train( } } -template class TreeType> -void RangeSearch::Train( +void RangeSearch::Train( Tree* referenceTree) { if (naive) @@ -279,12 +279,12 @@ void RangeSearch::Train( } } -template class TreeType> -void RangeSearch::Search( +void RangeSearch::Search( const MatType& querySet, const RangeType& range, std::vector>& neighbors, @@ -331,7 +331,7 @@ void RangeSearch::Search( distancePtr->resize(querySet.n_cols); // Create the helper object for the traversal. - typedef RangeSearchRules RuleType; + typedef RangeSearchRules RuleType; // Reset counts. baseCases = 0; @@ -340,7 +340,7 @@ void RangeSearch::Search( if (naive) { RuleType rules(*referenceSet, querySet, range, *neighborPtr, *distancePtr, - metric); + distance); // The naive brute-force solution. for (size_t i = 0; i < querySet.n_cols; ++i) @@ -353,7 +353,7 @@ void RangeSearch::Search( { // Create the traverser. RuleType rules(*referenceSet, querySet, range, *neighborPtr, *distancePtr, - metric); + distance); typename Tree::template SingleTreeTraverser traverser(rules); // Now have it traverse for each point. @@ -370,7 +370,7 @@ void RangeSearch::Search( // Create the traverser. RuleType rules(*referenceSet, queryTree->Dataset(), range, *neighborPtr, - *distancePtr, metric); + *distancePtr, distance); typename Tree::template DualTreeTraverser traverser(rules); traverser.Traverse(*queryTree, *referenceTree); @@ -449,12 +449,12 @@ void RangeSearch::Search( } } -template class TreeType> -void RangeSearch::Search( +void RangeSearch::Search( Tree* queryTree, const RangeType& range, std::vector>& neighbors, @@ -485,9 +485,9 @@ void RangeSearch::Search( distances.resize(querySet.n_cols); // Create the helper object for the traversal. - typedef RangeSearchRules RuleType; + typedef RangeSearchRules RuleType; RuleType rules(*referenceSet, queryTree->Dataset(), range, *neighborPtr, - distances, metric); + distances, distance); // Create the traverser. typename Tree::template DualTreeTraverser traverser(rules); @@ -516,12 +516,12 @@ void RangeSearch::Search( } } -template class TreeType> -void RangeSearch::Search( +void RangeSearch::Search( const RangeType& range, std::vector>& neighbors, std::vector>& distances) @@ -548,9 +548,9 @@ void RangeSearch::Search( distancePtr->resize(referenceSet->n_cols); // Create the helper object for the traversal. - typedef RangeSearchRules RuleType; + typedef RangeSearchRules RuleType; RuleType rules(*referenceSet, *referenceSet, range, *neighborPtr, - *distancePtr, metric, true /* don't return the query in the results */); + *distancePtr, distance, true /* don't return the query in the results */); if (naive) { @@ -613,13 +613,13 @@ void RangeSearch::Search( } } -template class TreeType> template -void RangeSearch::serialize( +void RangeSearch::serialize( Archive& ar, const uint32_t /* version */) { // Serialize preferences for search. @@ -644,7 +644,7 @@ void RangeSearch::serialize( } ar(CEREAL_POINTER(const_cast(referenceSet))); - ar(CEREAL_NVP(metric)); + ar(CEREAL_NVP(distance)); // If we are loading, set the tree to NULL and clean up memory if necessary. if (cereal::is_loading()) @@ -677,7 +677,7 @@ void RangeSearch::serialize( if (cereal::is_loading()) { referenceSet = &referenceTree->Dataset(); - metric = referenceTree->Metric(); // Get the metric from the tree. + distance = referenceTree->Distance(); // Get the distance from the tree. } } } diff --git a/src/mlpack/methods/range_search/range_search_rules.hpp b/src/mlpack/methods/range_search/range_search_rules.hpp index 444dcdb67c..5777cd7487 100644 --- a/src/mlpack/methods/range_search/range_search_rules.hpp +++ b/src/mlpack/methods/range_search/range_search_rules.hpp @@ -20,10 +20,10 @@ namespace mlpack { * The RangeSearchRules class is a template helper class used by RangeSearch * class when performing range searches. * - * @tparam MetricType The metric to use for computation. + * @tparam DistanceType The distance metric to use for computation. * @tparam TreeType The tree type to use; must adhere to the TreeType API. */ -template +template class RangeSearchRules { public: @@ -41,7 +41,7 @@ class RangeSearchRules * @param range Range to search for. * @param neighbors Vector to store resulting neighbors in. * @param distances Vector to store resulting distances in. - * @param metric Instantiated metric. + * @param distance Instantiated distance metric. * @param sameSet If true, the query and reference set are taken to be the * same, and a query point will not return itself in the results. */ @@ -50,7 +50,7 @@ class RangeSearchRules const RangeType& range, std::vector >& neighbors, std::vector >& distances, - MetricType& metric, + DistanceType& distance, const bool sameSet = false); /** @@ -141,8 +141,8 @@ class RangeSearchRules //! The vector the resultant neighbor distances should be stored in. std::vector >& distances; - //! The instantiated metric. - MetricType& metric; + //! The instantiated distance metric. + DistanceType& distance; //! If true, the query and reference set are taken to be the same. bool sameSet; diff --git a/src/mlpack/methods/range_search/range_search_rules_impl.hpp b/src/mlpack/methods/range_search/range_search_rules_impl.hpp index ec6bc71af8..c94fe7d9bf 100644 --- a/src/mlpack/methods/range_search/range_search_rules_impl.hpp +++ b/src/mlpack/methods/range_search/range_search_rules_impl.hpp @@ -17,21 +17,21 @@ namespace mlpack { -template -RangeSearchRules::RangeSearchRules( +template +RangeSearchRules::RangeSearchRules( const MatType& referenceSet, const MatType& querySet, const RangeType& range, std::vector >& neighbors, std::vector >& distances, - MetricType& metric, + DistanceType& distance, const bool sameSet) : referenceSet(referenceSet), querySet(querySet), range(range), neighbors(neighbors), distances(distances), - metric(metric), + distance(distance), sameSet(sameSet), lastQueryIndex(querySet.n_cols), lastReferenceIndex(referenceSet.n_cols), @@ -43,10 +43,10 @@ RangeSearchRules::RangeSearchRules( //! The base case. Evaluate the distance between the two points and add to the //! results if necessary. -template +template inline mlpack_force_inline -typename RangeSearchRules::ElemType -RangeSearchRules::BaseCase( +typename RangeSearchRules::ElemType +RangeSearchRules::BaseCase( const size_t queryIndex, const size_t referenceIndex) { @@ -58,7 +58,7 @@ RangeSearchRules::BaseCase( if ((lastQueryIndex == queryIndex) && (lastReferenceIndex == referenceIndex)) return 0.0; // No value to return... this shouldn't do anything bad. - const ElemType distance = metric.Evaluate(querySet.unsafe_col(queryIndex), + const ElemType d = distance.Evaluate(querySet.unsafe_col(queryIndex), referenceSet.unsafe_col(referenceIndex)); ++baseCases; @@ -66,19 +66,19 @@ RangeSearchRules::BaseCase( lastQueryIndex = queryIndex; lastReferenceIndex = referenceIndex; - if (range.Contains(distance)) + if (range.Contains(d)) { neighbors[queryIndex].push_back(referenceIndex); - distances[queryIndex].push_back(distance); + distances[queryIndex].push_back(d); } - return distance; + return d; } //! Single-tree scoring function. -template -typename RangeSearchRules::ElemType -RangeSearchRules::Score(const size_t queryIndex, +template +typename RangeSearchRules::ElemType +RangeSearchRules::Score(const size_t queryIndex, TreeType& referenceNode) { // We must get the minimum and maximum distances and store them in this @@ -137,9 +137,9 @@ RangeSearchRules::Score(const size_t queryIndex, } //! Single-tree rescoring function. -template -typename RangeSearchRules::ElemType -RangeSearchRules::Rescore( +template +typename RangeSearchRules::ElemType +RangeSearchRules::Rescore( const size_t /* queryIndex */, TreeType& /* referenceNode */, const ElemType oldScore) const @@ -149,9 +149,9 @@ RangeSearchRules::Rescore( } //! Dual-tree scoring function. -template -typename RangeSearchRules::ElemType -RangeSearchRules::Score(TreeType& queryNode, +template +typename RangeSearchRules::ElemType +RangeSearchRules::Score(TreeType& queryNode, TreeType& referenceNode) { RangeType distances; @@ -212,9 +212,9 @@ RangeSearchRules::Score(TreeType& queryNode, } //! Dual-tree rescoring function. -template -typename RangeSearchRules::ElemType -RangeSearchRules::Rescore( +template +typename RangeSearchRules::ElemType +RangeSearchRules::Rescore( TreeType& /* queryNode */, TreeType& /* referenceNode */, const ElemType oldScore) const @@ -225,9 +225,9 @@ RangeSearchRules::Rescore( //! Add all the points in the given node to the results for the given query //! point. -template -void RangeSearchRules::AddResult(const size_t queryIndex, - TreeType& referenceNode) +template +void RangeSearchRules::AddResult( + const size_t queryIndex, TreeType& referenceNode) { // Some types of trees calculate the base case evaluation before Score() is // called, so if the base case has already been calculated, then we must avoid @@ -255,11 +255,11 @@ void RangeSearchRules::AddResult(const size_t queryIndex, (queryIndex == referenceNode.Descendant(i))) continue; - const ElemType distance = metric.Evaluate(querySet.unsafe_col(queryIndex), + const ElemType d = distance.Evaluate(querySet.unsafe_col(queryIndex), referenceNode.Dataset().unsafe_col(referenceNode.Descendant(i))); neighbors[queryIndex].push_back(referenceNode.Descendant(i)); - distances[queryIndex].push_back(distance); + distances[queryIndex].push_back(d); } } diff --git a/src/mlpack/methods/range_search/rs_model.hpp b/src/mlpack/methods/range_search/rs_model.hpp index 03ed715209..4753c80668 100644 --- a/src/mlpack/methods/range_search/rs_model.hpp +++ b/src/mlpack/methods/range_search/rs_model.hpp @@ -82,7 +82,7 @@ class RSWrapperBase /** * RSWrapper is a wrapper class for most RangeSearch types. */ -template class TreeType> class RSWrapper : public RSWrapperBase @@ -156,7 +156,7 @@ class RSWrapper : public RSWrapperBase * the leaf size into account when building trees. The implementations of * Train() and bichromatic Search() take this leaf size into account. */ -template class TreeType> class LeafSizeRSWrapper : public RSWrapper diff --git a/src/mlpack/methods/range_search/rs_model_impl.hpp b/src/mlpack/methods/range_search/rs_model_impl.hpp index badafa753b..ee2f88c19c 100644 --- a/src/mlpack/methods/range_search/rs_model_impl.hpp +++ b/src/mlpack/methods/range_search/rs_model_impl.hpp @@ -289,7 +289,7 @@ inline void RSModel::CleanMemory() delete rSearch; } -template class TreeType> void RSWrapper::Train(util::Timers& timers, @@ -304,7 +304,7 @@ void RSWrapper::Train(util::Timers& timers, timers.Stop("tree_building"); } -template class TreeType> void RSWrapper::Search(util::Timers& timers, @@ -333,7 +333,7 @@ void RSWrapper::Search(util::Timers& timers, } } -template class TreeType> void RSWrapper::Search(util::Timers& timers, @@ -346,7 +346,7 @@ void RSWrapper::Search(util::Timers& timers, timers.Stop("computing_neighbors"); } -template class TreeType> void LeafSizeRSWrapper::Train(util::Timers& timers, @@ -374,7 +374,7 @@ void LeafSizeRSWrapper::Train(util::Timers& timers, } } -template class TreeType> void LeafSizeRSWrapper::Search( diff --git a/src/mlpack/methods/rann/ra_model.hpp b/src/mlpack/methods/rann/ra_model.hpp index 9fe5cf9d53..9e31c04176 100644 --- a/src/mlpack/methods/rann/ra_model.hpp +++ b/src/mlpack/methods/rann/ra_model.hpp @@ -105,7 +105,7 @@ class RAWrapperBase /** * RAWrapper is a wrapper class for most RASearch types. */ -template class TreeType> class RAWrapper : public RAWrapperBase @@ -207,7 +207,7 @@ class RAWrapper : public RAWrapperBase * leaf size into account when building trees. The implementations of Train() * and bichromatic Search() take this leaf size into account. */ -template class TreeType> class LeafSizeRAWrapper : public RAWrapper diff --git a/src/mlpack/methods/rann/ra_model_impl.hpp b/src/mlpack/methods/rann/ra_model_impl.hpp index 813b5ba992..ea2ad4ef96 100644 --- a/src/mlpack/methods/rann/ra_model_impl.hpp +++ b/src/mlpack/methods/rann/ra_model_impl.hpp @@ -238,7 +238,7 @@ inline std::string RAModel::TreeName() const } } -template class TreeType> void RAWrapper::Train(util::Timers& timers, @@ -254,7 +254,7 @@ void RAWrapper::Train(util::Timers& timers, timers.Stop("tree_building"); } -template class TreeType> void RAWrapper::Search(util::Timers& timers, @@ -283,7 +283,7 @@ void RAWrapper::Search(util::Timers& timers, } } -template class TreeType> void RAWrapper::Search(util::Timers& timers, @@ -296,7 +296,7 @@ void RAWrapper::Search(util::Timers& timers, timers.Stop("computing_neighbors"); } -template class TreeType> void LeafSizeRAWrapper::Train(util::Timers& timers, @@ -326,7 +326,7 @@ void LeafSizeRAWrapper::Train(util::Timers& timers, } } -template class TreeType> void LeafSizeRAWrapper::Search(util::Timers& timers, diff --git a/src/mlpack/methods/rann/ra_query_stat.hpp b/src/mlpack/methods/rann/ra_query_stat.hpp index 2e381f125e..6db406b612 100644 --- a/src/mlpack/methods/rann/ra_query_stat.hpp +++ b/src/mlpack/methods/rann/ra_query_stat.hpp @@ -17,7 +17,7 @@ #include -#include +#include #include namespace mlpack { diff --git a/src/mlpack/methods/rann/ra_search.hpp b/src/mlpack/methods/rann/ra_search.hpp index c36c23a343..2bed1d61a8 100644 --- a/src/mlpack/methods/rann/ra_search.hpp +++ b/src/mlpack/methods/rann/ra_search.hpp @@ -35,7 +35,7 @@ namespace mlpack { // Forward declaration. -template class TreeType> class LeafSizeRAWrapper; @@ -61,26 +61,26 @@ class LeafSizeRAWrapper; * RASearch is currently known to not work with ball trees (#356). * * @tparam SortPolicy The sort policy for distances; see NearestNeighborSort. - * @tparam MetricType The metric to use for computation. + * @tparam DistanceType The distance metric to use for computation. * @tparam TreeType The tree type to use. */ template class TreeType = KDTree> class RASearch { public: //! Convenience typedef. - typedef TreeType, MatType> Tree; + typedef TreeType, MatType> Tree; /** * Initialize the RASearch object, passing both a reference dataset (this is * the dataset that will be searched). Optionally, perform the computation in * naive mode or single-tree mode. An initialized distance metric can be - * given, for cases where the metric has internal data (i.e. the + * given, for cases where the distance metric has internal data (i.e. the * distance::MahalanobisDistance class). * * This method will copy the matrices to internal copies, which are rearranged @@ -109,7 +109,7 @@ class RASearch * @param singleMode If true, single-tree search will be used (as opposed to * dual-tree search). This is useful when Search() will be called with * few query points. - * @param metric An optional instance of the MetricType class. + * @param distance An optional instance of the DistanceType class. * @param tau The rank-approximation in percentile of the data. The default * value is 5%. * @param alpha The desired success probability. The default value is 0.95. @@ -129,7 +129,7 @@ class RASearch const bool sampleAtLeaves = false, const bool firstLeafExact = false, const size_t singleSampleLimit = 20, - const MetricType metric = MetricType()); + const DistanceType distance = DistanceType()); /** * Initialize the RASearch object with the given pre-constructed reference @@ -176,7 +176,7 @@ class RASearch * if there exists one. This defaults to 'false' for now. * @param singleSampleLimit The limit on the largest node that can be * approximated by sampling. This defaults to 20. - * @param metric Instantiated distance metric. + * @param distance Instantiated distance metric. */ RASearch(Tree* referenceTree, const bool singleMode = false, @@ -185,7 +185,7 @@ class RASearch const bool sampleAtLeaves = false, const bool firstLeafExact = false, const size_t singleSampleLimit = 20, - const MetricType metric = MetricType()); + const DistanceType distance = DistanceType()); /** * Create an RASearch object with no reference data. If Search() is called @@ -204,7 +204,7 @@ class RASearch * if there exists one. This defaults to 'false' for now. * @param singleSampleLimit The limit on the largest node that can be * approximated by sampling. This defaults to 20. - * @param metric Instantiated distance metric. + * @param distance Instantiated distance metric. */ RASearch(const bool naive = false, const bool singleMode = false, @@ -213,7 +213,7 @@ class RASearch const bool sampleAtLeaves = false, const bool firstLeafExact = false, const size_t singleSampleLimit = 20, - const MetricType metric = MetricType()); + const DistanceType distance = DistanceType()); /** * Delete the RASearch object. The tree is the only member we are @@ -388,8 +388,8 @@ class RASearch //! approximated by sampling. size_t singleSampleLimit; - //! Instantiation of kernel. - MetricType metric; + //! Instantiation of distance metric. + DistanceType distance; //! For access to mappings when building models. friend class LeafSizeRAWrapper; diff --git a/src/mlpack/methods/rann/ra_search_impl.hpp b/src/mlpack/methods/rann/ra_search_impl.hpp index c918d0d8d9..e766808a91 100644 --- a/src/mlpack/methods/rann/ra_search_impl.hpp +++ b/src/mlpack/methods/rann/ra_search_impl.hpp @@ -21,12 +21,12 @@ namespace mlpack { // Construct the object, taking ownership of the data matrix. template class TreeType> -RASearch:: +RASearch:: RASearch(MatType referenceSetIn, const bool naive, const bool singleMode, @@ -35,7 +35,7 @@ RASearch(MatType referenceSetIn, const bool sampleAtLeaves, const bool firstLeafExact, const size_t singleSampleLimit, - const MetricType metric) : + const DistanceType distance) : referenceTree(naive ? NULL : BuildTree( std::move(referenceSetIn), oldFromNewReferences)), referenceSet(naive ? new MatType(std::move(referenceSetIn)) : @@ -49,19 +49,19 @@ RASearch(MatType referenceSetIn, sampleAtLeaves(sampleAtLeaves), firstLeafExact(firstLeafExact), singleSampleLimit(singleSampleLimit), - metric(metric) + distance(distance) { // Nothing to do. } // Construct the object. template class TreeType> -RASearch:: +RASearch:: RASearch(Tree* referenceTree, const bool singleMode, const double tau, @@ -69,7 +69,7 @@ RASearch(Tree* referenceTree, const bool sampleAtLeaves, const bool firstLeafExact, const size_t singleSampleLimit, - const MetricType metric) : + const DistanceType distance) : referenceTree(referenceTree), referenceSet(&referenceTree->Dataset()), treeOwner(false), @@ -81,18 +81,18 @@ RASearch(Tree* referenceTree, sampleAtLeaves(sampleAtLeaves), firstLeafExact(firstLeafExact), singleSampleLimit(singleSampleLimit), - metric(metric) + distance(distance) // Nothing else to initialize. { } // Empty constructor. template class TreeType> -RASearch:: +RASearch:: RASearch(const bool naive, const bool singleMode, const double tau, @@ -100,7 +100,7 @@ RASearch(const bool naive, const bool sampleAtLeaves, const bool firstLeafExact, const size_t singleSampleLimit, - const MetricType metric) : + const DistanceType distance) : referenceTree(NULL), referenceSet(new MatType()), treeOwner(false), @@ -112,7 +112,7 @@ RASearch(const bool naive, sampleAtLeaves(sampleAtLeaves), firstLeafExact(firstLeafExact), singleSampleLimit(singleSampleLimit), - metric(metric) + distance(distance) { // Build the tree on the empty dataset, if necessary. if (!naive) @@ -127,12 +127,12 @@ RASearch(const bool naive, * deleting. The others will take care of themselves. */ template class TreeType> -RASearch:: +RASearch:: ~RASearch() { if (treeOwner && referenceTree) @@ -143,12 +143,12 @@ RASearch:: // Train on a new reference set. template class TreeType> -void RASearch::Train( +void RASearch::Train( MatType referenceSet) { // Clean up the old tree, if we built one. @@ -185,12 +185,12 @@ void RASearch::Train( //! Set the reference tree to a new reference tree. template class TreeType> -void RASearch::Train( +void RASearch::Train( Tree* referenceTree) { if (naive) @@ -213,12 +213,12 @@ void RASearch::Train( * distances. */ template class TreeType> -void RASearch:: +void RASearch:: Search(const MatType& querySet, const size_t k, arma::Mat& neighbors, @@ -260,11 +260,11 @@ Search(const MatType& querySet, neighborPtr->set_size(k, querySet.n_cols); distancePtr->set_size(k, querySet.n_cols); - typedef RASearchRules RuleType; + typedef RASearchRules RuleType; if (naive) { - RuleType rules(*referenceSet, querySet, k, metric, tau, alpha, naive, + RuleType rules(*referenceSet, querySet, k, distance, tau, alpha, naive, sampleAtLeaves, firstLeafExact, singleSampleLimit, false); // Find how many samples from the reference set we need and sample uniformly @@ -284,7 +284,7 @@ Search(const MatType& querySet, } else if (singleMode) { - RuleType rules(*referenceSet, querySet, k, metric, tau, alpha, naive, + RuleType rules(*referenceSet, querySet, k, distance, tau, alpha, naive, sampleAtLeaves, firstLeafExact, singleSampleLimit, false); // If the reference root node is a leaf, then the sampling has already been @@ -316,7 +316,7 @@ Search(const MatType& querySet, Tree* queryTree = BuildTree(const_cast(querySet), oldFromNewQueries); - RuleType rules(*referenceSet, queryTree->Dataset(), k, metric, tau, alpha, + RuleType rules(*referenceSet, queryTree->Dataset(), k, distance, tau, alpha, naive, sampleAtLeaves, firstLeafExact, singleSampleLimit, false); typename Tree::template DualTreeTraverser traverser(rules); @@ -395,12 +395,12 @@ Search(const MatType& querySet, } template class TreeType> -void RASearch::Search( +void RASearch::Search( Tree* queryTree, const size_t k, arma::Mat& neighbors, @@ -424,8 +424,8 @@ void RASearch::Search( distances.set_size(k, querySet.n_cols); // Create the helper object for the tree traversal. - typedef RASearchRules RuleType; - RuleType rules(*referenceSet, queryTree->Dataset(), k, metric, tau, alpha, + typedef RASearchRules RuleType; + RuleType rules(*referenceSet, queryTree->Dataset(), k, distance, tau, alpha, naive, sampleAtLeaves, firstLeafExact, singleSampleLimit, false); // Create the traverser. @@ -451,12 +451,12 @@ void RASearch::Search( } template class TreeType> -void RASearch::Search( +void RASearch::Search( const size_t k, arma::Mat& neighbors, arma::mat& distances) @@ -476,8 +476,8 @@ void RASearch::Search( distancePtr->set_size(k, referenceSet->n_cols); // Create the helper object for the tree traversal. - typedef RASearchRules RuleType; - RuleType rules(*referenceSet, *referenceSet, k, metric, tau, alpha, naive, + typedef RASearchRules RuleType; + RuleType rules(*referenceSet, *referenceSet, k, distance, tau, alpha, naive, sampleAtLeaves, firstLeafExact, singleSampleLimit, true /* same sets */); if (naive) @@ -537,12 +537,12 @@ void RASearch::Search( } template class TreeType> -void RASearch::ResetQueryTree( +void RASearch::ResetQueryTree( Tree* queryNode) const { queryNode->Stat().Bound() = SortPolicy::WorstDistance(); @@ -553,13 +553,13 @@ void RASearch::ResetQueryTree( } template class TreeType> template -void RASearch::serialize( +void RASearch::serialize( Archive& ar, const uint32_t /* version */) { // Serialize preferences for search. @@ -584,7 +584,7 @@ void RASearch::serialize( setOwner = true; } ar(CEREAL_POINTER(const_cast(referenceSet))); - ar(CEREAL_NVP(metric)); + ar(CEREAL_NVP(distance)); // If we are loading, set the tree to NULL and clean up memory if necessary. if (cereal::is_loading()) @@ -620,7 +620,7 @@ void RASearch::serialize( delete referenceSet; referenceSet = &referenceTree->Dataset(); - metric = referenceTree->Metric(); + distance = referenceTree->Distance(); setOwner = false; } } diff --git a/src/mlpack/methods/rann/ra_search_rules.hpp b/src/mlpack/methods/rann/ra_search_rules.hpp index d056cb0894..da203b0c91 100644 --- a/src/mlpack/methods/rann/ra_search_rules.hpp +++ b/src/mlpack/methods/rann/ra_search_rules.hpp @@ -25,10 +25,10 @@ namespace mlpack { * when performing rank-approximate search via random-sampling. * * @tparam SortPolicy The sort policy for distances. - * @tparam MetricType The metric to use for computation. + * @tparam DistanceType The distance metric to use for computation. * @tparam TreeType The tree type to use; must adhere to the TreeType API. */ -template +template class RASearchRules { public: @@ -39,7 +39,7 @@ class RASearchRules * @param referenceSet Set of reference data. * @param querySet Set of query data. * @param k Number of neighbors to search for. - * @param metric Instantiated metric. + * @param distance Instantiated distance metric. * @param tau The rank-approximation in percentile of the data. * @param alpha The desired success probability. * @param naive If true, the rank-approximate search will be performed by @@ -56,7 +56,7 @@ class RASearchRules RASearchRules(const arma::mat& referenceSet, const arma::mat& querySet, const size_t k, - MetricType& metric, + DistanceType& distance, const double tau = 5, const double alpha = 0.95, const bool naive = false, @@ -273,8 +273,8 @@ class RASearchRules //! Number of neighbors to search for. const size_t k; - //! The instantiated metric. - MetricType& metric; + //! The instantiated distance metric. + DistanceType& distance; //! Whether to sample at leaves or just use all of it. bool sampleAtLeaves; diff --git a/src/mlpack/methods/rann/ra_search_rules_impl.hpp b/src/mlpack/methods/rann/ra_search_rules_impl.hpp index b90f12ce7b..5253f1ac87 100644 --- a/src/mlpack/methods/rann/ra_search_rules_impl.hpp +++ b/src/mlpack/methods/rann/ra_search_rules_impl.hpp @@ -17,12 +17,12 @@ namespace mlpack { -template -RASearchRules:: +template +RASearchRules:: RASearchRules(const arma::mat& referenceSet, const arma::mat& querySet, const size_t k, - MetricType& metric, + DistanceType& distance, const double tau, const double alpha, const bool naive, @@ -33,7 +33,7 @@ RASearchRules(const arma::mat& referenceSet, referenceSet(referenceSet), querySet(querySet), k(k), - metric(metric), + distance(distance), sampleAtLeaves(sampleAtLeaves), firstLeafExact(firstLeafExact), singleSampleLimit(singleSampleLimit), @@ -94,8 +94,8 @@ RASearchRules(const arma::mat& referenceSet, } } -template -void RASearchRules::GetResults( +template +void RASearchRules::GetResults( arma::Mat& neighbors, arma::mat& distances) { @@ -114,9 +114,9 @@ void RASearchRules::GetResults( } }; -template +template inline mlpack_force_inline -double RASearchRules::BaseCase( +double RASearchRules::BaseCase( const size_t queryIndex, const size_t referenceIndex) { @@ -125,56 +125,56 @@ double RASearchRules::BaseCase( if (sameSet && (queryIndex == referenceIndex)) return 0.0; - double distance = metric.Evaluate(querySet.unsafe_col(queryIndex), - referenceSet.unsafe_col(referenceIndex)); + double d = distance.Evaluate(querySet.unsafe_col(queryIndex), + referenceSet.unsafe_col(referenceIndex)); - InsertNeighbor(queryIndex, referenceIndex, distance); + InsertNeighbor(queryIndex, referenceIndex, d); numSamplesMade[queryIndex]++; numDistComputations++; - return distance; + return d; } -template -inline double RASearchRules::Score( +template +inline double RASearchRules::Score( const size_t queryIndex, TreeType& referenceNode) { const arma::vec queryPoint = querySet.unsafe_col(queryIndex); - const double distance = SortPolicy::BestPointToNodeDistance(queryPoint, + const double d = SortPolicy::BestPointToNodeDistance(queryPoint, &referenceNode); const double bestDistance = candidates[queryIndex].top().first; - return Score(queryIndex, referenceNode, distance, bestDistance); + return Score(queryIndex, referenceNode, d, bestDistance); } -template -inline double RASearchRules::Score( +template +inline double RASearchRules::Score( const size_t queryIndex, TreeType& referenceNode, const double baseCaseResult) { const arma::vec queryPoint = querySet.unsafe_col(queryIndex); - const double distance = SortPolicy::BestPointToNodeDistance(queryPoint, + const double d = SortPolicy::BestPointToNodeDistance(queryPoint, &referenceNode, baseCaseResult); const double bestDistance = candidates[queryIndex].top().first; - return Score(queryIndex, referenceNode, distance, bestDistance); + return Score(queryIndex, referenceNode, d, bestDistance); } -template -inline double RASearchRules::Score( +template +inline double RASearchRules::Score( const size_t queryIndex, TreeType& referenceNode, - const double distance, + const double dist, const double bestDistance) { // If this is better than the best distance we've seen so far, maybe there // will be something down this node. Also check if enough samples are already // made for this query. - if (SortPolicy::IsBetter(distance, bestDistance) + if (SortPolicy::IsBetter(dist, bestDistance) && numSamplesMade[queryIndex] < numSamplesReqd) { // We cannot prune this node; try approximating it by sampling. @@ -192,7 +192,7 @@ inline double RASearchRules::Score( if (samplesReqd > singleSampleLimit && !referenceNode.IsLeaf()) { // If too many samples required and not at a leaf, then can't prune. - return distance; + return dist; } else { @@ -229,7 +229,7 @@ inline double RASearchRules::Score( else { // Not allowed to sample from leaves, so cannot prune. - return distance; + return dist; } } } @@ -238,7 +238,7 @@ inline double RASearchRules::Score( { // Try first to visit the first leaf to boost your accuracy and find // (near) duplicates if they exist. - return distance; + return dist; } } else @@ -258,8 +258,8 @@ inline double RASearchRules::Score( } } -template -inline double RASearchRules:: +template +inline double RASearchRules:: Rescore(const size_t queryIndex, TreeType& referenceNode, const double oldScore) @@ -350,16 +350,16 @@ Rescore(const size_t queryIndex, } } // Rescore(point, node, oldScore) -template -inline double RASearchRules::Score( +template +inline double RASearchRules::Score( TreeType& queryNode, TreeType& referenceNode) { // First try to find the distance bound to check if we can prune by distance. // Calculate the best node-to-node distance. - const double distance = SortPolicy::BestNodeToNodeDistance(&queryNode, - &referenceNode); + const double dist = SortPolicy::BestNodeToNodeDistance(&queryNode, + &referenceNode); double pointBound = DBL_MAX; double childBound = DBL_MAX; @@ -384,11 +384,11 @@ inline double RASearchRules::Score( queryNode.Stat().Bound() = std::min(pointBound, childBound); const double bestDistance = queryNode.Stat().Bound(); - return Score(queryNode, referenceNode, distance, bestDistance); + return Score(queryNode, referenceNode, dist, bestDistance); } -template -inline double RASearchRules::Score( +template +inline double RASearchRules::Score( TreeType& queryNode, TreeType& referenceNode, const double baseCaseResult) @@ -397,7 +397,7 @@ inline double RASearchRules::Score( // by distance. // Find the best node-to-node distance. - const double distance = SortPolicy::BestNodeToNodeDistance(&queryNode, + const double dist = SortPolicy::BestNodeToNodeDistance(&queryNode, &referenceNode, baseCaseResult); double pointBound = DBL_MAX; @@ -423,14 +423,14 @@ inline double RASearchRules::Score( queryNode.Stat().Bound() = std::min(pointBound, childBound); const double bestDistance = queryNode.Stat().Bound(); - return Score(queryNode, referenceNode, distance, bestDistance); + return Score(queryNode, referenceNode, dist, bestDistance); } -template -inline double RASearchRules::Score( +template +inline double RASearchRules::Score( TreeType& queryNode, TreeType& referenceNode, - const double distance, + const double dist, const double bestDistance) { // Update the number of samples made for this node -- propagate up from child @@ -463,7 +463,7 @@ inline double RASearchRules::Score( // If this is better than the best distance we've seen so far, maybe there // will be something down this node. Also check if enough samples are already // made for this 'queryNode'. - if (SortPolicy::IsBetter(distance, bestDistance) + if (SortPolicy::IsBetter(dist, bestDistance) && queryNode.Stat().NumSamplesMade() < numSamplesReqd) { // We cannot prune this node; try approximating this node by sampling. @@ -492,7 +492,7 @@ inline double RASearchRules::Score( queryNode.Stat().NumSamplesMade(), queryNode.Child(i).Stat().NumSamplesMade()); - return distance; + return dist; } else { @@ -566,7 +566,7 @@ inline double RASearchRules::Score( queryNode.Stat().NumSamplesMade(), queryNode.Child(i).Stat().NumSamplesMade()); - return distance; + return dist; } } } @@ -581,7 +581,7 @@ inline double RASearchRules::Score( queryNode.Stat().NumSamplesMade(), queryNode.Child(i).Stat().NumSamplesMade()); - return distance; + return dist; } } else @@ -604,8 +604,8 @@ inline double RASearchRules::Score( } } -template -inline double RASearchRules:: +template +inline double RASearchRules:: Rescore(TreeType& queryNode, TreeType& referenceNode, const double oldScore) @@ -796,17 +796,17 @@ Rescore(TreeType& queryNode, * * @param queryIndex Index of point whose neighbors we are inserting into. * @param neighbor Index of reference point which is being inserted. - * @param distance Distance from query point to reference point. + * @param dist Distance from query point to reference point. */ -template -inline void RASearchRules:: +template +inline void RASearchRules:: InsertNeighbor( const size_t queryIndex, const size_t neighbor, - const double distance) + const double dist) { CandidateList& pqueue = candidates[queryIndex]; - Candidate c = std::make_pair(distance, neighbor); + Candidate c = std::make_pair(dist, neighbor); if (CandidateCmp()(c, pqueue.top())) { diff --git a/src/mlpack/methods/rann/ra_typedef.hpp b/src/mlpack/methods/rann/ra_typedef.hpp index 83d9e15b64..f432837b33 100644 --- a/src/mlpack/methods/rann/ra_typedef.hpp +++ b/src/mlpack/methods/rann/ra_typedef.hpp @@ -16,7 +16,7 @@ // In case someone included this directly. #include "ra_search.hpp" -#include +#include #include #include diff --git a/src/mlpack/methods/reinforcement_learning/policy/aggregated_policy.hpp b/src/mlpack/methods/reinforcement_learning/policy/aggregated_policy.hpp index d6b587c5df..719fe8091d 100644 --- a/src/mlpack/methods/reinforcement_learning/policy/aggregated_policy.hpp +++ b/src/mlpack/methods/reinforcement_learning/policy/aggregated_policy.hpp @@ -15,7 +15,7 @@ #define MLPACK_METHODS_RL_POLICY_AGGREGATED_POLICY_HPP #include -#include +#include namespace mlpack { diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index 419a806501..9245c06344 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -57,6 +57,7 @@ add_executable(mlpack_test decision_tree_test.cpp det_test.cpp digamma_test.cpp + distance_test.cpp distribution_test.cpp drusilla_select_test.cpp emst_test.cpp diff --git a/src/mlpack/tests/dbscan_test.cpp b/src/mlpack/tests/dbscan_test.cpp index 99751313da..0c5617d87b 100644 --- a/src/mlpack/tests/dbscan_test.cpp +++ b/src/mlpack/tests/dbscan_test.cpp @@ -22,11 +22,11 @@ using namespace mlpack; * These will be removed when we refactor the Bounds to accept MatType. * For now, we will keep the following declarations. */ -template -using FloatHRectBound = HRectBound; +template +using FloatHRectBound = HRectBound; -template -using FloatKDTree = BinarySpaceTree +using FloatKDTree = BinarySpaceTree; TEST_CASE("OneClusterTest", "[DBSCANTest]") diff --git a/src/mlpack/tests/distance_test.cpp b/src/mlpack/tests/distance_test.cpp new file mode 100644 index 0000000000..de16a5427d --- /dev/null +++ b/src/mlpack/tests/distance_test.cpp @@ -0,0 +1,344 @@ +/** + * @file tests/distance_test.cpp + * + * Unit tests for the various distance metrics. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#include +#include "catch.hpp" +#include "test_catch_tools.hpp" + +using namespace std; +using namespace mlpack; + +/** + * Basic test of the Manhattan distance. + */ +TEST_CASE("ManhattanDistanceTest", "[DistanceTest]") +{ + // A couple quick tests. + arma::vec a = "1.0 3.0 4.0"; + arma::vec b = "3.0 3.0 5.0"; + + REQUIRE(ManhattanDistance::Evaluate(a, b) == Approx(3.0).epsilon(1e-7)); + REQUIRE(ManhattanDistance::Evaluate(b, a) == Approx(3.0).epsilon(1e-7)); + + // Check also for when the root is taken (should be the same). + REQUIRE((LMetric<1, true>::Evaluate(a, b)) == Approx(3.0).epsilon(1e-7)); + REQUIRE((LMetric<1, true>::Evaluate(b, a)) == Approx(3.0).epsilon(1e-7)); +} + +/** + * Basic test of squared Euclidean distance. + */ +TEST_CASE("SquaredEuclideanDistanceTest", "[DistanceTest]") +{ + // Sample 2-dimensional vectors. + arma::vec a = "1.0 2.0"; + arma::vec b = "0.0 -2.0"; + + REQUIRE(SquaredEuclideanDistance::Evaluate(a, b) == + Approx(17.0).epsilon(1e-7)); + REQUIRE(SquaredEuclideanDistance::Evaluate(b, a) == + Approx(17.0).epsilon(1e-7)); +} + +/** + * Basic test of Euclidean distance. + */ +TEST_CASE("EuclideanDistanceTest", "[DistanceTest]") +{ + arma::vec a = "1.0 3.0 5.0 7.0"; + arma::vec b = "4.0 0.0 2.0 0.0"; + + REQUIRE(EuclideanDistance::Evaluate(a, b) == + Approx(sqrt(76.0)).epsilon(1e-7)); + REQUIRE(EuclideanDistance::Evaluate(b, a) == + Approx(sqrt(76.0)).epsilon(1e-7)); +} + +/** + * Arbitrary test case for coverage. + */ +TEST_CASE("ArbitraryCaseTest", "[DistanceTest]") +{ + arma::vec a = "3.0 5.0 6.0 7.0"; + arma::vec b = "1.0 2.0 1.0 0.0"; + + REQUIRE((LMetric<3, false>::Evaluate(a, b)) == Approx(503.0).epsilon(1e-7)); + REQUIRE((LMetric<3, false>::Evaluate(b, a)) == Approx(503.0).epsilon(1e-7)); + + REQUIRE((LMetric<3, true>::Evaluate(a, b)) == + Approx(7.95284762).epsilon(1e-7)); + REQUIRE((LMetric<3, true>::Evaluate(b, a)) == + Approx(7.95284762).epsilon(1e-7)); +} + +/** + * Make sure two vectors of all zeros return zero distance, for a few different + * powers. + */ +TEST_CASE("LMetricZerosTest", "[DistanceTest]") +{ + arma::vec a(250); + a.fill(0.0); + + // We cannot use a loop because compilers seem to be unable to unroll the loop + // and realize the variable actually is knowable at compile-time. + REQUIRE(LMetric<1, false>::Evaluate(a, a) == 0); + REQUIRE(LMetric<1, true>::Evaluate(a, a) == 0); + REQUIRE(LMetric<2, false>::Evaluate(a, a) == 0); + REQUIRE(LMetric<2, true>::Evaluate(a, a) == 0); + REQUIRE(LMetric<3, false>::Evaluate(a, a) == 0); + REQUIRE(LMetric<3, true>::Evaluate(a, a) == 0); + REQUIRE(LMetric<4, false>::Evaluate(a, a) == 0); + REQUIRE(LMetric<4, true>::Evaluate(a, a) == 0); + REQUIRE(LMetric<5, false>::Evaluate(a, a) == 0); + REQUIRE(LMetric<5, true>::Evaluate(a, a) == 0); +} + +/** + * Simple test of Mahalanobis distance with unset covariance matrix in + * constructor. + */ +TEMPLATE_TEST_CASE("MDUnsetCovarianceTest", "[DistanceTest]", float, double) +{ + typedef TestType eT; + + MahalanobisDistance> md; + md.Q() = arma::eye>(4, 4); + arma::Col a = "1.0 2.0 2.0 3.0"; + arma::Col b = "0.0 0.0 1.0 3.0"; + + REQUIRE(md.Evaluate(a, b) == Approx(6.0).epsilon(1e-7)); + REQUIRE(md.Evaluate(b, a) == Approx(6.0).epsilon(1e-7)); +} + +/** + * Simple test of Mahalanobis distance with unset covariance matrix in + * constructor and t_take_root set to true. + */ +TEMPLATE_TEST_CASE("MDRootUnsetCovarianceTest", "[DistanceTest]", float, double) +{ + typedef TestType eT; + + MahalanobisDistance> md; + md.Q() = arma::eye>(4, 4); + arma::Col a = "1.0 2.0 2.5 5.0"; + arma::Col b = "0.0 2.0 0.5 8.0"; + + REQUIRE(md.Evaluate(a, b) == Approx(sqrt(14.0)).epsilon(1e-7)); + REQUIRE(md.Evaluate(b, a) == Approx(sqrt(14.0)).epsilon(1e-7)); +} + +/** + * Simple test of Mahalanobis distance setting identity covariance in + * constructor. + */ +TEMPLATE_TEST_CASE("MDEyeCovarianceTest", "[DistanceTest]", float, double) +{ + typedef TestType eT; + + MahalanobisDistance> md(4); + arma::Col a = "1.0 2.0 2.0 3.0"; + arma::Col b = "0.0 0.0 1.0 3.0"; + + REQUIRE(md.Evaluate(a, b) == Approx(6.0).epsilon(1e-7)); + REQUIRE(md.Evaluate(b, a) == Approx(6.0).epsilon(1e-7)); +} + +/** + * Simple test of Mahalanobis distance setting identity covariance in + * constructor and t_take_root set to true. + */ +TEMPLATE_TEST_CASE("MDRootEyeCovarianceTest", "[DistanceTest]", float, double) +{ + typedef TestType eT; + + MahalanobisDistance> md(4); + arma::Col a = "1.0 2.0 2.5 5.0"; + arma::Col b = "0.0 2.0 0.5 8.0"; + + REQUIRE(md.Evaluate(a, b) == Approx(sqrt(14.0)).epsilon(1e-7)); + REQUIRE(md.Evaluate(b, a) == Approx(sqrt(14.0)).epsilon(1e-7)); +} + +/** + * Simple test with diagonal covariance matrix. + */ +TEMPLATE_TEST_CASE("MDDiagonalCovarianceTest", "[DistanceTest]", float, double) +{ + typedef TestType eT; + + arma::Mat q = arma::eye>(5, 5); + q(0, 0) = 2.0; + q(1, 1) = 0.5; + q(2, 2) = 3.0; + q(3, 3) = 1.0; + q(4, 4) = 1.5; + MahalanobisDistance> md(std::move(q)); + + arma::Col a = "1.0 2.0 2.0 4.0 5.0"; + arma::Col b = "2.0 3.0 1.0 1.0 0.0"; + + REQUIRE(md.Evaluate(a, b) == Approx(52.0).epsilon(1e-7)); + REQUIRE(md.Evaluate(b, a) == Approx(52.0).epsilon(1e-7)); +} + +/** + * More specific case with more difficult covariance matrix. + */ +TEMPLATE_TEST_CASE("MDFullCovarianceTest", "[DistanceTest]", float, double) +{ + typedef TestType eT; + + arma::Mat q = "1.0 2.0 3.0 4.0;" + "0.5 0.6 0.7 0.1;" + "3.4 4.3 5.0 6.1;" + "1.0 2.0 4.0 1.0;"; + MahalanobisDistance> md(std::move(q)); + + arma::Col a = "1.0 2.0 2.0 4.0"; + arma::Col b = "2.0 3.0 1.0 1.0"; + + REQUIRE(md.Evaluate(a, b) == Approx(15.7).epsilon(1e-7)); + REQUIRE(md.Evaluate(b, a) == Approx(15.7).epsilon(1e-7)); +} + +/** + * Simple test for L-1 metric. + */ +TEST_CASE("L1MetricTest", "[DistanceTest]") +{ + arma::vec a1(5); + a1.randn(); + + arma::vec b1(5); + b1.randn(); + + arma::Col a2(5); + a2 = { 1, 2, 1, 0, 5 }; + + arma::Col b2(5); + b2 = { 2, 5, 2, 0, 1 }; + + ManhattanDistance lMetric; + + REQUIRE((double) accu(arma::abs(a1 - b1)) == + Approx(lMetric.Evaluate(a1, b1)).epsilon(1e-7)); + + REQUIRE((double) accu(arma::abs(a2 - b2)) == + Approx(lMetric.Evaluate(a2, b2)).epsilon(1e-7)); +} + +/** + * Simple test for L-2 metric. + */ +TEST_CASE("L2MetricTest", "[DistanceTest]") +{ + arma::vec a1(5); + a1.randn(); + + arma::vec b1(5); + b1.randn(); + + arma::vec a2(5); + a2 = { 1, 2, 1, 0, 5 }; + + arma::vec b2(5); + b2 = { 2, 5, 2, 0, 1 }; + + EuclideanDistance lMetric; + + REQUIRE((double) sqrt(accu(square(a1 - b1))) == + Approx(lMetric.Evaluate(a1, b1)).epsilon(1e-7)); + + REQUIRE((double) sqrt(accu(square(a2 - b2))) == + Approx(lMetric.Evaluate(a2, b2)).epsilon(1e-7)); +} + +/** + * Simple test for L-Infinity metric. + */ +TEST_CASE("LINFMetricTest", "[DistanceTest]") +{ + arma::vec a1(5); + a1.randn(); + + arma::vec b1(5); + b1.randn(); + + arma::Col a2(5); + a2 = { 1, 2, 1, 0, 5 }; + + arma::Col b2(5); + b2 = { 2, 5, 2, 0, 1 }; + + ChebyshevDistance lMetric; + + REQUIRE((double) arma::as_scalar(arma::max(arma::abs(a1 - b1))) == + Approx(lMetric.Evaluate(a1, b1)).epsilon(1e-7)); + + REQUIRE((double) arma::as_scalar(arma::max(arma::abs(a2 - b2))) == + Approx(lMetric.Evaluate(a2, b2)).epsilon(1e-7)); +} + +/** + * Simple test for IoU distance. + */ +TEST_CASE("IoUDistanceTest", "[DistanceTest]") +{ + arma::vec bbox1(4), bbox2(4); + bbox1 = { 1, 2, 100, 200 }; + bbox2 = { 1, 2, 100, 200 }; + // IoU of same bounding boxes equals 0.0. + REQUIRE(0.0 == Approx(IoUDistance<>::Evaluate(bbox1, bbox2)).epsilon(1e-6)); + + // Use coordinate system to represent bounding boxes. + // Bounding boxes represent {x0, y0, x1, y1}. + bbox1 = { 39, 63, 203, 112 }; + bbox2 = { 54, 66, 198, 114 }; + // Value calculated using Python interpreter. + REQUIRE(IoUDistance::Evaluate(bbox1, bbox2) == + Approx(1.0 - 0.7980093).epsilon(1e-6)); + + bbox1 = { 31, 69, 201, 125 }; + bbox2 = { 18, 63, 235, 135 }; + // Value calculated using Python interpreter. + REQUIRE(IoUDistance::Evaluate(bbox1, bbox2) == + Approx(1.0 - 0.612479577).epsilon(1e-6)); + + // Use hieght - width representation of bounding boxes. + // Bounding boxes represent {x0, y0, h, w}. + bbox1 = { 49, 75, 154, 50 }; + bbox2 = { 42, 78, 144, 48 }; + // Value calculated using Python interpreter. + REQUIRE(IoUDistance<>::Evaluate(bbox1, bbox2) == + Approx(1.0 - 0.7898879).epsilon(1e-6)); + + bbox1 = { 35, 51, 161, 59 }; + bbox2 = { 36, 60, 144, 48 }; + // Value calculated using Python interpreter. + REQUIRE(IoUDistance<>::Evaluate(bbox1, bbox2) == + Approx(1.0 - 0.7309670).epsilon(1e-6)); +} + +/** + * Mahalanobis Distance serialization test. + */ +TEST_CASE("MahalanobisDistanceSerializationTest", "[DistanceTest]") +{ + MahalanobisDistance<> d; + d.Q().randu(50, 50); + + MahalanobisDistance<> xmlD, jsonD, binaryD; + + SerializeObjectAll(d, xmlD, jsonD, binaryD); + + // Check the covariance matrices. + CheckMatrices(d.Q(), xmlD.Q(), jsonD.Q(), binaryD.Q()); +} diff --git a/src/mlpack/tests/distribution_test.cpp b/src/mlpack/tests/distribution_test.cpp index 9dc9e5755b..78dab01161 100644 --- a/src/mlpack/tests/distribution_test.cpp +++ b/src/mlpack/tests/distribution_test.cpp @@ -1191,25 +1191,6 @@ TEST_CASE("LaplaceDistributionLogProbabilityTest", "[DistributionTest]") Approx(-1.693147180559946).epsilon(1e-7)); } -/** - * Mahalanobis Distance serialization test. - */ -TEST_CASE("MahalanobisDistanceTest", "[DistributionTest]") -{ - MahalanobisDistance<> d; - d.Covariance().randu(50, 50); - - MahalanobisDistance<> xmlD, jsonD, binaryD; - - SerializeObjectAll(d, xmlD, jsonD, binaryD); - - // Check the covariance matrices. - CheckMatrices(d.Covariance(), - xmlD.Covariance(), - jsonD.Covariance(), - binaryD.Covariance()); -} - /** * Regression distribution serialization test. */ diff --git a/src/mlpack/tests/facilities_test.cpp b/src/mlpack/tests/facilities_test.cpp index 312391f36a..36e0a64155 100644 --- a/src/mlpack/tests/facilities_test.cpp +++ b/src/mlpack/tests/facilities_test.cpp @@ -2,7 +2,7 @@ * @file facilities_test.cpp * @author Khizir Siddiqui * - * Test file for facilities in metrics. + * Test file for facilities in distance metrics. * * mlpack is free software; you may redistribute it and/or modify it under the * terms of the 3-clause BSD license. You should have received a copy of the diff --git a/src/mlpack/tests/kde_test.cpp b/src/mlpack/tests/kde_test.cpp index 69f027bfd7..1f79bb4a38 100644 --- a/src/mlpack/tests/kde_test.cpp +++ b/src/mlpack/tests/kde_test.cpp @@ -23,13 +23,13 @@ void BruteForceKDE(const arma::mat& reference, arma::vec& densities, KernelType& kernel) { - EuclideanDistance metric; + EuclideanDistance distance; for (size_t i = 0; i < query.n_cols; ++i) { for (size_t j = 0; j < reference.n_cols; ++j) { - double distance = metric.Evaluate(query.col(i), reference.col(j)); - densities(i) += kernel.Evaluate(distance); + double dist = distance.Evaluate(query.col(i), reference.col(j)); + densities(i) += kernel.Evaluate(dist); } } densities /= reference.n_cols; @@ -137,9 +137,9 @@ TEST_CASE("GaussianKDEBruteForceTest", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE kde( - relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, metric); + relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, treeEstimations); @@ -168,9 +168,9 @@ TEST_CASE("GaussianSingleKDEBruteForceTest", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE kde( - relError, 0.0, kernel, KDEMode::KDE_SINGLE_TREE_MODE, metric); + relError, 0.0, kernel, KDEMode::KDE_SINGLE_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, treeEstimations); @@ -200,9 +200,9 @@ TEST_CASE("EpanechnikovCoverSingleKDETest", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE - kde(relError, 0.0, kernel, KDEMode::KDE_SINGLE_TREE_MODE, metric); + kde(relError, 0.0, kernel, KDEMode::KDE_SINGLE_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, treeEstimations); @@ -232,9 +232,9 @@ TEST_CASE("GaussianCoverSingleKDETest", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE - kde(relError, 0.0, kernel, KDEMode::KDE_SINGLE_TREE_MODE, metric); + kde(relError, 0.0, kernel, KDEMode::KDE_SINGLE_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, treeEstimations); @@ -264,9 +264,9 @@ TEST_CASE("EpanechnikovOctreeSingleKDETest", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE kde( - relError, 0.0, kernel, KDEMode::KDE_SINGLE_TREE_MODE, metric); + relError, 0.0, kernel, KDEMode::KDE_SINGLE_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, treeEstimations); @@ -335,9 +335,9 @@ TEST_CASE("OctreeGaussianKDETest", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE kde( - relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, metric); + relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, treeEstimations); @@ -366,9 +366,9 @@ TEST_CASE("RTreeGaussianKDETest", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE kde( - relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, metric); + relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, treeEstimations); @@ -398,9 +398,9 @@ TEST_CASE("StandardCoverTreeGaussianKDETest", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE - kde(relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, metric); + kde(relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, treeEstimations); @@ -430,12 +430,12 @@ TEST_CASE("StandardCoverTreeEpanechnikovKDETest", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE - kde(relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, metric); + kde(relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, treeEstimations); @@ -542,14 +542,14 @@ TEST_CASE("BreadthFirstKDETest", "[KDETest]") kernel); // Breadth-First KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE::template BreadthFirstDualTreeTraverser> - kde(relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, metric); + kde(relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, treeEstimations); @@ -578,9 +578,9 @@ TEST_CASE("OneDimensionalTest", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE kde( - relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, metric); + relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, treeEstimations); @@ -601,10 +601,10 @@ TEST_CASE("EmptyReferenceTest", "[KDETest]") const double relError = 0.01; // KDE. - EuclideanDistance metric; + EuclideanDistance distance; GaussianKernel kernel(kernelBandwidth); KDE kde( - relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, metric); + relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, distance); // When training using the dataset matrix. REQUIRE_THROWS_AS(kde.Train(reference), std::invalid_argument); @@ -631,12 +631,12 @@ TEST_CASE("EvaluationMatchDimensionsTest", "[KDETest]") const double relError = 0.01; // KDE. - EuclideanDistance metric; + EuclideanDistance distance; GaussianKernel kernel(kernelBandwidth); KDE kde(relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, metric); + KDTree> kde(relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, distance); kde.Train(reference); // When evaluating using the query dataset matrix. @@ -665,12 +665,12 @@ TEST_CASE("EmptyQuerySetTest", "[KDETest]") const double relError = 0.01; // KDE. - EuclideanDistance metric; + EuclideanDistance distance; GaussianKernel kernel(kernelBandwidth); KDE kde(relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, metric); + KDTree> kde(relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, distance); kde.Train(reference); // The query set must be empty. @@ -896,13 +896,13 @@ TEST_CASE("GaussianSingleKDTreeMonteCarloKDE", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE kde( relError, 0.0, kernel, KDEMode::KDE_SINGLE_TREE_MODE, - metric, + distance, true, 0.95, 100, @@ -946,13 +946,13 @@ TEST_CASE("GaussianSingleCoverTreeMonteCarloKDE", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE kde(relError, 0.0, kernel, KDEMode::KDE_SINGLE_TREE_MODE, - metric, + distance, true, 0.95, 100, @@ -996,13 +996,13 @@ TEST_CASE("GaussianSingleOctreeMonteCarloKDE", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE kde( relError, 0.0, kernel, KDEMode::KDE_SINGLE_TREE_MODE, - metric, + distance, true, 0.95, 100, @@ -1046,13 +1046,13 @@ TEST_CASE("GaussianDualKDTreeMonteCarloKDE", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE kde( relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, - metric, + distance, true, 0.95, 100, @@ -1096,13 +1096,13 @@ TEST_CASE("GaussianDualCoverTreeMonteCarloKDE", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE kde(relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, - metric, + distance, true, 0.95, 100, @@ -1146,13 +1146,13 @@ TEST_CASE("GaussianDualOctreeMonteCarloKDE", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE kde( relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, - metric, + distance, true, 0.95, 100, @@ -1196,7 +1196,7 @@ TEST_CASE("GaussianBreadthDualKDTreeMonteCarloKDE", "[KDETest]") kernel); // Optimized KDE. - EuclideanDistance metric; + EuclideanDistance distance; KDE::Evaluate(a, b)) == Approx(3.0).epsilon(1e-7)); - REQUIRE((LMetric<1, true>::Evaluate(b, a)) == Approx(3.0).epsilon(1e-7)); -} - -/** - * Basic test of squared Euclidean distance. - */ -TEST_CASE("SquaredEuclideanDistanceTest", "[KernelTest]") -{ - // Sample 2-dimensional vectors. - arma::vec a = "1.0 2.0"; - arma::vec b = "0.0 -2.0"; - - REQUIRE(SquaredEuclideanDistance::Evaluate(a, b) == - Approx(17.0).epsilon(1e-7)); - REQUIRE(SquaredEuclideanDistance::Evaluate(b, a) == - Approx(17.0).epsilon(1e-7)); -} - -/** - * Basic test of Euclidean distance. - */ -TEST_CASE("EuclideanDistanceTest", "[KernelTest]") -{ - arma::vec a = "1.0 3.0 5.0 7.0"; - arma::vec b = "4.0 0.0 2.0 0.0"; - - REQUIRE(EuclideanDistance::Evaluate(a, b) == - Approx(sqrt(76.0)).epsilon(1e-7)); - REQUIRE(EuclideanDistance::Evaluate(b, a) == - Approx(sqrt(76.0)).epsilon(1e-7)); -} - -/** - * Arbitrary test case for coverage. - */ -TEST_CASE("ArbitraryCaseTest", "[KernelTest]") -{ - arma::vec a = "3.0 5.0 6.0 7.0"; - arma::vec b = "1.0 2.0 1.0 0.0"; - - REQUIRE((LMetric<3, false>::Evaluate(a, b)) == Approx(503.0).epsilon(1e-7)); - REQUIRE((LMetric<3, false>::Evaluate(b, a)) == Approx(503.0).epsilon(1e-7)); - - REQUIRE((LMetric<3, true>::Evaluate(a, b)) == - Approx(7.95284762).epsilon(1e-7)); - REQUIRE((LMetric<3, true>::Evaluate(b, a)) == - Approx(7.95284762).epsilon(1e-7)); -} - -/** - * Make sure two vectors of all zeros return zero distance, for a few different - * powers. - */ -TEST_CASE("LMetricZerosTest", "[KernelTest]") -{ - arma::vec a(250); - a.fill(0.0); - - // We cannot use a loop because compilers seem to be unable to unroll the loop - // and realize the variable actually is knowable at compile-time. - REQUIRE(LMetric<1, false>::Evaluate(a, a) == 0); - REQUIRE(LMetric<1, true>::Evaluate(a, a) == 0); - REQUIRE(LMetric<2, false>::Evaluate(a, a) == 0); - REQUIRE(LMetric<2, true>::Evaluate(a, a) == 0); - REQUIRE(LMetric<3, false>::Evaluate(a, a) == 0); - REQUIRE(LMetric<3, true>::Evaluate(a, a) == 0); - REQUIRE(LMetric<4, false>::Evaluate(a, a) == 0); - REQUIRE(LMetric<4, true>::Evaluate(a, a) == 0); - REQUIRE(LMetric<5, false>::Evaluate(a, a) == 0); - REQUIRE(LMetric<5, true>::Evaluate(a, a) == 0); -} - -/** - * Simple test of Mahalanobis distance with unset covariance matrix in - * constructor. - */ -TEST_CASE("MDUnsetCovarianceTest", "[KernelTest]") -{ - MahalanobisDistance md; - md.Covariance() = arma::eye(4, 4); - arma::vec a = "1.0 2.0 2.0 3.0"; - arma::vec b = "0.0 0.0 1.0 3.0"; - - REQUIRE(md.Evaluate(a, b) == Approx(6.0).epsilon(1e-7)); - REQUIRE(md.Evaluate(b, a) == Approx(6.0).epsilon(1e-7)); -} - -/** - * Simple test of Mahalanobis distance with unset covariance matrix in - * constructor and t_take_root set to true. - */ -TEST_CASE("MDRootUnsetCovarianceTest", "[KernelTest]") -{ - MahalanobisDistance md; - md.Covariance() = arma::eye(4, 4); - arma::vec a = "1.0 2.0 2.5 5.0"; - arma::vec b = "0.0 2.0 0.5 8.0"; - - REQUIRE(md.Evaluate(a, b) == Approx(sqrt(14.0)).epsilon(1e-7)); - REQUIRE(md.Evaluate(b, a) == Approx(sqrt(14.0)).epsilon(1e-7)); -} - -/** - * Simple test of Mahalanobis distance setting identity covariance in - * constructor. - */ -TEST_CASE("MDEyeCovarianceTest", "[KernelTest]") -{ - MahalanobisDistance md(4); - arma::vec a = "1.0 2.0 2.0 3.0"; - arma::vec b = "0.0 0.0 1.0 3.0"; - - REQUIRE(md.Evaluate(a, b) == Approx(6.0).epsilon(1e-7)); - REQUIRE(md.Evaluate(b, a) == Approx(6.0).epsilon(1e-7)); -} - -/** - * Simple test of Mahalanobis distance setting identity covariance in - * constructor and t_take_root set to true. - */ -TEST_CASE("MDRootEyeCovarianceTest", "[KernelTest]") -{ - MahalanobisDistance md(4); - arma::vec a = "1.0 2.0 2.5 5.0"; - arma::vec b = "0.0 2.0 0.5 8.0"; - - REQUIRE(md.Evaluate(a, b) == Approx(sqrt(14.0)).epsilon(1e-7)); - REQUIRE(md.Evaluate(b, a) == Approx(sqrt(14.0)).epsilon(1e-7)); -} - -/** - * Simple test with diagonal covariance matrix. - */ -TEST_CASE("MDDiagonalCovarianceTest", "[KernelTest]") -{ - arma::mat cov = arma::eye(5, 5); - cov(0, 0) = 2.0; - cov(1, 1) = 0.5; - cov(2, 2) = 3.0; - cov(3, 3) = 1.0; - cov(4, 4) = 1.5; - MahalanobisDistance md(cov); - - arma::vec a = "1.0 2.0 2.0 4.0 5.0"; - arma::vec b = "2.0 3.0 1.0 1.0 0.0"; - - REQUIRE(md.Evaluate(a, b) == Approx(52.0).epsilon(1e-7)); - REQUIRE(md.Evaluate(b, a) == Approx(52.0).epsilon(1e-7)); -} - -/** - * More specific case with more difficult covariance matrix. - */ -TEST_CASE("MDFullCovarianceTest", "[KernelTest]") -{ - arma::mat cov = "1.0 2.0 3.0 4.0;" - "0.5 0.6 0.7 0.1;" - "3.4 4.3 5.0 6.1;" - "1.0 2.0 4.0 1.0;"; - MahalanobisDistance md(cov); - - arma::vec a = "1.0 2.0 2.0 4.0"; - arma::vec b = "2.0 3.0 1.0 1.0"; - - REQUIRE(md.Evaluate(a, b) == Approx(15.7).epsilon(1e-7)); - REQUIRE(md.Evaluate(b, a) == Approx(15.7).epsilon(1e-7)); -} - /** * Simple test case for the cosine distance. */ diff --git a/src/mlpack/tests/kmeans_test.cpp b/src/mlpack/tests/kmeans_test.cpp index bc1b0f50bd..8a930fad48 100644 --- a/src/mlpack/tests/kmeans_test.cpp +++ b/src/mlpack/tests/kmeans_test.cpp @@ -103,10 +103,10 @@ TEST_CASE("AllowEmptyClusterTest", "[KMeansTest]") arma::Col countsOld = counts; // Make sure the method doesn't modify any points. - LMetric<2, true> metric; + LMetric<2, true> distance; AllowEmptyClusters::EmptyCluster(kMeansData, 2, centroids, centroids, counts, - metric, 0); + distance, 0); // Make sure no assignments were changed. for (size_t i = 0; i < assignments.n_elem; ++i) @@ -136,10 +136,10 @@ TEST_CASE("KillEmptyClusterTest", "[KMeansTest]") arma::Col countsOld = counts; // Make sure the method modify the specified point. - LMetric<2, true> metric; + LMetric<2, true> distance; KillEmptyClusters::EmptyCluster(kMeansData, 2, centroids, centroids, counts, - metric, 0); + distance, 0); // Make sure no assignments were changed. for (size_t i = 0; i < assignments.n_elem; ++i) @@ -173,11 +173,11 @@ TEST_CASE("MaxVarianceNewClusterTest", "[KMeansTest]") arma::Col counts("3 2 0"); - LMetric<2, true> metric; + LMetric<2, true> distance; // This should only change one point. MaxVarianceNewCluster mvnc; - mvnc.EmptyCluster(data, 2, centroids, centroids, counts, metric, 0); + mvnc.EmptyCluster(data, 2, centroids, centroids, counts, distance, 0); // Add the variance of each point's distance away from the cluster. I think // this is the sensible thing to do. @@ -189,11 +189,11 @@ TEST_CASE("MaxVarianceNewClusterTest", "[KMeansTest]") for (size_t j = 0; j < centroids.n_cols; ++j) { - const double distance = metric.Evaluate(data.col(i), centroids.col(j)); + const double dist = distance.Evaluate(data.col(i), centroids.col(j)); - if (distance < minDistance) + if (dist < minDistance) { - minDistance = distance; + minDistance = dist; closestCluster = j; } } diff --git a/src/mlpack/tests/knn_test.cpp b/src/mlpack/tests/knn_test.cpp index 07f089b3b3..28a2cb59b2 100644 --- a/src/mlpack/tests/knn_test.cpp +++ b/src/mlpack/tests/knn_test.cpp @@ -21,11 +21,11 @@ using namespace mlpack; * These will be removed when we refactor the Bounds to accept MatType. * For now, we will keep the following declarations. */ -template -using FloatHRectBound = HRectBound; +template +using FloatHRectBound = HRectBound; -template -using FloatKDTree = BinarySpaceTree +using FloatKDTree = BinarySpaceTree; /** diff --git a/src/mlpack/tests/main_tests/kde_test.cpp b/src/mlpack/tests/main_tests/kde_test.cpp index 3a08b7cda6..74700bd47a 100644 --- a/src/mlpack/tests/main_tests/kde_test.cpp +++ b/src/mlpack/tests/main_tests/kde_test.cpp @@ -38,9 +38,9 @@ TEST_CASE_METHOD(KDETestFixture, "KDEGaussianRTreeResultsMain", double relError = 0.05; GaussianKernel kernel(kernelBandwidth); - EuclideanDistance metric; + EuclideanDistance distance; KDE kde( - relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, metric); + relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, kdeEstimations); // Normalize estimations. @@ -78,9 +78,9 @@ TEST_CASE_METHOD(KDETestFixture, "KDETriangularBallTreeResultsMain", double relError = 0.06; TriangularKernel kernel(kernelBandwidth); - EuclideanDistance metric; + EuclideanDistance distance; KDE kde( - relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, metric); + relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, kdeEstimations); @@ -115,9 +115,9 @@ TEST_CASE_METHOD(KDETestFixture, "KDEMonoResultsMain", double relError = 0.05; EpanechnikovKernel kernel(kernelBandwidth); - EuclideanDistance metric; + EuclideanDistance distance; KDE - kde(relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, metric); + kde(relError, 0.0, kernel, KDEMode::KDE_DUAL_TREE_MODE, distance); kde.Train(reference); // Perform monochromatic KDE. kde.Evaluate(kdeEstimations); @@ -227,9 +227,9 @@ TEST_CASE_METHOD(KDETestFixture, "KDEGaussianSingleKDTreeResultsMain", double relError = 0.06; GaussianKernel kernel(kernelBandwidth); - EuclideanDistance metric; + EuclideanDistance distance; KDE kde( - relError, 0.0, kernel, KDEMode::KDE_SINGLE_TREE_MODE, metric); + relError, 0.0, kernel, KDEMode::KDE_SINGLE_TREE_MODE, distance); kde.Train(reference); kde.Evaluate(query, kdeEstimations); kdeEstimations /= kernel.Normalizer(reference.n_rows); diff --git a/src/mlpack/tests/main_tests/lmnn_test.cpp b/src/mlpack/tests/main_tests/lmnn_test.cpp index 14c933cc05..13b68b3d47 100644 --- a/src/mlpack/tests/main_tests/lmnn_test.cpp +++ b/src/mlpack/tests/main_tests/lmnn_test.cpp @@ -12,7 +12,7 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -#include +#include #include #include diff --git a/src/mlpack/tests/main_tests/nca_test.cpp b/src/mlpack/tests/main_tests/nca_test.cpp index 138995e06f..95e69256a3 100644 --- a/src/mlpack/tests/main_tests/nca_test.cpp +++ b/src/mlpack/tests/main_tests/nca_test.cpp @@ -12,7 +12,7 @@ #define BINDING_TYPE BINDING_TYPE_TEST #include -#include +#include #include #include diff --git a/src/mlpack/tests/metric_test.cpp b/src/mlpack/tests/metric_test.cpp index abfe3c1d95..d1b5d39647 100644 --- a/src/mlpack/tests/metric_test.cpp +++ b/src/mlpack/tests/metric_test.cpp @@ -15,84 +15,6 @@ using namespace std; using namespace mlpack; -/** - * Simple test for L-1 metric. - */ -TEST_CASE("L1MetricTest", "[MetricTest]") -{ - arma::vec a1(5); - a1.randn(); - - arma::vec b1(5); - b1.randn(); - - arma::Col a2(5); - a2 = { 1, 2, 1, 0, 5 }; - - arma::Col b2(5); - b2 = { 2, 5, 2, 0, 1 }; - - ManhattanDistance lMetric; - - REQUIRE((double) accu(arma::abs(a1 - b1)) == - Approx(lMetric.Evaluate(a1, b1)).epsilon(1e-7)); - - REQUIRE((double) accu(arma::abs(a2 - b2)) == - Approx(lMetric.Evaluate(a2, b2)).epsilon(1e-7)); -} - -/** - * Simple test for L-2 metric. - */ -TEST_CASE("L2MetricTest", "[MetricTest]") -{ - arma::vec a1(5); - a1.randn(); - - arma::vec b1(5); - b1.randn(); - - arma::vec a2(5); - a2 = { 1, 2, 1, 0, 5 }; - - arma::vec b2(5); - b2 = { 2, 5, 2, 0, 1 }; - - EuclideanDistance lMetric; - - REQUIRE((double) sqrt(accu(square(a1 - b1))) == - Approx(lMetric.Evaluate(a1, b1)).epsilon(1e-7)); - - REQUIRE((double) sqrt(accu(square(a2 - b2))) == - Approx(lMetric.Evaluate(a2, b2)).epsilon(1e-7)); -} - -/** - * Simple test for L-Infinity metric. - */ -TEST_CASE("LINFMetricTest", "[MetricTest]") -{ - arma::vec a1(5); - a1.randn(); - - arma::vec b1(5); - b1.randn(); - - arma::Col a2(5); - a2 = { 1, 2, 1, 0, 5 }; - - arma::Col b2(5); - b2 = { 2, 5, 2, 0, 1 }; - - ChebyshevDistance lMetric; - - REQUIRE((double) arma::as_scalar(arma::max(arma::abs(a1 - b1))) == - Approx(lMetric.Evaluate(a1, b1)).epsilon(1e-7)); - - REQUIRE((double) arma::as_scalar(arma::max(arma::abs(a2 - b2))) == - Approx(lMetric.Evaluate(a2, b2)).epsilon(1e-7)); -} - /** * Simple test for IoU metric. */ diff --git a/src/mlpack/tests/mock_categorical_data.hpp b/src/mlpack/tests/mock_categorical_data.hpp index d889c8af3b..4c0d094db6 100644 --- a/src/mlpack/tests/mock_categorical_data.hpp +++ b/src/mlpack/tests/mock_categorical_data.hpp @@ -12,7 +12,7 @@ #define MLPACK_TESTS_MOCK_CATEGORICAL_DATA_HPP #include -#include +#include /** * Create a mock categorical dataset for testing classification. diff --git a/src/mlpack/tests/serialization_test.cpp b/src/mlpack/tests/serialization_test.cpp index dfc8682cf0..1433c9d9c6 100644 --- a/src/mlpack/tests/serialization_test.cpp +++ b/src/mlpack/tests/serialization_test.cpp @@ -155,7 +155,7 @@ TEST_CASE("MahalanobisBallBoundTest", "[SerializationTest]") BallBound, arma::vec> b(100); b.Center().randu(); b.Radius() = 14.0; - b.Metric().Covariance().randu(100, 100); + b.Distance().Q().randu(100, 100); BallBound, arma::vec> xmlB, jsonB, binaryB; @@ -168,10 +168,10 @@ TEST_CASE("MahalanobisBallBoundTest", "[SerializationTest]") // Check the vectors. CheckMatrices(b.Center(), xmlB.Center(), jsonB.Center(), binaryB.Center()); - CheckMatrices(b.Metric().Covariance(), - xmlB.Metric().Covariance(), - jsonB.Metric().Covariance(), - binaryB.Metric().Covariance()); + CheckMatrices(b.Distance().Q(), + xmlB.Distance().Q(), + jsonB.Distance().Q(), + binaryB.Distance().Q()); } TEST_CASE("HRectBoundTest", "[SerializationTest]") diff --git a/src/mlpack/tests/tree_test.cpp b/src/mlpack/tests/tree_test.cpp index ac62ce5c7d..d4aa0a21a5 100644 --- a/src/mlpack/tests/tree_test.cpp +++ b/src/mlpack/tests/tree_test.cpp @@ -1537,7 +1537,7 @@ TEST_CASE("RPTreeTest", "[TreeTest]") } } -template +template void CheckRPTreeSplit(const TreeType& tree) { typedef typename TreeType::ElemType ElemType; @@ -1552,7 +1552,7 @@ void CheckRPTreeSplit(const TreeType& tree) ElemType maxDist = 0; for (size_t k =0; k < tree.Left()->NumDescendants(); ++k) { - ElemType dist = MetricType::Evaluate(center, + ElemType dist = DistanceType::Evaluate(center, tree.Dataset().col(tree.Left()->Descendant(k))); if (dist > maxDist) @@ -1561,7 +1561,7 @@ void CheckRPTreeSplit(const TreeType& tree) for (size_t k =0; k < tree.Right()->NumDescendants(); ++k) { - ElemType dist = MetricType::Evaluate(center, + ElemType dist = DistanceType::Evaluate(center, tree.Dataset().col(tree.Right()->Descendant(k))); REQUIRE(maxDist <= dist * @@ -1569,8 +1569,8 @@ void CheckRPTreeSplit(const TreeType& tree) } } - CheckRPTreeSplit(*tree.Left()); - CheckRPTreeSplit(*tree.Right()); + CheckRPTreeSplit(*tree.Left()); + CheckRPTreeSplit(*tree.Right()); } TEST_CASE("RPTreeSplitTest", "[TreeTest]") @@ -1656,7 +1656,8 @@ TEST_CASE("BallTreeTest", "[TreeTest]") } /** - * Ensure that we can build a ball tree with a custom instantiated metric type. + * Ensure that we can build a ball tree with a custom instantiated distance + * type. */ TEST_CASE("MahalanobisBallTreeTest", "[TreeTest]") { @@ -1828,7 +1829,7 @@ void CheckSelfChild(const TreeType& node) REQUIRE(found == true); } -template +template void CheckCovering(const TreeType& node) { // Return if a leaf. No checking necessary. @@ -1845,13 +1846,13 @@ void CheckCovering(const TreeType& node) { const size_t childPoint = node.Child(i).Point(); - double distance = MetricType::Evaluate(dataset.col(nodePoint), + double distance = DistanceType::Evaluate(dataset.col(nodePoint), dataset.col(childPoint)); REQUIRE(distance <= maxDistance); // Check the child. - CheckCovering(node.Child(i)); + CheckCovering(node.Child(i)); } } diff --git a/src/mlpack/tests/ub_tree_test.cpp b/src/mlpack/tests/ub_tree_test.cpp index 52afab822e..fbd134535a 100644 --- a/src/mlpack/tests/ub_tree_test.cpp +++ b/src/mlpack/tests/ub_tree_test.cpp @@ -149,7 +149,7 @@ TEST_CASE("UBTreeBoundTest", "[UBTreeTest]") } // Ensure that MinDistance() and MaxDistance() works correctly. -template +template void CheckDistance(TreeType& tree, TreeType* node = NULL) { typedef typename TreeType::ElemType ElemType; @@ -160,7 +160,7 @@ void CheckDistance(TreeType& tree, TreeType* node = NULL) while (node->Parent() != NULL) node = node->Parent(); - CheckDistance(tree, node); + CheckDistance(tree, node); for (size_t j = 0; j < tree.Dataset().n_cols; ++j) { @@ -169,7 +169,7 @@ void CheckDistance(TreeType& tree, TreeType* node = NULL) ElemType minDist = std::numeric_limits::max(); for (size_t i = 0; i < tree.NumDescendants(); ++i) { - ElemType dist = MetricType::Evaluate( + ElemType dist = DistanceType::Evaluate( tree.Dataset().col(tree.Descendant(i)), tree.Dataset().col(j)); @@ -194,8 +194,8 @@ void CheckDistance(TreeType& tree, TreeType* node = NULL) if (!tree.IsLeaf()) { - CheckDistance(*tree.Left()); - CheckDistance(*tree.Right()); + CheckDistance(*tree.Left()); + CheckDistance(*tree.Right()); } } else @@ -207,7 +207,7 @@ void CheckDistance(TreeType& tree, TreeType* node = NULL) for (size_t i = 0; i < tree.NumDescendants(); ++i) for (size_t j = 0; j < node->NumDescendants(); ++j) { - ElemType dist = MetricType::Evaluate( + ElemType dist = DistanceType::Evaluate( tree.Dataset().col(tree.Descendant(i)), node->Dataset().col(node->Descendant(j))); @@ -231,8 +231,8 @@ void CheckDistance(TreeType& tree, TreeType* node = NULL) } if (!node->IsLeaf()) { - CheckDistance(tree, node->Left()); - CheckDistance(tree, node->Right()); + CheckDistance(tree, node->Left()); + CheckDistance(tree, node->Right()); } } } diff --git a/src/mlpack/tests/vantage_point_tree_test.cpp b/src/mlpack/tests/vantage_point_tree_test.cpp index 537595a9a2..4dde750504 100644 --- a/src/mlpack/tests/vantage_point_tree_test.cpp +++ b/src/mlpack/tests/vantage_point_tree_test.cpp @@ -130,9 +130,9 @@ void CheckBound(TreeType& tree) // Ensure that the bound contains all descendant points. for (size_t i = 0; i < tree.NumPoints(); ++i) { - ElemType dist = tree.Bound().Metric().Evaluate(tree.Bound().Center(), + ElemType dist = tree.Bound().Distance().Evaluate(tree.Bound().Center(), tree.Dataset().col(tree.Point(i))); - ElemType hollowDist = tree.Bound().Metric().Evaluate( + ElemType hollowDist = tree.Bound().Distance().Evaluate( tree.Bound().HollowCenter(), tree.Dataset().col(tree.Point(i))); @@ -148,9 +148,9 @@ void CheckBound(TreeType& tree) // Ensure that the bound contains all descendant points. for (size_t i = 0; i < tree.NumDescendants(); ++i) { - ElemType dist = tree.Bound().Metric().Evaluate(tree.Bound().Center(), + ElemType dist = tree.Bound().Distance().Evaluate(tree.Bound().Center(), tree.Dataset().col(tree.Descendant(i))); - ElemType hollowDist = tree.Bound().Metric().Evaluate( + ElemType hollowDist = tree.Bound().Distance().Evaluate( tree.Bound().HollowCenter(), tree.Dataset().col(tree.Descendant(i)));