pub struct SeqIter<'a, S, G: RandomAccessGraph, P, const PRED: bool> { /* private fields */ }
Expand description
Sequential depth-first visits.
This is an iterative implementation that does not need a large stack size.
There are three version of the visit, which are type aliases to the same
common implementation: SeqNoPred
, SeqPred
and SeqPath
(the
generic implementation should not be instantiated by the user).
SeqNoPred
does not keep track of predecessors, nor of nodes on the stack; it can be used, for example, to compute reachability information.SeqPred
keeps track of predecessors, but not of nodes on the stack; it can be used, for example, to compute a topological sort.SeqPath
keeps track of predecessors and nodes on the stack; it can be used, for example, to establish acyclicity).
Each type of visit uses incrementally more space:
SeqNoPred
uses one bit per node to remember known nodes and a stack of iterators, one for each node on the visit path.SeqPred
uses one bit per node to remember known nodes and a stack of pairs made of an iterator and a predecessor, one for each node on the visit path.SeqPath
uses two bits per node to remember known nodes and whether the node is on the visit path, and a stack of pairs made of an iterator and a predecessor, one for each node on the visit path.
The visits differ also in the type of events they generate:
SeqNoPred
generates events of typeEventNoPred
.SeqPred
generates events of typeEventPred
, with the proviso that the Boolean associated with events of typeRevisit
is always false.SeqPath
generates events of typeEventPred
.
With respect to EventNoPred
, EventPred
provides the predecessor of the
current node and a postvisit event.
If the visit was interrupted, the nodes still on the visit path can be
retrieved using the stack
method (only for SeqPred
and
SeqPath
).
§Examples
Let’s test acyclicity:
use webgraph_algo::visits::*;
use webgraph_algo::visits::depth_first::*;
use webgraph::graphs::vec_graph::VecGraph;
use webgraph::traits::SequentialLabeling;
use webgraph::labels::proj::Left;
use std::ops::ControlFlow::*;
let graph = VecGraph::from_arcs([(0, 1), (1, 2), (2, 0), (1, 3)]);
let mut visit = depth_first::SeqPath::new(&graph);
assert!(visit.visit(
0..graph.num_nodes(),
|event| {
match event {
// Stop the visit as soon as a back edge is found
EventPred::Revisit { on_stack: true, .. } => Break(StoppedWhenDone),
_ => Continue(()),
}
},
).is_break()); // As the graph is not acyclic
Or, assuming the input is acyclic, let us compute the reverse of a topological sort:
use webgraph_algo::visits::*;
use webgraph_algo::visits::depth_first::*;
use webgraph::graphs::vec_graph::VecGraph;
use webgraph::labels::proj::Left;
use webgraph::traits::labels::SequentialLabeling;
use std::ops::ControlFlow::Continue;
use no_break::NoBreak;
let graph = VecGraph::from_arcs([(0, 1), (1, 2), (1, 3), (0, 3)]);
let mut visit = depth_first::SeqPred::new(&graph);
let mut top_sort = Vec::with_capacity(graph.num_nodes());
visit.visit(
0..graph.num_nodes(),
|event| {
if let EventPred::Postvisit { node, .. } = event {
top_sort.push(node);
}
Continue(())
}
).continue_value_no_break();
Implementations§
Source§impl<'a, S: NodeStates, G: RandomAccessGraph, P, const PRED: bool> SeqIter<'a, S, G, P, PRED>
impl<'a, S: NodeStates, G: RandomAccessGraph, P, const PRED: bool> SeqIter<'a, S, G, P, PRED>
Source§impl<'a, S, G: RandomAccessGraph> SeqIter<'a, S, G, usize, true>
impl<'a, S, G: RandomAccessGraph> SeqIter<'a, S, G, usize, true>
Sourcepub fn stack(&mut self) -> StackIterator<'a, '_, S, G> ⓘ
pub fn stack(&mut self) -> StackIterator<'a, '_, S, G> ⓘ
Returns an iterator over the nodes still on the visit path, except for the last one.
Node will be returned in reverse order of visit.
This method is useful only in the case of interrupted visits, as in a completed visit the stack will be empty. The last node on the visit path at the moment of the interruption must be treated separately.
Trait Implementations§
Source§impl<S: NodeStates, G: RandomAccessGraph> Sequential<EventPred> for SeqIter<'_, S, G, usize, true>
impl<S: NodeStates, G: RandomAccessGraph> Sequential<EventPred> for SeqIter<'_, S, G, usize, true>
Source§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,
init: T,
callback: C,
filter: F,
) -> ControlFlow<E, ()>
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, init: T, callback: C, filter: F, ) -> ControlFlow<E, ()>
Source§fn visit_filtered<R: IntoIterator<Item = usize>, E, C: FnMut(A) -> ControlFlow<E, ()>, F: FnMut(A::FilterArgs) -> bool>(
&mut self,
roots: R,
callback: C,
filter: F,
) -> ControlFlow<E, ()>
fn visit_filtered<R: IntoIterator<Item = usize>, E, C: FnMut(A) -> ControlFlow<E, ()>, F: FnMut(A::FilterArgs) -> bool>( &mut self, roots: R, callback: C, filter: F, ) -> ControlFlow<E, ()>
Source§fn visit_with<R: IntoIterator<Item = usize>, T, E, C: FnMut(&mut T, A) -> ControlFlow<E, ()>>(
&mut self,
roots: R,
init: T,
callback: C,
) -> ControlFlow<E, ()>
fn visit_with<R: IntoIterator<Item = usize>, T, E, C: FnMut(&mut T, A) -> ControlFlow<E, ()>>( &mut self, roots: R, init: T, callback: C, ) -> ControlFlow<E, ()>
Source§fn visit<R: IntoIterator<Item = usize>, E, C: FnMut(A) -> ControlFlow<E, ()>>(
&mut self,
roots: R,
callback: C,
) -> ControlFlow<E, ()>
fn visit<R: IntoIterator<Item = usize>, E, C: FnMut(A) -> ControlFlow<E, ()>>( &mut self, roots: R, callback: C, ) -> ControlFlow<E, ()>
Auto Trait Implementations§
impl<'a, S, G, P, const PRED: bool> Freeze for SeqIter<'a, S, G, P, PRED>where
S: Freeze,
impl<'a, S, G, P, const PRED: bool> RefUnwindSafe for SeqIter<'a, S, G, P, PRED>where
S: RefUnwindSafe,
G: RefUnwindSafe,
<<G as RandomAccessLabeling>::Labels<'a> as IntoIterator>::IntoIter: RefUnwindSafe,
P: RefUnwindSafe,
impl<'a, S, G, P, const PRED: bool> Send for SeqIter<'a, S, G, P, PRED>where
S: Send,
G: Sync,
<<G as RandomAccessLabeling>::Labels<'a> as IntoIterator>::IntoIter: Send,
P: Send,
impl<'a, S, G, P, const PRED: bool> Sync for SeqIter<'a, S, G, P, PRED>where
S: Sync,
G: Sync,
<<G as RandomAccessLabeling>::Labels<'a> as IntoIterator>::IntoIter: Sync,
P: Sync,
impl<'a, S, G, P, const PRED: bool> Unpin for SeqIter<'a, S, G, P, PRED>where
S: Unpin,
<<G as RandomAccessLabeling>::Labels<'a> as IntoIterator>::IntoIter: Unpin,
P: Unpin,
impl<'a, S, G, P, const PRED: bool> UnwindSafe for SeqIter<'a, S, G, P, PRED>where
S: UnwindSafe,
G: RefUnwindSafe,
<<G as RandomAccessLabeling>::Labels<'a> as IntoIterator>::IntoIter: UnwindSafe,
P: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T, U> CastableInto<U> for Twhere
U: CastableFrom<T>,
impl<T, U> CastableInto<U> for Twhere
U: CastableFrom<T>,
Source§impl<T, U> CastableInto<U> for Twhere
U: CastableFrom<T>,
impl<T, U> CastableInto<U> for Twhere
U: CastableFrom<T>,
Source§impl<T> DowncastableFrom<T> for T
impl<T> DowncastableFrom<T> for T
Source§fn downcast_from(value: T) -> T
fn downcast_from(value: T) -> T
Source§impl<T> DowncastableFrom<T> for T
impl<T> DowncastableFrom<T> for T
Source§fn downcast_from(value: T) -> T
fn downcast_from(value: T) -> T
Source§impl<T, U> DowncastableInto<U> for Twhere
U: DowncastableFrom<T>,
impl<T, U> DowncastableInto<U> for Twhere
U: DowncastableFrom<T>,
Source§impl<T, U> DowncastableInto<U> for Twhere
U: DowncastableFrom<T>,
impl<T, U> DowncastableInto<U> for Twhere
U: DowncastableFrom<T>,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more