use crate::traits::{RandomAccessGraph, RandomAccessLabeling};
use crate::visits::{
Sequential,
depth_first::{EventNoPred, EventPred, FilterArgsNoPred, FilterArgsPred},
};
use sealed::sealed;
use std::ops::ControlFlow::{self, Continue};
use sux::bits::BitVec;
use sux::traits::{BitVecOps, BitVecOpsMut};
pub type SeqNoPred<'a, G> = SeqIter<'a, TwoStates, G, (), false>;
pub type SeqPred<'a, G> = SeqIter<'a, TwoStates, G, usize, true>;
pub type SeqPath<'a, G> = SeqIter<'a, ThreeStates, G, usize, true>;
pub struct SeqIter<'a, S, G: RandomAccessGraph, P, const PRED: bool> {
graph: &'a G,
stack: Vec<(
<<G as RandomAccessLabeling>::Labels<'a> as IntoIterator>::IntoIter,
P,
)>,
state: S,
}
pub struct StackIter<'a, 'b, S, G: RandomAccessGraph> {
visit: &'b mut SeqIter<'a, S, G, usize, true>,
}
impl<S, G: RandomAccessGraph> Iterator for StackIter<'_, '_, S, G> {
type Item = usize;
fn next(&mut self) -> Option<usize> {
if self.visit.stack.len() <= 1 {
return None;
}
self.visit.stack.pop().map(|(_, parent)| parent)
}
}
impl<'a, S: NodeStates, G: RandomAccessGraph, P, const PRED: bool> SeqIter<'a, S, G, P, PRED> {
pub fn new(graph: &'a G) -> SeqIter<'a, S, G, P, PRED> {
let num_nodes = graph.num_nodes();
Self {
graph,
stack: Vec::with_capacity(16),
state: S::new(num_nodes),
}
}
pub fn reset(&mut self) {
self.stack.clear();
self.state.reset();
}
}
impl<'a, S, G: RandomAccessGraph> SeqIter<'a, S, G, usize, true> {
pub fn stack(&mut self) -> StackIter<'a, '_, S, G> {
StackIter { visit: self }
}
}
#[doc(hidden)]
#[sealed]
pub trait NodeStates {
fn new(n: usize) -> Self;
fn set_on_stack(&mut self, node: usize);
fn set_off_stack(&mut self, node: usize);
fn on_stack(&self, node: usize) -> bool;
fn set_known(&mut self, node: usize);
fn known(&self, node: usize) -> bool;
fn reset(&mut self);
}
#[doc(hidden)]
pub struct TwoStates(BitVec);
#[sealed]
impl NodeStates for TwoStates {
fn new(n: usize) -> TwoStates {
TwoStates(BitVec::new(n))
}
#[inline(always)]
fn set_on_stack(&mut self, _node: usize) {}
#[inline(always)]
fn set_off_stack(&mut self, _node: usize) {}
#[inline(always)]
fn on_stack(&self, _node: usize) -> bool {
false
}
#[inline(always)]
fn set_known(&mut self, node: usize) {
self.0.set(node, true);
}
#[inline(always)]
fn known(&self, node: usize) -> bool {
self.0.get(node)
}
#[inline(always)]
fn reset(&mut self) {
self.0.reset();
}
}
#[doc(hidden)]
pub struct ThreeStates(BitVec);
#[sealed]
impl NodeStates for ThreeStates {
fn new(n: usize) -> ThreeStates {
ThreeStates(BitVec::new(2 * n))
}
#[inline(always)]
fn set_on_stack(&mut self, node: usize) {
self.0.set(node * 2 + 1, true);
}
#[inline(always)]
fn set_off_stack(&mut self, node: usize) {
self.0.set(node * 2 + 1, false);
}
#[inline(always)]
fn on_stack(&self, node: usize) -> bool {
self.0.get(node * 2 + 1)
}
#[inline(always)]
fn set_known(&mut self, node: usize) {
self.0.set(node * 2, true);
}
#[inline(always)]
fn known(&self, node: usize) -> bool {
self.0.get(node * 2)
}
#[inline(always)]
fn reset(&mut self) {
self.0.reset();
}
}
impl<S: NodeStates, G: RandomAccessGraph> Sequential<EventPred> for SeqIter<'_, S, G, usize, true> {
fn visit_filtered_with<
R: IntoIterator<Item = usize>,
T,
E,
C: FnMut(&mut T, EventPred) -> ControlFlow<E, ()>,
F: FnMut(&mut T, FilterArgsPred) -> bool,
>(
&mut self,
roots: R,
mut init: T,
mut callback: C,
mut filter: F,
) -> ControlFlow<E, ()> {
let state = &mut self.state;
for root in roots {
if state.known(root)
|| !filter(
&mut init,
FilterArgsPred {
node: root,
pred: root,
root,
depth: 0,
},
)
{
continue;
}
callback(&mut init, EventPred::Init { root })?;
state.set_known(root);
callback(
&mut init,
EventPred::Previsit {
node: root,
parent: root,
root,
depth: 0,
},
)?;
self.stack
.push((self.graph.successors(root).into_iter(), root));
state.set_on_stack(root);
let mut curr = root;
'recurse: loop {
let depth = self.stack.len();
let Some((iter, parent)) = self.stack.last_mut() else {
callback(&mut init, EventPred::Done { root })?;
break;
};
for succ in iter {
if state.known(succ) {
callback(
&mut init,
EventPred::Revisit {
node: succ,
pred: curr,
root,
depth,
on_stack: state.on_stack(succ),
},
)?;
} else {
if filter(
&mut init,
FilterArgsPred {
node: succ,
pred: curr,
root,
depth,
},
) {
state.set_known(succ);
callback(
&mut init,
EventPred::Previsit {
node: succ,
parent: curr,
root,
depth,
},
)?;
self.stack
.push((self.graph.successors(succ).into_iter(), curr));
state.set_on_stack(succ);
curr = succ;
continue 'recurse;
} }
}
callback(
&mut init,
EventPred::Postvisit {
node: curr,
parent: *parent,
root,
depth: depth - 1,
},
)?;
state.set_off_stack(curr);
curr = *parent;
self.stack.pop();
}
}
Continue(())
}
fn reset(&mut self) {
self.stack.clear();
self.state.reset();
}
}
impl<G: RandomAccessGraph> Sequential<EventNoPred> for SeqIter<'_, TwoStates, G, (), false> {
fn visit_filtered_with<
R: IntoIterator<Item = usize>,
T,
E,
C: FnMut(&mut T, EventNoPred) -> ControlFlow<E, ()>,
F: FnMut(&mut T, FilterArgsNoPred) -> bool,
>(
&mut self,
roots: R,
mut init: T,
mut callback: C,
mut filter: F,
) -> ControlFlow<E, ()> {
let state = &mut self.state;
for root in roots {
if state.known(root)
|| !filter(
&mut init,
FilterArgsNoPred {
node: root,
root,
depth: 0,
},
)
{
continue;
}
callback(&mut init, EventNoPred::Init { root })?;
state.set_known(root);
callback(
&mut init,
EventNoPred::Previsit {
node: root,
root,
depth: 0,
},
)?;
self.stack
.push((self.graph.successors(root).into_iter(), ()));
'recurse: loop {
let depth = self.stack.len();
let Some((iter, _)) = self.stack.last_mut() else {
callback(&mut init, EventNoPred::Done { root })?;
break;
};
for succ in iter {
if state.known(succ) {
callback(
&mut init,
EventNoPred::Revisit {
node: succ,
root,
depth,
},
)?;
} else {
if filter(
&mut init,
FilterArgsNoPred {
node: succ,
root,
depth,
},
) {
state.set_known(succ);
callback(
&mut init,
EventNoPred::Previsit {
node: succ,
root,
depth,
},
)?;
self.stack
.push((self.graph.successors(succ).into_iter(), ()));
continue 'recurse;
} }
}
self.stack.pop();
}
}
Continue(())
}
fn reset(&mut self) {
self.stack.clear();
self.state.reset();
}
}
impl<'a, 'b, G: RandomAccessGraph> IntoIterator for &'b mut SeqPred<'a, G> {
type Item = IterEvent;
type IntoIter = DfsOrder<'a, 'b, G>;
fn into_iter(self) -> Self::IntoIter {
DfsOrder::new(self)
}
}
pub struct DfsOrder<'a, 'b, G: RandomAccessGraph> {
visit: &'b mut SeqPred<'a, G>,
root: usize,
visited_nodes: usize,
}
impl<'a, 'b, G: RandomAccessGraph> DfsOrder<'a, 'b, G> {
pub fn new(visit: &'b mut SeqPred<'a, G>) -> Self {
visit.reset(); DfsOrder {
visit,
root: 0,
visited_nodes: 0,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IterEvent {
pub root: usize,
pub parent: usize,
pub node: usize,
pub depth: usize,
}
impl<'a, 'b, G: RandomAccessGraph> Iterator for DfsOrder<'a, 'b, G> {
type Item = IterEvent;
fn next(&mut self) -> Option<Self::Item> {
let state = &mut self.visit.state;
let stack = &mut self.visit.stack;
while let Some((iter, parent)) = stack.last_mut() {
let parent = *parent; for succ in iter {
if state.known(succ) {
continue;
}
state.set_known(succ);
stack.push((self.visit.graph.successors(succ).into_iter(), succ));
self.visited_nodes += 1;
return Some(IterEvent {
root: self.root,
parent,
node: succ,
depth: stack.len() - 1,
});
}
stack.pop();
}
while self.root < self.visit.graph.num_nodes() && state.known(self.root) {
self.root += 1;
}
if self.root >= self.visit.graph.num_nodes() {
return None;
}
let root = self.root;
self.root += 1;
self.visited_nodes += 1;
state.set_known(root);
stack.push((self.visit.graph.successors(root).into_iter(), root));
Some(IterEvent {
root,
parent: root,
node: root,
depth: 0,
})
}
}
impl<'a, 'b, G: RandomAccessGraph> ExactSizeIterator for DfsOrder<'a, 'b, G> {
fn len(&self) -> usize {
self.visit.graph.num_nodes() - self.visited_nodes
}
}