graphrs/algorithms/components/connectivity.rs
1use crate::{ext::vec::VecExt, Error, Graph};
2use std::collections::HashSet;
3use std::fmt::Display;
4use std::hash::Hash;
5
6/**
7Returns the components of a graph.
8A connected component is a maximal connected subgraph of an undirected graph.
9
10# Arguments:
11
12* `graph`: a [Graph](../../struct.Graph.html) instance that must be undirected.
13
14# Examples:
15
16```
17use graphrs::{Edge, Graph, GraphSpecs};
18use graphrs::{algorithms::components};
19let edges = vec![
20 Edge::new("n1", "n2"),
21 Edge::new("n2", "n3"),
22 Edge::new("n3", "n4"),
23 Edge::new("o1", "o2"),
24 Edge::new("p1", "p2"),
25 Edge::new("p2", "p3"),
26];
27let specs = GraphSpecs::undirected_create_missing();
28let graph: Graph<&str, ()> = Graph::new_from_nodes_and_edges(vec![], edges, specs).unwrap();
29let result = components::connected_components(&graph).unwrap();
30assert_eq!(result.len(), 3);
31```
32*/
33pub fn connected_components<T, A>(graph: &Graph<T, A>) -> Result<Vec<HashSet<T>>, Error>
34where
35 T: Hash + Eq + Clone + Ord + Display + Send + Sync,
36 A: Clone + Send + Sync,
37{
38 graph.ensure_undirected()?;
39 let mut seen = HashSet::new();
40 let mut return_vec = vec![];
41 for v in graph.get_all_node_names() {
42 if !seen.contains(v) {
43 let bfs = graph.breadth_first_search(&v).to_hashset();
44 seen = seen.union(&bfs).cloned().collect();
45 return_vec.push(bfs);
46 }
47 }
48 Ok(return_vec)
49}
50
51/**
52Returns the number of components in a graph.
53A connected component is a maximal connected subgraph of an undirected graph.
54
55# Arguments:
56
57* `graph`: a [Graph](../../struct.Graph.html) instance that must be undirected.
58
59# Examples:
60
61```
62use graphrs::{Edge, Graph, GraphSpecs};
63use graphrs::{algorithms::components};
64let edges = vec![
65 Edge::new("n1", "n2"),
66 Edge::new("n2", "n3"),
67 Edge::new("n3", "n4"),
68 Edge::new("o1", "o2"),
69 Edge::new("p1", "p2"),
70 Edge::new("p2", "p3"),
71];
72let specs = GraphSpecs::undirected_create_missing();
73let graph: Graph<&str, ()> = Graph::new_from_nodes_and_edges(vec![], edges, specs).unwrap();
74let result = components::number_of_connected_components(&graph).unwrap();
75assert_eq!(result, 3);
76```
77*/
78pub fn number_of_connected_components<T, A>(graph: &Graph<T, A>) -> Result<usize, Error>
79where
80 T: Hash + Eq + Clone + Ord + Display + Send + Sync,
81 A: Clone + Send + Sync,
82{
83 let result = connected_components(graph)?;
84 Ok(result.len())
85}
86
87/**
88Returns the set of nodes in the component of a graph containing a given node.
89
90# Arguments:
91
92* `graph`: a [Graph](../../struct.Graph.html) instance that must be undirected.
93* `node_name`: the node whose component is to be returned.
94
95# Examples:
96
97```
98use graphrs::{Edge, Graph, GraphSpecs};
99use graphrs::{algorithms::components};
100let edges = vec![
101 Edge::new("n1", "n2"),
102 Edge::new("n2", "n3"),
103 Edge::new("n3", "n4"),
104 Edge::new("o1", "o2"),
105 Edge::new("p1", "p2"),
106 Edge::new("p2", "p3"),
107];
108let specs = GraphSpecs::undirected_create_missing();
109let graph: Graph<&str, ()> = Graph::new_from_nodes_and_edges(vec![], edges, specs).unwrap();
110let result = components::node_connected_component(&graph, &"n2").unwrap();
111assert_eq!(result.len(), 4);
112```
113*/
114pub fn node_connected_component<T, A>(
115 graph: &Graph<T, A>,
116 node_name: &T,
117) -> Result<HashSet<T>, Error>
118where
119 T: Hash + Eq + Clone + Ord + Display + Send + Sync,
120 A: Clone + Send + Sync,
121{
122 graph.ensure_undirected()?;
123 let bfs = graph.breadth_first_search(node_name);
124 Ok(bfs.to_hashset())
125}