Initial release #1
@@ -7,6 +7,12 @@ pub struct Vertex(usize);
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Incidence(usize);
|
||||
|
||||
impl Incidence {
|
||||
fn normalize(&self) -> Self {
|
||||
Self(self.0 & !1)
|
||||
}
|
||||
}
|
||||
|
||||
struct VertexIncidenceHeader {
|
||||
incidence_count: usize,
|
||||
first_incidence: Option<Incidence>,
|
||||
@@ -26,13 +32,29 @@ impl<'a> Iterator for AdjacentVertexIterator<'a> {
|
||||
type Item = Vertex;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let incidence = self.incidence?;
|
||||
let entry = &self.graph.incidences[incidence.0];
|
||||
let current = self.incidence?;
|
||||
let entry = &self.graph.incidences[current.0];
|
||||
self.incidence = entry.next;
|
||||
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 {
|
||||
// TODO: Index 'vertices' by a 'Vertex' instead of 'Vertex.0'?
|
||||
vertices: Vec<VertexIncidenceHeader>,
|
||||
@@ -117,6 +139,13 @@ impl GraphTopology for AppendGraph {
|
||||
(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 {
|
||||
self.vertices.push(VertexIncidenceHeader {
|
||||
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 {
|
||||
// TODO: Arena index and generation types could be externalized to Graph.
|
||||
vertices: Arena<VertexIncidenceHeader, usize, usize>,
|
||||
@@ -142,6 +160,10 @@ impl Graph {
|
||||
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 {
|
||||
@@ -205,6 +227,13 @@ impl GraphTopology for Graph {
|
||||
.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 {
|
||||
self.vertices.insert(VertexIncidenceHeader {
|
||||
incidence_count: 0,
|
||||
|
||||
@@ -6,6 +6,10 @@ macro_rules! graph_topology_test_fixtures {
|
||||
$T,
|
||||
[<$T as $crate::traits::GraphTopology>::Vertex; 10],
|
||||
[<$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 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[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]
|
||||
fn vertex_count() {
|
||||
let (graph, _, _) = make_test_graph();
|
||||
let (graph, _, _, _) = make_test_graph();
|
||||
assert_eq!(graph.vertex_count(), 10, "unexpected vertex count");
|
||||
}
|
||||
|
||||
@@ -75,7 +125,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");
|
||||
}
|
||||
|
||||
@@ -88,7 +138,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!(
|
||||
@@ -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]
|
||||
fn are_adjacent_vertex_self() {
|
||||
let mut graph = <$T>::new();
|
||||
@@ -124,7 +204,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",
|
||||
@@ -178,7 +258,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.
|
||||
@@ -194,9 +274,9 @@ macro_rules! graph_topology_tests {
|
||||
#[test]
|
||||
fn adjacent_vertices_empty() {
|
||||
let mut graph = <$T>::new();
|
||||
let vertex = graph.add_vertex();
|
||||
let v = graph.add_vertex();
|
||||
assert_eq!(
|
||||
graph.adjacent_vertices(vertex).count(),
|
||||
graph.adjacent_vertices(v).count(),
|
||||
0,
|
||||
"adjacent vertex iterator of vertex with degree 0 should have no elements"
|
||||
);
|
||||
@@ -204,7 +284,7 @@ macro_rules! graph_topology_tests {
|
||||
|
||||
#[test]
|
||||
fn adjacent_vertices() {
|
||||
let (graph, vertices, _) = make_test_graph();
|
||||
let (graph, vertices, _, _) = make_test_graph();
|
||||
// Checks adjacency of vertex 4.
|
||||
assert_eq!(
|
||||
graph.adjacent_vertices(vertices[4]).count(),
|
||||
@@ -240,42 +320,10 @@ 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() {
|
||||
fn adjacent_vertices_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"
|
||||
);
|
||||
let mut iter = graph.adjacent_vertices(v);
|
||||
assert_eq!(iter.next(), Some(v), "vertex should be adjacent to itself");
|
||||
assert_eq!(
|
||||
@@ -291,35 +339,172 @@ macro_rules! graph_topology_tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_edges() {
|
||||
fn adjacent_vertices_multiple_edges() {
|
||||
let k = 3;
|
||||
let mut graph = <$T>::new();
|
||||
let vertices = [graph.add_vertex(), graph.add_vertex()];
|
||||
for _ in 0..k {
|
||||
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 {
|
||||
let mut iter = graph.adjacent_vertices(vertices[i]);
|
||||
for j in 0..k {
|
||||
assert_eq!(
|
||||
iter.next(),
|
||||
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[1 - i]
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
@@ -400,7 +585,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,
|
||||
@@ -587,7 +772,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(),
|
||||
@@ -617,7 +802,7 @@ macro_rules! graph_topology_deletion_tests {
|
||||
|
||||
#[test]
|
||||
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]);
|
||||
assert_eq!(graph.edge_count(), 12, "unexpected edge count after delete");
|
||||
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 adjacent_vertices(&self, v: Self::Vertex) -> impl Iterator<Item = Self::Vertex>;
|
||||
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_edge(&mut self, v1: Self::Vertex, v2: Self::Vertex) -> Self::Edge;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user