Merge remote-tracking branch 'origin/master' into reduce-pca-test-size
This commit is contained in:
@@ -5,10 +5,10 @@
|
||||
# available on your system in order to find the BLAS library. If OpenBLAS will
|
||||
# be compiled, the OPENBLAS_TARGET variable must be set. This can be done
|
||||
# by, e.g., setting BOARD_NAME (which will set OPENBLAS_TARGET in
|
||||
# `board/flags-config.cmake`).
|
||||
# `flags-config.cmake`).
|
||||
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
include(board/flags-config.cmake)
|
||||
include(CMake/crosscompile-arch-config.cmake)
|
||||
if (NOT CMAKE_SYSROOT AND (NOT TOOLCHAIN_PREFIX))
|
||||
message(FATAL_ERROR "Neither CMAKE_SYSROOT nor TOOLCHAIN_PREFIX are set; please set both of them and try again.")
|
||||
elseif(NOT CMAKE_SYSROOT)
|
||||
|
||||
@@ -56,7 +56,7 @@ elseif(BOARD MATCHES "RPI3" OR BOARD MATCHES "CORTEXA53")
|
||||
set(OPENBLAS_TARGET "CORTEXA53")
|
||||
set(OPENBLAS_BINARY "64")
|
||||
elseif(BOARD MATCHES "RPI4" OR BOARD MATCHES "CORTEXA72")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=cortex-a72 -ftree-vectorize")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv8.2-a+crypto+fp16+rcpc+dotprod -fasynchronous-unwind-tables")
|
||||
set(OPENBLAS_TARGET "CORTEXA72")
|
||||
set(OPENBLAS_BINARY "64")
|
||||
elseif(BOARD MATCHES "JETSONAGX" OR BOARD MATCHES "CORTEXA76")
|
||||
@@ -1,14 +1,14 @@
|
||||
## This file handles cross-compilation configurations for aarch64,
|
||||
## known as arm64. The objective of this file is to find and assign
|
||||
## cross-compiler and the entire toolchain.
|
||||
## This file handles cross-compilation configurations for any architecture.
|
||||
## The objective of this file is to find and assign cross-compiler and the
|
||||
## entire toolchain.
|
||||
##
|
||||
## This configuration works best with the buildroot toolchain. When using this
|
||||
## file, be sure to set the TOOLCHAIN_PREFIX and CMAKE_SYSROOT variables,
|
||||
## preferably via the CMake configuration command (e.g. `-DCMAKE_SYSROOT=<...>`).
|
||||
##
|
||||
## Currently, we recommend using buildroot toolchain for
|
||||
## cross-compilation. Here is the link to download the toolchains:
|
||||
## https://toolchains.bootlin.com/
|
||||
## You can use any toochain to produce the cross compiled binaries. However,
|
||||
## we recommend using buildroot toolchain for cross-compilation. Here is the
|
||||
## link to download the toolchains: https://toolchains.bootlin.com/
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSROOT)
|
||||
@@ -28,7 +28,7 @@ types cannot be used.
|
||||
easily defined as below:
|
||||
|
||||
```c++
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
```
|
||||
|
||||
and otherwise a template parameter with the name `ElemType` can be used. It is
|
||||
|
||||
@@ -202,7 +202,7 @@ class ExampleTree
|
||||
public:
|
||||
// This is the element type held by the matrix.
|
||||
// It will generally either be `double`, or `float`.
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
|
||||
//////////////////////
|
||||
//// Constructors ////
|
||||
@@ -1270,6 +1270,8 @@ TreeType policy API:
|
||||
- [`MeanSplitKDTree`](../user/core/trees/mean_split_kdtree.md)
|
||||
- [`BallTree`](../user/core/trees/ball_tree.md)
|
||||
- [`MeanSplitBallTree`](../user/core/trees/mean_split_ball_tree.md)
|
||||
- [`RPTree`](../user/core/trees/rp_tree.md)
|
||||
- [`MaxRPTree`](../user/core/trees/max_rp_tree.md)
|
||||
- [`UBTree`](../user/core/trees/ub_tree.md)
|
||||
- `RTree`
|
||||
- `RStarTree`
|
||||
|
||||
@@ -113,9 +113,9 @@ cross-compilation toolchain.
|
||||
cmake \
|
||||
-DBUILD_TESTS=ON \
|
||||
-DBOARD_NAME="RPI2" \
|
||||
-DCMAKE_CROSSCOMPILE=ON \
|
||||
-DCMAKE_TOOLCHAIN_FILE=../board/crosscompile-toolchain.cmake \
|
||||
-DTOOLCHAIN_PREFIX=/path/to/bootlin/toolchain/armv7-eabihf--glibc--stable-2023.08-1/bin/arm-buildroot-linux-gnueabihf- \
|
||||
-DCMAKE_CROSSCOMPILING=ON \
|
||||
-DCMAKE_TOOLCHAIN_FILE=../CMake/crosscompile-toolchain.cmake \
|
||||
-DTOOLCHAIN_PREFIX=/path/to/bootlin/toolchain/armv7-eabihf--glibc--stable-2024.02-1/bin/arm-buildroot-linux-gnueabihf- \
|
||||
-DCMAKE_SYSROOT=/path/to/bootlin/toolchain/armv7-eabihf--glibc--stable-2024.02-1/arm-buildroot-linux-gnueabihf/sysroot \
|
||||
../
|
||||
```
|
||||
|
||||
+9
-4
@@ -102,13 +102,18 @@ when the sidebar is built for each page.
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="LINKROOTuser/core/trees/ub_tree.html">
|
||||
<code>UBTree</code>
|
||||
<a href="LINKROOTuser/core/trees/rp_tree.html">
|
||||
<code>RPTree</code>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="LINKROOTuser/core/trees/binary_space_tree.html">
|
||||
<code>BinarySpaceTree</code>
|
||||
<a href="LINKROOTuser/core/trees/max_rp_tree.html">
|
||||
<code>MaxRPTree</code>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="LINKROOTuser/core/trees/ub_tree.html">
|
||||
<code>UBTree</code>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
@@ -386,8 +386,9 @@ IPMetric<PolynomialKernel> metric(pk);
|
||||
// the custom base of 1.5 (default is 1.3). We have to be sure to use the right
|
||||
// type here -- FastMKS needs the FastMKSStat object as the tree's
|
||||
// StatisticType.
|
||||
typedef CoverTree<IPMetric<PolynomialKernel>, FirstPointIsRoot, FastMKSStat>
|
||||
TreeType; // Convenience typedef.
|
||||
// Convenience typedef.
|
||||
using TreeType =
|
||||
CoverTree<IPMetric<PolynomialKernel>, FirstPointIsRoot, FastMKSStat>;
|
||||
TreeType* tree = new TreeType(data, metric, 1.5);
|
||||
|
||||
// Now initialize FastMKS with that statistic. We don't need to specify the
|
||||
@@ -455,7 +456,7 @@ extern arma::mat data;
|
||||
|
||||
// The custom tree type. We'll assume that the first template parameter is the
|
||||
// statistic type.
|
||||
typedef CustomTree<FastMKSStat> TreeType;
|
||||
using TreeType = CustomTree<FastMKSStat>;
|
||||
|
||||
// The FastMKS constructor will create the tree.
|
||||
FastMKS<LinearKernel, arma::mat, TreeType> f(data);
|
||||
|
||||
@@ -213,7 +213,7 @@ The `KNN` class is, specifically, a typedef of the more extensible
|
||||
distance.
|
||||
|
||||
```c++
|
||||
typedef NeighborSearch<NearestNeighborSort, EuclideanDistance> KNN;
|
||||
using KNN = NeighborSearch<NearestNeighborSort, EuclideanDistance>;
|
||||
```
|
||||
|
||||
Using the `KNN` class is particularly simple; first, the object must be
|
||||
|
||||
@@ -447,7 +447,10 @@ std::cout << "Trigamma(1.0): " << t2 << "." << std::endl;
|
||||
## `RandVector()`
|
||||
|
||||
* `RandVector(v)` generates a random vector on the unit sphere (i.e. with an
|
||||
L2-norm of 1) and stores it in `v` (an `arma::vec`).
|
||||
L2-norm of 1) and stores it in the vector `v`.
|
||||
|
||||
* `v` should be a dense floating-point Armadillo vector (e.g. `arma::vec` or
|
||||
`arma::fvec`).
|
||||
|
||||
* The [Box-Muller transform](https://en.wikipedia.org/wiki/Box-Muller_transform)
|
||||
is used to generate the vector.
|
||||
|
||||
@@ -7,9 +7,11 @@ different trees. The following tree types are available in mlpack:
|
||||
|
||||
* [`KDTree`](trees/kdtree.md)
|
||||
* [`MeanSplitKDTree`](trees/mean_split_kdtree.md)
|
||||
* [`MeanSplitBallTree`](trees/mean_split_ball_tree.md)
|
||||
* [`BinarySpaceTree`](trees/binary_space_tree.md)
|
||||
* [`BallTree`](trees/ball_tree.md)
|
||||
* [`MeanSplitBallTree`](trees/mean_split_ball_tree.md)
|
||||
* [`RPTree`](trees/rp_tree.md)
|
||||
* [`MaxRPTree`](trees/max_rp_tree.md)
|
||||
* [`BinarySpaceTree`](trees/binary_space_tree.md)
|
||||
* [`UBTree`](trees/ub_tree.md)
|
||||
|
||||
*Note:* this documentation is a work in progress. Not all trees are documented
|
||||
|
||||
@@ -546,16 +546,16 @@ std::cout << "Saved tree with " << tree.Dataset().n_cols << " points to "
|
||||
---
|
||||
|
||||
Load a 32-bit floating point `BallTree` from disk, then traverse it manually and
|
||||
find the number of leaf nodes with fewer than 10 children.
|
||||
find the number of leaf nodes with fewer than 10 points.
|
||||
|
||||
```c++
|
||||
// This assumes the tree has already been saved to 'tree.bin' (as in the example
|
||||
// above).
|
||||
|
||||
// This convenient typedef saves us a long type name!
|
||||
typedef mlpack::BallTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat> TreeType;
|
||||
using TreeType = mlpack::BallTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat>;
|
||||
|
||||
TreeType tree;
|
||||
mlpack::data::Load("tree.bin", "tree", tree);
|
||||
|
||||
@@ -1968,6 +1968,11 @@ to write a fully custom split:
|
||||
dimension with maximum width
|
||||
* [`VantagePointSplit`](#vantagepointsplit): split by selecting a 'vantage
|
||||
point' and then split points into 'near' and 'far' sets
|
||||
* [`RPTreeMeanSplit`](#rptreemeansplit): projects points onto a random vector,
|
||||
splitting on the median value of the projections, or in some cases on the
|
||||
distance from the mean value
|
||||
* [`RPTreeMaxSplit`](#rptreemaxsplit): projects points onto a random vector,
|
||||
splitting on a random offset of the median of projected points
|
||||
* [`UBTreeSplit`](#ubtreesplit): splits a [`CellBound`](#cellbound) into two
|
||||
balanced children
|
||||
* [Custom `SplitType`s](#custom-splittypes): implement a fully custom
|
||||
@@ -2005,7 +2010,7 @@ The splitting strategy for the `MeanSplit` class is, given a set of points:
|
||||
* Compute the mean value `m` of the points in dimension `d`.
|
||||
* Split in dimension `d`.
|
||||
* Points less than `m` will go to the left child.
|
||||
* Points greater than `m` will go to the right child.
|
||||
* Points greater than or equal to `m` will go to the right child.
|
||||
|
||||
In practice, the `MeanSplit` splitting strategy often results in a tree with
|
||||
fewer leaf nodes than `MidpointSplit`, because each split is more likely to be
|
||||
@@ -2063,6 +2068,67 @@ Then, `MyVantagePointSplit` can be used directly with `BinarySpaceTree` as a
|
||||
For implementation details, see
|
||||
[the source code](/src/mlpack/core/tree/binary_space_tree/vantage_point_split_impl.hpp).
|
||||
|
||||
### `RPTreeMeanSplit`
|
||||
|
||||
The `RPTreeMeanSplit` class is a splitting strategy that can be used by
|
||||
[`BinarySpaceTree`](#binaryspacetree). It is the splitting strategy used by the
|
||||
[`RPTree`](rp_tree.md) class, and uses a random projection to split points. The
|
||||
general idea is described in the paper by
|
||||
[Dasgupta and Freund](https://www.cs.cornell.edu/~abrahao/tdg/papers/p537.pdf),
|
||||
as the `RPTree-Mean` version of the `ChooseRule()` function.
|
||||
|
||||
The splitting strategy for the `RPTreeMeanSplit` class is, given a set of
|
||||
points:
|
||||
|
||||
* Draw a random vector `z`.
|
||||
* Sample up to 100 points and compute `d`, the average pairwise distance
|
||||
between the points.
|
||||
* If `10 * d` is less than or equal to the squared diameter of the bounding box
|
||||
of the points:
|
||||
- Project all points onto the vector `z`, and compute the median `v` of the
|
||||
projected values.
|
||||
- Points with projected value less than `v` will go to the left child.
|
||||
- Points with projected value greater than or equal to `v` will go to the
|
||||
right child.
|
||||
* Otherwise:
|
||||
- Compute the mean `s` of all points.
|
||||
- Points with distance from `s` less than the median distance from `s`
|
||||
will go to the left child.
|
||||
- Points with distance from `s` greater than or equal to the median distance
|
||||
from `s` will go to the right child.
|
||||
|
||||
The implementation strategy differs slightly from the `RPTree-Mean` version in
|
||||
the paper: instead of computing the true average pairwise distance between all
|
||||
points, a sample of 100 points is used.
|
||||
|
||||
For implementation details, see
|
||||
[the source code](/src/mlpack/core/tree/binary_space_tree/rp_tree_mean_split_impl.hpp).
|
||||
|
||||
### `RPTreeMaxSplit`
|
||||
|
||||
The `RPTreeMaxSplit` class is a splitting strategy that can be used by
|
||||
[`BinarySpaceTree`](#binaryspacetree). It is the splitting strategy used by the
|
||||
[`MaxRPTree`](max_rp_tree.md) class, and uses a random projection to split
|
||||
points. The general idea is described in the paper by
|
||||
[Dasgupta and Freund](https://www.cs.cornell.edu/~abrahao/tdg/papers/p537.pdf),
|
||||
as the `RPTree-Max` version of the `ChooseRule()` function.
|
||||
|
||||
The splitting strategy for the `RPTreeMaxSplit` class is, given a set of points,
|
||||
|
||||
* Draw a random vector `z`.
|
||||
* Sample up to 100 points (call this sample `S`).
|
||||
* Compute `v`, the median value of projections of points in `S` onto `z`.
|
||||
* Points with projection onto `z` less than `v` will go to the left child.
|
||||
* Points with projection onto `z` greater than or equal to `v` will go to the
|
||||
right child.
|
||||
|
||||
The implementation strategy differs slightly from the `RPTree-Max` version in
|
||||
the paper: instead of computing the median on all points, a sample of 100 points
|
||||
is used.
|
||||
|
||||
For implementation details, see
|
||||
[the source code](/src/mlpack/core/tree/binary_space_tree/rp_tree_max_split_impl.hpp).
|
||||
|
||||
### `UBTreeSplit`
|
||||
|
||||
The `UBTreeSplit` class is a splitting strategy that can be used by
|
||||
@@ -2210,11 +2276,11 @@ arma::mat dataset;
|
||||
mlpack::data::Load("corel-histogram.csv", dataset, true);
|
||||
|
||||
// Convenience typedef for the tree type.
|
||||
typedef mlpack::BinarySpaceTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::mat,
|
||||
mlpack::HRectBound,
|
||||
mlpack::MidpointSplit> TreeType;
|
||||
using TreeType = mlpack::BinarySpaceTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::mat,
|
||||
mlpack::HRectBound,
|
||||
mlpack::MidpointSplit>;
|
||||
|
||||
// Build trees on the first half and the second half of points.
|
||||
TreeType tree1(dataset.cols(0, dataset.n_cols / 2));
|
||||
@@ -2300,18 +2366,18 @@ std::cout << "Saved tree with " << tree.Dataset().n_cols << " points to "
|
||||
---
|
||||
|
||||
Load a 32-bit floating point `BinarySpaceTree` from disk, then traverse it
|
||||
manually and find the number of leaf nodes with less than 10 children.
|
||||
manually and find the number of leaf nodes with less than 10 points.
|
||||
|
||||
```c++
|
||||
// This assumes the tree has already been saved to 'tree.bin' (as in the example
|
||||
// above).
|
||||
|
||||
// This convenient typedef saves us a long type name!
|
||||
typedef mlpack::BinarySpaceTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat,
|
||||
mlpack::HRectBound,
|
||||
mlpack::MidpointSplit> TreeType;
|
||||
using TreeType = mlpack::BinarySpaceTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat,
|
||||
mlpack::HRectBound,
|
||||
mlpack::MidpointSplit>;
|
||||
|
||||
TreeType tree;
|
||||
mlpack::data::Load("tree.bin", "tree", tree);
|
||||
|
||||
@@ -540,16 +540,16 @@ std::cout << "Saved tree with " << tree.Dataset().n_cols << " points to "
|
||||
---
|
||||
|
||||
Load a 32-bit floating point `KDTree` from disk, then traverse it manually and
|
||||
find the number of leaf nodes with fewer than 10 children.
|
||||
find the number of leaf nodes with fewer than 10 points.
|
||||
|
||||
```c++
|
||||
// This assumes the tree has already been saved to 'tree.bin' (as in the example
|
||||
// above).
|
||||
|
||||
// This convenient typedef saves us a long type name!
|
||||
typedef mlpack::KDTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat> TreeType;
|
||||
using TreeType = mlpack::KDTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat>;
|
||||
|
||||
TreeType tree;
|
||||
mlpack::data::Load("tree.bin", "tree", tree);
|
||||
|
||||
@@ -0,0 +1,635 @@
|
||||
# `MaxRPTree`
|
||||
|
||||
<!-- TODO: link to knn.md once it's done -->
|
||||
|
||||
The `MaxRPTree` class represents a random projection tree, a variant of the
|
||||
[`k`-d tree](kdtree.md) based on random projections. The random projection tree
|
||||
is a well-known data structure for efficient distance operations (such as
|
||||
nearest neighbor search) in low dimensions---typically less than 100.
|
||||
|
||||
An `MaxRPTree` (or the similar [`RPTree`](rp_tree.md)) may be preferred over
|
||||
a [`KDTree`](kdtree.md) or other tree structures as it is theoretically known to
|
||||
adapt to the intrinsic dimension of the data. This is similar to the cover
|
||||
tree, but the implementation is far simpler and as a result, more efficient.
|
||||
|
||||
<!-- TODO: add cover tree link above -->
|
||||
|
||||
mlpack's `MaxRPTree` implementation supports three template parameters for
|
||||
configurable behavior, and implements all the functionality required by the
|
||||
[TreeType API](../../../developer/trees.md#the-treetype-api), plus some
|
||||
additional functionality specific to random projection trees.
|
||||
|
||||
* [Template parameters](#template-parameters)
|
||||
* [Constructors](#constructors)
|
||||
* [Basic tree properties](#basic-tree-properties)
|
||||
* [Bounding distances with the tree](#bounding-distances-with-the-tree)
|
||||
* [Tree traversals](#tree-traversals)
|
||||
* [Example usage](#example-usage)
|
||||
|
||||
## See also
|
||||
|
||||
<!-- TODO: add links to all distance-based algorithms and other trees? -->
|
||||
|
||||
* [`RPTree`](rp_tree.md)
|
||||
* [kd-tree on Wikipedia](https://en.wikipedia.org/wiki/Kd-tree)
|
||||
* [Random projection on Wikipedia](https://en.wikipedia.org/wiki/Random_projection)
|
||||
* [`BinarySpaceTree`](binary_space_tree.md)
|
||||
* [Binary space partitioning on Wikipedia](https://dl.acm.org/doi/pdf/10.1145/361002.361007)
|
||||
* [Random Projection Trees and Low Dimensional Manifolds (pdf)](https://www.cs.cornell.edu/~abrahao/tdg/papers/p537.pdf)
|
||||
* [Tree-Independent Dual-Tree Algorithms (pdf)](https://www.ratml.org/pub/pdf/2013tree.pdf)
|
||||
|
||||
## Template parameters
|
||||
|
||||
In accordance with the [TreeType
|
||||
API](../../../developer/trees.md#template-parameters-required-by-the-treetype-policy)
|
||||
(see also [this more detailed section](../../../developer/trees.md#template-parameters)),
|
||||
the `MaxRPTree` class takes three template parameters:
|
||||
|
||||
```
|
||||
MaxRPTree<DistanceType, StatisticType, MatType>
|
||||
```
|
||||
|
||||
* `DistanceType`: the [distance metric](../distances.md) to use for distance
|
||||
computations. For the `MaxRPTree`, this must be an
|
||||
[`LMetric`](../distances.md#lmetric). By default, this is
|
||||
[`EuclideanDistance`](../distances.md#lmetric).
|
||||
* [`StatisticType`](binary_space_tree.md#statistictype): this holds auxiliary
|
||||
information in each tree node. By default,
|
||||
[`EmptyStatistic`](binary_space_tree.md#emptystatistic) is used, which holds
|
||||
no information.
|
||||
* `MatType`: the type of matrix used to represent points. Must be a type
|
||||
matching the [Armadillo API](../../matrices.md). By default, `arma::mat` is
|
||||
used, but other types such as `arma::fmat` or similar will work just fine.
|
||||
|
||||
The `MaxRPTree` class itself is a convenience typedef of the generic
|
||||
[`BinarySpaceTree`](binary_space_tree.md) class, using the
|
||||
[`HRectBound`](binary_space_tree.md#hrectbound) class as the bounding structure,
|
||||
and using the [`RPTreeMaxSplit`](binary_space_tree.md#rptreemaxsplit)
|
||||
splitting strategy for construction, which splits a node along a random
|
||||
projection, or, in some cases, based on the distance from the vector-valued mean
|
||||
of points in the node.
|
||||
|
||||
If no template parameters are explicitly specified, then defaults are used:
|
||||
|
||||
```
|
||||
MaxRPTree<> = MaxRPTree<EuclideanDistance, EmptyStatistic, arma::mat>
|
||||
```
|
||||
|
||||
## Constructors
|
||||
|
||||
`MaxRPTree`s are efficiently constructed by permuting points in a dataset in a
|
||||
quicksort-like algorithm. However, this means that the ordering of points in
|
||||
the tree's dataset (accessed with `node.Dataset()`) after construction may be
|
||||
different.
|
||||
|
||||
---
|
||||
|
||||
* `node = MaxRPTree(data, maxLeafSize=20)`
|
||||
* `node = MaxRPTree(data, oldFromNew, maxLeafSize=20)`
|
||||
* `node = MaxRPTree(data, oldFromNew, newFromOld, maxLeafSize=20)`
|
||||
- Construct a `MaxRPTree` on the given `data`, using `maxLeafSize` as the
|
||||
maximum number of points held in a leaf.
|
||||
- By default, `data` is copied. Avoid a copy by using `std::move()` (e.g.
|
||||
`std::move(data)`); when doing this, `data` will be set to an empty matrix.
|
||||
- Optionally, construct mappings from old points to new points. `oldFromNew`
|
||||
and `newFromOld` will have length `data.n_cols`, and:
|
||||
* `oldFromNew[i]` indicates that point `i` in the tree's dataset was
|
||||
originally point `oldFromNew[i]` in `data`; that is,
|
||||
`node.Dataset().col(i)` is the point `data.col(oldFromNew[i])`.
|
||||
* `newFromOld[i]` indicates that point `i` in `data` is now point
|
||||
`newFromOld[i]` in the tree's dataset; that is,
|
||||
`node.Dataset().col(newFromOld[i])` is the point `data.col(i)`.
|
||||
|
||||
---
|
||||
|
||||
* `node = MaxRPTree<DistanceType, StatisticType, MatType>(data, maxLeafSize=20)`
|
||||
* `node = MaxRPTree<DistanceType, StatisticType, MatType>(data, oldFromNew, maxLeafSize=20)`
|
||||
* `node = MaxRPTree<DistanceType, StatisticType, MatType>(data, oldFromNew, newFromOld, maxLeafSize=20)`
|
||||
- Construct a `MaxRPTree` on the given `data`, using custom template
|
||||
parameters to control the behavior of the tree, using `maxLeafSize` as the
|
||||
maximum number of points held in a leaf.
|
||||
- By default, `data` is copied. Avoid a copy by using `std::move()` (e.g.
|
||||
`std::move(data)`); when doing this, `data` will be set to an empty matrix.
|
||||
- Optionally, construct mappings from old points to new points. `oldFromNew`
|
||||
and `newFromOld` will have length `data.n_cols`, and:
|
||||
* `oldFromNew[i]` indicates that point `i` in the tree's dataset was
|
||||
originally point `oldFromNew[i]` in `data`; that is,
|
||||
`node.Dataset().col(i)` is the point `data.col(oldFromNew[i])`.
|
||||
* `newFromOld[i]` indicates that point `i` in `data` is now point
|
||||
`newFromOld[i]` in the tree's dataset; that is,
|
||||
`node.Dataset().col(newFromOld[i])` is the point `data.col(i)`.
|
||||
|
||||
---
|
||||
|
||||
* `node = MaxRPTree()`
|
||||
- Construct an empty random projection tree with no children and no points.
|
||||
|
||||
---
|
||||
|
||||
***Notes:***
|
||||
|
||||
- The name `node` is used here for `MaxRPTree` objects instead of `tree`,
|
||||
because each `MaxRPTree` object is a single node in the tree. The
|
||||
constructor returns the node that is the root of the tree.
|
||||
|
||||
- Inserting individual points or removing individual points from a `MaxRPTree`
|
||||
is not supported, because this generally results in a random projection tree
|
||||
with very loose bounding boxes. It is better to simply build a new
|
||||
`MaxRPTree` on the modified dataset. For trees that support individual
|
||||
insertion and deletions, see the `RectangleTree` class and all its variants
|
||||
(e.g. `RTree`, `RStarTree`, etc.).
|
||||
|
||||
- See also the
|
||||
[developer documentation on tree constructors](../../../developer/trees.md#constructors-and-destructors).
|
||||
|
||||
<!-- TODO: add links to RectangleTree above when it is documented -->
|
||||
|
||||
---
|
||||
|
||||
### Constructor parameters:
|
||||
|
||||
| **name** | **type** | **description** | **default** |
|
||||
|----------|----------|-----------------|-------------|
|
||||
| `data` | [`arma::mat`](../../matrices.md) | [Column-major](../../matrices.md#representing-data-in-mlpack) matrix to build the tree on. Pass with `std::move(data)` to avoid copying the matrix. | _(N/A)_ |
|
||||
| `maxLeafSize` | `size_t` | Maximum number of points to store in each leaf. | `20` |
|
||||
| `oldFromNew` | `std::vector<size_t>` | Mappings from points in `node.Dataset()` to points in `data`. | _(N/A)_ |
|
||||
| `newFromOld` | `std::vector<size_t>` | Mappings from points in `data` to points in `node.Dataset()`. | _(N/A)_ |
|
||||
|
||||
## Basic tree properties
|
||||
|
||||
Once a `MaxRPTree` object is constructed, various properties of the tree can be
|
||||
accessed or inspected. Many of these functions are required by the [TreeType
|
||||
API](../../../developer/trees.md#the-treetype-api).
|
||||
|
||||
### Navigating the tree
|
||||
|
||||
* `node.NumChildren()` returns the number of children in `node`. This is
|
||||
either `2` if `node` has children, or `0` if `node` is a leaf.
|
||||
|
||||
* `node.IsLeaf()` returns a `bool` indicating whether or not `node` is a leaf.
|
||||
|
||||
* `node.Child(i)` returns a `MaxRPTree&` that is the `i`th child.
|
||||
- `i` must be `0` or `1`.
|
||||
- This function should only be called if `node.NumChildren()` is not `0`
|
||||
(e.g. if `node` is not a leaf). Note that this returns a valid
|
||||
`MaxRPTree&` that can itself be used just like the root node of the tree!
|
||||
- `node.Left()` and `node.Right()` are convenience functions specific to
|
||||
`MaxRPTree` that will return `MaxRPTree*` (pointers) to the left and right
|
||||
children, respectively, or `NULL` if `node` has no children.
|
||||
|
||||
* `node.Parent()` will return a `MaxRPTree*` that points to the parent of
|
||||
`node`, or `NULL` if `node` is the root of the `MaxRPTree`.
|
||||
|
||||
---
|
||||
|
||||
### Accessing members of a tree
|
||||
|
||||
* `node.Bound()` will return an
|
||||
[`HRectBound&`](binary_space_tree.md#hrectbound) object that represents the
|
||||
hyperrectangle bounding box of `node`. This is the smallest hyperrectangle
|
||||
that encloses all the descendant points of `node`.
|
||||
|
||||
* `node.Stat()` will return an `EmptyStatistic&` (or a `StatisticType&` if a
|
||||
[custom `StatisticType`](#template-parameters) was specified as a template
|
||||
parameter) holding the statistics of the node that were computed during tree
|
||||
construction.
|
||||
|
||||
* `node.Distance()` will return a
|
||||
[`EuclideanDistance&`](../distances.md#lmetric) (or a `DistanceType&` if a
|
||||
[custom `DistanceType`](#template-parameters) was specified as a template
|
||||
parameter).
|
||||
- This function is required by the
|
||||
[TreeType API](../../../developer/trees.md#the-treetype-api), but given
|
||||
that `MaxRPTree` requires an [`LMetric`](../distances.md#lmetric) to be
|
||||
used, and `LMetric` only has `static` functions and holds no state, this
|
||||
function is not likely to be useful.
|
||||
|
||||
See also the
|
||||
[developer documentation](../../../developer/trees.md#basic-tree-functionality)
|
||||
for basic tree functionality in mlpack.
|
||||
|
||||
---
|
||||
|
||||
### Accessing data held in a tree
|
||||
|
||||
* `node.Dataset()` will return a `const arma::mat&` that is the dataset the
|
||||
tree was built on. Note that this is a permuted version of the `data` matrix
|
||||
passed to the constructor.
|
||||
- If a [custom `MatType`](#template-parameters) is being used, the return
|
||||
type will be `const MatType&` instead of `const arma::mat&`.
|
||||
|
||||
* `node.NumPoints()` returns a `size_t` indicating the number of points held
|
||||
directly in `node`.
|
||||
- If `node` is not a leaf, this will return `0`, as `MaxRPTree` only holds
|
||||
points directly in its leaves.
|
||||
- If `node` is a leaf, then the number of points will be less than or equal
|
||||
to the `maxLeafSize` that was specified when the tree was constructed.
|
||||
|
||||
* `node.Point(i)` returns a `size_t` indicating the index of the `i`'th point
|
||||
in `node.Dataset()`.
|
||||
- `i` must be in the range `[0, node.NumPoints() - 1]` (inclusive).
|
||||
- `node` must be a leaf (as non-leaves do not hold any points).
|
||||
- The `i`'th point in `node` can then be accessed as
|
||||
`node.Dataset().col(node.Point(i))`.
|
||||
- In a `MaxRPTree`, because of the permutation of points done [during
|
||||
construction](#constructors), point indices are contiguous:
|
||||
`node.Point(i + j)` is the same as `node.Point(i) + j` for valid `i` and
|
||||
`j`.
|
||||
- Accessing the actual `i`'th point itself can be done with, e.g.,
|
||||
`node.Dataset().col(node.Point(i))`.
|
||||
|
||||
* `node.NumDescendants()` returns a `size_t` indicating the number of points
|
||||
held in all descendant leaves of `node`.
|
||||
- If `node` is the root of the tree, then `node.NumDescendants()` will be
|
||||
equal to `node.Dataset().n_cols`.
|
||||
|
||||
* `node.Descendant(i)` returns a `size_t` indicating the index of the `i`'th
|
||||
descendant point in `node.Dataset()`.
|
||||
- `i` must be in the range `[0, node.NumDescendants() - 1]` (inclusive).
|
||||
- `node` does not need to be a leaf.
|
||||
- The `i`'th descendant point in `node` can then be accessed as
|
||||
`node.Dataset().col(node.Descendant(i))`.
|
||||
- In a `MaxRPTree`, because of the permutation of points done [during
|
||||
construction](#constructors), point indices are contiguous:
|
||||
`node.Descendant(i + j)` is the same as `node.Descendant(i) + j` for valid
|
||||
`i` and `j`.
|
||||
- Accessing the actual `i`'th descendant itself can be done with, e.g.,
|
||||
`node.Dataset().col(node.Descendant(i))`.
|
||||
|
||||
* `node.Begin()` returns a `size_t` indicating the index of the first
|
||||
descendant point of `node`.
|
||||
- This is equivalent to `node.Descendant(0)`.
|
||||
|
||||
* `node.Count()` returns a `size_t` indicating the number of descendant points of `node`.
|
||||
- This is equivalent to `node.NumDescendants()`.
|
||||
|
||||
---
|
||||
|
||||
### Accessing computed bound quantities of a tree
|
||||
|
||||
The following quantities are cached for each node in a `MaxRPTree`, and so
|
||||
accessing them does not require any computation.
|
||||
|
||||
* `node.FurthestPointDistance()` returns a `double` representing the distance
|
||||
between the center of the bounding hyperrectangle of `node` and the furthest
|
||||
point held by `node`.
|
||||
- If `node` is not a leaf, this returns 0 (because `node` does not hold any
|
||||
points).
|
||||
|
||||
* `node.FurthestDescendantDistance()` returns a `double` representing the
|
||||
distance between the center of the bounding hyperrectangle of `node` and the
|
||||
furthest descendant point held by `node`.
|
||||
|
||||
* `node.MinimumBoundDistance()` returns a `double` representing minimum
|
||||
possible distance from the center of the node to any edge of the
|
||||
hyperrectangle bound.
|
||||
- This quantity is half the width of the smallest dimension of
|
||||
`node.Bound()`.
|
||||
|
||||
* `node.ParentDistance()` returns a `double` representing the distance between
|
||||
the center of the bounding hyperrectangle of `node` and the center of the
|
||||
bounding hyperrectangle of its parent.
|
||||
- If `node` is the root of the tree, `0` is returned.
|
||||
|
||||
***Notes:***
|
||||
|
||||
- If a [custom `MatType`](#template-parameters) was specified when constructing
|
||||
the `MaxRPTree`, then the return type of each method is the element type of
|
||||
the given `MatType` instead of `double`. (e.g., if `MatType` is
|
||||
`arma::fmat`, then the return type is `float`.)
|
||||
|
||||
- For more details on each bound quantity, see the
|
||||
[developer documentation](../../../developer/trees.md#complex-tree-functionality-and-bounds)
|
||||
on bound quantities for trees.
|
||||
|
||||
---
|
||||
|
||||
### Other functionality
|
||||
|
||||
* `node.Center(center)` computes the center of the bounding hyperrectangle of
|
||||
`node` and stores it in `center`.
|
||||
- `center` should be of type `arma::vec&`. (If a [custom
|
||||
`MatType`](#template-parameters) was specified when constructing the
|
||||
`MaxRPTree`, the type is instead the column vector type for the given
|
||||
`MatType`; e.g., `arma::fvec&` when `MatType` is `arma::fmat`.)
|
||||
- `center` will be set to have size equivalent to the dimensionality of the
|
||||
dataset held by `node`.
|
||||
- This is equivalent to calling `node.Bound().Center(center)`.
|
||||
|
||||
* A `MaxRPTree` can be serialized with
|
||||
[`data::Save()` and `data::Load()`](../../load_save.md#mlpack-objects).
|
||||
|
||||
## Bounding distances with the tree
|
||||
|
||||
The primary use of trees in mlpack is bounding distances to points or other tree
|
||||
nodes. The following functions can be used for these tasks.
|
||||
|
||||
* `node.GetNearestChild(point)`
|
||||
* `node.GetFurthestChild(point)`
|
||||
- Return a `size_t` indicating the index of the child (`0` for left, `1` for
|
||||
right) that is closest to (or furthest from) `point`, with respect
|
||||
to the `MinDistance()` (or `MaxDistance()`) function.
|
||||
- If there is a tie, `0` (the left child) is returned.
|
||||
- If `node` is a leaf, `0` is returned.
|
||||
- `point` should be of type `arma::vec`. (If a [custom
|
||||
`MatType`](#template-parameters) was specified when constructing the
|
||||
`MaxRPTree`, the type is instead the column vector type for the given
|
||||
`MatType`; e.g., `arma::fvec` when `MatType` is `arma::fmat`.)
|
||||
|
||||
* `node.GetNearestChild(other)`
|
||||
* `node.GetFurthestChild(other)`
|
||||
- Return a `size_t` indicating the index of the child (`0` for left, `1` for
|
||||
right) that is closest to (or furthest from) the `MaxRPTree` node `other`,
|
||||
with respect to the `MinDistance()` (or `MaxDistance()`) function.
|
||||
- If there is a tie, `2` (an invalid index) is returned. ***Note that this
|
||||
behavior differs from the version above that takes a point.***
|
||||
- If `node` is a leaf, `0` is returned.
|
||||
|
||||
---
|
||||
|
||||
* `node.MinDistance(point)`
|
||||
* `node.MinDistance(other)`
|
||||
- Return a `double` indicating the minimum possible distance between `node`
|
||||
and `point`, or the `MaxRPTree` node `other`.
|
||||
- This is equivalent to the minimum possible distance between any point
|
||||
contained in the bounding hyperrectangle of `node` and `point`, or between
|
||||
any point contained in the bounding hyperrectangle of `node` and any point
|
||||
contained in the bounding hyperrectangle of `other`.
|
||||
- `point` should be of type `arma::vec`. (If a [custom
|
||||
`MatType`](#template-parameters) was specified when constructing the
|
||||
`MaxRPTree`, the type is instead the column vector type for the given
|
||||
`MatType`, and the return type is the element type of `MatType`; e.g.,
|
||||
`point` should be `arma::fvec` when `MatType` is `arma::fmat`, and the
|
||||
returned distance is `float`).
|
||||
|
||||
* `node.MaxDistance(point)`
|
||||
* `node.MaxDistance(other)`
|
||||
- Return a `double` indicating the maximum possible distance between `node`
|
||||
and `point`, or the `MaxRPTree` node `other`.
|
||||
- This is equivalent to the maximum possible distance between any point
|
||||
contained in the bounding hyperrectangle of `node` and `point`, or between
|
||||
any point contained in the bounding hyperrectangle of `node` and any point
|
||||
contained in the bounding hyperrectangle of `other`.
|
||||
- `point` should be of type `arma::vec`. (If a [custom
|
||||
`MatType`](#template-parameters) was specified when constructing the
|
||||
`MaxRPTree`, the type is instead the column vector type for the given
|
||||
`MatType`, and the return type is the element type of `MatType`; e.g.,
|
||||
`point` should be `arma::fvec` when `MatType` is `arma::fmat`, and the
|
||||
returned distance is `float`).
|
||||
|
||||
* `node.RangeDistance(point)`
|
||||
* `node.RangeDistance(other)`
|
||||
- Return a [`Range`](../math.md#range) whose lower bound is
|
||||
`node.MinDistance(point)` or `node.MinDistance(other)`, and whose upper
|
||||
bound is `node.MaxDistance(point)` or `node.MaxDistance(other)`.
|
||||
- `point` should be of type `arma::vec`. (If a
|
||||
[custom `MatType`](#template-parameters) was specified when constructing
|
||||
the `MaxRPTree`, the type is instead the column vector type for the given
|
||||
`MatType`, and the return type is a `RangeType` with element type the same
|
||||
as `MatType`; e.g., `point` should be `arma::fvec` when `MatType` is
|
||||
`arma::fmat`, and the returned type is
|
||||
[`RangeType<float>`](../math.md#range)).
|
||||
|
||||
### Tree traversals
|
||||
|
||||
Like every mlpack tree, the `MaxRPTree` class provides a [single-tree and
|
||||
dual-tree traversal](../../../developer/trees.md#traversals) that can be paired
|
||||
with a [`RuleType` class](../../../developer/trees.md#rules) to implement a
|
||||
single-tree or dual-tree algorithm.
|
||||
|
||||
* `MaxRPTree::SingleTreeTraverser`
|
||||
- Implements a depth-first single-tree traverser.
|
||||
|
||||
* `MaxRPTree::DualTreeTraverser`
|
||||
- Implements a dual-depth-first dual-tree traverser.
|
||||
|
||||
In addition to those two classes, which are required by the
|
||||
[`TreeType` policy](../../../developer/trees.md), an additional traverser is
|
||||
available:
|
||||
|
||||
* `MaxRPTree::BreadthFirstDualTreeTraverser`
|
||||
- Implements a dual-breadth-first dual-tree traverser.
|
||||
- ***Note:*** this traverser is not useful for all tasks; because the
|
||||
`MaxRPTree` only holds points in the leaves, this means that no base cases
|
||||
(e.g. comparisons between points) will be called until *all* pairs of
|
||||
intermediate nodes have been scored!
|
||||
|
||||
## Example usage
|
||||
|
||||
Build a `MaxRPTree` on the `cloud` dataset and print basic statistics about the
|
||||
tree.
|
||||
|
||||
```c++
|
||||
// See https://datasets.mlpack.org/cloud.csv.
|
||||
arma::mat dataset;
|
||||
mlpack::data::Load("cloud.csv", dataset, true);
|
||||
|
||||
// Build the random projection tree with a leaf size of 10. (This means that
|
||||
// nodes are split until they contain 10 or fewer points.)
|
||||
//
|
||||
// The std::move() means that `dataset` will be empty after this call, and no
|
||||
// data will be copied during tree building.
|
||||
//
|
||||
// Note that the '<>' isn't necessary if C++20 is being used (e.g.
|
||||
// `mlpack::MaxRPTree tree(...)` will work fine in C++20 or newer).
|
||||
mlpack::MaxRPTree<> tree(std::move(dataset));
|
||||
|
||||
// Print the bounding box of the root node.
|
||||
std::cout << "Bounding box of root node:" << std::endl;
|
||||
for (size_t i = 0; i < tree.Bound().Dim(); ++i)
|
||||
{
|
||||
std::cout << " - Dimension " << i << ": [" << tree.Bound()[i].Lo() << ", "
|
||||
<< tree.Bound()[i].Hi() << "]." << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
// Print the number of descendant points of the root, and of each of its
|
||||
// children.
|
||||
std::cout << "Descendant points of root: "
|
||||
<< tree.NumDescendants() << "." << std::endl;
|
||||
std::cout << "Descendant points of left child: "
|
||||
<< tree.Left()->NumDescendants() << "." << std::endl;
|
||||
std::cout << "Descendant points of right child: "
|
||||
<< tree.Right()->NumDescendants() << "." << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
// Compute the center of the rp-tree.
|
||||
arma::vec center;
|
||||
tree.Center(center);
|
||||
std::cout << "Center of random projection tree: " << center.t();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Build two `MaxRPTree`s on subsets of the corel dataset and compute minimum and
|
||||
maximum distances between different nodes in the tree.
|
||||
|
||||
```c++
|
||||
// See https://datasets.mlpack.org/corel-histogram.csv.
|
||||
arma::mat dataset;
|
||||
mlpack::data::Load("corel-histogram.csv", dataset, true);
|
||||
|
||||
// Build rp-trees on the first half and the second half of points.
|
||||
mlpack::MaxRPTree<> tree1(dataset.cols(0, dataset.n_cols / 2));
|
||||
mlpack::MaxRPTree<> tree2(dataset.cols(dataset.n_cols / 2 + 1,
|
||||
dataset.n_cols - 1));
|
||||
|
||||
// Compute the maximum distance between the trees.
|
||||
std::cout << "Maximum distance between tree root nodes: "
|
||||
<< tree1.MaxDistance(tree2) << "." << std::endl;
|
||||
|
||||
// Get the leftmost grandchild of the first tree's root---if it exists.
|
||||
if (!tree1.IsLeaf() && !tree1.Child(0).IsLeaf())
|
||||
{
|
||||
mlpack::MaxRPTree<>& node1 = tree1.Child(0).Child(0);
|
||||
|
||||
// Get the rightmost grandchild of the second tree's root---if it exists.
|
||||
if (!tree2.IsLeaf() && !tree2.Child(1).IsLeaf())
|
||||
{
|
||||
mlpack::MaxRPTree<>& node2 = tree2.Child(1).Child(1);
|
||||
|
||||
// Print the minimum and maximum distance between the nodes.
|
||||
mlpack::Range dists = node1.RangeDistance(node2);
|
||||
std::cout << "Possible distances between two grandchild nodes: ["
|
||||
<< dists.Lo() << ", " << dists.Hi() << "]." << std::endl;
|
||||
|
||||
// Print the minimum distance between the first node and the first
|
||||
// descendant point of the second node.
|
||||
const size_t descendantIndex = node2.Descendant(0);
|
||||
const double descendantMinDist =
|
||||
node1.MinDistance(node2.Dataset().col(descendantIndex));
|
||||
std::cout << "Minimum distance between grandchild node and descendant "
|
||||
<< "point: " << descendantMinDist << "." << std::endl;
|
||||
|
||||
// Which child of node2 is closer to node1?
|
||||
const size_t closerIndex = node2.GetNearestChild(node1);
|
||||
if (closerIndex == 0)
|
||||
std::cout << "The left child of node2 is closer to node1." << std::endl;
|
||||
else if (closerIndex == 1)
|
||||
std::cout << "The right child of node2 is closer to node1." << std::endl;
|
||||
else // closerIndex == 2 in this case.
|
||||
std::cout << "Both children of node2 are equally close to node1."
|
||||
<< std::endl;
|
||||
|
||||
// And which child of node1 is further from node2?
|
||||
const size_t furtherIndex = node1.GetFurthestChild(node2);
|
||||
if (furtherIndex == 0)
|
||||
std::cout << "The left child of node1 is further from node2."
|
||||
<< std::endl;
|
||||
else if (furtherIndex == 1)
|
||||
std::cout << "The right child of node1 is further from node2."
|
||||
<< std::endl;
|
||||
else // furtherIndex == 2 in this case.
|
||||
std::cout << "Both children of node1 are equally far from node2."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Build a `MaxRPTree` on 32-bit floating point data and save it to disk.
|
||||
|
||||
```c++
|
||||
// See https://datasets.mlpack.org/corel-histogram.csv.
|
||||
arma::fmat dataset;
|
||||
mlpack::data::Load("corel-histogram.csv", dataset);
|
||||
|
||||
// Build the MaxRPTree using 32-bit floating point data as the matrix type.
|
||||
// We will still use the default EmptyStatistic and EuclideanDistance
|
||||
// parameters. A leaf size of 100 is used here.
|
||||
mlpack::MaxRPTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat> tree(std::move(dataset), 100);
|
||||
|
||||
// Save the MaxRPTree to disk with the name 'tree'.
|
||||
mlpack::data::Save("tree.bin", "tree", tree);
|
||||
|
||||
std::cout << "Saved tree with " << tree.Dataset().n_cols << " points to "
|
||||
<< "'tree.bin'." << std::endl;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Load a 32-bit floating point `MaxRPTree` from disk, then traverse it manually
|
||||
and find the number of leaf nodes with fewer than 10 points.
|
||||
|
||||
```c++
|
||||
// This assumes the tree has already been saved to 'tree.bin' (as in the example
|
||||
// above).
|
||||
|
||||
// This convenient typedef saves us a long type name!
|
||||
typedef mlpack::MaxRPTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat> TreeType;
|
||||
|
||||
TreeType tree;
|
||||
mlpack::data::Load("tree.bin", "tree", tree);
|
||||
std::cout << "Tree loaded with " << tree.NumDescendants() << " points."
|
||||
<< std::endl;
|
||||
|
||||
// Recurse in a depth-first manner. Count both the total number of leaves, and
|
||||
// the number of leaves with fewer than 10 points.
|
||||
size_t leafCount = 0;
|
||||
size_t totalLeafCount = 0;
|
||||
std::stack<TreeType*> stack;
|
||||
stack.push(&tree);
|
||||
while (!stack.empty())
|
||||
{
|
||||
TreeType* node = stack.top();
|
||||
stack.pop();
|
||||
|
||||
if (node->NumPoints() < 10)
|
||||
++leafCount;
|
||||
++totalLeafCount;
|
||||
|
||||
if (!node->IsLeaf())
|
||||
{
|
||||
stack.push(node->Left());
|
||||
stack.push(node->Right());
|
||||
}
|
||||
}
|
||||
|
||||
// Note that it would be possible to use TreeType::SingleTreeTraverser to
|
||||
// perform the recursion above, but that is more well-suited for more complex
|
||||
// tasks that require pruning and other non-trivial behavior; so using a simple
|
||||
// stack is the better option here.
|
||||
|
||||
// Print the results.
|
||||
std::cout << leafCount << " out of " << totalLeafCount << " leaves have fewer "
|
||||
<< "than 10 points." << std::endl;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Build a `MaxRPTree` and map between original points and new points.
|
||||
|
||||
```c++
|
||||
// See https://datasets.mlpack.org/cloud.csv.
|
||||
arma::mat dataset;
|
||||
mlpack::data::Load("cloud.csv", dataset, true);
|
||||
|
||||
// Build the tree.
|
||||
std::vector<size_t> oldFromNew, newFromOld;
|
||||
mlpack::MaxRPTree<> tree(dataset, oldFromNew, newFromOld);
|
||||
|
||||
// oldFromNew and newFromOld will be set to the same size as the dataset.
|
||||
std::cout << "Number of points in dataset: " << dataset.n_cols << "."
|
||||
<< std::endl;
|
||||
std::cout << "Size of oldFromNew: " << oldFromNew.size() << "." << std::endl;
|
||||
std::cout << "Size of newFromOld: " << newFromOld.size() << "." << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
// See where point 42 in the tree's dataset came from.
|
||||
std::cout << "Point 42 in the permuted tree's dataset:" << std::endl;
|
||||
std::cout << " " << tree.Dataset().col(42).t();
|
||||
std::cout << "Was originally point " << oldFromNew[42] << ":" << std::endl;
|
||||
std::cout << " " << dataset.col(oldFromNew[42]).t();
|
||||
std::cout << std::endl;
|
||||
|
||||
// See where point 7 in the original dataset was mapped.
|
||||
std::cout << "Point 7 in original dataset:" << std::endl;
|
||||
std::cout << " " << dataset.col(7).t();
|
||||
std::cout << "Mapped to point " << newFromOld[7] << ":" << std::endl;
|
||||
std::cout << " " << tree.Dataset().col(newFromOld[7]).t();
|
||||
```
|
||||
@@ -544,16 +544,16 @@ std::cout << "Saved tree with " << tree.Dataset().n_cols << " points to "
|
||||
---
|
||||
|
||||
Load a 32-bit floating point `BallTree` from disk, then traverse it manually and
|
||||
find the number of leaf nodes with fewer than 10 children.
|
||||
find the number of leaf nodes with fewer than 10 points.
|
||||
|
||||
```c++
|
||||
// This assumes the tree has already been saved to 'tree.bin' (as in the example
|
||||
// above).
|
||||
|
||||
// This convenient typedef saves us a long type name!
|
||||
typedef mlpack::MeanSplitBallTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat> TreeType;
|
||||
using TreeType = mlpack::MeanSplitBallTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat>;
|
||||
|
||||
TreeType tree;
|
||||
mlpack::data::Load("tree.bin", "tree", tree);
|
||||
|
||||
@@ -553,16 +553,16 @@ std::cout << "Saved tree with " << tree.Dataset().n_cols << " points to "
|
||||
---
|
||||
|
||||
Load a 32-bit floating point `MeanSplitKDTree` from disk, then traverse it
|
||||
manually and find the number of leaf nodes with fewer than 10 children.
|
||||
manually and find the number of leaf nodes with fewer than 10 points.
|
||||
|
||||
```c++
|
||||
// This assumes the tree has already been saved to 'tree.bin' (as in the example
|
||||
// above).
|
||||
|
||||
// This convenient typedef saves us a long type name!
|
||||
typedef mlpack::MeanSplitKDTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat> TreeType;
|
||||
using TreeType = mlpack::MeanSplitKDTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat>;
|
||||
|
||||
TreeType tree;
|
||||
mlpack::data::Load("tree.bin", "tree", tree);
|
||||
|
||||
@@ -0,0 +1,635 @@
|
||||
# `RPTree`
|
||||
|
||||
<!-- TODO: link to knn.md once it's done -->
|
||||
|
||||
The `RPTree` class represents a random projection tree, a variant of the
|
||||
[`k`-d tree](kdtree.md) based on random projections. The random projection tree
|
||||
is a well-known data structure for efficient distance operations (such as
|
||||
nearest neighbor search) in low dimensions---typically less than 100.
|
||||
|
||||
An `RPTree` (or the similar [`MaxRPTree`](max_rp_tree.md)) may be preferred over
|
||||
a [`KDTree`](kdtree.md) or other tree structures as it is theoretically known to
|
||||
adapt to the intrinsic dimension of the data. This is similar to the cover
|
||||
tree, but the implementation is far simpler and as a result, more efficient.
|
||||
|
||||
<!-- TODO: add cover tree link above -->
|
||||
|
||||
mlpack's `RPTree` implementation supports three template parameters for
|
||||
configurable behavior, and implements all the functionality required by the
|
||||
[TreeType API](../../../developer/trees.md#the-treetype-api), plus some
|
||||
additional functionality specific to random projection trees.
|
||||
|
||||
* [Template parameters](#template-parameters)
|
||||
* [Constructors](#constructors)
|
||||
* [Basic tree properties](#basic-tree-properties)
|
||||
* [Bounding distances with the tree](#bounding-distances-with-the-tree)
|
||||
* [Tree traversals](#tree-traversals)
|
||||
* [Example usage](#example-usage)
|
||||
|
||||
## See also
|
||||
|
||||
<!-- TODO: add links to all distance-based algorithms and other trees? -->
|
||||
|
||||
* [`MaxRPTree`](max_rp_tree.md)
|
||||
* [kd-tree on Wikipedia](https://en.wikipedia.org/wiki/Kd-tree)
|
||||
* [Random projection on Wikipedia](https://en.wikipedia.org/wiki/Random_projection)
|
||||
* [`BinarySpaceTree`](binary_space_tree.md)
|
||||
* [Binary space partitioning on Wikipedia](https://dl.acm.org/doi/pdf/10.1145/361002.361007)
|
||||
* [Random Projection Trees and Low Dimensional Manifolds (pdf)](https://www.cs.cornell.edu/~abrahao/tdg/papers/p537.pdf)
|
||||
* [Tree-Independent Dual-Tree Algorithms (pdf)](https://www.ratml.org/pub/pdf/2013tree.pdf)
|
||||
|
||||
## Template parameters
|
||||
|
||||
In accordance with the [TreeType
|
||||
API](../../../developer/trees.md#template-parameters-required-by-the-treetype-policy)
|
||||
(see also [this more detailed section](../../../developer/trees.md#template-parameters)),
|
||||
the `RPTree` class takes three template parameters:
|
||||
|
||||
```
|
||||
RPTree<DistanceType, StatisticType, MatType>
|
||||
```
|
||||
|
||||
* `DistanceType`: the [distance metric](../distances.md) to use for distance
|
||||
computations. For the `RPTree`, this must be an
|
||||
[`LMetric`](../distances.md#lmetric). By default, this is
|
||||
[`EuclideanDistance`](../distances.md#lmetric).
|
||||
* [`StatisticType`](binary_space_tree.md#statistictype): this holds auxiliary
|
||||
information in each tree node. By default,
|
||||
[`EmptyStatistic`](binary_space_tree.md#emptystatistic) is used, which holds
|
||||
no information.
|
||||
* `MatType`: the type of matrix used to represent points. Must be a type
|
||||
matching the [Armadillo API](../../matrices.md). By default, `arma::mat` is
|
||||
used, but other types such as `arma::fmat` or similar will work just fine.
|
||||
|
||||
The `RPTree` class itself is a convenience typedef of the generic
|
||||
[`BinarySpaceTree`](binary_space_tree.md) class, using the
|
||||
[`HRectBound`](binary_space_tree.md#hrectbound) class as the bounding structure,
|
||||
and using the [`RPTreeMeanSplit`](binary_space_tree.md#rptreemeansplit)
|
||||
splitting strategy for construction, which splits a node along a random
|
||||
projection, or, in some cases, based on the distance from the vector-valued mean
|
||||
of points in the node.
|
||||
|
||||
If no template parameters are explicitly specified, then defaults are used:
|
||||
|
||||
```
|
||||
RPTree<> = RPTree<EuclideanDistance, EmptyStatistic, arma::mat>
|
||||
```
|
||||
|
||||
## Constructors
|
||||
|
||||
`RPTree`s are efficiently constructed by permuting points in a dataset in a
|
||||
quicksort-like algorithm. However, this means that the ordering of points in
|
||||
the tree's dataset (accessed with `node.Dataset()`) after construction may be
|
||||
different.
|
||||
|
||||
---
|
||||
|
||||
* `node = RPTree(data, maxLeafSize=20)`
|
||||
* `node = RPTree(data, oldFromNew, maxLeafSize=20)`
|
||||
* `node = RPTree(data, oldFromNew, newFromOld, maxLeafSize=20)`
|
||||
- Construct an `RPTree` on the given `data`, using `maxLeafSize` as the
|
||||
maximum number of points held in a leaf.
|
||||
- By default, `data` is copied. Avoid a copy by using `std::move()` (e.g.
|
||||
`std::move(data)`); when doing this, `data` will be set to an empty matrix.
|
||||
- Optionally, construct mappings from old points to new points. `oldFromNew`
|
||||
and `newFromOld` will have length `data.n_cols`, and:
|
||||
* `oldFromNew[i]` indicates that point `i` in the tree's dataset was
|
||||
originally point `oldFromNew[i]` in `data`; that is,
|
||||
`node.Dataset().col(i)` is the point `data.col(oldFromNew[i])`.
|
||||
* `newFromOld[i]` indicates that point `i` in `data` is now point
|
||||
`newFromOld[i]` in the tree's dataset; that is,
|
||||
`node.Dataset().col(newFromOld[i])` is the point `data.col(i)`.
|
||||
|
||||
---
|
||||
|
||||
* `node = RPTree<DistanceType, StatisticType, MatType>(data, maxLeafSize=20)`
|
||||
* `node = RPTree<DistanceType, StatisticType, MatType>(data, oldFromNew, maxLeafSize=20)`
|
||||
* `node = RPTree<DistanceType, StatisticType, MatType>(data, oldFromNew, newFromOld, maxLeafSize=20)`
|
||||
- Construct an `RPTree` on the given `data`, using custom template parameters
|
||||
to control the behavior of the tree, using `maxLeafSize` as the maximum
|
||||
number of points held in a leaf.
|
||||
- By default, `data` is copied. Avoid a copy by using `std::move()` (e.g.
|
||||
`std::move(data)`); when doing this, `data` will be set to an empty matrix.
|
||||
- Optionally, construct mappings from old points to new points. `oldFromNew`
|
||||
and `newFromOld` will have length `data.n_cols`, and:
|
||||
* `oldFromNew[i]` indicates that point `i` in the tree's dataset was
|
||||
originally point `oldFromNew[i]` in `data`; that is,
|
||||
`node.Dataset().col(i)` is the point `data.col(oldFromNew[i])`.
|
||||
* `newFromOld[i]` indicates that point `i` in `data` is now point
|
||||
`newFromOld[i]` in the tree's dataset; that is,
|
||||
`node.Dataset().col(newFromOld[i])` is the point `data.col(i)`.
|
||||
|
||||
---
|
||||
|
||||
* `node = RPTree()`
|
||||
- Construct an empty random projection tree with no children and no points.
|
||||
|
||||
---
|
||||
|
||||
***Notes:***
|
||||
|
||||
- The name `node` is used here for `RPTree` objects instead of `tree`, because
|
||||
each `RPTree` object is a single node in the tree. The constructor returns
|
||||
the node that is the root of the tree.
|
||||
|
||||
- Inserting individual points or removing individual points from an `RPTree` is
|
||||
not supported, because this generally results in a random projection tree
|
||||
with very loose bounding boxes. It is better to simply build a new `RPTree`
|
||||
on the modified dataset. For trees that support individual insertion and
|
||||
deletions, see the `RectangleTree` class and all its variants (e.g. `RTree`,
|
||||
`RStarTree`, etc.).
|
||||
|
||||
- See also the
|
||||
[developer documentation on tree constructors](../../../developer/trees.md#constructors-and-destructors).
|
||||
|
||||
<!-- TODO: add links to RectangleTree above when it is documented -->
|
||||
|
||||
---
|
||||
|
||||
### Constructor parameters:
|
||||
|
||||
| **name** | **type** | **description** | **default** |
|
||||
|----------|----------|-----------------|-------------|
|
||||
| `data` | [`arma::mat`](../../matrices.md) | [Column-major](../../matrices.md#representing-data-in-mlpack) matrix to build the tree on. Pass with `std::move(data)` to avoid copying the matrix. | _(N/A)_ |
|
||||
| `maxLeafSize` | `size_t` | Maximum number of points to store in each leaf. | `20` |
|
||||
| `oldFromNew` | `std::vector<size_t>` | Mappings from points in `node.Dataset()` to points in `data`. | _(N/A)_ |
|
||||
| `newFromOld` | `std::vector<size_t>` | Mappings from points in `data` to points in `node.Dataset()`. | _(N/A)_ |
|
||||
|
||||
## Basic tree properties
|
||||
|
||||
Once an `RPTree` object is constructed, various properties of the tree can be
|
||||
accessed or inspected. Many of these functions are required by the [TreeType
|
||||
API](../../../developer/trees.md#the-treetype-api).
|
||||
|
||||
### Navigating the tree
|
||||
|
||||
* `node.NumChildren()` returns the number of children in `node`. This is
|
||||
either `2` if `node` has children, or `0` if `node` is a leaf.
|
||||
|
||||
* `node.IsLeaf()` returns a `bool` indicating whether or not `node` is a leaf.
|
||||
|
||||
* `node.Child(i)` returns an `RPTree&` that is the `i`th child.
|
||||
- `i` must be `0` or `1`.
|
||||
- This function should only be called if `node.NumChildren()` is not `0`
|
||||
(e.g. if `node` is not a leaf). Note that this returns a valid `RPTree&`
|
||||
that can itself be used just like the root node of the tree!
|
||||
- `node.Left()` and `node.Right()` are convenience functions specific to
|
||||
`RPTree` that will return `RPTree*` (pointers) to the left and right
|
||||
children, respectively, or `NULL` if `node` has no children.
|
||||
|
||||
* `node.Parent()` will return an `RPTree*` that points to the parent of `node`,
|
||||
or `NULL` if `node` is the root of the `RPTree`.
|
||||
|
||||
---
|
||||
|
||||
### Accessing members of a tree
|
||||
|
||||
* `node.Bound()` will return an
|
||||
[`HRectBound&`](binary_space_tree.md#hrectbound) object that represents the
|
||||
hyperrectangle bounding box of `node`. This is the smallest hyperrectangle
|
||||
that encloses all the descendant points of `node`.
|
||||
|
||||
* `node.Stat()` will return an `EmptyStatistic&` (or a `StatisticType&` if a
|
||||
[custom `StatisticType`](#template-parameters) was specified as a template
|
||||
parameter) holding the statistics of the node that were computed during tree
|
||||
construction.
|
||||
|
||||
* `node.Distance()` will return a
|
||||
[`EuclideanDistance&`](../distances.md#lmetric) (or a `DistanceType&` if a
|
||||
[custom `DistanceType`](#template-parameters) was specified as a template
|
||||
parameter).
|
||||
- This function is required by the
|
||||
[TreeType API](../../../developer/trees.md#the-treetype-api), but given
|
||||
that `RPTree` requires an [`LMetric`](../distances.md#lmetric) to be used,
|
||||
and `LMetric` only has `static` functions and holds no state, this function
|
||||
is not likely to be useful.
|
||||
|
||||
See also the
|
||||
[developer documentation](../../../developer/trees.md#basic-tree-functionality)
|
||||
for basic tree functionality in mlpack.
|
||||
|
||||
---
|
||||
|
||||
### Accessing data held in a tree
|
||||
|
||||
* `node.Dataset()` will return a `const arma::mat&` that is the dataset the
|
||||
tree was built on. Note that this is a permuted version of the `data` matrix
|
||||
passed to the constructor.
|
||||
- If a [custom `MatType`](#template-parameters) is being used, the return
|
||||
type will be `const MatType&` instead of `const arma::mat&`.
|
||||
|
||||
* `node.NumPoints()` returns a `size_t` indicating the number of points held
|
||||
directly in `node`.
|
||||
- If `node` is not a leaf, this will return `0`, as `RPTree` only holds
|
||||
points directly in its leaves.
|
||||
- If `node` is a leaf, then the number of points will be less than or equal
|
||||
to the `maxLeafSize` that was specified when the tree was constructed.
|
||||
|
||||
* `node.Point(i)` returns a `size_t` indicating the index of the `i`'th point
|
||||
in `node.Dataset()`.
|
||||
- `i` must be in the range `[0, node.NumPoints() - 1]` (inclusive).
|
||||
- `node` must be a leaf (as non-leaves do not hold any points).
|
||||
- The `i`'th point in `node` can then be accessed as
|
||||
`node.Dataset().col(node.Point(i))`.
|
||||
- In an `RPTree`, because of the permutation of points done [during
|
||||
construction](#constructors), point indices are contiguous:
|
||||
`node.Point(i + j)` is the same as `node.Point(i) + j` for valid `i` and
|
||||
`j`.
|
||||
- Accessing the actual `i`'th point itself can be done with, e.g.,
|
||||
`node.Dataset().col(node.Point(i))`.
|
||||
|
||||
* `node.NumDescendants()` returns a `size_t` indicating the number of points
|
||||
held in all descendant leaves of `node`.
|
||||
- If `node` is the root of the tree, then `node.NumDescendants()` will be
|
||||
equal to `node.Dataset().n_cols`.
|
||||
|
||||
* `node.Descendant(i)` returns a `size_t` indicating the index of the `i`'th
|
||||
descendant point in `node.Dataset()`.
|
||||
- `i` must be in the range `[0, node.NumDescendants() - 1]` (inclusive).
|
||||
- `node` does not need to be a leaf.
|
||||
- The `i`'th descendant point in `node` can then be accessed as
|
||||
`node.Dataset().col(node.Descendant(i))`.
|
||||
- In an `RPTree`, because of the permutation of points done [during
|
||||
construction](#constructors), point indices are contiguous:
|
||||
`node.Descendant(i + j)` is the same as `node.Descendant(i) + j` for valid
|
||||
`i` and `j`.
|
||||
- Accessing the actual `i`'th descendant itself can be done with, e.g.,
|
||||
`node.Dataset().col(node.Descendant(i))`.
|
||||
|
||||
* `node.Begin()` returns a `size_t` indicating the index of the first
|
||||
descendant point of `node`.
|
||||
- This is equivalent to `node.Descendant(0)`.
|
||||
|
||||
* `node.Count()` returns a `size_t` indicating the number of descendant points of `node`.
|
||||
- This is equivalent to `node.NumDescendants()`.
|
||||
|
||||
---
|
||||
|
||||
### Accessing computed bound quantities of a tree
|
||||
|
||||
The following quantities are cached for each node in an `RPTree`, and so
|
||||
accessing them does not require any computation.
|
||||
|
||||
* `node.FurthestPointDistance()` returns a `double` representing the distance
|
||||
between the center of the bounding hyperrectangle of `node` and the furthest
|
||||
point held by `node`.
|
||||
- If `node` is not a leaf, this returns 0 (because `node` does not hold any
|
||||
points).
|
||||
|
||||
* `node.FurthestDescendantDistance()` returns a `double` representing the
|
||||
distance between the center of the bounding hyperrectangle of `node` and the
|
||||
furthest descendant point held by `node`.
|
||||
|
||||
* `node.MinimumBoundDistance()` returns a `double` representing minimum
|
||||
possible distance from the center of the node to any edge of the
|
||||
hyperrectangle bound.
|
||||
- This quantity is half the width of the smallest dimension of
|
||||
`node.Bound()`.
|
||||
|
||||
* `node.ParentDistance()` returns a `double` representing the distance between
|
||||
the center of the bounding hyperrectangle of `node` and the center of the
|
||||
bounding hyperrectangle of its parent.
|
||||
- If `node` is the root of the tree, `0` is returned.
|
||||
|
||||
***Notes:***
|
||||
|
||||
- If a [custom `MatType`](#template-parameters) was specified when constructing
|
||||
the `RPTree`, then the return type of each method is the element type of the
|
||||
given `MatType` instead of `double`. (e.g., if `MatType` is `arma::fmat`,
|
||||
then the return type is `float`.)
|
||||
|
||||
- For more details on each bound quantity, see the
|
||||
[developer documentation](../../../developer/trees.md#complex-tree-functionality-and-bounds)
|
||||
on bound quantities for trees.
|
||||
|
||||
---
|
||||
|
||||
### Other functionality
|
||||
|
||||
* `node.Center(center)` computes the center of the bounding hyperrectangle of
|
||||
`node` and stores it in `center`.
|
||||
- `center` should be of type `arma::vec&`. (If a [custom
|
||||
`MatType`](#template-parameters) was specified when constructing the
|
||||
`RPTree`, the type is instead the column vector type for the given
|
||||
`MatType`; e.g., `arma::fvec&` when `MatType` is `arma::fmat`.)
|
||||
- `center` will be set to have size equivalent to the dimensionality of the
|
||||
dataset held by `node`.
|
||||
- This is equivalent to calling `node.Bound().Center(center)`.
|
||||
|
||||
* A `RPTree` can be serialized with
|
||||
[`data::Save()` and `data::Load()`](../../load_save.md#mlpack-objects).
|
||||
|
||||
## Bounding distances with the tree
|
||||
|
||||
The primary use of trees in mlpack is bounding distances to points or other tree
|
||||
nodes. The following functions can be used for these tasks.
|
||||
|
||||
* `node.GetNearestChild(point)`
|
||||
* `node.GetFurthestChild(point)`
|
||||
- Return a `size_t` indicating the index of the child (`0` for left, `1` for
|
||||
right) that is closest to (or furthest from) `point`, with respect
|
||||
to the `MinDistance()` (or `MaxDistance()`) function.
|
||||
- If there is a tie, `0` (the left child) is returned.
|
||||
- If `node` is a leaf, `0` is returned.
|
||||
- `point` should be of type `arma::vec`. (If a [custom
|
||||
`MatType`](#template-parameters) was specified when constructing the
|
||||
`RPTree`, the type is instead the column vector type for the given
|
||||
`MatType`; e.g., `arma::fvec` when `MatType` is `arma::fmat`.)
|
||||
|
||||
* `node.GetNearestChild(other)`
|
||||
* `node.GetFurthestChild(other)`
|
||||
- Return a `size_t` indicating the index of the child (`0` for left, `1` for
|
||||
right) that is closest to (or furthest from) the `RPTree` node `other`,
|
||||
with respect to the `MinDistance()` (or `MaxDistance()`) function.
|
||||
- If there is a tie, `2` (an invalid index) is returned. ***Note that this
|
||||
behavior differs from the version above that takes a point.***
|
||||
- If `node` is a leaf, `0` is returned.
|
||||
|
||||
---
|
||||
|
||||
* `node.MinDistance(point)`
|
||||
* `node.MinDistance(other)`
|
||||
- Return a `double` indicating the minimum possible distance between `node`
|
||||
and `point`, or the `RPTree` node `other`.
|
||||
- This is equivalent to the minimum possible distance between any point
|
||||
contained in the bounding hyperrectangle of `node` and `point`, or between
|
||||
any point contained in the bounding hyperrectangle of `node` and any point
|
||||
contained in the bounding hyperrectangle of `other`.
|
||||
- `point` should be of type `arma::vec`. (If a [custom
|
||||
`MatType`](#template-parameters) was specified when constructing the
|
||||
`RPTree`, the type is instead the column vector type for the given
|
||||
`MatType`, and the return type is the element type of `MatType`; e.g.,
|
||||
`point` should be `arma::fvec` when `MatType` is `arma::fmat`, and the
|
||||
returned distance is `float`).
|
||||
|
||||
* `node.MaxDistance(point)`
|
||||
* `node.MaxDistance(other)`
|
||||
- Return a `double` indicating the maximum possible distance between `node`
|
||||
and `point`, or the `RPTree` node `other`.
|
||||
- This is equivalent to the maximum possible distance between any point
|
||||
contained in the bounding hyperrectangle of `node` and `point`, or between
|
||||
any point contained in the bounding hyperrectangle of `node` and any point
|
||||
contained in the bounding hyperrectangle of `other`.
|
||||
- `point` should be of type `arma::vec`. (If a [custom
|
||||
`MatType`](#template-parameters) was specified when constructing the
|
||||
`RPTree`, the type is instead the column vector type for the given
|
||||
`MatType`, and the return type is the element type of `MatType`; e.g.,
|
||||
`point` should be `arma::fvec` when `MatType` is `arma::fmat`, and the
|
||||
returned distance is `float`).
|
||||
|
||||
* `node.RangeDistance(point)`
|
||||
* `node.RangeDistance(other)`
|
||||
- Return a [`Range`](../math.md#range) whose lower bound is
|
||||
`node.MinDistance(point)` or `node.MinDistance(other)`, and whose upper
|
||||
bound is `node.MaxDistance(point)` or `node.MaxDistance(other)`.
|
||||
- `point` should be of type `arma::vec`. (If a
|
||||
[custom `MatType`](#template-parameters) was specified when constructing
|
||||
the `RPTree`, the type is instead the column vector type for the given
|
||||
`MatType`, and the return type is a `RangeType` with element type the same
|
||||
as `MatType`; e.g., `point` should be `arma::fvec` when `MatType` is
|
||||
`arma::fmat`, and the returned type is
|
||||
[`RangeType<float>`](../math.md#range)).
|
||||
|
||||
### Tree traversals
|
||||
|
||||
Like every mlpack tree, the `RPTree` class provides a [single-tree and dual-tree
|
||||
traversal](../../../developer/trees.md#traversals) that can be paired with a
|
||||
[`RuleType` class](../../../developer/trees.md#rules) to implement a single-tree
|
||||
or dual-tree algorithm.
|
||||
|
||||
* `RPTree::SingleTreeTraverser`
|
||||
- Implements a depth-first single-tree traverser.
|
||||
|
||||
* `RPTree::DualTreeTraverser`
|
||||
- Implements a dual-depth-first dual-tree traverser.
|
||||
|
||||
In addition to those two classes, which are required by the
|
||||
[`TreeType` policy](../../../developer/trees.md), an additional traverser is
|
||||
available:
|
||||
|
||||
* `RPTree::BreadthFirstDualTreeTraverser`
|
||||
- Implements a dual-breadth-first dual-tree traverser.
|
||||
- ***Note:*** this traverser is not useful for all tasks; because the
|
||||
`RPTree` only holds points in the leaves, this means that no base cases
|
||||
(e.g. comparisons between points) will be called until *all* pairs of
|
||||
intermediate nodes have been scored!
|
||||
|
||||
## Example usage
|
||||
|
||||
Build an `RPTree` on the `cloud` dataset and print basic statistics about the
|
||||
tree.
|
||||
|
||||
```c++
|
||||
// See https://datasets.mlpack.org/cloud.csv.
|
||||
arma::mat dataset;
|
||||
mlpack::data::Load("cloud.csv", dataset, true);
|
||||
|
||||
// Build the random projection tree with a leaf size of 10. (This means that
|
||||
// nodes are split until they contain 10 or fewer points.)
|
||||
//
|
||||
// The std::move() means that `dataset` will be empty after this call, and no
|
||||
// data will be copied during tree building.
|
||||
//
|
||||
// Note that the '<>' isn't necessary if C++20 is being used (e.g.
|
||||
// `mlpack::RPTree tree(...)` will work fine in C++20 or newer).
|
||||
mlpack::RPTree<> tree(std::move(dataset));
|
||||
|
||||
// Print the bounding box of the root node.
|
||||
std::cout << "Bounding box of root node:" << std::endl;
|
||||
for (size_t i = 0; i < tree.Bound().Dim(); ++i)
|
||||
{
|
||||
std::cout << " - Dimension " << i << ": [" << tree.Bound()[i].Lo() << ", "
|
||||
<< tree.Bound()[i].Hi() << "]." << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
// Print the number of descendant points of the root, and of each of its
|
||||
// children.
|
||||
std::cout << "Descendant points of root: "
|
||||
<< tree.NumDescendants() << "." << std::endl;
|
||||
std::cout << "Descendant points of left child: "
|
||||
<< tree.Left()->NumDescendants() << "." << std::endl;
|
||||
std::cout << "Descendant points of right child: "
|
||||
<< tree.Right()->NumDescendants() << "." << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
// Compute the center of the rp-tree.
|
||||
arma::vec center;
|
||||
tree.Center(center);
|
||||
std::cout << "Center of random projection tree: " << center.t();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Build two `RPTree`s on subsets of the corel dataset and compute minimum and
|
||||
maximum distances between different nodes in the tree.
|
||||
|
||||
```c++
|
||||
// See https://datasets.mlpack.org/corel-histogram.csv.
|
||||
arma::mat dataset;
|
||||
mlpack::data::Load("corel-histogram.csv", dataset, true);
|
||||
|
||||
// Build rp-trees on the first half and the second half of points.
|
||||
mlpack::RPTree<> tree1(dataset.cols(0, dataset.n_cols / 2));
|
||||
mlpack::RPTree<> tree2(dataset.cols(dataset.n_cols / 2 + 1,
|
||||
dataset.n_cols - 1));
|
||||
|
||||
// Compute the maximum distance between the trees.
|
||||
std::cout << "Maximum distance between tree root nodes: "
|
||||
<< tree1.MaxDistance(tree2) << "." << std::endl;
|
||||
|
||||
// Get the leftmost grandchild of the first tree's root---if it exists.
|
||||
if (!tree1.IsLeaf() && !tree1.Child(0).IsLeaf())
|
||||
{
|
||||
mlpack::RPTree<>& node1 = tree1.Child(0).Child(0);
|
||||
|
||||
// Get the rightmost grandchild of the second tree's root---if it exists.
|
||||
if (!tree2.IsLeaf() && !tree2.Child(1).IsLeaf())
|
||||
{
|
||||
mlpack::RPTree<>& node2 = tree2.Child(1).Child(1);
|
||||
|
||||
// Print the minimum and maximum distance between the nodes.
|
||||
mlpack::Range dists = node1.RangeDistance(node2);
|
||||
std::cout << "Possible distances between two grandchild nodes: ["
|
||||
<< dists.Lo() << ", " << dists.Hi() << "]." << std::endl;
|
||||
|
||||
// Print the minimum distance between the first node and the first
|
||||
// descendant point of the second node.
|
||||
const size_t descendantIndex = node2.Descendant(0);
|
||||
const double descendantMinDist =
|
||||
node1.MinDistance(node2.Dataset().col(descendantIndex));
|
||||
std::cout << "Minimum distance between grandchild node and descendant "
|
||||
<< "point: " << descendantMinDist << "." << std::endl;
|
||||
|
||||
// Which child of node2 is closer to node1?
|
||||
const size_t closerIndex = node2.GetNearestChild(node1);
|
||||
if (closerIndex == 0)
|
||||
std::cout << "The left child of node2 is closer to node1." << std::endl;
|
||||
else if (closerIndex == 1)
|
||||
std::cout << "The right child of node2 is closer to node1." << std::endl;
|
||||
else // closerIndex == 2 in this case.
|
||||
std::cout << "Both children of node2 are equally close to node1."
|
||||
<< std::endl;
|
||||
|
||||
// And which child of node1 is further from node2?
|
||||
const size_t furtherIndex = node1.GetFurthestChild(node2);
|
||||
if (furtherIndex == 0)
|
||||
std::cout << "The left child of node1 is further from node2."
|
||||
<< std::endl;
|
||||
else if (furtherIndex == 1)
|
||||
std::cout << "The right child of node1 is further from node2."
|
||||
<< std::endl;
|
||||
else // furtherIndex == 2 in this case.
|
||||
std::cout << "Both children of node1 are equally far from node2."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Build an `RPTree` on 32-bit floating point data and save it to disk.
|
||||
|
||||
```c++
|
||||
// See https://datasets.mlpack.org/corel-histogram.csv.
|
||||
arma::fmat dataset;
|
||||
mlpack::data::Load("corel-histogram.csv", dataset);
|
||||
|
||||
// Build the RPTree using 32-bit floating point data as the matrix type.
|
||||
// We will still use the default EmptyStatistic and EuclideanDistance
|
||||
// parameters. A leaf size of 100 is used here.
|
||||
mlpack::RPTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat> tree(std::move(dataset), 100);
|
||||
|
||||
// Save the RPTree to disk with the name 'tree'.
|
||||
mlpack::data::Save("tree.bin", "tree", tree);
|
||||
|
||||
std::cout << "Saved tree with " << tree.Dataset().n_cols << " points to "
|
||||
<< "'tree.bin'." << std::endl;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Load a 32-bit floating point `RPTree` from disk, then traverse it manually and
|
||||
find the number of leaf nodes with fewer than 10 points.
|
||||
|
||||
```c++
|
||||
// This assumes the tree has already been saved to 'tree.bin' (as in the example
|
||||
// above).
|
||||
|
||||
// This convenient typedef saves us a long type name!
|
||||
using TreeType = mlpack::RPTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat>;
|
||||
|
||||
TreeType tree;
|
||||
mlpack::data::Load("tree.bin", "tree", tree);
|
||||
std::cout << "Tree loaded with " << tree.NumDescendants() << " points."
|
||||
<< std::endl;
|
||||
|
||||
// Recurse in a depth-first manner. Count both the total number of leaves, and
|
||||
// the number of leaves with fewer than 10 points.
|
||||
size_t leafCount = 0;
|
||||
size_t totalLeafCount = 0;
|
||||
std::stack<TreeType*> stack;
|
||||
stack.push(&tree);
|
||||
while (!stack.empty())
|
||||
{
|
||||
TreeType* node = stack.top();
|
||||
stack.pop();
|
||||
|
||||
if (node->NumPoints() < 10)
|
||||
++leafCount;
|
||||
++totalLeafCount;
|
||||
|
||||
if (!node->IsLeaf())
|
||||
{
|
||||
stack.push(node->Left());
|
||||
stack.push(node->Right());
|
||||
}
|
||||
}
|
||||
|
||||
// Note that it would be possible to use TreeType::SingleTreeTraverser to
|
||||
// perform the recursion above, but that is more well-suited for more complex
|
||||
// tasks that require pruning and other non-trivial behavior; so using a simple
|
||||
// stack is the better option here.
|
||||
|
||||
// Print the results.
|
||||
std::cout << leafCount << " out of " << totalLeafCount << " leaves have fewer "
|
||||
<< "than 10 points." << std::endl;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Build an `RPTree` and map between original points and new points.
|
||||
|
||||
```c++
|
||||
// See https://datasets.mlpack.org/cloud.csv.
|
||||
arma::mat dataset;
|
||||
mlpack::data::Load("cloud.csv", dataset, true);
|
||||
|
||||
// Build the tree.
|
||||
std::vector<size_t> oldFromNew, newFromOld;
|
||||
mlpack::RPTree<> tree(dataset, oldFromNew, newFromOld);
|
||||
|
||||
// oldFromNew and newFromOld will be set to the same size as the dataset.
|
||||
std::cout << "Number of points in dataset: " << dataset.n_cols << "."
|
||||
<< std::endl;
|
||||
std::cout << "Size of oldFromNew: " << oldFromNew.size() << "." << std::endl;
|
||||
std::cout << "Size of newFromOld: " << newFromOld.size() << "." << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
// See where point 42 in the tree's dataset came from.
|
||||
std::cout << "Point 42 in the permuted tree's dataset:" << std::endl;
|
||||
std::cout << " " << tree.Dataset().col(42).t();
|
||||
std::cout << "Was originally point " << oldFromNew[42] << ":" << std::endl;
|
||||
std::cout << " " << dataset.col(oldFromNew[42]).t();
|
||||
std::cout << std::endl;
|
||||
|
||||
// See where point 7 in the original dataset was mapped.
|
||||
std::cout << "Point 7 in original dataset:" << std::endl;
|
||||
std::cout << " " << dataset.col(7).t();
|
||||
std::cout << "Mapped to point " << newFromOld[7] << ":" << std::endl;
|
||||
std::cout << " " << tree.Dataset().col(newFromOld[7]).t();
|
||||
```
|
||||
@@ -558,9 +558,9 @@ find the number of leaf nodes with less than 10 children.
|
||||
// above).
|
||||
|
||||
// This convenient typedef saves us a long type name!
|
||||
typedef mlpack::VPTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat> TreeType;
|
||||
using TreeType = mlpack::VPTree<mlpack::EuclideanDistance,
|
||||
mlpack::EmptyStatistic,
|
||||
arma::fmat>;
|
||||
|
||||
TreeType tree;
|
||||
mlpack::data::Load("tree.bin", "tree", tree);
|
||||
|
||||
@@ -256,10 +256,10 @@ arma::Row<size_t> labels =
|
||||
|
||||
// Train in the constructor, using floating-point data.
|
||||
// The weak learner type is now a floating-point Perceptron.
|
||||
typedef mlpack::Perceptron<
|
||||
using PerceptronType = mlpack::Perceptron<
|
||||
mlpack::SimpleWeightUpdate,
|
||||
mlpack::ZeroInitialization,
|
||||
arma::fmat> PerceptronType;
|
||||
arma::fmat>;
|
||||
mlpack::AdaBoost<PerceptronType, arma::fmat> ab(dataset, labels, 5);
|
||||
|
||||
// Create test data (500 points).
|
||||
|
||||
@@ -418,9 +418,9 @@ arma::Row<size_t> labels =
|
||||
|
||||
// Train in the constructor, using floating-point data.
|
||||
// The weak learner type is now a floating-point Perceptron.
|
||||
typedef mlpack::Perceptron<mlpack::SimpleWeightUpdate,
|
||||
mlpack::ZeroInitialization,
|
||||
arma::fmat> PerceptronType;
|
||||
using PerceptronType = mlpack::Perceptron<mlpack::SimpleWeightUpdate,
|
||||
mlpack::ZeroInitialization,
|
||||
arma::fmat>;
|
||||
mlpack::AdaBoost<PerceptronType, arma::fmat> ab(dataset, labels, 5);
|
||||
|
||||
// Create test data (500 points).
|
||||
|
||||
@@ -659,8 +659,9 @@ mlpack::RandomAcolInitialization<5> initW;
|
||||
mlpack::RandomAMFInitialization initH;
|
||||
|
||||
// Combine the two initializations so we can pass it to the AMF class.
|
||||
typedef mlpack::MergeInitialization<mlpack::RandomAcolInitialization<5>,
|
||||
mlpack::RandomAMFInitialization> InitType;
|
||||
using InitType =
|
||||
mlpack::MergeInitialization<mlpack::RandomAcolInitialization<5>,
|
||||
mlpack::RandomAMFInitialization>;
|
||||
InitType init(initW, initH);
|
||||
|
||||
// Create an AMF object with the custom initialization.
|
||||
|
||||
@@ -35,7 +35,7 @@ void PrintR(util::Params& params,
|
||||
const util::BindingDetails& doc = params.Doc();
|
||||
|
||||
map<string, util::ParamData>& parameters = params.Parameters();
|
||||
typedef map<string, util::ParamData>::iterator ParamIter;
|
||||
using ParamIter = map<string, util::ParamData>::iterator;
|
||||
|
||||
// First, let's get a list of input and output options. We'll take two passes
|
||||
// so that the required input options are the first in the list.
|
||||
|
||||
@@ -195,7 +195,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */)
|
||||
// All numeric elements should be multiplied by 3.
|
||||
if (params.Has("matrix_and_info_in"))
|
||||
{
|
||||
typedef tuple<data::DatasetInfo, arma::mat> TupleType;
|
||||
using TupleType = tuple<data::DatasetInfo, arma::mat>;
|
||||
TupleType tuple = std::move(params.Get<TupleType>("matrix_and_info_in"));
|
||||
|
||||
const data::DatasetInfo& di = std::get<0>(tuple);
|
||||
|
||||
@@ -42,7 +42,7 @@ void DeleteAllocatedMemoryImpl(
|
||||
const std::enable_if_t<data::HasSerialize<T>::value>* = 0)
|
||||
{
|
||||
// Delete the allocated memory (hopefully we actually own it).
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
using TupleType = std::tuple<T*, std::string>;
|
||||
delete std::get<0>(*std::any_cast<TupleType>(&d.value));
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ void* GetAllocatedMemory(
|
||||
{
|
||||
// Here we have a model, which is a tuple, and we need the address of the
|
||||
// memory.
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
using TupleType = std::tuple<T*, std::string>;
|
||||
return std::get<0>(*std::any_cast<TupleType>(&d.value));
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ T& GetParam(
|
||||
// contains the filename. It's possible we could load empty matrices many
|
||||
// times, but I am not bothered by that---it shouldn't be something that
|
||||
// happens.
|
||||
typedef std::tuple<T, typename ParameterType<T>::type> TupleType;
|
||||
using TupleType = std::tuple<T, typename ParameterType<T>::type>;
|
||||
TupleType& tuple = *std::any_cast<TupleType>(&d.value);
|
||||
const std::string& value = std::get<0>(std::get<1>(tuple));
|
||||
T& matrix = std::get<0>(tuple);
|
||||
@@ -85,7 +85,7 @@ T& GetParam(
|
||||
{
|
||||
// If this is an input parameter, we need to load both the matrix and the
|
||||
// dataset info.
|
||||
typedef std::tuple<T, std::tuple<std::string, size_t, size_t>> TupleType;
|
||||
using TupleType = std::tuple<T, std::tuple<std::string, size_t, size_t>>;
|
||||
TupleType* tuple = std::any_cast<TupleType>(&d.value);
|
||||
const std::string& value = std::get<0>(std::get<1>(*tuple));
|
||||
T& t = std::get<0>(*tuple);
|
||||
@@ -115,7 +115,7 @@ T*& GetParam(
|
||||
{
|
||||
// If the model is an input model, we have to load it from file. 'value'
|
||||
// contains the filename.
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
using TupleType = std::tuple<T*, std::string>;
|
||||
TupleType* tuple = std::any_cast<TupleType>(&d.value);
|
||||
const std::string& value = std::get<1>(*tuple);
|
||||
if (d.input && !d.loaded)
|
||||
|
||||
@@ -77,7 +77,7 @@ std::string GetPrintableParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>>* /* junk */)
|
||||
{
|
||||
// Extract the string from the tuple that's being held.
|
||||
typedef std::tuple<T, typename ParameterType<T>::type> TupleType;
|
||||
using TupleType = std::tuple<T, typename ParameterType<T>::type>;
|
||||
const TupleType* tuple = std::any_cast<TupleType>(&data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
@@ -105,7 +105,7 @@ std::string GetPrintableParam(
|
||||
const std::enable_if_t<data::HasSerialize<T>::value>*)
|
||||
{
|
||||
// Extract the string from the tuple that's being held.
|
||||
typedef std::tuple<T*, typename ParameterType<T>::type> TupleType;
|
||||
using TupleType = std::tuple<T*, typename ParameterType<T>::type>;
|
||||
const TupleType* tuple = std::any_cast<TupleType>(&data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
|
||||
@@ -48,7 +48,7 @@ T& GetRawParam(
|
||||
arma::mat>>>* = 0)
|
||||
{
|
||||
// Don't load the matrix.
|
||||
typedef std::tuple<T, std::tuple<std::string, size_t, size_t>> TupleType;
|
||||
using TupleType = std::tuple<T, std::tuple<std::string, size_t, size_t>>;
|
||||
T& value = std::get<0>(*std::any_cast<TupleType>(&d.value));
|
||||
return value;
|
||||
}
|
||||
@@ -63,7 +63,7 @@ T*& GetRawParam(
|
||||
const std::enable_if_t<data::HasSerialize<T>::value>* = 0)
|
||||
{
|
||||
// Don't load the model.
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
using TupleType = std::tuple<T*, std::string>;
|
||||
T*& value = std::get<0>(*std::any_cast<TupleType>(&d.value));
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ void InPlaceCopyInternal(
|
||||
= 0)
|
||||
{
|
||||
// Make the output filename the same as the input filename.
|
||||
typedef std::tuple<T, typename ParameterType<T>::type> TupleType;
|
||||
using TupleType = std::tuple<T, typename ParameterType<T>::type>;
|
||||
TupleType& tuple = *std::any_cast<TupleType>(&d.value);
|
||||
std::string& value = std::get<0>(std::get<1>(tuple));
|
||||
|
||||
@@ -78,7 +78,7 @@ void InPlaceCopyInternal(
|
||||
const std::enable_if_t<data::HasSerialize<T>::value>* = 0)
|
||||
{
|
||||
// Make the output filename the same as the input filename.
|
||||
typedef std::tuple<T*, typename ParameterType<T>::type> TupleType;
|
||||
using TupleType = std::tuple<T*, typename ParameterType<T>::type>;
|
||||
TupleType& tuple = *std::any_cast<TupleType>(&d.value);
|
||||
std::string& value = std::get<1>(tuple);
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ void OutputParamImpl(
|
||||
util::ParamData& data,
|
||||
const std::enable_if_t<arma::is_arma_type<T>::value>*)
|
||||
{
|
||||
typedef std::tuple<T, std::tuple<std::string, size_t, size_t>> TupleType;
|
||||
using TupleType = std::tuple<T, std::tuple<std::string, size_t, size_t>>;
|
||||
const T& output = std::get<0>(*std::any_cast<TupleType>(&data.value));
|
||||
const std::string& filename =
|
||||
std::get<0>(std::get<1>(*std::any_cast<TupleType>(&data.value)));
|
||||
@@ -77,7 +77,7 @@ void OutputParamImpl(
|
||||
// The const cast is necessary here because Serialize() can't ever be marked
|
||||
// const. In this case we can assume it though, since we will be saving and
|
||||
// not loading.
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
using TupleType = std::tuple<T*, std::string>;
|
||||
T*& output = const_cast<T*&>(std::get<0>(*std::any_cast<TupleType>(
|
||||
&data.value)));
|
||||
const std::string& filename =
|
||||
@@ -95,7 +95,7 @@ void OutputParamImpl(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>>* /* junk */)
|
||||
{
|
||||
// Output the matrix with the mappings.
|
||||
typedef std::tuple<T, std::tuple<std::string, size_t, size_t>> TupleType;
|
||||
using TupleType = std::tuple<T, std::tuple<std::string, size_t, size_t>>;
|
||||
const T& tuple = std::get<0>(*std::any_cast<TupleType>(&data.value));
|
||||
const std::string& filename =
|
||||
std::get<0>(std::get<1>(*std::any_cast<TupleType>(&data.value)));
|
||||
|
||||
@@ -23,14 +23,14 @@ namespace cli {
|
||||
template<bool HasSerialize, typename T>
|
||||
struct ParameterTypeDeducer
|
||||
{
|
||||
typedef T type;
|
||||
using type = T;
|
||||
};
|
||||
|
||||
// If we have a serialize() function, then the type is a string.
|
||||
template<typename T>
|
||||
struct ParameterTypeDeducer<true, T>
|
||||
{
|
||||
typedef std::string type;
|
||||
using type = std::string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -41,8 +41,8 @@ struct ParameterTypeDeducer<true, T>
|
||||
template<typename T>
|
||||
struct ParameterType
|
||||
{
|
||||
typedef typename ParameterTypeDeducer<data::HasSerialize<T>::value, T>::type
|
||||
type;
|
||||
using type =
|
||||
typename ParameterTypeDeducer<data::HasSerialize<T>::value, T>::type;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -53,7 +53,7 @@ struct ParameterType
|
||||
template<typename eT>
|
||||
struct ParameterType<arma::Col<eT>>
|
||||
{
|
||||
typedef std::tuple<std::string, size_t, size_t> type;
|
||||
using type = std::tuple<std::string, size_t, size_t>;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -65,7 +65,7 @@ struct ParameterType<arma::Col<eT>>
|
||||
template<typename eT>
|
||||
struct ParameterType<arma::Row<eT>>
|
||||
{
|
||||
typedef std::tuple<std::string, size_t, size_t> type;
|
||||
using type = std::tuple<std::string, size_t, size_t>;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -76,7 +76,7 @@ struct ParameterType<arma::Row<eT>>
|
||||
template<typename eT>
|
||||
struct ParameterType<arma::Mat<eT>>
|
||||
{
|
||||
typedef std::tuple<std::string, size_t, size_t> type;
|
||||
using type = std::tuple<std::string, size_t, size_t>;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -86,7 +86,7 @@ template<typename eT, typename PolicyType>
|
||||
struct ParameterType<std::tuple<mlpack::data::DatasetMapper<PolicyType,
|
||||
std::string>, arma::Mat<eT>>>
|
||||
{
|
||||
typedef std::tuple<std::string, size_t, size_t> type;
|
||||
using type = std::tuple<std::string, size_t, size_t>;
|
||||
};
|
||||
|
||||
} // namespace cli
|
||||
|
||||
@@ -62,7 +62,7 @@ void SetParam(
|
||||
std::tuple<data::DatasetInfo, arma::mat>>>* = 0)
|
||||
{
|
||||
// We're setting the string filename.
|
||||
typedef std::tuple<T, typename ParameterType<T>::type> TupleType;
|
||||
using TupleType = std::tuple<T, typename ParameterType<T>::type>;
|
||||
TupleType& tuple = *std::any_cast<TupleType>(&d.value);
|
||||
std::get<0>(std::get<1>(tuple)) = std::any_cast<std::string>(value);
|
||||
}
|
||||
@@ -79,7 +79,7 @@ void SetParam(
|
||||
const std::enable_if_t<data::HasSerialize<T>::value>* = 0)
|
||||
{
|
||||
// We're setting the string filename.
|
||||
typedef std::tuple<T*, typename ParameterType<T>::type> TupleType;
|
||||
using TupleType = std::tuple<T*, typename ParameterType<T>::type>;
|
||||
TupleType& tuple = *std::any_cast<TupleType>(&d.value);
|
||||
std::get<1>(tuple) = std::any_cast<std::string>(value);
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ void mlpackToArmaMatWithInfo(void* params,
|
||||
int mlpackArmaMatWithInfoElements(void* params, const char* identifier)
|
||||
{
|
||||
util::Params& p = *((util::Params*) params);
|
||||
typedef std::tuple<data::DatasetInfo, arma::mat> TupleType;
|
||||
using TupleType = std::tuple<data::DatasetInfo, arma::mat>;
|
||||
return std::get<1>(p.Get<TupleType>(identifier)).n_elem;
|
||||
}
|
||||
|
||||
@@ -387,7 +387,7 @@ int mlpackArmaMatWithInfoElements(void* params, const char* identifier)
|
||||
int mlpackArmaMatWithInfoRows(void* params, const char* identifier)
|
||||
{
|
||||
util::Params& p = *((util::Params*) params);
|
||||
typedef std::tuple<data::DatasetInfo, arma::mat> TupleType;
|
||||
using TupleType = std::tuple<data::DatasetInfo, arma::mat>;
|
||||
return std::get<1>(p.Get<TupleType>(identifier)).n_rows;
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ int mlpackArmaMatWithInfoRows(void* params, const char* identifier)
|
||||
int mlpackArmaMatWithInfoCols(void* params, const char* identifier)
|
||||
{
|
||||
util::Params& p = *((util::Params*) params);
|
||||
typedef std::tuple<data::DatasetInfo, arma::mat> TupleType;
|
||||
using TupleType = std::tuple<data::DatasetInfo, arma::mat>;
|
||||
return std::get<1>(p.Get<TupleType>(identifier)).n_cols;
|
||||
}
|
||||
|
||||
@@ -408,7 +408,7 @@ int mlpackArmaMatWithInfoCols(void* params, const char* identifier)
|
||||
void* mlpackArmaPtrMatWithInfoPtr(void* params, const char* identifier)
|
||||
{
|
||||
util::Params& p = *((util::Params*) params);
|
||||
typedef std::tuple<data::DatasetInfo, arma::mat> TupleType;
|
||||
using TupleType = std::tuple<data::DatasetInfo, arma::mat>;
|
||||
arma::mat& m = std::get<1>(p.Get<TupleType>(identifier));
|
||||
if (m.is_empty())
|
||||
{
|
||||
|
||||
@@ -43,7 +43,7 @@ void PrintGo(util::Params& params,
|
||||
const std::string& bindingName)
|
||||
{
|
||||
std::map<std::string, util::ParamData>& parameters = params.Parameters();
|
||||
typedef std::map<std::string, util::ParamData>::iterator ParamIter;
|
||||
using ParamIter = std::map<std::string, util::ParamData>::iterator;
|
||||
|
||||
// Split into input and output parameters. Take two passes on the input
|
||||
// parameters, so that we get the required ones first.
|
||||
|
||||
@@ -191,7 +191,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timer */)
|
||||
// All numeric elements should be multiplied by 3.
|
||||
if (params.Has("matrix_and_info_in"))
|
||||
{
|
||||
typedef tuple<data::DatasetInfo, arma::mat> TupleType;
|
||||
using TupleType = tuple<data::DatasetInfo, arma::mat>;
|
||||
TupleType tuple = std::move(params.Get<TupleType>("matrix_and_info_in"));
|
||||
|
||||
const data::DatasetInfo& di = std::get<0>(tuple);
|
||||
|
||||
@@ -34,7 +34,7 @@ void PrintJL(const string& bindingName,
|
||||
const BindingDetails& doc = p.Doc();
|
||||
|
||||
map<string, ParamData>& parameters = p.Parameters();
|
||||
typedef map<string, ParamData>::iterator ParamIter;
|
||||
using ParamIter = map<string, ParamData>::iterator;
|
||||
|
||||
// First, let's get a list of input and output options. We'll take two passes
|
||||
// so that the required input options are the first in the list.
|
||||
|
||||
@@ -193,7 +193,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */)
|
||||
// All numeric elements should be multiplied by 3.
|
||||
if (params.Has("matrix_and_info_in"))
|
||||
{
|
||||
typedef tuple<data::DatasetInfo, arma::mat> TupleType;
|
||||
using TupleType = tuple<data::DatasetInfo, arma::mat>;
|
||||
TupleType tuple = std::move(params.Get<TupleType>("matrix_and_info_in"));
|
||||
|
||||
const data::DatasetInfo& di = std::get<0>(tuple);
|
||||
|
||||
@@ -89,8 +89,8 @@ inline void SetParamWithInfo(util::Params& params,
|
||||
T& matrix,
|
||||
const bool* dims)
|
||||
{
|
||||
typedef typename std::tuple<data::DatasetInfo, T> TupleType;
|
||||
typedef typename T::elem_type eT;
|
||||
using TupleType = std::tuple<data::DatasetInfo, T>;
|
||||
using eT = typename T::elem_type;
|
||||
|
||||
// The true type of the parameter is std::tuple<T, DatasetInfo>.
|
||||
const size_t dimensions = matrix.n_rows;
|
||||
@@ -149,7 +149,7 @@ T& GetParamWithInfo(util::Params& params,
|
||||
const std::string& paramName)
|
||||
{
|
||||
// T will be the Armadillo type.
|
||||
typedef std::tuple<data::DatasetInfo, T> TupleType;
|
||||
using TupleType = std::tuple<data::DatasetInfo, T>;
|
||||
return std::get<1>(params.Get<TupleType>(paramName));
|
||||
}
|
||||
|
||||
|
||||
@@ -302,7 +302,7 @@ void PrintOutputProcessing(util::ParamData& d,
|
||||
const void* input,
|
||||
void* /* output */)
|
||||
{
|
||||
typedef std::tuple<util::Params, std::tuple<size_t, bool>> TupleType;
|
||||
using TupleType = std::tuple<util::Params, std::tuple<size_t, bool>>;
|
||||
TupleType* tuple = (TupleType*) input;
|
||||
|
||||
PrintOutputProcessing<std::remove_pointer_t<T>>(
|
||||
|
||||
@@ -40,7 +40,7 @@ void PrintPYX(const util::BindingDetails& doc,
|
||||
util::Params params = IO::Parameters(bindingName);
|
||||
|
||||
std::map<std::string, util::ParamData>& parameters = params.Parameters();
|
||||
typedef std::map<std::string, util::ParamData>::iterator ParamIter;
|
||||
using ParamIter = std::map<std::string, util::ParamData>::iterator;
|
||||
|
||||
// Split into input and output parameters. Take two passes on the input
|
||||
// parameters, so that we get the required ones first.
|
||||
@@ -258,7 +258,7 @@ void PrintPYX(const util::BindingDetails& doc,
|
||||
cout << " result = {}" << endl;
|
||||
cout << endl;
|
||||
|
||||
typedef std::tuple<util::Params, std::tuple<size_t, bool>> TupleType;
|
||||
using TupleType = std::tuple<util::Params, std::tuple<size_t, bool>>;
|
||||
|
||||
for (size_t i = 0; i < outputOptions.size(); ++i)
|
||||
{
|
||||
|
||||
@@ -293,7 +293,7 @@ class TestPythonBinding(unittest.TestCase):
|
||||
"""
|
||||
Test a Pandas Series input paramter
|
||||
"""
|
||||
x = pd.Series(np.random.rand(100))
|
||||
x = pd.Series(np.random.rand(100))
|
||||
z = copy.deepcopy(x)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
@@ -313,7 +313,7 @@ class TestPythonBinding(unittest.TestCase):
|
||||
"""
|
||||
Test a Pandas Series input paramter
|
||||
"""
|
||||
x = pd.Series(np.random.rand(100))
|
||||
x = pd.Series(np.random.rand(100))
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
|
||||
@@ -235,7 +235,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timer */)
|
||||
// All numeric elements should be multiplied by 3.
|
||||
if (params.Has("matrix_and_info_in"))
|
||||
{
|
||||
typedef tuple<data::DatasetInfo, arma::mat> TupleType;
|
||||
using TupleType = tuple<data::DatasetInfo, arma::mat>;
|
||||
TupleType tuple = std::move(params.Get<TupleType>("matrix_and_info_in"));
|
||||
|
||||
const data::DatasetInfo& di = std::get<0>(tuple);
|
||||
|
||||
@@ -26,8 +26,8 @@ class TestFunctionMap
|
||||
{
|
||||
public:
|
||||
// Convenience typedef.
|
||||
typedef std::map<std::string, std::map<std::string,
|
||||
void (*)(util::ParamData&, const void*, void*)>> FunctionMapType;
|
||||
using FunctionMapType = std::map<std::string, std::map<std::string,
|
||||
void (*)(util::ParamData&, const void*, void*)>>;
|
||||
|
||||
//! Get the instantiated TestFunctionMap object.
|
||||
static TestFunctionMap& GetSingleton();
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace data {
|
||||
inline void CheckCategoricalParam(util::Params& params,
|
||||
const std::string& paramName)
|
||||
{
|
||||
typedef typename std::tuple<DatasetInfo, arma::mat> TupleType;
|
||||
using TupleType = std::tuple<DatasetInfo, arma::mat>;
|
||||
arma::mat& matrix = std::get<1>(params.Get<TupleType>(paramName));
|
||||
|
||||
// This comes from Params::CheckInputMatrix().
|
||||
|
||||
@@ -170,8 +170,8 @@ class DatasetMapper
|
||||
std::vector<Datatype> types;
|
||||
|
||||
// Forward mapping type.
|
||||
using ForwardMapType = typename std::unordered_map<InputType, typename
|
||||
PolicyType::MappedType>;
|
||||
using ForwardMapType = std::unordered_map<InputType,
|
||||
typename PolicyType::MappedType>;
|
||||
|
||||
// Reverse mapping type. Multiple inputs may map to a single output, hence
|
||||
// the need for std::vector.
|
||||
|
||||
@@ -160,8 +160,8 @@ void LoadARFF(const std::string& filename,
|
||||
}
|
||||
|
||||
// Make sure all strings are mapped, if we have any.
|
||||
typedef std::map<size_t, std::vector<std::string>>::const_iterator
|
||||
IteratorType;
|
||||
using IteratorType =
|
||||
std::map<size_t, std::vector<std::string>>::const_iterator;
|
||||
for (IteratorType it = categoryStrings.begin(); it != categoryStrings.end();
|
||||
++it)
|
||||
{
|
||||
|
||||
@@ -122,7 +122,7 @@ class IncrementPolicy
|
||||
if (numMappings == 0)
|
||||
types[dimension] = Datatype::categorical;
|
||||
|
||||
typedef typename std::pair<InputType, MappedType> PairType;
|
||||
using PairType = std::pair<InputType, MappedType>;
|
||||
maps[dimension].first.insert(PairType(input, numMappings));
|
||||
|
||||
// Do we need to create the second map?
|
||||
|
||||
@@ -112,7 +112,7 @@ class MissingPolicy
|
||||
maps[dimension].first.count(string) == 0)
|
||||
{
|
||||
// This string does not exist yet.
|
||||
typedef std::pair<std::string, MappedType> PairType;
|
||||
using PairType = std::pair<std::string, MappedType>;
|
||||
maps[dimension].first.insert(PairType(string, value));
|
||||
|
||||
// Insert right mapping too.
|
||||
|
||||
@@ -158,7 +158,7 @@ class TfIdfEncodingPolicy
|
||||
InverseDocumentFrequency<typename MatType::elem_type>(
|
||||
output.n_cols, numContainingStrings[value]);
|
||||
|
||||
output(value - 1, line) = tf * idf;
|
||||
output(value - 1, line) = tf * idf;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,7 +188,7 @@ class TfIdfEncodingPolicy
|
||||
const ElemType idf = InverseDocumentFrequency<ElemType>(
|
||||
output.size(), numContainingStrings[value]);
|
||||
|
||||
output[line][value - 1] = tf * idf;
|
||||
output[line][value - 1] = tf * idf;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -66,7 +66,7 @@ class IoUDistance
|
||||
static typename VecTypeA::elem_type Evaluate(const VecTypeA& a,
|
||||
const VecTypeB& b)
|
||||
{
|
||||
typedef typename VecTypeA::elem_type ElemType;
|
||||
using ElemType = typename VecTypeA::elem_type;
|
||||
|
||||
return (ElemType) (1.0 - IoU<UseCoordinates>::Evaluate(a, b));
|
||||
}
|
||||
|
||||
@@ -97,23 +97,23 @@ class LMetric
|
||||
/**
|
||||
* The Manhattan (L1) distance.
|
||||
*/
|
||||
typedef LMetric<1, false> ManhattanDistance;
|
||||
using ManhattanDistance = LMetric<1, false>;
|
||||
|
||||
/**
|
||||
* The squared Euclidean (L2) distance. Note that this is not technically a
|
||||
* metric! But it can sometimes be used when distances are required.
|
||||
*/
|
||||
typedef LMetric<2, false> SquaredEuclideanDistance;
|
||||
using SquaredEuclideanDistance = LMetric<2, false>;
|
||||
|
||||
/**
|
||||
* The Euclidean (L2) distance.
|
||||
*/
|
||||
typedef LMetric<2, true> EuclideanDistance;
|
||||
using EuclideanDistance = LMetric<2, true>;
|
||||
|
||||
/**
|
||||
* The L-infinity distance.
|
||||
*/
|
||||
typedef LMetric<INT_MAX, false> ChebyshevDistance;
|
||||
using ChebyshevDistance = LMetric<2147483647, false>;
|
||||
|
||||
|
||||
} // namespace mlpack
|
||||
|
||||
@@ -59,7 +59,7 @@ template<bool TakeRoot = true, typename MatType = arma::mat>
|
||||
class MahalanobisDistance
|
||||
{
|
||||
public:
|
||||
typedef typename GetColType<MatType>::type VecType;
|
||||
using VecType = typename GetColType<MatType>::type;
|
||||
|
||||
/**
|
||||
* Initialize the Mahalanobis distance with the empty matrix as Q.
|
||||
|
||||
@@ -22,8 +22,8 @@ class DiagonalGaussianDistribution
|
||||
{
|
||||
public:
|
||||
// Convenience typedefs.
|
||||
typedef typename GetColType<MatType>::type VecType;
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
using VecType = typename GetColType<MatType>::type;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
|
||||
private:
|
||||
//! Mean of the distribution.
|
||||
|
||||
@@ -54,10 +54,10 @@ class DiscreteDistribution
|
||||
{
|
||||
public:
|
||||
// Convenience typedefs.
|
||||
typedef typename GetColType<MatType>::type VecType;
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
typedef typename GetColType<ObsMatType>::type ObsVecType;
|
||||
typedef typename ObsMatType::elem_type ObsType;
|
||||
using VecType = typename GetColType<MatType>::type;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
using ObsVecType = typename GetColType<ObsMatType>::type;
|
||||
using ObsType = typename ObsMatType::elem_type;
|
||||
|
||||
/**
|
||||
* Default constructor, which creates a distribution that has no
|
||||
|
||||
@@ -54,8 +54,8 @@ class GammaDistribution
|
||||
{
|
||||
public:
|
||||
// Convenience typedefs.
|
||||
typedef typename GetColType<MatType>::type VecType;
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
using VecType = typename GetColType<MatType>::type;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
|
||||
/**
|
||||
* Construct the Gamma distribution with the given number of dimensions
|
||||
|
||||
@@ -25,8 +25,8 @@ class GaussianDistribution
|
||||
{
|
||||
public:
|
||||
// Convenience typedefs for derived types of MatType.
|
||||
typedef typename GetColType<MatType>::type VecType;
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
using VecType = typename GetColType<MatType>::type;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
|
||||
private:
|
||||
//! Mean of the distribution.
|
||||
|
||||
@@ -52,8 +52,8 @@ class LaplaceDistribution
|
||||
{
|
||||
public:
|
||||
// Convenience typedefs.
|
||||
typedef typename GetColType<MatType>::type VecType;
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
using VecType = typename GetColType<MatType>::type;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
|
||||
/**
|
||||
* Default constructor, which creates a Laplace distribution with zero
|
||||
|
||||
@@ -32,9 +32,9 @@ class RegressionDistribution
|
||||
{
|
||||
public:
|
||||
// Convenience typedefs.
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
typedef typename GetColType<MatType>::type VecType;
|
||||
typedef typename GetRowType<MatType>::type RowType;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
using VecType = typename GetColType<MatType>::type;
|
||||
using RowType = typename GetRowType<MatType>::type;
|
||||
|
||||
private:
|
||||
//! Regression function for representing conditional mean.
|
||||
|
||||
@@ -58,7 +58,7 @@ class KernelTraits<CosineSimilarity>
|
||||
};
|
||||
|
||||
// This name is deprecated and can be removed in mlpack 5.0.0.
|
||||
typedef CosineSimilarity CosineDistance;
|
||||
using CosineDistance = CosineSimilarity;
|
||||
|
||||
} // namespace mlpack
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ inline arma::Mat<std::complex<T>> ColumnCovariance(
|
||||
Log::Fatal << "ColumnCovariance(): normType must be 0 or 1" << std::endl;
|
||||
}
|
||||
|
||||
typedef typename std::complex<T> eT;
|
||||
using eT = std::complex<T>;
|
||||
|
||||
arma::Mat<eT> out;
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ typename T::elem_type AccuLog(const T& x)
|
||||
if (maxVal == -std::numeric_limits<typename T::elem_type>::infinity())
|
||||
return maxVal;
|
||||
|
||||
return maxVal + std::log(sum(exp(x - maxVal)));;
|
||||
return maxVal + std::log(sum(exp(x - maxVal)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,8 @@ namespace mlpack {
|
||||
/**
|
||||
* Overwrites a dimension-N vector to a random vector on the unit sphere in R^N.
|
||||
*/
|
||||
inline void RandVector(arma::vec& v)
|
||||
template<typename eT>
|
||||
inline void RandVector(arma::Col<eT>& v)
|
||||
{
|
||||
for (size_t i = 0; i + 1 < v.n_elem; i += 2)
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace mlpack {
|
||||
template<typename T>
|
||||
class RangeType;
|
||||
|
||||
typedef RangeType<double> Range;
|
||||
using Range = RangeType<double>;
|
||||
|
||||
/**
|
||||
* Simple real-valued range. It contains an upper and lower bound.
|
||||
|
||||
@@ -53,7 +53,7 @@ ElemType BLEU<ElemType, PrecisionType>::Evaluate(
|
||||
{
|
||||
// WordVector is a string container type.
|
||||
// Also, TranslationCorpusType is an array of such containers.
|
||||
typedef typename TranslationCorpusType::value_type WordVector;
|
||||
using WordVector = typename TranslationCorpusType::value_type;
|
||||
|
||||
// matchesByOrder: It catches how many times sequence of a particular order
|
||||
// is encountered in both reference corpus and translation corpus.
|
||||
|
||||
@@ -83,7 +83,7 @@ void NMS<UseCoordinates>::Evaluate(
|
||||
sortedIndices);
|
||||
|
||||
BoundingBoxesType x1 = boundingBoxes.submat(arma::uvec(1).fill(0),
|
||||
sortedIndices);;
|
||||
sortedIndices);
|
||||
|
||||
BoundingBoxesType y2 = boundingBoxes.submat(arma::uvec(1).fill(3),
|
||||
sortedIndices);
|
||||
|
||||
@@ -54,11 +54,11 @@ namespace mlpack {
|
||||
template<typename AddressType, typename VecType>
|
||||
void PointToAddress(AddressType& address, const VecType& point)
|
||||
{
|
||||
typedef typename VecType::elem_type VecElemType;
|
||||
using VecElemType = typename VecType::elem_type;
|
||||
// Check that the arguments are compatible.
|
||||
typedef std::conditional_t<sizeof(VecElemType) * CHAR_BIT <= 32,
|
||||
uint32_t,
|
||||
uint64_t> AddressElemType;
|
||||
using AddressElemType =
|
||||
std::conditional_t<sizeof(VecElemType) * CHAR_BIT <= 32,
|
||||
uint32_t, uint64_t>;
|
||||
|
||||
static_assert(std::is_same_v<typename AddressType::elem_type,
|
||||
AddressElemType> == true, "The vector element type does not "
|
||||
@@ -150,11 +150,11 @@ void PointToAddress(AddressType& address, const VecType& point)
|
||||
template<typename AddressType, typename VecType>
|
||||
void AddressToPoint(VecType& point, const AddressType& address)
|
||||
{
|
||||
typedef typename VecType::elem_type VecElemType;
|
||||
using VecElemType = typename VecType::elem_type;
|
||||
// Check that the arguments are compatible.
|
||||
typedef std::conditional_t<sizeof(VecElemType) * CHAR_BIT <= 32,
|
||||
uint32_t,
|
||||
uint64_t> AddressElemType;
|
||||
using AddressElemType =
|
||||
std::conditional_t<sizeof(VecElemType) * CHAR_BIT <= 32,
|
||||
uint32_t, uint64_t>;
|
||||
|
||||
static_assert(std::is_same_v<typename AddressType::elem_type,
|
||||
AddressElemType> == true, "The vector element type does not "
|
||||
|
||||
@@ -33,7 +33,7 @@ class BallBound
|
||||
{
|
||||
public:
|
||||
//! A public version of the vector type.
|
||||
typedef VecType Vec;
|
||||
using Vec = VecType;
|
||||
|
||||
private:
|
||||
//! The radius of the ball bound.
|
||||
|
||||
@@ -55,11 +55,11 @@ class BinarySpaceTree
|
||||
{
|
||||
public:
|
||||
//! So other classes can use TreeType::Mat.
|
||||
typedef MatType Mat;
|
||||
using Mat = MatType;
|
||||
//! The type of element held in MatType.
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
|
||||
typedef SplitType<BoundType<DistanceType, ElemType>, MatType> Split;
|
||||
using Split = SplitType<BoundType<DistanceType, ElemType>, MatType>;
|
||||
|
||||
private:
|
||||
//! The left child node.
|
||||
|
||||
@@ -50,8 +50,8 @@ class BinarySpaceTree<DistanceType, StatisticType, MatType, BoundType,
|
||||
*/
|
||||
BreadthFirstDualTreeTraverser(RuleType& rule);
|
||||
|
||||
typedef QueueFrame<BinarySpaceTree, typename RuleType::TraversalInfoType>
|
||||
QueueFrameType;
|
||||
using QueueFrameType =
|
||||
QueueFrame<BinarySpaceTree, typename RuleType::TraversalInfoType>;
|
||||
|
||||
/**
|
||||
* Traverse the two trees. This does not reset the number of prunes.
|
||||
|
||||
@@ -32,7 +32,7 @@ class RPTreeMaxSplit
|
||||
{
|
||||
public:
|
||||
//! The element type held by the matrix type.
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
//! An information about the partition.
|
||||
struct SplitInfo
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ class RPTreeMeanSplit
|
||||
{
|
||||
public:
|
||||
//! The element type held by the matrix type.
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
//! An information about the partition.
|
||||
struct SplitInfo
|
||||
{
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
namespace mlpack {
|
||||
|
||||
template<typename BoundType, typename MatType>
|
||||
bool RPTreeMeanSplit<BoundType, MatType>::SplitNode(const BoundType& bound,
|
||||
MatType& data,
|
||||
const size_t begin,
|
||||
const size_t count,
|
||||
SplitInfo& splitInfo)
|
||||
bool RPTreeMeanSplit<BoundType, MatType>::SplitNode(const BoundType& bound,
|
||||
MatType& data,
|
||||
const size_t begin,
|
||||
const size_t count,
|
||||
SplitInfo& splitInfo)
|
||||
{
|
||||
const size_t maxNumSamples = 100;
|
||||
const size_t numSamples = std::min(maxNumSamples, count);
|
||||
|
||||
@@ -232,8 +232,9 @@ using VPTree = BinarySpaceTree<DistanceType,
|
||||
*
|
||||
* @see @ref trees, BinarySpaceTree, BallTree, MeanSplitKDTree
|
||||
*/
|
||||
|
||||
template<typename DistanceType, typename StatisticType, typename MatType>
|
||||
template<typename DistanceType = EuclideanDistance,
|
||||
typename StatisticType = EmptyStatistic,
|
||||
typename MatType = arma::mat>
|
||||
using MaxRPTree = BinarySpaceTree<DistanceType,
|
||||
StatisticType,
|
||||
MatType,
|
||||
@@ -267,7 +268,9 @@ using MaxRPTree = BinarySpaceTree<DistanceType,
|
||||
*
|
||||
* @see @ref trees, BinarySpaceTree, BallTree, MeanSplitKDTree
|
||||
*/
|
||||
template<typename DistanceType, typename StatisticType, typename MatType>
|
||||
template<typename DistanceType = EuclideanDistance,
|
||||
typename StatisticType = EmptyStatistic,
|
||||
typename MatType = arma::mat>
|
||||
using RPTree = BinarySpaceTree<DistanceType,
|
||||
StatisticType,
|
||||
MatType,
|
||||
|
||||
@@ -29,10 +29,9 @@ class UBTreeSplit
|
||||
{
|
||||
public:
|
||||
//! The type of an address element.
|
||||
typedef std::conditional_t<
|
||||
using AddressElemType = std::conditional_t<
|
||||
sizeof(typename MatType::elem_type) * CHAR_BIT <= 32,
|
||||
uint32_t,
|
||||
uint64_t> AddressElemType;
|
||||
uint32_t, uint64_t>;
|
||||
|
||||
//! An information about the partition.
|
||||
struct SplitInfo
|
||||
|
||||
@@ -32,9 +32,9 @@ class VantagePointSplit
|
||||
{
|
||||
public:
|
||||
//! The matrix element type.
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
//! The bounding shape type.
|
||||
typedef typename BoundType::DistanceType DistanceType;
|
||||
using DistanceType = typename BoundType::DistanceType;
|
||||
//! A struct that contains an information about the split.
|
||||
struct SplitInfo
|
||||
{
|
||||
|
||||
@@ -76,9 +76,8 @@ class CellBound
|
||||
public:
|
||||
//! Depending on the precision of the tree element type, we may need to use
|
||||
//! uint32_t or uint64_t.
|
||||
typedef std::conditional_t<sizeof(ElemType) * CHAR_BIT <= 32,
|
||||
uint32_t,
|
||||
uint64_t> AddressElemType;
|
||||
using AddressElemType = std::conditional_t<sizeof(ElemType) * CHAR_BIT <= 32,
|
||||
uint32_t, uint64_t>;
|
||||
|
||||
/**
|
||||
* Empty constructor; creates a bound of dimensionality 0.
|
||||
|
||||
@@ -32,7 +32,7 @@ template<typename MatType = arma::mat>
|
||||
class CosineTree
|
||||
{
|
||||
public:
|
||||
typedef typename GetDenseColType<MatType>::type VecType;
|
||||
using VecType = typename GetDenseColType<MatType>::type;
|
||||
|
||||
/**
|
||||
* CosineTree constructor for the root node of the tree. It initializes the
|
||||
|
||||
@@ -99,9 +99,9 @@ class CoverTree
|
||||
{
|
||||
public:
|
||||
//! So that other classes can access the matrix type.
|
||||
typedef MatType Mat;
|
||||
using Mat = MatType;
|
||||
//! The type held by the matrix type.
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
|
||||
/**
|
||||
* Create the cover tree with the given dataset and given base.
|
||||
|
||||
@@ -72,8 +72,8 @@ SingleTreeTraverser<RuleType>::Traverse(
|
||||
{
|
||||
// This is a non-recursive implementation (which should be faster than a
|
||||
// recursive implementation).
|
||||
typedef CoverTreeMapEntry<DistanceType, StatisticType, MatType,
|
||||
RootPointPolicy> MapEntryType;
|
||||
using MapEntryType = CoverTreeMapEntry<DistanceType, StatisticType, MatType,
|
||||
RootPointPolicy>;
|
||||
|
||||
// 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
|
||||
|
||||
@@ -33,7 +33,7 @@ class HollowBallBound
|
||||
{
|
||||
public:
|
||||
//! A public version of the metric type.
|
||||
typedef TDistanceType DistanceType;
|
||||
using DistanceType = TDistanceType;
|
||||
|
||||
private:
|
||||
//! The inner and the outer radii of the bound.
|
||||
|
||||
@@ -25,9 +25,9 @@ class Octree
|
||||
{
|
||||
public:
|
||||
//! So other classes can use TreeType::Mat.
|
||||
typedef MatType Mat;
|
||||
using Mat = MatType;
|
||||
//! The type of element held in MatType.
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
|
||||
//! A single-tree traverser; see single_tree_traverser.hpp.
|
||||
template<typename RuleType>
|
||||
|
||||
@@ -30,9 +30,9 @@ class DiscreteHilbertValue
|
||||
public:
|
||||
//! Depending on the precision of the tree element type, we may need to use
|
||||
//! uint32_t or uint64_t.
|
||||
typedef std::conditional_t<sizeof(TreeElemType) * CHAR_BIT <= 32,
|
||||
uint32_t,
|
||||
uint64_t> HilbertElemType;
|
||||
using HilbertElemType =
|
||||
std::conditional_t<sizeof(TreeElemType) * CHAR_BIT <= 32,
|
||||
uint32_t, uint64_t>;
|
||||
|
||||
//! Default constructor.
|
||||
DiscreteHilbertValue();
|
||||
|
||||
@@ -152,7 +152,7 @@ DiscreteHilbertValue<TreeElemType>::
|
||||
CalculateValue(const VecType& pt,
|
||||
typename std::enable_if_t<IsVector<VecType>::value>*)
|
||||
{
|
||||
typedef typename VecType::elem_type VecElemType;
|
||||
using VecElemType = typename VecType::elem_type;
|
||||
arma::Col<HilbertElemType> res(pt.n_rows);
|
||||
// Calculate the number of bits for the exponent.
|
||||
const int numExpBits = std::ceil(std::log2(
|
||||
|
||||
@@ -22,7 +22,7 @@ class HilbertRTreeAuxiliaryInformation
|
||||
{
|
||||
public:
|
||||
//! The element type held by the tree.
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
//! Default constructor
|
||||
HilbertRTreeAuxiliaryInformation();
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class MinimalCoverageSweep
|
||||
template<typename TreeType>
|
||||
struct SweepCost
|
||||
{
|
||||
typedef typename TreeType::ElemType type;
|
||||
using type = typename TreeType::ElemType;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,8 +24,8 @@ SweepNonLeafNode(const size_t axis,
|
||||
const TreeType* node,
|
||||
typename TreeType::ElemType& axisCut)
|
||||
{
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
typedef HRectBound<EuclideanDistance, ElemType> BoundType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
using BoundType = HRectBound<EuclideanDistance, ElemType>;
|
||||
|
||||
std::vector<std::pair<ElemType, size_t>> sorted(node->NumChildren());
|
||||
|
||||
@@ -88,8 +88,8 @@ SweepLeafNode(const size_t axis,
|
||||
const TreeType* node,
|
||||
typename TreeType::ElemType& axisCut)
|
||||
{
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
typedef HRectBound<EuclideanDistance, ElemType> BoundType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
using BoundType = HRectBound<EuclideanDistance, ElemType>;
|
||||
|
||||
std::vector<std::pair<ElemType, size_t>> sorted(node->Count());
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class MinimalSplitsNumberSweep
|
||||
template<typename>
|
||||
struct SweepCost
|
||||
{
|
||||
typedef size_t type;
|
||||
using type = size_t;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,7 @@ size_t MinimalSplitsNumberSweep<SplitPolicy>::SweepNonLeafNode(
|
||||
const TreeType* node,
|
||||
typename TreeType::ElemType& axisCut)
|
||||
{
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
|
||||
std::vector<std::pair<ElemType, size_t>> sorted(node->NumChildren());
|
||||
|
||||
|
||||
@@ -24,9 +24,9 @@ class RPlusPlusTreeAuxiliaryInformation
|
||||
{
|
||||
public:
|
||||
//! The element type held by the tree.
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
//! The bound type held by the auxiliary information.
|
||||
typedef HRectBound<EuclideanDistance, ElemType> BoundType;
|
||||
using BoundType = HRectBound<EuclideanDistance, ElemType>;
|
||||
|
||||
//! Construct the auxiliary information object.
|
||||
RPlusPlusTreeAuxiliaryInformation();
|
||||
|
||||
@@ -104,7 +104,7 @@ void RPlusPlusTreeAuxiliaryInformation<TreeType>::SplitAuxiliaryInfo(
|
||||
const size_t axis,
|
||||
const typename TreeType::ElemType cut)
|
||||
{
|
||||
typedef HRectBound<EuclideanDistance, ElemType> Bound;
|
||||
using Bound = HRectBound<EuclideanDistance, ElemType>;
|
||||
Bound& treeOneBound = treeOne->AuxiliaryInfo().OuterBound();
|
||||
Bound& treeTwoBound = treeTwo->AuxiliaryInfo().OuterBound();
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ template<typename TreeType>
|
||||
size_t RPlusTreeDescentHeuristic::ChooseDescentNode(TreeType* node,
|
||||
const size_t point)
|
||||
{
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
size_t bestIndex = 0;
|
||||
bool success = true;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ template<typename SplitPolicyType,
|
||||
class RPlusTreeSplit
|
||||
{
|
||||
public:
|
||||
typedef SplitPolicyType SplitPolicy;
|
||||
using SplitPolicy = SplitPolicyType;
|
||||
/**
|
||||
* Split a leaf node using the "default" algorithm. If necessary, this split
|
||||
* will propagate upwards through the tree.
|
||||
|
||||
@@ -25,7 +25,7 @@ template<typename TreeType>
|
||||
void RPlusTreeSplit<SplitPolicyType, SweepType>::
|
||||
SplitLeafNode(TreeType* tree, std::vector<bool>& relevels)
|
||||
{
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
|
||||
if (tree->Count() == 1)
|
||||
{
|
||||
@@ -122,7 +122,7 @@ template<typename TreeType>
|
||||
bool RPlusTreeSplit<SplitPolicyType, SweepType>::
|
||||
SplitNonLeafNode(TreeType* tree, std::vector<bool>& relevels)
|
||||
{
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
// If we are splitting the root node, we need will do things differently so
|
||||
// that the constructor and other methods don't confuse the end user by giving
|
||||
// an address of another node.
|
||||
@@ -333,9 +333,8 @@ PartitionNode(const TreeType* node, size_t& minCutAxis,
|
||||
return false; // No partition required.
|
||||
|
||||
// Define the type of the sweep cost.
|
||||
typedef typename
|
||||
SweepType<SplitPolicyType>::template SweepCost<TreeType>::type
|
||||
SweepCostType;
|
||||
using SweepCostType = typename
|
||||
SweepType<SplitPolicyType>::template SweepCost<TreeType>::type;
|
||||
|
||||
SweepCostType minCost = std::numeric_limits<SweepCostType>::max();
|
||||
minCutAxis = node->Bound().Dim();
|
||||
|
||||
@@ -23,7 +23,7 @@ inline size_t RStarTreeDescentHeuristic::ChooseDescentNode(
|
||||
const size_t point)
|
||||
{
|
||||
// Convenience typedef.
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
|
||||
bool tiedOne = false;
|
||||
std::vector<ElemType> originalScores(node->NumChildren());
|
||||
@@ -164,7 +164,7 @@ inline size_t RStarTreeDescentHeuristic::ChooseDescentNode(
|
||||
const TreeType* insertedNode)
|
||||
{
|
||||
// Convenience typedef.
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
|
||||
std::vector<ElemType> scores(node->NumChildren());
|
||||
std::vector<ElemType> vols(node->NumChildren());
|
||||
|
||||
@@ -28,7 +28,7 @@ size_t RStarTreeSplit::ReinsertPoints(TreeType* tree,
|
||||
std::vector<bool>& relevels)
|
||||
{
|
||||
// Convenience typedef.
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
|
||||
// Check if we need to reinsert.
|
||||
if (relevels[tree->TreeDepth() - 1])
|
||||
@@ -83,8 +83,8 @@ void RStarTreeSplit::PickLeafSplit(TreeType* tree,
|
||||
size_t& bestIndex)
|
||||
{
|
||||
// Convenience typedef.
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
typedef HRectBound<EuclideanDistance, ElemType> BoundType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
using BoundType = HRectBound<EuclideanDistance, ElemType>;
|
||||
|
||||
bestAxis = 0;
|
||||
bestIndex = 0;
|
||||
@@ -176,7 +176,7 @@ template<typename TreeType>
|
||||
void RStarTreeSplit::SplitLeafNode(TreeType *tree, std::vector<bool>& relevels)
|
||||
{
|
||||
// Convenience typedef.
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
|
||||
// If there's no need to split, don't.
|
||||
if (tree->Count() <= tree->MaxLeafSize())
|
||||
@@ -272,8 +272,8 @@ bool RStarTreeSplit::SplitNonLeafNode(
|
||||
std::vector<bool>& relevels)
|
||||
{
|
||||
// Convenience typedef.
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
typedef HRectBound<EuclideanDistance, ElemType> BoundType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
using BoundType = HRectBound<EuclideanDistance, ElemType>;
|
||||
|
||||
// Reinsertion isn't done for non-leaf nodes; the paper doesn't seem to make
|
||||
// it clear how to reinsert an entire node without reinserting each of the
|
||||
|
||||
@@ -22,7 +22,7 @@ inline size_t RTreeDescentHeuristic::ChooseDescentNode(const TreeType* node,
|
||||
const size_t point)
|
||||
{
|
||||
// Convenience typedef.
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
|
||||
ElemType minScore = std::numeric_limits<ElemType>::max();
|
||||
int bestIndex = 0;
|
||||
@@ -66,7 +66,7 @@ inline size_t RTreeDescentHeuristic::ChooseDescentNode(
|
||||
const TreeType* insertedNode)
|
||||
{
|
||||
// Convenience typedef.
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
|
||||
ElemType minScore = std::numeric_limits<ElemType>::max();
|
||||
int bestIndex = 0;
|
||||
|
||||
@@ -195,7 +195,7 @@ template<typename TreeType>
|
||||
void RTreeSplit::GetBoundSeeds(const TreeType *tree, int& iRet, int& jRet)
|
||||
{
|
||||
// Convenience typedef.
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
|
||||
ElemType worstPairScore = -1.0;
|
||||
for (size_t i = 0; i < tree->NumChildren(); ++i)
|
||||
@@ -230,7 +230,7 @@ void RTreeSplit::AssignPointDestNode(TreeType* oldTree,
|
||||
const int intJ)
|
||||
{
|
||||
// Convenience typedef.
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
|
||||
size_t end = oldTree->Count();
|
||||
|
||||
@@ -366,7 +366,7 @@ void RTreeSplit::AssignNodeDestNode(TreeType* oldTree,
|
||||
const int intJ)
|
||||
{
|
||||
// Convenience typedef.
|
||||
typedef typename TreeType::ElemType ElemType;
|
||||
using ElemType = typename TreeType::ElemType;
|
||||
|
||||
size_t end = oldTree->NumChildren();
|
||||
assert(end > 1); // If this isn't true, the tree is really weird.
|
||||
|
||||
@@ -58,11 +58,11 @@ class RectangleTree
|
||||
|
||||
public:
|
||||
//! So other classes can use TreeType::Mat.
|
||||
typedef MatType Mat;
|
||||
using Mat = MatType;
|
||||
//! The element type held by the matrix type.
|
||||
typedef typename MatType::elem_type ElemType;
|
||||
using ElemType = typename MatType::elem_type;
|
||||
//! The auxiliary information type held by the tree.
|
||||
typedef AuxiliaryInformationType<RectangleTree> AuxiliaryInformation;
|
||||
using AuxiliaryInformation = AuxiliaryInformationType<RectangleTree>;
|
||||
private:
|
||||
//! The max number of child nodes a non-leaf node can have.
|
||||
size_t maxNumChildren;
|
||||
|
||||
@@ -165,7 +165,7 @@ class XTreeAuxiliaryInformation
|
||||
* The X tree requires that the tree records it's "split history". To make
|
||||
* this easy, we use the following structure.
|
||||
*/
|
||||
typedef struct SplitHistoryStruct
|
||||
struct SplitHistoryStruct
|
||||
{
|
||||
int lastDimension;
|
||||
std::vector<bool> history;
|
||||
@@ -201,7 +201,7 @@ class XTreeAuxiliaryInformation
|
||||
ar(CEREAL_NVP(lastDimension));
|
||||
ar(CEREAL_NVP(history));
|
||||
}
|
||||
} SplitHistoryStruct;
|
||||
};
|
||||
|
||||
private:
|
||||
//! The max number of child nodes a non-leaf normal node can have.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user