Move metrics to distances/ and dists to distributions/. And adapt... everything.

This commit is contained in:
Ryan Curtin
2024-06-14 15:14:48 -04:00
parent e9bf5665c9
commit cccf60d974
189 changed files with 3740 additions and 3374 deletions
+111
View File
@@ -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<typename VecTypeA, typename VecTypeB>
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<typename VecTypeA, typename VecTypeB>
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 <mlpack.hpp>
#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<arma::mat>(10, 5000);
// Instantiate the RangeSearch object with the ExampleDistance.
RangeSearch<ExampleDistance> rs(data);
// These vectors will store the results.
vector<vector<size_t>> neighbors;
vector<vector<double>> distances;
// Create a random 10-dimensional query point.
arma::vec query = arma::randu<arma::vec>(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:
<!-- TODO: link to the core.md documentation -->
- `ManhattanDistance`
- `EuclideanDistance`
- `ChebyshevDistance`
- `MahalanobisDistance`
- `LMetric` (for arbitrary L-metrics)
- `IPMetric` (requires a [KernelType](kernels.md) parameter)
+3 -3
View File
@@ -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
-108
View File
@@ -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<typename VecTypeA, typename VecTypeB>
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<typename VecTypeA, typename VecTypeB>
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 <mlpack.hpp>
#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<arma::mat>(10, 5000);
// Instantiate the RangeSearch object with the ExampleKernel.
RangeSearch<ExampleKernel> rs(data);
// These vectors will store the results.
vector<vector<size_t>> neighbors;
vector<vector<double>> distances;
// Create a random 10-dimensional query point.
arma::vec query = arma::randu<arma::vec>(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)
+65 -63
View File
@@ -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<ManhattanDistance, QuadTree> rs(...);
@@ -124,17 +124,18 @@ RangeSearch<ManhattanDistance,
Unfortunately, the price to pay for this user convenience is that *every*
`TreeType` must have three template parameters, and they must be in exactly
that order. Fortunately, there is an additional benefit: we are guaranteed that
the tree is built using the same metric as the method (that is, a user can't
specify different metric types to the algorithm and to the tree, which they can
without template template parameters).
the tree is built using the same distance metric as the method (that is, a user
can't specify different metric types to the algorithm and to the tree, which
they can without template template parameters).
There are two important notes about this:
- Not every possible input of `MetricType`, `StatisticType`, and/or `MatType`
- Not every possible input of `DistanceType`, `StatisticType`, and/or `MatType`
necessarily need to be valid or work correctly for each type of tree. For
instance, the `QuadTree` is limited to Euclidean metrics and will not work
otherwise. Either compile-time static checks or detailed documentation can
help keep users from using invalid combinations of template arguments.
instance, the `QuadTree` is limited to Euclidean distance metrics and will
not work otherwise. Either compile-time static checks or detailed
documentation can help keep users from using invalid combinations of template
arguments.
- Some types of trees have more template parameters than just these three. One
example is the generalized binary space tree, where the bounding shape of
@@ -150,7 +151,7 @@ There are two important notes about this:
```c++
// This is the definition of the BinarySpaceTree class, which has five template
// parameters.
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename BoundType,
@@ -160,12 +161,12 @@ class BinarySpaceTree;
// The 'using' keyword gives us a template typedef, so we can define the
// MeanSplitKDTree template class, which has three parameters and is a valid
// TreeType policy class.
template<typename MetricType, typename StatisticType, typename MatType>
using MeanSplitKDTree = BinarySpaceTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using MeanSplitKDTree = BinarySpaceTree<DistanceType,
StatisticType,
MatType,
HRectBound<MetricType>
MeanSplit<BoundType, MetricType>>;
HRectBound<DistanceType>
MeanSplit<BoundType, DistanceType>>;
```
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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType>
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<typename VecTypeA, typename VecTypeB>
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<typename Archive>
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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType>
template<>
class TreeTraits<KDTree<MetricType, StatisticType, MatType>>
class TreeTraits<KDTree<DistanceType, StatisticType, MatType>>
{
public:
// The regions represented by the two children of a node may not overlap.
+1 -1
View File
@@ -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.)
+16 -16
View File
@@ -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<typename VecType>
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<MahalanobisDistance> 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++
+14 -14
View File
@@ -296,13 +296,13 @@ arguments:
```c++
template<
typename SortPolicy = NearestNeighborSort,
typename MetricType = EuclideanDistance,
typename DistanceType = EuclideanDistance,
typename MatType = arma::mat,
template<typename TreeMetricType,
template<typename TreeDistanceType,
typename TreeStatType,
typename TreeMatType> class TreeType = KDTree,
template<typename RuleType> class TraversalType =
TreeType<MetricType, NeighborSearchStat<SortPolicy>,
TreeType<DistanceType, NeighborSearchStat<SortPolicy>,
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<typename VecType>
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
+13 -13
View File
@@ -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<typename MetricType = EuclideanDistance,
template<typename DistanceType = EuclideanDistance,
typename MatType = arma::mat,
template<typename TreeMetricType,
template<typename TreeDistanceType,
typename TreeStatType,
typename TreeMatType> 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<typename VecType>
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
+427 -103
View File
@@ -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:
<!-- TODO: better names for each link -->
* [`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<KernelType>`](#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, TakeRoot>
```
* `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<INT_MAX>`)
---
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<false>`) 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<true>` 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<true>::Evaluate(bb1Coord, bb2Coord);
const double d2Coord = mlpack::IoUDistance<true>::Evaluate(bb2Coord, bb3Coord);
const double d3Coord = mlpack::IoUDistance<true>::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<KernelType>`
The `IPMetric<KernelType>` 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<KernelType>()`
- Construct a new `IPMetric` using a default-constructed `KernelType`.
- A default constructor for `KernelType` must be available (e.g. `k =
KernelType()`).
* `d = IPMetric<KernelType>(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<KernelType>(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<mlpack::EpanechnikovKernel> 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<mlpack::LinearKernel> ip2;
std::cout << " Euclidean distance between x1/x2: "
<< mlpack::EuclideanDistance::Evaluate(x1, x2) << "." << std::endl;
std::cout << " IPMetric<LinearKernel> 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<EpanechnikovKernel> 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<TakeRoot = true, MatType = arma::mat>
```
* 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<arma::fvec>(20));
mlpack::MahalanobisDistance<false /* do not take square root */,
arma::fmat> 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
<!-- TODO: link to the completed HMM documentation -->
@@ -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:
<!-- TODO: better names for each link -->
* [`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, TakeRoot>
```
* `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<INT_MAX>`)
---
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.
+2 -1
View File
@@ -50,7 +50,8 @@
#include <mlpack/core/util/backtrace.hpp>
#endif
#include <mlpack/core/dists/dists.hpp>
#include <mlpack/core/distances/distances.hpp>
#include <mlpack/core/distributions/distributions.hpp>
#include <mlpack/core/kernels/kernels.hpp>
#include <mlpack/core/metrics/metrics.hpp>
#include <mlpack/core/tree/tree.hpp>
+4 -4
View File
@@ -14,7 +14,7 @@
#define MLPACK_CORE_CV_METRICS_FACILITIES_HPP
#include <mlpack/core.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/distances/lmetric.hpp>
namespace mlpack {
@@ -24,16 +24,16 @@ namespace mlpack {
* @param data Column-major matrix.
* @param metric Distance metric to be used.
*/
template<typename DataType, typename Metric>
template<typename DataType, typename DistanceType>
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);
}
}
@@ -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 {
@@ -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 <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/distances/lmetric.hpp>
#include <mlpack/core/kernels/linear_kernel.hpp>
namespace mlpack {
@@ -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 <mlpack/prereqs.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"
@@ -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 <mlpack/prereqs.hpp>
@@ -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<bool TakeRoot = true>
template<bool TakeRoot = true, typename MatType = arma::mat>
class MahalanobisDistance
{
public:
typedef typename GetColType<MatType>::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<arma::mat>(dimensionality, dimensionality)) { }
q(arma::eye<MatType>(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<typename VecTypeA, typename VecTypeB>
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<typename Archive>
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<TakeRoot, MatType>), (1));
#include "mahalanobis_distance_impl.hpp"
#endif
@@ -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<bool TakeRoot, typename MatType>
template<typename VecTypeA, typename VecTypeB>
double MahalanobisDistance<TakeRoot, MatType>::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<bool TakeRoot, typename MatType>
template<typename Archive>
void MahalanobisDistance<TakeRoot, MatType>::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<MatType>::from(qTmp);
}
else
{
ar(CEREAL_NVP(q));
}
}
} // namespace mlpack
#endif
@@ -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.
@@ -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.
@@ -1,5 +1,5 @@
/**
* @file core/dists/discrete_distribution.hpp
* @file core/distributions/discrete_distribution.hpp
* @author Ryan Curtin
* @author Rohan Raj
*
@@ -1,5 +1,5 @@
/**
* @file core/dists/discrete_distribution_impl.hpp
* @file core/distributions/discrete_distribution_impl.hpp
* @author Ryan Curtin
* @author Rohan Raj
*
@@ -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"
@@ -1,5 +1,5 @@
/**
* @file core/dists/gamma_distribution.hpp
* @file core/distributions/gamma_distribution.hpp
* @author Yannis Mentekidis
* @author Rohan Raj
*
@@ -1,5 +1,5 @@
/**
* @file core/dists/gamma_distribution_impl.hpp
* @file core/distributions/gamma_distribution_impl.hpp
* @author Yannis Mentekidis
* @author Rohan Raj
*
@@ -1,5 +1,5 @@
/**
* @file core/dists/gaussian_distribution.hpp
* @file core/distributions/gaussian_distribution.hpp
* @author Ryan Curtin
* @author Michael Fox
*
@@ -1,5 +1,5 @@
/**
* @file core/dists/gaussian_distribution_impl.hpp
* @file core/distributions/gaussian_distribution_impl.hpp
* @author Ryan Curtin
* @author Michael Fox
*
@@ -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
@@ -1,5 +1,5 @@
/*
* @file core/dists/laplace_distribution_impl.hpp
* @file core/distributions/laplace_distribution_impl.hpp
* @author Zhihao Lou
* @author Rohan Raj
*
@@ -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 <mlpack/prereqs.hpp>
#include <mlpack/core/dists/gaussian_distribution.hpp>
#include <mlpack/core/distributions/gaussian_distribution.hpp>
#include <mlpack/methods/linear_regression/linear_regression.hpp>
namespace mlpack {
@@ -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"
+1 -1
View File
@@ -13,7 +13,7 @@
#define MLPACK_CORE_KERNELS_CAUCHY_KERNEL_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/distances/lmetric.hpp>
#include <mlpack/core/kernels/kernel_traits.hpp>
namespace mlpack {
@@ -16,7 +16,7 @@
#include "epanechnikov_kernel.hpp"
#include <mlpack/core/util/log.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/distances/lmetric.hpp>
namespace mlpack {
+1 -1
View File
@@ -15,7 +15,7 @@
#define MLPACK_CORE_KERNELS_GAUSSIAN_KERNEL_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/distances/lmetric.hpp>
#include <mlpack/core/kernels/kernel_traits.hpp>
namespace mlpack {
@@ -13,7 +13,7 @@
#define MLPACK_CORE_KERNELS_TRIANGULAR_KERNEL_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/distances/lmetric.hpp>
namespace mlpack {
+5 -10
View File
@@ -13,6 +13,7 @@
*/
#ifndef MLPACK_CORE_METRICS_IOU_HPP
#define MLPACK_CORE_METRICS_IOU_HPP
#include <mlpack/prereqs.hpp>
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<bool UseCoordinates = false>
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.
@@ -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<typename VecTypeA, typename VecTypeB>
double MahalanobisDistance<false>::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<typename VecTypeA, typename VecTypeB>
double MahalanobisDistance<true>::Evaluate(const VecTypeA& a,
const VecTypeB& b)
{
// Check if covariance matrix has been initialized.
if (covariance.n_rows == 0)
covariance = arma::eye<arma::mat>(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<bool TakeRoot>
template<typename Archive>
void MahalanobisDistance<TakeRoot>::serialize(Archive& ar,
const uint32_t /* version */)
{
ar(CEREAL_NVP(covariance));
}
} // namespace mlpack
#endif
+4 -5
View File
@@ -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
+20 -13
View File
@@ -13,20 +13,20 @@
#define MLPACK_CORE_TREE_BALLBOUND_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/distances/lmetric.hpp>
#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<typename MetricType = LMetric<2, true>,
template<typename DistanceType = LMetric<2, true>,
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<typename Archive>
@@ -209,8 +216,8 @@ class BallBound
};
//! A specialization of BoundTraits for this bound type.
template<typename MetricType, typename VecType>
struct BoundTraits<BallBound<MetricType, VecType>>
template<typename DistanceType, typename VecType>
struct BoundTraits<BallBound<DistanceType, VecType>>
{
//! These bounds are potentially loose in some dimensions.
const static bool HasTightBounds = false;
+79 -95
View File
@@ -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<typename MetricType, typename VecType>
BallBound<MetricType, VecType>::BallBound() :
template<typename DistanceType, typename VecType>
BallBound<DistanceType, VecType>::BallBound() :
radius(std::numeric_limits<ElemType>::lowest()),
metric(new MetricType()),
ownsMetric(true)
distance(new DistanceType()),
ownsDistance(true)
{ /* Nothing to do. */ }
/**
@@ -32,12 +32,12 @@ BallBound<MetricType, VecType>::BallBound() :
*
* @param dimension Dimensionality of ball bound.
*/
template<typename MetricType, typename VecType>
BallBound<MetricType, VecType>::BallBound(const size_t dimension) :
template<typename DistanceType, typename VecType>
BallBound<DistanceType, VecType>::BallBound(const size_t dimension) :
radius(std::numeric_limits<ElemType>::lowest()),
center(dimension),
metric(new MetricType()),
ownsMetric(true)
distance(new DistanceType()),
ownsDistance(true)
{ /* Nothing to do. */ }
/**
@@ -46,86 +46,86 @@ BallBound<MetricType, VecType>::BallBound(const size_t dimension) :
* @param radius Radius of ball bound.
* @param center Center of ball bound.
*/
template<typename MetricType, typename VecType>
BallBound<MetricType, VecType>::BallBound(const ElemType radius,
template<typename DistanceType, typename VecType>
BallBound<DistanceType, VecType>::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<typename MetricType, typename VecType>
BallBound<MetricType, VecType>::BallBound(const BallBound& other) :
template<typename DistanceType, typename VecType>
BallBound<DistanceType, VecType>::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<typename MetricType, typename VecType>
BallBound<MetricType, VecType>& BallBound<MetricType, VecType>::operator=(
template<typename DistanceType, typename VecType>
BallBound<DistanceType, VecType>& BallBound<DistanceType, VecType>::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<typename MetricType, typename VecType>
BallBound<MetricType, VecType>::BallBound(BallBound&& other) :
template<typename DistanceType, typename VecType>
BallBound<DistanceType, VecType>::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<typename MetricType, typename VecType>
BallBound<MetricType, VecType>& BallBound<MetricType, VecType>::operator=(
template<typename DistanceType, typename VecType>
BallBound<DistanceType, VecType>& BallBound<DistanceType, VecType>::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<typename MetricType, typename VecType>
BallBound<MetricType, VecType>::~BallBound()
template<typename DistanceType, typename VecType>
BallBound<DistanceType, VecType>::~BallBound()
{
if (ownsMetric)
delete metric;
if (ownsDistance)
delete distance;
}
//! Get the range in a certain dimension.
template<typename MetricType, typename VecType>
RangeType<typename BallBound<MetricType, VecType>::ElemType>
BallBound<MetricType, VecType>::operator[](const size_t i) const
template<typename DistanceType, typename VecType>
RangeType<typename BallBound<DistanceType, VecType>::ElemType>
BallBound<DistanceType, VecType>::operator[](const size_t i) const
{
if (radius < 0)
return Range();
@@ -136,44 +136,44 @@ BallBound<MetricType, VecType>::operator[](const size_t i) const
/**
* Determines if a point is within the bound.
*/
template<typename MetricType, typename VecType>
bool BallBound<MetricType, VecType>::Contains(const VecType& point) const
template<typename DistanceType, typename VecType>
bool BallBound<DistanceType, VecType>::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<typename MetricType, typename VecType>
template<typename DistanceType, typename VecType>
template<typename OtherVecType>
typename BallBound<MetricType, VecType>::ElemType
BallBound<MetricType, VecType>::MinDistance(
typename BallBound<DistanceType, VecType>::ElemType
BallBound<DistanceType, VecType>::MinDistance(
const OtherVecType& point,
typename std::enable_if_t<IsVector<OtherVecType>::value>* /* junk */) const
{
if (radius < 0)
return std::numeric_limits<ElemType>::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 MetricType, typename VecType>
typename BallBound<MetricType, VecType>::ElemType
BallBound<MetricType, VecType>::MinDistance(const BallBound& other)
template<typename DistanceType, typename VecType>
typename BallBound<DistanceType, VecType>::ElemType
BallBound<DistanceType, VecType>::MinDistance(const BallBound& other)
const
{
if (radius < 0)
return std::numeric_limits<ElemType>::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<MetricType, VecType>::MinDistance(const BallBound& other)
/**
* Computes maximum distance.
*/
template<typename MetricType, typename VecType>
template<typename DistanceType, typename VecType>
template<typename OtherVecType>
typename BallBound<MetricType, VecType>::ElemType
BallBound<MetricType, VecType>::MaxDistance(
typename BallBound<DistanceType, VecType>::ElemType
BallBound<DistanceType, VecType>::MaxDistance(
const OtherVecType& point,
typename std::enable_if_t<IsVector<OtherVecType>::value>* /* junk */) const
{
if (radius < 0)
return std::numeric_limits<ElemType>::max();
else
return metric->Evaluate(point, center) + radius;
return distance->Evaluate(point, center) + radius;
}
/**
* Computes maximum distance.
*/
template<typename MetricType, typename VecType>
typename BallBound<MetricType, VecType>::ElemType
BallBound<MetricType, VecType>::MaxDistance(const BallBound& other)
template<typename DistanceType, typename VecType>
typename BallBound<DistanceType, VecType>::ElemType
BallBound<DistanceType, VecType>::MaxDistance(const BallBound& other)
const
{
if (radius < 0)
return std::numeric_limits<ElemType>::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<MetricType, VecType>::MaxDistance(const BallBound& other)
*
* Example: bound1.MinDistanceSq(other) for minimum squared distance.
*/
template<typename MetricType, typename VecType>
template<typename DistanceType, typename VecType>
template<typename OtherVecType>
RangeType<typename BallBound<MetricType, VecType>::ElemType>
BallBound<MetricType, VecType>::RangeDistance(
RangeType<typename BallBound<DistanceType, VecType>::ElemType>
BallBound<DistanceType, VecType>::RangeDistance(
const OtherVecType& point,
typename std::enable_if_t<IsVector<OtherVecType>::value>* /* junk */) const
{
@@ -226,14 +226,14 @@ BallBound<MetricType, VecType>::RangeDistance(
std::numeric_limits<ElemType>::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<typename MetricType, typename VecType>
RangeType<typename BallBound<MetricType, VecType>::ElemType>
BallBound<MetricType, VecType>::RangeDistance(
template<typename DistanceType, typename VecType>
RangeType<typename BallBound<DistanceType, VecType>::ElemType>
BallBound<DistanceType, VecType>::RangeDistance(
const BallBound& other) const
{
if (radius < 0)
@@ -241,39 +241,22 @@ BallBound<MetricType, VecType>::RangeDistance(
std::numeric_limits<ElemType>::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<typename MetricType, typename VecType>
const BallBound<VecType>&
BallBound<MetricType, VecType>::operator|=(
const BallBound<VecType>& 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<typename MetricType, typename VecType>
template<typename DistanceType, typename VecType>
template<typename MatType>
const BallBound<MetricType, VecType>&
BallBound<MetricType, VecType>::operator|=(const MatType& data)
const BallBound<DistanceType, VecType>&
BallBound<DistanceType, VecType>::operator|=(const MatType& data)
{
if (radius < 0)
{
@@ -284,7 +267,7 @@ BallBound<MetricType, VecType>::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<MetricType, VecType>::operator|=(const MatType& data)
}
//! Serialize the BallBound.
template<typename MetricType, typename VecType>
template<typename DistanceType, typename VecType>
template<typename Archive>
void BallBound<MetricType, VecType>::serialize(
void BallBound<DistanceType, VecType>::serialize(
Archive& ar,
const uint32_t /* version */)
{
@@ -312,13 +295,14 @@ void BallBound<MetricType, VecType>::serialize(
if (cereal::is_loading<Archive>())
{
// 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
@@ -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<typename MetricType,
template<typename DistanceType,
typename StatisticType = EmptyStatistic,
typename MatType = arma::mat,
template<typename BoundMetricType, typename...> class BoundType =
template<typename BoundDistanceType, typename...> class BoundType =
HRectBound,
template<typename SplitBoundType, typename SplitMatType>
class SplitType = MidpointSplit>
@@ -58,7 +58,7 @@ class BinarySpaceTree
//! The type of element held in MatType.
typedef typename MatType::elem_type ElemType;
typedef SplitType<BoundType<MetricType>, MatType> Split;
typedef SplitType<BoundType<DistanceType>, MatType> Split;
private:
//! The left child node.
@@ -74,7 +74,7 @@ class BinarySpaceTree
//! children).
size_t count;
//! The bound object for this node.
BoundType<MetricType> bound;
BoundType<DistanceType> 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<BoundType<MetricType>, MatType>& splitter,
SplitType<BoundType<DistanceType>, MatType>& splitter,
const size_t maxLeafSize = 20);
/**
@@ -236,7 +236,7 @@ class BinarySpaceTree
const size_t begin,
const size_t count,
std::vector<size_t>& oldFromNew,
SplitType<BoundType<MetricType>, MatType>& splitter,
SplitType<BoundType<DistanceType>, MatType>& splitter,
const size_t maxLeafSize = 20);
/**
@@ -266,7 +266,7 @@ class BinarySpaceTree
const size_t count,
std::vector<size_t>& oldFromNew,
std::vector<size_t>& newFromOld,
SplitType<BoundType<MetricType>, MatType>& splitter,
SplitType<BoundType<DistanceType>, MatType>& splitter,
const size_t maxLeafSize = 20);
/**
@@ -315,9 +315,9 @@ class BinarySpaceTree
~BinarySpaceTree();
//! Return the bound object for this node.
const BoundType<MetricType>& Bound() const { return bound; }
const BoundType<DistanceType>& Bound() const { return bound; }
//! Return the bound object for this node.
BoundType<MetricType>& Bound() { return bound; }
BoundType<DistanceType>& 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<BoundType<MetricType>, MatType>& splitter);
SplitType<BoundType<DistanceType>, MatType>& splitter);
/**
* Splits the current node, assigning its left and right children recursively.
@@ -526,7 +530,7 @@ class BinarySpaceTree
*/
void SplitNode(std::vector<size_t>& oldFromNew,
const size_t maxLeafSize,
SplitType<BoundType<MetricType>, MatType>& splitter);
SplitType<BoundType<DistanceType>, 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<MetricType>& boundToUpdate);
void UpdateBound(HollowBallBound<DistanceType>& boundToUpdate);
protected:
/**
@@ -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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
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<BoundType<MetricType>, MatType> splitter;
SplitType<BoundType<DistanceType>, MatType> splitter;
SplitNode(maxLeafSize, splitter);
// Create the statistic depending on if we are a leaf or not.
stat = StatisticType(*this);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree(
const MatType& data,
std::vector<size_t>& oldFromNew,
@@ -74,20 +74,20 @@ BinarySpaceTree(
oldFromNew[i] = i; // Fill with unharmed indices.
// Now do the actual splitting.
SplitType<BoundType<MetricType>, MatType> splitter;
SplitType<BoundType<DistanceType>, MatType> splitter;
SplitNode(oldFromNew, maxLeafSize, splitter);
// Create the statistic depending on if we are a leaf or not.
stat = StatisticType(*this);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree(
const MatType& data,
std::vector<size_t>& oldFromNew,
@@ -108,7 +108,7 @@ BinarySpaceTree(
oldFromNew[i] = i; // Fill with unharmed indices.
// Now do the actual splitting.
SplitType<BoundType<MetricType>, MatType> splitter;
SplitType<BoundType<DistanceType>, 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
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<BoundType<MetricType>, MatType> splitter;
SplitType<BoundType<DistanceType>, MatType> splitter;
SplitNode(maxLeafSize, splitter);
// Create the statistic depending on if we are a leaf or not.
stat = StatisticType(*this);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree(
MatType&& data,
std::vector<size_t>& oldFromNew,
@@ -171,20 +171,20 @@ BinarySpaceTree(
oldFromNew[i] = i; // Fill with unharmed indices.
// Now do the actual splitting.
SplitType<BoundType<MetricType>, MatType> splitter;
SplitType<BoundType<DistanceType>, MatType> splitter;
SplitNode(oldFromNew, maxLeafSize, splitter);
// Create the statistic depending on if we are a leaf or not.
stat = StatisticType(*this);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree(
MatType&& data,
std::vector<size_t>& oldFromNew,
@@ -205,7 +205,7 @@ BinarySpaceTree(
oldFromNew[i] = i; // Fill with unharmed indices.
// Now do the actual splitting.
SplitType<BoundType<MetricType>, MatType> splitter;
SplitType<BoundType<DistanceType>, 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree(
BinarySpaceTree* parent,
const size_t begin,
const size_t count,
SplitType<BoundType<MetricType>, MatType>& splitter,
SplitType<BoundType<DistanceType>, MatType>& splitter,
const size_t maxLeafSize) :
left(NULL),
right(NULL),
@@ -245,19 +245,19 @@ BinarySpaceTree(
stat = StatisticType(*this);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree(
BinarySpaceTree* parent,
const size_t begin,
const size_t count,
std::vector<size_t>& oldFromNew,
SplitType<BoundType<MetricType>, MatType>& splitter,
SplitType<BoundType<DistanceType>, MatType>& splitter,
const size_t maxLeafSize) :
left(NULL),
right(NULL),
@@ -278,20 +278,20 @@ BinarySpaceTree(
stat = StatisticType(*this);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree(
BinarySpaceTree* parent,
const size_t begin,
const size_t count,
std::vector<size_t>& oldFromNew,
std::vector<size_t>& newFromOld,
SplitType<BoundType<MetricType>, MatType>& splitter,
SplitType<BoundType<DistanceType>, 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree(
const BinarySpaceTree& other) :
left(NULL),
@@ -381,14 +381,14 @@ BinarySpaceTree(
/**
* Copy assignment operator: copy the given other tree.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>&
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>&
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>&
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>&
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
operator=(BinarySpaceTree&& other)
{
// Return if it's the same tree.
@@ -501,13 +501,13 @@ operator=(BinarySpaceTree&& other)
/**
* Move constructor.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree(BinarySpaceTree&& other) :
left(other.left),
right(other.right),
@@ -543,14 +543,14 @@ BinarySpaceTree(BinarySpaceTree&& other) :
/**
* Initialize the tree from an archive.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename Archive>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree(
Archive& ar,
const typename std::enable_if_t<cereal::is_loading<Archive>()>*) :
@@ -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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
~BinarySpaceTree()
{
delete left;
@@ -583,13 +583,13 @@ BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
delete dataset;
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
inline bool BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
inline bool BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::IsLeaf() const
{
return !left;
@@ -598,13 +598,13 @@ inline bool BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
/**
* Returns the number of children in this node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
inline size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
inline size_t BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::NumChildren() const
{
if (left && right)
@@ -619,14 +619,14 @@ inline size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
* 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename VecType>
size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
size_t BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::GetNearestChild(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>*)
@@ -643,14 +643,14 @@ size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
* 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename VecType>
size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
size_t BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::GetFurthestChild(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>*)
@@ -667,13 +667,13 @@ size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
* 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
size_t BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::GetNearestChild(const BinarySpaceTree& queryNode)
{
if (IsLeaf() || !left || !right)
@@ -692,13 +692,13 @@ size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
* 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
size_t BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::GetFurthestChild(const BinarySpaceTree& queryNode)
{
if (IsLeaf() || !left || !right)
@@ -717,16 +717,16 @@ size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
* Return a bound on the furthest point in the node from the center. This
* returns 0 unless the node is a leaf.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
inline
typename BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
typename BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::ElemType
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::FurthestPointDistance() const
{
if (!IsLeaf())
@@ -743,32 +743,32 @@ BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
* furthest descendant distance may be less than what this method returns (but
* it will never be greater than this).
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
inline
typename BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
typename BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::ElemType
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::FurthestDescendantDistance() const
{
return furthestDescendantDistance;
}
//! Return the minimum distance from the center to any bound edge.
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
inline
typename BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
typename BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::ElemType
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::MinimumBoundDistance() const
{
return bound.MinWidth() / 2.0;
@@ -777,15 +777,15 @@ BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
/**
* Return the specified child.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
inline BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
inline BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>&
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::Child(const size_t child) const
{
if (child == 0)
@@ -797,13 +797,13 @@ inline BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
/**
* Return the number of points contained in this node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
inline size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
inline size_t BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::NumPoints() const
{
if (left)
@@ -815,13 +815,13 @@ inline size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
/**
* Return the number of descendants contained in the node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
inline size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
inline size_t BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::NumDescendants() const
{
return count;
@@ -830,13 +830,13 @@ inline size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
/**
* Return the index of a particular descendant contained in this node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
inline size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
inline size_t BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::Descendant(const size_t index) const
{
return (begin + index);
@@ -845,27 +845,28 @@ inline size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
/**
* Return the index of a particular point contained in this node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
inline size_t BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
inline size_t BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::Point(const size_t index) const
{
return (begin + index);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
void
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
SplitNode(const size_t maxLeafSize,
SplitType<BoundType<MetricType>, MatType>& splitter)
SplitType<BoundType<DistanceType>, MatType>& splitter)
{
// We need to expand the bounds of this node properly.
UpdateBound(bound);
@@ -914,25 +915,26 @@ void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
void
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
SplitNode(std::vector<size_t>& oldFromNew,
const size_t maxLeafSize,
SplitType<BoundType<MetricType>, MatType>& splitter)
SplitType<BoundType<DistanceType>, MatType>& splitter)
{
// We need to expand the bounds of this node properly.
UpdateBound(bound);
@@ -982,37 +984,39 @@ SplitNode(std::vector<size_t>& 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename BoundType2>
void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
void
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
UpdateBound(BoundType2& boundToUpdate)
{
if (count > 0)
boundToUpdate |= dataset->cols(begin, begin + count - 1);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
UpdateBound(HollowBallBound<MetricType>& boundToUpdate)
void
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
UpdateBound(HollowBallBound<DistanceType>& boundToUpdate)
{
if (!parent)
{
@@ -1032,13 +1036,13 @@ UpdateBound(HollowBallBound<MetricType>& boundToUpdate)
}
// Default constructor (private), for cereal.
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree() :
left(NULL),
right(NULL),
@@ -1056,14 +1060,15 @@ BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
/**
* Serialize the tree.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename Archive>
void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
void
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
serialize(Archive& ar, const uint32_t /* version */)
{
// If we're loading, and we have children, they need to be deleted.
@@ -32,14 +32,14 @@ struct QueueFrame
TraversalInfoType traversalInfo;
};
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename RuleType>
class BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
class BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::BreadthFirstDualTreeTraverser
{
public:
@@ -19,14 +19,14 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename RuleType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BreadthFirstDualTreeTraverser<RuleType>::BreadthFirstDualTreeTraverser(
RuleType& rule) :
rule(rule),
@@ -47,18 +47,19 @@ bool operator<(const QueueFrame<TreeType, TraversalInfoType>& a,
return false;
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename RuleType>
void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
void
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BreadthFirstDualTreeTraverser<RuleType>::Traverse(
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>&
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>&
queryRoot,
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>&
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>&
referenceRoot)
{
// Increment the visit counter.
@@ -87,16 +88,16 @@ BreadthFirstDualTreeTraverser<RuleType>::Traverse(
Traverse(queryRoot, queue);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename RuleType>
void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
void BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
BreadthFirstDualTreeTraverser<RuleType>::Traverse(
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>&
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>&
queryNode,
std::priority_queue<QueueFrameType>& referenceQueue)
{
@@ -21,14 +21,14 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename RuleType>
class BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
class BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::DualTreeTraverser
{
public:
@@ -19,14 +19,14 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename RuleType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
DualTreeTraverser<RuleType>::DualTreeTraverser(RuleType& rule) :
rule(rule),
numPrunes(0),
@@ -35,18 +35,19 @@ DualTreeTraverser<RuleType>::DualTreeTraverser(RuleType& rule) :
numBaseCases(0)
{ /* Nothing to do. */ }
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename RuleType>
void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
void
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
DualTreeTraverser<RuleType>::Traverse(
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>&
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>&
queryNode,
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>&
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>&
referenceNode)
{
// Increment the visit counter.
@@ -20,14 +20,14 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename RuleType>
class BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
class BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
SplitType>::SingleTreeTraverser
{
public:
@@ -21,30 +21,31 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename RuleType>
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
SingleTreeTraverser<RuleType>::SingleTreeTraverser(RuleType& rule) :
rule(rule),
numPrunes(0)
{ /* Nothing to do. */ }
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
template<typename RuleType>
void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
void
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>::
SingleTreeTraverser<RuleType>::Traverse(
const size_t queryIndex,
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>&
BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType, SplitType>&
referenceNode)
{
// If we are a leaf, run the base case as necessary.
@@ -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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType,
template<typename BoundDistanceType, typename...> class BoundType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
class TreeTraits<BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
SplitType>>
class TreeTraits<BinarySpaceTree<
DistanceType, StatisticType, MatType, BoundType, SplitType>>
{
public:
/**
@@ -77,12 +77,12 @@ class TreeTraits<BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
* projection tree. The only difference with general BinarySpaceTree is that the
* tree can have overlapping children.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType>
class TreeTraits<BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
RPTreeMaxSplit>>
template<typename BoundDistanceType, typename...> class BoundType>
class TreeTraits<BinarySpaceTree<
DistanceType, StatisticType, MatType, BoundType, RPTreeMaxSplit>>
{
public:
/**
@@ -127,11 +127,11 @@ class TreeTraits<BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
* projection tree. The only difference with general BinarySpaceTree is that the
* tree can have overlapping children.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename BoundMetricType, typename...> class BoundType>
class TreeTraits<BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
template<typename BoundDistanceType, typename...> class BoundType>
class TreeTraits<BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
RPTreeMeanSplit>>
{
public:
@@ -178,13 +178,13 @@ class TreeTraits<BinarySpaceTree<MetricType, StatisticType, MatType, BoundType,
* overlapping children.
* See mlpack/core/tree/tree_traits.hpp for more information.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
class TreeTraits<BinarySpaceTree<MetricType, StatisticType, MatType, BallBound,
SplitType>>
class TreeTraits<BinarySpaceTree<
DistanceType, StatisticType, MatType, BallBound, SplitType>>
{
public:
static const bool HasOverlappingChildren = true;
@@ -202,13 +202,13 @@ class TreeTraits<BinarySpaceTree<MetricType, StatisticType, MatType, BallBound,
* The only difference with general BinarySpaceTree is that the tree can have
* overlapping children.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
class TreeTraits<BinarySpaceTree<MetricType, StatisticType, MatType,
HollowBallBound, SplitType>>
class TreeTraits<BinarySpaceTree<
DistanceType, StatisticType, MatType, HollowBallBound, SplitType>>
{
public:
static const bool HasOverlappingChildren = true;
@@ -226,13 +226,13 @@ class TreeTraits<BinarySpaceTree<MetricType, StatisticType, MatType,
* overlapping children.
* See mlpack/core/tree/tree_traits.hpp for more information.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename SplitBoundType, typename SplitMatType>
class SplitType>
class TreeTraits<BinarySpaceTree<MetricType, StatisticType, MatType, CellBound,
SplitType>>
class TreeTraits<BinarySpaceTree<
DistanceType, StatisticType, MatType, CellBound, SplitType>>
{
public:
static const bool HasOverlappingChildren = true;
@@ -54,8 +54,8 @@ namespace mlpack {
*
* @see @ref trees, BinarySpaceTree, MeanSplitKDTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using KDTree = BinarySpaceTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using KDTree = BinarySpaceTree<DistanceType,
StatisticType,
MatType,
HRectBound,
@@ -71,8 +71,8 @@ using KDTree = BinarySpaceTree<MetricType,
*
* @see @ref trees, BinarySpaceTree, KDTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using MeanSplitKDTree = BinarySpaceTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using MeanSplitKDTree = BinarySpaceTree<DistanceType,
StatisticType,
MatType,
HRectBound,
@@ -103,8 +103,8 @@ using MeanSplitKDTree = BinarySpaceTree<MetricType,
*
* @see @ref trees, BinarySpaceTree, KDTree, MeanSplitBallTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using BallTree = BinarySpaceTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using BallTree = BinarySpaceTree<DistanceType,
StatisticType,
MatType,
BallBound,
@@ -132,8 +132,8 @@ using BallTree = BinarySpaceTree<MetricType,
*
* @see @ref trees, BinarySpaceTree, BallTree, MeanSplitKDTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using MeanSplitBallTree = BinarySpaceTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using MeanSplitBallTree = BinarySpaceTree<DistanceType,
StatisticType,
MatType,
BallBound,
@@ -190,8 +190,8 @@ template<typename BoundType,
typename MatType = arma::mat>
using VPTreeSplit = VantagePointSplit<BoundType, MatType, 100>;
template<typename MetricType, typename StatisticType, typename MatType>
using VPTree = BinarySpaceTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using VPTree = BinarySpaceTree<DistanceType,
StatisticType,
MatType,
HollowBallBound,
@@ -223,8 +223,8 @@ using VPTree = BinarySpaceTree<MetricType,
* @see @ref trees, BinarySpaceTree, BallTree, MeanSplitKDTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using MaxRPTree = BinarySpaceTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using MaxRPTree = BinarySpaceTree<DistanceType,
StatisticType,
MatType,
HRectBound,
@@ -257,8 +257,8 @@ using MaxRPTree = BinarySpaceTree<MetricType,
*
* @see @ref trees, BinarySpaceTree, BallTree, MeanSplitKDTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using RPTree = BinarySpaceTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using RPTree = BinarySpaceTree<DistanceType,
StatisticType,
MatType,
HRectBound,
@@ -292,8 +292,8 @@ using RPTree = BinarySpaceTree<MetricType,
*
* @see @ref trees, BinarySpaceTree, BallTree, MeanSplitKDTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using UBTree = BinarySpaceTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using UBTree = BinarySpaceTree<DistanceType,
StatisticType,
MatType,
CellBound,
@@ -34,7 +34,7 @@ class VantagePointSplit
//! The matrix element type.
typedef typename MatType::elem_type ElemType;
//! The bounding shape type.
typedef typename BoundType::MetricType MetricType;
typedef typename BoundType::DistanceType DistanceType;
//! A struct that contains an information about the split.
struct SplitInfo
{
@@ -42,20 +42,20 @@ class VantagePointSplit
arma::Col<ElemType> 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<typename VecType>
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,
@@ -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<typename BoundType, typename MatType, size_t MaxNumSamples>
void VantagePointSplit<BoundType, MatType, MaxNumSamples>::
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<ElemType> 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;
+1 -1
View File
@@ -13,7 +13,7 @@
#define MLPACK_CORE_TREE_BOUNDS_HPP
#include <mlpack/core/math/range.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/distances/lmetric.hpp>
#include "bound_traits.hpp"
#include "hrectbound.hpp"
+17 -10
View File
@@ -36,7 +36,7 @@
#include <mlpack/prereqs.hpp>
#include <mlpack/core/math/range.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/distances/lmetric.hpp>
#include "bound_traits.hpp"
#include "address.hpp"
@@ -69,7 +69,7 @@ namespace mlpack {
* }
* @endcode
*/
template<typename MetricType = LMetric<2, true>,
template<typename DistanceType = LMetric<2, true>,
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<AddressElemType> 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<typename MetricType, typename ElemType>
struct BoundTraits<CellBound<MetricType, ElemType>>
template<typename DistanceType, typename ElemType>
struct BoundTraits<CellBound<DistanceType, ElemType>>
{
//! These bounds are always tight for each dimension.
const static bool HasTightBounds = true;
+106 -106
View File
@@ -23,8 +23,8 @@ namespace mlpack {
/**
* Empty constructor.
*/
template<typename MetricType, typename ElemType>
inline CellBound<MetricType, ElemType>::CellBound() :
template<typename DistanceType, typename ElemType>
inline CellBound<DistanceType, ElemType>::CellBound() :
dim(0),
bounds(NULL),
loBound(arma::Mat<ElemType>()),
@@ -39,8 +39,8 @@ inline CellBound<MetricType, ElemType>::CellBound() :
* Initializes to specified dimensionality with each dimension the empty
* set.
*/
template<typename MetricType, typename ElemType>
inline CellBound<MetricType, ElemType>::CellBound(const size_t dimension) :
template<typename DistanceType, typename ElemType>
inline CellBound<DistanceType, ElemType>::CellBound(const size_t dimension) :
dim(dimension),
bounds(new RangeType<ElemType>[dim]),
loBound(arma::Mat<ElemType>(dim, maxNumBounds)),
@@ -60,9 +60,9 @@ inline CellBound<MetricType, ElemType>::CellBound(const size_t dimension) :
/**
* Copy constructor necessary to prevent memory leaks.
*/
template<typename MetricType, typename ElemType>
inline CellBound<MetricType, ElemType>::CellBound(
const CellBound<MetricType, ElemType>& other) :
template<typename DistanceType, typename ElemType>
inline CellBound<DistanceType, ElemType>::CellBound(
const CellBound<DistanceType, ElemType>& other) :
dim(other.Dim()),
bounds(new RangeType<ElemType>[dim]),
loBound(other.loBound),
@@ -80,11 +80,11 @@ inline CellBound<MetricType, ElemType>::CellBound(
/**
* Same as the copy constructor.
*/
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
inline CellBound<
MetricType,
ElemType>& CellBound<MetricType, ElemType>::operator=(
const CellBound<MetricType, ElemType>& other)
DistanceType,
ElemType>& CellBound<DistanceType, ElemType>::operator=(
const CellBound<DistanceType, ElemType>& other)
{
if (this == &other)
return *this;
@@ -116,9 +116,9 @@ inline CellBound<
/**
* Move constructor: take possession of another bound's information.
*/
template<typename MetricType, typename ElemType>
inline CellBound<MetricType, ElemType>::CellBound(
CellBound<MetricType, ElemType>&& other) :
template<typename DistanceType, typename ElemType>
inline CellBound<DistanceType, ElemType>::CellBound(
CellBound<DistanceType, ElemType>&& other) :
dim(other.dim),
bounds(other.bounds),
loBound(std::move(other.loBound)),
@@ -137,8 +137,8 @@ inline CellBound<MetricType, ElemType>::CellBound(
/**
* Destructor: clean up memory.
*/
template<typename MetricType, typename ElemType>
inline CellBound<MetricType, ElemType>::~CellBound()
template<typename DistanceType, typename ElemType>
inline CellBound<DistanceType, ElemType>::~CellBound()
{
if (bounds)
delete[] bounds;
@@ -147,8 +147,8 @@ inline CellBound<MetricType, ElemType>::~CellBound()
/**
* Resets all dimensions to the empty set.
*/
template<typename MetricType, typename ElemType>
inline void CellBound<MetricType, ElemType>::Clear()
template<typename DistanceType, typename ElemType>
inline void CellBound<DistanceType, ElemType>::Clear()
{
for (size_t k = 0; k < dim; ++k)
{
@@ -166,8 +166,8 @@ inline void CellBound<MetricType, ElemType>::Clear()
*
* @param centroid Vector which the centroid will be written to.
*/
template<typename MetricType, typename ElemType>
inline void CellBound<MetricType, ElemType>::Center(
template<typename DistanceType, typename ElemType>
inline void CellBound<DistanceType, ElemType>::Center(
arma::Col<ElemType>& center) const
{
// Set size correctly if necessary.
@@ -178,9 +178,9 @@ inline void CellBound<MetricType, ElemType>::Center(
center(i) = bounds[i].Mid();
}
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename MatType>
void CellBound<MetricType, ElemType>::AddBound(
void CellBound<DistanceType, ElemType>::AddBound(
const arma::Col<ElemType>& loCorner,
const arma::Col<ElemType>& hiCorner,
const MatType& data)
@@ -223,9 +223,9 @@ void CellBound<MetricType, ElemType>::AddBound(
}
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename MatType>
void CellBound<MetricType, ElemType>::InitHighBound(size_t numEqualBits,
void CellBound<DistanceType, ElemType>::InitHighBound(size_t numEqualBits,
const MatType& data)
{
arma::Col<AddressElemType> tmpHiAddress(hiAddress);
@@ -312,9 +312,9 @@ void CellBound<MetricType, ElemType>::InitHighBound(size_t numEqualBits,
}
}
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename MatType>
void CellBound<MetricType, ElemType>::InitLowerBound(size_t numEqualBits,
void CellBound<DistanceType, ElemType>::InitLowerBound(size_t numEqualBits,
const MatType& data)
{
arma::Col<AddressElemType> tmpHiAddress(loAddress);
@@ -402,9 +402,9 @@ void CellBound<MetricType, ElemType>::InitLowerBound(size_t numEqualBits,
}
}
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename MatType>
void CellBound<MetricType, ElemType>::UpdateAddressBounds(const MatType& data)
void CellBound<DistanceType, ElemType>::UpdateAddressBounds(const MatType& data)
{
numBounds = 0;
@@ -470,9 +470,9 @@ void CellBound<MetricType, ElemType>::UpdateAddressBounds(const MatType& data)
/**
* Calculates minimum bound-to-point squared distance.
*/
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename VecType>
inline ElemType CellBound<MetricType, ElemType>::MinDistance(
inline ElemType CellBound<DistanceType, ElemType>::MinDistance(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>* /* junk */) const
{
@@ -495,9 +495,9 @@ inline ElemType CellBound<MetricType, ElemType>::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<MetricType, ElemType>::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<MetricType, ElemType>::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<typename MetricType, typename ElemType>
ElemType CellBound<MetricType, ElemType>::MinDistance(const CellBound& other)
template<typename DistanceType, typename ElemType>
ElemType CellBound<DistanceType, ElemType>::MinDistance(const CellBound& other)
const
{
Log::Assert(dim == other.dim);
@@ -565,9 +565,9 @@ ElemType CellBound<MetricType, ElemType>::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<MetricType, ElemType>::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<MetricType, ElemType>::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<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename VecType>
inline ElemType CellBound<MetricType, ElemType>::MaxDistance(
inline ElemType CellBound<DistanceType, ElemType>::MaxDistance(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>* /* junk */) const
{
@@ -627,12 +627,12 @@ inline ElemType CellBound<MetricType, ElemType>::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<MetricType, ElemType>::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<MetricType, ElemType>::MaxDistance(
/**
* Computes maximum distance.
*/
template<typename MetricType, typename ElemType>
inline ElemType CellBound<MetricType, ElemType>::MaxDistance(
template<typename DistanceType, typename ElemType>
inline ElemType CellBound<DistanceType, ElemType>::MaxDistance(
const CellBound& other)
const
{
@@ -677,12 +677,12 @@ inline ElemType CellBound<MetricType, ElemType>::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<MetricType, ElemType>::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<MetricType, ElemType>::MaxDistance(
/**
* Calculates minimum and maximum bound-to-bound squared distance.
*/
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
inline RangeType<ElemType>
CellBound<MetricType, ElemType>::RangeDistance(
CellBound<DistanceType, ElemType>::RangeDistance(
const CellBound& other) const
{
ElemType minLoSum = std::numeric_limits<ElemType>::max();
@@ -741,20 +741,20 @@ CellBound<MetricType, ElemType>::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<MetricType, ElemType>::RangeDistance(
maxHiSum = hiSum;
}
if (MetricType::TakeRoot)
if (DistanceType::TakeRoot)
{
if (MetricType::Power == 1)
if (DistanceType::Power == 1)
return RangeType<ElemType>(minLoSum, maxHiSum);
else if (MetricType::Power == 2)
else if (DistanceType::Power == 2)
return RangeType<ElemType>((ElemType) std::sqrt(minLoSum),
(ElemType) std::sqrt(maxHiSum));
else
{
return RangeType<ElemType>(
(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<MetricType, ElemType>::RangeDistance(
/**
* Calculates minimum and maximum bound-to-point squared distance.
*/
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename VecType>
inline RangeType<ElemType>
CellBound<MetricType, ElemType>::RangeDistance(
CellBound<DistanceType, ElemType>::RangeDistance(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>* /* junk */) const
{
@@ -830,20 +830,20 @@ CellBound<MetricType, ElemType>::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<MetricType, ElemType>::RangeDistance(
maxHiSum = hiSum;
}
if (MetricType::TakeRoot)
if (DistanceType::TakeRoot)
{
if (MetricType::Power == 1)
if (DistanceType::Power == 1)
return RangeType<ElemType>(minLoSum, maxHiSum);
else if (MetricType::Power == 2)
else if (DistanceType::Power == 2)
return RangeType<ElemType>((ElemType) std::sqrt(minLoSum),
(ElemType) std::sqrt(maxHiSum));
else
{
return RangeType<ElemType>(
(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<MetricType, ElemType>::RangeDistance(
/**
* Expands this region to include a new point.
*/
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename MatType>
inline CellBound<MetricType, ElemType>&
CellBound<MetricType, ElemType>::operator|=(const MatType& data)
inline CellBound<DistanceType, ElemType>&
CellBound<DistanceType, ElemType>::operator|=(const MatType& data)
{
Log::Assert(data.n_rows == dim);
@@ -905,9 +905,9 @@ CellBound<MetricType, ElemType>::operator|=(const MatType& data)
/**
* Expands this region to encompass another bound.
*/
template<typename MetricType, typename ElemType>
inline CellBound<MetricType, ElemType>&
CellBound<MetricType, ElemType>::operator|=(const CellBound& other)
template<typename DistanceType, typename ElemType>
inline CellBound<DistanceType, ElemType>&
CellBound<DistanceType, ElemType>::operator|=(const CellBound& other)
{
assert(other.dim == dim);
@@ -943,9 +943,9 @@ CellBound<MetricType, ElemType>::operator|=(const CellBound& other)
/**
* Determines if a point is within this bound.
*/
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename VecType>
inline bool CellBound<MetricType, ElemType>::Contains(
inline bool CellBound<DistanceType, ElemType>::Contains(
const VecType& point) const
{
for (size_t i = 0; i < point.n_elem; ++i)
@@ -968,24 +968,24 @@ inline bool CellBound<MetricType, ElemType>::Contains(
/**
* Returns the diameter of the hyperrectangle (that is, the longest diagonal).
*/
template<typename MetricType, typename ElemType>
inline ElemType CellBound<MetricType, ElemType>::Diameter() const
template<typename DistanceType, typename ElemType>
inline ElemType CellBound<DistanceType, ElemType>::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<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename Archive>
void CellBound<MetricType, ElemType>::serialize(
void CellBound<DistanceType, ElemType>::serialize(
Archive& ar,
const uint32_t /* version */)
{
@@ -996,7 +996,7 @@ void CellBound<MetricType, ElemType>::serialize(
ar(CEREAL_NVP(numBounds));
ar(CEREAL_NVP(loAddress));
ar(CEREAL_NVP(hiAddress));
ar(CEREAL_NVP(metric));
ar(CEREAL_NVP(distance));
}
} // namespace mlpack
+32 -27
View File
@@ -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<typename MetricType = LMetric<2, true>,
template<typename DistanceType = LMetric<2, true>,
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.
@@ -34,15 +34,15 @@ void BuildStatistics(TreeType* node)
// Create the cover tree.
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
}
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::CoverTree(
const MatType& dataset,
MetricType& metric,
DistanceType& distance,
const ElemType base) :
dataset(&dataset),
point(RootPointPolicy::ChooseRoot(dataset)),
@@ -151,9 +152,9 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
}
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::CoverTree(
MatType&& data,
const ElemType base) :
dataset(new MatType(std::move(data))),
@@ -246,12 +247,12 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
}
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
}
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::CoverTree(
const MatType& dataset,
const ElemType base,
const size_t pointIndex,
@@ -440,7 +441,7 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
// Manually create a cover tree node.
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::CoverTree(
const MatType& dataset,
const ElemType base,
const size_t pointIndex,
@@ -481,7 +482,7 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
CoverTree* parent,
const ElemType parentDistance,
const ElemType furthestDescendantDistance,
MetricType* metric) :
DistanceType* distance) :
dataset(&dataset),
point(pointIndex),
scale(scale),
@@ -490,24 +491,24 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::CoverTree(
const CoverTree& other) :
dataset((other.parent == NULL && other.localDataset) ?
new MatType(*other.dataset) : other.dataset),
@@ -519,9 +520,9 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
// Copy assignment operator: copy the given other tree.
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>&
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>&
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
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<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::CoverTree(
CoverTree&& other) :
dataset(other.dataset),
point(other.point),
@@ -639,9 +640,9 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>&
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>&
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
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<typename Archive>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::CoverTree(
Archive& ar,
const typename std::enable_if_t<cereal::is_loading<Archive>()>*) :
CoverTree() // Create an empty CoverTree.
@@ -738,20 +739,20 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::~CoverTree()
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::~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<MetricType, StatisticType, MatType, RootPointPolicy>::~CoverTree()
//! Return the number of descendant points.
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
inline size_t
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
NumDescendants() const
{
return numDescendants;
@@ -774,13 +775,13 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
//! Return the index of a particular descendant point.
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
inline size_t
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::Descendant(
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::Descendant(
const size_t index) const
{
// The first descendant is the point contained within this node.
@@ -808,12 +809,12 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy>
template<typename VecType>
size_t CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
size_t CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
GetNearestChild(const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>*)
{
@@ -838,12 +839,12 @@ size_t CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
* 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy>
template<typename VecType>
size_t CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
size_t CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
GetFurthestChild(const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>*)
{
@@ -868,11 +869,11 @@ size_t CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
* 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy>
size_t CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
size_t CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
GetNearestChild(const CoverTree& queryNode)
{
if (IsLeaf())
@@ -896,11 +897,11 @@ size_t CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
* 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy>
size_t CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
size_t CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
GetFurthestChild(const CoverTree& queryNode)
{
if (IsLeaf())
@@ -921,31 +922,31 @@ size_t CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
}
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
typename CoverTree<MetricType, StatisticType, MatType,
typename CoverTree<DistanceType, StatisticType, MatType,
RootPointPolicy>::ElemType
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
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<MetricType, StatisticType, MatType,
typename CoverTree<DistanceType, StatisticType, MatType,
RootPointPolicy>::ElemType
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
MinDistance(const CoverTree& other, const ElemType distance) const
{
// We already have the distance as evaluated by the metric.
@@ -954,59 +955,59 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
}
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
typename CoverTree<MetricType, StatisticType, MatType,
typename CoverTree<DistanceType, StatisticType, MatType,
RootPointPolicy>::ElemType
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
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<MetricType, StatisticType, MatType,
typename CoverTree<DistanceType, StatisticType, MatType,
RootPointPolicy>::ElemType
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
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<MetricType, StatisticType, MatType,
typename CoverTree<DistanceType, StatisticType, MatType,
RootPointPolicy>::ElemType
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
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<MetricType, StatisticType, MatType,
typename CoverTree<DistanceType, StatisticType, MatType,
RootPointPolicy>::ElemType
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
MaxDistance(const CoverTree& other, const ElemType distance) const
{
// We already have the distance as evaluated by the metric.
@@ -1015,29 +1016,29 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
}
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
typename CoverTree<MetricType, StatisticType, MatType,
typename CoverTree<DistanceType, StatisticType, MatType,
RootPointPolicy>::ElemType
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
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<MetricType, StatisticType, MatType,
typename CoverTree<DistanceType, StatisticType, MatType,
RootPointPolicy>::ElemType
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
MaxDistance(const arma::vec& /* other */, const ElemType distance) const
{
return distance + furthestDescendantDistance;
@@ -1045,23 +1046,23 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
//! Return the minimum and maximum distance to another node.
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
RangeType<typename
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::ElemType>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::ElemType>
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
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<ElemType> 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<MetricType, StatisticType, MatType, RootPointPolicy>::
//! 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<typename
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::ElemType>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::ElemType>
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
RangeDistance(const CoverTree& other,
const ElemType distance) const
{
@@ -1092,34 +1093,34 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
//! Return the minimum and maximum distance to another point.
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
RangeType<typename
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::ElemType>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::ElemType>
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
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<ElemType>(
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<typename
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::ElemType>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::ElemType>
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
RangeDistance(const arma::vec& /* other */,
const ElemType distance) const
{
@@ -1130,13 +1131,13 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
//! 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<MetricType, StatisticType, MatType, RootPointPolicy>::CreateChildren(
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::CreateChildren(
arma::Col<size_t>& indices,
arma::vec& distances,
size_t nearSetSize,
@@ -1159,7 +1160,7 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::CreateChildren(
}
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
size_t CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
size_t CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
SplitNearFar(arma::Col<size_t>& indices,
arma::vec& distances,
const ElemType bound,
@@ -1383,12 +1384,12 @@ size_t CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
// Returns the maximum distance between points.
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
void CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
ComputeDistances(const size_t pointIndex,
const arma::Col<size_t>& indices,
arma::vec& distances,
@@ -1399,18 +1400,18 @@ void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
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<MetricType, StatisticType, MatType, RootPointPolicy>::
size_t CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
SortPointSet(arma::Col<size_t>& indices,
arma::vec& distances,
const size_t childFarSetSize,
@@ -1470,12 +1471,12 @@ size_t CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
}
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
void CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
MoveToUsedSet(arma::Col<size_t>& indices,
arma::vec& distances,
size_t& nearSetSize,
@@ -1616,12 +1617,12 @@ void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
}
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
size_t CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
size_t CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
PruneFarSet(arma::Col<size_t>& indices,
arma::vec& distances,
const ElemType bound,
@@ -1662,12 +1663,12 @@ size_t CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
* implicit nodes that have been created.
*/
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
inline void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
inline void CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
RemoveNewImplicitNodes()
{
// If we created an implicit node, take its self-child instead (this could
@@ -1697,12 +1698,12 @@ inline void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
* Default constructor, only for use with cereal.
*/
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree() :
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::CoverTree() :
dataset(NULL),
point(0),
scale(INT_MIN),
@@ -1711,9 +1712,9 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::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<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree() :
* Serialize to/from a cereal archive.
*/
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
template<typename Archive>
void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::serialize(
void
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::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<Archive>())
{
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<MetricType, StatisticType, MatType, RootPointPolicy>::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<Archive>() && !hasParent)
{
localMetric = true;
localDistance = true;
localDataset = true;
}
@@ -1777,7 +1779,7 @@ void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::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;
}
@@ -18,13 +18,13 @@
namespace mlpack {
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
template<typename RuleType>
class CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
class CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
DualTreeTraverser
{
public:
@@ -63,7 +63,7 @@ class CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
struct DualCoverTreeMapEntry
{
//! The node this entry refers to.
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>*
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>*
referenceNode;
//! The score of the node.
double score;
@@ -18,26 +18,26 @@
namespace mlpack {
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
template<typename RuleType>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
DualTreeTraverser<RuleType>::DualTreeTraverser(RuleType& rule) :
rule(rule),
numPrunes(0)
{ /* Nothing to do. */ }
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
template<typename RuleType>
void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
void CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
DualTreeTraverser<RuleType>::Traverse(CoverTree& queryNode,
CoverTree& referenceNode)
{
@@ -60,13 +60,13 @@ DualTreeTraverser<RuleType>::Traverse(CoverTree& queryNode,
}
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
template<typename RuleType>
void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
void CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
DualTreeTraverser<RuleType>::Traverse(
CoverTree& queryNode,
std::map<int, std::vector<DualCoverTreeMapEntry>, std::greater<int>>&
@@ -150,13 +150,13 @@ DualTreeTraverser<RuleType>::Traverse(
}
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
template<typename RuleType>
void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
void CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
DualTreeTraverser<RuleType>::PruneMap(
CoverTree& queryNode,
std::map<int, std::vector<DualCoverTreeMapEntry>, std::greater<int>>&
@@ -271,13 +271,13 @@ DualTreeTraverser<RuleType>::PruneMap(
}
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
template<typename RuleType>
void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
void CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
DualTreeTraverser<RuleType>::ReferenceRecursion(
CoverTree& queryNode,
std::map<int, std::vector<DualCoverTreeMapEntry>, std::greater<int>>&
@@ -21,13 +21,13 @@
namespace mlpack {
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
template<typename RuleType>
class CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
class CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
SingleTreeTraverser
{
public:
@@ -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<MetricType, StatisticType, MatType, RootPointPolicy>* node;
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>* 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<typename RuleType>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
SingleTreeTraverser<RuleType>::SingleTreeTraverser(RuleType& rule) :
rule(rule),
numPrunes(0)
{ /* Nothing to do. */ }
template<
typename MetricType,
typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
template<typename RuleType>
void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
void CoverTree<DistanceType, StatisticType, MatType, RootPointPolicy>::
SingleTreeTraverser<RuleType>::Traverse(
const size_t queryIndex,
CoverTree& referenceNode)
{
// This is a non-recursive implementation (which should be faster than a
// recursive implementation).
typedef CoverTreeMapEntry<MetricType, StatisticType, MatType, RootPointPolicy>
MapEntryType;
typedef CoverTreeMapEntry<DistanceType, StatisticType, MatType,
RootPointPolicy> 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
+3 -2
View File
@@ -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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename RootPointPolicy>
class TreeTraits<CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>>
class TreeTraits<CoverTree<
DistanceType, StatisticType, MatType, RootPointPolicy>>
{
public:
/**
+2 -2
View File
@@ -34,8 +34,8 @@ namespace mlpack {
*
* @see @ref trees, CoverTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using StandardCoverTree = CoverTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using StandardCoverTree = CoverTree<DistanceType,
StatisticType,
MatType,
FirstPointIsRoot>;
+28 -25
View File
@@ -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<typename MetricType = LMetric<2, true>,
template<typename DistanceType = LMetric<2, true>,
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
+23 -16
View File
@@ -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 <mlpack/prereqs.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/distances/lmetric.hpp>
#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<typename TMetricType = LMetric<2, true>,
template<typename TDistanceType = LMetric<2, true>,
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<ElemType> center;
//! The center of the hollow.
arma::Col<ElemType> 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<typename Archive>
@@ -238,8 +245,8 @@ class HollowBallBound
};
//! A specialization of BoundTraits for this bound type.
template<typename MetricType, typename ElemType>
struct BoundTraits<HollowBallBound<MetricType, ElemType>>
template<typename DistanceType, typename ElemType>
struct BoundTraits<HollowBallBound<DistanceType, ElemType>>
{
//! These bounds are potentially loose in some dimensions.
const static bool HasTightBounds = false;
+91 -90
View File
@@ -18,12 +18,12 @@
namespace mlpack {
//! Empty Constructor.
template<typename TMetricType, typename ElemType>
HollowBallBound<TMetricType, ElemType>::HollowBallBound() :
template<typename TDistanceType, typename ElemType>
HollowBallBound<TDistanceType, ElemType>::HollowBallBound() :
radii(std::numeric_limits<ElemType>::lowest(),
std::numeric_limits<ElemType>::lowest()),
metric(new MetricType()),
ownsMetric(true)
distance(new DistanceType()),
ownsDistance(true)
{ /* Nothing to do. */ }
/**
@@ -31,15 +31,15 @@ HollowBallBound<TMetricType, ElemType>::HollowBallBound() :
*
* @param dimension Dimensionality of ball bound.
*/
template<typename TMetricType, typename ElemType>
HollowBallBound<TMetricType, ElemType>::
template<typename TDistanceType, typename ElemType>
HollowBallBound<TDistanceType, ElemType>::
HollowBallBound(const size_t dimension) :
radii(std::numeric_limits<ElemType>::lowest(),
std::numeric_limits<ElemType>::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<typename TMetricType, typename ElemType>
template<typename TDistanceType, typename ElemType>
template<typename VecType>
HollowBallBound<TMetricType, ElemType>::
HollowBallBound<TDistanceType, ElemType>::
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<typename TMetricType, typename ElemType>
HollowBallBound<TMetricType, ElemType>::HollowBallBound(
template<typename TDistanceType, typename ElemType>
HollowBallBound<TDistanceType, ElemType>::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<typename TMetricType, typename ElemType>
HollowBallBound<TMetricType, ElemType>& HollowBallBound<TMetricType, ElemType>::
template<typename TDistanceType, typename ElemType>
HollowBallBound<TDistanceType, ElemType>& HollowBallBound<TDistanceType, ElemType>::
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<typename TMetricType, typename ElemType>
HollowBallBound<TMetricType, ElemType>::HollowBallBound(
template<typename TDistanceType, typename ElemType>
HollowBallBound<TDistanceType, ElemType>::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<ElemType>();
other.hollowCenter = arma::Col<ElemType>();
other.metric = NULL;
other.ownsMetric = false;
other.distance = NULL;
other.ownsDistance = false;
}
//! Move assignment operator.
template<typename TMetricType, typename ElemType>
HollowBallBound<TMetricType, ElemType>& HollowBallBound<TMetricType, ElemType>::
template<typename TDistanceType, typename ElemType>
HollowBallBound<TDistanceType, ElemType>& HollowBallBound<TDistanceType, ElemType>::
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<ElemType>();
other.hollowCenter = arma::Col<ElemType>();
other.metric = nullptr;
other.ownsMetric = false;
other.distance = nullptr;
other.ownsDistance = false;
}
return *this;
}
//! Destructor to release allocated memory.
template<typename TMetricType, typename ElemType>
HollowBallBound<TMetricType, ElemType>::~HollowBallBound()
template<typename TDistanceType, typename ElemType>
HollowBallBound<TDistanceType, ElemType>::~HollowBallBound()
{
if (ownsMetric)
delete metric;
if (ownsDistance)
delete distance;
}
//! Get the range in a certain dimension.
template<typename TMetricType, typename ElemType>
RangeType<ElemType> HollowBallBound<TMetricType, ElemType>::operator[](
template<typename TDistanceType, typename ElemType>
RangeType<ElemType> HollowBallBound<TDistanceType, ElemType>::operator[](
const size_t i) const
{
if (radii.Hi() < 0)
@@ -157,21 +157,21 @@ RangeType<ElemType> HollowBallBound<TMetricType, ElemType>::operator[](
/**
* Determines if a point is within the bound.
*/
template<typename TMetricType, typename ElemType>
template<typename TDistanceType, typename ElemType>
template<typename VecType>
bool HollowBallBound<TMetricType, ElemType>::Contains(
bool HollowBallBound<TDistanceType, ElemType>::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<TMetricType, ElemType>::Contains(
/**
* Determines if another bound is within this bound.
*/
template<typename TMetricType, typename ElemType>
bool HollowBallBound<TMetricType, ElemType>::Contains(
template<typename TDistanceType, typename ElemType>
bool HollowBallBound<TDistanceType, ElemType>::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<TMetricType, ElemType>::Contains(
/**
* Calculates minimum bound-to-point squared distance.
*/
template<typename TMetricType, typename ElemType>
template<typename TDistanceType, typename ElemType>
template<typename VecType>
ElemType HollowBallBound<TMetricType, ElemType>::MinDistance(
ElemType HollowBallBound<TDistanceType, ElemType>::MinDistance(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>* /* junk */) const
{
@@ -225,14 +225,15 @@ ElemType HollowBallBound<TMetricType, ElemType>::MinDistance(
return std::numeric_limits<ElemType>::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<TMetricType, ElemType>::MinDistance(
/**
* Calculates minimum bound-to-bound squared distance.
*/
template<typename TMetricType, typename ElemType>
ElemType HollowBallBound<TMetricType, ElemType>::MinDistance(
template<typename TDistanceType, typename ElemType>
ElemType HollowBallBound<TDistanceType, ElemType>::MinDistance(
const HollowBallBound& other)
const
{
@@ -250,7 +251,7 @@ ElemType HollowBallBound<TMetricType, ElemType>::MinDistance(
return std::numeric_limits<ElemType>::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<TMetricType, ElemType>::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<TMetricType, ElemType>::MinDistance(
/**
* Computes maximum distance.
*/
template<typename TMetricType, typename ElemType>
template<typename TDistanceType, typename ElemType>
template<typename VecType>
ElemType HollowBallBound<TMetricType, ElemType>::MaxDistance(
ElemType HollowBallBound<TDistanceType, ElemType>::MaxDistance(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>* /* junk */) const
{
if (radii.Hi() < 0)
return std::numeric_limits<ElemType>::max();
else
return metric->Evaluate(point, center) + radii.Hi();
return distance->Evaluate(point, center) + radii.Hi();
}
/**
* Computes maximum distance.
*/
template<typename TMetricType, typename ElemType>
ElemType HollowBallBound<TMetricType, ElemType>::MaxDistance(
template<typename TDistanceType, typename ElemType>
ElemType HollowBallBound<TDistanceType, ElemType>::MaxDistance(
const HollowBallBound& other)
const
{
if (radii.Hi() < 0)
return std::numeric_limits<ElemType>::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<TMetricType, ElemType>::MaxDistance(
*
* Example: bound1.MinDistanceSq(other) for minimum squared distance.
*/
template<typename TMetricType, typename ElemType>
template<typename TDistanceType, typename ElemType>
template<typename VecType>
RangeType<ElemType> HollowBallBound<TMetricType, ElemType>::RangeDistance(
RangeType<ElemType> HollowBallBound<TDistanceType, ElemType>::RangeDistance(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>* /* junk */) const
{
@@ -319,7 +320,7 @@ RangeType<ElemType> HollowBallBound<TMetricType, ElemType>::RangeDistance(
else
{
RangeType<ElemType> 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<ElemType> HollowBallBound<TMetricType, ElemType>::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<ElemType> HollowBallBound<TMetricType, ElemType>::RangeDistance(
}
}
template<typename TMetricType, typename ElemType>
RangeType<ElemType> HollowBallBound<TMetricType, ElemType>::RangeDistance(
template<typename TDistanceType, typename ElemType>
RangeType<ElemType> HollowBallBound<TDistanceType, ElemType>::RangeDistance(
const HollowBallBound& other) const
{
if (radii.Hi() < 0)
@@ -346,7 +347,7 @@ RangeType<ElemType> HollowBallBound<TMetricType, ElemType>::RangeDistance(
{
RangeType<ElemType> 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<ElemType> HollowBallBound<TMetricType, ElemType>::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<ElemType> HollowBallBound<TMetricType, ElemType>::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<ElemType> HollowBallBound<TMetricType, ElemType>::RangeDistance(
* The difference lies in the way we initialize the ball bound. The way we
* expand the bound is same.
*/
template<typename TMetricType, typename ElemType>
template<typename TDistanceType, typename ElemType>
template<typename MatType>
const HollowBallBound<TMetricType, ElemType>&
HollowBallBound<TMetricType, ElemType>::operator|=(const MatType& data)
const HollowBallBound<TDistanceType, ElemType>&
HollowBallBound<TDistanceType, ElemType>::operator|=(const MatType& data)
{
if (radii.Hi() < 0)
{
@@ -397,8 +398,8 @@ HollowBallBound<TMetricType, ElemType>::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<TMetricType, ElemType>::operator|=(const MatType& data)
/**
* Expand the bound to include the given bound.
*/
template<typename TMetricType, typename ElemType>
const HollowBallBound<TMetricType, ElemType>&
HollowBallBound<TMetricType, ElemType>::operator|=(const HollowBallBound& other)
template<typename TDistanceType, typename ElemType>
const HollowBallBound<TDistanceType, ElemType>&
HollowBallBound<TDistanceType, ElemType>::operator|=(const HollowBallBound& other)
{
if (radii.Hi() < 0)
{
@@ -432,13 +433,13 @@ HollowBallBound<TMetricType, ElemType>::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<TMetricType, ElemType>::operator|=(const HollowBallBound& other)
//! Serialize the BallBound.
template<typename TMetricType, typename ElemType>
template<typename TDistanceType, typename ElemType>
template<typename Archive>
void HollowBallBound<TMetricType, ElemType>::serialize(
void HollowBallBound<TDistanceType, ElemType>::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<Archive>())
{
// 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;
}
}
+21 -14
View File
@@ -16,14 +16,14 @@
#include <mlpack/prereqs.hpp>
#include <mlpack/core/math/range.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/distances/lmetric.hpp>
#include "bound_traits.hpp"
namespace mlpack {
//! Utility struct where Value is true if and only if the argument is of type
//! LMetric.
template<typename MetricType>
template<typename DistanceType>
struct IsLMetric
{
static const bool Value = false;
@@ -41,15 +41,15 @@ struct IsLMetric<LMetric<Power, TakeRoot>>
* 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<typename MetricType = LMetric<2, true>,
template<typename DistanceType = LMetric<2, true>,
typename ElemType = double>
class HRectBound
{
// It is required that HRectBound have an LMetric as the given MetricType.
static_assert(IsLMetric<MetricType>::Value == true,
// It is required that HRectBound have an LMetric as the given DistanceType.
static_assert(IsLMetric<DistanceType>::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<ElemType>* 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<typename MetricType, typename ElemType>
struct BoundTraits<HRectBound<MetricType, ElemType>>
template<typename DistanceType, typename ElemType>
struct BoundTraits<HRectBound<DistanceType, ElemType>>
{
//! These bounds are always tight for each dimension.
const static bool HasTightBounds = true;
+115 -116
View File
@@ -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<typename MetricType, typename ElemType>
inline HRectBound<MetricType, ElemType>::HRectBound() :
template<typename DistanceType, typename ElemType>
inline HRectBound<DistanceType, ElemType>::HRectBound() :
dim(0),
bounds(NULL),
minWidth(0)
@@ -33,8 +32,8 @@ inline HRectBound<MetricType, ElemType>::HRectBound() :
* Initializes to specified dimensionality with each dimension the empty
* set.
*/
template<typename MetricType, typename ElemType>
inline HRectBound<MetricType, ElemType>::HRectBound(const size_t dimension) :
template<typename DistanceType, typename ElemType>
inline HRectBound<DistanceType, ElemType>::HRectBound(const size_t dimension) :
dim(dimension),
bounds(new RangeType<ElemType>[dim]),
minWidth(0)
@@ -43,9 +42,9 @@ inline HRectBound<MetricType, ElemType>::HRectBound(const size_t dimension) :
/**
* Copy constructor necessary to prevent memory leaks.
*/
template<typename MetricType, typename ElemType>
inline HRectBound<MetricType, ElemType>::HRectBound(
const HRectBound<MetricType, ElemType>& other) :
template<typename DistanceType, typename ElemType>
inline HRectBound<DistanceType, ElemType>::HRectBound(
const HRectBound<DistanceType, ElemType>& other) :
dim(other.Dim()),
bounds(new RangeType<ElemType>[dim]),
minWidth(other.MinWidth())
@@ -58,11 +57,11 @@ inline HRectBound<MetricType, ElemType>::HRectBound(
/**
* Same as the copy constructor.
*/
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
inline HRectBound<
MetricType,
ElemType>& HRectBound<MetricType,
ElemType>::operator=(const HRectBound<MetricType, ElemType>& other)
DistanceType,
ElemType>& HRectBound<DistanceType,
ElemType>::operator=(const HRectBound<DistanceType, ElemType>& other)
{
if (this == &other)
return *this;
@@ -89,9 +88,9 @@ inline HRectBound<
/**
* Move constructor: take possession of another bound's information.
*/
template<typename MetricType, typename ElemType>
inline HRectBound<MetricType, ElemType>::HRectBound(
HRectBound<MetricType, ElemType>&& other) :
template<typename DistanceType, typename ElemType>
inline HRectBound<DistanceType, ElemType>::HRectBound(
HRectBound<DistanceType, ElemType>&& other) :
dim(other.dim),
bounds(other.bounds),
minWidth(other.minWidth)
@@ -105,10 +104,10 @@ inline HRectBound<MetricType, ElemType>::HRectBound(
/**
* Move assignment operator.
*/
template<typename MetricType, typename ElemType>
inline HRectBound<MetricType, ElemType>&
HRectBound<MetricType, ElemType>::operator=(
HRectBound<MetricType, ElemType>&& other)
template<typename DistanceType, typename ElemType>
inline HRectBound<DistanceType, ElemType>&
HRectBound<DistanceType, ElemType>::operator=(
HRectBound<DistanceType, ElemType>&& other)
{
if (this != &other)
{
@@ -125,8 +124,8 @@ HRectBound<MetricType, ElemType>::operator=(
/**
* Destructor: clean up memory.
*/
template<typename MetricType, typename ElemType>
inline HRectBound<MetricType, ElemType>::~HRectBound()
template<typename DistanceType, typename ElemType>
inline HRectBound<DistanceType, ElemType>::~HRectBound()
{
if (bounds)
delete[] bounds;
@@ -135,8 +134,8 @@ inline HRectBound<MetricType, ElemType>::~HRectBound()
/**
* Resets all dimensions to the empty set.
*/
template<typename MetricType, typename ElemType>
inline void HRectBound<MetricType, ElemType>::Clear()
template<typename DistanceType, typename ElemType>
inline void HRectBound<DistanceType, ElemType>::Clear()
{
for (size_t i = 0; i < dim; ++i)
bounds[i] = RangeType<ElemType>();
@@ -148,8 +147,8 @@ inline void HRectBound<MetricType, ElemType>::Clear()
*
* @param centroid Vector which the centroid will be written to.
*/
template<typename MetricType, typename ElemType>
inline void HRectBound<MetricType, ElemType>::Center(
template<typename DistanceType, typename ElemType>
inline void HRectBound<DistanceType, ElemType>::Center(
arma::Col<ElemType>& center) const
{
// Set size correctly if necessary.
@@ -165,8 +164,8 @@ inline void HRectBound<MetricType, ElemType>::Center(
*
* @return Volume of the hyperrectangle.
*/
template<typename MetricType, typename ElemType>
inline ElemType HRectBound<MetricType, ElemType>::Volume() const
template<typename DistanceType, typename ElemType>
inline ElemType HRectBound<DistanceType, ElemType>::Volume() const
{
ElemType volume = 1.0;
for (size_t i = 0; i < dim; ++i)
@@ -183,9 +182,9 @@ inline ElemType HRectBound<MetricType, ElemType>::Volume() const
/**
* Calculates minimum bound-to-point squared distance.
*/
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename VecType>
inline ElemType HRectBound<MetricType, ElemType>::MinDistance(
inline ElemType HRectBound<DistanceType, ElemType>::MinDistance(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>* /* junk */) const
{
@@ -202,9 +201,9 @@ inline ElemType HRectBound<MetricType, ElemType>::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<MetricType, ElemType>::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<MetricType, ElemType>::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<typename MetricType, typename ElemType>
ElemType HRectBound<MetricType, ElemType>::MinDistance(const HRectBound& other)
template<typename DistanceType, typename ElemType>
ElemType HRectBound<DistanceType, ElemType>::MinDistance(const HRectBound& other)
const
{
Log::Assert(dim == other.dim);
@@ -262,9 +261,9 @@ ElemType HRectBound<MetricType, ElemType>::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<MetricType, ElemType>::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<MetricType, ElemType>::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<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename VecType>
inline ElemType HRectBound<MetricType, ElemType>::MaxDistance(
inline ElemType HRectBound<DistanceType, ElemType>::MaxDistance(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>* /* junk */) const
{
@@ -319,24 +318,24 @@ inline ElemType HRectBound<MetricType, ElemType>::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<MetricType, ElemType>::MaxDistance(
/**
* Computes maximum distance.
*/
template<typename MetricType, typename ElemType>
inline ElemType HRectBound<MetricType, ElemType>::MaxDistance(
template<typename DistanceType, typename ElemType>
inline ElemType HRectBound<DistanceType, ElemType>::MaxDistance(
const HRectBound& other)
const
{
@@ -361,24 +360,24 @@ inline ElemType HRectBound<MetricType, ElemType>::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<MetricType, ElemType>::MaxDistance(
/**
* Calculates minimum and maximum bound-to-bound squared distance.
*/
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
inline RangeType<ElemType>
HRectBound<MetricType, ElemType>::RangeDistance(
HRectBound<DistanceType, ElemType>::RangeDistance(
const HRectBound& other) const
{
ElemType loSum = 0;
@@ -415,36 +414,36 @@ HRectBound<MetricType, ElemType>::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<ElemType>(loSum, hiSum);
else if (MetricType::Power == 2)
else if (DistanceType::Power == 2)
return RangeType<ElemType>((ElemType) std::sqrt(loSum),
(ElemType) std::sqrt(hiSum));
else
{
return RangeType<ElemType>(
(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<MetricType, ElemType>::RangeDistance(
/**
* Calculates minimum and maximum bound-to-point squared distance.
*/
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename VecType>
inline RangeType<ElemType>
HRectBound<MetricType, ElemType>::RangeDistance(
HRectBound<DistanceType, ElemType>::RangeDistance(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>* /* junk */) const
{
@@ -492,36 +491,36 @@ HRectBound<MetricType, ElemType>::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<ElemType>(loSum, hiSum);
else if (MetricType::Power == 2)
else if (DistanceType::Power == 2)
return RangeType<ElemType>((ElemType) std::sqrt(loSum),
(ElemType) std::sqrt(hiSum));
else
{
return RangeType<ElemType>(
(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<MetricType, ElemType>::RangeDistance(
/**
* Expands this region to include a new point.
*/
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename MatType>
inline HRectBound<MetricType, ElemType>&
HRectBound<MetricType, ElemType>::operator|=(const MatType& data)
inline HRectBound<DistanceType, ElemType>&
HRectBound<DistanceType, ElemType>::operator|=(const MatType& data)
{
Log::Assert(data.n_rows == dim);
@@ -556,9 +555,9 @@ HRectBound<MetricType, ElemType>::operator|=(const MatType& data)
/**
* Expands this region to encompass another bound.
*/
template<typename MetricType, typename ElemType>
inline HRectBound<MetricType, ElemType>&
HRectBound<MetricType, ElemType>::operator|=(const HRectBound& other)
template<typename DistanceType, typename ElemType>
inline HRectBound<DistanceType, ElemType>&
HRectBound<DistanceType, ElemType>::operator|=(const HRectBound& other)
{
assert(other.dim == dim);
@@ -577,9 +576,9 @@ HRectBound<MetricType, ElemType>::operator|=(const HRectBound& other)
/**
* Determines if a point is within this bound.
*/
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename VecType>
inline bool HRectBound<MetricType, ElemType>::Contains(
inline bool HRectBound<DistanceType, ElemType>::Contains(
const VecType& point) const
{
for (size_t i = 0; i < point.n_elem; ++i)
@@ -594,8 +593,8 @@ inline bool HRectBound<MetricType, ElemType>::Contains(
/**
* Determines if this bound partially contains a bound.
*/
template<typename MetricType, typename ElemType>
inline bool HRectBound<MetricType, ElemType>::Contains(
template<typename DistanceType, typename ElemType>
inline bool HRectBound<DistanceType, ElemType>::Contains(
const HRectBound& bound) const
{
for (size_t i = 0; i < dim; ++i)
@@ -614,11 +613,11 @@ inline bool HRectBound<MetricType, ElemType>::Contains(
/**
* Returns the intersection of this bound and another.
*/
template<typename MetricType, typename ElemType>
inline HRectBound<MetricType, ElemType>
HRectBound<MetricType, ElemType>::operator&(const HRectBound& bound) const
template<typename DistanceType, typename ElemType>
inline HRectBound<DistanceType, ElemType>
HRectBound<DistanceType, ElemType>::operator&(const HRectBound& bound) const
{
HRectBound<MetricType, ElemType> result(dim);
HRectBound<DistanceType, ElemType> result(dim);
for (size_t k = 0; k < dim; ++k)
{
@@ -631,9 +630,9 @@ HRectBound<MetricType, ElemType>::operator&(const HRectBound& bound) const
/**
* Intersects this bound with another.
*/
template<typename MetricType, typename ElemType>
inline HRectBound<MetricType, ElemType>&
HRectBound<MetricType, ElemType>::operator&=(const HRectBound& bound)
template<typename DistanceType, typename ElemType>
inline HRectBound<DistanceType, ElemType>&
HRectBound<DistanceType, ElemType>::operator&=(const HRectBound& bound)
{
for (size_t k = 0; k < dim; ++k)
{
@@ -646,8 +645,8 @@ HRectBound<MetricType, ElemType>::operator&=(const HRectBound& bound)
/**
* Returns the volume of overlap of this bound and another.
*/
template<typename MetricType, typename ElemType>
inline ElemType HRectBound<MetricType, ElemType>::Overlap(
template<typename DistanceType, typename ElemType>
inline ElemType HRectBound<DistanceType, ElemType>::Overlap(
const HRectBound& bound) const
{
ElemType volume = 1.0;
@@ -668,31 +667,31 @@ inline ElemType HRectBound<MetricType, ElemType>::Overlap(
/**
* Returns the diameter of the hyperrectangle (that is, the longest diagonal).
*/
template<typename MetricType, typename ElemType>
inline ElemType HRectBound<MetricType, ElemType>::Diameter() const
template<typename DistanceType, typename ElemType>
inline ElemType HRectBound<DistanceType, ElemType>::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<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
template<typename Archive>
void HRectBound<MetricType, ElemType>::serialize(
void HRectBound<DistanceType, ElemType>::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
@@ -17,11 +17,11 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType>
template<typename RuleType>
class Octree<MetricType, StatisticType, MatType>::DualTreeTraverser
class Octree<DistanceType, StatisticType, MatType>::DualTreeTraverser
{
public:
/**
@@ -17,9 +17,9 @@
namespace mlpack {
template<typename MetricType, typename StatisticType, typename MatType>
template<typename DistanceType, typename StatisticType, typename MatType>
template<typename RuleType>
Octree<MetricType, StatisticType, MatType>::DualTreeTraverser<RuleType>::
Octree<DistanceType, StatisticType, MatType>::DualTreeTraverser<RuleType>::
DualTreeTraverser(RuleType& rule) :
rule(rule),
numPrunes(0),
@@ -30,9 +30,9 @@ Octree<MetricType, StatisticType, MatType>::DualTreeTraverser<RuleType>::
// Nothing to do.
}
template<typename MetricType, typename StatisticType, typename MatType>
template<typename DistanceType, typename StatisticType, typename MatType>
template<typename RuleType>
void Octree<MetricType, StatisticType, MatType>::DualTreeTraverser<RuleType>::
void Octree<DistanceType, StatisticType, MatType>::DualTreeTraverser<RuleType>::
Traverse(Octree& queryNode, Octree& referenceNode)
{
// Increment the visit counter.
+12 -8
View File
@@ -18,7 +18,7 @@
namespace mlpack {
template<typename MetricType = EuclideanDistance,
template<typename DistanceType = EuclideanDistance,
typename StatisticType = EmptyStatistic,
typename MatType = arma::mat>
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<MetricType> bound;
HRectBound<DistanceType> 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<MetricType>& Bound() const { return bound; }
const HRectBound<DistanceType>& Bound() const { return bound; }
//! Modify the bound object for this node.
HRectBound<MetricType>& Bound() { return bound; }
HRectBound<DistanceType>& 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
+90 -90
View File
@@ -19,8 +19,8 @@
namespace mlpack {
//! Construct the tree.
template<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>::Octree(const MatType& dataset,
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>::Octree(const MatType& dataset,
const size_t maxLeafSize) :
begin(0),
count(dataset.n_cols),
@@ -55,8 +55,8 @@ Octree<MetricType, StatisticType, MatType>::Octree(const MatType& dataset,
}
//! Construct the tree.
template<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>::Octree(
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>::Octree(
const MatType& dataset,
std::vector<size_t>& oldFromNew,
const size_t maxLeafSize) :
@@ -97,8 +97,8 @@ Octree<MetricType, StatisticType, MatType>::Octree(
}
//! Construct the tree.
template<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>::Octree(
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>::Octree(
const MatType& dataset,
std::vector<size_t>& oldFromNew,
std::vector<size_t>& newFromOld,
@@ -145,8 +145,8 @@ Octree<MetricType, StatisticType, MatType>::Octree(
}
//! Construct the tree.
template<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>::Octree(MatType&& dataset,
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>::Octree(MatType&& dataset,
const size_t maxLeafSize) :
begin(0),
count(dataset.n_cols),
@@ -181,8 +181,8 @@ Octree<MetricType, StatisticType, MatType>::Octree(MatType&& dataset,
}
//! Construct the tree.
template<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>::Octree(
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>::Octree(
MatType&& dataset,
std::vector<size_t>& oldFromNew,
const size_t maxLeafSize) :
@@ -223,8 +223,8 @@ Octree<MetricType, StatisticType, MatType>::Octree(
}
//! Construct the tree.
template<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>::Octree(
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>::Octree(
MatType&& dataset,
std::vector<size_t>& oldFromNew,
std::vector<size_t>& newFromOld,
@@ -271,8 +271,8 @@ Octree<MetricType, StatisticType, MatType>::Octree(
}
//! Construct a child node.
template<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>::Octree(
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>::Octree(
Octree* parent,
const size_t begin,
const size_t count,
@@ -296,7 +296,7 @@ Octree<MetricType, StatisticType, MatType>::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<MetricType, StatisticType, MatType>::Octree(
}
//! Construct a child node.
template<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>::Octree(
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>::Octree(
Octree* parent,
const size_t begin,
const size_t count,
@@ -331,7 +331,7 @@ Octree<MetricType, StatisticType, MatType>::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<MetricType, StatisticType, MatType>::Octree(
}
//! Copy the given tree.
template<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>::Octree(const Octree& other) :
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>::Octree(const Octree& other) :
begin(other.begin),
count(other.count),
bound(other.bound),
@@ -350,7 +350,7 @@ Octree<MetricType, StatisticType, MatType>::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<MetricType, StatisticType, MatType>::Octree(const Octree& other) :
}
//! Copy assignment operator: copy the given other tree.
template<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>&
Octree<MetricType, StatisticType, MatType>::
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>&
Octree<DistanceType, StatisticType, MatType>::
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<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>::Octree(Octree&& other) :
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>::Octree(Octree&& other) :
children(std::move(other.children)),
begin(other.begin),
count(other.count),
@@ -411,7 +411,7 @@ Octree<MetricType, StatisticType, MatType>::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<MetricType, StatisticType, MatType>::Octree(Octree&& other) :
}
//! Move assignment operator: take ownership of the given tree.
template<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>&
Octree<MetricType, StatisticType, MatType>::
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>&
Octree<DistanceType, StatisticType, MatType>::
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<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>::Octree() :
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>::Octree() :
begin(0),
count(0),
bound(0),
@@ -480,9 +480,9 @@ Octree<MetricType, StatisticType, MatType>::Octree() :
// Nothing to do.
}
template<typename MetricType, typename StatisticType, typename MatType>
template<typename DistanceType, typename StatisticType, typename MatType>
template<typename Archive>
Octree<MetricType, StatisticType, MatType>::Octree(
Octree<DistanceType, StatisticType, MatType>::Octree(
Archive& ar,
const typename std::enable_if_t<cereal::is_loading<Archive>()>*) :
Octree() // Create an empty tree.
@@ -491,8 +491,8 @@ Octree<MetricType, StatisticType, MatType>::Octree(
ar(CEREAL_NVP(*this));
}
template<typename MetricType, typename StatisticType, typename MatType>
Octree<MetricType, StatisticType, MatType>::~Octree()
template<typename DistanceType, typename StatisticType, typename MatType>
Octree<DistanceType, StatisticType, MatType>::~Octree()
{
// Delete the dataset if we aren't the parent.
if (!parent)
@@ -504,15 +504,15 @@ Octree<MetricType, StatisticType, MatType>::~Octree()
children.clear();
}
template<typename MetricType, typename StatisticType, typename MatType>
size_t Octree<MetricType, StatisticType, MatType>::NumChildren() const
template<typename DistanceType, typename StatisticType, typename MatType>
size_t Octree<DistanceType, StatisticType, MatType>::NumChildren() const
{
return children.size();
}
template<typename MetricType, typename StatisticType, typename MatType>
template<typename DistanceType, typename StatisticType, typename MatType>
template<typename VecType>
size_t Octree<MetricType, StatisticType, MatType>::GetNearestChild(
size_t Octree<DistanceType, StatisticType, MatType>::GetNearestChild(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>*) const
{
@@ -533,9 +533,9 @@ size_t Octree<MetricType, StatisticType, MatType>::GetNearestChild(
return bestIndex;
}
template<typename MetricType, typename StatisticType, typename MatType>
template<typename DistanceType, typename StatisticType, typename MatType>
template<typename VecType>
size_t Octree<MetricType, StatisticType, MatType>::GetFurthestChild(
size_t Octree<DistanceType, StatisticType, MatType>::GetFurthestChild(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>*) const
{
@@ -556,8 +556,8 @@ size_t Octree<MetricType, StatisticType, MatType>::GetFurthestChild(
return bestIndex;
}
template<typename MetricType, typename StatisticType, typename MatType>
size_t Octree<MetricType, StatisticType, MatType>::GetNearestChild(
template<typename DistanceType, typename StatisticType, typename MatType>
size_t Octree<DistanceType, StatisticType, MatType>::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<MetricType, StatisticType, MatType>::GetNearestChild(
return bestIndex;
}
template<typename MetricType, typename StatisticType, typename MatType>
size_t Octree<MetricType, StatisticType, MatType>::GetFurthestChild(
template<typename DistanceType, typename StatisticType, typename MatType>
size_t Octree<DistanceType, StatisticType, MatType>::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<MetricType, StatisticType, MatType>::GetFurthestChild(
return bestIndex;
}
template<typename MetricType, typename StatisticType, typename MatType>
typename Octree<MetricType, StatisticType, MatType>::ElemType
Octree<MetricType, StatisticType, MatType>::FurthestPointDistance()
template<typename DistanceType, typename StatisticType, typename MatType>
typename Octree<DistanceType, StatisticType, MatType>::ElemType
Octree<DistanceType, StatisticType, MatType>::FurthestPointDistance()
const
{
// If we are not a leaf, then this distance is 0. Otherwise, return the
@@ -608,85 +608,85 @@ Octree<MetricType, StatisticType, MatType>::FurthestPointDistance()
return (children.size() > 0) ? 0.0 : furthestDescendantDistance;
}
template<typename MetricType, typename StatisticType, typename MatType>
typename Octree<MetricType, StatisticType, MatType>::ElemType
Octree<MetricType, StatisticType, MatType>::FurthestDescendantDistance() const
template<typename DistanceType, typename StatisticType, typename MatType>
typename Octree<DistanceType, StatisticType, MatType>::ElemType
Octree<DistanceType, StatisticType, MatType>::FurthestDescendantDistance() const
{
return furthestDescendantDistance;
}
template<typename MetricType, typename StatisticType, typename MatType>
typename Octree<MetricType, StatisticType, MatType>::ElemType
Octree<MetricType, StatisticType, MatType>::MinimumBoundDistance() const
template<typename DistanceType, typename StatisticType, typename MatType>
typename Octree<DistanceType, StatisticType, MatType>::ElemType
Octree<DistanceType, StatisticType, MatType>::MinimumBoundDistance() const
{
return bound.MinWidth() / 2.0;
}
template<typename MetricType, typename StatisticType, typename MatType>
size_t Octree<MetricType, StatisticType, MatType>::NumPoints() const
template<typename DistanceType, typename StatisticType, typename MatType>
size_t Octree<DistanceType, StatisticType, MatType>::NumPoints() const
{
// We have no points unless we are a leaf;
return (children.size() > 0) ? 0 : count;
}
template<typename MetricType, typename StatisticType, typename MatType>
size_t Octree<MetricType, StatisticType, MatType>::NumDescendants() const
template<typename DistanceType, typename StatisticType, typename MatType>
size_t Octree<DistanceType, StatisticType, MatType>::NumDescendants() const
{
return count;
}
template<typename MetricType, typename StatisticType, typename MatType>
size_t Octree<MetricType, StatisticType, MatType>::Descendant(
template<typename DistanceType, typename StatisticType, typename MatType>
size_t Octree<DistanceType, StatisticType, MatType>::Descendant(
const size_t index) const
{
return begin + index;
}
template<typename MetricType, typename StatisticType, typename MatType>
size_t Octree<MetricType, StatisticType, MatType>::Point(const size_t index)
template<typename DistanceType, typename StatisticType, typename MatType>
size_t Octree<DistanceType, StatisticType, MatType>::Point(const size_t index)
const
{
return begin + index;
}
template<typename MetricType, typename StatisticType, typename MatType>
typename Octree<MetricType, StatisticType, MatType>::ElemType
Octree<MetricType, StatisticType, MatType>::MinDistance(const Octree& other)
template<typename DistanceType, typename StatisticType, typename MatType>
typename Octree<DistanceType, StatisticType, MatType>::ElemType
Octree<DistanceType, StatisticType, MatType>::MinDistance(const Octree& other)
const
{
return bound.MinDistance(other.Bound());
}
template<typename MetricType, typename StatisticType, typename MatType>
typename Octree<MetricType, StatisticType, MatType>::ElemType
Octree<MetricType, StatisticType, MatType>::MaxDistance(const Octree& other)
template<typename DistanceType, typename StatisticType, typename MatType>
typename Octree<DistanceType, StatisticType, MatType>::ElemType
Octree<DistanceType, StatisticType, MatType>::MaxDistance(const Octree& other)
const
{
return bound.MaxDistance(other.Bound());
}
template<typename MetricType, typename StatisticType, typename MatType>
RangeType<typename Octree<MetricType, StatisticType, MatType>::ElemType>
Octree<MetricType, StatisticType, MatType>::RangeDistance(const Octree& other)
template<typename DistanceType, typename StatisticType, typename MatType>
RangeType<typename Octree<DistanceType, StatisticType, MatType>::ElemType>
Octree<DistanceType, StatisticType, MatType>::RangeDistance(const Octree& other)
const
{
return bound.RangeDistance(other.Bound());
}
template<typename MetricType, typename StatisticType, typename MatType>
template<typename DistanceType, typename StatisticType, typename MatType>
template<typename VecType>
typename Octree<MetricType, StatisticType, MatType>::ElemType
Octree<MetricType, StatisticType, MatType>::MinDistance(
typename Octree<DistanceType, StatisticType, MatType>::ElemType
Octree<DistanceType, StatisticType, MatType>::MinDistance(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>*) const
{
return bound.MinDistance(point);
}
template<typename MetricType, typename StatisticType, typename MatType>
template<typename DistanceType, typename StatisticType, typename MatType>
template<typename VecType>
typename Octree<MetricType, StatisticType, MatType>::ElemType
Octree<MetricType, StatisticType, MatType>::MaxDistance(
typename Octree<DistanceType, StatisticType, MatType>::ElemType
Octree<DistanceType, StatisticType, MatType>::MaxDistance(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>*) const
{
@@ -694,10 +694,10 @@ Octree<MetricType, StatisticType, MatType>::MaxDistance(
}
template<typename MetricType, typename StatisticType, typename MatType>
template<typename DistanceType, typename StatisticType, typename MatType>
template<typename VecType>
RangeType<typename Octree<MetricType, StatisticType, MatType>::ElemType>
Octree<MetricType, StatisticType, MatType>::RangeDistance(
RangeType<typename Octree<DistanceType, StatisticType, MatType>::ElemType>
Octree<DistanceType, StatisticType, MatType>::RangeDistance(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>*) const
{
@@ -705,9 +705,9 @@ Octree<MetricType, StatisticType, MatType>::RangeDistance(
}
//! Serialize the tree.
template<typename MetricType, typename StatisticType, typename MatType>
template<typename DistanceType, typename StatisticType, typename MatType>
template<typename Archive>
void Octree<MetricType, StatisticType, MatType>::serialize(
void Octree<DistanceType, StatisticType, MatType>::serialize(
Archive& ar,
const uint32_t /* version */)
{
@@ -732,7 +732,7 @@ void Octree<MetricType, StatisticType, MatType>::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<MetricType, StatisticType, MatType>::serialize(
}
//! Split the node.
template<typename MetricType, typename StatisticType, typename MatType>
void Octree<MetricType, StatisticType, MatType>::SplitNode(
template<typename DistanceType, typename StatisticType, typename MatType>
void Octree<DistanceType, StatisticType, MatType>::SplitNode(
const arma::vec& center,
const double width,
const size_t maxLeafSize)
@@ -871,8 +871,8 @@ void Octree<MetricType, StatisticType, MatType>::SplitNode(
}
//! Split the node, and store mappings.
template<typename MetricType, typename StatisticType, typename MatType>
void Octree<MetricType, StatisticType, MatType>::SplitNode(
template<typename DistanceType, typename StatisticType, typename MatType>
void Octree<DistanceType, StatisticType, MatType>::SplitNode(
const arma::vec& center,
const double width,
std::vector<size_t>& oldFromNew,
@@ -17,9 +17,9 @@
namespace mlpack {
template<typename MetricType, typename StatisticType, typename MatType>
template<typename DistanceType, typename StatisticType, typename MatType>
template<typename RuleType>
class Octree<MetricType, StatisticType, MatType>::SingleTreeTraverser
class Octree<DistanceType, StatisticType, MatType>::SingleTreeTraverser
{
public:
/**
@@ -17,9 +17,9 @@
namespace mlpack {
template<typename MetricType, typename StatisticType, typename MatType>
template<typename DistanceType, typename StatisticType, typename MatType>
template<typename RuleType>
Octree<MetricType, StatisticType, MatType>::SingleTreeTraverser<RuleType>::
Octree<DistanceType, StatisticType, MatType>::SingleTreeTraverser<RuleType>::
SingleTreeTraverser(RuleType& rule) :
rule(rule),
numPrunes(0)
@@ -27,9 +27,10 @@ Octree<MetricType, StatisticType, MatType>::SingleTreeTraverser<RuleType>::
// Nothing to do.
}
template<typename MetricType, typename StatisticType, typename MatType>
template<typename DistanceType, typename StatisticType, typename MatType>
template<typename RuleType>
void Octree<MetricType, StatisticType, MatType>::SingleTreeTraverser<RuleType>::
void
Octree<DistanceType, StatisticType, MatType>::SingleTreeTraverser<RuleType>::
Traverse(const size_t queryIndex, Octree& referenceNode)
{
// If we are a leaf, run the base cases.
+2 -2
View File
@@ -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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType>
class TreeTraits<Octree<MetricType, StatisticType, MatType>>
class TreeTraits<Octree<DistanceType, StatisticType, MatType>>
{
public:
/**
@@ -20,14 +20,14 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
template<typename RuleType>
class RectangleTree<MetricType, StatisticType, MatType, SplitType,
class RectangleTree<DistanceType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>::DualTreeTraverser
{
public:
@@ -21,14 +21,14 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
template<typename RuleType>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
DualTreeTraverser<RuleType>::DualTreeTraverser(RuleType& rule) :
rule(rule),
@@ -38,14 +38,14 @@ DualTreeTraverser<RuleType>::DualTreeTraverser(RuleType& rule) :
numBaseCases(0)
{ /* Nothing to do */ }
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
template<typename RuleType>
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
void RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
DualTreeTraverser<RuleType>::Traverse(RectangleTree& queryNode,
RectangleTree& referenceNode)
@@ -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);
}
@@ -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<typename MetricType = EuclideanDistance,
template<typename DistanceType = EuclideanDistance,
typename StatisticType = EmptyStatistic,
typename MatType = arma::mat,
typename SplitType = RTreeSplit,
@@ -52,9 +52,9 @@ template<typename MetricType = EuclideanDistance,
NoAuxiliaryInformation>
class RectangleTree
{
// The metric *must* be the euclidean distance.
static_assert(std::is_same<MetricType, EuclideanDistance>::value,
"RectangleTree: MetricType must be EuclideanDistance.");
// The distance metric *must* be the euclidean distance.
static_assert(std::is_same<DistanceType, EuclideanDistance>::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<MetricType>& Bound() const { return bound; }
const HRectBound<DistanceType>& Bound() const { return bound; }
//! Modify the bound object for this node.
HRectBound<MetricType>& Bound() { return bound; }
HRectBound<DistanceType>& 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<MatType&>(*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<MetricType>& changedBound);
bool ShrinkBoundForBound(const HRectBound<DistanceType>& changedBound);
/**
* Make an exact copy of this node, pointers and everything.
@@ -20,13 +20,13 @@
namespace mlpack {
// Build the statistics, bottom-up.
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
void RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
BuildStatistics(RectangleTree* node)
{
@@ -38,13 +38,13 @@ BuildStatistics(RectangleTree* node)
node->Stat() = StatisticType(*node);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
RectangleTree(const MatType& data,
const size_t maxLeafSize,
@@ -79,13 +79,13 @@ RectangleTree(const MatType& data,
BuildStatistics(this);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
RectangleTree(MatType&& data,
const size_t maxLeafSize,
@@ -120,16 +120,16 @@ RectangleTree(MatType&& data,
BuildStatistics(this);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
RectangleTree(
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>*
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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
RectangleTree(
const RectangleTree& other,
@@ -205,13 +205,13 @@ RectangleTree(
/**
* Move constructor.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
RectangleTree(RectangleTree&& other) :
maxNumChildren(other.MaxNumChildren()),
@@ -264,15 +264,15 @@ RectangleTree(RectangleTree&& other) :
/**
* Copy assignment operator: copy the given other tree.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>&
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
operator=(const RectangleTree& other)
{
@@ -317,15 +317,15 @@ operator=(const RectangleTree& other)
/**
* Move assignment operator: take ownership of the given tree.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>&
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
operator=(RectangleTree&& other)
{
@@ -379,14 +379,14 @@ operator=(RectangleTree&& other)
/**
* Construct the tree from a cereal archive.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
template<typename Archive>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
~RectangleTree()
{
@@ -423,13 +423,13 @@ RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
* Deletes this node but leaves the children untouched. Needed for when we
* split nodes and remove nodes (inserting and deleting points).
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
void RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
SoftDelete()
{
@@ -445,13 +445,13 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
/**
* Nullify the auxiliary information.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
void RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
NullifyData()
{
@@ -462,13 +462,13 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
* Recurse through the tree and insert the point at the leaf node chosen
* by the heuristic.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
void RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
InsertPoint(const size_t point)
{
@@ -499,13 +499,13 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
/**
* Inserts a point into the tree, tracking which levels have been inserted into.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
void RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
InsertPoint(const size_t point, std::vector<bool>& relevels)
{
@@ -539,13 +539,13 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
* @param relevels The levels that have been reinserted to on this top level
* insertion.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
void RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
InsertNode(RectangleTree* node,
const size_t level,
@@ -575,13 +575,13 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
* Recurse through the tree to remove the point. Once we find the point, we
* shrink the rectangles if necessary.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
bool RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
bool RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
DeletePoint(const size_t point)
{
@@ -627,13 +627,13 @@ bool RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
* Recurse through the tree to remove the point. Once we find the point, we
* shrink the rectangles if necessary.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
bool RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
bool RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
DeletePoint(const size_t point, std::vector<bool>& relevels)
{
@@ -672,13 +672,13 @@ bool RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
* Recurse through the tree to remove the node. Once we find the node, we
* shrink the rectangles if necessary.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
bool RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
bool RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
RemoveNode(const RectangleTree* node, std::vector<bool>& relevels)
{
@@ -712,13 +712,13 @@ bool RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
return false;
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
size_t RectangleTree<MetricType, StatisticType, MatType, SplitType,
size_t RectangleTree<DistanceType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>::TreeSize() const
{
int n = 0;
@@ -728,13 +728,13 @@ size_t RectangleTree<MetricType, StatisticType, MatType, SplitType,
return n + 1; // Add one for this node.
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
size_t RectangleTree<MetricType, StatisticType, MatType, SplitType,
size_t RectangleTree<DistanceType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>::TreeDepth() const
{
int n = 1;
@@ -749,13 +749,13 @@ size_t RectangleTree<MetricType, StatisticType, MatType, SplitType,
return n;
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
inline bool RectangleTree<MetricType, StatisticType, MatType, SplitType,
inline bool RectangleTree<DistanceType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>::IsLeaf() const
{
return (numChildren == 0);
@@ -765,14 +765,14 @@ inline bool RectangleTree<MetricType, StatisticType, MatType, SplitType,
* 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
template<typename VecType>
size_t RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
size_t RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::GetNearestChild(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>*)
@@ -798,14 +798,14 @@ size_t RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
* 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
template<typename VecType>
size_t RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
size_t RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::GetFurthestChild(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>*)
@@ -831,13 +831,13 @@ size_t RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
* 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
size_t RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
size_t RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::GetNearestChild(const RectangleTree& queryNode)
{
if (IsLeaf())
@@ -861,13 +861,13 @@ size_t RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
* 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
size_t RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
size_t RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::GetFurthestChild(const RectangleTree& queryNode)
{
if (IsLeaf())
@@ -891,16 +891,16 @@ size_t RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
* Return a bound on the furthest point in the node form the centroid.
* This returns 0 unless the node is a leaf.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
inline
typename RectangleTree<MetricType, StatisticType, MatType, SplitType,
typename RectangleTree<DistanceType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>::ElemType
RectangleTree<MetricType, StatisticType, MatType, SplitType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>::FurthestPointDistance() const
{
if (!IsLeaf())
@@ -917,16 +917,16 @@ RectangleTree<MetricType, StatisticType, MatType, SplitType,
* furthest descendant distance may be less than what this method returns (but
* it will never be greater than this).
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
inline
typename RectangleTree<MetricType, StatisticType, MatType, SplitType,
typename RectangleTree<DistanceType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>::ElemType
RectangleTree<MetricType, StatisticType, MatType, SplitType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>::FurthestDescendantDistance() const
{
// Return the distance from the centroid to a corner of the bound.
@@ -937,13 +937,13 @@ RectangleTree<MetricType, StatisticType, MatType, SplitType,
* Return the number of points contained in this node. Zero if it is a non-leaf
* node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
inline size_t RectangleTree<MetricType, StatisticType, MatType, SplitType,
inline size_t RectangleTree<DistanceType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>::NumPoints() const
{
if (numChildren != 0) // This is not a leaf node.
@@ -955,13 +955,13 @@ inline size_t RectangleTree<MetricType, StatisticType, MatType, SplitType,
/**
* Return the number of descendants under or in this node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
inline size_t RectangleTree<MetricType, StatisticType, MatType, SplitType,
inline size_t RectangleTree<DistanceType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>::NumDescendants() const
{
return numDescendants;
@@ -970,13 +970,13 @@ inline size_t RectangleTree<MetricType, StatisticType, MatType, SplitType,
/**
* Return the index of a particular descendant contained in this node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
inline size_t RectangleTree<MetricType, StatisticType, MatType, SplitType,
inline size_t RectangleTree<DistanceType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>::Descendant(const size_t index) const
{
// I think this may be inefficient...
@@ -1004,13 +1004,13 @@ inline size_t RectangleTree<MetricType, StatisticType, MatType, SplitType,
* Split the tree. This calls the SplitType code to split a node. This method
* should only be called on a leaf node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
void RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
SplitNode(std::vector<bool>& relevels)
{
@@ -1036,13 +1036,13 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
}
//! Default constructor for cereal.
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
void RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
CondenseTree(const arma::vec& point,
std::vector<bool>& relevels,
@@ -1249,13 +1249,13 @@ void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
/**
* Shrink the bound so it fits tightly after the removal of this point.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
bool RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
bool RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
ShrinkBoundForPoint(const arma::vec& point)
{
@@ -1347,15 +1347,15 @@ bool RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
/**
* Shrink the bound so it fits tightly after the removal of another bound.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
bool RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
bool RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
ShrinkBoundForBound(const HRectBound<MetricType>& /* b */)
ShrinkBoundForBound(const HRectBound<DistanceType>& /* b */)
{
// Using the sum is safe since none of the dimensions can increase.
ElemType sum = 0;
@@ -1383,14 +1383,14 @@ bool RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
/**
* Serialize the tree.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
template<typename Archive>
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
void RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::serialize(
Archive& ar,
const uint32_t /* version */)
@@ -20,14 +20,14 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
template<typename RuleType>
class RectangleTree<MetricType, StatisticType, MatType, SplitType,
class RectangleTree<DistanceType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>::SingleTreeTraverser
{
public:
@@ -21,28 +21,28 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
template<typename RuleType>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
SingleTreeTraverser<RuleType>::SingleTreeTraverser(RuleType& rule) :
rule(rule),
numPrunes(0)
{ /* Nothing to do */ }
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
template<typename RuleType>
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
void RectangleTree<DistanceType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
SingleTreeTraverser<RuleType>::Traverse(
const size_t queryIndex,
@@ -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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
class TreeTraits<RectangleTree<MetricType, StatisticType, MatType, SplitType,
class TreeTraits<RectangleTree<DistanceType, StatisticType, MatType, SplitType,
DescentType, AuxiliaryInformationType>>
{
public:
@@ -75,14 +75,14 @@ class TreeTraits<RectangleTree<MetricType, StatisticType, MatType, SplitType,
* Since the R+/R++ tree can not have overlapping children, we should define
* traits for the R+/R++ tree.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
typename SplitPolicyType,
template<typename> class SweepType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
class TreeTraits<RectangleTree<MetricType,
class TreeTraits<RectangleTree<DistanceType,
StatisticType,
MatType,
RPlusTreeSplit<SplitPolicyType,
+12 -12
View File
@@ -37,8 +37,8 @@ namespace mlpack {
*
* @see @ref trees, RStarTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using RTree = RectangleTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using RTree = RectangleTree<DistanceType,
StatisticType,
MatType,
RTreeSplit,
@@ -65,8 +65,8 @@ using RTree = RectangleTree<MetricType,
*
* @see @ref trees, RTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using RStarTree = RectangleTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using RStarTree = RectangleTree<DistanceType,
StatisticType,
MatType,
RStarTreeSplit,
@@ -91,8 +91,8 @@ using RStarTree = RectangleTree<MetricType,
*
* @see @ref trees, RTree, RStarTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using XTree = RectangleTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using XTree = RectangleTree<DistanceType,
StatisticType,
MatType,
XTreeSplit,
@@ -126,8 +126,8 @@ template<typename TreeType>
using DiscreteHilbertRTreeAuxiliaryInformation =
HilbertRTreeAuxiliaryInformation<TreeType, DiscreteHilbertValue>;
template<typename MetricType, typename StatisticType, typename MatType>
using HilbertRTree = RectangleTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using HilbertRTree = RectangleTree<DistanceType,
StatisticType,
MatType,
HilbertRTreeSplit<2>,
@@ -157,8 +157,8 @@ using HilbertRTree = RectangleTree<MetricType,
*
* @see @ref trees, RTree, RTree, RPlusTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using RPlusTree = RectangleTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using RPlusTree = RectangleTree<DistanceType,
StatisticType,
MatType,
RPlusTreeSplit<RPlusTreeSplitPolicy,
@@ -186,8 +186,8 @@ using RPlusTree = RectangleTree<MetricType,
*
* @see @ref trees, RTree, RTree, RPlusTree, RPlusPlusTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using RPlusPlusTree = RectangleTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using RPlusPlusTree = RectangleTree<DistanceType,
StatisticType,
MatType,
RPlusTreeSplit<RPlusPlusTreeSplitPolicy,
@@ -139,15 +139,15 @@ class HyperplaneBase
/**
* AxisOrthogonalHyperplane represents a hyperplane orthogonal to an axis.
*/
template<typename MetricType>
using AxisOrthogonalHyperplane = HyperplaneBase<HRectBound<MetricType>,
template<typename DistanceType>
using AxisOrthogonalHyperplane = HyperplaneBase<HRectBound<DistanceType>,
AxisParallelProjVector>;
/**
* Hyperplane represents a general hyperplane (not necessarily axis-orthogonal).
*/
template<typename MetricType>
using Hyperplane = HyperplaneBase<BallBound<MetricType>, ProjVector>;
template<typename DistanceType>
using Hyperplane = HyperplaneBase<BallBound<DistanceType>, ProjVector>;
} // namespace mlpack
@@ -18,7 +18,7 @@
namespace mlpack {
template<typename MetricType, typename MatType>
template<typename DistanceType, typename MatType>
class MeanSpaceSplit
{
public:
@@ -18,9 +18,9 @@
namespace mlpack {
template<typename MetricType, typename MatType>
template<typename DistanceType, typename MatType>
template<typename HyperplaneType>
bool MeanSpaceSplit<MetricType, MatType>::SplitSpace(
bool MeanSpaceSplit<DistanceType, MatType>::SplitSpace(
const typename HyperplaneType::BoundType& bound,
const MatType& data,
const arma::Col<size_t>& points,
@@ -29,7 +29,7 @@ bool MeanSpaceSplit<MetricType, MatType>::SplitSpace(
typename HyperplaneType::ProjVectorType projVector;
double midValue;
if (!SpaceSplit<MetricType, MatType>::GetProjVector(bound, data, points,
if (!SpaceSplit<DistanceType, MatType>::GetProjVector(bound, data, points,
projVector, midValue))
return false;
@@ -18,7 +18,7 @@
namespace mlpack {
template<typename MetricType, typename MatType>
template<typename DistanceType, typename MatType>
class MidpointSpaceSplit
{
public:
@@ -18,9 +18,9 @@
namespace mlpack {
template<typename MetricType, typename MatType>
template<typename DistanceType, typename MatType>
template<typename HyperplaneType>
bool MidpointSpaceSplit<MetricType, MatType>::SplitSpace(
bool MidpointSpaceSplit<DistanceType, MatType>::SplitSpace(
const typename HyperplaneType::BoundType& bound,
const MatType& data,
const arma::Col<size_t>& points,
@@ -29,7 +29,7 @@ bool MidpointSpaceSplit<MetricType, MatType>::SplitSpace(
typename HyperplaneType::ProjVectorType projVector;
double midValue;
if (!SpaceSplit<MetricType, MatType>::GetProjVector(bound, data, points,
if (!SpaceSplit<DistanceType, MatType>::GetProjVector(bound, data, points,
projVector, midValue))
return false;
@@ -54,9 +54,9 @@ class AxisParallelProjVector
* @param bound Bound to be projected.
* @return Range of projected values.
*/
template<typename MetricType, typename ElemType>
template<typename DistanceType, typename ElemType>
RangeType<ElemType> Project(
const HRectBound<MetricType, ElemType>& bound) const
const HRectBound<DistanceType, ElemType>& bound) const
{
return bound[dim];
}
@@ -67,9 +67,9 @@ class AxisParallelProjVector
* @param bound Bound to be projected.
* @return Range of projected values.
*/
template<typename MetricType, typename VecType>
template<typename DistanceType, typename VecType>
RangeType<typename VecType::elem_type> Project(
const BallBound<MetricType, VecType>& bound) const
const BallBound<DistanceType, VecType>& bound) const
{
return bound[dim];
}
@@ -128,9 +128,9 @@ class ProjVector
* @param bound Bound to be projected.
* @return Range of projected values.
*/
template<typename MetricType, typename VecType>
template<typename DistanceType, typename VecType>
RangeType<typename VecType::elem_type> Project(
const BallBound<MetricType, VecType>& bound) const
const BallBound<DistanceType, VecType>& bound) const
{
typedef typename VecType::elem_type ElemType;
const double center = Project(bound.Center());
@@ -18,7 +18,7 @@
namespace mlpack {
template<typename MetricType, typename MatType>
template<typename DistanceType, typename MatType>
class SpaceSplit
{
public:
@@ -35,7 +35,7 @@ class SpaceSplit
* @return Flag to determine if it is possible.
*/
static bool GetProjVector(
const HRectBound<MetricType>& bound,
const HRectBound<DistanceType>& bound,
const MatType& data,
const arma::Col<size_t>& points,
AxisParallelProjVector& projVector,
@@ -17,9 +17,9 @@
namespace mlpack {
template<typename MetricType, typename MatType>
bool SpaceSplit<MetricType, MatType>::GetProjVector(
const HRectBound<MetricType>& bound,
template<typename DistanceType, typename MatType>
bool SpaceSplit<DistanceType, MatType>::GetProjVector(
const HRectBound<DistanceType>& bound,
const MatType& data,
const arma::Col<size_t>& /* points */,
AxisParallelProjVector& projVector,
@@ -50,25 +50,25 @@ bool SpaceSplit<MetricType, MatType>::GetProjVector(
return true;
}
template<typename MetricType, typename MatType>
template<typename DistanceType, typename MatType>
template<typename BoundType>
bool SpaceSplit<MetricType, MatType>::GetProjVector(
bool SpaceSplit<DistanceType, MatType>::GetProjVector(
const BoundType& /* bound */,
const MatType& data,
const arma::Col<size_t>& 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<MetricType, MatType>::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;
@@ -23,15 +23,15 @@ struct IsSpillTree
};
// Specialization for SpillTree.
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType>
template<typename HyperplaneDistanceType>
class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
struct IsSpillTree<SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
SplitType>>
struct IsSpillTree<SpillTree<DistanceType, StatisticType, MatType,
HyperplaneType, SplitType>>
{
static const bool value = true;
};
@@ -24,15 +24,15 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
template<typename RuleType, bool Defeatist>
class SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillDualTreeTraverser
class SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::SpillDualTreeTraverser
{
public:
/**
@@ -20,14 +20,14 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
template<typename RuleType, bool Defeatist>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillDualTreeTraverser<RuleType, Defeatist>::SpillDualTreeTraverser(
RuleType& rule) :
rule(rule),
@@ -37,18 +37,19 @@ SpillDualTreeTraverser<RuleType, Defeatist>::SpillDualTreeTraverser(
numBaseCases(0)
{ /* Nothing to do. */ }
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
template<typename RuleType, bool Defeatist>
void SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
void
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillDualTreeTraverser<RuleType, Defeatist>::Traverse(
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>&
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>&
queryNode,
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>&
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>&
referenceNode,
const bool bruteForce)
{
@@ -23,15 +23,15 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
template<typename RuleType, bool Defeatist>
class SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillSingleTreeTraverser
class SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::SpillSingleTreeTraverser
{
public:
/**
@@ -20,31 +20,32 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
template<typename RuleType, bool Defeatist>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillSingleTreeTraverser<RuleType, Defeatist>::SpillSingleTreeTraverser(
RuleType& rule) :
rule(rule),
numPrunes(0)
{ /* Nothing to do. */ }
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
template<typename RuleType, bool Defeatist>
void SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
void
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillSingleTreeTraverser<RuleType, Defeatist>::Traverse(
const size_t queryIndex,
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>&
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>&
referenceNode,
const bool bruteForce)
{
+13 -9
View File
@@ -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<typename MetricType,
template<typename DistanceType,
typename StatisticType = EmptyStatistic,
typename MatType = arma::mat,
template<typename HyperplaneMetricType>
template<typename HyperplaneDistanceType>
class HyperplaneType = AxisOrthogonalHyperplane,
template<typename SplitMetricType, typename SplitMatType>
template<typename SplitDistanceType, typename SplitMatType>
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<MetricType>::BoundType BoundType;
typedef typename HyperplaneType<DistanceType>::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<MetricType> hyperplane;
HyperplaneType<DistanceType> 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<MetricType>& Hyperplane() const { return hyperplane; }
const HyperplaneType<DistanceType>& 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;
@@ -18,13 +18,13 @@
namespace mlpack {
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree(
const MatType& data,
const double tau,
@@ -55,13 +55,13 @@ SpillTree(
stat = StatisticType(*this);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree(
MatType&& data,
const double tau,
@@ -92,13 +92,13 @@ SpillTree(
stat = StatisticType(*this);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree(
SpillTree* parent,
arma::Col<size_t>& 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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>&
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>&
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
operator=(const SpillTree& other)
{
if (this == &other)
@@ -276,13 +276,13 @@ operator=(const SpillTree& other)
/**
* Move constructor.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>&
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>&
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
operator=(SpillTree&& other)
{
if (this == &other)
@@ -381,14 +381,14 @@ operator=(SpillTree&& other)
/**
* Initialize the tree from an archive.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
template<typename Archive>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree(
Archive& ar,
const typename std::enable_if_t<cereal::is_loading<Archive>()>*) :
@@ -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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
~SpillTree()
{
delete left;
@@ -422,13 +422,13 @@ SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
delete dataset;
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
inline bool SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
inline bool SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::IsLeaf() const
{
return !left;
@@ -437,13 +437,13 @@ inline bool SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
/**
* Returns the number of children in this node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
inline size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
inline size_t SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::NumChildren() const
{
if (left && right)
@@ -460,14 +460,14 @@ inline size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
* returned is not necessarily the nearest). If this is a leaf node, it will
* return NumChildren() (invalid index).
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
template<typename VecType>
size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
size_t SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::GetNearestChild(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>*)
@@ -486,14 +486,14 @@ size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
* returned is not necessarily the furthest). If this is a leaf node, it will
* return NumChildren() (invalid index).
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
template<typename VecType>
size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
size_t SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::GetFurthestChild(
const VecType& point,
typename std::enable_if_t<IsVector<VecType>::value>*)
@@ -512,13 +512,13 @@ size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
* returned is not necessarily the nearest). If it can't decide it will
* return NumChildren() (invalid index).
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
size_t SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::GetNearestChild(const SpillTree& queryNode)
{
if (IsLeaf() || !left || !right)
@@ -538,13 +538,13 @@ size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
* returned is not necessarily the furthest). If this is a leaf node, it will
* return NumChildren() (invalid index).
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
size_t SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::GetFurthestChild(const SpillTree& queryNode)
{
if (IsLeaf() || !left || !right)
@@ -562,15 +562,15 @@ size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
* Return a bound on the furthest point in the node from the center. This
* returns 0 unless the node is a leaf.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
inline typename SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
inline typename SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::ElemType
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
FurthestPointDistance() const
{
if (!IsLeaf())
@@ -587,30 +587,30 @@ SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
* furthest descendant distance may be less than what this method returns (but
* it will never be greater than this).
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
inline typename SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
inline typename SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::ElemType
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
FurthestDescendantDistance() const
{
return furthestDescendantDistance;
}
//! Return the minimum distance from the center to any bound edge.
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
inline typename SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
inline typename SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::ElemType
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
MinimumBoundDistance() const
{
return bound.MinWidth() / 2.0;
@@ -619,14 +619,14 @@ SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
/**
* Return the specified child.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
inline SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>&
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
inline SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>&
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
Child(const size_t child) const
{
if (child == 0)
@@ -638,13 +638,13 @@ SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
/**
* Return the number of points contained in this node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
inline size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
inline size_t SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::NumPoints() const
{
if (IsLeaf())
@@ -655,13 +655,13 @@ inline size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
/**
* Return the number of descendants contained in the node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
inline size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
inline size_t SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::NumDescendants() const
{
return count;
@@ -670,13 +670,13 @@ inline size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
/**
* Return the index of a particular descendant contained in this node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
inline size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
inline size_t SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::Descendant(const size_t index) const
{
if (IsLeaf() || overlappingNode)
@@ -694,13 +694,13 @@ inline size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
/**
* Return the index of a particular point contained in this node.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
inline size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
inline size_t SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>::Point(const size_t index) const
{
if (IsLeaf())
@@ -709,13 +709,13 @@ inline size_t SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
return (size_t() - 1);
}
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
void SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
void SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
SplitNode(arma::Col<size_t>& points,
const size_t maxLeafSize,
const double tau,
@@ -736,7 +736,7 @@ void SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
return; // We can't split this.
}
const bool split = SplitType<MetricType, MatType>::SplitSpace(bound,
const bool split = SplitType<DistanceType, MatType>::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<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
bool SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
bool SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
SplitPoints(const double tau,
const double rho,
const arma::Col<size_t>& points,
@@ -869,13 +869,13 @@ bool SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
}
// Default constructor (private), for cereal.
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
SpillTree() :
left(NULL),
right(NULL),
@@ -895,14 +895,14 @@ SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
/**
* Serialize the tree.
*/
template<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
template<typename Archive>
void SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
void SpillTree<DistanceType, StatisticType, MatType, HyperplaneType, SplitType>::
serialize(Archive& ar, const uint32_t /* version */)
{
// If we're loading, and we have children, they need to be deleted.
+4 -4
View File
@@ -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<typename MetricType,
template<typename DistanceType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
template<typename HyperplaneDistanceType> class HyperplaneType,
template<typename SplitDistanceType, typename SplitMatType>
class SplitType>
class TreeTraits<SpillTree<MetricType, StatisticType, MatType, HyperplaneType,
class TreeTraits<SpillTree<DistanceType, StatisticType, MatType, HyperplaneType,
SplitType>>
{
public:
+8 -8
View File
@@ -53,8 +53,8 @@ namespace mlpack {
*
* @see @ref trees, SpillTree, MeanSPTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using SPTree = SpillTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using SPTree = SpillTree<DistanceType,
StatisticType,
MatType,
AxisOrthogonalHyperplane,
@@ -71,8 +71,8 @@ using SPTree = SpillTree<MetricType,
*
* @see @ref trees, SpillTree, SPTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using MeanSPTree = SpillTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using MeanSPTree = SpillTree<DistanceType,
StatisticType,
MatType,
AxisOrthogonalHyperplane,
@@ -91,8 +91,8 @@ using MeanSPTree = SpillTree<MetricType,
*
* @see @ref trees, SpillTree, SPTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using NonOrtSPTree = SpillTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using NonOrtSPTree = SpillTree<DistanceType,
StatisticType,
MatType,
Hyperplane,
@@ -110,8 +110,8 @@ using NonOrtSPTree = SpillTree<MetricType,
*
* @see @ref trees, SpillTree, MeanSPTree, NonOrtSPTree
*/
template<typename MetricType, typename StatisticType, typename MatType>
using NonOrtMeanSPTree = SpillTree<MetricType,
template<typename DistanceType, typename StatisticType, typename MatType>
using NonOrtMeanSPTree = SpillTree<DistanceType,
StatisticType,
MatType,
Hyperplane,

Some files were not shown because too many files have changed in this diff Show More