4 个版本 (2 个破坏性更新)
0.3.0 | 2021 年 10 月 24 日 |
---|---|
0.2.0 | 2020 年 8 月 24 日 |
0.1.1 | 2020 年 6 月 30 日 |
0.1.0 | 2020 年 6 月 24 日 |
在 算法 中排名 848
每月下载 774 次
在 2 crates 中使用
105KB
2.5K SLoC
acap
尽可能接近 —— Rust 中的 最近邻搜索。
示例
use acap::euclid::Euclidean;
use acap::vp::VpTree;
use acap::NearestNeighbors;
let tree = VpTree::balanced(vec![
Euclidean([3, 4]),
Euclidean([5, 12]),
Euclidean([8, 15]),
Euclidean([7, 24]),
]);
let nearest = tree.nearest(&[7, 7]).unwrap();
assert_eq!(nearest.item, &Euclidean([3, 4]));
assert_eq!(nearest.distance, 5);
lib.rs
:
尽可能接近 —— Rust 中的 最近邻搜索。
概述
点之间距离的概念由 Proximity
特性来捕捉。其 distance()
方法返回一个 Distance
,可以通过 value()
获取实际的数值距离。这些抽象层允许 acap
以泛型方式使用不同类型的不同距离函数。
Proximity
计算的距离没有限制。例如,它们不必是对称的、次可加的,甚至不必是正的。具有这些理想属性的实现将额外实现 Metric
标记特性。这种区分允许 acap
支持多种有用的度量和非度量距离。
作为一个具体的例子,考虑 Euclidean<[i32; 2]>
。 Euclidean
包装器为任何具有 坐标 的类型配备了 欧几里得距离 函数作为其 Proximity
实现的 Proximity
use acap::distance::Proximity;
use acap::euclid::Euclidean;
let a = Euclidean([3, 4]);
let b = Euclidean([7, 7]);
assert_eq!(a.distance(&b), 5);
在这种情况下,distance()
并不直接返回一个数字;作为一种优化,它返回一个 EuclideanDistance
包装器。这个包装器存储距离的平方值,以避免在绝对必要之前计算平方根。尽管如此,它仍然可以透明地支持与数值的比较。
# use acap::distance::Proximity;
# use acap::euclid::Euclidean;
# let a = Euclidean([3, 4]);
# let b = Euclidean([7, 7]);
use acap::distance::Distance;
let d = a.distance(&b);
assert!(d > 4 && d < 6);
assert_eq!(d, 5);
assert_eq!(d.value(), 5.0f32);
为了从一个点的一组其他点中找到最近的邻居,NearestNeighbors
trait 提供了一个统一接口来访问许多不同的相似性搜索数据结构。其中之一是 vantage-point tree,在 acap
中作为 VpTree
提供。
# use acap::euclid::Euclidean;
use acap::vp::VpTree;
let tree = VpTree::balanced(vec![
Euclidean([3, 4]),
Euclidean([5, 12]),
Euclidean([8, 15]),
Euclidean([7, 24]),
]);
VpTree
实现了 NearestNeighbors
,它有一个 nearest()
方法,该方法返回一个可选的 Neighbor
。Neighbor
结构体包含找到的实际邻居以及与目标点的距离。
# use acap::euclid::Euclidean;
# use acap::vp::VpTree;
use acap::knn::NearestNeighbors;
# let tree = VpTree::balanced(
# vec![Euclidean([3, 4]), Euclidean([5, 12]), Euclidean([8, 15]), Euclidean([7, 24])]
# );
let nearest = tree.nearest(&[7, 7]).unwrap();
assert_eq!(nearest.item, &Euclidean([3, 4]));
assert_eq!(nearest.distance, 5);
NearestNeighbors
还提供了 nearest_within()
,k_nearest()
和 k_nearest_within()
方法,这些方法在可能的阈值内找到最多 k
个邻居。
精确计算最近邻居可能很昂贵,特别是在高维空间中。出于性能原因,NearestNeighbors
实现可以返回近似结果。许多实现都有速度/精度权衡,可以进行调整。那些总是返回精确结果的实现也将实现 ExactNeighbors
标记特征。例如,当 Proximity
函数是一个 Metric
时,VpTree
将是精确的。
示例
无所有权的搜索
由于 Proximity
为引用提供了通用实现,因此你可以在最近邻索引中存储引用,而不是让它自己持有数据。
use acap::euclid::Euclidean;
use acap::knn::NearestNeighbors;
use acap::vp::VpTree;
let points = vec![
Euclidean([3, 4]),
Euclidean([5, 12]),
Euclidean([8, 15]),
Euclidean([7, 24]),
];
let tree = VpTree::balanced(points.iter());
let nearest = tree.nearest(&&[7, 7]).unwrap();
assert!(std::ptr::eq(*nearest.item, &points[0]));
自定义距离函数
请参阅 Proximity
文档。
依赖项
~155KB