Release 0.3.0 #8

Merged
warrence merged 69 commits from release-0.3.0 into main 2026-10-15 10:06:13 +02:00
11 changed files with 179 additions and 254 deletions
Showing only changes of commit 3d1e8246a8 - Show all commits
+1 -2
View File
@@ -558,8 +558,7 @@ where
let mut visited = graph.vertex_map(false);
visited[source] = true;
let mut predecessor: ElementMap<G::Vertex, Option<(G::Vertex, G::Edge)>> =
graph.vertex_map(None);
let mut predecessor = graph.vertex_map(None);
let mut queue = VecDeque::from([source]);
while let Some(v) = queue.pop_front() {
+1 -1
View File
@@ -89,7 +89,7 @@ impl<E: Copy, T: Clone> ElementMap<E, T> {
/// ```
pub fn map<U: Clone>(&self, f: impl Fn(&T) -> U) -> ElementMap<E, U> {
ElementMap {
data: self.data.iter().map(|v| f(v)).collect(),
data: self.data.iter().map(&f).collect(),
default: f(&self.default),
to_index: self.to_index,
}
+2 -2
View File
@@ -308,8 +308,8 @@ mod tests {
#[test]
fn opposite_symmetry() {
let (graph, ..) = FrozenGraph::standard();
for i in 0..graph.incidences.len() {
let opp = graph.incidences[i].opposite;
for (i, inc) in graph.incidences.iter().enumerate() {
let opp = inc.opposite;
assert_ne!(opp, i, "incidence should not equal its own opposite");
assert_eq!(
graph.incidences[opp].opposite, i,
+8 -7
View File
@@ -5,6 +5,8 @@ use crate::models::{AppendGraph, FrozenGraph};
use crate::traits::{GraphTopology, GraphTopologyAddition, GraphTopologyConversion, Incidence};
pub trait MakeTestGraph: GraphTopology + Sized {
// Since this is only a test fixture, the complex return type here is deemed acceptable.
#[allow(clippy::type_complexity)]
fn standard() -> (
Self,
[Self::Vertex; 10],
@@ -293,12 +295,12 @@ pub fn assert_standard_unweighted_predecessors_v0<V: Debug + Copy + PartialEq>(
vec![Some(vertices[4])],
vec![Some(vertices[5]), Some(vertices[6]), Some(vertices[7])],
];
for i in 0..10 {
assert_eq!(vertices.len(), expected.len());
for (&v, exp) in vertices.iter().zip(&expected) {
assert!(
expected[i].contains(&actual[vertices[i]]),
"unexpected predecessor {:?} of vertex {:?}",
actual[vertices[i]],
vertices[i]
exp.contains(&actual[v]),
"unexpected predecessor {:?} of vertex {v:?}",
actual[v]
);
}
}
@@ -320,8 +322,7 @@ where
{
let path = path_option.unwrap_or_else(|| {
panic!(
"path should exist between source vertex {:?} and connected targets {:?}",
source, targets
"path should exist between source vertex {source:?} and connected targets {targets:?}"
)
});
@@ -43,10 +43,11 @@ pub fn reserve_vertices_increases_capacity<G: GraphTopologyAddition>() {
}
pub fn reserve_vertices_prevents_reallocation_on_add<G: GraphTopologyAddition>() {
const N: usize = 10;
let mut graph = G::default();
graph.reserve_vertices(10);
graph.reserve_vertices(N);
let capacity_before = graph.vertex_capacity();
for _ in 0..10 {
for _ in 0..N {
graph.add_vertex();
}
assert_eq!(
@@ -78,12 +79,13 @@ pub fn reserve_edges_increases_capacity<G: GraphTopologyAddition>() {
}
pub fn reserve_edges_prevents_reallocation_on_add<G: GraphTopologyAddition>() {
const N: usize = 10;
let mut graph = G::default();
let u = graph.add_vertex();
let v = graph.add_vertex();
graph.reserve_edges(10);
graph.reserve_edges(N);
let capacity_before = graph.edge_capacity();
for _ in 0..10 {
for _ in 0..N {
graph.add_edge(u, v);
}
assert_eq!(
+55 -79
View File
@@ -262,7 +262,8 @@ where
G::Vertex: Debug,
{
let (mut graph, vertices, _, _) = G::standard();
graph.delete_vertex(vertices[2]);
let del = vertices[2];
graph.delete_vertex(del);
assert_eq!(
graph.vertex_count(),
9,
@@ -274,17 +275,12 @@ where
"unexpected vertex iterator count after delete"
);
for v in graph.vertices() {
assert_ne!(
v, vertices[2],
"deleted vertex {:?} appeared in iterator",
vertices[2]
);
assert_ne!(v, del, "deleted vertex {del:?} appeared in iterator");
}
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
for &v in vertices.iter().filter(|&&u| u != del) {
assert!(
graph.vertices().any(|v| v == vertices[i]),
"expected vertex {:?} missing from iterator after delete",
vertices[i]
graph.vertices().any(|u| u == v),
"expected vertex {v:?} missing from iterator after delete"
);
}
}
@@ -295,9 +291,9 @@ where
G::Edge: Debug,
{
let (mut graph, _, edges, _) = G::standard();
let e = edges[2].0;
graph.delete_edge(e);
for &(f, v0, v1) in edges.iter().filter(|&&(f, _, _)| f != e) {
let del = edges[2].0;
graph.delete_edge(del);
for &(f, v0, v1) in edges.iter().filter(|&&(f, _, _)| f != del) {
let (u0, u1) = graph.incident_vertices(f);
assert!(
(u0 == v0 && u1 == v1) || (u0 == v1 && u1 == v0),
@@ -340,13 +336,15 @@ where
G::Edge: Debug,
{
let (mut graph, vertices, edges, incidences) = G::standard();
graph.delete_edge(edges[2].0);
for i in 0..10 {
let mut expected: Vec<_> = incidences[i]
let del = edges[2].0;
graph.delete_edge(del);
assert_eq!(vertices.len(), incidences.len());
for (&v, incs) in vertices.iter().zip(&incidences) {
let mut expected = incs
.iter()
.filter_map(|x| (x.edge != edges[2].0).then_some(x.edge))
.filter_map(|x| (x.edge != del).then_some(x.edge))
.collect();
assert_incident_edges_after_delete(&graph, vertices[i], &mut expected);
assert_incident_edges_after_delete(&graph, v, &mut expected);
}
}
@@ -356,13 +354,14 @@ where
G::Edge: Debug,
{
let (mut graph, vertices, _, incidences) = G::standard();
graph.delete_vertex(vertices[2]);
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
let mut expected: Vec<_> = incidences[i]
let del = vertices[2];
graph.delete_vertex(del);
for (&v, incs) in vertices.iter().zip(&incidences).filter(|&(&u, _)| u != del) {
let mut expected = incs
.iter()
.filter_map(|x| (x.vertex != vertices[2]).then_some(x.edge))
.filter_map(|x| (x.vertex != del).then_some(x.edge))
.collect();
assert_incident_edges_after_delete(&graph, vertices[i], &mut expected);
assert_incident_edges_after_delete(&graph, v, &mut expected);
}
}
@@ -372,14 +371,11 @@ where
G::Edge: Debug,
{
let (mut graph, vertices, _, incidences) = G::standard();
graph.delete_vertex(vertices[2]);
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
let remaining = incidences[i]
.iter()
.filter(|x| x.vertex != vertices[2])
.cloned()
.collect();
assert_vertex_incidences(&graph, vertices[i], remaining);
let del = vertices[2];
graph.delete_vertex(del);
for (&v, incs) in vertices.iter().zip(&incidences).filter(|&(&u, _)| u != del) {
let remaining = incs.iter().filter(|x| x.vertex != del).cloned().collect();
assert_vertex_incidences(&graph, v, remaining);
}
}
@@ -389,14 +385,12 @@ where
G::Edge: Debug,
{
let (mut graph, vertices, edges, incidences) = G::standard();
graph.delete_edge(edges[2].0);
for i in 0..10 {
let remaining = incidences[i]
.iter()
.filter(|x| x.edge != edges[2].0)
.cloned()
.collect();
assert_vertex_incidences(&graph, vertices[i], remaining);
let del = edges[2].0;
graph.delete_edge(del);
assert_eq!(vertices.len(), incidences.len());
for (&v, incs) in vertices.iter().zip(&incidences) {
let remaining = incs.iter().filter(|x| x.edge != del).cloned().collect();
assert_vertex_incidences(&graph, v, remaining);
}
}
@@ -406,14 +400,11 @@ where
G::Edge: Debug,
{
let (mut graph, vertices, _, incidences) = G::standard();
graph.delete_vertex(vertices[2]);
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
let remaining = incidences[i]
.iter()
.filter(|x| x.vertex != vertices[2])
.cloned()
.collect();
assert_vertex_incidence_cursor(&graph, vertices[i], remaining);
let del = vertices[2];
graph.delete_vertex(del);
for (&v, incs) in vertices.iter().zip(&incidences).filter(|&(&u, _)| u != del) {
let remaining = incs.iter().filter(|x| x.vertex != del).cloned().collect();
assert_vertex_incidence_cursor(&graph, v, remaining);
}
}
@@ -423,14 +414,12 @@ where
G::Edge: Debug,
{
let (mut graph, vertices, edges, incidences) = G::standard();
graph.delete_edge(edges[2].0);
for i in 0..10 {
let remaining = incidences[i]
.iter()
.filter(|x| x.edge != edges[2].0)
.cloned()
.collect();
assert_vertex_incidence_cursor(&graph, vertices[i], remaining);
let del = edges[2].0;
graph.delete_edge(del);
assert_eq!(vertices.len(), incidences.len());
for (&v, incs) in vertices.iter().zip(&incidences) {
let remaining = incs.iter().filter(|x| x.edge != del).cloned().collect();
assert_vertex_incidence_cursor(&graph, v, remaining);
}
}
@@ -445,26 +434,22 @@ fn assert_vertex_incidences<G: GraphTopology>(
assert_eq!(
graph.incidences(v).count(),
expected.len(),
"unexpected incidence count for vertex {:?} after delete",
v
"unexpected incidence count for vertex {v:?} after delete"
);
for incidence in graph.incidences(v) {
let pos = expected
.iter()
.position(|x| *x == incidence)
.position(|&x| x == incidence)
.unwrap_or_else(|| {
panic!(
"unexpected incidence {incidence:?} of vertex {:?} from iterator after delete",
v
"unexpected incidence {incidence:?} of vertex {v:?} from iterator after delete"
)
});
expected.swap_remove(pos);
}
assert!(
expected.is_empty(),
"expected incidences {:?} of vertex {:?} not matched by iterator after delete",
expected,
v
"expected incidences {expected:?} of vertex {v:?} not matched by iterator after delete"
);
}
@@ -480,20 +465,17 @@ fn assert_vertex_incidence_cursor<G: GraphTopology>(
while let Some(incidence) = cursor.next(graph) {
let pos = expected
.iter()
.position(|x| *x == incidence)
.position(|&x| x == incidence)
.unwrap_or_else(|| {
panic!(
"unexpected incidence {incidence:?} of vertex {:?} from cursor after delete",
v
"unexpected incidence {incidence:?} of vertex {v:?} from cursor after delete"
)
});
expected.swap_remove(pos);
}
assert!(
expected.is_empty(),
"expected incidences {:?} of vertex {:?} not matched by cursor after delete",
expected,
v
"expected incidences {expected:?} of vertex {v:?} not matched by cursor after delete"
);
}
@@ -508,22 +490,16 @@ fn assert_incident_edges_after_delete<G: GraphTopology>(
assert_eq!(
graph.incident_edges(v).count(),
expected.len(),
"unexpected incident edge count for vertex {:?} after delete",
v
"unexpected incident edge count for vertex {v:?} after delete"
);
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 {:?} after delete",
v
)
let pos = expected.iter().position(|&f| f == e).unwrap_or_else(|| {
panic!("unexpected incident edge {e:?} of vertex {v:?} after delete")
});
expected.swap_remove(pos);
}
assert!(
expected.is_empty(),
"expected incident edges {:?} of vertex {:?} not matched after delete",
expected,
v
"expected incident edges {expected:?} of vertex {v:?} not matched after delete"
);
}
+71 -112
View File
@@ -128,14 +128,10 @@ where
G::Vertex: Debug,
{
let (graph, vertices, _, _) = G::standard();
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]
);
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:?}");
}
}
@@ -200,23 +196,18 @@ where
vertices[9],
vertices[3]
);
for i in 0..graph.vertex_count() {
let exp = match i {
1 | 2 | 4 | 5 | 6 => true,
_ => false,
};
for (i, &v) in vertices.iter().enumerate() {
let exp = matches!(i, 1 | 2 | 4 | 5 | 6);
assert_eq!(
graph.are_adjacent(vertices[2], vertices[i]),
graph.are_adjacent(vertices[2], v),
exp,
"unexpected adjacency of {:?} and {:?}",
vertices[2],
vertices[i]
"unexpected adjacency of {:?} and {v:?}",
vertices[2]
);
assert_eq!(
graph.are_adjacent(vertices[i], vertices[2]),
graph.are_adjacent(v, vertices[2]),
exp,
"unexpected adjacency of {:?} and {:?}",
vertices[i],
"unexpected adjacency of {v:?} and {:?}",
vertices[2]
);
}
@@ -289,8 +280,7 @@ where
assert_eq!(
expected_adjacency.len(),
0,
"expected adjacent vertices {:?} of {:?} were not matched by iterator",
expected_adjacency,
"expected adjacent vertices {expected_adjacency:?} of {:?} were not matched by iterator",
vertices[4]
);
}
@@ -320,21 +310,19 @@ where
{
const K: usize = 3;
let (graph, vertices, _) = G::multiple_edges::<K>();
for i in 0..2 {
let mut iter = graph.adjacent_vertices(vertices[i]);
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 {:?}",
vertices[i]
"unexpected adjacent vertex {j} of vertex {v:?}"
);
}
assert_eq!(
iter.next(),
None,
"too many adjacent vertices of vertex {:?} from iterator",
vertices[i]
"too many adjacent vertices of vertex {v:?} from iterator"
);
}
}
@@ -372,12 +360,11 @@ where
{
let (graph, [v0, v1], edges) = G::multiple_edges::<2>();
assert_ne!(edges[0], edges[1], "edges should be distinct");
for i in 0..2 {
let (u0, u1) = graph.incident_vertices(edges[i]);
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 {:?} (index {i})",
edges[i]
"unexpected incident vertices {u0:?} and {u1:?} for multi-edge {e:?} (index {i})"
);
}
}
@@ -436,28 +423,23 @@ where
G::Edge: Debug,
{
let (graph, vertices, _, incidences) = G::standard();
for i in 0..10 {
assert_eq!(vertices.len(), incidences.len());
for (&v, incs) in vertices.iter().zip(&incidences) {
assert_eq!(
graph.incident_edges(vertices[i]).count(),
incidences[i].len(),
"unexpected incident edge count for vertex {:?}",
vertices[i]
graph.incident_edges(v).count(),
incs.len(),
"unexpected incident edge count for vertex {v:?}"
);
let mut expected: Vec<_> = incidences[i].iter().map(|x| x.edge).collect();
for e in graph.incident_edges(vertices[i]) {
let pos = expected.iter().position(|f| *f == e).unwrap_or_else(|| {
panic!(
"unexpected incident edge {e:?} of vertex {:?} from iterator",
vertices[i]
)
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 {:?} of vertex {:?} were not matched by iterator",
expected,
vertices[i]
"expected incident edges {expected:?} of vertex {v:?} were not matched by iterator"
);
}
}
@@ -488,19 +470,18 @@ where
{
const K: usize = 3;
let (graph, vertices, edges) = G::multiple_edges::<K>();
for i in 0..2 {
for &v in &vertices {
let mut expected = edges.to_vec();
for e in graph.incident_edges(vertices[i]) {
let pos = expected.iter().position(|f| *f == e).unwrap_or_else(|| {
panic!("unexpected incident edge {e:?} of vertex {:?}", vertices[i])
});
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 {:?} of vertex {:?} were not matched by iterator",
expected,
vertices[i]
"expected incident edges {expected:?} of vertex {v:?} were not matched by iterator"
);
}
}
@@ -520,31 +501,26 @@ where
G::Edge: Debug,
{
let (graph, vertices, _, incidences) = G::standard();
for i in 0..10 {
assert_eq!(vertices.len(), incidences.len());
for (&v, incs) in vertices.iter().zip(&incidences) {
assert_eq!(
graph.incidences(vertices[i]).count(),
incidences[i].len(),
"unexpected incidence count for vertex {:?}",
vertices[i]
graph.incidences(v).count(),
incs.len(),
"unexpected incidence count for vertex {v:?}"
);
let mut expected = incidences[i].clone();
for incidence in graph.incidences(vertices[i]) {
let mut expected = incs.clone();
for incidence in graph.incidences(v) {
let pos = expected
.iter()
.position(|x| *x == incidence)
.position(|&x| x == incidence)
.unwrap_or_else(|| {
panic!(
"unexpected incidence {incidence:?} of vertex {:?} from iterator",
vertices[i]
)
panic!("unexpected incidence {incidence:?} of vertex {v:?} from iterator")
});
expected.swap_remove(pos);
}
assert!(
expected.is_empty(),
"expected incidences {:?} of vertex {:?} were not matched by iterator",
expected,
vertices[i]
"expected incidences {expected:?} of vertex {v:?} were not matched by iterator"
);
}
}
@@ -613,34 +589,28 @@ where
{
const K: usize = 3;
let (graph, vertices, edges) = G::multiple_edges::<K>();
for i in 0..2 {
let mut iter = graph.incidences(vertices[i]);
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 {:?}",
vertices[i]
)
panic!("incidence {j} missing, expected {K} incidences for vertex {v:?}")
});
assert_eq!(
current.vertex,
vertices[1 - i],
"unexpected adjacent vertex of vertex {:?} in incidence {j}",
vertices[i]
"unexpected adjacent vertex of vertex {v:?} in incidence {j}"
);
assert_eq!(
edges.iter().filter(|e| **e == current.edge).count(),
edges.iter().filter(|&&e| e == current.edge).count(),
1,
"unexpected incident edge {:?} of vertex {:?}",
current.edge,
vertices[i],
"unexpected incident edge {:?} of vertex {v:?}",
current.edge
);
}
assert_eq!(
iter.next(),
None,
"too many adjacent vertices of {:?} from iterator",
vertices[i]
"too many adjacent vertices of {v:?} from iterator"
);
}
}
@@ -665,26 +635,22 @@ where
G::Edge: Debug,
{
let (graph, vertices, _, incidences) = G::standard();
for i in 0..10 {
let mut expected = incidences[i].clone();
let mut cursor = graph.incidence_cursor(vertices[i]);
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)
.position(|&x| x == incidence)
.unwrap_or_else(|| {
panic!(
"unexpected incidence {incidence:?} of vertex {:?} from cursor",
vertices[i]
)
panic!("unexpected incidence {incidence:?} of vertex {v:?} from cursor")
});
expected.swap_remove(pos);
}
assert!(
expected.is_empty(),
"expected incidences {:?} of vertex {:?} were not matched by cursor",
expected,
vertices[i]
"expected incidences {expected:?} of vertex {v:?} were not matched by cursor"
);
}
}
@@ -716,34 +682,28 @@ where
{
const K: usize = 3;
let (graph, vertices, edges) = G::multiple_edges::<K>();
for i in 0..2 {
let mut cursor = graph.incidence_cursor(vertices[i]);
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 {:?}",
vertices[i]
)
panic!("incidence {j} missing, expected {K} incidences for vertex {v:?}")
});
assert_eq!(
current.vertex,
vertices[1 - i],
"unexpected adjacent vertex of vertex {:?} in incidence {j}",
vertices[i]
"unexpected adjacent vertex of vertex {v:?} in incidence {j}"
);
assert_eq!(
edges.iter().filter(|e| **e == current.edge).count(),
edges.iter().filter(|&&e| e == current.edge).count(),
1,
"unexpected incident edge {:?} of vertex {:?}",
current.edge,
vertices[i],
"unexpected incident edge {:?} of vertex {v:?}",
current.edge
);
}
assert_eq!(
cursor.next(&graph),
None,
"too many incidences of {:?} from cursor",
vertices[i]
"too many incidences of {v:?} from cursor"
);
}
}
@@ -800,15 +760,14 @@ where
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(|| {
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 {:?} of vertex {u:?} not matched by incident_edges",
expected
"incidence edges {expected:?} of vertex {u:?} not matched by incident_edges"
);
}
}
+1
View File
@@ -347,6 +347,7 @@ pub trait IncidenceCursor<G: GraphTopology + ?Sized>: Copy {
/// assert!(c2.next(&graph).is_some());
/// assert!(c2.next(&graph).is_none());
/// ```
// TODO: Replace the above example graph with a path generator function.
fn next(&mut self, graph: &G) -> Option<Incidence<G::Vertex, G::Edge>>;
}
+7 -13
View File
@@ -162,11 +162,10 @@ where
G::Vertex: Debug,
{
let (graph, vertices, _, _) = G::standard();
for i in 0..10 {
for v in vertices {
assert!(
algorithms::dfs_find(&graph, vertices[0], vertices[i]),
"vertex {:?} should be reachable from {:?}",
vertices[i],
algorithms::dfs_find(&graph, vertices[0], v),
"vertex {v:?} should be reachable from {:?}",
vertices[0]
);
}
@@ -328,12 +327,8 @@ fn assert_dfs_visited<G: GraphTopology>(
) where
G::Vertex: Debug,
{
for i in 0..10 {
assert!(
visited[vertices[i]],
"vertex {:?} should be visited",
vertices[i]
);
for &v in vertices {
assert!(visited[v], "vertex {v:?} should be visited");
}
}
@@ -349,9 +344,8 @@ fn assert_dfs_predecessors<G: GraphTopology>(
predecessors[vertices[0]], None,
"source should have no predecessor"
);
for i in 1..10 {
let v = vertices[i];
let p = predecessors[v].expect(&format!("vertex {v:?} should have a predecessor"));
for &v in vertices.iter().skip(1) {
let p = predecessors[v].unwrap_or_else(|| panic!("vertex {v:?} should have a predecessor"));
assert!(
visited[p],
"predecessor {p:?} of vertex {v:?} should be visited"
+25 -32
View File
@@ -6,7 +6,7 @@ use grapherity::algorithms::DijkstraResult;
use grapherity::maps::ElementMap;
use grapherity::testing::fixtures;
use grapherity::testing::fixtures::MakeTestGraph;
use grapherity::traits::{GraphTopology, Incidence};
use grapherity::traits::GraphTopology;
macro_rules! dijkstra_tests {
($T:ty) => {
@@ -78,21 +78,19 @@ fn dijkstra_zero_weight_loop<G: MakeTestGraph>()
where
G::Vertex: Debug + Hash,
{
let (graph, vertices, _, weights) = make_two_edge_path_with_zero_weight_loops::<G>();
let (graph, vertices, weights) = make_two_edge_path_with_zero_weight_loops::<G>();
let result = algorithms::dijkstra(&graph, vertices[0], |e| weights[e]);
assert_single_vertex::<G>(&result, vertices[0]);
for i in 1..3 {
for (i, &v) in vertices.iter().enumerate().skip(1) {
assert_eq!(
result.predecessors[vertices[i]],
result.predecessors[v],
Some(vertices[i - 1]),
"unexpected predecessor of vertex {:?}",
vertices[i]
"unexpected predecessor of vertex {v:?}"
);
assert_eq!(
result.distances[vertices[i]],
result.distances[v],
Some(i.try_into().unwrap()),
"unexpected distance of vertex {:?}",
vertices[i]
"unexpected distance of vertex {v:?}"
);
}
}
@@ -101,7 +99,7 @@ fn dijkstra<G: MakeTestGraph>()
where
G::Vertex: Debug + Hash,
{
let (graph, vertices, _, _, weights) = make_standard_weighted::<G>();
let (graph, vertices, weights) = make_standard_weighted::<G>();
let result = algorithms::dijkstra(&graph, vertices[0], |e| weights[e]);
assert_standard_weighted_distances_v0::<G>(&result.distances, &vertices);
assert_standard_weighted_predecessors_v0::<G>(&result.predecessors, &vertices);
@@ -111,7 +109,7 @@ fn dijkstra_distances<G: MakeTestGraph>()
where
G::Vertex: Debug + Hash,
{
let (graph, vertices, _, _, weights) = make_standard_weighted::<G>();
let (graph, vertices, weights) = make_standard_weighted::<G>();
let distances = algorithms::dijkstra_distances(&graph, vertices[0], |e| weights[e]);
assert_standard_weighted_distances_v0::<G>(&distances, &vertices);
}
@@ -201,7 +199,7 @@ fn assert_disconnected<G: GraphTopology>(
) where
G::Vertex: Debug,
{
assert_distances_disconnected::<G>(&result.distances, &vertices);
assert_distances_disconnected::<G>(&result.distances, vertices);
for &v in vertices {
assert_eq!(
result.predecessors[v], None,
@@ -242,12 +240,12 @@ fn assert_standard_weighted_predecessors_v0<G: GraphTopology>(
vec![Some(vertices[7])],
vec![Some(vertices[6])],
];
for i in 0..10 {
assert_eq!(vertices.len(), expected.len());
for (&v, exp) in vertices.iter().zip(&expected) {
assert!(
expected[i].contains(&actual[vertices[i]]),
"unexpected predecessor {:?} of {:?}",
actual[vertices[i]],
vertices[i]
exp.contains(&actual[v]),
"unexpected predecessor {:?} of {v:?}",
actual[v]
);
}
}
@@ -270,35 +268,30 @@ fn assert_standard_weighted_distances_v0<G: GraphTopology>(
Some(145),
Some(29),
];
for i in 0..10 {
assert_eq!(vertices.len(), expected.len());
for (&v, &exp) in vertices.iter().zip(&expected) {
assert_eq!(
actual[vertices[i]], expected[i],
"unexpected distance from {:?} to {:?}",
vertices[0], vertices[i]
actual[v], exp,
"unexpected distance from {:?} to {v:?}",
vertices[0]
);
}
}
fn make_standard_weighted<G: MakeTestGraph>() -> (
G,
[G::Vertex; 10],
[(G::Edge, G::Vertex, G::Vertex); 18],
[Vec<Incidence<G::Vertex, G::Edge>>; 10],
ElementMap<G::Edge, u32>,
) {
let (graph, vertices, edges, incidences) = G::standard();
fn make_standard_weighted<G: MakeTestGraph>() -> (G, [G::Vertex; 10], ElementMap<G::Edge, u32>) {
let (graph, vertices, edges, _) = G::standard();
let mut weights = graph.edge_map(99);
for i in [1, 3, 7, 10, 12, 14, 15, 17] {
weights[edges[i].0] = i.try_into().unwrap();
}
(graph, vertices, edges, incidences, weights)
(graph, vertices, weights)
}
fn make_two_edge_path_with_zero_weight_loops<G: MakeTestGraph>()
-> (G, [G::Vertex; 3], [G::Edge; 4], ElementMap<G::Edge, u32>) {
-> (G, [G::Vertex; 3], ElementMap<G::Edge, u32>) {
let (graph, vertices, edges) = G::two_edge_path_with_loops();
let mut weights = graph.edge_map(1);
weights[edges[2]] = 0;
weights[edges[3]] = 0;
(graph, vertices, edges, weights)
(graph, vertices, weights)
}