algorithms_edu/algo/graph/tree/
isomorphism.rs1use crate::algo::graph::tree::center::Center;
9use crate::algo::graph::tree::Node;
10use crate::algo::graph::UnweightedAdjacencyList;
11
12impl From<Center> for Vec<usize> {
13 fn from(center: Center) -> Self {
14 match center {
15 Center::One(x) => vec![x],
16 Center::Two(x, y) => vec![x, y],
17 }
18 }
19}
20
21impl Node {
22 pub fn encode(&self) -> Vec<u8> {
23 let mut labels: Vec<_> = self.children.iter().map(|node| node.encode()).collect();
24 labels.sort();
25 let mut res = Vec::new();
26 res.push(b'(');
27 for label in &labels {
28 res.extend_from_slice(label);
29 }
30 res.push(b')');
31 res
32 }
33}
34
35impl UnweightedAdjacencyList {
36 pub fn is_isomorphic_with(&self, other: &UnweightedAdjacencyList) -> bool {
37 let this_centers: Vec<usize> = self.center().into();
38 let other_centers: Vec<usize> = other.center().into();
39 for &c1 in &this_centers {
40 let tree1 = Node::from_adjacency_list(&self, c1);
41 for &c2 in &other_centers {
42 let tree2 = Node::from_adjacency_list(&self, c2);
43 if tree1.encode() == tree2.encode() {
44 return true;
45 }
46 }
47 }
48 false
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn test_tree_encoding() {
58 let adj = UnweightedAdjacencyList::new_undirected(
59 10,
60 &[
61 [0, 2],
62 [0, 1],
63 [0, 3],
64 [2, 6],
65 [2, 7],
66 [1, 4],
67 [1, 5],
68 [5, 9],
69 [3, 8],
70 ],
71 );
72 let root = Node::from_adjacency_list(&adj, 0);
73 let encoded = root.encode();
74 let encoded = String::from_utf8(encoded).unwrap();
75 assert_eq!(&encoded, "(((())())(()())(()))")
76 }
77
78 #[test]
79 fn test_tree_isomorphism() {
80 let tree1 = UnweightedAdjacencyList::new_undirected(5, &[[2, 0], [3, 4], [2, 1], [2, 3]]);
81 let tree2 = UnweightedAdjacencyList::new_undirected(5, &[[1, 0], [2, 4], [1, 3], [1, 2]]);
82 assert!(tree1.is_isomorphic_with(&tree2));
83 }
84}