Add GraphTopology.incidence_cursor() for certain use-cases where the iterator is problematic
Also add raw_incidences() and step_incidence() to AppendGraph analogously to Graph, which allows to remove RawIncidenceIterator and simplify its call sites.
This commit is contained in:
+27
-25
@@ -1,5 +1,5 @@
|
|||||||
use crate::maps::{EdgeMap, VertexMap};
|
use crate::maps::{EdgeMap, VertexMap};
|
||||||
use crate::traits::GraphTopology;
|
use crate::traits::{GraphTopology, IncidenceCursor};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct Vertex(usize);
|
pub struct Vertex(usize);
|
||||||
@@ -18,24 +18,20 @@ struct VertexIncidenceHeader {
|
|||||||
first_incidence: Option<Incidence>,
|
first_incidence: Option<Incidence>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
struct IncidenceEntry {
|
struct IncidenceEntry {
|
||||||
next: Option<Incidence>,
|
next: Option<Incidence>,
|
||||||
adjacent: Vertex,
|
adjacent: Vertex,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RawIncidenceIterator<'a> {
|
#[derive(Copy, Clone)]
|
||||||
graph: &'a AppendGraph,
|
pub struct AppendGraphIncidenceCursor {
|
||||||
incidence: Option<Incidence>,
|
incidence: Option<Incidence>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for RawIncidenceIterator<'a> {
|
impl IncidenceCursor<AppendGraph> for AppendGraphIncidenceCursor {
|
||||||
type Item = (Vertex, Incidence);
|
fn next(&mut self, graph: &AppendGraph) -> Option<(Vertex, Incidence)> {
|
||||||
|
graph.step_incidence(&mut self.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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +58,18 @@ impl AppendGraph {
|
|||||||
self.vertices[v1.0].incidence_count += 1;
|
self.vertices[v1.0].incidence_count += 1;
|
||||||
self.vertices[v1.0].first_incidence = Some(Incidence(self.incidences.len() - 1));
|
self.vertices[v1.0].first_incidence = Some(Incidence(self.incidences.len() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn raw_incidences(&self, v: Vertex) -> impl Iterator<Item = (Vertex, Incidence)> {
|
||||||
|
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<Incidence>) -> Option<(Vertex, Incidence)> {
|
||||||
|
let current = (*incidence)?;
|
||||||
|
let entry = self.incidences[current.0];
|
||||||
|
*incidence = entry.next;
|
||||||
|
Some((entry.adjacent, current))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for AppendGraph {
|
impl Default for AppendGraph {
|
||||||
@@ -72,8 +80,8 @@ impl Default for AppendGraph {
|
|||||||
|
|
||||||
impl GraphTopology for AppendGraph {
|
impl GraphTopology for AppendGraph {
|
||||||
type Vertex = Vertex;
|
type Vertex = Vertex;
|
||||||
|
|
||||||
type Edge = Incidence;
|
type Edge = Incidence;
|
||||||
|
type IncidenceCursor = AppendGraphIncidenceCursor;
|
||||||
|
|
||||||
fn vertex_count(&self) -> usize {
|
fn vertex_count(&self) -> usize {
|
||||||
self.vertices.len()
|
self.vertices.len()
|
||||||
@@ -112,11 +120,7 @@ impl GraphTopology for AppendGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn adjacent_vertices(&self, v: Self::Vertex) -> impl Iterator<Item = Self::Vertex> {
|
fn adjacent_vertices(&self, v: Self::Vertex) -> impl Iterator<Item = Self::Vertex> {
|
||||||
RawIncidenceIterator {
|
self.raw_incidences(v).map(|(v, _)| v)
|
||||||
graph: self,
|
|
||||||
incidence: self.vertices[v.0].first_incidence,
|
|
||||||
}
|
|
||||||
.map(|(v, _)| v)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn incident_vertices(&self, e: Self::Edge) -> (Self::Vertex, Self::Vertex) {
|
fn incident_vertices(&self, e: Self::Edge) -> (Self::Vertex, Self::Vertex) {
|
||||||
@@ -130,19 +134,17 @@ impl GraphTopology for AppendGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn incident_edges(&self, v: Self::Vertex) -> impl Iterator<Item = Self::Edge> {
|
fn incident_edges(&self, v: Self::Vertex) -> impl Iterator<Item = Self::Edge> {
|
||||||
RawIncidenceIterator {
|
self.raw_incidences(v).map(|(_, e)| e.normalize())
|
||||||
graph: self,
|
|
||||||
incidence: self.vertices[v.0].first_incidence,
|
|
||||||
}
|
|
||||||
.map(|(_, e)| e.normalize())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)> {
|
||||||
RawIncidenceIterator {
|
self.raw_incidences(v).map(|(v, e)| (v, e.normalize()))
|
||||||
graph: self,
|
}
|
||||||
|
|
||||||
|
fn incidence_cursor(&self, v: Self::Vertex) -> Self::IncidenceCursor {
|
||||||
|
AppendGraphIncidenceCursor {
|
||||||
incidence: self.vertices[v.0].first_incidence,
|
incidence: self.vertices[v.0].first_incidence,
|
||||||
}
|
}
|
||||||
.map(|(v, e)| (v, e.normalize()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_vertex(&mut self) -> Self::Vertex {
|
fn add_vertex(&mut self) -> Self::Vertex {
|
||||||
|
|||||||
+21
-2
@@ -1,7 +1,7 @@
|
|||||||
use typed_generational_arena::{Arena, Index};
|
use typed_generational_arena::{Arena, Index};
|
||||||
|
|
||||||
use crate::maps::{EdgeMap, VertexMap};
|
use crate::maps::{EdgeMap, VertexMap};
|
||||||
use crate::traits::{GraphTopology, GraphTopologyDeletion};
|
use crate::traits::{GraphTopology, GraphTopologyDeletion, IncidenceCursor};
|
||||||
|
|
||||||
type Vertex = Index<VertexIncidenceHeader, usize, usize>;
|
type Vertex = Index<VertexIncidenceHeader, usize, usize>;
|
||||||
|
|
||||||
@@ -34,6 +34,19 @@ impl IncidentEdgeCursor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct GraphIncidenceCursor {
|
||||||
|
incidence: Option<IncidenceSlot>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IncidenceCursor<Graph> for GraphIncidenceCursor {
|
||||||
|
fn next(&mut self, graph: &Graph) -> Option<(Vertex, Edge)> {
|
||||||
|
graph
|
||||||
|
.step_incidence(&mut self.incidence)
|
||||||
|
.map(|(vs, e)| (graph.vertices.get_idx(vs.0).unwrap(), 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>,
|
||||||
@@ -137,8 +150,8 @@ impl Default for Graph {
|
|||||||
|
|
||||||
impl GraphTopology for Graph {
|
impl GraphTopology for Graph {
|
||||||
type Vertex = Vertex;
|
type Vertex = Vertex;
|
||||||
|
|
||||||
type Edge = Edge;
|
type Edge = Edge;
|
||||||
|
type IncidenceCursor = GraphIncidenceCursor;
|
||||||
|
|
||||||
fn vertex_count(&self) -> usize {
|
fn vertex_count(&self) -> usize {
|
||||||
self.vertices.len()
|
self.vertices.len()
|
||||||
@@ -210,6 +223,12 @@ impl GraphTopology for Graph {
|
|||||||
.map(|(vs, e)| (self.vertices.get_idx(vs.0).unwrap(), self.normalize_edge(e)))
|
.map(|(vs, e)| (self.vertices.get_idx(vs.0).unwrap(), self.normalize_edge(e)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn incidence_cursor(&self, v: Self::Vertex) -> Self::IncidenceCursor {
|
||||||
|
GraphIncidenceCursor {
|
||||||
|
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,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use crate::maps::{EdgeMap, VertexMap};
|
|||||||
pub trait GraphTopology {
|
pub trait GraphTopology {
|
||||||
type Vertex: Copy + Eq;
|
type Vertex: Copy + Eq;
|
||||||
type Edge: Copy + Eq;
|
type Edge: Copy + Eq;
|
||||||
|
type IncidenceCursor: IncidenceCursor<Self> + Copy;
|
||||||
|
|
||||||
fn vertex_count(&self) -> usize;
|
fn vertex_count(&self) -> usize;
|
||||||
fn vertex_capacity(&self) -> usize;
|
fn vertex_capacity(&self) -> usize;
|
||||||
@@ -20,6 +21,7 @@ pub trait GraphTopology {
|
|||||||
fn edges(&self) -> impl Iterator<Item = Self::Edge>;
|
fn edges(&self) -> impl Iterator<Item = Self::Edge>;
|
||||||
fn incident_edges(&self, v: Self::Vertex) -> impl Iterator<Item = Self::Edge>;
|
fn incident_edges(&self, v: Self::Vertex) -> 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 incidence_cursor(&self, v: Self::Vertex) -> Self::IncidenceCursor;
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -28,3 +30,7 @@ pub trait GraphTopologyDeletion: GraphTopology {
|
|||||||
fn delete_vertex(&mut self, v: Self::Vertex);
|
fn delete_vertex(&mut self, v: Self::Vertex);
|
||||||
fn delete_edge(&mut self, e: Self::Edge);
|
fn delete_edge(&mut self, e: Self::Edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait IncidenceCursor<G: GraphTopology + ?Sized> {
|
||||||
|
fn next(&mut self, graph: &G) -> Option<(G::Vertex, G::Edge)>;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user