Initial release #1
@@ -7,6 +7,12 @@ pub struct Vertex(usize);
|
|||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct Incidence(usize);
|
pub struct Incidence(usize);
|
||||||
|
|
||||||
|
impl Incidence {
|
||||||
|
fn normalize(&self) -> Self {
|
||||||
|
Self(self.0 & !1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct VertexIncidenceHeader {
|
struct VertexIncidenceHeader {
|
||||||
incidence_count: usize,
|
incidence_count: usize,
|
||||||
first_incidence: Option<Incidence>,
|
first_incidence: Option<Incidence>,
|
||||||
@@ -26,13 +32,29 @@ impl<'a> Iterator for AdjacentVertexIterator<'a> {
|
|||||||
type Item = Vertex;
|
type Item = Vertex;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let incidence = self.incidence?;
|
let current = self.incidence?;
|
||||||
let entry = &self.graph.incidences[incidence.0];
|
let entry = &self.graph.incidences[current.0];
|
||||||
self.incidence = entry.next;
|
self.incidence = entry.next;
|
||||||
Some(entry.adjacent)
|
Some(entry.adjacent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct IncidenceIterator<'a> {
|
||||||
|
graph: &'a AppendGraph,
|
||||||
|
incidence: Option<Incidence>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for IncidenceIterator<'a> {
|
||||||
|
type Item = (Vertex, Incidence);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let current = self.incidence?;
|
||||||
|
let entry = &self.graph.incidences[current.0];
|
||||||
|
self.incidence = entry.next;
|
||||||
|
Some((entry.adjacent, current.normalize()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct AppendGraph {
|
pub struct AppendGraph {
|
||||||
// TODO: Index 'vertices' by a 'Vertex' instead of 'Vertex.0'?
|
// TODO: Index 'vertices' by a 'Vertex' instead of 'Vertex.0'?
|
||||||
vertices: Vec<VertexIncidenceHeader>,
|
vertices: Vec<VertexIncidenceHeader>,
|
||||||
@@ -117,6 +139,13 @@ impl GraphTopology for AppendGraph {
|
|||||||
(0..self.incidences.len()).step_by(2).map(Incidence)
|
(0..self.incidences.len()).step_by(2).map(Incidence)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn incidences(&self, v: Self::Vertex) -> impl Iterator<Item = (Self::Vertex, Self::Edge)> {
|
||||||
|
IncidenceIterator {
|
||||||
|
graph: self,
|
||||||
|
incidence: self.vertices[v.0].first_incidence,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn add_vertex(&mut self) -> Self::Vertex {
|
fn add_vertex(&mut self) -> Self::Vertex {
|
||||||
self.vertices.push(VertexIncidenceHeader {
|
self.vertices.push(VertexIncidenceHeader {
|
||||||
incidence_count: 0,
|
incidence_count: 0,
|
||||||
|
|||||||
@@ -70,6 +70,24 @@ impl IncidentEdgeCursor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct IncidenceIterator<'a> {
|
||||||
|
graph: &'a Graph,
|
||||||
|
incidence: Option<IncidenceSlot>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for IncidenceIterator<'a> {
|
||||||
|
type Item = (Vertex, Edge);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let current = self.incidence?;
|
||||||
|
let e = self.graph.incidences.get_idx(current.0).unwrap();
|
||||||
|
let entry = &self.graph.incidences[e];
|
||||||
|
self.incidence = entry.next;
|
||||||
|
let v = self.graph.vertices.get_idx(entry.adjacent.0).unwrap();
|
||||||
|
Some((v, self.graph.normalize_edge(e)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Graph {
|
pub struct Graph {
|
||||||
// TODO: Arena index and generation types could be externalized to Graph.
|
// TODO: Arena index and generation types could be externalized to Graph.
|
||||||
vertices: Arena<VertexIncidenceHeader, usize, usize>,
|
vertices: Arena<VertexIncidenceHeader, usize, usize>,
|
||||||
@@ -142,6 +160,10 @@ impl Graph {
|
|||||||
self.incidences[previous].next = next;
|
self.incidences[previous].next = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn normalize_edge(&self, e: Edge) -> Edge {
|
||||||
|
self.incidences.get_idx(e.arr_idx() & !1).unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Graph {
|
impl Default for Graph {
|
||||||
@@ -205,6 +227,13 @@ impl GraphTopology for Graph {
|
|||||||
.map(|(i, _)| i)
|
.map(|(i, _)| i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn incidences(&self, v: Self::Vertex) -> impl Iterator<Item = (Self::Vertex, Self::Edge)> {
|
||||||
|
IncidenceIterator {
|
||||||
|
graph: self,
|
||||||
|
incidence: self.vertices[v].first_incidence,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn add_vertex(&mut self) -> Self::Vertex {
|
fn add_vertex(&mut self) -> Self::Vertex {
|
||||||
self.vertices.insert(VertexIncidenceHeader {
|
self.vertices.insert(VertexIncidenceHeader {
|
||||||
incidence_count: 0,
|
incidence_count: 0,
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ macro_rules! graph_topology_test_fixtures {
|
|||||||
$T,
|
$T,
|
||||||
[<$T as $crate::traits::GraphTopology>::Vertex; 10],
|
[<$T as $crate::traits::GraphTopology>::Vertex; 10],
|
||||||
[<$T as $crate::traits::GraphTopology>::Edge; 18],
|
[<$T as $crate::traits::GraphTopology>::Edge; 18],
|
||||||
|
[Vec<(
|
||||||
|
<$T as $crate::traits::GraphTopology>::Vertex,
|
||||||
|
<$T as $crate::traits::GraphTopology>::Edge,
|
||||||
|
)>; 10],
|
||||||
) {
|
) {
|
||||||
let mut graph = <$T>::new();
|
let mut graph = <$T>::new();
|
||||||
let vertices: [<$T as $crate::traits::GraphTopology>::Vertex; 10] =
|
let vertices: [<$T as $crate::traits::GraphTopology>::Vertex; 10] =
|
||||||
@@ -30,7 +34,53 @@ macro_rules! graph_topology_test_fixtures {
|
|||||||
graph.add_edge(vertices[7], vertices[8]),
|
graph.add_edge(vertices[7], vertices[8]),
|
||||||
graph.add_edge(vertices[7], vertices[9]),
|
graph.add_edge(vertices[7], vertices[9]),
|
||||||
];
|
];
|
||||||
(graph, vertices, edges)
|
let incidences: [Vec<_>; 10] = [
|
||||||
|
vec![(vertices[1], edges[0]), (vertices[1], edges[1])],
|
||||||
|
vec![
|
||||||
|
(vertices[0], edges[0]),
|
||||||
|
(vertices[0], edges[1]),
|
||||||
|
(vertices[2], edges[2]),
|
||||||
|
(vertices[3], edges[3]),
|
||||||
|
(vertices[4], edges[4]),
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
(vertices[2], edges[5]),
|
||||||
|
(vertices[2], edges[5]),
|
||||||
|
(vertices[1], edges[2]),
|
||||||
|
(vertices[4], edges[6]),
|
||||||
|
(vertices[4], edges[7]),
|
||||||
|
(vertices[5], edges[8]),
|
||||||
|
(vertices[6], edges[9]),
|
||||||
|
],
|
||||||
|
vec![(vertices[1], edges[3]), (vertices[6], edges[10])],
|
||||||
|
vec![
|
||||||
|
(vertices[1], edges[4]),
|
||||||
|
(vertices[2], edges[6]),
|
||||||
|
(vertices[2], edges[7]),
|
||||||
|
(vertices[4], edges[11]),
|
||||||
|
(vertices[4], edges[11]),
|
||||||
|
(vertices[7], edges[12]),
|
||||||
|
(vertices[8], edges[13]),
|
||||||
|
],
|
||||||
|
vec![(vertices[2], edges[8]), (vertices[9], edges[14])],
|
||||||
|
vec![
|
||||||
|
(vertices[2], edges[9]),
|
||||||
|
(vertices[3], edges[10]),
|
||||||
|
(vertices[9], edges[15]),
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
(vertices[4], edges[12]),
|
||||||
|
(vertices[8], edges[16]),
|
||||||
|
(vertices[9], edges[17]),
|
||||||
|
],
|
||||||
|
vec![(vertices[4], edges[13]), (vertices[7], edges[16])],
|
||||||
|
vec![
|
||||||
|
(vertices[5], edges[14]),
|
||||||
|
(vertices[6], edges[15]),
|
||||||
|
(vertices[7], edges[17]),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
(graph, vertices, edges, incidences)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -54,7 +104,7 @@ macro_rules! graph_topology_tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn vertex_count() {
|
fn vertex_count() {
|
||||||
let (graph, _, _) = make_test_graph();
|
let (graph, _, _, _) = make_test_graph();
|
||||||
assert_eq!(graph.vertex_count(), 10, "unexpected vertex count");
|
assert_eq!(graph.vertex_count(), 10, "unexpected vertex count");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +125,7 @@ macro_rules! graph_topology_tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn edge_count() {
|
fn edge_count() {
|
||||||
let (graph, _, _) = make_test_graph();
|
let (graph, _, _, _) = make_test_graph();
|
||||||
assert_eq!(graph.edge_count(), 18, "unexpected edge count");
|
assert_eq!(graph.edge_count(), 18, "unexpected edge count");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +138,7 @@ macro_rules! graph_topology_tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn degree() {
|
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];
|
let expected_degrees = [2, 5, 7, 2, 7, 2, 3, 3, 2, 3];
|
||||||
for i in 0..graph.vertex_count() {
|
for i in 0..graph.vertex_count() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -100,6 +150,36 @@ macro_rules! graph_topology_tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn loop_edge() {
|
||||||
|
let mut graph = <$T>::new();
|
||||||
|
let v = graph.add_vertex();
|
||||||
|
graph.add_edge(v, v);
|
||||||
|
assert_eq!(graph.vertex_count(), 1, "unexpected vertex count");
|
||||||
|
assert_eq!(graph.edge_count(), 1, "unexpected edge count");
|
||||||
|
assert_eq!(graph.degree(v), 2, "unexpected degree");
|
||||||
|
assert!(
|
||||||
|
graph.are_adjacent(v, v),
|
||||||
|
"vertex with loop edge should be adjacent to itself"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multiple_edges() {
|
||||||
|
let k = 3;
|
||||||
|
let mut graph = <$T>::new();
|
||||||
|
let v1 = graph.add_vertex();
|
||||||
|
let v2 = graph.add_vertex();
|
||||||
|
for _ in 0..k {
|
||||||
|
graph.add_edge(v1, v2);
|
||||||
|
}
|
||||||
|
assert_eq!(graph.vertex_count(), 2, "unexpected vertex count");
|
||||||
|
assert_eq!(graph.edge_count(), k, "unexpected edge count");
|
||||||
|
assert_eq!(graph.degree(v1), k, "unexpected degree of vertex {v1:?}");
|
||||||
|
assert_eq!(graph.degree(v2), k, "unexpected degree of vertex {v2:?}");
|
||||||
|
assert!(graph.are_adjacent(v1, v2), "should be adjacent");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn are_adjacent_vertex_self() {
|
fn are_adjacent_vertex_self() {
|
||||||
let mut graph = <$T>::new();
|
let mut graph = <$T>::new();
|
||||||
@@ -124,7 +204,7 @@ macro_rules! graph_topology_tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn are_adjacent() {
|
fn are_adjacent() {
|
||||||
let (graph, vertices, _) = make_test_graph();
|
let (graph, vertices, _, _) = make_test_graph();
|
||||||
assert!(
|
assert!(
|
||||||
graph.are_adjacent(vertices[0], vertices[1]),
|
graph.are_adjacent(vertices[0], vertices[1]),
|
||||||
"expected {:?} and {:?} to be adjacent",
|
"expected {:?} and {:?} to be adjacent",
|
||||||
@@ -178,7 +258,7 @@ macro_rules! graph_topology_tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn vertices() {
|
fn vertices() {
|
||||||
let (graph, vertices, _) = make_test_graph();
|
let (graph, vertices, _, _) = make_test_graph();
|
||||||
assert_eq!(graph.vertices().count(), 10, "unexpected vertex count");
|
assert_eq!(graph.vertices().count(), 10, "unexpected vertex count");
|
||||||
|
|
||||||
// Expects each vertex to appear exactly once.
|
// Expects each vertex to appear exactly once.
|
||||||
@@ -194,9 +274,9 @@ macro_rules! graph_topology_tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn adjacent_vertices_empty() {
|
fn adjacent_vertices_empty() {
|
||||||
let mut graph = <$T>::new();
|
let mut graph = <$T>::new();
|
||||||
let vertex = graph.add_vertex();
|
let v = graph.add_vertex();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
graph.adjacent_vertices(vertex).count(),
|
graph.adjacent_vertices(v).count(),
|
||||||
0,
|
0,
|
||||||
"adjacent vertex iterator of vertex with degree 0 should have no elements"
|
"adjacent vertex iterator of vertex with degree 0 should have no elements"
|
||||||
);
|
);
|
||||||
@@ -204,7 +284,7 @@ macro_rules! graph_topology_tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn adjacent_vertices() {
|
fn adjacent_vertices() {
|
||||||
let (graph, vertices, _) = make_test_graph();
|
let (graph, vertices, _, _) = make_test_graph();
|
||||||
// Checks adjacency of vertex 4.
|
// Checks adjacency of vertex 4.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
graph.adjacent_vertices(vertices[4]).count(),
|
graph.adjacent_vertices(vertices[4]).count(),
|
||||||
@@ -240,42 +320,10 @@ macro_rules! graph_topology_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn edges_empty() {
|
fn adjacent_vertices_loop_edge() {
|
||||||
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();
|
let mut graph = <$T>::new();
|
||||||
let v = graph.add_vertex();
|
let v = graph.add_vertex();
|
||||||
graph.add_edge(v, v);
|
graph.add_edge(v, v);
|
||||||
assert_eq!(graph.vertex_count(), 1, "unexpected vertex count");
|
|
||||||
assert_eq!(graph.edge_count(), 1, "unexpected edge count");
|
|
||||||
assert_eq!(graph.degree(v), 2, "unexpected degree");
|
|
||||||
assert!(
|
|
||||||
graph.are_adjacent(v, v),
|
|
||||||
"vertex with loop edge should be adjacent to itself"
|
|
||||||
);
|
|
||||||
let mut iter = graph.adjacent_vertices(v);
|
let mut iter = graph.adjacent_vertices(v);
|
||||||
assert_eq!(iter.next(), Some(v), "vertex should be adjacent to itself");
|
assert_eq!(iter.next(), Some(v), "vertex should be adjacent to itself");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -291,35 +339,172 @@ macro_rules! graph_topology_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multiple_edges() {
|
fn adjacent_vertices_multiple_edges() {
|
||||||
let k = 3;
|
let k = 3;
|
||||||
let mut graph = <$T>::new();
|
let mut graph = <$T>::new();
|
||||||
let vertices = [graph.add_vertex(), graph.add_vertex()];
|
let vertices = [graph.add_vertex(), graph.add_vertex()];
|
||||||
for _ in 0..k {
|
for _ in 0..k {
|
||||||
graph.add_edge(vertices[0], vertices[1]);
|
graph.add_edge(vertices[0], vertices[1]);
|
||||||
}
|
}
|
||||||
assert_eq!(
|
|
||||||
graph.vertex_count(),
|
|
||||||
vertices.len(),
|
|
||||||
"unexpected vertex count"
|
|
||||||
);
|
|
||||||
assert_eq!(graph.edge_count(), k, "unexpected edge count");
|
|
||||||
for v in vertices {
|
|
||||||
assert_eq!(graph.degree(v), k, "unexpected degree of {v:?}");
|
|
||||||
}
|
|
||||||
assert!(
|
|
||||||
graph.are_adjacent(vertices[0], vertices[1]),
|
|
||||||
"should be adjacent"
|
|
||||||
);
|
|
||||||
for i in 0..2 {
|
for i in 0..2 {
|
||||||
let mut iter = graph.adjacent_vertices(vertices[i]);
|
let mut iter = graph.adjacent_vertices(vertices[i]);
|
||||||
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]),
|
||||||
"adjacent vertex {j} of vertex {:?} should be {:?}",
|
"unexpected adjacent vertex {j} of vertex {:?}",
|
||||||
|
vertices[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
iter.next(),
|
||||||
|
None,
|
||||||
|
"too many adjacent vertices of vertex {:?} from iterator",
|
||||||
|
vertices[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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 incidences_empty() {
|
||||||
|
let mut graph = <$T>::new();
|
||||||
|
let v = graph.add_vertex();
|
||||||
|
assert_eq!(
|
||||||
|
graph.incidences(v).count(),
|
||||||
|
0,
|
||||||
|
"incidence iterator of vertex with degree 0 should have no elements"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incidences() {
|
||||||
|
let (graph, vertices, _, incidences) = make_test_graph();
|
||||||
|
for i in 0..10 {
|
||||||
|
assert_eq!(
|
||||||
|
graph.incidences(vertices[i]).count(),
|
||||||
|
incidences[i].len(),
|
||||||
|
"unexpected incidence count for vertex {:?}",
|
||||||
|
vertices[i]
|
||||||
|
);
|
||||||
|
let mut remaining = incidences[i].clone();
|
||||||
|
for incidence in graph.incidences(vertices[i]) {
|
||||||
|
let pos = remaining
|
||||||
|
.iter()
|
||||||
|
.position(|(v, e)| *v == incidence.0 && *e == incidence.1)
|
||||||
|
.expect(&format!(
|
||||||
|
"unexpected incidence {incidence:?} of vertex {:?} from the iterator",
|
||||||
|
vertices[i]
|
||||||
|
));
|
||||||
|
remaining.swap_remove(pos);
|
||||||
|
}
|
||||||
|
assert!(
|
||||||
|
remaining.is_empty(),
|
||||||
|
"expected incidences {:?} of vertex {:?} were not matched by the iterator",
|
||||||
|
remaining,
|
||||||
|
vertices[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incidences_edge_consistency() {
|
||||||
|
// For each incidence (v, e) of u, the same edge e must appear in the incidences of v.
|
||||||
|
// For loop edges (u == v), the edge must appear exactly twice in the incidences of u.
|
||||||
|
let (graph, _, _, _) = make_test_graph();
|
||||||
|
for u in graph.vertices() {
|
||||||
|
for (v, e) in graph.incidences(u) {
|
||||||
|
if u == v {
|
||||||
|
assert_eq!(
|
||||||
|
graph.incidences(u).filter(|(_, f)| *f == e).count(),
|
||||||
|
2,
|
||||||
|
"loop edge {e:?} should appear exactly twice in incidences of vertex {u:?}"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
assert!(
|
||||||
|
graph.incidences(v).any(|(w, f)| w == u && f == e),
|
||||||
|
"edge {e:?} from incidences of vertex {u:?} missing in incidences of adjacent vertex {v:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incidences_loop_edge() {
|
||||||
|
let mut graph = <$T>::new();
|
||||||
|
let v = graph.add_vertex();
|
||||||
|
let e = graph.add_edge(v, v);
|
||||||
|
let mut iter = graph.incidences(v);
|
||||||
|
assert_eq!(
|
||||||
|
iter.next(),
|
||||||
|
Some((v, e)),
|
||||||
|
"vertex should be adjacent to itself"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
iter.next(),
|
||||||
|
Some((v, e)),
|
||||||
|
"vertex should be adjacent to itself twice"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
iter.next(),
|
||||||
|
None,
|
||||||
|
"too many adjacent vertices from iterator"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incidences_multiple_edges() {
|
||||||
|
let k = 3;
|
||||||
|
let mut graph = <$T>::new();
|
||||||
|
let vertices = [graph.add_vertex(), graph.add_vertex()];
|
||||||
|
let mut edges = Vec::new();
|
||||||
|
for _ in 0..k {
|
||||||
|
edges.push(graph.add_edge(vertices[0], vertices[1]));
|
||||||
|
}
|
||||||
|
for i in 0..2 {
|
||||||
|
let mut iter = graph.incidences(vertices[i]);
|
||||||
|
for j in 0..k {
|
||||||
|
let current = iter.next().expect(&format!(
|
||||||
|
"incidence {j} missing, expected {k} incidences for vertex {:?}",
|
||||||
|
vertices[i]
|
||||||
|
));
|
||||||
|
assert_eq!(
|
||||||
|
current.0,
|
||||||
|
vertices[1 - i],
|
||||||
|
"unexpected adjacent vertex of vertex {:?} in incidence {j}",
|
||||||
|
vertices[i]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
edges.iter().filter(|e| **e == current.1).count(),
|
||||||
|
1,
|
||||||
|
"unexpected incident edge {:?} of vertex {:?}",
|
||||||
|
current.1,
|
||||||
vertices[i],
|
vertices[i],
|
||||||
vertices[1 - i]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -400,7 +585,7 @@ macro_rules! graph_topology_deletion_tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn delete_vertex_connected() {
|
fn delete_vertex_connected() {
|
||||||
let (mut graph, vertices, _) = make_test_graph();
|
let (mut graph, vertices, _, _) = make_test_graph();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
graph.vertex_count(),
|
graph.vertex_count(),
|
||||||
10,
|
10,
|
||||||
@@ -587,7 +772,7 @@ macro_rules! graph_topology_deletion_tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn vertices_after_delete() {
|
fn vertices_after_delete() {
|
||||||
let (mut graph, vertices, _) = make_test_graph();
|
let (mut graph, vertices, _, _) = make_test_graph();
|
||||||
graph.delete_vertex(vertices[2]);
|
graph.delete_vertex(vertices[2]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
graph.vertex_count(),
|
graph.vertex_count(),
|
||||||
@@ -617,7 +802,7 @@ macro_rules! graph_topology_deletion_tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn edges_after_delete() {
|
fn edges_after_delete() {
|
||||||
let (mut graph, vertices, edges) = make_test_graph();
|
let (mut graph, vertices, edges, _) = make_test_graph();
|
||||||
graph.delete_vertex(vertices[2]);
|
graph.delete_vertex(vertices[2]);
|
||||||
assert_eq!(graph.edge_count(), 12, "unexpected edge count after delete");
|
assert_eq!(graph.edge_count(), 12, "unexpected edge count after delete");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -640,5 +825,76 @@ macro_rules! graph_topology_deletion_tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incidences_after_delete_vertex() {
|
||||||
|
let (mut graph, vertices, _, incidences) = make_test_graph();
|
||||||
|
graph.delete_vertex(vertices[2]);
|
||||||
|
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
|
||||||
|
let mut remaining: Vec<_> = incidences[i]
|
||||||
|
.iter()
|
||||||
|
.filter(|(v, _)| *v != vertices[2])
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
assert_eq!(
|
||||||
|
graph.incidences(vertices[i]).count(),
|
||||||
|
remaining.len(),
|
||||||
|
"unexpected incidence count for vertex {:?} after delete",
|
||||||
|
vertices[i]
|
||||||
|
);
|
||||||
|
for incidence in graph.incidences(vertices[i]) {
|
||||||
|
let pos = remaining
|
||||||
|
.iter()
|
||||||
|
.position(|(v, e)| *v == incidence.0 && *e == incidence.1)
|
||||||
|
.expect(&format!(
|
||||||
|
"unexpected incidence {incidence:?} of vertex {:?} after delete",
|
||||||
|
vertices[i]
|
||||||
|
));
|
||||||
|
remaining.swap_remove(pos);
|
||||||
|
}
|
||||||
|
assert!(
|
||||||
|
remaining.is_empty(),
|
||||||
|
"expected incidences {:?} of vertex {:?} not matched after delete",
|
||||||
|
remaining,
|
||||||
|
vertices[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incidences_after_delete_edge() {
|
||||||
|
let (mut graph, vertices, edges, incidences) = make_test_graph();
|
||||||
|
// Deletes the edge from vertices[1] to vertices[2].
|
||||||
|
graph.delete_edge(edges[2]);
|
||||||
|
for i in 0..10 {
|
||||||
|
let mut remaining: Vec<_> = incidences[i]
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, e)| *e != edges[2])
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
assert_eq!(
|
||||||
|
graph.incidences(vertices[i]).count(),
|
||||||
|
remaining.len(),
|
||||||
|
"unexpected incidence count for vertex {:?} after delete",
|
||||||
|
vertices[i]
|
||||||
|
);
|
||||||
|
for incidence in graph.incidences(vertices[i]) {
|
||||||
|
let pos = remaining
|
||||||
|
.iter()
|
||||||
|
.position(|(v, e)| *v == incidence.0 && *e == incidence.1)
|
||||||
|
.expect(&format!(
|
||||||
|
"unexpected incidence {incidence:?} of vertex {:?} after delete",
|
||||||
|
vertices[i]
|
||||||
|
));
|
||||||
|
remaining.swap_remove(pos);
|
||||||
|
}
|
||||||
|
assert!(
|
||||||
|
remaining.is_empty(),
|
||||||
|
"expected incidences {:?} of vertex {:?} not matched after delete",
|
||||||
|
remaining,
|
||||||
|
vertices[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ pub trait GraphTopology {
|
|||||||
fn vertices(&self) -> impl Iterator<Item = Self::Vertex>;
|
fn vertices(&self) -> impl Iterator<Item = Self::Vertex>;
|
||||||
fn adjacent_vertices(&self, v: Self::Vertex) -> impl Iterator<Item = Self::Vertex>;
|
fn adjacent_vertices(&self, v: Self::Vertex) -> impl Iterator<Item = Self::Vertex>;
|
||||||
fn edges(&self) -> impl Iterator<Item = Self::Edge>;
|
fn edges(&self) -> impl Iterator<Item = Self::Edge>;
|
||||||
|
fn incidences(&self, v: Self::Vertex) -> impl Iterator<Item = (Self::Vertex, Self::Edge)>;
|
||||||
fn add_vertex(&mut self) -> Self::Vertex;
|
fn add_vertex(&mut self) -> Self::Vertex;
|
||||||
fn add_edge(&mut self, v1: Self::Vertex, v2: Self::Vertex) -> Self::Edge;
|
fn add_edge(&mut self, v1: Self::Vertex, v2: Self::Vertex) -> Self::Edge;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user