Add GraphTopology::incident_vertices and tests
This commit is contained in:
@@ -120,6 +120,12 @@ impl GraphTopology for AppendGraph {
|
|||||||
.map(|(v, _)| v)
|
.map(|(v, _)| v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn incident_vertices(&self, e: Self::Edge) -> (Self::Vertex, Self::Vertex) {
|
||||||
|
let v2 = self.incidences[e.0].adjacent;
|
||||||
|
let v1 = self.incidences[e.0 ^ 1].adjacent;
|
||||||
|
(v1, v2)
|
||||||
|
}
|
||||||
|
|
||||||
fn edges(&self) -> impl Iterator<Item = Self::Edge> {
|
fn edges(&self) -> impl Iterator<Item = Self::Edge> {
|
||||||
(0..self.incidences.len()).step_by(2).map(Incidence)
|
(0..self.incidences.len()).step_by(2).map(Incidence)
|
||||||
}
|
}
|
||||||
@@ -153,4 +159,18 @@ mod tests {
|
|||||||
|
|
||||||
crate::graph_topology_test_fixtures!(AppendGraph);
|
crate::graph_topology_test_fixtures!(AppendGraph);
|
||||||
crate::graph_topology_tests!(AppendGraph);
|
crate::graph_topology_tests!(AppendGraph);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incident_vertices_paired_index() {
|
||||||
|
let mut graph = AppendGraph::new();
|
||||||
|
let v1 = graph.add_vertex();
|
||||||
|
let v2 = graph.add_vertex();
|
||||||
|
let e = graph.add_edge(v1, v2);
|
||||||
|
let f = Incidence(e.0 + 1);
|
||||||
|
let (u1, u2) = graph.incident_vertices(f);
|
||||||
|
assert!(
|
||||||
|
(u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1),
|
||||||
|
"unexpected incident vertices {u1:?} and {u2:?} for edge {f:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,6 +176,19 @@ impl GraphTopology for Graph {
|
|||||||
.map(|(vs, _)| self.vertices.get_idx(vs.0).unwrap())
|
.map(|(vs, _)| self.vertices.get_idx(vs.0).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn incident_vertices(&self, e: Self::Edge) -> (Self::Vertex, Self::Vertex) {
|
||||||
|
let v2 = self
|
||||||
|
.vertices
|
||||||
|
.get_idx(self.incidences[e].adjacent.0)
|
||||||
|
.unwrap();
|
||||||
|
let f = self.incidences.get_idx(e.arr_idx() ^ 1).unwrap();
|
||||||
|
let v1 = self
|
||||||
|
.vertices
|
||||||
|
.get_idx(self.incidences[f].adjacent.0)
|
||||||
|
.unwrap();
|
||||||
|
(v1, v2)
|
||||||
|
}
|
||||||
|
|
||||||
fn edges(&self) -> impl Iterator<Item = Self::Edge> {
|
fn edges(&self) -> impl Iterator<Item = Self::Edge> {
|
||||||
self.incidences
|
self.incidences
|
||||||
.iter()
|
.iter()
|
||||||
@@ -249,6 +262,23 @@ mod tests {
|
|||||||
crate::graph_topology_tests!(Graph);
|
crate::graph_topology_tests!(Graph);
|
||||||
crate::graph_topology_deletion_tests!(Graph);
|
crate::graph_topology_deletion_tests!(Graph);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incident_vertices_paired_index() {
|
||||||
|
let mut graph = Graph::new();
|
||||||
|
let v1 = graph.add_vertex();
|
||||||
|
let v2 = graph.add_vertex();
|
||||||
|
let e = graph.add_edge(v1, v2);
|
||||||
|
let f = graph
|
||||||
|
.incidences
|
||||||
|
.get_idx(e.arr_idx() + 1)
|
||||||
|
.expect("paired index should be valid");
|
||||||
|
let (u1, u2) = graph.incident_vertices(f);
|
||||||
|
assert!(
|
||||||
|
(u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1),
|
||||||
|
"unexpected incident vertices {u1:?} and {u2:?} for edge {f:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn delete_edge_paired_index() {
|
fn delete_edge_paired_index() {
|
||||||
let mut graph = Graph::new();
|
let mut graph = Graph::new();
|
||||||
|
|||||||
@@ -365,6 +365,84 @@ macro_rules! graph_topology_tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incident_vertices_single_edge() {
|
||||||
|
let mut graph = <$T>::new();
|
||||||
|
let v1 = graph.add_vertex();
|
||||||
|
let v2 = graph.add_vertex();
|
||||||
|
let e = graph.add_edge(v1, v2);
|
||||||
|
let (u1, u2) = graph.incident_vertices(e);
|
||||||
|
assert!(
|
||||||
|
(u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1),
|
||||||
|
"unexpected incident vertices {u1:?} and {u2:?} for edge {e:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incident_vertices_loop_edge() {
|
||||||
|
let mut graph = <$T>::new();
|
||||||
|
let v = graph.add_vertex();
|
||||||
|
let e = graph.add_edge(v, v);
|
||||||
|
assert_eq!(
|
||||||
|
graph.incident_vertices(e),
|
||||||
|
(v, v),
|
||||||
|
"unexpected incident vertices for loop edge {e:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incident_vertices_multiple_edges() {
|
||||||
|
let mut graph = <$T>::new();
|
||||||
|
let v1 = graph.add_vertex();
|
||||||
|
let v2 = graph.add_vertex();
|
||||||
|
let e1 = graph.add_edge(v1, v2);
|
||||||
|
let e2 = graph.add_edge(v1, v2);
|
||||||
|
assert_ne!(e1, e2, "edges should be distinct");
|
||||||
|
let (u1, u2) = graph.incident_vertices(e1);
|
||||||
|
assert!(
|
||||||
|
(u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1),
|
||||||
|
"unexpected incident vertices {u1:?} and {u2:?} for first multi-edge {e1:?}"
|
||||||
|
);
|
||||||
|
let (u1, u2) = graph.incident_vertices(e2);
|
||||||
|
assert!(
|
||||||
|
(u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1),
|
||||||
|
"unexpected incident vertices {u1:?} and {u2:?} for second multi-edge {e2:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incident_vertices() {
|
||||||
|
let (graph, vertices, edges, _) = make_test_graph();
|
||||||
|
let expected: [(<$T as $crate::traits::GraphTopology>::Vertex, <$T as $crate::traits::GraphTopology>::Vertex); 18] = [
|
||||||
|
(vertices[0], vertices[1]),
|
||||||
|
(vertices[0], vertices[1]),
|
||||||
|
(vertices[1], vertices[2]),
|
||||||
|
(vertices[1], vertices[3]),
|
||||||
|
(vertices[1], vertices[4]),
|
||||||
|
(vertices[2], vertices[2]),
|
||||||
|
(vertices[2], vertices[4]),
|
||||||
|
(vertices[2], vertices[4]),
|
||||||
|
(vertices[2], vertices[5]),
|
||||||
|
(vertices[2], vertices[6]),
|
||||||
|
(vertices[3], vertices[6]),
|
||||||
|
(vertices[4], vertices[4]),
|
||||||
|
(vertices[4], vertices[7]),
|
||||||
|
(vertices[4], vertices[8]),
|
||||||
|
(vertices[5], vertices[9]),
|
||||||
|
(vertices[6], vertices[9]),
|
||||||
|
(vertices[7], vertices[8]),
|
||||||
|
(vertices[7], vertices[9]),
|
||||||
|
];
|
||||||
|
for (i, &(v1, v2)) in expected.iter().enumerate() {
|
||||||
|
let (u1, u2) = graph.incident_vertices(edges[i]);
|
||||||
|
assert!(
|
||||||
|
(u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1),
|
||||||
|
"unexpected incident vertices {u1:?} and {u2:?} for edges[{i}]: edge {:?}",
|
||||||
|
edges[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn edges_empty() {
|
fn edges_empty() {
|
||||||
let graph = <$T>::new();
|
let graph = <$T>::new();
|
||||||
@@ -514,6 +592,20 @@ macro_rules! graph_topology_tests {
|
|||||||
vertices[i]
|
vertices[i]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incident_vertices_incidences_consistency() {
|
||||||
|
let (graph, _, _, _) = make_test_graph();
|
||||||
|
for u in graph.vertices() {
|
||||||
|
for (v, e) in graph.incidences(u) {
|
||||||
|
let (w1, w2) = graph.incident_vertices(e);
|
||||||
|
assert!(
|
||||||
|
(w1 == u && w2 == v) || (w1 == v && w2 == u),
|
||||||
|
"incident vertices {w1:?} and {w2:?} of edge {e:?} are inconsistent with incidence ({v:?}, {e:?}) of vertex {u:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -800,6 +892,43 @@ macro_rules! graph_topology_deletion_tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incident_vertices_after_delete_edge() {
|
||||||
|
let (mut graph, vertices, edges, _) = make_test_graph();
|
||||||
|
graph.delete_edge(edges[2]);
|
||||||
|
let expected: [(
|
||||||
|
usize,
|
||||||
|
<Graph as $crate::traits::GraphTopology>::Vertex,
|
||||||
|
<Graph as $crate::traits::GraphTopology>::Vertex,
|
||||||
|
); 17] = [
|
||||||
|
(0, vertices[0], vertices[1]),
|
||||||
|
(1, vertices[0], vertices[1]),
|
||||||
|
(3, vertices[1], vertices[3]),
|
||||||
|
(4, vertices[1], vertices[4]),
|
||||||
|
(5, vertices[2], vertices[2]),
|
||||||
|
(6, vertices[2], vertices[4]),
|
||||||
|
(7, vertices[2], vertices[4]),
|
||||||
|
(8, vertices[2], vertices[5]),
|
||||||
|
(9, vertices[2], vertices[6]),
|
||||||
|
(10, vertices[3], vertices[6]),
|
||||||
|
(11, vertices[4], vertices[4]),
|
||||||
|
(12, vertices[4], vertices[7]),
|
||||||
|
(13, vertices[4], vertices[8]),
|
||||||
|
(14, vertices[5], vertices[9]),
|
||||||
|
(15, vertices[6], vertices[9]),
|
||||||
|
(16, vertices[7], vertices[8]),
|
||||||
|
(17, vertices[7], vertices[9]),
|
||||||
|
];
|
||||||
|
for (i, v1, v2) in expected {
|
||||||
|
let (u1, u2) = graph.incident_vertices(edges[i]);
|
||||||
|
assert!(
|
||||||
|
(u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1),
|
||||||
|
"unexpected incident vertices {u1:?} and {u2:?} for edges[{i}] ({:?}) after delete",
|
||||||
|
edges[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[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();
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,6 @@ use crate::maps::{EdgeMap, VertexMap};
|
|||||||
|
|
||||||
// TODO: Add functions to reserve memory for vertices and edges.
|
// TODO: Add functions to reserve memory for vertices and edges.
|
||||||
// TODO: Add iterator of incident edges for a vertex.
|
// TODO: Add iterator of incident edges for a vertex.
|
||||||
// TODO: Add finding incident vertices for an edge.
|
|
||||||
// TODO: Split out GraphTopologyAddition trait.
|
// TODO: Split out GraphTopologyAddition trait.
|
||||||
pub trait GraphTopology {
|
pub trait GraphTopology {
|
||||||
type Vertex: Copy + Eq;
|
type Vertex: Copy + Eq;
|
||||||
@@ -18,6 +17,7 @@ pub trait GraphTopology {
|
|||||||
fn are_adjacent(&self, v1: Self::Vertex, v2: Self::Vertex) -> bool;
|
fn are_adjacent(&self, v1: Self::Vertex, v2: Self::Vertex) -> bool;
|
||||||
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 incident_vertices(&self, e: Self::Edge) -> (Self::Vertex, 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 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;
|
||||||
|
|||||||
Reference in New Issue
Block a user