Add GraphTopology::edges() and tests

This commit is contained in:
2026-05-05 22:54:33 +02:00
parent c589095737
commit 6e9867a65e
4 changed files with 97 additions and 29 deletions
+4
View File
@@ -102,6 +102,10 @@ impl GraphTopology for AppendGraph {
}
}
fn edges(&self) -> impl Iterator<Item = Self::Edge> {
(0..self.incidences.len()).step_by(2).map(Incidence)
}
fn add_vertex(&mut self) -> Self::Vertex {
self.vertices.push(VertexIncidenceHeader {
incidence_count: 0,
+7
View File
@@ -181,6 +181,13 @@ impl GraphTopology for Graph {
}
}
fn edges(&self) -> impl Iterator<Item = Self::Edge> {
self.incidences
.iter()
.filter(|(i, _)| i.arr_idx() % 2 == 0)
.map(|(i, _)| i)
}
fn add_vertex(&mut self) -> Self::Vertex {
self.vertices.insert(VertexIncidenceHeader {
incidence_count: 0,
+85 -28
View File
@@ -2,29 +2,35 @@
#[macro_export]
macro_rules! graph_topology_test_fixtures {
($T:ty) => {
fn make_test_graph() -> ($T, [<$T as $crate::traits::GraphTopology>::Vertex; 10]) {
fn make_test_graph() -> (
$T,
[<$T as $crate::traits::GraphTopology>::Vertex; 10],
[<$T as $crate::traits::GraphTopology>::Edge; 18],
) {
let mut graph = <$T>::new();
let vertices: [<$T as $crate::traits::GraphTopology>::Vertex; 10] =
core::array::from_fn(|_| graph.add_vertex());
graph.add_edge(vertices[0], vertices[1]);
graph.add_edge(vertices[0], vertices[1]);
graph.add_edge(vertices[1], vertices[2]);
graph.add_edge(vertices[1], vertices[3]);
graph.add_edge(vertices[1], vertices[4]);
graph.add_edge(vertices[2], vertices[2]);
graph.add_edge(vertices[2], vertices[4]);
graph.add_edge(vertices[2], vertices[4]);
graph.add_edge(vertices[2], vertices[5]);
graph.add_edge(vertices[2], vertices[6]);
graph.add_edge(vertices[3], vertices[6]);
graph.add_edge(vertices[4], vertices[4]);
graph.add_edge(vertices[4], vertices[7]);
graph.add_edge(vertices[4], vertices[8]);
graph.add_edge(vertices[5], vertices[9]);
graph.add_edge(vertices[6], vertices[9]);
graph.add_edge(vertices[7], vertices[8]);
graph.add_edge(vertices[7], vertices[9]);
(graph, vertices)
let edges = [
graph.add_edge(vertices[0], vertices[1]),
graph.add_edge(vertices[0], vertices[1]),
graph.add_edge(vertices[1], vertices[2]),
graph.add_edge(vertices[1], vertices[3]),
graph.add_edge(vertices[1], vertices[4]),
graph.add_edge(vertices[2], vertices[2]),
graph.add_edge(vertices[2], vertices[4]),
graph.add_edge(vertices[2], vertices[4]),
graph.add_edge(vertices[2], vertices[5]),
graph.add_edge(vertices[2], vertices[6]),
graph.add_edge(vertices[3], vertices[6]),
graph.add_edge(vertices[4], vertices[4]),
graph.add_edge(vertices[4], vertices[7]),
graph.add_edge(vertices[4], vertices[8]),
graph.add_edge(vertices[5], vertices[9]),
graph.add_edge(vertices[6], vertices[9]),
graph.add_edge(vertices[7], vertices[8]),
graph.add_edge(vertices[7], vertices[9]),
];
(graph, vertices, edges)
}
};
}
@@ -48,7 +54,7 @@ macro_rules! graph_topology_tests {
#[test]
fn vertex_count() {
let (graph, _) = make_test_graph();
let (graph, _, _) = make_test_graph();
assert_eq!(graph.vertex_count(), 10, "unexpected vertex count");
}
@@ -69,7 +75,7 @@ macro_rules! graph_topology_tests {
#[test]
fn edge_count() {
let (graph, _) = make_test_graph();
let (graph, _, _) = make_test_graph();
assert_eq!(graph.edge_count(), 18, "unexpected edge count");
}
@@ -82,7 +88,7 @@ macro_rules! graph_topology_tests {
#[test]
fn degree() {
let (graph, vertices) = make_test_graph();
let (graph, vertices, _) = make_test_graph();
let expected_degrees = [2, 5, 7, 2, 7, 2, 3, 3, 2, 3];
for i in 0..graph.vertex_count() {
assert_eq!(
@@ -118,7 +124,7 @@ macro_rules! graph_topology_tests {
#[test]
fn are_adjacent() {
let (graph, vertices) = make_test_graph();
let (graph, vertices, _) = make_test_graph();
assert!(
graph.are_adjacent(vertices[0], vertices[1]),
"expected {:?} and {:?} to be adjacent",
@@ -172,7 +178,7 @@ macro_rules! graph_topology_tests {
#[test]
fn vertices() {
let (graph, vertices) = make_test_graph();
let (graph, vertices, _) = make_test_graph();
assert_eq!(graph.vertices().count(), 10, "unexpected vertex count");
// Expects each vertex to appear exactly once.
@@ -198,7 +204,7 @@ macro_rules! graph_topology_tests {
#[test]
fn neighbors() {
let (graph, vertices) = make_test_graph();
let (graph, vertices, _) = make_test_graph();
// Checks neighbors of vertex 4.
assert_eq!(
graph.neighbors(vertices[4]).count(),
@@ -233,6 +239,31 @@ macro_rules! graph_topology_tests {
);
}
#[test]
fn edges_empty() {
let graph = <$T>::new();
assert_eq!(
graph.edges().count(),
0,
"edge iterator of empty graph should have no elements"
);
}
#[test]
fn edges() {
let (graph, _, edges) = make_test_graph();
assert_eq!(graph.edges().count(), 18, "unexpected edge count");
// Expects each edge to appear exactly once.
for e in graph.edges() {
assert_eq!(
edges.iter().filter(|&x| *x == e).count(),
1,
"unexpected edge {e:?} from the iterator"
);
}
}
#[test]
fn loop_edge() {
let mut graph = <$T>::new();
@@ -369,7 +400,7 @@ macro_rules! graph_topology_deletion_tests {
#[test]
fn delete_vertex_connected() {
let (mut graph, vertices) = make_test_graph();
let (mut graph, vertices, _) = make_test_graph();
assert_eq!(
graph.vertex_count(),
10,
@@ -556,7 +587,7 @@ macro_rules! graph_topology_deletion_tests {
#[test]
fn vertices_after_delete() {
let (mut graph, vertices) = make_test_graph();
let (mut graph, vertices, _) = make_test_graph();
graph.delete_vertex(vertices[2]);
assert_eq!(
graph.vertex_count(),
@@ -583,5 +614,31 @@ macro_rules! graph_topology_deletion_tests {
);
}
}
#[test]
fn edges_after_delete() {
let (mut graph, vertices, edges) = make_test_graph();
graph.delete_vertex(vertices[2]);
assert_eq!(graph.edge_count(), 12, "unexpected edge count after delete");
assert_eq!(
graph.edges().count(),
12,
"unexpected edge iterator count after delete"
);
for i in [2, 5, 6, 7, 8, 9] {
assert!(
!graph.edges().any(|e| e == edges[i]),
"deleted edge {:?} appeared in iterator",
edges[i]
);
}
for i in [0, 1, 3, 4, 10, 11, 12, 13, 14, 15, 16, 17] {
assert!(
graph.edges().any(|e| e == edges[i]),
"expected edge {:?} missing from iterator after delete",
edges[i]
);
}
}
};
}
+1 -1
View File
@@ -1,5 +1,4 @@
// TODO: Add functions to reserve memory for vertices and edges.
// TODO: Add iterator of all edges.
// TODO: Add iterator of incident edges for a vertex.
// TODO: Add finding incident vertices for an edge.
// TODO: Split out GraphTopologyAddition trait.
@@ -13,6 +12,7 @@ pub trait GraphTopology {
fn are_adjacent(&self, v1: Self::Vertex, v2: Self::Vertex) -> bool;
fn vertices(&self) -> impl Iterator<Item = Self::Vertex>;
fn neighbors(&self, v: Self::Vertex) -> impl Iterator<Item = Self::Vertex>;
fn edges(&self) -> impl Iterator<Item = Self::Edge>;
fn add_vertex(&mut self) -> Self::Vertex;
fn add_edge(&mut self, v1: Self::Vertex, v2: Self::Vertex) -> Self::Edge;
}