Release 0.3.0 #8
+1
-2
@@ -558,8 +558,7 @@ where
|
|||||||
|
|
||||||
let mut visited = graph.vertex_map(false);
|
let mut visited = graph.vertex_map(false);
|
||||||
visited[source] = true;
|
visited[source] = true;
|
||||||
let mut predecessor: ElementMap<G::Vertex, Option<(G::Vertex, G::Edge)>> =
|
let mut predecessor = graph.vertex_map(None);
|
||||||
graph.vertex_map(None);
|
|
||||||
let mut queue = VecDeque::from([source]);
|
let mut queue = VecDeque::from([source]);
|
||||||
|
|
||||||
while let Some(v) = queue.pop_front() {
|
while let Some(v) = queue.pop_front() {
|
||||||
|
|||||||
+2
-2
@@ -6,10 +6,10 @@
|
|||||||
//! Currently supported are:
|
//! Currently supported are:
|
||||||
//!
|
//!
|
||||||
//! * Undirected graph types [`Graph`], [`AppendGraph`], and [`FrozenGraph`] built on a flat,
|
//! * 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,
|
//! * [`ElementMap`] to freely associate custom data with vertices and edges,
|
||||||
//! * Connectivity and pathing algorithms: [Dijkstra's algorithm], [DFS], and [BFS] in different
|
//! * Connectivity and pathing algorithms: [Dijkstra's algorithm], [DFS], and [BFS] in different
|
||||||
//! variants,
|
//! variants,
|
||||||
//! * Exposed [`traits`] to implement custom graph data structures or algorithms.
|
//! * Exposed [`traits`] to implement custom graph data structures or algorithms.
|
||||||
//!
|
//!
|
||||||
//! # Usage example
|
//! # Usage example
|
||||||
|
|||||||
+1
-1
@@ -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> {
|
pub fn map<U: Clone>(&self, f: impl Fn(&T) -> U) -> ElementMap<E, U> {
|
||||||
ElementMap {
|
ElementMap {
|
||||||
data: self.data.iter().map(|v| f(v)).collect(),
|
data: self.data.iter().map(&f).collect(),
|
||||||
default: f(&self.default),
|
default: f(&self.default),
|
||||||
to_index: self.to_index,
|
to_index: self.to_index,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -308,8 +308,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn opposite_symmetry() {
|
fn opposite_symmetry() {
|
||||||
let (graph, ..) = FrozenGraph::standard();
|
let (graph, ..) = FrozenGraph::standard();
|
||||||
for i in 0..graph.incidences.len() {
|
for (i, inc) in graph.incidences.iter().enumerate() {
|
||||||
let opp = graph.incidences[i].opposite;
|
let opp = inc.opposite;
|
||||||
assert_ne!(opp, i, "incidence should not equal its own opposite");
|
assert_ne!(opp, i, "incidence should not equal its own opposite");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
graph.incidences[opp].opposite, i,
|
graph.incidences[opp].opposite, i,
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ use crate::models::{AppendGraph, FrozenGraph};
|
|||||||
use crate::traits::{GraphTopology, GraphTopologyAddition, GraphTopologyConversion, Incidence};
|
use crate::traits::{GraphTopology, GraphTopologyAddition, GraphTopologyConversion, Incidence};
|
||||||
|
|
||||||
pub trait MakeTestGraph: GraphTopology + Sized {
|
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() -> (
|
fn standard() -> (
|
||||||
Self,
|
Self,
|
||||||
[Self::Vertex; 10],
|
[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[4])],
|
||||||
vec![Some(vertices[5]), Some(vertices[6]), Some(vertices[7])],
|
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!(
|
assert!(
|
||||||
expected[i].contains(&actual[vertices[i]]),
|
exp.contains(&actual[v]),
|
||||||
"unexpected predecessor {:?} of vertex {:?}",
|
"unexpected predecessor {:?} of vertex {v:?}",
|
||||||
actual[vertices[i]],
|
actual[v]
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -320,8 +322,7 @@ where
|
|||||||
{
|
{
|
||||||
let path = path_option.unwrap_or_else(|| {
|
let path = path_option.unwrap_or_else(|| {
|
||||||
panic!(
|
panic!(
|
||||||
"path should exist between source vertex {:?} and connected targets {:?}",
|
"path should exist between source vertex {source:?} and connected targets {targets:?}"
|
||||||
source, targets
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -43,10 +43,11 @@ pub fn reserve_vertices_increases_capacity<G: GraphTopologyAddition>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn reserve_vertices_prevents_reallocation_on_add<G: GraphTopologyAddition>() {
|
pub fn reserve_vertices_prevents_reallocation_on_add<G: GraphTopologyAddition>() {
|
||||||
|
const N: usize = 10;
|
||||||
let mut graph = G::default();
|
let mut graph = G::default();
|
||||||
graph.reserve_vertices(10);
|
graph.reserve_vertices(N);
|
||||||
let capacity_before = graph.vertex_capacity();
|
let capacity_before = graph.vertex_capacity();
|
||||||
for _ in 0..10 {
|
for _ in 0..N {
|
||||||
graph.add_vertex();
|
graph.add_vertex();
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -78,12 +79,13 @@ pub fn reserve_edges_increases_capacity<G: GraphTopologyAddition>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn reserve_edges_prevents_reallocation_on_add<G: GraphTopologyAddition>() {
|
pub fn reserve_edges_prevents_reallocation_on_add<G: GraphTopologyAddition>() {
|
||||||
|
const N: usize = 10;
|
||||||
let mut graph = G::default();
|
let mut graph = G::default();
|
||||||
let u = graph.add_vertex();
|
let u = graph.add_vertex();
|
||||||
let v = graph.add_vertex();
|
let v = graph.add_vertex();
|
||||||
graph.reserve_edges(10);
|
graph.reserve_edges(N);
|
||||||
let capacity_before = graph.edge_capacity();
|
let capacity_before = graph.edge_capacity();
|
||||||
for _ in 0..10 {
|
for _ in 0..N {
|
||||||
graph.add_edge(u, v);
|
graph.add_edge(u, v);
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
@@ -262,7 +262,8 @@ where
|
|||||||
G::Vertex: Debug,
|
G::Vertex: Debug,
|
||||||
{
|
{
|
||||||
let (mut graph, vertices, _, _) = G::standard();
|
let (mut graph, vertices, _, _) = G::standard();
|
||||||
graph.delete_vertex(vertices[2]);
|
let del = vertices[2];
|
||||||
|
graph.delete_vertex(del);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
graph.vertex_count(),
|
graph.vertex_count(),
|
||||||
9,
|
9,
|
||||||
@@ -274,17 +275,12 @@ where
|
|||||||
"unexpected vertex iterator count after delete"
|
"unexpected vertex iterator count after delete"
|
||||||
);
|
);
|
||||||
for v in graph.vertices() {
|
for v in graph.vertices() {
|
||||||
assert_ne!(
|
assert_ne!(v, del, "deleted vertex {del:?} appeared in iterator");
|
||||||
v, vertices[2],
|
|
||||||
"deleted vertex {:?} appeared in iterator",
|
|
||||||
vertices[2]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
|
for &v in vertices.iter().filter(|&&u| u != del) {
|
||||||
assert!(
|
assert!(
|
||||||
graph.vertices().any(|v| v == vertices[i]),
|
graph.vertices().any(|u| u == v),
|
||||||
"expected vertex {:?} missing from iterator after delete",
|
"expected vertex {v:?} missing from iterator after delete"
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,9 +291,9 @@ where
|
|||||||
G::Edge: Debug,
|
G::Edge: Debug,
|
||||||
{
|
{
|
||||||
let (mut graph, _, edges, _) = G::standard();
|
let (mut graph, _, edges, _) = G::standard();
|
||||||
let e = edges[2].0;
|
let del = edges[2].0;
|
||||||
graph.delete_edge(e);
|
graph.delete_edge(del);
|
||||||
for &(f, v0, v1) in edges.iter().filter(|&&(f, _, _)| f != e) {
|
for &(f, v0, v1) in edges.iter().filter(|&&(f, _, _)| f != del) {
|
||||||
let (u0, u1) = graph.incident_vertices(f);
|
let (u0, u1) = graph.incident_vertices(f);
|
||||||
assert!(
|
assert!(
|
||||||
(u0 == v0 && u1 == v1) || (u0 == v1 && u1 == v0),
|
(u0 == v0 && u1 == v1) || (u0 == v1 && u1 == v0),
|
||||||
@@ -340,13 +336,15 @@ where
|
|||||||
G::Edge: Debug,
|
G::Edge: Debug,
|
||||||
{
|
{
|
||||||
let (mut graph, vertices, edges, incidences) = G::standard();
|
let (mut graph, vertices, edges, incidences) = G::standard();
|
||||||
graph.delete_edge(edges[2].0);
|
let del = edges[2].0;
|
||||||
for i in 0..10 {
|
graph.delete_edge(del);
|
||||||
let mut expected: Vec<_> = incidences[i]
|
assert_eq!(vertices.len(), incidences.len());
|
||||||
|
for (&v, incs) in vertices.iter().zip(&incidences) {
|
||||||
|
let mut expected = incs
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|x| (x.edge != edges[2].0).then_some(x.edge))
|
.filter_map(|x| (x.edge != del).then_some(x.edge))
|
||||||
.collect();
|
.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,
|
G::Edge: Debug,
|
||||||
{
|
{
|
||||||
let (mut graph, vertices, _, incidences) = G::standard();
|
let (mut graph, vertices, _, incidences) = G::standard();
|
||||||
graph.delete_vertex(vertices[2]);
|
let del = vertices[2];
|
||||||
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
|
graph.delete_vertex(del);
|
||||||
let mut expected: Vec<_> = incidences[i]
|
for (&v, incs) in vertices.iter().zip(&incidences).filter(|&(&u, _)| u != del) {
|
||||||
|
let mut expected = incs
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|x| (x.vertex != vertices[2]).then_some(x.edge))
|
.filter_map(|x| (x.vertex != del).then_some(x.edge))
|
||||||
.collect();
|
.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,
|
G::Edge: Debug,
|
||||||
{
|
{
|
||||||
let (mut graph, vertices, _, incidences) = G::standard();
|
let (mut graph, vertices, _, incidences) = G::standard();
|
||||||
graph.delete_vertex(vertices[2]);
|
let del = vertices[2];
|
||||||
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
|
graph.delete_vertex(del);
|
||||||
let remaining = incidences[i]
|
for (&v, incs) in vertices.iter().zip(&incidences).filter(|&(&u, _)| u != del) {
|
||||||
.iter()
|
let remaining = incs.iter().filter(|x| x.vertex != del).cloned().collect();
|
||||||
.filter(|x| x.vertex != vertices[2])
|
assert_vertex_incidences(&graph, v, remaining);
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
assert_vertex_incidences(&graph, vertices[i], remaining);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,14 +385,12 @@ where
|
|||||||
G::Edge: Debug,
|
G::Edge: Debug,
|
||||||
{
|
{
|
||||||
let (mut graph, vertices, edges, incidences) = G::standard();
|
let (mut graph, vertices, edges, incidences) = G::standard();
|
||||||
graph.delete_edge(edges[2].0);
|
let del = edges[2].0;
|
||||||
for i in 0..10 {
|
graph.delete_edge(del);
|
||||||
let remaining = incidences[i]
|
assert_eq!(vertices.len(), incidences.len());
|
||||||
.iter()
|
for (&v, incs) in vertices.iter().zip(&incidences) {
|
||||||
.filter(|x| x.edge != edges[2].0)
|
let remaining = incs.iter().filter(|x| x.edge != del).cloned().collect();
|
||||||
.cloned()
|
assert_vertex_incidences(&graph, v, remaining);
|
||||||
.collect();
|
|
||||||
assert_vertex_incidences(&graph, vertices[i], remaining);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,14 +400,11 @@ where
|
|||||||
G::Edge: Debug,
|
G::Edge: Debug,
|
||||||
{
|
{
|
||||||
let (mut graph, vertices, _, incidences) = G::standard();
|
let (mut graph, vertices, _, incidences) = G::standard();
|
||||||
graph.delete_vertex(vertices[2]);
|
let del = vertices[2];
|
||||||
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
|
graph.delete_vertex(del);
|
||||||
let remaining = incidences[i]
|
for (&v, incs) in vertices.iter().zip(&incidences).filter(|&(&u, _)| u != del) {
|
||||||
.iter()
|
let remaining = incs.iter().filter(|x| x.vertex != del).cloned().collect();
|
||||||
.filter(|x| x.vertex != vertices[2])
|
assert_vertex_incidence_cursor(&graph, v, remaining);
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
assert_vertex_incidence_cursor(&graph, vertices[i], remaining);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,14 +414,12 @@ where
|
|||||||
G::Edge: Debug,
|
G::Edge: Debug,
|
||||||
{
|
{
|
||||||
let (mut graph, vertices, edges, incidences) = G::standard();
|
let (mut graph, vertices, edges, incidences) = G::standard();
|
||||||
graph.delete_edge(edges[2].0);
|
let del = edges[2].0;
|
||||||
for i in 0..10 {
|
graph.delete_edge(del);
|
||||||
let remaining = incidences[i]
|
assert_eq!(vertices.len(), incidences.len());
|
||||||
.iter()
|
for (&v, incs) in vertices.iter().zip(&incidences) {
|
||||||
.filter(|x| x.edge != edges[2].0)
|
let remaining = incs.iter().filter(|x| x.edge != del).cloned().collect();
|
||||||
.cloned()
|
assert_vertex_incidence_cursor(&graph, v, remaining);
|
||||||
.collect();
|
|
||||||
assert_vertex_incidence_cursor(&graph, vertices[i], remaining);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,26 +434,22 @@ fn assert_vertex_incidences<G: GraphTopology>(
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
graph.incidences(v).count(),
|
graph.incidences(v).count(),
|
||||||
expected.len(),
|
expected.len(),
|
||||||
"unexpected incidence count for vertex {:?} after delete",
|
"unexpected incidence count for vertex {v:?} after delete"
|
||||||
v
|
|
||||||
);
|
);
|
||||||
for incidence in graph.incidences(v) {
|
for incidence in graph.incidences(v) {
|
||||||
let pos = expected
|
let pos = expected
|
||||||
.iter()
|
.iter()
|
||||||
.position(|x| *x == incidence)
|
.position(|&x| x == incidence)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
panic!(
|
panic!(
|
||||||
"unexpected incidence {incidence:?} of vertex {:?} from iterator after delete",
|
"unexpected incidence {incidence:?} of vertex {v:?} from iterator after delete"
|
||||||
v
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
expected.swap_remove(pos);
|
expected.swap_remove(pos);
|
||||||
}
|
}
|
||||||
assert!(
|
assert!(
|
||||||
expected.is_empty(),
|
expected.is_empty(),
|
||||||
"expected incidences {:?} of vertex {:?} not matched by iterator after delete",
|
"expected incidences {expected:?} of vertex {v:?} not matched by iterator after delete"
|
||||||
expected,
|
|
||||||
v
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,20 +465,17 @@ fn assert_vertex_incidence_cursor<G: GraphTopology>(
|
|||||||
while let Some(incidence) = cursor.next(graph) {
|
while let Some(incidence) = cursor.next(graph) {
|
||||||
let pos = expected
|
let pos = expected
|
||||||
.iter()
|
.iter()
|
||||||
.position(|x| *x == incidence)
|
.position(|&x| x == incidence)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
panic!(
|
panic!(
|
||||||
"unexpected incidence {incidence:?} of vertex {:?} from cursor after delete",
|
"unexpected incidence {incidence:?} of vertex {v:?} from cursor after delete"
|
||||||
v
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
expected.swap_remove(pos);
|
expected.swap_remove(pos);
|
||||||
}
|
}
|
||||||
assert!(
|
assert!(
|
||||||
expected.is_empty(),
|
expected.is_empty(),
|
||||||
"expected incidences {:?} of vertex {:?} not matched by cursor after delete",
|
"expected incidences {expected:?} of vertex {v:?} not matched by cursor after delete"
|
||||||
expected,
|
|
||||||
v
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,22 +490,16 @@ fn assert_incident_edges_after_delete<G: GraphTopology>(
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
graph.incident_edges(v).count(),
|
graph.incident_edges(v).count(),
|
||||||
expected.len(),
|
expected.len(),
|
||||||
"unexpected incident edge count for vertex {:?} after delete",
|
"unexpected incident edge count for vertex {v:?} after delete"
|
||||||
v
|
|
||||||
);
|
);
|
||||||
for e in graph.incident_edges(v) {
|
for e in graph.incident_edges(v) {
|
||||||
let pos = expected.iter().position(|f| *f == e).unwrap_or_else(|| {
|
let pos = expected.iter().position(|&f| f == e).unwrap_or_else(|| {
|
||||||
panic!(
|
panic!("unexpected incident edge {e:?} of vertex {v:?} after delete")
|
||||||
"unexpected incident edge {e:?} of vertex {:?} after delete",
|
|
||||||
v
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
expected.swap_remove(pos);
|
expected.swap_remove(pos);
|
||||||
}
|
}
|
||||||
assert!(
|
assert!(
|
||||||
expected.is_empty(),
|
expected.is_empty(),
|
||||||
"expected incident edges {:?} of vertex {:?} not matched after delete",
|
"expected incident edges {expected:?} of vertex {v:?} not matched after delete"
|
||||||
expected,
|
|
||||||
v
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,14 +128,10 @@ where
|
|||||||
G::Vertex: Debug,
|
G::Vertex: Debug,
|
||||||
{
|
{
|
||||||
let (graph, vertices, _, _) = G::standard();
|
let (graph, vertices, _, _) = G::standard();
|
||||||
let expected_degrees = [2, 5, 7, 2, 7, 2, 3, 3, 2, 3];
|
let expected = [2, 5, 7, 2, 7, 2, 3, 3, 2, 3];
|
||||||
for i in 0..graph.vertex_count() {
|
assert_eq!(vertices.len(), expected.len());
|
||||||
assert_eq!(
|
for (&v, &exp) in vertices.iter().zip(&expected) {
|
||||||
graph.degree(vertices[i]),
|
assert_eq!(graph.degree(v), exp, "unexpected degree of {v:?}");
|
||||||
expected_degrees[i],
|
|
||||||
"unexpected degree of {:?}",
|
|
||||||
vertices[i]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,23 +196,18 @@ where
|
|||||||
vertices[9],
|
vertices[9],
|
||||||
vertices[3]
|
vertices[3]
|
||||||
);
|
);
|
||||||
for i in 0..graph.vertex_count() {
|
for (i, &v) in vertices.iter().enumerate() {
|
||||||
let exp = match i {
|
let exp = matches!(i, 1 | 2 | 4 | 5 | 6);
|
||||||
1 | 2 | 4 | 5 | 6 => true,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
graph.are_adjacent(vertices[2], vertices[i]),
|
graph.are_adjacent(vertices[2], v),
|
||||||
exp,
|
exp,
|
||||||
"unexpected adjacency of {:?} and {:?}",
|
"unexpected adjacency of {:?} and {v:?}",
|
||||||
vertices[2],
|
vertices[2]
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
graph.are_adjacent(vertices[i], vertices[2]),
|
graph.are_adjacent(v, vertices[2]),
|
||||||
exp,
|
exp,
|
||||||
"unexpected adjacency of {:?} and {:?}",
|
"unexpected adjacency of {v:?} and {:?}",
|
||||||
vertices[i],
|
|
||||||
vertices[2]
|
vertices[2]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -289,8 +280,7 @@ where
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
expected_adjacency.len(),
|
expected_adjacency.len(),
|
||||||
0,
|
0,
|
||||||
"expected adjacent vertices {:?} of {:?} were not matched by iterator",
|
"expected adjacent vertices {expected_adjacency:?} of {:?} were not matched by iterator",
|
||||||
expected_adjacency,
|
|
||||||
vertices[4]
|
vertices[4]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -320,21 +310,19 @@ where
|
|||||||
{
|
{
|
||||||
const K: usize = 3;
|
const K: usize = 3;
|
||||||
let (graph, vertices, _) = G::multiple_edges::<K>();
|
let (graph, vertices, _) = G::multiple_edges::<K>();
|
||||||
for i in 0..2 {
|
for (i, &v) in vertices.iter().enumerate() {
|
||||||
let mut iter = graph.adjacent_vertices(vertices[i]);
|
let mut iter = graph.adjacent_vertices(v);
|
||||||
for j in 0..K {
|
for j in 0..K {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
iter.next(),
|
iter.next(),
|
||||||
Some(vertices[1 - i]),
|
Some(vertices[1 - i]),
|
||||||
"unexpected adjacent vertex {j} of vertex {:?}",
|
"unexpected adjacent vertex {j} of vertex {v:?}"
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
iter.next(),
|
iter.next(),
|
||||||
None,
|
None,
|
||||||
"too many adjacent vertices of vertex {:?} from iterator",
|
"too many adjacent vertices of vertex {v:?} from iterator"
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -372,12 +360,11 @@ where
|
|||||||
{
|
{
|
||||||
let (graph, [v0, v1], edges) = G::multiple_edges::<2>();
|
let (graph, [v0, v1], edges) = G::multiple_edges::<2>();
|
||||||
assert_ne!(edges[0], edges[1], "edges should be distinct");
|
assert_ne!(edges[0], edges[1], "edges should be distinct");
|
||||||
for i in 0..2 {
|
for (i, &e) in edges.iter().enumerate() {
|
||||||
let (u0, u1) = graph.incident_vertices(edges[i]);
|
let (u0, u1) = graph.incident_vertices(e);
|
||||||
assert!(
|
assert!(
|
||||||
(u0 == v0 && u1 == v1) || (u0 == v1 && u1 == v0),
|
(u0 == v0 && u1 == v1) || (u0 == v1 && u1 == v0),
|
||||||
"unexpected incident vertices {u0:?} and {u1:?} for multi-edge {:?} (index {i})",
|
"unexpected incident vertices {u0:?} and {u1:?} for multi-edge {e:?} (index {i})"
|
||||||
edges[i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -436,28 +423,23 @@ where
|
|||||||
G::Edge: Debug,
|
G::Edge: Debug,
|
||||||
{
|
{
|
||||||
let (graph, vertices, _, incidences) = G::standard();
|
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!(
|
assert_eq!(
|
||||||
graph.incident_edges(vertices[i]).count(),
|
graph.incident_edges(v).count(),
|
||||||
incidences[i].len(),
|
incs.len(),
|
||||||
"unexpected incident edge count for vertex {:?}",
|
"unexpected incident edge count for vertex {v:?}"
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
let mut expected: Vec<_> = incidences[i].iter().map(|x| x.edge).collect();
|
let mut expected: Vec<_> = incs.iter().map(|x| x.edge).collect();
|
||||||
for e in graph.incident_edges(vertices[i]) {
|
for e in graph.incident_edges(v) {
|
||||||
let pos = expected.iter().position(|f| *f == e).unwrap_or_else(|| {
|
let pos = expected.iter().position(|&f| f == e).unwrap_or_else(|| {
|
||||||
panic!(
|
panic!("unexpected incident edge {e:?} of vertex {v:?} from iterator")
|
||||||
"unexpected incident edge {e:?} of vertex {:?} from iterator",
|
|
||||||
vertices[i]
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
expected.swap_remove(pos);
|
expected.swap_remove(pos);
|
||||||
}
|
}
|
||||||
assert!(
|
assert!(
|
||||||
expected.is_empty(),
|
expected.is_empty(),
|
||||||
"expected incident edges {:?} of vertex {:?} were not matched by iterator",
|
"expected incident edges {expected:?} of vertex {v:?} were not matched by iterator"
|
||||||
expected,
|
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -488,19 +470,18 @@ where
|
|||||||
{
|
{
|
||||||
const K: usize = 3;
|
const K: usize = 3;
|
||||||
let (graph, vertices, edges) = G::multiple_edges::<K>();
|
let (graph, vertices, edges) = G::multiple_edges::<K>();
|
||||||
for i in 0..2 {
|
for &v in &vertices {
|
||||||
let mut expected = edges.to_vec();
|
let mut expected = edges.to_vec();
|
||||||
for e in graph.incident_edges(vertices[i]) {
|
for e in graph.incident_edges(v) {
|
||||||
let pos = expected.iter().position(|f| *f == e).unwrap_or_else(|| {
|
let pos = expected
|
||||||
panic!("unexpected incident edge {e:?} of vertex {:?}", vertices[i])
|
.iter()
|
||||||
});
|
.position(|&f| f == e)
|
||||||
|
.unwrap_or_else(|| panic!("unexpected incident edge {e:?} of vertex {v:?}"));
|
||||||
expected.swap_remove(pos);
|
expected.swap_remove(pos);
|
||||||
}
|
}
|
||||||
assert!(
|
assert!(
|
||||||
expected.is_empty(),
|
expected.is_empty(),
|
||||||
"expected incident edges {:?} of vertex {:?} were not matched by iterator",
|
"expected incident edges {expected:?} of vertex {v:?} were not matched by iterator"
|
||||||
expected,
|
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -520,31 +501,26 @@ where
|
|||||||
G::Edge: Debug,
|
G::Edge: Debug,
|
||||||
{
|
{
|
||||||
let (graph, vertices, _, incidences) = G::standard();
|
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!(
|
assert_eq!(
|
||||||
graph.incidences(vertices[i]).count(),
|
graph.incidences(v).count(),
|
||||||
incidences[i].len(),
|
incs.len(),
|
||||||
"unexpected incidence count for vertex {:?}",
|
"unexpected incidence count for vertex {v:?}"
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
let mut expected = incidences[i].clone();
|
let mut expected = incs.clone();
|
||||||
for incidence in graph.incidences(vertices[i]) {
|
for incidence in graph.incidences(v) {
|
||||||
let pos = expected
|
let pos = expected
|
||||||
.iter()
|
.iter()
|
||||||
.position(|x| *x == incidence)
|
.position(|&x| x == incidence)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
panic!(
|
panic!("unexpected incidence {incidence:?} of vertex {v:?} from iterator")
|
||||||
"unexpected incidence {incidence:?} of vertex {:?} from iterator",
|
|
||||||
vertices[i]
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
expected.swap_remove(pos);
|
expected.swap_remove(pos);
|
||||||
}
|
}
|
||||||
assert!(
|
assert!(
|
||||||
expected.is_empty(),
|
expected.is_empty(),
|
||||||
"expected incidences {:?} of vertex {:?} were not matched by iterator",
|
"expected incidences {expected:?} of vertex {v:?} were not matched by iterator"
|
||||||
expected,
|
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -613,34 +589,28 @@ where
|
|||||||
{
|
{
|
||||||
const K: usize = 3;
|
const K: usize = 3;
|
||||||
let (graph, vertices, edges) = G::multiple_edges::<K>();
|
let (graph, vertices, edges) = G::multiple_edges::<K>();
|
||||||
for i in 0..2 {
|
for (i, &v) in vertices.iter().enumerate() {
|
||||||
let mut iter = graph.incidences(vertices[i]);
|
let mut iter = graph.incidences(v);
|
||||||
for j in 0..K {
|
for j in 0..K {
|
||||||
let current = iter.next().unwrap_or_else(|| {
|
let current = iter.next().unwrap_or_else(|| {
|
||||||
panic!(
|
panic!("incidence {j} missing, expected {K} incidences for vertex {v:?}")
|
||||||
"incidence {j} missing, expected {K} incidences for vertex {:?}",
|
|
||||||
vertices[i]
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
current.vertex,
|
current.vertex,
|
||||||
vertices[1 - i],
|
vertices[1 - i],
|
||||||
"unexpected adjacent vertex of vertex {:?} in incidence {j}",
|
"unexpected adjacent vertex of vertex {v:?} in incidence {j}"
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
edges.iter().filter(|e| **e == current.edge).count(),
|
edges.iter().filter(|&&e| e == current.edge).count(),
|
||||||
1,
|
1,
|
||||||
"unexpected incident edge {:?} of vertex {:?}",
|
"unexpected incident edge {:?} of vertex {v:?}",
|
||||||
current.edge,
|
current.edge
|
||||||
vertices[i],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
iter.next(),
|
iter.next(),
|
||||||
None,
|
None,
|
||||||
"too many adjacent vertices of {:?} from iterator",
|
"too many adjacent vertices of {v:?} from iterator"
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -665,26 +635,22 @@ where
|
|||||||
G::Edge: Debug,
|
G::Edge: Debug,
|
||||||
{
|
{
|
||||||
let (graph, vertices, _, incidences) = G::standard();
|
let (graph, vertices, _, incidences) = G::standard();
|
||||||
for i in 0..10 {
|
assert_eq!(vertices.len(), incidences.len());
|
||||||
let mut expected = incidences[i].clone();
|
for (&v, incs) in vertices.iter().zip(&incidences) {
|
||||||
let mut cursor = graph.incidence_cursor(vertices[i]);
|
let mut expected = incs.clone();
|
||||||
|
let mut cursor = graph.incidence_cursor(v);
|
||||||
while let Some(incidence) = cursor.next(&graph) {
|
while let Some(incidence) = cursor.next(&graph) {
|
||||||
let pos = expected
|
let pos = expected
|
||||||
.iter()
|
.iter()
|
||||||
.position(|x| *x == incidence)
|
.position(|&x| x == incidence)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
panic!(
|
panic!("unexpected incidence {incidence:?} of vertex {v:?} from cursor")
|
||||||
"unexpected incidence {incidence:?} of vertex {:?} from cursor",
|
|
||||||
vertices[i]
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
expected.swap_remove(pos);
|
expected.swap_remove(pos);
|
||||||
}
|
}
|
||||||
assert!(
|
assert!(
|
||||||
expected.is_empty(),
|
expected.is_empty(),
|
||||||
"expected incidences {:?} of vertex {:?} were not matched by cursor",
|
"expected incidences {expected:?} of vertex {v:?} were not matched by cursor"
|
||||||
expected,
|
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -716,34 +682,28 @@ where
|
|||||||
{
|
{
|
||||||
const K: usize = 3;
|
const K: usize = 3;
|
||||||
let (graph, vertices, edges) = G::multiple_edges::<K>();
|
let (graph, vertices, edges) = G::multiple_edges::<K>();
|
||||||
for i in 0..2 {
|
for (i, &v) in vertices.iter().enumerate() {
|
||||||
let mut cursor = graph.incidence_cursor(vertices[i]);
|
let mut cursor = graph.incidence_cursor(v);
|
||||||
for j in 0..K {
|
for j in 0..K {
|
||||||
let current = cursor.next(&graph).unwrap_or_else(|| {
|
let current = cursor.next(&graph).unwrap_or_else(|| {
|
||||||
panic!(
|
panic!("incidence {j} missing, expected {K} incidences for vertex {v:?}")
|
||||||
"incidence {j} missing, expected {K} incidences for vertex {:?}",
|
|
||||||
vertices[i]
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
current.vertex,
|
current.vertex,
|
||||||
vertices[1 - i],
|
vertices[1 - i],
|
||||||
"unexpected adjacent vertex of vertex {:?} in incidence {j}",
|
"unexpected adjacent vertex of vertex {v:?} in incidence {j}"
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
edges.iter().filter(|e| **e == current.edge).count(),
|
edges.iter().filter(|&&e| e == current.edge).count(),
|
||||||
1,
|
1,
|
||||||
"unexpected incident edge {:?} of vertex {:?}",
|
"unexpected incident edge {:?} of vertex {v:?}",
|
||||||
current.edge,
|
current.edge
|
||||||
vertices[i],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cursor.next(&graph),
|
cursor.next(&graph),
|
||||||
None,
|
None,
|
||||||
"too many incidences of {:?} from cursor",
|
"too many incidences of {v:?} from cursor"
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -800,15 +760,14 @@ where
|
|||||||
for u in graph.vertices() {
|
for u in graph.vertices() {
|
||||||
let mut expected: Vec<_> = graph.incidences(u).map(|x| x.edge).collect();
|
let mut expected: Vec<_> = graph.incidences(u).map(|x| x.edge).collect();
|
||||||
for e in graph.incident_edges(u) {
|
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")
|
panic!("incident edge {e:?} of vertex {u:?} missing from incidences")
|
||||||
});
|
});
|
||||||
expected.swap_remove(pos);
|
expected.swap_remove(pos);
|
||||||
}
|
}
|
||||||
assert!(
|
assert!(
|
||||||
expected.is_empty(),
|
expected.is_empty(),
|
||||||
"incidence edges {:?} of vertex {u:?} not matched by incident_edges",
|
"incidence edges {expected:?} of vertex {u:?} not matched by incident_edges"
|
||||||
expected
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -347,6 +347,7 @@ pub trait IncidenceCursor<G: GraphTopology + ?Sized>: Copy {
|
|||||||
/// assert!(c2.next(&graph).is_some());
|
/// assert!(c2.next(&graph).is_some());
|
||||||
/// assert!(c2.next(&graph).is_none());
|
/// 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>>;
|
fn next(&mut self, graph: &G) -> Option<Incidence<G::Vertex, G::Edge>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-13
@@ -162,11 +162,10 @@ where
|
|||||||
G::Vertex: Debug,
|
G::Vertex: Debug,
|
||||||
{
|
{
|
||||||
let (graph, vertices, _, _) = G::standard();
|
let (graph, vertices, _, _) = G::standard();
|
||||||
for i in 0..10 {
|
for v in vertices {
|
||||||
assert!(
|
assert!(
|
||||||
algorithms::dfs_find(&graph, vertices[0], vertices[i]),
|
algorithms::dfs_find(&graph, vertices[0], v),
|
||||||
"vertex {:?} should be reachable from {:?}",
|
"vertex {v:?} should be reachable from {:?}",
|
||||||
vertices[i],
|
|
||||||
vertices[0]
|
vertices[0]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -328,12 +327,8 @@ fn assert_dfs_visited<G: GraphTopology>(
|
|||||||
) where
|
) where
|
||||||
G::Vertex: Debug,
|
G::Vertex: Debug,
|
||||||
{
|
{
|
||||||
for i in 0..10 {
|
for &v in vertices {
|
||||||
assert!(
|
assert!(visited[v], "vertex {v:?} should be visited");
|
||||||
visited[vertices[i]],
|
|
||||||
"vertex {:?} should be visited",
|
|
||||||
vertices[i]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,9 +344,8 @@ fn assert_dfs_predecessors<G: GraphTopology>(
|
|||||||
predecessors[vertices[0]], None,
|
predecessors[vertices[0]], None,
|
||||||
"source should have no predecessor"
|
"source should have no predecessor"
|
||||||
);
|
);
|
||||||
for i in 1..10 {
|
for &v in vertices.iter().skip(1) {
|
||||||
let v = vertices[i];
|
let p = predecessors[v].unwrap_or_else(|| panic!("vertex {v:?} should have a predecessor"));
|
||||||
let p = predecessors[v].expect(&format!("vertex {v:?} should have a predecessor"));
|
|
||||||
assert!(
|
assert!(
|
||||||
visited[p],
|
visited[p],
|
||||||
"predecessor {p:?} of vertex {v:?} should be visited"
|
"predecessor {p:?} of vertex {v:?} should be visited"
|
||||||
|
|||||||
+25
-32
@@ -6,7 +6,7 @@ use grapherity::algorithms::DijkstraResult;
|
|||||||
use grapherity::maps::ElementMap;
|
use grapherity::maps::ElementMap;
|
||||||
use grapherity::testing::fixtures;
|
use grapherity::testing::fixtures;
|
||||||
use grapherity::testing::fixtures::MakeTestGraph;
|
use grapherity::testing::fixtures::MakeTestGraph;
|
||||||
use grapherity::traits::{GraphTopology, Incidence};
|
use grapherity::traits::GraphTopology;
|
||||||
|
|
||||||
macro_rules! dijkstra_tests {
|
macro_rules! dijkstra_tests {
|
||||||
($T:ty) => {
|
($T:ty) => {
|
||||||
@@ -78,21 +78,19 @@ fn dijkstra_zero_weight_loop<G: MakeTestGraph>()
|
|||||||
where
|
where
|
||||||
G::Vertex: Debug + Hash,
|
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]);
|
let result = algorithms::dijkstra(&graph, vertices[0], |e| weights[e]);
|
||||||
assert_single_vertex::<G>(&result, vertices[0]);
|
assert_single_vertex::<G>(&result, vertices[0]);
|
||||||
for i in 1..3 {
|
for (i, &v) in vertices.iter().enumerate().skip(1) {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.predecessors[vertices[i]],
|
result.predecessors[v],
|
||||||
Some(vertices[i - 1]),
|
Some(vertices[i - 1]),
|
||||||
"unexpected predecessor of vertex {:?}",
|
"unexpected predecessor of vertex {v:?}"
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.distances[vertices[i]],
|
result.distances[v],
|
||||||
Some(i.try_into().unwrap()),
|
Some(i.try_into().unwrap()),
|
||||||
"unexpected distance of vertex {:?}",
|
"unexpected distance of vertex {v:?}"
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +99,7 @@ fn dijkstra<G: MakeTestGraph>()
|
|||||||
where
|
where
|
||||||
G::Vertex: Debug + Hash,
|
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]);
|
let result = algorithms::dijkstra(&graph, vertices[0], |e| weights[e]);
|
||||||
assert_standard_weighted_distances_v0::<G>(&result.distances, &vertices);
|
assert_standard_weighted_distances_v0::<G>(&result.distances, &vertices);
|
||||||
assert_standard_weighted_predecessors_v0::<G>(&result.predecessors, &vertices);
|
assert_standard_weighted_predecessors_v0::<G>(&result.predecessors, &vertices);
|
||||||
@@ -111,7 +109,7 @@ fn dijkstra_distances<G: MakeTestGraph>()
|
|||||||
where
|
where
|
||||||
G::Vertex: Debug + Hash,
|
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]);
|
let distances = algorithms::dijkstra_distances(&graph, vertices[0], |e| weights[e]);
|
||||||
assert_standard_weighted_distances_v0::<G>(&distances, &vertices);
|
assert_standard_weighted_distances_v0::<G>(&distances, &vertices);
|
||||||
}
|
}
|
||||||
@@ -201,7 +199,7 @@ fn assert_disconnected<G: GraphTopology>(
|
|||||||
) where
|
) where
|
||||||
G::Vertex: Debug,
|
G::Vertex: Debug,
|
||||||
{
|
{
|
||||||
assert_distances_disconnected::<G>(&result.distances, &vertices);
|
assert_distances_disconnected::<G>(&result.distances, vertices);
|
||||||
for &v in vertices {
|
for &v in vertices {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.predecessors[v], None,
|
result.predecessors[v], None,
|
||||||
@@ -242,12 +240,12 @@ fn assert_standard_weighted_predecessors_v0<G: GraphTopology>(
|
|||||||
vec![Some(vertices[7])],
|
vec![Some(vertices[7])],
|
||||||
vec![Some(vertices[6])],
|
vec![Some(vertices[6])],
|
||||||
];
|
];
|
||||||
for i in 0..10 {
|
assert_eq!(vertices.len(), expected.len());
|
||||||
|
for (&v, exp) in vertices.iter().zip(&expected) {
|
||||||
assert!(
|
assert!(
|
||||||
expected[i].contains(&actual[vertices[i]]),
|
exp.contains(&actual[v]),
|
||||||
"unexpected predecessor {:?} of {:?}",
|
"unexpected predecessor {:?} of {v:?}",
|
||||||
actual[vertices[i]],
|
actual[v]
|
||||||
vertices[i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,35 +268,30 @@ fn assert_standard_weighted_distances_v0<G: GraphTopology>(
|
|||||||
Some(145),
|
Some(145),
|
||||||
Some(29),
|
Some(29),
|
||||||
];
|
];
|
||||||
for i in 0..10 {
|
assert_eq!(vertices.len(), expected.len());
|
||||||
|
for (&v, &exp) in vertices.iter().zip(&expected) {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
actual[vertices[i]], expected[i],
|
actual[v], exp,
|
||||||
"unexpected distance from {:?} to {:?}",
|
"unexpected distance from {:?} to {v:?}",
|
||||||
vertices[0], vertices[i]
|
vertices[0]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_standard_weighted<G: MakeTestGraph>() -> (
|
fn make_standard_weighted<G: MakeTestGraph>() -> (G, [G::Vertex; 10], ElementMap<G::Edge, u32>) {
|
||||||
G,
|
let (graph, vertices, edges, _) = G::standard();
|
||||||
[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();
|
|
||||||
let mut weights = graph.edge_map(99);
|
let mut weights = graph.edge_map(99);
|
||||||
for i in [1, 3, 7, 10, 12, 14, 15, 17] {
|
for i in [1, 3, 7, 10, 12, 14, 15, 17] {
|
||||||
weights[edges[i].0] = i.try_into().unwrap();
|
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>()
|
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 (graph, vertices, edges) = G::two_edge_path_with_loops();
|
||||||
let mut weights = graph.edge_map(1);
|
let mut weights = graph.edge_map(1);
|
||||||
weights[edges[2]] = 0;
|
weights[edges[2]] = 0;
|
||||||
weights[edges[3]] = 0;
|
weights[edges[3]] = 0;
|
||||||
(graph, vertices, edges, weights)
|
(graph, vertices, weights)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user