981 lines
34 KiB
Rust
981 lines
34 KiB
Rust
#[cfg(test)]
|
|
#[macro_export]
|
|
macro_rules! graph_topology_test_fixtures {
|
|
($T:ty) => {
|
|
fn make_test_graph() -> (
|
|
$T,
|
|
[<$T as $crate::traits::GraphTopology>::Vertex; 10],
|
|
[(
|
|
<$T as $crate::traits::GraphTopology>::Edge,
|
|
<$T as $crate::traits::GraphTopology>::Vertex,
|
|
<$T as $crate::traits::GraphTopology>::Vertex,
|
|
); 18],
|
|
[Vec<(
|
|
<$T as $crate::traits::GraphTopology>::Vertex,
|
|
<$T as $crate::traits::GraphTopology>::Edge,
|
|
)>; 10],
|
|
) {
|
|
let mut graph = <$T>::new();
|
|
let vertices: [<$T as $crate::traits::GraphTopology>::Vertex; 10] =
|
|
core::array::from_fn(|_| graph.add_vertex());
|
|
let edges = [
|
|
(vertices[0], vertices[1]),
|
|
(vertices[0], vertices[1]),
|
|
(vertices[1], vertices[2]),
|
|
(vertices[1], vertices[3]),
|
|
(vertices[1], vertices[4]),
|
|
(vertices[2], vertices[2]),
|
|
(vertices[2], vertices[4]),
|
|
(vertices[2], vertices[4]),
|
|
(vertices[2], vertices[5]),
|
|
(vertices[2], vertices[6]),
|
|
(vertices[3], vertices[6]),
|
|
(vertices[4], vertices[4]),
|
|
(vertices[4], vertices[7]),
|
|
(vertices[4], vertices[8]),
|
|
(vertices[5], vertices[9]),
|
|
(vertices[6], vertices[9]),
|
|
(vertices[7], vertices[8]),
|
|
(vertices[7], vertices[9]),
|
|
]
|
|
.map(|(v1, v2)| (graph.add_edge(v1, v2), v1, v2));
|
|
let incidences: [Vec<_>; 10] = [
|
|
vec![(vertices[1], edges[0].0), (vertices[1], edges[1].0)],
|
|
vec![
|
|
(vertices[0], edges[0].0),
|
|
(vertices[0], edges[1].0),
|
|
(vertices[2], edges[2].0),
|
|
(vertices[3], edges[3].0),
|
|
(vertices[4], edges[4].0),
|
|
],
|
|
vec![
|
|
(vertices[2], edges[5].0),
|
|
(vertices[2], edges[5].0),
|
|
(vertices[1], edges[2].0),
|
|
(vertices[4], edges[6].0),
|
|
(vertices[4], edges[7].0),
|
|
(vertices[5], edges[8].0),
|
|
(vertices[6], edges[9].0),
|
|
],
|
|
vec![(vertices[1], edges[3].0), (vertices[6], edges[10].0)],
|
|
vec![
|
|
(vertices[1], edges[4].0),
|
|
(vertices[2], edges[6].0),
|
|
(vertices[2], edges[7].0),
|
|
(vertices[4], edges[11].0),
|
|
(vertices[4], edges[11].0),
|
|
(vertices[7], edges[12].0),
|
|
(vertices[8], edges[13].0),
|
|
],
|
|
vec![(vertices[2], edges[8].0), (vertices[9], edges[14].0)],
|
|
vec![
|
|
(vertices[2], edges[9].0),
|
|
(vertices[3], edges[10].0),
|
|
(vertices[9], edges[15].0),
|
|
],
|
|
vec![
|
|
(vertices[4], edges[12].0),
|
|
(vertices[8], edges[16].0),
|
|
(vertices[9], edges[17].0),
|
|
],
|
|
vec![(vertices[4], edges[13].0), (vertices[7], edges[16].0)],
|
|
vec![
|
|
(vertices[5], edges[14].0),
|
|
(vertices[6], edges[15].0),
|
|
(vertices[7], edges[17].0),
|
|
],
|
|
];
|
|
(graph, vertices, edges, incidences)
|
|
}
|
|
};
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[macro_export]
|
|
macro_rules! graph_topology_tests {
|
|
($T:ty) => {
|
|
#[test]
|
|
fn add_vertex() {
|
|
let mut graph = <$T>::new();
|
|
let v = graph.add_vertex();
|
|
assert_ne!(graph.add_vertex(), v, "unexpected duplicate vertex");
|
|
}
|
|
|
|
#[test]
|
|
fn vertex_count_empty() {
|
|
let graph = <$T>::new();
|
|
assert_eq!(graph.vertex_count(), 0, "unexpected vertex count");
|
|
}
|
|
|
|
#[test]
|
|
fn vertex_count() {
|
|
let (graph, _, _, _) = make_test_graph();
|
|
assert_eq!(graph.vertex_count(), 10, "unexpected vertex count");
|
|
}
|
|
|
|
#[test]
|
|
fn add_edge() {
|
|
let mut graph = <$T>::new();
|
|
let v1 = graph.add_vertex();
|
|
let v2 = graph.add_vertex();
|
|
let e = graph.add_edge(v1, v2);
|
|
assert_ne!(graph.add_edge(v1, v2), e, "unexpected duplicate edge");
|
|
}
|
|
|
|
#[test]
|
|
fn edge_count_empty() {
|
|
let graph = <$T>::new();
|
|
assert_eq!(graph.edge_count(), 0, "unexpected edge count");
|
|
}
|
|
|
|
#[test]
|
|
fn edge_count() {
|
|
let (graph, _, _, _) = make_test_graph();
|
|
assert_eq!(graph.edge_count(), 18, "unexpected edge count");
|
|
}
|
|
|
|
#[test]
|
|
fn degree_zero() {
|
|
let mut graph = <$T>::new();
|
|
let v = graph.add_vertex();
|
|
assert_eq!(graph.degree(v), 0, "unexpected non-zero degree");
|
|
}
|
|
|
|
#[test]
|
|
fn degree() {
|
|
let (graph, vertices, _, _) = make_test_graph();
|
|
let expected_degrees = [2, 5, 7, 2, 7, 2, 3, 3, 2, 3];
|
|
for i in 0..graph.vertex_count() {
|
|
assert_eq!(
|
|
graph.degree(vertices[i]),
|
|
expected_degrees[i],
|
|
"unexpected degree of {:?}",
|
|
vertices[i]
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn loop_edge() {
|
|
let mut graph = <$T>::new();
|
|
let v = graph.add_vertex();
|
|
graph.add_edge(v, v);
|
|
assert_eq!(graph.vertex_count(), 1, "unexpected vertex count");
|
|
assert_eq!(graph.edge_count(), 1, "unexpected edge count");
|
|
assert_eq!(graph.degree(v), 2, "unexpected degree");
|
|
assert!(
|
|
graph.are_adjacent(v, v),
|
|
"vertex with loop edge should be adjacent to itself"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_edges() {
|
|
let k = 3;
|
|
let mut graph = <$T>::new();
|
|
let v1 = graph.add_vertex();
|
|
let v2 = graph.add_vertex();
|
|
for _ in 0..k {
|
|
graph.add_edge(v1, v2);
|
|
}
|
|
assert_eq!(graph.vertex_count(), 2, "unexpected vertex count");
|
|
assert_eq!(graph.edge_count(), k, "unexpected edge count");
|
|
assert_eq!(graph.degree(v1), k, "unexpected degree of vertex {v1:?}");
|
|
assert_eq!(graph.degree(v2), k, "unexpected degree of vertex {v2:?}");
|
|
assert!(graph.are_adjacent(v1, v2), "should be adjacent");
|
|
}
|
|
|
|
#[test]
|
|
fn are_adjacent_vertex_self() {
|
|
let mut graph = <$T>::new();
|
|
let v = graph.add_vertex();
|
|
assert!(
|
|
!graph.are_adjacent(v, v),
|
|
"should not be adjacent to itself"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn are_adjacent_single_edge() {
|
|
let mut graph = <$T>::new();
|
|
let v1 = graph.add_vertex();
|
|
let v2 = graph.add_vertex();
|
|
assert!(!graph.are_adjacent(v1, v2), "should not be adjacent");
|
|
assert!(!graph.are_adjacent(v2, v1), "should not be adjacent");
|
|
graph.add_edge(v1, v2);
|
|
assert!(graph.are_adjacent(v1, v2), "should be adjacent");
|
|
assert!(graph.are_adjacent(v2, v1), "should be adjacent");
|
|
}
|
|
|
|
#[test]
|
|
fn are_adjacent() {
|
|
let (graph, vertices, _, _) = make_test_graph();
|
|
assert!(
|
|
graph.are_adjacent(vertices[0], vertices[1]),
|
|
"expected {:?} and {:?} to be adjacent",
|
|
vertices[0],
|
|
vertices[1]
|
|
);
|
|
assert!(
|
|
graph.are_adjacent(vertices[9], vertices[5]),
|
|
"expected {:?} and {:?} to be adjacent",
|
|
vertices[9],
|
|
vertices[5]
|
|
);
|
|
assert!(
|
|
!graph.are_adjacent(vertices[9], vertices[3]),
|
|
"unexpected adjacency of {:?} and {:?}",
|
|
vertices[9],
|
|
vertices[3]
|
|
);
|
|
|
|
for i in 0..graph.vertex_count() {
|
|
let exp = match i {
|
|
1 | 2 | 4 | 5 | 6 => true,
|
|
_ => false,
|
|
};
|
|
assert_eq!(
|
|
graph.are_adjacent(vertices[2], vertices[i]),
|
|
exp,
|
|
"unexpected adjacency of {:?} and {:?}",
|
|
vertices[2],
|
|
vertices[i]
|
|
);
|
|
assert_eq!(
|
|
graph.are_adjacent(vertices[i], vertices[2]),
|
|
exp,
|
|
"unexpected adjacency of {:?} and {:?}",
|
|
vertices[i],
|
|
vertices[2]
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn vertices_empty() {
|
|
let graph = <$T>::new();
|
|
assert_eq!(
|
|
graph.vertices().count(),
|
|
0,
|
|
"vertex iterator of empty graph should have no elements"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn vertices() {
|
|
let (graph, vertices, _, _) = make_test_graph();
|
|
assert_eq!(graph.vertices().count(), 10, "unexpected vertex count");
|
|
|
|
// Expects each vertex to appear exactly once.
|
|
for v in graph.vertices() {
|
|
assert_eq!(
|
|
vertices.iter().filter(|&x| *x == v).count(),
|
|
1,
|
|
"unexpected vertex {v:?} from the iterator"
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn adjacent_vertices_empty() {
|
|
let mut graph = <$T>::new();
|
|
let v = graph.add_vertex();
|
|
assert_eq!(
|
|
graph.adjacent_vertices(v).count(),
|
|
0,
|
|
"adjacent vertex iterator of vertex with degree 0 should have no elements"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn adjacent_vertices() {
|
|
let (graph, vertices, _, _) = make_test_graph();
|
|
// Checks adjacency of vertex 4.
|
|
assert_eq!(
|
|
graph.adjacent_vertices(vertices[4]).count(),
|
|
7,
|
|
"unexpected adjacency count"
|
|
);
|
|
let mut expected_adjacency = vec![
|
|
vertices[1],
|
|
vertices[2],
|
|
vertices[2],
|
|
vertices[4],
|
|
vertices[4],
|
|
vertices[7],
|
|
vertices[8],
|
|
];
|
|
for v in graph.adjacent_vertices(vertices[4]) {
|
|
let i = expected_adjacency
|
|
.iter()
|
|
.position(|w| *w == v)
|
|
.expect(&format!(
|
|
"unexpected adjacent vertex {v:?} of {:?} from the iterator",
|
|
vertices[4]
|
|
));
|
|
expected_adjacency.swap_remove(i);
|
|
}
|
|
assert_eq!(
|
|
expected_adjacency.len(),
|
|
0,
|
|
"expected adjacent vertices {:?} of {:?} were not matched by the iterator",
|
|
expected_adjacency,
|
|
vertices[4]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn adjacent_vertices_loop_edge() {
|
|
let mut graph = <$T>::new();
|
|
let v = graph.add_vertex();
|
|
graph.add_edge(v, v);
|
|
let mut iter = graph.adjacent_vertices(v);
|
|
assert_eq!(iter.next(), Some(v), "vertex should be adjacent to itself");
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some(v),
|
|
"vertex should be adjacent to itself twice"
|
|
);
|
|
assert_eq!(
|
|
iter.next(),
|
|
None,
|
|
"too many adjacent vertices from iterator"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn adjacent_vertices_multiple_edges() {
|
|
let k = 3;
|
|
let mut graph = <$T>::new();
|
|
let vertices = [graph.add_vertex(), graph.add_vertex()];
|
|
for _ in 0..k {
|
|
graph.add_edge(vertices[0], vertices[1]);
|
|
}
|
|
for i in 0..2 {
|
|
let mut iter = graph.adjacent_vertices(vertices[i]);
|
|
for j in 0..k {
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some(vertices[1 - i]),
|
|
"unexpected adjacent vertex {j} of vertex {:?}",
|
|
vertices[i]
|
|
);
|
|
}
|
|
assert_eq!(
|
|
iter.next(),
|
|
None,
|
|
"too many adjacent vertices of vertex {:?} from iterator",
|
|
vertices[i]
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn incident_vertices_single_edge() {
|
|
let mut graph = <$T>::new();
|
|
let v1 = graph.add_vertex();
|
|
let v2 = graph.add_vertex();
|
|
let e = graph.add_edge(v1, v2);
|
|
let (u1, u2) = graph.incident_vertices(e);
|
|
assert!(
|
|
(u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1),
|
|
"unexpected incident vertices {u1:?} and {u2:?} for edge {e:?}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn incident_vertices_loop_edge() {
|
|
let mut graph = <$T>::new();
|
|
let v = graph.add_vertex();
|
|
let e = graph.add_edge(v, v);
|
|
assert_eq!(
|
|
graph.incident_vertices(e),
|
|
(v, v),
|
|
"unexpected incident vertices for loop edge {e:?}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn incident_vertices_multiple_edges() {
|
|
let mut graph = <$T>::new();
|
|
let v1 = graph.add_vertex();
|
|
let v2 = graph.add_vertex();
|
|
let e1 = graph.add_edge(v1, v2);
|
|
let e2 = graph.add_edge(v1, v2);
|
|
assert_ne!(e1, e2, "edges should be distinct");
|
|
let (u1, u2) = graph.incident_vertices(e1);
|
|
assert!(
|
|
(u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1),
|
|
"unexpected incident vertices {u1:?} and {u2:?} for first multi-edge {e1:?}"
|
|
);
|
|
let (u1, u2) = graph.incident_vertices(e2);
|
|
assert!(
|
|
(u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1),
|
|
"unexpected incident vertices {u1:?} and {u2:?} for second multi-edge {e2:?}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn incident_vertices() {
|
|
let (graph, _, edges, _) = make_test_graph();
|
|
for &(e, v1, v2) in edges.iter() {
|
|
let (u1, u2) = graph.incident_vertices(e);
|
|
assert!(
|
|
(u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1),
|
|
"unexpected incident vertices {u1:?} and {u2:?} for edge {e:?}"
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn edges_empty() {
|
|
let graph = <$T>::new();
|
|
assert_eq!(
|
|
graph.edges().count(),
|
|
0,
|
|
"edge iterator of empty graph should have no elements"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn edges() {
|
|
let (graph, _, edges, _) = make_test_graph();
|
|
assert_eq!(graph.edges().count(), 18, "unexpected edge count");
|
|
|
|
// Expects each edge to appear exactly once.
|
|
for e in graph.edges() {
|
|
assert_eq!(
|
|
edges.iter().filter(|&&(f, _, _)| f == e).count(),
|
|
1,
|
|
"unexpected edge {e:?} from the iterator"
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn incidences_empty() {
|
|
let mut graph = <$T>::new();
|
|
let v = graph.add_vertex();
|
|
assert_eq!(
|
|
graph.incidences(v).count(),
|
|
0,
|
|
"incidence iterator of vertex with degree 0 should have no elements"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn incidences() {
|
|
let (graph, vertices, _, incidences) = make_test_graph();
|
|
for i in 0..10 {
|
|
assert_eq!(
|
|
graph.incidences(vertices[i]).count(),
|
|
incidences[i].len(),
|
|
"unexpected incidence count for vertex {:?}",
|
|
vertices[i]
|
|
);
|
|
let mut remaining = incidences[i].clone();
|
|
for incidence in graph.incidences(vertices[i]) {
|
|
let pos = remaining
|
|
.iter()
|
|
.position(|(v, e)| *v == incidence.0 && *e == incidence.1)
|
|
.expect(&format!(
|
|
"unexpected incidence {incidence:?} of vertex {:?} from the iterator",
|
|
vertices[i]
|
|
));
|
|
remaining.swap_remove(pos);
|
|
}
|
|
assert!(
|
|
remaining.is_empty(),
|
|
"expected incidences {:?} of vertex {:?} were not matched by the iterator",
|
|
remaining,
|
|
vertices[i]
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn incidences_edge_consistency() {
|
|
// For each incidence (v, e) of u, the same edge e must appear in the incidences of v.
|
|
// For loop edges (u == v), the edge must appear exactly twice in the incidences of u.
|
|
let (graph, _, _, _) = make_test_graph();
|
|
for u in graph.vertices() {
|
|
for (v, e) in graph.incidences(u) {
|
|
if u == v {
|
|
assert_eq!(
|
|
graph.incidences(u).filter(|(_, f)| *f == e).count(),
|
|
2,
|
|
"loop edge {e:?} should appear exactly twice in incidences of vertex {u:?}"
|
|
);
|
|
} else {
|
|
assert!(
|
|
graph.incidences(v).any(|(w, f)| w == u && f == e),
|
|
"edge {e:?} from incidences of vertex {u:?} missing in incidences of adjacent vertex {v:?}"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn incidences_loop_edge() {
|
|
let mut graph = <$T>::new();
|
|
let v = graph.add_vertex();
|
|
let e = graph.add_edge(v, v);
|
|
let mut iter = graph.incidences(v);
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some((v, e)),
|
|
"vertex should be adjacent to itself"
|
|
);
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some((v, e)),
|
|
"vertex should be adjacent to itself twice"
|
|
);
|
|
assert_eq!(
|
|
iter.next(),
|
|
None,
|
|
"too many adjacent vertices from iterator"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn incidences_multiple_edges() {
|
|
let k = 3;
|
|
let mut graph = <$T>::new();
|
|
let vertices = [graph.add_vertex(), graph.add_vertex()];
|
|
let mut edges = Vec::new();
|
|
for _ in 0..k {
|
|
edges.push(graph.add_edge(vertices[0], vertices[1]));
|
|
}
|
|
for i in 0..2 {
|
|
let mut iter = graph.incidences(vertices[i]);
|
|
for j in 0..k {
|
|
let current = iter.next().expect(&format!(
|
|
"incidence {j} missing, expected {k} incidences for vertex {:?}",
|
|
vertices[i]
|
|
));
|
|
assert_eq!(
|
|
current.0,
|
|
vertices[1 - i],
|
|
"unexpected adjacent vertex of vertex {:?} in incidence {j}",
|
|
vertices[i]
|
|
);
|
|
assert_eq!(
|
|
edges.iter().filter(|e| **e == current.1).count(),
|
|
1,
|
|
"unexpected incident edge {:?} of vertex {:?}",
|
|
current.1,
|
|
vertices[i],
|
|
);
|
|
}
|
|
assert_eq!(
|
|
iter.next(),
|
|
None,
|
|
"too many adjacent vertices of {:?} from iterator",
|
|
vertices[i]
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn incident_vertices_incidences_consistency() {
|
|
let (graph, _, _, _) = make_test_graph();
|
|
for u in graph.vertices() {
|
|
for (v, e) in graph.incidences(u) {
|
|
let (w1, w2) = graph.incident_vertices(e);
|
|
assert!(
|
|
(w1 == u && w2 == v) || (w1 == v && w2 == u),
|
|
"incident vertices {w1:?} and {w2:?} of edge {e:?} are inconsistent with incidence ({v:?}, {e:?}) of vertex {u:?}"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[macro_export]
|
|
macro_rules! graph_topology_deletion_tests {
|
|
($T:ty) => {
|
|
#[test]
|
|
fn delete_vertex() {
|
|
let mut graph = Graph::new();
|
|
let v = graph.add_vertex();
|
|
assert_eq!(
|
|
graph.vertex_count(),
|
|
1,
|
|
"unexpected vertex count before delete"
|
|
);
|
|
graph.delete_vertex(v);
|
|
assert_eq!(
|
|
graph.vertex_count(),
|
|
0,
|
|
"unexpected vertex count after delete"
|
|
);
|
|
assert_ne!(
|
|
graph.add_vertex(),
|
|
v,
|
|
"unexpected duplicate vertex after delete"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn delete_vertex_loop() {
|
|
let mut graph = Graph::new();
|
|
let v = graph.add_vertex();
|
|
graph.add_edge(v, v);
|
|
assert_eq!(
|
|
graph.vertex_count(),
|
|
1,
|
|
"unexpected vertex count before delete"
|
|
);
|
|
assert_eq!(graph.edge_count(), 1, "unexpected edge count before delete");
|
|
assert!(
|
|
graph.are_adjacent(v, v),
|
|
"expected vertex to be self-adjacent before delete"
|
|
);
|
|
assert_eq!(graph.degree(v), 2, "unexpected vertex degree before delete");
|
|
graph.delete_vertex(v);
|
|
assert_eq!(
|
|
graph.vertex_count(),
|
|
0,
|
|
"unexpected vertex count after delete"
|
|
);
|
|
assert_eq!(graph.edge_count(), 0, "unexpected edge count after delete");
|
|
assert_ne!(
|
|
graph.add_vertex(),
|
|
v,
|
|
"unexpected duplicate vertex after delete"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn delete_vertex_invalid_index() {
|
|
let mut graph = Graph::new();
|
|
let v = graph.add_vertex();
|
|
graph.delete_vertex(v);
|
|
let result = std::panic::catch_unwind(move || graph.delete_vertex(v));
|
|
assert!(result.is_err(), "second deletion should panic");
|
|
}
|
|
|
|
#[test]
|
|
fn delete_vertex_connected() {
|
|
let (mut graph, vertices, _, _) = make_test_graph();
|
|
assert_eq!(
|
|
graph.vertex_count(),
|
|
10,
|
|
"unexpected vertex count before delete"
|
|
);
|
|
assert_eq!(
|
|
graph.edge_count(),
|
|
18,
|
|
"unexpected edge count before delete"
|
|
);
|
|
graph.delete_vertex(vertices[2]);
|
|
assert_eq!(
|
|
graph.vertex_count(),
|
|
9,
|
|
"unexpected vertex count after delete"
|
|
);
|
|
assert_eq!(graph.edge_count(), 12, "unexpected edge count after delete");
|
|
let expected_edges = [
|
|
(vertices[0], vertices[1]),
|
|
(vertices[1], vertices[3]),
|
|
(vertices[1], vertices[4]),
|
|
(vertices[3], vertices[6]),
|
|
(vertices[4], vertices[4]),
|
|
(vertices[4], vertices[7]),
|
|
(vertices[4], vertices[8]),
|
|
(vertices[5], vertices[9]),
|
|
(vertices[6], vertices[9]),
|
|
(vertices[7], vertices[8]),
|
|
(vertices[7], vertices[9]),
|
|
];
|
|
for (v, u) in expected_edges {
|
|
assert!(
|
|
graph.are_adjacent(v, u),
|
|
"expected {v:?} and {u:?} to be adjacent after delete"
|
|
);
|
|
}
|
|
for v in [vertices[1], vertices[4], vertices[5], vertices[6]] {
|
|
assert!(
|
|
!graph.adjacent_vertices(v).any(|u| u == vertices[2]),
|
|
"unexpected adjacency of {v:?} to deleted vertex {:?}",
|
|
vertices[2]
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn delete_edge() {
|
|
let mut graph = Graph::new();
|
|
let v1 = graph.add_vertex();
|
|
let v2 = graph.add_vertex();
|
|
let e = graph.add_edge(v1, v2);
|
|
assert_eq!(
|
|
graph.vertex_count(),
|
|
2,
|
|
"unexpected vertex count before delete"
|
|
);
|
|
assert_eq!(graph.edge_count(), 1, "unexpected edge count before delete");
|
|
assert!(
|
|
graph.are_adjacent(v1, v2),
|
|
"expected vertices to be adjacent before delete"
|
|
);
|
|
assert_eq!(
|
|
graph.degree(v1),
|
|
1,
|
|
"unexpected vertex degree before delete"
|
|
);
|
|
assert_eq!(
|
|
graph.degree(v2),
|
|
1,
|
|
"unexpected vertex degree before delete"
|
|
);
|
|
graph.delete_edge(e);
|
|
assert_eq!(
|
|
graph.vertex_count(),
|
|
2,
|
|
"unexpected vertex count after delete"
|
|
);
|
|
assert_eq!(graph.edge_count(), 0, "unexpected edge count after delete");
|
|
assert!(
|
|
!graph.are_adjacent(v1, v2),
|
|
"unexpected adjacency after delete"
|
|
);
|
|
assert_eq!(graph.degree(v1), 0, "unexpected vertex degree after delete");
|
|
assert_eq!(graph.degree(v2), 0, "unexpected vertex degree after delete");
|
|
assert_ne!(
|
|
graph.add_edge(v1, v2),
|
|
e,
|
|
"unexpected duplicate edge after delete"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn delete_edge_loop() {
|
|
let mut graph = Graph::new();
|
|
let v = graph.add_vertex();
|
|
let e = graph.add_edge(v, v);
|
|
assert_eq!(
|
|
graph.vertex_count(),
|
|
1,
|
|
"unexpected vertex count before delete"
|
|
);
|
|
assert_eq!(graph.edge_count(), 1, "unexpected edge count before delete");
|
|
assert!(
|
|
graph.are_adjacent(v, v),
|
|
"expected vertex to be self-adjacent before delete"
|
|
);
|
|
assert_eq!(graph.degree(v), 2, "unexpected vertex degree before delete");
|
|
graph.delete_edge(e);
|
|
assert_eq!(
|
|
graph.vertex_count(),
|
|
1,
|
|
"unexpected vertex count after delete"
|
|
);
|
|
assert_eq!(graph.edge_count(), 0, "unexpected edge count after delete");
|
|
assert!(
|
|
!graph.are_adjacent(v, v),
|
|
"unexpected adjacency after delete"
|
|
);
|
|
assert_eq!(graph.degree(v), 0, "unexpected vertex degree after delete");
|
|
assert_ne!(
|
|
graph.add_edge(v, v),
|
|
e,
|
|
"unexpected duplicate edge after delete"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn delete_edge_multiple() {
|
|
let mut graph = Graph::new();
|
|
let v1 = graph.add_vertex();
|
|
let v2 = graph.add_vertex();
|
|
let e = graph.add_edge(v1, v2);
|
|
graph.add_edge(v1, v2);
|
|
assert_eq!(
|
|
graph.vertex_count(),
|
|
2,
|
|
"unexpected vertex count before delete"
|
|
);
|
|
assert_eq!(graph.edge_count(), 2, "unexpected edge count before delete");
|
|
assert!(
|
|
graph.are_adjacent(v1, v2),
|
|
"expected vertices to be adjacent before delete"
|
|
);
|
|
assert_eq!(
|
|
graph.degree(v1),
|
|
2,
|
|
"unexpected vertex degree before delete"
|
|
);
|
|
assert_eq!(
|
|
graph.degree(v2),
|
|
2,
|
|
"unexpected vertex degree before delete"
|
|
);
|
|
graph.delete_edge(e);
|
|
assert_eq!(
|
|
graph.vertex_count(),
|
|
2,
|
|
"unexpected vertex count after delete"
|
|
);
|
|
assert_eq!(graph.edge_count(), 1, "unexpected edge count after delete");
|
|
assert!(
|
|
graph.are_adjacent(v1, v2),
|
|
"expected vertices to be adjacent after delete"
|
|
);
|
|
assert_eq!(graph.degree(v1), 1, "unexpected vertex degree after delete");
|
|
assert_eq!(graph.degree(v2), 1, "unexpected vertex degree after delete");
|
|
assert_ne!(
|
|
graph.add_edge(v1, v2),
|
|
e,
|
|
"unexpected duplicate edge after delete"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn delete_edge_invalid_index() {
|
|
let mut graph = Graph::new();
|
|
let v1 = graph.add_vertex();
|
|
let v2 = graph.add_vertex();
|
|
let e = graph.add_edge(v1, v2);
|
|
graph.delete_edge(e);
|
|
let result = std::panic::catch_unwind(move || graph.delete_edge(e));
|
|
assert!(result.is_err(), "second deletion should panic");
|
|
}
|
|
|
|
#[test]
|
|
fn vertices_after_delete() {
|
|
let (mut graph, vertices, _, _) = make_test_graph();
|
|
graph.delete_vertex(vertices[2]);
|
|
assert_eq!(
|
|
graph.vertex_count(),
|
|
9,
|
|
"unexpected vertex count after delete"
|
|
);
|
|
assert_eq!(
|
|
graph.vertices().count(),
|
|
9,
|
|
"unexpected vertex iterator count after delete"
|
|
);
|
|
for v in graph.vertices() {
|
|
assert_ne!(
|
|
v, vertices[2],
|
|
"deleted vertex {:?} appeared in iterator",
|
|
vertices[2]
|
|
);
|
|
}
|
|
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
|
|
assert!(
|
|
graph.vertices().any(|v| v == vertices[i]),
|
|
"expected vertex {:?} missing from iterator after delete",
|
|
vertices[i]
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn incident_vertices_after_delete_edge() {
|
|
let (mut graph, _, edges, _) = make_test_graph();
|
|
let e = edges[2].0;
|
|
graph.delete_edge(e);
|
|
for &(f, v1, v2) in edges.iter().filter(|&&(f, _, _)| f != e) {
|
|
let (u1, u2) = graph.incident_vertices(f);
|
|
assert!(
|
|
(u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1),
|
|
"unexpected incident vertices {u1:?} and {u2:?} for edge {f:?} after delete"
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn edges_after_delete() {
|
|
let (mut graph, vertices, edges, _) = make_test_graph();
|
|
graph.delete_vertex(vertices[2]);
|
|
assert_eq!(graph.edge_count(), 12, "unexpected edge count after delete");
|
|
assert_eq!(
|
|
graph.edges().count(),
|
|
12,
|
|
"unexpected edge iterator count after delete"
|
|
);
|
|
for i in [2, 5, 6, 7, 8, 9] {
|
|
assert!(
|
|
!graph.edges().any(|e| e == edges[i].0),
|
|
"deleted edge {:?} appeared in iterator",
|
|
edges[i].0
|
|
);
|
|
}
|
|
for i in [0, 1, 3, 4, 10, 11, 12, 13, 14, 15, 16, 17] {
|
|
assert!(
|
|
graph.edges().any(|e| e == edges[i].0),
|
|
"expected edge {:?} missing from iterator after delete",
|
|
edges[i].0
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn incidences_after_delete_vertex() {
|
|
let (mut graph, vertices, _, incidences) = make_test_graph();
|
|
graph.delete_vertex(vertices[2]);
|
|
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
|
|
let remaining = incidences[i]
|
|
.iter()
|
|
.filter(|(v, _)| *v != vertices[2])
|
|
.cloned()
|
|
.collect();
|
|
assert_vertex_incidences(&graph, vertices[i], remaining);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn incidences_after_delete_edge() {
|
|
let (mut graph, vertices, edges, incidences) = make_test_graph();
|
|
// Deletes the edge from vertices[1] to vertices[2].
|
|
graph.delete_edge(edges[2].0);
|
|
for i in 0..10 {
|
|
let remaining = incidences[i]
|
|
.iter()
|
|
.filter(|(_, e)| *e != edges[2].0)
|
|
.cloned()
|
|
.collect();
|
|
assert_vertex_incidences(&graph, vertices[i], remaining);
|
|
}
|
|
}
|
|
|
|
fn assert_vertex_incidences(
|
|
graph: &$T,
|
|
v: <$T as $crate::traits::GraphTopology>::Vertex,
|
|
mut expected: Vec<(
|
|
<$T as $crate::traits::GraphTopology>::Vertex,
|
|
<$T as $crate::traits::GraphTopology>::Edge,
|
|
)>,
|
|
) {
|
|
assert_eq!(
|
|
graph.incidences(v).count(),
|
|
expected.len(),
|
|
"unexpected incidence count for vertex {:?} after delete",
|
|
v
|
|
);
|
|
for incidence in graph.incidences(v) {
|
|
let pos = expected
|
|
.iter()
|
|
.position(|(u, e)| *u == incidence.0 && *e == incidence.1)
|
|
.expect(&format!(
|
|
"unexpected incidence {incidence:?} of vertex {:?} after delete",
|
|
v
|
|
));
|
|
expected.swap_remove(pos);
|
|
}
|
|
assert!(
|
|
expected.is_empty(),
|
|
"expected incidences {:?} of vertex {:?} not matched after delete",
|
|
expected,
|
|
v
|
|
);
|
|
}
|
|
};
|
|
}
|