Common neighbors #9

Merged
warrence merged 6 commits from common-neighbors into main 2026-10-16 20:30:32 +02:00
Showing only changes of commit 3ae0aa9b67 - Show all commits
+110 -19
View File
@@ -84,37 +84,128 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::fmt::Debug;
use super::*; use super::*;
use crate::models::{FrozenGraph, Graph};
#[test] #[test]
fn petersen() { fn petersen_append_graph() {
let mut graph = AppendGraph::new(); petersen_add::<AppendGraph>();
let (vertices, edges) = super::petersen(&mut graph); }
assert_eq!(
graph.vertex_count(), #[test]
10, fn petersen_graph() {
"unexpected number of added vertices" petersen_add::<Graph>();
); }
assert_eq!(graph.edge_count(), 15, "unexpected number of added edges");
#[test]
fn petersen_frozen_graph() {
petersen_generate_as::<FrozenGraph>();
}
fn petersen_generate_as<G: GraphTopologyConversion>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, vertices, edges) = generate_as::<G, _, _>(petersen);
assert_petersen(&graph, &vertices, &edges);
}
fn petersen_add<G: GraphTopologyAddition>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let mut graph = G::default();
let (vertices, edges) = petersen(&mut graph);
assert_petersen(&graph, &vertices, &edges);
}
fn assert_petersen<G: GraphTopology>(graph: &G, vertices: &[G::Vertex], edges: &[G::Edge])
where
G::Vertex: Debug,
G::Edge: Debug,
{
assert_element_counts(graph, 10, 15);
assert_handles(graph.vertices(), vertices, "vertex");
assert_handles(graph.edges(), edges, "edge");
assert_no_loops_no_multi_edges(graph);
assert!( assert!(
graph.vertices().all(|v| graph.degree(v) == 3), graph.vertices().all(|v| graph.degree(v) == 3),
"all vertices should have degree 3" "all vertices should have degree 3"
); );
assert_handles_in_graph(&graph, &vertices, &edges); // Checks that each pair of vertices (u, v) has no common neighbor if they are adjacent, and
// exactly one common neighbor otherwise.
for (i, &v) in vertices.iter().enumerate() {
for &u in &vertices[i + 1..] {
if graph.are_adjacent(v, u) {
assert!(
graph.common_neighbors(u, v).next().is_none(),
"adjacent vertices {u:?} and {v:?} should not have a common neighbor"
);
} else {
assert_eq!(
graph.common_neighbors(u, v).count(),
1,
"non-adjacent vertices {u:?} and {v:?} should have exactly one common neighbor"
);
}
}
}
} }
fn assert_handles_in_graph<G: GraphTopology>( fn assert_element_counts<G: GraphTopology>(
graph: &G, graph: &G,
vertices: &[G::Vertex], expected_vertex_count: usize,
edges: &[G::Edge], expected_edge_count: usize,
) { ) {
assert!( assert_eq!(
vertices.iter().all(|&v| graph.vertices().any(|u| u == v)), graph.vertex_count(),
"all returned vertices should be in the graph" expected_vertex_count,
"unexpected number of vertices"
); );
assert!( assert_eq!(
edges.iter().all(|&e| graph.edges().any(|f| f == e)), graph.edge_count(),
"all returned edges should be in the graph" expected_edge_count,
"unexpected number of edges"
); );
} }
/// Asserts that every handle in `returned` is unique and in `all`.
fn assert_handles<T: PartialEq + Debug>(
all: impl Iterator<Item = T>,
returned: &[T],
kind: &str,
) {
let mut remaining: Vec<T> = all.collect();
for e in returned {
let Some(position) = remaining.iter().position(|x| x == e) else {
panic!("returned {kind} {e:?} is not in the graph or appears more than once");
};
remaining.swap_remove(position);
}
}
fn assert_no_loops_no_multi_edges<G: GraphTopology>(graph: &G)
where
G::Vertex: Debug,
G::Edge: Debug,
{
for e in graph.edges() {
let (u, v) = graph.incident_vertices(e);
assert_ne!(u, v, "unexpected loop edge {e:?}");
}
for v in graph.vertices() {
let mut neighbors = Vec::new();
for u in graph.adjacent_vertices(v) {
assert!(
!neighbors.contains(&u),
"unexpected multi-edge between {v:?} and {u:?}"
);
neighbors.push(u);
}
}
}
} }