use crate::core::Graph;
#[must_use]
pub fn is_same_graph(g1: &Graph, g2: &Graph) -> bool {
if g1.vcount() != g2.vcount() {
return false;
}
if g1.ecount() != g2.ecount() {
return false;
}
if g1.is_directed() != g2.is_directed() {
return false;
}
let m = g1.ecount();
if m == 0 {
return true;
}
let Ok(m_u32) = u32::try_from(m) else {
return false;
};
let e1_result: Result<Vec<(u32, u32)>, _> = (0..m_u32).map(|e| g1.edge(e)).collect();
let e2_result: Result<Vec<(u32, u32)>, _> = (0..m_u32).map(|e| g2.edge(e)).collect();
let (Ok(mut e1), Ok(mut e2)) = (e1_result, e2_result) else {
return false;
};
e1.sort_unstable();
e2.sort_unstable();
e1 == e2
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::Graph;
#[test]
fn same_graph_identical_construction() {
let mut g1 = Graph::with_vertices(3);
g1.add_edges(vec![(0u32, 1u32), (1, 2)]).unwrap();
let mut g2 = Graph::with_vertices(3);
g2.add_edges(vec![(0u32, 1u32), (1, 2)]).unwrap();
assert!(is_same_graph(&g1, &g2));
}
#[test]
fn same_graph_edge_order_does_not_matter() {
let mut g1 = Graph::with_vertices(3);
g1.add_edges(vec![(0u32, 1u32), (1, 2)]).unwrap();
let mut g2 = Graph::with_vertices(3);
g2.add_edges(vec![(1u32, 2u32), (0, 1)]).unwrap();
assert!(is_same_graph(&g1, &g2));
}
#[test]
fn same_graph_undirected_endpoint_orientation_does_not_matter() {
let mut g1 = Graph::with_vertices(2);
g1.add_edge(0, 1).unwrap();
let mut g2 = Graph::with_vertices(2);
g2.add_edge(1, 0).unwrap();
assert!(is_same_graph(&g1, &g2));
}
#[test]
fn different_vcount_not_same() {
let mut g1 = Graph::with_vertices(3);
g1.add_edge(0, 1).unwrap();
let mut g2 = Graph::with_vertices(4);
g2.add_edge(0, 1).unwrap();
assert!(!is_same_graph(&g1, &g2));
}
#[test]
fn different_ecount_not_same() {
let mut g1 = Graph::with_vertices(3);
g1.add_edge(0, 1).unwrap();
let mut g2 = Graph::with_vertices(3);
g2.add_edges(vec![(0u32, 1u32), (1, 2)]).unwrap();
assert!(!is_same_graph(&g1, &g2));
}
#[test]
fn directed_vs_undirected_not_same() {
let mut g1 = Graph::new(3, true).unwrap();
g1.add_edge(0, 1).unwrap();
let mut g2 = Graph::with_vertices(3);
g2.add_edge(0, 1).unwrap();
assert!(!is_same_graph(&g1, &g2));
}
#[test]
fn directed_edge_direction_matters() {
let mut g1 = Graph::new(2, true).unwrap();
g1.add_edge(0, 1).unwrap();
let mut g2 = Graph::new(2, true).unwrap();
g2.add_edge(1, 0).unwrap();
assert!(!is_same_graph(&g1, &g2));
}
#[test]
fn parallel_edges_multiplicity_matters() {
let mut g1 = Graph::with_vertices(2);
g1.add_edges(vec![(0u32, 1u32), (0, 1)]).unwrap();
let mut g2 = Graph::with_vertices(2);
g2.add_edges(vec![(0u32, 1u32), (0, 1)]).unwrap();
assert!(is_same_graph(&g1, &g2));
let mut g3 = Graph::with_vertices(2);
g3.add_edge(0, 1).unwrap();
assert!(!is_same_graph(&g1, &g3));
}
#[test]
fn self_loop_recognised_as_same() {
let mut g1 = Graph::with_vertices(2);
g1.add_edges(vec![(0u32, 0u32), (0, 1)]).unwrap();
let mut g2 = Graph::with_vertices(2);
g2.add_edges(vec![(0u32, 1u32), (0, 0)]).unwrap();
assert!(is_same_graph(&g1, &g2));
}
#[test]
fn empty_graphs_are_same_when_vcount_matches() {
let g1 = Graph::with_vertices(0);
let g2 = Graph::with_vertices(0);
assert!(is_same_graph(&g1, &g2));
let g3 = Graph::with_vertices(5);
let g4 = Graph::with_vertices(5);
assert!(is_same_graph(&g3, &g4));
}
#[test]
fn isomorphic_but_different_edge_sets_not_same() {
let mut g1 = Graph::with_vertices(3);
g1.add_edges(vec![(0u32, 1u32), (1, 2)]).unwrap();
let mut g2 = Graph::with_vertices(3);
g2.add_edges(vec![(0u32, 2u32), (1, 2)]).unwrap();
assert!(!is_same_graph(&g1, &g2));
}
#[test]
fn reflexivity() {
let mut g = Graph::with_vertices(4);
g.add_edges(vec![(0u32, 1u32), (0, 2), (1, 3)]).unwrap();
let g2 = g.clone();
assert!(is_same_graph(&g, &g2));
}
}