pub mod bfs;
pub mod dfs;
pub(crate) mod raw;
mod visit_set;
#[doc(inline)]
pub use self::{
bfs::Bfs,
dfs::{Dfs, DfsEvents, DfsNoBacktrack, DfsPostOrder},
visit_set::{TypedBitSet, VisitSet},
};
use std::collections::VecDeque;
use rustc_hash::FxHashSet;
use raw::*;
use crate::core::{
GraphBase, Neighbors, VertexSet,
id::{IdType, UseVertexId},
};
#[doc(alias = "Walker")]
pub trait Visitor<G> {
type Item;
fn visit_next(&mut self, graph: &G) -> Option<Self::Item>;
fn iter<'a>(&'a mut self, graph: &'a G) -> Iter<'a, Self, G>
where
Self: Sized,
{
Iter {
visitor: self,
graph,
}
}
fn into_iter(self, graph: &G) -> IntoIter<'_, Self, G>
where
Self: Sized,
{
IntoIter {
visitor: self,
graph,
}
}
}
pub struct Iter<'a, V, G> {
visitor: &'a mut V,
graph: &'a G,
}
impl<'a, V, G> Iterator for Iter<'a, V, G>
where
V: Visitor<G>,
{
type Item = V::Item;
fn next(&mut self) -> Option<Self::Item> {
self.visitor.visit_next(self.graph)
}
}
pub struct IntoIter<'a, V, G> {
visitor: V,
graph: &'a G,
}
impl<'a, V, G> Iterator for IntoIter<'a, V, G>
where
V: Visitor<G>,
{
type Item = V::Item;
fn next(&mut self) -> Option<Self::Item> {
self.visitor.visit_next(self.graph)
}
}
pub trait VisitRoots<I: IdType> {
fn next_root(&mut self) -> Option<I>;
fn is_done(&mut self, _visited: &impl VisitSet<I>) -> bool {
false
}
}
impl<I: IdType, T> VisitRoots<I> for T
where
T: Iterator<Item = I>,
{
fn next_root(&mut self) -> Option<I> {
self.next()
}
}
pub struct VisitAll<'a, G>
where
G: VertexSet,
{
graph: &'a G,
ids: G::VerticesByIdIter<'a>,
}
impl<'a, G> VisitAll<'a, G>
where
G: VertexSet,
{
pub fn new(graph: &'a G) -> Self {
Self {
graph,
ids: graph.vertices_by_id(),
}
}
}
impl<G> VisitRoots<G::VertexId> for VisitAll<'_, G>
where
G: VertexSet,
{
fn next_root(&mut self) -> Option<G::VertexId> {
self.ids.next()
}
fn is_done(&mut self, visited: &impl VisitSet<G::VertexId>) -> bool {
visited.visited_count() == self.graph.vertex_count()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Time(pub usize);
impl Time {
pub const MAX: Time = Time(usize::MAX);
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DfsEvent<G>
where
G: GraphBase,
{
Open {
vertex: G::VertexId,
time: Time,
},
TreeEdge {
from: G::VertexId,
to: G::VertexId,
edge: G::EdgeId,
},
BackEdge {
from: G::VertexId,
to: G::VertexId,
edge: G::EdgeId,
},
CrossForwardEdge {
from: G::VertexId,
to: G::VertexId,
edge: G::EdgeId,
},
Close {
vertex: G::VertexId,
time: Time,
},
}
#[cfg(test)]
mod tests {
use crate::{
core::{
GraphAdd, GraphFull,
id::DefaultId,
marker::{Directed, Undirected},
},
storage::{AdjList, Stable},
};
use super::*;
macro_rules! dfs_event {
(open, $v:expr, $t:expr) => {
DfsEvent::Open {
vertex: $v,
time: Time($t),
}
};
(tree, $e:expr, ($u:expr, $v:expr)) => {
DfsEvent::TreeEdge {
from: $u,
to: $v,
edge: $e,
}
};
(back, $e:expr, ($u:expr, $v:expr)) => {
DfsEvent::BackEdge {
from: $u,
to: $v,
edge: $e,
}
};
(cross_forward, $e:expr, ($u:expr, $v:expr)) => {
DfsEvent::CrossForwardEdge {
from: $u,
to: $v,
edge: $e,
}
};
(close, $v:expr, $t:expr) => {
DfsEvent::Close {
vertex: $v,
time: Time($t),
}
};
}
#[test]
fn bfs_connected() {
let mut graph = AdjList::<_, _, Undirected, DefaultId>::new();
let v0 = graph.add_vertex(());
let v1 = graph.add_vertex(());
let v2 = graph.add_vertex(());
let v3 = graph.add_vertex(());
let v4 = graph.add_vertex(());
let v5 = graph.add_vertex(());
graph.add_edge(&v0, &v1, ());
graph.add_edge(&v1, &v2, ());
graph.add_edge(&v1, &v3, ());
graph.add_edge(&v1, &v4, ());
graph.add_edge(&v2, &v5, ());
graph.add_edge(&v5, &v4, ());
let vertices = Bfs::new(&graph).start(v0).iter(&graph).collect::<Vec<_>>();
assert_eq!(vertices, vec![v0, v1, v2, v3, v4, v5]);
}
#[test]
fn dfs_connected() {
let mut graph = AdjList::<_, _, Undirected, DefaultId>::new();
let v0 = graph.add_vertex(());
let v1 = graph.add_vertex(());
let v2 = graph.add_vertex(());
let v3 = graph.add_vertex(());
let v4 = graph.add_vertex(());
let v5 = graph.add_vertex(());
graph.add_edge(&v0, &v1, ());
graph.add_edge(&v1, &v2, ());
graph.add_edge(&v1, &v3, ());
graph.add_edge(&v1, &v4, ());
graph.add_edge(&v2, &v5, ());
graph.add_edge(&v5, &v4, ());
let vertices = Dfs::new(&graph).start(v0).iter(&graph).collect::<Vec<_>>();
assert_eq!(vertices, vec![v0, v1, v4, v5, v2, v3]);
}
#[test]
fn bfs_disconnected() {
let mut graph = Stable::new(AdjList::<_, _, Undirected, DefaultId>::new());
let v0 = graph.add_vertex(());
let v1 = graph.add_vertex(());
let v2 = graph.add_vertex(());
let v3 = graph.add_vertex(());
let v4 = graph.add_vertex(());
let v5 = graph.add_vertex(());
graph.add_edge(&v0, &v1, ());
graph.add_edge(&v1, &v2, ());
graph.add_edge(&v1, &v3, ());
graph.add_edge(&v1, &v4, ());
graph.add_edge(&v2, &v5, ());
graph.add_edge(&v5, &v4, ());
graph.remove_vertex(&v1);
let vertices = Bfs::new(&graph).start(v2).iter(&graph).collect::<Vec<_>>();
assert_eq!(vertices, vec![v2, v5, v4]);
}
#[test]
fn dfs_disconnected() {
let mut graph = Stable::new(AdjList::<_, _, Undirected, DefaultId>::new());
let v0 = graph.add_vertex(());
let v1 = graph.add_vertex(());
let v2 = graph.add_vertex(());
let v3 = graph.add_vertex(());
let v4 = graph.add_vertex(());
let v5 = graph.add_vertex(());
graph.add_edge(&v0, &v1, ());
graph.add_edge(&v1, &v2, ());
graph.add_edge(&v1, &v3, ());
graph.add_edge(&v1, &v4, ());
graph.add_edge(&v2, &v5, ());
graph.add_edge(&v5, &v4, ());
graph.remove_vertex(&v1);
let vertices = Dfs::new(&graph).start(v2).iter(&graph).collect::<Vec<_>>();
assert_eq!(vertices, vec![v2, v5, v4]);
}
#[test]
fn bfs_disconnected_all() {
let mut graph = Stable::new(AdjList::<_, _, Undirected, DefaultId>::new());
let v0 = graph.add_vertex(());
let v1 = graph.add_vertex(());
let v2 = graph.add_vertex(());
let v3 = graph.add_vertex(());
let v4 = graph.add_vertex(());
let v5 = graph.add_vertex(());
graph.add_edge(&v0, &v1, ());
graph.add_edge(&v1, &v2, ());
graph.add_edge(&v1, &v3, ());
graph.add_edge(&v1, &v4, ());
graph.add_edge(&v2, &v5, ());
graph.add_edge(&v5, &v4, ());
graph.remove_vertex(&v1);
let vertices = Bfs::new(&graph)
.start_all(&graph)
.iter(&graph)
.collect::<Vec<_>>();
assert_eq!(vertices, vec![v0, v2, v5, v4, v3]);
}
#[test]
fn dfs_disconnected_all() {
let mut graph = Stable::new(AdjList::<_, _, Undirected, DefaultId>::new());
let v0 = graph.add_vertex(());
let v1 = graph.add_vertex(());
let v2 = graph.add_vertex(());
let v3 = graph.add_vertex(());
let v4 = graph.add_vertex(());
let v5 = graph.add_vertex(());
graph.add_edge(&v0, &v1, ());
graph.add_edge(&v1, &v2, ());
graph.add_edge(&v1, &v3, ());
graph.add_edge(&v1, &v4, ());
graph.add_edge(&v2, &v5, ());
graph.add_edge(&v5, &v4, ());
graph.remove_vertex(&v1);
let vertices = Dfs::new(&graph)
.start_all(&graph)
.iter(&graph)
.collect::<Vec<_>>();
assert_eq!(vertices, vec![v0, v2, v5, v4, v3]);
}
#[test]
fn bfs_disconnected_multi() {
let mut graph = Stable::new(AdjList::<_, _, Undirected, DefaultId>::new());
let v0 = graph.add_vertex(());
let v1 = graph.add_vertex(());
let v2 = graph.add_vertex(());
let v3 = graph.add_vertex(());
let v4 = graph.add_vertex(());
let v5 = graph.add_vertex(());
graph.add_edge(&v0, &v1, ());
graph.add_edge(&v1, &v2, ());
graph.add_edge(&v1, &v3, ());
graph.add_edge(&v1, &v4, ());
graph.add_edge(&v2, &v5, ());
graph.add_edge(&v5, &v4, ());
graph.remove_vertex(&v1);
let vertices = Bfs::new(&graph)
.start_multi([v0, v2].into_iter())
.iter(&graph)
.collect::<Vec<_>>();
assert_eq!(vertices, vec![v0, v2, v5, v4]);
}
#[test]
fn bfs_disconnected_multi_mutation() {
let mut graph = Stable::new(AdjList::<_, _, Undirected, DefaultId>::new());
let v0 = graph.add_vertex(());
let v1 = graph.add_vertex(());
let v2 = graph.add_vertex(());
let v3 = graph.add_vertex(());
let v4 = graph.add_vertex(());
let v5 = graph.add_vertex(());
graph.add_edge(&v0, &v1, ());
graph.add_edge(&v1, &v2, ());
graph.add_edge(&v1, &v3, ());
graph.add_edge(&v1, &v4, ());
graph.add_edge(&v2, &v5, ());
graph.add_edge(&v5, &v4, ());
graph.remove_vertex(&v1);
let mut visit = Bfs::new(&graph);
let mut visit = visit.start_multi([v0, v2].into_iter());
graph.remove_vertex(&v0);
let vertices = visit.iter(&graph).collect::<Vec<_>>();
assert_eq!(vertices, vec![v2, v5, v4]);
}
#[test]
fn dfs_events() {
let mut graph = AdjList::<_, _, Undirected, DefaultId>::new();
let v0 = graph.add_vertex(());
let v1 = graph.add_vertex(());
let v2 = graph.add_vertex(());
let v3 = graph.add_vertex(());
let v4 = graph.add_vertex(());
let v5 = graph.add_vertex(());
let v6 = graph.add_vertex(());
let v7 = graph.add_vertex(());
let e0 = graph.add_edge(&v0, &v1, ());
let e1 = graph.add_edge(&v1, &v2, ());
let e2 = graph.add_edge(&v2, &v3, ());
let e3 = graph.add_edge(&v3, &v4, ());
let e4 = graph.add_edge(&v4, &v2, ());
let e5 = graph.add_edge(&v1, &v5, ());
let e6 = graph.add_edge(&v5, &v6, ());
let e7 = graph.add_edge(&v6, &v7, ());
let e8 = graph.add_edge(&v5, &v7, ());
let e9 = graph.add_edge(&v3, &v6, ());
let events = DfsEvents::new(&graph)
.start(v0)
.iter(&graph)
.collect::<Vec<_>>();
let expected = vec![
dfs_event!(open, v0, 0),
dfs_event!(tree, e0, (v0, v1)),
dfs_event!(open, v1, 1),
dfs_event!(tree, e5, (v1, v5)),
dfs_event!(open, v5, 2),
dfs_event!(tree, e8, (v5, v7)),
dfs_event!(open, v7, 3),
dfs_event!(tree, e7, (v7, v6)),
dfs_event!(open, v6, 4),
dfs_event!(tree, e9, (v6, v3)),
dfs_event!(open, v3, 5),
dfs_event!(tree, e3, (v3, v4)),
dfs_event!(open, v4, 6),
dfs_event!(tree, e4, (v4, v2)),
dfs_event!(open, v2, 7),
dfs_event!(back, e2, (v2, v3)),
dfs_event!(back, e1, (v2, v1)),
dfs_event!(close, v2, 8),
dfs_event!(close, v4, 9),
dfs_event!(close, v3, 10),
dfs_event!(back, e6, (v6, v5)),
dfs_event!(close, v6, 11),
dfs_event!(close, v7, 12),
dfs_event!(close, v5, 13),
dfs_event!(close, v1, 14),
dfs_event!(close, v0, 15),
];
assert_eq!(events, expected);
}
#[test]
fn dfs_events_directed() {
let mut graph = AdjList::<_, _, Directed, DefaultId>::new();
let v0 = graph.add_vertex(());
let v1 = graph.add_vertex(());
let v2 = graph.add_vertex(());
let v3 = graph.add_vertex(());
let v4 = graph.add_vertex(());
let v5 = graph.add_vertex(());
let v6 = graph.add_vertex(());
let v7 = graph.add_vertex(());
let e0 = graph.add_edge(&v0, &v1, ());
let e1 = graph.add_edge(&v1, &v2, ());
let e2 = graph.add_edge(&v2, &v3, ());
let e3 = graph.add_edge(&v3, &v4, ());
let e4 = graph.add_edge(&v4, &v2, ());
let e5 = graph.add_edge(&v1, &v5, ());
let e6 = graph.add_edge(&v5, &v6, ());
let e7 = graph.add_edge(&v6, &v7, ());
let e8 = graph.add_edge(&v5, &v7, ());
let e9 = graph.add_edge(&v3, &v6, ());
let events = DfsEvents::new(&graph)
.start(v0)
.iter(&graph)
.collect::<Vec<_>>();
let expected = vec![
dfs_event!(open, v0, 0),
dfs_event!(tree, e0, (v0, v1)),
dfs_event!(open, v1, 1),
dfs_event!(tree, e5, (v1, v5)),
dfs_event!(open, v5, 2),
dfs_event!(tree, e8, (v5, v7)),
dfs_event!(open, v7, 3),
dfs_event!(close, v7, 4),
dfs_event!(tree, e6, (v5, v6)),
dfs_event!(open, v6, 5),
dfs_event!(cross_forward, e7, (v6, v7)),
dfs_event!(close, v6, 6),
dfs_event!(close, v5, 7),
dfs_event!(tree, e1, (v1, v2)),
dfs_event!(open, v2, 8),
dfs_event!(tree, e2, (v2, v3)),
dfs_event!(open, v3, 9),
dfs_event!(cross_forward, e9, (v3, v6)),
dfs_event!(tree, e3, (v3, v4)),
dfs_event!(open, v4, 10),
dfs_event!(back, e4, (v4, v2)),
dfs_event!(close, v4, 11),
dfs_event!(close, v3, 12),
dfs_event!(close, v2, 13),
dfs_event!(close, v1, 14),
dfs_event!(close, v0, 15),
];
assert_eq!(events, expected);
}
#[test]
fn dfs_events_isolated() {
let mut graph = AdjList::<_, (), Undirected, DefaultId>::new();
let v0 = graph.add_vertex(());
let events = DfsEvents::new(&graph)
.start(v0)
.iter(&graph)
.collect::<Vec<_>>();
let expected = vec![dfs_event!(open, v0, 0), dfs_event!(close, v0, 1)];
assert_eq!(events, expected);
}
#[test]
fn dfs_post_order() {
let mut graph = AdjList::<_, _, Undirected, DefaultId>::new();
let v0 = graph.add_vertex(());
let v1 = graph.add_vertex(());
let v2 = graph.add_vertex(());
let v3 = graph.add_vertex(());
let v4 = graph.add_vertex(());
let v5 = graph.add_vertex(());
graph.add_edge(&v0, &v1, ());
graph.add_edge(&v1, &v2, ());
graph.add_edge(&v1, &v3, ());
graph.add_edge(&v1, &v4, ());
graph.add_edge(&v2, &v5, ());
graph.add_edge(&v5, &v4, ());
let vertices = DfsPostOrder::new(&graph)
.start(v0)
.iter(&graph)
.collect::<Vec<_>>();
assert_eq!(vertices, vec![v2, v5, v4, v3, v1, v0]);
}
#[test]
fn dfs_no_backtrack() {
let mut graph = AdjList::<_, _, Undirected, DefaultId>::new();
let v0 = graph.add_vertex(());
let v1 = graph.add_vertex(());
let v2 = graph.add_vertex(());
let v3 = graph.add_vertex(());
let v4 = graph.add_vertex(());
let v5 = graph.add_vertex(());
graph.add_edge(&v0, &v1, ());
graph.add_edge(&v1, &v2, ());
graph.add_edge(&v1, &v3, ());
graph.add_edge(&v1, &v4, ());
graph.add_edge(&v2, &v5, ());
graph.add_edge(&v5, &v4, ());
let vertices = DfsNoBacktrack::new(&graph)
.start(v0)
.iter(&graph)
.collect::<Vec<_>>();
assert_eq!(vertices, vec![v0, v1, v2, v5, v4]);
}
}