Initial release #1
@@ -1 +1,2 @@
|
||||
pub mod append_graph;
|
||||
pub mod graph;
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
use crate::traits::GraphTopology;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Vertex(usize);
|
||||
|
||||
impl From<Vertex> for usize {
|
||||
fn from(v: Vertex) -> usize {
|
||||
v.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Incidence(usize);
|
||||
|
||||
struct VertexIncidenceHeader {
|
||||
incidence_count: usize,
|
||||
first_incidence: Option<Incidence>,
|
||||
}
|
||||
|
||||
struct IncidenceEntry {
|
||||
next: Option<Incidence>,
|
||||
neighbor: Vertex,
|
||||
}
|
||||
struct VertexNeighborIterator<'a> {
|
||||
graph: &'a Graph,
|
||||
incidence: Option<Incidence>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for VertexNeighborIterator<'a> {
|
||||
type Item = Vertex;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let incidence = self.incidence?;
|
||||
let entry = &self.graph.incidences[incidence.0];
|
||||
self.incidence = entry.next;
|
||||
Some(entry.neighbor)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Graph cannot support deleting vertices because of the external indices "Vertex". They could be made stable with e.g. slotmap or generational arena.
|
||||
// TODO: Add function to delete vertices.
|
||||
// TODO: Add function to delete edges.
|
||||
pub struct Graph {
|
||||
// TODO: Index 'vertices' by a 'Vertex' instead of 'Vertex.0'?
|
||||
vertices: Vec<VertexIncidenceHeader>,
|
||||
incidences: Vec<IncidenceEntry>,
|
||||
}
|
||||
|
||||
impl Graph {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
vertices: vec![],
|
||||
incidences: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn add_incidence(&mut self, v1: Vertex, v2: Vertex) {
|
||||
self.incidences.push(IncidenceEntry {
|
||||
next: self.vertices[v1.0].first_incidence.take(),
|
||||
neighbor: v2,
|
||||
});
|
||||
self.vertices[v1.0].incidence_count += 1;
|
||||
self.vertices[v1.0].first_incidence = Some(Incidence(self.incidences.len() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
impl GraphTopology for Graph {
|
||||
type Vertex = Vertex;
|
||||
|
||||
type Edge = Incidence;
|
||||
|
||||
fn vertex_count(&self) -> usize {
|
||||
self.vertices.len()
|
||||
}
|
||||
|
||||
fn edge_count(&self) -> usize {
|
||||
self.incidences.len() / 2
|
||||
}
|
||||
|
||||
fn degree(&self, v: Self::Vertex) -> usize {
|
||||
self.vertices[v.0].incidence_count
|
||||
}
|
||||
|
||||
fn are_adjacent(&self, v1: Self::Vertex, v2: Self::Vertex) -> bool {
|
||||
self.neighbors(v1).find(|&x| x == v2).is_some()
|
||||
}
|
||||
|
||||
fn vertices(&self) -> impl Iterator<Item = Self::Vertex> {
|
||||
(0..self.vertices.len()).map(Vertex)
|
||||
}
|
||||
|
||||
fn neighbors(&self, v: Self::Vertex) -> impl Iterator<Item = Self::Vertex> {
|
||||
VertexNeighborIterator {
|
||||
graph: self,
|
||||
incidence: self.vertices[v.0].first_incidence,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_vertex(&mut self) -> Self::Vertex {
|
||||
self.vertices.push(VertexIncidenceHeader {
|
||||
incidence_count: 0,
|
||||
first_incidence: None,
|
||||
});
|
||||
Vertex(self.vertices.len() - 1)
|
||||
}
|
||||
|
||||
fn add_edge(&mut self, v1: Self::Vertex, v2: Self::Vertex) -> Self::Edge {
|
||||
self.add_incidence(v1, v2);
|
||||
self.add_incidence(v2, v1);
|
||||
Incidence(self.incidences.len() - 2)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn add_vertex() {
|
||||
let mut graph = Graph::new();
|
||||
let v = graph.add_vertex();
|
||||
assert_ne!(graph.add_vertex(), v, "unexpected duplicate vertex");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vertex_count_empty() {
|
||||
let graph = Graph::new();
|
||||
assert_eq!(graph.vertex_count(), 0, "unexpected vertex count");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vertex_count() {
|
||||
let (graph, _) = make_test_graph();
|
||||
assert_eq!(graph.vertex_count(), 10, "unexpected vertex count");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_edge() {
|
||||
let mut graph = Graph::new();
|
||||
let v1 = graph.add_vertex();
|
||||
let v2 = graph.add_vertex();
|
||||
let e = graph.add_edge(v1, v2);
|
||||
assert_ne!(graph.add_edge(v1, v2), e, "unexpected duplicate edge");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn edge_count_empty() {
|
||||
let graph = Graph::new();
|
||||
assert_eq!(graph.edge_count(), 0, "unexpected edge count");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn edge_count() {
|
||||
let (graph, _) = make_test_graph();
|
||||
assert_eq!(graph.edge_count(), 14, "unexpected edge count");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn degree_zero() {
|
||||
let mut graph = Graph::new();
|
||||
let v = graph.add_vertex();
|
||||
assert_eq!(graph.degree(v), 0, "unexpected non-zero degree");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn degree() {
|
||||
let (graph, vertices) = make_test_graph();
|
||||
let expected_degrees = [1, 4, 4, 2, 4, 2, 3, 3, 2, 3];
|
||||
for i in 0..graph.vertex_count() {
|
||||
assert_eq!(
|
||||
graph.degree(vertices[i]),
|
||||
expected_degrees[i],
|
||||
"unexpected degree of {:?}",
|
||||
vertices[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn are_adjacent_vertex_self() {
|
||||
let mut graph = Graph::new();
|
||||
let v = graph.add_vertex();
|
||||
assert_eq!(
|
||||
graph.are_adjacent(v, v),
|
||||
false,
|
||||
"should not be adjacent to itself"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn are_adjacent_single_edge() {
|
||||
let mut graph = Graph::new();
|
||||
let v1 = graph.add_vertex();
|
||||
let v2 = graph.add_vertex();
|
||||
assert!(!graph.are_adjacent(v1, v2), "should not be adjacent");
|
||||
assert!(!graph.are_adjacent(v2, v1), "should not be adjacent");
|
||||
graph.add_edge(v1, v2);
|
||||
assert!(graph.are_adjacent(v1, v2), "should be adjacent");
|
||||
assert!(graph.are_adjacent(v2, v1), "should be adjacent");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn are_adjacent() {
|
||||
let (graph, vertices) = make_test_graph();
|
||||
assert!(
|
||||
graph.are_adjacent(vertices[0], vertices[1]),
|
||||
"expected {:?} and {:?} to be adjacent",
|
||||
vertices[0],
|
||||
vertices[1]
|
||||
);
|
||||
assert!(
|
||||
graph.are_adjacent(vertices[9], vertices[5]),
|
||||
"expected {:?} and {:?} to be adjacent",
|
||||
vertices[0],
|
||||
vertices[5]
|
||||
);
|
||||
assert!(
|
||||
!graph.are_adjacent(vertices[9], vertices[3]),
|
||||
"unexpected adjacency of {:?} and {:?}",
|
||||
vertices[9],
|
||||
vertices[3]
|
||||
);
|
||||
|
||||
for i in 0..graph.vertex_count() {
|
||||
let exp = match i {
|
||||
2 => continue,
|
||||
1 | 4 | 5 | 6 => true,
|
||||
_ => false,
|
||||
};
|
||||
assert_eq!(
|
||||
graph.are_adjacent(vertices[2], vertices[i]),
|
||||
exp,
|
||||
"unexpected adjacency of {:?} and {:?}",
|
||||
vertices[2],
|
||||
vertices[i]
|
||||
);
|
||||
assert_eq!(
|
||||
graph.are_adjacent(vertices[i], vertices[2]),
|
||||
exp,
|
||||
"unexpected adjacency of {:?} and {:?}",
|
||||
vertices[i],
|
||||
vertices[2]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vertices_empty() {
|
||||
let graph = Graph::new();
|
||||
assert_eq!(
|
||||
graph.vertices().count(),
|
||||
0,
|
||||
"vertex iterator of empty graph should have no elements"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vertices() {
|
||||
let (graph, vertices) = make_test_graph();
|
||||
assert_eq!(graph.vertices().count(), 10, "unexpected vertex count");
|
||||
|
||||
// Expects each vertex to appear exactly once.
|
||||
for v in graph.vertices() {
|
||||
assert_eq!(
|
||||
vertices.iter().filter(|&x| *x == v).count(),
|
||||
1,
|
||||
"unexpected vertex {v:?} from the iterator"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn neighbors_empty() {
|
||||
let mut graph = Graph::new();
|
||||
let vertex = graph.add_vertex();
|
||||
assert_eq!(
|
||||
graph.neighbors(vertex).count(),
|
||||
0,
|
||||
"neighbor iterator of vertex with degree 0 should have no elements"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn neighbors() {
|
||||
let (graph, vertices) = make_test_graph();
|
||||
// Checks neighbors of vertex 4.
|
||||
assert_eq!(
|
||||
graph.neighbors(vertices[4]).count(),
|
||||
4,
|
||||
"unexpected vertex count"
|
||||
);
|
||||
|
||||
// Expects each neighbor to appear exactly once. This will not work if there are multiple edges.
|
||||
let neighbors: Vec<Vertex> = vec![vertices[1], vertices[2], vertices[7], vertices[8]];
|
||||
for v in graph.neighbors(vertices[4]) {
|
||||
assert_eq!(
|
||||
neighbors.iter().filter(|&x| *x == v).count(),
|
||||
1,
|
||||
"unexpected neighbor {v:?} of {:?} from the iterator",
|
||||
vertices[4]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loop_edge() {
|
||||
let mut graph = Graph::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_eq!(
|
||||
graph.are_adjacent(v, v),
|
||||
true,
|
||||
"vertex with loop edge should be adjacent to itself"
|
||||
);
|
||||
let mut neighbors = graph.neighbors(v);
|
||||
assert_eq!(
|
||||
neighbors.next(),
|
||||
Some(v),
|
||||
"vertex should be neighbor of itself"
|
||||
);
|
||||
assert_eq!(
|
||||
neighbors.next(),
|
||||
Some(v),
|
||||
"vertex should be neighbor of itself twice"
|
||||
);
|
||||
assert_eq!(neighbors.next(), None, "two many neighbors from iterator");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_edges() {
|
||||
let mult = 3;
|
||||
let mut graph = Graph::new();
|
||||
let vertices = [graph.add_vertex(), graph.add_vertex()];
|
||||
for _ in 0..mult {
|
||||
graph.add_edge(vertices[0], vertices[1]);
|
||||
}
|
||||
assert_eq!(
|
||||
graph.vertex_count(),
|
||||
vertices.len(),
|
||||
"unexpected vertex count"
|
||||
);
|
||||
assert_eq!(graph.edge_count(), mult, "unexpected edge count");
|
||||
for v in vertices {
|
||||
assert_eq!(graph.degree(v), mult, "unexpected degree of {v:?}");
|
||||
}
|
||||
assert_eq!(
|
||||
graph.are_adjacent(vertices[0], vertices[1]),
|
||||
true,
|
||||
"should be adjacent"
|
||||
);
|
||||
for i in 0..2 {
|
||||
let mut neighbors = graph.neighbors(vertices[i]);
|
||||
for j in 0..mult {
|
||||
assert_eq!(
|
||||
neighbors.next(),
|
||||
Some(vertices[1 - i]),
|
||||
"neighbor {j} of vertex {:?} should be {:?}",
|
||||
vertices[i],
|
||||
vertices[1 - i]
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
neighbors.next(),
|
||||
None,
|
||||
"two many neighbors of {:?} from iterator",
|
||||
vertices[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn make_test_graph() -> (Graph, [Vertex; 10]) {
|
||||
let mut graph = Graph::new();
|
||||
let vertices: [Vertex; 10] = core::array::from_fn(|_| graph.add_vertex());
|
||||
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[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[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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user