acap/
lib.rs

1//! As Close As Possible — [nearest neighbor search] in Rust.
2//!
3//! # Overview
4//!
5//! The notion of distances between points is captured by the [`Proximity`] trait.  Its
6//! [`distance()`] method returns a [`Distance`], from which the actual numerical distance may be
7//! retrieved with [`value()`].  These layers of abstraction allow `acap` to work generically with
8//! different distance functions over different types.
9//!
10//! There are no restrictions on the distances computed by a [`Proximity`].  For example, they don't
11//! have to be symmetric, subadditive, or even positive.  Implementations that do have these
12//! desirable properties will additionally implement the [`Metric`] marker trait.  This distinction
13//! allows `acap` to support a wide variety of useful metric and non-metric distances.
14//!
15//! As a concrete example, consider `Euclidean<[i32; 2]>`.  The [`Euclidean`] wrapper equips any
16//! type that has [coordinates] with the [Euclidean distance] function as its [`Proximity`]
17//! implementation:
18//!
19//!     use acap::distance::Proximity;
20//!     use acap::euclid::Euclidean;
21//!
22//!     let a = Euclidean([3, 4]);
23//!     let b = Euclidean([7, 7]);
24//!     assert_eq!(a.distance(&b), 5);
25//!
26//! In this case, `distance()` doesn't return a number directly; as an optimization, it returns a
27//! [`EuclideanDistance`] wrapper.  This wrapper stores the squared value of the distance, to avoid
28//! computing square roots until absolutely necessary.  Still, it transparently supports comparisons
29//! with numerical values:
30//!
31//!     # use acap::distance::Proximity;
32//!     # use acap::euclid::Euclidean;
33//!     # let a = Euclidean([3, 4]);
34//!     # let b = Euclidean([7, 7]);
35//!     use acap::distance::Distance;
36//!
37//!     let d = a.distance(&b);
38//!     assert!(d > 4 && d < 6);
39//!     assert_eq!(d, 5);
40//!     assert_eq!(d.value(), 5.0f32);
41//!
42//! For finding the nearest neighbors to a point from a set of other points, the
43//! [`NearestNeighbors`] trait provides a uniform interface to [many different similarity search
44//! data structures].  One such structure is the [vantage-point tree], available in `acap` as
45//! [`VpTree`]:
46//!
47//!     # use acap::euclid::Euclidean;
48//!     use acap::vp::VpTree;
49//!
50//!     let tree = VpTree::balanced(vec![
51//!         Euclidean([3, 4]),
52//!         Euclidean([5, 12]),
53//!         Euclidean([8, 15]),
54//!         Euclidean([7, 24]),
55//!     ]);
56//!
57//! [`VpTree`] implements [`NearestNeighbors`], which has a [`nearest()`] method that returns an
58//! optional [`Neighbor`].  The [`Neighbor`] struct holds the actual neighbor it found, and the
59//! distance it was from the target:
60//!
61//!     # use acap::euclid::Euclidean;
62//!     # use acap::vp::VpTree;
63//!     use acap::knn::NearestNeighbors;
64//!
65//!     # let tree = VpTree::balanced(
66//!     #     vec![Euclidean([3, 4]), Euclidean([5, 12]), Euclidean([8, 15]), Euclidean([7, 24])]
67//!     # );
68//!     let nearest = tree.nearest(&[7, 7]).unwrap();
69//!     assert_eq!(nearest.item, &Euclidean([3, 4]));
70//!     assert_eq!(nearest.distance, 5);
71//!
72//! [`NearestNeighbors`] also provides the [`nearest_within()`], [`k_nearest()`], and
73//! [`k_nearest_within()`] methods which find up to `k` neighbors within a possible threshold.
74//!
75//! It can be expensive to compute nearest neighbors exactly, especially in high dimensions.
76//! For performance reasons, [`NearestNeighbors`] implementations are allowed to return approximate
77//! results.  Many implementations have a speed/accuracy tradeoff which can be tuned.  Those
78//! implementations which always return exact results will also implement the [`ExactNeighbors`]
79//! marker trait.  For example, a [`VpTree`] will be exact when the [`Proximity`] function is a
80//! [`Metric`].
81//!
82//! # Examples
83//!
84//! ## Searching without owning
85//!
86//! Since [`Proximity`] has a blanket implementation for references, you can store references in a
87//! nearest neighbor index instead of having it hold the data itself:
88//!
89//!     use acap::euclid::Euclidean;
90//!     use acap::knn::NearestNeighbors;
91//!     use acap::vp::VpTree;
92//!
93//!     let points = vec![
94//!         Euclidean([3, 4]),
95//!         Euclidean([5, 12]),
96//!         Euclidean([8, 15]),
97//!         Euclidean([7, 24]),
98//!     ];
99//!
100//!     let tree = VpTree::balanced(points.iter());
101//!
102//!     let nearest = tree.nearest(&&[7, 7]).unwrap();
103//!     assert!(std::ptr::eq(*nearest.item, &points[0]));
104//!
105//! ## Custom distance functions
106//!
107//! See the [`Proximity`] documentation.
108//!
109//! [nearest neighbor search]: https://en.wikipedia.org/wiki/Nearest_neighbor_search
110//! [`distance()`]: distance::Proximity#tymethod.distance
111//! [`value()`]: distance::Distance#method.value
112//! [coordinates]: coords::Coordinates
113//! [Euclidean distance]: https://en.wikipedia.org/wiki/Euclidean_distance
114//! [`NearestNeighbors`]: knn::NearestNeighbors
115//! [many different similarity search data structures]: knn::NearestNeighbors#implementors
116//! [vantage-point tree]: https://en.wikipedia.org/wiki/Vantage-point_tree
117//! [`VpTree`]: vp::VpTree
118//! [`Neighbor`]: knn::Neighbor
119//! [`nearest()`]: knn::NearestNeighbors#method.nearest
120//! [`k_nearest()`]: knn::NearestNeighbors#method.k_nearest
121//! [`nearest_within()`]: knn::NearestNeighbors#method.nearest_within
122//! [`k_nearest_within()`]: knn::NearestNeighbors#method.k_nearest_within
123//! [`ExactNeighbors`]: knn::ExactNeighbors
124
125#![warn(rust_2018_idioms)]
126
127#![no_std]
128
129extern crate alloc;
130
131pub mod chebyshev;
132pub mod coords;
133pub mod cos;
134pub mod distance;
135pub mod euclid;
136pub mod exhaustive;
137pub mod hamming;
138pub mod kd;
139pub mod knn;
140pub mod lp;
141pub mod taxi;
142pub mod vp;
143
144mod util;
145
146pub use coords::Coordinates;
147pub use distance::{Distance, Metric, Proximity};
148pub use euclid::{euclidean_distance, Euclidean, EuclideanDistance};
149pub use knn::{ExactNeighbors, NearestNeighbors, Neighbor};