causal_hub/graphs/algorithms/components/connected_components.rs
1use std::collections::BTreeSet;
2
3use crate::{
4 graphs::{directions, UndirectedGraph},
5 prelude::BFS,
6 V,
7};
8
9/// Connected components structure.
10pub struct ConnectedComponents<'a, G>
11where
12 G: UndirectedGraph<Direction = directions::Undirected>,
13{
14 g: &'a G,
15 queue: BTreeSet<usize>,
16}
17
18impl<'a, G> ConnectedComponents<'a, G>
19where
20 G: UndirectedGraph<Direction = directions::Undirected>,
21{
22 /// Build a CC iterator.
23 ///
24 /// # Examples
25 ///
26 /// ```
27 /// use std::collections::BTreeSet;
28 ///
29 /// use causal_hub::prelude::*;
30 ///
31 /// // Build a new undirected graph.
32 /// let g = Graph::new(
33 /// ["A", "B", "C", "D", "E", "F"],
34 /// [
35 /// ("A", "B"),
36 /// ("B", "C"),
37 /// ("D", "E"),
38 /// ]
39 /// );
40 ///
41 /// // Build a connected component iterator.
42 /// let mut cc = CC::from(&g);
43 ///
44 /// // Assert connected components.
45 /// assert!(
46 /// cc.eq([
47 /// BTreeSet::from([0, 1, 2]),
48 /// BTreeSet::from([3, 4]),
49 /// BTreeSet::from([5]),
50 /// ])
51 /// );
52 /// ```
53 ///
54 pub fn new(g: &'a G) -> Self {
55 // Initialize to-be-visited queue.
56 let queue = V!(g).collect();
57
58 Self { g, queue }
59 }
60}
61
62impl<'a, G> Iterator for ConnectedComponents<'a, G>
63where
64 G: UndirectedGraph<Direction = directions::Undirected>,
65{
66 type Item = BTreeSet<usize>;
67
68 fn next(&mut self) -> Option<Self::Item> {
69 // Check if there is still a vertex to be visited.
70 self.queue.pop_first().map(|x| {
71 // Perform BFS Tree visit starting from the vertex.
72 let component = BFS::from((self.g, x)).collect();
73 // Remove visited vertices from the to-be-visited set.
74 self.queue = &self.queue - &component;
75
76 component
77 })
78 }
79}
80
81impl<'a, G> From<&'a G> for ConnectedComponents<'a, G>
82where
83 G: UndirectedGraph<Direction = directions::Undirected>,
84{
85 fn from(g: &'a G) -> Self {
86 Self::new(g)
87 }
88}
89
90/// Alias for connected components.
91pub type CC<'a, G> = ConnectedComponents<'a, G>;