Skip to main content

weavatrix_graph/algo/components/
weak.rs

1use crate::IndexGraphView;
2use crate::Vec;
3
4#[must_use]
5pub fn weakly_connected_components<G>(graph: &G) -> Vec<Vec<G::Node>>
6where
7    G: IndexGraphView,
8{
9    with_filter(graph, &|_| true)
10}
11
12#[must_use]
13pub fn weakly_connected_components_filtered<G, F>(graph: &G, allows_edge: F) -> Vec<Vec<G::Node>>
14where
15    G: IndexGraphView,
16    F: Fn(G::Edge) -> bool,
17{
18    with_filter(graph, &allows_edge)
19}
20
21fn with_filter<G, F>(graph: &G, allows_edge: &F) -> Vec<Vec<G::Node>>
22where
23    G: IndexGraphView,
24    F: Fn(G::Edge) -> bool,
25{
26    let node_bound = graph.node_bound();
27    let mut sets = DisjointSet::new(node_bound);
28    for (edge, endpoints) in graph.edge_references() {
29        if !allows_edge(edge) {
30            continue;
31        }
32        let source = G::node_slot(endpoints.source());
33        let target = G::node_slot(endpoints.target());
34        if source < node_bound && target < node_bound {
35            sets.union(source, target);
36        }
37    }
38
39    let mut grouped = vec![Vec::new(); node_bound];
40    for node in graph.node_indices() {
41        let slot = G::node_slot(node);
42        if slot < node_bound {
43            grouped[sets.root(slot)].push(node);
44        }
45    }
46    let mut components = grouped
47        .into_iter()
48        .filter(|component| !component.is_empty())
49        .collect::<Vec<_>>();
50    components.sort_unstable_by_key(|component| G::node_slot(component[0]));
51    components
52}
53
54struct DisjointSet {
55    parent: Vec<usize>,
56    rank: Vec<u8>,
57}
58
59impl DisjointSet {
60    fn new(len: usize) -> Self {
61        Self {
62            parent: (0..len).collect(),
63            rank: vec![0; len],
64        }
65    }
66
67    fn find(&mut self, mut node: usize) -> usize {
68        loop {
69            let parent = self.parent[node];
70            if parent == node {
71                return node;
72            }
73            self.parent[node] = self.parent[parent];
74            node = parent;
75        }
76    }
77
78    fn root(&self, mut node: usize) -> usize {
79        loop {
80            let parent = self.parent[node];
81            if parent == node {
82                return node;
83            }
84            node = parent;
85        }
86    }
87
88    fn union(&mut self, left: usize, right: usize) {
89        let mut left = self.find(left);
90        let mut right = self.find(right);
91        if left == right {
92            return;
93        }
94        if self.rank[left] < self.rank[right] {
95            core::mem::swap(&mut left, &mut right);
96        }
97        self.parent[right] = left;
98        if self.rank[left] == self.rank[right] {
99            self.rank[left] += 1;
100        }
101    }
102}