petgraph/algo/
maximal_cliques.rs
1use crate::visit::{GetAdjacencyMatrix, IntoNeighbors, IntoNodeIdentifiers};
2use alloc::vec::Vec;
3use core::hash::Hash;
4use core::iter::FromIterator;
5use hashbrown::HashSet;
6
7fn bron_kerbosch_pivot<G>(
10 g: G,
11 adj_mat: &G::AdjMatrix,
12 r: HashSet<G::NodeId>,
13 mut p: HashSet<G::NodeId>,
14 mut x: HashSet<G::NodeId>,
15) -> Vec<HashSet<G::NodeId>>
16where
17 G: GetAdjacencyMatrix + IntoNeighbors,
18 G::NodeId: Eq + Hash,
19{
20 let mut cliques = Vec::with_capacity(1);
21 if p.is_empty() {
22 if x.is_empty() {
23 cliques.push(r);
24 }
25 return cliques;
26 }
27 let u = p.iter().max_by_key(|&v| g.neighbors(*v).count()).unwrap();
29 let mut todo = p
30 .iter()
31 .filter(|&v| *u == *v || !g.is_adjacent(adj_mat, *u, *v) || !g.is_adjacent(adj_mat, *v, *u)) .cloned()
33 .collect::<Vec<G::NodeId>>();
34 while let Some(v) = todo.pop() {
35 let neighbors = HashSet::from_iter(g.neighbors(v));
36 p.remove(&v);
37 let mut next_r = r.clone();
38 next_r.insert(v);
39
40 let next_p = p
41 .intersection(&neighbors)
42 .cloned()
43 .collect::<HashSet<G::NodeId>>();
44 let next_x = x
45 .intersection(&neighbors)
46 .cloned()
47 .collect::<HashSet<G::NodeId>>();
48
49 cliques.extend(bron_kerbosch_pivot(g, adj_mat, next_r, next_p, next_x));
50
51 x.insert(v);
52 }
53
54 cliques
55}
56
57pub fn maximal_cliques<G>(g: G) -> Vec<HashSet<G::NodeId>>
90where
91 G: GetAdjacencyMatrix + IntoNodeIdentifiers + IntoNeighbors,
92 G::NodeId: Eq + Hash,
93{
94 let adj_mat = g.adjacency_matrix();
95 let r = HashSet::new();
96 let p = g.node_identifiers().collect::<HashSet<G::NodeId>>();
97 let x = HashSet::new();
98 bron_kerbosch_pivot(g, &adj_mat, r, p, x)
99}