vrp_core/algorithms/clustering/
dbscan.rs1#[cfg(test)]
5#[path = "../../../tests/unit/algorithms/clustering/dbscan_test.rs"]
6mod dbscan_test;
7
8use std::collections::{HashMap, HashSet};
9use std::hash::Hash;
10
11pub type Cluster<'a, T> = Vec<&'a T>;
13
14pub fn create_clusters<'a, T, IS, FN, IR>(points: IS, min_points: usize, neighborhood_fn: FN) -> Vec<Cluster<'a, T>>
19where
20 T: Clone + Hash + Eq,
21 IS: IntoIterator<Item = &'a T>,
22 FN: Fn(&'a T) -> IR + 'a,
23 IR: Iterator<Item = &'a T> + 'a,
24{
25 let mut point_types = HashMap::<&T, PointType>::new();
26 let mut clusters = Vec::new();
27
28 for point in points {
29 if point_types.contains_key(point) {
30 continue;
31 }
32
33 let mut neighbors = neighborhood_fn(point).collect::<Vec<_>>();
34 let mut neighbors_index = neighbors.iter().cloned().collect::<HashSet<_>>();
35
36 if neighbors.len() < min_points {
37 point_types.insert(point, PointType::Noise);
38 } else {
39 let mut cluster = vec![point];
40 point_types.insert(point, PointType::Clustered);
41
42 let mut index = 0;
43 while index < neighbors.len() {
44 let point = neighbors[index];
45 let point_type = point_types.get(point).cloned();
46
47 if point_type.is_none() {
48 let other_neighbours = neighborhood_fn(point).collect::<Vec<_>>();
49 if other_neighbours.len() >= min_points {
50 neighbors
51 .extend(other_neighbours.iter().filter(|&point| !neighbors_index.contains(point)).cloned());
52 neighbors_index.extend(other_neighbours.into_iter());
53 }
54 }
55
56 match point_type {
57 Some(PointType::Clustered) => {}
58 _ => {
59 point_types.insert(point, PointType::Clustered);
60 cluster.push(point);
61 }
62 }
63
64 index += 1;
65 }
66
67 clusters.push(cluster);
68 }
69 }
70
71 clusters
72}
73
74#[derive(Clone, Eq, PartialEq)]
75enum PointType {
76 Noise,
77 Clustered,
78}