guppy/petgraph_support/
walk.rsuse crate::petgraph_support::edge_triple;
use petgraph::visit::{IntoEdges, VisitMap, Visitable, Walker};
use std::iter;
#[derive(Clone, Debug)]
pub(crate) struct EdgeDfs<E, N, VM> {
pub stack: Vec<(N, N, E)>,
pub discovered: VM,
}
impl<E, N, VM> EdgeDfs<E, N, VM>
where
E: Copy + PartialEq,
N: Copy + PartialEq,
VM: VisitMap<N>,
{
pub(crate) fn new<G>(graph: G, initials: impl IntoIterator<Item = N>) -> Self
where
G: Visitable<Map = VM> + IntoEdges<NodeId = N, EdgeId = E>,
{
let mut discovered = graph.visit_map();
let stack = initials
.into_iter()
.filter_map(|node_ix| {
if discovered.visit(node_ix) {
Some(graph.edges(node_ix).map(edge_triple))
} else {
None
}
})
.flatten()
.collect();
Self { stack, discovered }
}
#[allow(dead_code)]
pub(crate) fn new_single<G>(graph: G, start: N) -> Self
where
G: Visitable<Map = VM> + IntoEdges<NodeId = N, EdgeId = E>,
{
Self::new(graph, iter::once(start))
}
pub fn next<G>(&mut self, graph: G) -> Option<(N, N, E)>
where
G: IntoEdges<NodeId = N, EdgeId = E>,
{
let (source, target, edge) = self.stack.pop()?;
if self.discovered.visit(target) {
self.stack.extend(graph.edges(target).map(edge_triple));
}
Some((source, target, edge))
}
}
impl<G> Walker<G> for EdgeDfs<G::EdgeId, G::NodeId, G::Map>
where
G: IntoEdges + Visitable,
{
type Item = (G::NodeId, G::NodeId, G::EdgeId);
fn walk_next(&mut self, context: G) -> Option<Self::Item> {
self.next(context)
}
}