use alloc::{collections::VecDeque, vec::Vec};
use super::{
GraphRef, IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers, Reversed, VisitMap,
Visitable,
};
use crate::Incoming;
#[derive(Clone, Debug)]
pub struct Dfs<N, VM> {
pub stack: Vec<N>,
pub discovered: VM,
}
impl<N, VM> Default for Dfs<N, VM>
where
VM: Default,
{
fn default() -> Self {
Dfs {
stack: Vec::new(),
discovered: VM::default(),
}
}
}
impl<N, VM> Dfs<N, VM>
where
N: Copy + PartialEq,
VM: VisitMap<N>,
{
pub fn new<G>(graph: G, start: N) -> Self
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
let mut dfs = Dfs::empty(graph);
dfs.move_to(start);
dfs
}
pub fn from_parts(stack: Vec<N>, discovered: VM) -> Self {
Dfs { stack, discovered }
}
pub fn reset<G>(&mut self, graph: G)
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
graph.reset_map(&mut self.discovered);
self.stack.clear();
}
pub fn empty<G>(graph: G) -> Self
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
Dfs {
stack: Vec::new(),
discovered: graph.visit_map(),
}
}
pub fn move_to(&mut self, start: N) {
self.stack.clear();
self.stack.push(start);
}
pub fn next<G>(&mut self, graph: G) -> Option<N>
where
G: IntoNeighbors<NodeId = N>,
{
while let Some(node) = self.stack.pop() {
if self.discovered.visit(node) {
for succ in graph.neighbors(node) {
if !self.discovered.is_visited(&succ) {
self.stack.push(succ);
}
}
return Some(node);
}
}
None
}
}
#[derive(Clone, Debug)]
pub struct DfsPostOrder<N, VM> {
pub stack: Vec<N>,
pub discovered: VM,
pub finished: VM,
}
impl<N, VM> Default for DfsPostOrder<N, VM>
where
VM: Default,
{
fn default() -> Self {
DfsPostOrder {
stack: Vec::new(),
discovered: VM::default(),
finished: VM::default(),
}
}
}
impl<N, VM> DfsPostOrder<N, VM>
where
N: Copy + PartialEq,
VM: VisitMap<N>,
{
pub fn new<G>(graph: G, start: N) -> Self
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
let mut dfs = Self::empty(graph);
dfs.move_to(start);
dfs
}
pub fn empty<G>(graph: G) -> Self
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
DfsPostOrder {
stack: Vec::new(),
discovered: graph.visit_map(),
finished: graph.visit_map(),
}
}
pub fn reset<G>(&mut self, graph: G)
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
graph.reset_map(&mut self.discovered);
graph.reset_map(&mut self.finished);
self.stack.clear();
}
pub fn move_to(&mut self, start: N) {
self.stack.clear();
self.stack.push(start);
}
pub fn next<G>(&mut self, graph: G) -> Option<N>
where
G: IntoNeighbors<NodeId = N>,
{
while let Some(&nx) = self.stack.last() {
if self.discovered.visit(nx) {
for succ in graph.neighbors(nx) {
if !self.discovered.is_visited(&succ) {
self.stack.push(succ);
}
}
} else {
self.stack.pop();
if self.finished.visit(nx) {
return Some(nx);
}
}
}
None
}
}
#[derive(Clone)]
pub struct Bfs<N, VM> {
pub stack: VecDeque<N>,
pub discovered: VM,
}
impl<N, VM> Default for Bfs<N, VM>
where
VM: Default,
{
fn default() -> Self {
Bfs {
stack: VecDeque::new(),
discovered: VM::default(),
}
}
}
impl<N, VM> Bfs<N, VM>
where
N: Copy + PartialEq,
VM: VisitMap<N>,
{
pub fn new<G>(graph: G, start: N) -> Self
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
let mut discovered = graph.visit_map();
discovered.visit(start);
let mut stack = VecDeque::new();
stack.push_front(start);
Bfs { stack, discovered }
}
pub fn next<G>(&mut self, graph: G) -> Option<N>
where
G: IntoNeighbors<NodeId = N>,
{
if let Some(node) = self.stack.pop_front() {
for succ in graph.neighbors(node) {
if self.discovered.visit(succ) {
self.stack.push_back(succ);
}
}
return Some(node);
}
None
}
}
#[derive(Clone)]
pub struct Topo<N, VM> {
tovisit: Vec<N>,
ordered: VM,
}
impl<N, VM> Default for Topo<N, VM>
where
VM: Default,
{
fn default() -> Self {
Topo {
tovisit: Vec::new(),
ordered: VM::default(),
}
}
}
impl<N, VM> Topo<N, VM>
where
N: Copy + PartialEq,
VM: VisitMap<N>,
{
pub fn new<G>(graph: G) -> Self
where
G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
{
let mut topo = Self::empty(graph);
topo.extend_with_initials(graph);
topo
}
pub fn with_initials<G, I>(graph: G, initials: I) -> Self
where
G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
I: IntoIterator<Item = N>,
{
Topo {
tovisit: initials
.into_iter()
.filter(|&n| graph.neighbors_directed(n, Incoming).next().is_none())
.collect(),
ordered: graph.visit_map(),
}
}
fn extend_with_initials<G>(&mut self, g: G)
where
G: IntoNodeIdentifiers + IntoNeighborsDirected<NodeId = N>,
{
self.tovisit.extend(
g.node_identifiers()
.filter(move |&a| g.neighbors_directed(a, Incoming).next().is_none()),
);
}
fn empty<G>(graph: G) -> Self
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
Topo {
ordered: graph.visit_map(),
tovisit: Vec::new(),
}
}
pub fn reset<G>(&mut self, graph: G)
where
G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
{
graph.reset_map(&mut self.ordered);
self.tovisit.clear();
self.extend_with_initials(graph);
}
pub fn next<G>(&mut self, g: G) -> Option<N>
where
G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
{
while let Some(nix) = self.tovisit.pop() {
if self.ordered.is_visited(&nix) {
continue;
}
self.ordered.visit(nix);
for neigh in g.neighbors(nix) {
if Reversed(g)
.neighbors(neigh)
.all(|b| self.ordered.is_visited(&b))
{
self.tovisit.push(neigh);
}
}
return Some(nix);
}
None
}
}
pub trait Walker<Context> {
type Item;
fn walk_next(&mut self, context: Context) -> Option<Self::Item>;
fn iter(self, context: Context) -> WalkerIter<Self, Context>
where
Self: Sized,
Context: Clone,
{
WalkerIter {
walker: self,
context,
}
}
}
#[derive(Clone, Debug)]
pub struct WalkerIter<W, C> {
walker: W,
context: C,
}
impl<W, C> WalkerIter<W, C>
where
W: Walker<C>,
C: Clone,
{
pub fn context(&self) -> C {
self.context.clone()
}
pub fn inner_ref(&self) -> &W {
&self.walker
}
pub fn inner_mut(&mut self) -> &mut W {
&mut self.walker
}
}
impl<W, C> Iterator for WalkerIter<W, C>
where
W: Walker<C>,
C: Clone,
{
type Item = W::Item;
fn next(&mut self) -> Option<Self::Item> {
self.walker.walk_next(self.context.clone())
}
}
impl<C, W: ?Sized> Walker<C> for &mut W
where
W: Walker<C>,
{
type Item = W::Item;
fn walk_next(&mut self, context: C) -> Option<Self::Item> {
(**self).walk_next(context)
}
}
impl<G> Walker<G> for Dfs<G::NodeId, G::Map>
where
G: IntoNeighbors + Visitable,
{
type Item = G::NodeId;
fn walk_next(&mut self, context: G) -> Option<Self::Item> {
self.next(context)
}
}
impl<G> Walker<G> for DfsPostOrder<G::NodeId, G::Map>
where
G: IntoNeighbors + Visitable,
{
type Item = G::NodeId;
fn walk_next(&mut self, context: G) -> Option<Self::Item> {
self.next(context)
}
}
impl<G> Walker<G> for Bfs<G::NodeId, G::Map>
where
G: IntoNeighbors + Visitable,
{
type Item = G::NodeId;
fn walk_next(&mut self, context: G) -> Option<Self::Item> {
self.next(context)
}
}
impl<G> Walker<G> for Topo<G::NodeId, G::Map>
where
G: IntoNeighborsDirected + Visitable,
{
type Item = G::NodeId;
fn walk_next(&mut self, context: G) -> Option<Self::Item> {
self.next(context)
}
}