use crate::maps::{EdgeMap, VertexMap}; use crate::traits::{GraphTopology, IncidenceCursor}; #[derive(Copy, Clone, PartialEq, Eq, Debug)] 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, } #[derive(Copy, Clone)] struct IncidenceEntry { next: Option, adjacent: Vertex, } #[derive(Copy, Clone)] pub struct AppendGraphIncidenceCursor { incidence: Option, } impl IncidenceCursor for AppendGraphIncidenceCursor { fn next(&mut self, graph: &AppendGraph) -> Option<(Vertex, Incidence)> { graph.step_incidence(&mut self.incidence) } } pub struct AppendGraph { vertices: Vec, incidences: Vec, } impl AppendGraph { pub fn new() -> Self { Self { vertices: vec![], incidences: vec![], } } // Adds a single incidence of an edge, which is composed by two such incidences, to the // incidences vector. fn add_incidence(&mut self, v1: Vertex, v2: Vertex) { self.incidences.push(IncidenceEntry { next: self.vertices[v1.0].first_incidence.take(), adjacent: v2, }); self.vertices[v1.0].incidence_count += 1; self.vertices[v1.0].first_incidence = Some(Incidence(self.incidences.len() - 1)); } fn raw_incidences(&self, v: Vertex) -> impl Iterator { let mut incidence = self.vertices[v.0].first_incidence; std::iter::from_fn(move || self.step_incidence(&mut incidence)) } fn step_incidence(&self, incidence: &mut Option) -> Option<(Vertex, Incidence)> { let current = (*incidence)?; let entry = self.incidences[current.0]; *incidence = entry.next; Some((entry.adjacent, current)) } } impl Default for AppendGraph { fn default() -> Self { Self::new() } } impl GraphTopology for AppendGraph { type Vertex = Vertex; type Edge = Incidence; type IncidenceCursor = AppendGraphIncidenceCursor; fn vertex_count(&self) -> usize { self.vertices.len() } fn vertex_capacity(&self) -> usize { self.vertices.len() } fn vertex_map(&self, default: T) -> VertexMap { VertexMap::new(default, |v| v.0, self.vertex_capacity()) } fn edge_count(&self) -> usize { self.incidences.len() / 2 } fn edge_capacity(&self) -> usize { self.incidences.len() / 2 } fn edge_map(&self, default: T) -> EdgeMap { EdgeMap::new(default, |e| e.0 / 2, self.edge_capacity()) } 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.adjacent_vertices(v1).any(|x| x == v2) } fn vertices(&self) -> impl Iterator { (0..self.vertices.len()).map(Vertex) } fn adjacent_vertices(&self, v: Self::Vertex) -> impl Iterator { self.raw_incidences(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 { (0..self.incidences.len()).step_by(2).map(Incidence) } fn incident_edges(&self, v: Self::Vertex) -> impl Iterator { self.raw_incidences(v).map(|(_, e)| e.normalize()) } fn incidences(&self, v: Self::Vertex) -> impl Iterator { self.raw_incidences(v).map(|(v, e)| (v, e.normalize())) } fn incidence_cursor(&self, v: Self::Vertex) -> Self::IncidenceCursor { AppendGraphIncidenceCursor { 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::*; crate::graph_topology_test_fixtures!(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:?}" ); } }