use modular_decomposition::{modular_decomposition, ModuleKind}; use petgraph::dot::Config::EdgeNoLabel; use petgraph::dot::Dot; use petgraph::visit::{Dfs, GraphBase, GraphProp, IntoNeighbors, NodeCompactIndexable, NodeCount, NodeIndexable}; use petgraph::{Incoming, Undirected}; struct Graph(Vec>); impl Graph { fn from_edges(edges: impl IntoIterator) -> Self { let mut adj = vec![]; for (u, v) in edges { assert_ne!(u, v); if u >= adj.len() { adj.resize(u + 1, vec![]) } if v >= adj.len() { adj.resize(v + 1, vec![]) } adj[u].push(v); adj[v].push(u); } Self(adj) } } impl GraphBase for Graph { type EdgeId = usize; type NodeId = usize; } impl GraphProp for Graph { type EdgeType = Undirected; } struct Neighbors<'a>(std::slice::Iter<'a, usize>); impl<'a> Iterator for Neighbors<'a> { type Item = usize; fn next(&mut self) -> Option { self.0.next().copied() } } impl<'a> IntoNeighbors for &'a Graph { type Neighbors = Neighbors<'a>; fn neighbors(self, a: Self::NodeId) -> Self::Neighbors { Neighbors(self.0[a].iter()) } } impl NodeCount for Graph { fn node_count(&self) -> usize { self.0.len() } } impl NodeIndexable for Graph { fn node_bound(&self) -> usize { self.node_count() } fn to_index(&self, a: Self::NodeId) -> usize { a } fn from_index(&self, i: usize) -> Self::NodeId { i } } impl NodeCompactIndexable for Graph {} fn main() { let graph = Graph::from_edges([(0, 1), (1, 2), (2, 3)]); let tree = modular_decomposition(&graph).map(|tree| tree.into_digraph()).unwrap_or_default(); println!("{:?}", Dot::with_config(&tree, &[EdgeNoLabel])); let mut factorizing_permutation = Vec::new(); let root = tree.externals(Incoming).next().unwrap(); let mut dfs = Dfs::new(&tree, root); while let Some(node) = dfs.next(&tree) { if let ModuleKind::Node(u) = tree[node] { factorizing_permutation.push(u); } } let factorizing_permutation: Vec<_> = factorizing_permutation.to_vec(); println!("{:?}", factorizing_permutation); }