rust_igraph/algorithms/operators/
is_same_graph.rs1use crate::core::Graph;
15
16#[must_use]
55pub fn is_same_graph(g1: &Graph, g2: &Graph) -> bool {
56 if g1.vcount() != g2.vcount() {
57 return false;
58 }
59 if g1.ecount() != g2.ecount() {
60 return false;
61 }
62 if g1.is_directed() != g2.is_directed() {
63 return false;
64 }
65
66 let m = g1.ecount();
67 if m == 0 {
68 return true;
69 }
70
71 let Ok(m_u32) = u32::try_from(m) else {
78 return false;
79 };
80 let mut e1: Vec<(u32, u32)> = (0..m_u32)
81 .map(|e| g1.edge(e).expect("valid edge id"))
82 .collect();
83 let mut e2: Vec<(u32, u32)> = (0..m_u32)
84 .map(|e| g2.edge(e).expect("valid edge id"))
85 .collect();
86 e1.sort_unstable();
89 e2.sort_unstable();
90 e1 == e2
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96 use crate::core::Graph;
97
98 #[test]
99 fn same_graph_identical_construction() {
100 let mut g1 = Graph::with_vertices(3);
101 g1.add_edges(vec![(0u32, 1u32), (1, 2)]).unwrap();
102 let mut g2 = Graph::with_vertices(3);
103 g2.add_edges(vec![(0u32, 1u32), (1, 2)]).unwrap();
104 assert!(is_same_graph(&g1, &g2));
105 }
106
107 #[test]
108 fn same_graph_edge_order_does_not_matter() {
109 let mut g1 = Graph::with_vertices(3);
110 g1.add_edges(vec![(0u32, 1u32), (1, 2)]).unwrap();
111 let mut g2 = Graph::with_vertices(3);
112 g2.add_edges(vec![(1u32, 2u32), (0, 1)]).unwrap();
113 assert!(is_same_graph(&g1, &g2));
114 }
115
116 #[test]
117 fn same_graph_undirected_endpoint_orientation_does_not_matter() {
118 let mut g1 = Graph::with_vertices(2);
119 g1.add_edge(0, 1).unwrap();
120 let mut g2 = Graph::with_vertices(2);
121 g2.add_edge(1, 0).unwrap();
122 assert!(is_same_graph(&g1, &g2));
123 }
124
125 #[test]
126 fn different_vcount_not_same() {
127 let mut g1 = Graph::with_vertices(3);
128 g1.add_edge(0, 1).unwrap();
129 let mut g2 = Graph::with_vertices(4);
130 g2.add_edge(0, 1).unwrap();
131 assert!(!is_same_graph(&g1, &g2));
132 }
133
134 #[test]
135 fn different_ecount_not_same() {
136 let mut g1 = Graph::with_vertices(3);
137 g1.add_edge(0, 1).unwrap();
138 let mut g2 = Graph::with_vertices(3);
139 g2.add_edges(vec![(0u32, 1u32), (1, 2)]).unwrap();
140 assert!(!is_same_graph(&g1, &g2));
141 }
142
143 #[test]
144 fn directed_vs_undirected_not_same() {
145 let mut g1 = Graph::new(3, true).unwrap();
146 g1.add_edge(0, 1).unwrap();
147 let mut g2 = Graph::with_vertices(3);
148 g2.add_edge(0, 1).unwrap();
149 assert!(!is_same_graph(&g1, &g2));
150 }
151
152 #[test]
153 fn directed_edge_direction_matters() {
154 let mut g1 = Graph::new(2, true).unwrap();
156 g1.add_edge(0, 1).unwrap();
157 let mut g2 = Graph::new(2, true).unwrap();
158 g2.add_edge(1, 0).unwrap();
159 assert!(!is_same_graph(&g1, &g2));
160 }
161
162 #[test]
163 fn parallel_edges_multiplicity_matters() {
164 let mut g1 = Graph::with_vertices(2);
166 g1.add_edges(vec![(0u32, 1u32), (0, 1)]).unwrap();
167 let mut g2 = Graph::with_vertices(2);
168 g2.add_edges(vec![(0u32, 1u32), (0, 1)]).unwrap();
169 assert!(is_same_graph(&g1, &g2));
170 let mut g3 = Graph::with_vertices(2);
172 g3.add_edge(0, 1).unwrap();
173 assert!(!is_same_graph(&g1, &g3));
174 }
175
176 #[test]
177 fn self_loop_recognised_as_same() {
178 let mut g1 = Graph::with_vertices(2);
179 g1.add_edges(vec![(0u32, 0u32), (0, 1)]).unwrap();
180 let mut g2 = Graph::with_vertices(2);
181 g2.add_edges(vec![(0u32, 1u32), (0, 0)]).unwrap();
182 assert!(is_same_graph(&g1, &g2));
183 }
184
185 #[test]
186 fn empty_graphs_are_same_when_vcount_matches() {
187 let g1 = Graph::with_vertices(0);
188 let g2 = Graph::with_vertices(0);
189 assert!(is_same_graph(&g1, &g2));
190 let g3 = Graph::with_vertices(5);
191 let g4 = Graph::with_vertices(5);
192 assert!(is_same_graph(&g3, &g4));
193 }
194
195 #[test]
196 fn isomorphic_but_different_edge_sets_not_same() {
197 let mut g1 = Graph::with_vertices(3);
200 g1.add_edges(vec![(0u32, 1u32), (1, 2)]).unwrap();
201 let mut g2 = Graph::with_vertices(3);
202 g2.add_edges(vec![(0u32, 2u32), (1, 2)]).unwrap();
203 assert!(!is_same_graph(&g1, &g2));
204 }
205
206 #[test]
207 fn reflexivity() {
208 let mut g = Graph::with_vertices(4);
209 g.add_edges(vec![(0u32, 1u32), (0, 2), (1, 3)]).unwrap();
210 let g2 = g.clone();
211 assert!(is_same_graph(&g, &g2));
212 }
213}