diff --git a/src/algorithms.rs b/src/algorithms.rs index d36653d..19ff46d 100644 --- a/src/algorithms.rs +++ b/src/algorithms.rs @@ -558,8 +558,7 @@ where let mut visited = graph.vertex_map(false); visited[source] = true; - let mut predecessor: ElementMap> = - graph.vertex_map(None); + let mut predecessor = graph.vertex_map(None); let mut queue = VecDeque::from([source]); while let Some(v) = queue.pop_front() { diff --git a/src/lib.rs b/src/lib.rs index 843225d..51f83a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,10 +6,10 @@ //! Currently supported are: //! //! * Undirected graph types [`Graph`], [`AppendGraph`], and [`FrozenGraph`] built on a flat, -//! index-based adjacency list, +//! index-based adjacency list, //! * [`ElementMap`] to freely associate custom data with vertices and edges, //! * Connectivity and pathing algorithms: [Dijkstra's algorithm], [DFS], and [BFS] in different -//! variants, +//! variants, //! * Exposed [`traits`] to implement custom graph data structures or algorithms. //! //! # Usage example diff --git a/src/maps.rs b/src/maps.rs index bb45b09..7c01d8a 100644 --- a/src/maps.rs +++ b/src/maps.rs @@ -89,7 +89,7 @@ impl ElementMap { /// ``` pub fn map(&self, f: impl Fn(&T) -> U) -> ElementMap { 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, } diff --git a/src/models/frozen_graph.rs b/src/models/frozen_graph.rs index 9167f69..4c1f8c5 100644 --- a/src/models/frozen_graph.rs +++ b/src/models/frozen_graph.rs @@ -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, diff --git a/src/testing/fixtures.rs b/src/testing/fixtures.rs index 52e8953..721bf1f 100644 --- a/src/testing/fixtures.rs +++ b/src/testing/fixtures.rs @@ -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( 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:?}" ) }); diff --git a/src/testing/graph_topology_addition_testing.rs b/src/testing/graph_topology_addition_testing.rs index 935d715..c15d0e6 100644 --- a/src/testing/graph_topology_addition_testing.rs +++ b/src/testing/graph_topology_addition_testing.rs @@ -43,10 +43,11 @@ pub fn reserve_vertices_increases_capacity() { } pub fn reserve_vertices_prevents_reallocation_on_add() { + 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() { } pub fn reserve_edges_prevents_reallocation_on_add() { + 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!( diff --git a/src/testing/graph_topology_deletion_testing.rs b/src/testing/graph_topology_deletion_testing.rs index 1ef5217..7ad8edf 100644 --- a/src/testing/graph_topology_deletion_testing.rs +++ b/src/testing/graph_topology_deletion_testing.rs @@ -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( 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( 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( 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" ); } diff --git a/src/testing/graph_topology_testing.rs b/src/testing/graph_topology_testing.rs index df58962..2c4c394 100644 --- a/src/testing/graph_topology_testing.rs +++ b/src/testing/graph_topology_testing.rs @@ -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::(); - 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::(); - 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::(); - 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::(); - 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" ); } } diff --git a/src/traits.rs b/src/traits.rs index 0d5414b..7f27523 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -347,6 +347,7 @@ pub trait IncidenceCursor: 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>; } diff --git a/tests/dfs.rs b/tests/dfs.rs index 25fa58b..39afd23 100644 --- a/tests/dfs.rs +++ b/tests/dfs.rs @@ -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( ) 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( 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" diff --git a/tests/dijkstra.rs b/tests/dijkstra.rs index 36a69cc..a2f5559 100644 --- a/tests/dijkstra.rs +++ b/tests/dijkstra.rs @@ -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() where G::Vertex: Debug + Hash, { - let (graph, vertices, _, weights) = make_two_edge_path_with_zero_weight_loops::(); + let (graph, vertices, weights) = make_two_edge_path_with_zero_weight_loops::(); let result = algorithms::dijkstra(&graph, vertices[0], |e| weights[e]); assert_single_vertex::(&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() where G::Vertex: Debug + Hash, { - let (graph, vertices, _, _, weights) = make_standard_weighted::(); + let (graph, vertices, weights) = make_standard_weighted::(); let result = algorithms::dijkstra(&graph, vertices[0], |e| weights[e]); assert_standard_weighted_distances_v0::(&result.distances, &vertices); assert_standard_weighted_predecessors_v0::(&result.predecessors, &vertices); @@ -111,7 +109,7 @@ fn dijkstra_distances() where G::Vertex: Debug + Hash, { - let (graph, vertices, _, _, weights) = make_standard_weighted::(); + let (graph, vertices, weights) = make_standard_weighted::(); let distances = algorithms::dijkstra_distances(&graph, vertices[0], |e| weights[e]); assert_standard_weighted_distances_v0::(&distances, &vertices); } @@ -201,7 +199,7 @@ fn assert_disconnected( ) where G::Vertex: Debug, { - assert_distances_disconnected::(&result.distances, &vertices); + assert_distances_disconnected::(&result.distances, vertices); for &v in vertices { assert_eq!( result.predecessors[v], None, @@ -242,12 +240,12 @@ fn assert_standard_weighted_predecessors_v0( 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( 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, - [G::Vertex; 10], - [(G::Edge, G::Vertex, G::Vertex); 18], - [Vec>; 10], - ElementMap, -) { - let (graph, vertices, edges, incidences) = G::standard(); +fn make_standard_weighted() -> (G, [G::Vertex; 10], ElementMap) { + 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, [G::Vertex; 3], [G::Edge; 4], ElementMap) { +-> (G, [G::Vertex; 3], ElementMap) { 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) }