774 lines
22 KiB
Rust
774 lines
22 KiB
Rust
use std::fmt::Debug;
|
|
|
|
use crate::testing::fixtures::MakeTestGraph;
|
|
use crate::traits::{Incidence, IncidenceCursor};
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! graph_topology_tests {
|
|
($T:ty) => {
|
|
$crate::graph_topology_tests!(@wrap $T,
|
|
vertex_count_empty,
|
|
vertex_count,
|
|
vertex_map,
|
|
edge_count_empty,
|
|
edge_count,
|
|
edge_map,
|
|
degree_zero,
|
|
degree,
|
|
loop_edge,
|
|
multiple_edges,
|
|
are_adjacent_vertex_self,
|
|
are_adjacent_single_edge,
|
|
are_adjacent,
|
|
vertices_empty,
|
|
vertices,
|
|
adjacent_vertices_empty,
|
|
adjacent_vertices,
|
|
adjacent_vertices_loop_edge,
|
|
adjacent_vertices_multiple_edges,
|
|
incident_vertices_single_edge,
|
|
incident_vertices_loop_edge,
|
|
incident_vertices_multiple_edges,
|
|
incident_vertices,
|
|
edges_empty,
|
|
edges,
|
|
incident_edges_empty,
|
|
incident_edges,
|
|
incident_edges_loop_edge,
|
|
incident_edges_multiple_edges,
|
|
incidences_empty,
|
|
incidences,
|
|
incidences_edge_consistency,
|
|
incidences_loop_edge,
|
|
incidences_multiple_edges,
|
|
incidence_cursor_empty,
|
|
incidence_cursor,
|
|
incidence_cursor_loop_edge,
|
|
incidence_cursor_multiple_edges,
|
|
incidence_cursor_copy,
|
|
incident_vertices_incidences_consistency,
|
|
incident_edges_incidences_consistency,
|
|
);
|
|
};
|
|
|
|
(@wrap $T:ty, $($name:ident),* $(,)?) => {
|
|
$(
|
|
#[test]
|
|
fn $name() {
|
|
$crate::testing::graph_topology_testing::$name::<$T>();
|
|
}
|
|
)*
|
|
};
|
|
}
|
|
|
|
pub fn vertex_count_empty<G: MakeTestGraph>() {
|
|
let graph = G::empty();
|
|
assert_eq!(graph.vertex_count(), 0, "unexpected vertex count");
|
|
}
|
|
|
|
pub fn vertex_count<G: MakeTestGraph>() {
|
|
let (graph, _, _, _) = G::standard();
|
|
assert_eq!(graph.vertex_count(), 10, "unexpected vertex count");
|
|
}
|
|
|
|
pub fn vertex_map<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
{
|
|
let (graph, vertices, _, _) = G::standard();
|
|
let mut map = graph.vertex_map(88);
|
|
for (i, &v) in vertices.iter().enumerate() {
|
|
assert_eq!(
|
|
map[v], 88,
|
|
"unexpected value from default map read for vertex {v:?}"
|
|
);
|
|
map[v] = i;
|
|
}
|
|
for (i, &v) in vertices.iter().enumerate() {
|
|
assert_eq!(map[v], i, "unexpected value after write for vertex {v:?}");
|
|
}
|
|
}
|
|
|
|
pub fn edge_count_empty<G: MakeTestGraph>() {
|
|
let graph = G::empty();
|
|
assert_eq!(graph.edge_count(), 0, "unexpected edge count");
|
|
}
|
|
|
|
pub fn edge_count<G: MakeTestGraph>() {
|
|
let (graph, _, _, _) = G::standard();
|
|
assert_eq!(graph.edge_count(), 18, "unexpected edge count");
|
|
}
|
|
|
|
pub fn edge_map<G: MakeTestGraph>()
|
|
where
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, _, edges, _) = G::standard();
|
|
let mut map = graph.edge_map(99);
|
|
for (i, &(e, _, _)) in edges.iter().enumerate() {
|
|
assert_eq!(
|
|
map[e], 99,
|
|
"unexpected value from default map read for edge {e:?}"
|
|
);
|
|
map[e] = i;
|
|
}
|
|
for (i, &(e, _, _)) in edges.iter().enumerate() {
|
|
assert_eq!(map[e], i, "unexpected value after write for edge {e:?}");
|
|
}
|
|
}
|
|
|
|
pub fn degree_zero<G: MakeTestGraph>() {
|
|
let (graph, v) = G::single_vertex();
|
|
assert_eq!(graph.degree(v), 0, "unexpected non-zero degree");
|
|
}
|
|
|
|
pub fn degree<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
{
|
|
let (graph, vertices, _, _) = G::standard();
|
|
let expected = [2, 5, 7, 2, 7, 2, 3, 3, 2, 3];
|
|
assert_eq!(vertices.len(), expected.len());
|
|
for (&v, &exp) in vertices.iter().zip(&expected) {
|
|
assert_eq!(graph.degree(v), exp, "unexpected degree of {v:?}");
|
|
}
|
|
}
|
|
|
|
pub fn loop_edge<G: MakeTestGraph>() {
|
|
let (graph, v, _) = G::loop_edge();
|
|
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"
|
|
);
|
|
}
|
|
|
|
pub fn multiple_edges<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
{
|
|
const K: usize = 3;
|
|
let (graph, [v0, v1], _) = G::multiple_edges::<K>();
|
|
assert_eq!(graph.vertex_count(), 2, "unexpected vertex count");
|
|
assert_eq!(graph.edge_count(), K, "unexpected edge count");
|
|
assert_eq!(graph.degree(v0), K, "unexpected degree of vertex {v0:?}");
|
|
assert_eq!(graph.degree(v1), K, "unexpected degree of vertex {v1:?}",);
|
|
assert!(graph.are_adjacent(v0, v1), "should be adjacent");
|
|
}
|
|
|
|
pub fn are_adjacent_vertex_self<G: MakeTestGraph>() {
|
|
let (graph, v) = G::single_vertex();
|
|
assert!(
|
|
!graph.are_adjacent(v, v),
|
|
"should not be adjacent to itself"
|
|
);
|
|
}
|
|
|
|
pub fn are_adjacent_single_edge<G: MakeTestGraph>() {
|
|
let (graph, [v0, v1], _) = G::single_edge();
|
|
assert!(graph.are_adjacent(v0, v1), "should be adjacent");
|
|
assert!(graph.are_adjacent(v1, v0), "should be adjacent");
|
|
}
|
|
|
|
pub fn are_adjacent<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
{
|
|
let (graph, vertices, _, _) = G::standard();
|
|
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, &v) in vertices.iter().enumerate() {
|
|
let exp = matches!(i, 1 | 2 | 4 | 5 | 6);
|
|
assert_eq!(
|
|
graph.are_adjacent(vertices[2], v),
|
|
exp,
|
|
"unexpected adjacency of {:?} and {v:?}",
|
|
vertices[2]
|
|
);
|
|
assert_eq!(
|
|
graph.are_adjacent(v, vertices[2]),
|
|
exp,
|
|
"unexpected adjacency of {v:?} and {:?}",
|
|
vertices[2]
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn vertices_empty<G: MakeTestGraph>() {
|
|
let graph = G::empty();
|
|
assert_eq!(
|
|
graph.vertices().count(),
|
|
0,
|
|
"vertex iterator of empty graph should have no elements"
|
|
);
|
|
}
|
|
|
|
pub fn vertices<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
{
|
|
let (graph, vertices, _, _) = G::standard();
|
|
assert_eq!(graph.vertices().count(), 10, "unexpected vertex count");
|
|
for v in graph.vertices() {
|
|
assert_eq!(
|
|
vertices.iter().filter(|&x| *x == v).count(),
|
|
1,
|
|
"unexpected vertex {v:?} from iterator"
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn adjacent_vertices_empty<G: MakeTestGraph>() {
|
|
let (graph, v) = G::single_vertex();
|
|
assert_eq!(
|
|
graph.adjacent_vertices(v).count(),
|
|
0,
|
|
"adjacent vertex iterator of vertex with degree 0 should have no elements"
|
|
);
|
|
}
|
|
|
|
pub fn adjacent_vertices<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
{
|
|
let (graph, vertices, _, _) = G::standard();
|
|
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)
|
|
.unwrap_or_else(|| {
|
|
panic!(
|
|
"unexpected adjacent vertex {v:?} of {:?} from iterator",
|
|
vertices[4]
|
|
)
|
|
});
|
|
expected_adjacency.swap_remove(i);
|
|
}
|
|
assert_eq!(
|
|
expected_adjacency.len(),
|
|
0,
|
|
"expected adjacent vertices {expected_adjacency:?} of {:?} were not matched by iterator",
|
|
vertices[4]
|
|
);
|
|
}
|
|
|
|
pub fn adjacent_vertices_loop_edge<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
{
|
|
let (graph, v, _) = G::loop_edge();
|
|
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"
|
|
);
|
|
}
|
|
|
|
pub fn adjacent_vertices_multiple_edges<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
{
|
|
const K: usize = 3;
|
|
let (graph, vertices, _) = G::multiple_edges::<K>();
|
|
for (i, &v) in vertices.iter().enumerate() {
|
|
let mut iter = graph.adjacent_vertices(v);
|
|
for j in 0..K {
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some(vertices[1 - i]),
|
|
"unexpected adjacent vertex {j} of vertex {v:?}"
|
|
);
|
|
}
|
|
assert_eq!(
|
|
iter.next(),
|
|
None,
|
|
"too many adjacent vertices of vertex {v:?} from iterator"
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn incident_vertices_single_edge<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, [v0, v1], e) = G::single_edge();
|
|
let (u0, u1) = graph.incident_vertices(e);
|
|
assert!(
|
|
(u0 == v0 && u1 == v1) || (u0 == v1 && u1 == v0),
|
|
"unexpected incident vertices {u0:?} and {u1:?} for edge {e:?}"
|
|
);
|
|
}
|
|
|
|
pub fn incident_vertices_loop_edge<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, v, e) = G::loop_edge();
|
|
assert_eq!(
|
|
graph.incident_vertices(e),
|
|
(v, v),
|
|
"unexpected incident vertices for loop edge {e:?}"
|
|
);
|
|
}
|
|
|
|
pub fn incident_vertices_multiple_edges<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, [v0, v1], edges) = G::multiple_edges::<2>();
|
|
assert_ne!(edges[0], edges[1], "edges should be distinct");
|
|
for (i, &e) in edges.iter().enumerate() {
|
|
let (u0, u1) = graph.incident_vertices(e);
|
|
assert!(
|
|
(u0 == v0 && u1 == v1) || (u0 == v1 && u1 == v0),
|
|
"unexpected incident vertices {u0:?} and {u1:?} for multi-edge {e:?} (index {i})"
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn incident_vertices<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, _, edges, _) = G::standard();
|
|
for &(e, v0, v1) in edges.iter() {
|
|
let (u0, u1) = graph.incident_vertices(e);
|
|
assert!(
|
|
(u0 == v0 && u1 == v1) || (u0 == v1 && u1 == v0),
|
|
"unexpected incident vertices {u0:?} and {u1:?} for edge {e:?}"
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn edges_empty<G: MakeTestGraph>() {
|
|
let graph = G::empty();
|
|
assert_eq!(
|
|
graph.edges().count(),
|
|
0,
|
|
"edge iterator of empty graph should have no elements"
|
|
);
|
|
}
|
|
|
|
pub fn edges<G: MakeTestGraph>()
|
|
where
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, _, edges, _) = G::standard();
|
|
assert_eq!(graph.edges().count(), 18, "unexpected edge count");
|
|
for e in graph.edges() {
|
|
assert_eq!(
|
|
edges.iter().filter(|&&(f, _, _)| f == e).count(),
|
|
1,
|
|
"unexpected edge {e:?} from iterator"
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn incident_edges_empty<G: MakeTestGraph>() {
|
|
let (graph, v) = G::single_vertex();
|
|
assert_eq!(
|
|
graph.incident_edges(v).count(),
|
|
0,
|
|
"incident edge iterator of vertex with degree 0 should have no elements"
|
|
);
|
|
}
|
|
|
|
pub fn incident_edges<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, vertices, _, incidences) = G::standard();
|
|
assert_eq!(vertices.len(), incidences.len());
|
|
for (&v, incs) in vertices.iter().zip(&incidences) {
|
|
assert_eq!(
|
|
graph.incident_edges(v).count(),
|
|
incs.len(),
|
|
"unexpected incident edge count for vertex {v:?}"
|
|
);
|
|
let mut expected: Vec<_> = incs.iter().map(|x| x.edge).collect();
|
|
for e in graph.incident_edges(v) {
|
|
let pos = expected.iter().position(|&f| f == e).unwrap_or_else(|| {
|
|
panic!("unexpected incident edge {e:?} of vertex {v:?} from iterator")
|
|
});
|
|
expected.swap_remove(pos);
|
|
}
|
|
assert!(
|
|
expected.is_empty(),
|
|
"expected incident edges {expected:?} of vertex {v:?} were not matched by iterator"
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn incident_edges_loop_edge<G: MakeTestGraph>()
|
|
where
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, v, e) = G::loop_edge();
|
|
let mut iter = graph.incident_edges(v);
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some(e),
|
|
"loop edge should appear in incident edges"
|
|
);
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some(e),
|
|
"loop edge should appear twice in incident edges"
|
|
);
|
|
assert_eq!(iter.next(), None, "too many incident edges from iterator");
|
|
}
|
|
|
|
pub fn incident_edges_multiple_edges<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
const K: usize = 3;
|
|
let (graph, vertices, edges) = G::multiple_edges::<K>();
|
|
for &v in &vertices {
|
|
let mut expected = edges.to_vec();
|
|
for e in graph.incident_edges(v) {
|
|
let pos = expected
|
|
.iter()
|
|
.position(|&f| f == e)
|
|
.unwrap_or_else(|| panic!("unexpected incident edge {e:?} of vertex {v:?}"));
|
|
expected.swap_remove(pos);
|
|
}
|
|
assert!(
|
|
expected.is_empty(),
|
|
"expected incident edges {expected:?} of vertex {v:?} were not matched by iterator"
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn incidences_empty<G: MakeTestGraph>() {
|
|
let (graph, v) = G::single_vertex();
|
|
assert_eq!(
|
|
graph.incidences(v).count(),
|
|
0,
|
|
"incidence iterator of vertex with degree 0 should have no elements"
|
|
);
|
|
}
|
|
|
|
pub fn incidences<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, vertices, _, incidences) = G::standard();
|
|
assert_eq!(vertices.len(), incidences.len());
|
|
for (&v, incs) in vertices.iter().zip(&incidences) {
|
|
assert_eq!(
|
|
graph.incidences(v).count(),
|
|
incs.len(),
|
|
"unexpected incidence count for vertex {v:?}"
|
|
);
|
|
let mut expected = incs.clone();
|
|
for incidence in graph.incidences(v) {
|
|
let pos = expected
|
|
.iter()
|
|
.position(|&x| x == incidence)
|
|
.unwrap_or_else(|| {
|
|
panic!("unexpected incidence {incidence:?} of vertex {v:?} from iterator")
|
|
});
|
|
expected.swap_remove(pos);
|
|
}
|
|
assert!(
|
|
expected.is_empty(),
|
|
"expected incidences {expected:?} of vertex {v:?} were not matched by iterator"
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn incidences_edge_consistency<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, _, _, _) = G::standard();
|
|
for u in graph.vertices() {
|
|
for incidence in graph.incidences(u) {
|
|
if u == incidence.vertex {
|
|
assert_eq!(
|
|
graph
|
|
.incidences(u)
|
|
.filter(|x| x.edge == incidence.edge)
|
|
.count(),
|
|
2,
|
|
"loop edge {:?} should appear exactly twice in incidences of vertex {u:?}",
|
|
incidence.edge
|
|
);
|
|
} else {
|
|
assert!(
|
|
graph
|
|
.incidences(incidence.vertex)
|
|
.any(|x| x.vertex == u && x.edge == incidence.edge),
|
|
"edge {:?} from incidences of vertex {u:?} missing in incidences of \
|
|
adjacent vertex {:?}",
|
|
incidence.edge,
|
|
incidence.vertex
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn incidences_loop_edge<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, v, e) = G::loop_edge();
|
|
let mut iter = graph.incidences(v);
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some(Incidence { vertex: v, edge: e }),
|
|
"vertex should be adjacent to itself"
|
|
);
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some(Incidence { vertex: v, edge: e }),
|
|
"vertex should be adjacent to itself twice"
|
|
);
|
|
assert_eq!(
|
|
iter.next(),
|
|
None,
|
|
"too many adjacent vertices from iterator"
|
|
);
|
|
}
|
|
|
|
pub fn incidences_multiple_edges<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
const K: usize = 3;
|
|
let (graph, vertices, edges) = G::multiple_edges::<K>();
|
|
for (i, &v) in vertices.iter().enumerate() {
|
|
let mut iter = graph.incidences(v);
|
|
for j in 0..K {
|
|
let current = iter.next().unwrap_or_else(|| {
|
|
panic!("incidence {j} missing, expected {K} incidences for vertex {v:?}")
|
|
});
|
|
assert_eq!(
|
|
current.vertex,
|
|
vertices[1 - i],
|
|
"unexpected adjacent vertex of vertex {v:?} in incidence {j}"
|
|
);
|
|
assert_eq!(
|
|
edges.iter().filter(|&&e| e == current.edge).count(),
|
|
1,
|
|
"unexpected incident edge {:?} of vertex {v:?}",
|
|
current.edge
|
|
);
|
|
}
|
|
assert_eq!(
|
|
iter.next(),
|
|
None,
|
|
"too many adjacent vertices of {v:?} from iterator"
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn incidence_cursor_empty<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, v) = G::single_vertex();
|
|
let mut cursor = graph.incidence_cursor(v);
|
|
assert_eq!(
|
|
cursor.next(&graph),
|
|
None,
|
|
"incidence cursor of vertex with degree 0 should immediately be exhausted"
|
|
);
|
|
}
|
|
|
|
pub fn incidence_cursor<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, vertices, _, incidences) = G::standard();
|
|
assert_eq!(vertices.len(), incidences.len());
|
|
for (&v, incs) in vertices.iter().zip(&incidences) {
|
|
let mut expected = incs.clone();
|
|
let mut cursor = graph.incidence_cursor(v);
|
|
while let Some(incidence) = cursor.next(&graph) {
|
|
let pos = expected
|
|
.iter()
|
|
.position(|&x| x == incidence)
|
|
.unwrap_or_else(|| {
|
|
panic!("unexpected incidence {incidence:?} of vertex {v:?} from cursor")
|
|
});
|
|
expected.swap_remove(pos);
|
|
}
|
|
assert!(
|
|
expected.is_empty(),
|
|
"expected incidences {expected:?} of vertex {v:?} were not matched by cursor"
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn incidence_cursor_loop_edge<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, v, e) = G::loop_edge();
|
|
let mut cursor = graph.incidence_cursor(v);
|
|
assert_eq!(
|
|
cursor.next(&graph),
|
|
Some(Incidence { vertex: v, edge: e }),
|
|
"vertex should be adjacent to itself"
|
|
);
|
|
assert_eq!(
|
|
cursor.next(&graph),
|
|
Some(Incidence { vertex: v, edge: e }),
|
|
"vertex should be adjacent to itself twice"
|
|
);
|
|
assert_eq!(cursor.next(&graph), None, "too many incidences from cursor");
|
|
}
|
|
|
|
pub fn incidence_cursor_multiple_edges<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
const K: usize = 3;
|
|
let (graph, vertices, edges) = G::multiple_edges::<K>();
|
|
for (i, &v) in vertices.iter().enumerate() {
|
|
let mut cursor = graph.incidence_cursor(v);
|
|
for j in 0..K {
|
|
let current = cursor.next(&graph).unwrap_or_else(|| {
|
|
panic!("incidence {j} missing, expected {K} incidences for vertex {v:?}")
|
|
});
|
|
assert_eq!(
|
|
current.vertex,
|
|
vertices[1 - i],
|
|
"unexpected adjacent vertex of vertex {v:?} in incidence {j}"
|
|
);
|
|
assert_eq!(
|
|
edges.iter().filter(|&&e| e == current.edge).count(),
|
|
1,
|
|
"unexpected incident edge {:?} of vertex {v:?}",
|
|
current.edge
|
|
);
|
|
}
|
|
assert_eq!(
|
|
cursor.next(&graph),
|
|
None,
|
|
"too many incidences of {v:?} from cursor"
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn incidence_cursor_copy<G: MakeTestGraph>() {
|
|
let (graph, [_, v, _], _) = G::two_edge_path();
|
|
let mut c1 = graph.incidence_cursor(v);
|
|
assert!(c1.next(&graph).is_some(), "expected first incidence");
|
|
let mut c2 = c1;
|
|
assert!(
|
|
c1.next(&graph).is_some(),
|
|
"expected second incidence from original cursor"
|
|
);
|
|
assert!(
|
|
c1.next(&graph).is_none(),
|
|
"expected original cursor to be exhausted"
|
|
);
|
|
assert!(
|
|
c2.next(&graph).is_some(),
|
|
"expected second incidence from copied cursor"
|
|
);
|
|
assert!(
|
|
c2.next(&graph).is_none(),
|
|
"expected copied cursor to be exhausted"
|
|
);
|
|
}
|
|
|
|
pub fn incident_vertices_incidences_consistency<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, _, _, _) = G::standard();
|
|
for u in graph.vertices() {
|
|
for incidence in graph.incidences(u) {
|
|
let (w1, w2) = graph.incident_vertices(incidence.edge);
|
|
assert!(
|
|
(w1 == u && w2 == incidence.vertex) || (w1 == incidence.vertex && w2 == u),
|
|
"edge endpoints {w1:?} and {w2:?} are inconsistent with incidence \
|
|
({:?}, {:?}) of vertex {u:?}",
|
|
incidence.vertex,
|
|
incidence.edge
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn incident_edges_incidences_consistency<G: MakeTestGraph>()
|
|
where
|
|
G::Vertex: Debug,
|
|
G::Edge: Debug,
|
|
{
|
|
let (graph, _, _, _) = G::standard();
|
|
for u in graph.vertices() {
|
|
let mut expected: Vec<_> = graph.incidences(u).map(|x| x.edge).collect();
|
|
for e in graph.incident_edges(u) {
|
|
let pos = expected.iter().position(|&f| f == e).unwrap_or_else(|| {
|
|
panic!("incident edge {e:?} of vertex {u:?} missing from incidences")
|
|
});
|
|
expected.swap_remove(pos);
|
|
}
|
|
assert!(
|
|
expected.is_empty(),
|
|
"incidence edges {expected:?} of vertex {u:?} not matched by incident_edges"
|
|
);
|
|
}
|
|
}
|