Add Incidence struct for GraphTopology to use
This commit is contained in:
@@ -296,10 +296,12 @@ macro_rules! dijkstra_tests {
|
||||
<$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],
|
||||
[Vec<
|
||||
$crate::traits::Incidence<
|
||||
<$T as $crate::traits::GraphTopology>::Vertex,
|
||||
<$T as $crate::traits::GraphTopology>::Edge,
|
||||
>,
|
||||
>; 10],
|
||||
$crate::maps::EntityMap<<$T as $crate::traits::GraphTopology>::Edge, u32>,
|
||||
) {
|
||||
use $crate::traits::GraphTopology;
|
||||
|
||||
@@ -10,12 +10,12 @@ macro_rules! graph_topology_test_fixtures {
|
||||
<$T as $crate::traits::GraphTopology>::Vertex,
|
||||
<$T as $crate::traits::GraphTopology>::Vertex,
|
||||
); 18],
|
||||
[Vec<(
|
||||
[Vec<$crate::traits::Incidence<
|
||||
<$T as $crate::traits::GraphTopology>::Vertex,
|
||||
<$T as $crate::traits::GraphTopology>::Edge,
|
||||
)>; 10],
|
||||
>>; 10],
|
||||
) {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::{GraphTopology, Incidence};
|
||||
let mut graph = <$T>::new();
|
||||
let vertices: [<$T as $crate::traits::GraphTopology>::Vertex; 10] =
|
||||
core::array::from_fn(|_| graph.add_vertex());
|
||||
@@ -40,50 +40,54 @@ macro_rules! graph_topology_test_fixtures {
|
||||
(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)],
|
||||
let i = |vertex, edge| Incidence { vertex, edge };
|
||||
let incidences: [Vec<Incidence<
|
||||
<$T as GraphTopology>::Vertex,
|
||||
<$T as GraphTopology>::Edge,
|
||||
>>; 10] = [
|
||||
vec![i(vertices[1], edges[0].0), i(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),
|
||||
i(vertices[0], edges[0].0),
|
||||
i(vertices[0], edges[1].0),
|
||||
i(vertices[2], edges[2].0),
|
||||
i(vertices[3], edges[3].0),
|
||||
i(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),
|
||||
i(vertices[2], edges[5].0),
|
||||
i(vertices[2], edges[5].0),
|
||||
i(vertices[1], edges[2].0),
|
||||
i(vertices[4], edges[6].0),
|
||||
i(vertices[4], edges[7].0),
|
||||
i(vertices[5], edges[8].0),
|
||||
i(vertices[6], edges[9].0),
|
||||
],
|
||||
vec![(vertices[1], edges[3].0), (vertices[6], edges[10].0)],
|
||||
vec![i(vertices[1], edges[3].0), i(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),
|
||||
i(vertices[1], edges[4].0),
|
||||
i(vertices[2], edges[6].0),
|
||||
i(vertices[2], edges[7].0),
|
||||
i(vertices[4], edges[11].0),
|
||||
i(vertices[4], edges[11].0),
|
||||
i(vertices[7], edges[12].0),
|
||||
i(vertices[8], edges[13].0),
|
||||
],
|
||||
vec![(vertices[2], edges[8].0), (vertices[9], edges[14].0)],
|
||||
vec![i(vertices[2], edges[8].0), i(vertices[9], edges[14].0)],
|
||||
vec![
|
||||
(vertices[2], edges[9].0),
|
||||
(vertices[3], edges[10].0),
|
||||
(vertices[9], edges[15].0),
|
||||
i(vertices[2], edges[9].0),
|
||||
i(vertices[3], edges[10].0),
|
||||
i(vertices[9], edges[15].0),
|
||||
],
|
||||
vec![
|
||||
(vertices[4], edges[12].0),
|
||||
(vertices[8], edges[16].0),
|
||||
(vertices[9], edges[17].0),
|
||||
i(vertices[4], edges[12].0),
|
||||
i(vertices[8], edges[16].0),
|
||||
i(vertices[9], edges[17].0),
|
||||
],
|
||||
vec![(vertices[4], edges[13].0), (vertices[7], edges[16].0)],
|
||||
vec![i(vertices[4], edges[13].0), i(vertices[7], edges[16].0)],
|
||||
vec![
|
||||
(vertices[5], edges[14].0),
|
||||
(vertices[6], edges[15].0),
|
||||
(vertices[7], edges[17].0),
|
||||
i(vertices[5], edges[14].0),
|
||||
i(vertices[6], edges[15].0),
|
||||
i(vertices[7], edges[17].0),
|
||||
],
|
||||
];
|
||||
(graph, vertices, edges, incidences)
|
||||
@@ -540,7 +544,7 @@ macro_rules! graph_topology_tests {
|
||||
"unexpected incident edge count for vertex {:?}",
|
||||
vertices[i]
|
||||
);
|
||||
let mut expected: Vec<_> = incidences[i].iter().map(|(_, e)| *e).collect();
|
||||
let mut expected: Vec<_> = incidences[i].iter().map(|x| x.edge).collect();
|
||||
for e in graph.incident_edges(vertices[i]) {
|
||||
let pos = expected
|
||||
.iter()
|
||||
@@ -634,7 +638,7 @@ macro_rules! graph_topology_tests {
|
||||
for incidence in graph.incidences(vertices[i]) {
|
||||
let pos = expected
|
||||
.iter()
|
||||
.position(|(v, e)| *v == incidence.0 && *e == incidence.1)
|
||||
.position(|x| *x == incidence)
|
||||
.expect(&format!(
|
||||
"unexpected incidence {incidence:?} of vertex {:?} from iterator",
|
||||
vertices[i]
|
||||
@@ -657,17 +661,21 @@ macro_rules! graph_topology_tests {
|
||||
// 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 {
|
||||
for incidence in graph.incidences(u) {
|
||||
if u == incidence.vertex {
|
||||
assert_eq!(
|
||||
graph.incidences(u).filter(|(_, f)| *f == e).count(),
|
||||
graph.incidences(u).filter(|x| x.edge == incidence.edge).count(),
|
||||
2,
|
||||
"loop edge {e:?} should appear exactly twice in incidences of vertex {u:?}"
|
||||
"loop edge {:?} should appear exactly twice in incidences of vertex {u:?}",
|
||||
incidence.edge
|
||||
);
|
||||
} 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:?}"
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -676,19 +684,19 @@ macro_rules! graph_topology_tests {
|
||||
|
||||
#[test]
|
||||
fn incidences_loop_edge() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::{GraphTopology, Incidence};
|
||||
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)),
|
||||
Some(Incidence { vertex: v, edge: e }),
|
||||
"vertex should be adjacent to itself"
|
||||
);
|
||||
assert_eq!(
|
||||
iter.next(),
|
||||
Some((v, e)),
|
||||
Some(Incidence { vertex: v, edge: e }),
|
||||
"vertex should be adjacent to itself twice"
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -716,16 +724,16 @@ macro_rules! graph_topology_tests {
|
||||
vertices[i]
|
||||
));
|
||||
assert_eq!(
|
||||
current.0,
|
||||
current.vertex,
|
||||
vertices[1 - i],
|
||||
"unexpected adjacent vertex of vertex {:?} in incidence {j}",
|
||||
vertices[i]
|
||||
);
|
||||
assert_eq!(
|
||||
edges.iter().filter(|e| **e == current.1).count(),
|
||||
edges.iter().filter(|e| **e == current.edge).count(),
|
||||
1,
|
||||
"unexpected incident edge {:?} of vertex {:?}",
|
||||
current.1,
|
||||
current.edge,
|
||||
vertices[i],
|
||||
);
|
||||
}
|
||||
@@ -761,7 +769,7 @@ macro_rules! graph_topology_tests {
|
||||
while let Some(incidence) = cursor.next(&graph) {
|
||||
let pos = expected
|
||||
.iter()
|
||||
.position(|(v, e)| *v == incidence.0 && *e == incidence.1)
|
||||
.position(|x| *x == incidence)
|
||||
.expect(&format!(
|
||||
"unexpected incidence {incidence:?} of vertex {:?} from cursor",
|
||||
vertices[i]
|
||||
@@ -779,19 +787,19 @@ macro_rules! graph_topology_tests {
|
||||
|
||||
#[test]
|
||||
fn incidence_cursor_loop_edge() {
|
||||
use $crate::traits::{GraphTopology, IncidenceCursor};
|
||||
use $crate::traits::{GraphTopology, Incidence, IncidenceCursor};
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
let e = graph.add_edge(v, v);
|
||||
let mut cursor = graph.incidence_cursor(v);
|
||||
assert_eq!(
|
||||
cursor.next(&graph),
|
||||
Some((v, e)),
|
||||
Some(Incidence { vertex: v, edge: e }),
|
||||
"vertex should be adjacent to itself"
|
||||
);
|
||||
assert_eq!(
|
||||
cursor.next(&graph),
|
||||
Some((v, e)),
|
||||
Some(Incidence { vertex: v, edge: e }),
|
||||
"vertex should be adjacent to itself twice"
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -819,16 +827,16 @@ macro_rules! graph_topology_tests {
|
||||
vertices[i]
|
||||
));
|
||||
assert_eq!(
|
||||
current.0,
|
||||
current.vertex,
|
||||
vertices[1 - i],
|
||||
"unexpected adjacent vertex of vertex {:?} in incidence {j}",
|
||||
vertices[i]
|
||||
);
|
||||
assert_eq!(
|
||||
edges.iter().filter(|e| **e == current.1).count(),
|
||||
edges.iter().filter(|e| **e == current.edge).count(),
|
||||
1,
|
||||
"unexpected incident edge {:?} of vertex {:?}",
|
||||
current.1,
|
||||
current.edge,
|
||||
vertices[i],
|
||||
);
|
||||
}
|
||||
@@ -868,11 +876,12 @@ macro_rules! graph_topology_tests {
|
||||
use $crate::traits::GraphTopology;
|
||||
let (graph, _, _, _) = make_test_graph();
|
||||
for u in graph.vertices() {
|
||||
for (v, e) in graph.incidences(u) {
|
||||
let (w1, w2) = graph.incident_vertices(e);
|
||||
for incidence in graph.incidences(u) {
|
||||
let (w1, w2) = graph.incident_vertices(incidence.edge);
|
||||
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:?}"
|
||||
(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
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -883,7 +892,7 @@ macro_rules! graph_topology_tests {
|
||||
use $crate::traits::GraphTopology;
|
||||
let (graph, _, _, _) = make_test_graph();
|
||||
for u in graph.vertices() {
|
||||
let mut expected: Vec<_> = graph.incidences(u).map(|(_, e)| e).collect();
|
||||
let mut expected: Vec<_> = graph.incidences(u).map(|x| x.edge).collect();
|
||||
for e in graph.incident_edges(u) {
|
||||
let pos = expected
|
||||
.iter()
|
||||
@@ -1256,7 +1265,7 @@ macro_rules! graph_topology_deletion_tests {
|
||||
for i in 0..10 {
|
||||
let mut expected: Vec<_> = incidences[i]
|
||||
.iter()
|
||||
.filter_map(|(_, e)| (*e != edges[2].0).then_some(*e))
|
||||
.filter_map(|x| (x.edge != edges[2].0).then_some(x.edge))
|
||||
.collect();
|
||||
assert_eq!(
|
||||
graph.incident_edges(vertices[i]).count(),
|
||||
@@ -1289,7 +1298,7 @@ macro_rules! graph_topology_deletion_tests {
|
||||
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
|
||||
let mut expected: Vec<_> = incidences[i]
|
||||
.iter()
|
||||
.filter_map(|(v, e)| (*v != vertices[2]).then_some(*e))
|
||||
.filter_map(|x| (x.vertex != vertices[2]).then_some(x.edge))
|
||||
.collect();
|
||||
assert_eq!(
|
||||
graph.incident_edges(vertices[i]).count(),
|
||||
@@ -1321,7 +1330,7 @@ macro_rules! graph_topology_deletion_tests {
|
||||
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
|
||||
let remaining = incidences[i]
|
||||
.iter()
|
||||
.filter(|(v, _)| *v != vertices[2])
|
||||
.filter(|x| x.vertex != vertices[2])
|
||||
.cloned()
|
||||
.collect();
|
||||
assert_vertex_incidences(&graph, vertices[i], remaining);
|
||||
@@ -1337,7 +1346,7 @@ macro_rules! graph_topology_deletion_tests {
|
||||
for i in 0..10 {
|
||||
let remaining = incidences[i]
|
||||
.iter()
|
||||
.filter(|(_, e)| *e != edges[2].0)
|
||||
.filter(|x| x.edge != edges[2].0)
|
||||
.cloned()
|
||||
.collect();
|
||||
assert_vertex_incidences(&graph, vertices[i], remaining);
|
||||
@@ -1347,10 +1356,10 @@ macro_rules! graph_topology_deletion_tests {
|
||||
fn assert_vertex_incidences(
|
||||
graph: &$T,
|
||||
v: <$T as $crate::traits::GraphTopology>::Vertex,
|
||||
mut expected: Vec<(
|
||||
mut expected: Vec<$crate::traits::Incidence<
|
||||
<$T as $crate::traits::GraphTopology>::Vertex,
|
||||
<$T as $crate::traits::GraphTopology>::Edge,
|
||||
)>,
|
||||
>>,
|
||||
) {
|
||||
use $crate::traits::GraphTopology;
|
||||
assert_eq!(
|
||||
@@ -1362,7 +1371,7 @@ macro_rules! graph_topology_deletion_tests {
|
||||
for incidence in graph.incidences(v) {
|
||||
let pos = expected
|
||||
.iter()
|
||||
.position(|(u, e)| *u == incidence.0 && *e == incidence.1)
|
||||
.position(|x| *x == incidence)
|
||||
.expect(&format!(
|
||||
"unexpected incidence {incidence:?} of vertex {:?} from iterator after delete",
|
||||
v
|
||||
@@ -1385,7 +1394,7 @@ macro_rules! graph_topology_deletion_tests {
|
||||
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
|
||||
let remaining = incidences[i]
|
||||
.iter()
|
||||
.filter(|(v, _)| *v != vertices[2])
|
||||
.filter(|x| x.vertex != vertices[2])
|
||||
.cloned()
|
||||
.collect();
|
||||
assert_vertex_incidence_cursor(&graph, vertices[i], remaining);
|
||||
@@ -1401,7 +1410,7 @@ macro_rules! graph_topology_deletion_tests {
|
||||
for i in 0..10 {
|
||||
let remaining = incidences[i]
|
||||
.iter()
|
||||
.filter(|(_, e)| *e != edges[2].0)
|
||||
.filter(|x| x.edge != edges[2].0)
|
||||
.cloned()
|
||||
.collect();
|
||||
assert_vertex_incidence_cursor(&graph, vertices[i], remaining);
|
||||
@@ -1411,17 +1420,17 @@ macro_rules! graph_topology_deletion_tests {
|
||||
fn assert_vertex_incidence_cursor(
|
||||
graph: &$T,
|
||||
v: <$T as $crate::traits::GraphTopology>::Vertex,
|
||||
mut expected: Vec<(
|
||||
mut expected: Vec<$crate::traits::Incidence<
|
||||
<$T as $crate::traits::GraphTopology>::Vertex,
|
||||
<$T as $crate::traits::GraphTopology>::Edge,
|
||||
)>,
|
||||
>>,
|
||||
) {
|
||||
use $crate::traits::IncidenceCursor;
|
||||
let mut cursor = graph.incidence_cursor(v);
|
||||
while let Some(incidence) = cursor.next(graph) {
|
||||
let pos = expected
|
||||
.iter()
|
||||
.position(|(u, e)| *u == incidence.0 && *e == incidence.1)
|
||||
.position(|x| *x == incidence)
|
||||
.expect(&format!(
|
||||
"unexpected incidence {incidence:?} of vertex {:?} from cursor after delete",
|
||||
v
|
||||
|
||||
Reference in New Issue
Block a user