1use super::{GraphRef, IntoNodeIdentifiers, Reversed};
2use super::{IntoNeighbors, IntoNeighborsDirected, VisitMap, Visitable};
3use crate::Incoming;
4use std::collections::VecDeque;
5
6#[derive(Clone, Debug)]
37pub struct Dfs<N, VM> {
38    pub stack: Vec<N>,
40    pub discovered: VM,
42}
43
44impl<N, VM> Default for Dfs<N, VM>
45where
46    VM: Default,
47{
48    fn default() -> Self {
49        Dfs {
50            stack: Vec::new(),
51            discovered: VM::default(),
52        }
53    }
54}
55
56impl<N, VM> Dfs<N, VM>
57where
58    N: Copy + PartialEq,
59    VM: VisitMap<N>,
60{
61    pub fn new<G>(graph: G, start: N) -> Self
64    where
65        G: GraphRef + Visitable<NodeId = N, Map = VM>,
66    {
67        let mut dfs = Dfs::empty(graph);
68        dfs.move_to(start);
69        dfs
70    }
71
72    pub fn from_parts(stack: Vec<N>, discovered: VM) -> Self {
74        Dfs { stack, discovered }
75    }
76
77    pub fn reset<G>(&mut self, graph: G)
79    where
80        G: GraphRef + Visitable<NodeId = N, Map = VM>,
81    {
82        graph.reset_map(&mut self.discovered);
83        self.stack.clear();
84    }
85
86    pub fn empty<G>(graph: G) -> Self
88    where
89        G: GraphRef + Visitable<NodeId = N, Map = VM>,
90    {
91        Dfs {
92            stack: Vec::new(),
93            discovered: graph.visit_map(),
94        }
95    }
96
97    pub fn move_to(&mut self, start: N) {
100        self.stack.clear();
101        self.stack.push(start);
102    }
103
104    pub fn next<G>(&mut self, graph: G) -> Option<N>
106    where
107        G: IntoNeighbors<NodeId = N>,
108    {
109        while let Some(node) = self.stack.pop() {
110            if self.discovered.visit(node) {
111                for succ in graph.neighbors(node) {
112                    if !self.discovered.is_visited(&succ) {
113                        self.stack.push(succ);
114                    }
115                }
116                return Some(node);
117            }
118        }
119        None
120    }
121}
122
123#[derive(Clone, Debug)]
131pub struct DfsPostOrder<N, VM> {
132    pub stack: Vec<N>,
134    pub discovered: VM,
136    pub finished: VM,
138}
139
140impl<N, VM> Default for DfsPostOrder<N, VM>
141where
142    VM: Default,
143{
144    fn default() -> Self {
145        DfsPostOrder {
146            stack: Vec::new(),
147            discovered: VM::default(),
148            finished: VM::default(),
149        }
150    }
151}
152
153impl<N, VM> DfsPostOrder<N, VM>
154where
155    N: Copy + PartialEq,
156    VM: VisitMap<N>,
157{
158    pub fn new<G>(graph: G, start: N) -> Self
161    where
162        G: GraphRef + Visitable<NodeId = N, Map = VM>,
163    {
164        let mut dfs = Self::empty(graph);
165        dfs.move_to(start);
166        dfs
167    }
168
169    pub fn empty<G>(graph: G) -> Self
171    where
172        G: GraphRef + Visitable<NodeId = N, Map = VM>,
173    {
174        DfsPostOrder {
175            stack: Vec::new(),
176            discovered: graph.visit_map(),
177            finished: graph.visit_map(),
178        }
179    }
180
181    pub fn reset<G>(&mut self, graph: G)
183    where
184        G: GraphRef + Visitable<NodeId = N, Map = VM>,
185    {
186        graph.reset_map(&mut self.discovered);
187        graph.reset_map(&mut self.finished);
188        self.stack.clear();
189    }
190
191    pub fn move_to(&mut self, start: N) {
194        self.stack.clear();
195        self.stack.push(start);
196    }
197
198    pub fn next<G>(&mut self, graph: G) -> Option<N>
200    where
201        G: IntoNeighbors<NodeId = N>,
202    {
203        while let Some(&nx) = self.stack.last() {
204            if self.discovered.visit(nx) {
205                for succ in graph.neighbors(nx) {
207                    if !self.discovered.is_visited(&succ) {
208                        self.stack.push(succ);
209                    }
210                }
211            } else {
212                self.stack.pop();
213                if self.finished.visit(nx) {
214                    return Some(nx);
216                }
217            }
218        }
219        None
220    }
221}
222
223#[derive(Clone)]
253pub struct Bfs<N, VM> {
254    pub stack: VecDeque<N>,
256    pub discovered: VM,
258}
259
260impl<N, VM> Default for Bfs<N, VM>
261where
262    VM: Default,
263{
264    fn default() -> Self {
265        Bfs {
266            stack: VecDeque::new(),
267            discovered: VM::default(),
268        }
269    }
270}
271
272impl<N, VM> Bfs<N, VM>
273where
274    N: Copy + PartialEq,
275    VM: VisitMap<N>,
276{
277    pub fn new<G>(graph: G, start: N) -> Self
280    where
281        G: GraphRef + Visitable<NodeId = N, Map = VM>,
282    {
283        let mut discovered = graph.visit_map();
284        discovered.visit(start);
285        let mut stack = VecDeque::new();
286        stack.push_front(start);
287        Bfs { stack, discovered }
288    }
289
290    pub fn next<G>(&mut self, graph: G) -> Option<N>
292    where
293        G: IntoNeighbors<NodeId = N>,
294    {
295        if let Some(node) = self.stack.pop_front() {
296            for succ in graph.neighbors(node) {
297                if self.discovered.visit(succ) {
298                    self.stack.push_back(succ);
299                }
300            }
301
302            return Some(node);
303        }
304        None
305    }
306}
307
308#[derive(Clone)]
314pub struct Topo<N, VM> {
315    tovisit: Vec<N>,
316    ordered: VM,
317}
318
319impl<N, VM> Default for Topo<N, VM>
320where
321    VM: Default,
322{
323    fn default() -> Self {
324        Topo {
325            tovisit: Vec::new(),
326            ordered: VM::default(),
327        }
328    }
329}
330
331impl<N, VM> Topo<N, VM>
332where
333    N: Copy + PartialEq,
334    VM: VisitMap<N>,
335{
336    pub fn new<G>(graph: G) -> Self
339    where
340        G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
341    {
342        let mut topo = Self::empty(graph);
343        topo.extend_with_initials(graph);
344        topo
345    }
346
347    pub fn with_initials<G, I>(graph: G, initials: I) -> Self
351    where
352        G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
353        I: IntoIterator<Item = N>,
354    {
355        Topo {
356            tovisit: initials
357                .into_iter()
358                .filter(|&n| graph.neighbors_directed(n, Incoming).next().is_none())
359                .collect(),
360            ordered: graph.visit_map(),
361        }
362    }
363
364    fn extend_with_initials<G>(&mut self, g: G)
365    where
366        G: IntoNodeIdentifiers + IntoNeighborsDirected<NodeId = N>,
367    {
368        self.tovisit.extend(
370            g.node_identifiers()
371                .filter(move |&a| g.neighbors_directed(a, Incoming).next().is_none()),
372        );
373    }
374
375    fn empty<G>(graph: G) -> Self
379    where
380        G: GraphRef + Visitable<NodeId = N, Map = VM>,
381    {
382        Topo {
383            ordered: graph.visit_map(),
384            tovisit: Vec::new(),
385        }
386    }
387
388    pub fn reset<G>(&mut self, graph: G)
390    where
391        G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
392    {
393        graph.reset_map(&mut self.ordered);
394        self.tovisit.clear();
395        self.extend_with_initials(graph);
396    }
397
398    pub fn next<G>(&mut self, g: G) -> Option<N>
404    where
405        G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
406    {
407        while let Some(nix) = self.tovisit.pop() {
409            if self.ordered.is_visited(&nix) {
410                continue;
411            }
412            self.ordered.visit(nix);
413            for neigh in g.neighbors(nix) {
414                if Reversed(g)
417                    .neighbors(neigh)
418                    .all(|b| self.ordered.is_visited(&b))
419                {
420                    self.tovisit.push(neigh);
421                }
422            }
423            return Some(nix);
424        }
425        None
426    }
427}
428
429pub trait Walker<Context> {
435    type Item;
436    fn walk_next(&mut self, context: Context) -> Option<Self::Item>;
438
439    fn iter(self, context: Context) -> WalkerIter<Self, Context>
441    where
442        Self: Sized,
443        Context: Clone,
444    {
445        WalkerIter {
446            walker: self,
447            context,
448        }
449    }
450}
451
452#[derive(Clone, Debug)]
454pub struct WalkerIter<W, C> {
455    walker: W,
456    context: C,
457}
458
459impl<W, C> WalkerIter<W, C>
460where
461    W: Walker<C>,
462    C: Clone,
463{
464    pub fn context(&self) -> C {
465        self.context.clone()
466    }
467
468    pub fn inner_ref(&self) -> &W {
469        &self.walker
470    }
471
472    pub fn inner_mut(&mut self) -> &mut W {
473        &mut self.walker
474    }
475}
476
477impl<W, C> Iterator for WalkerIter<W, C>
478where
479    W: Walker<C>,
480    C: Clone,
481{
482    type Item = W::Item;
483    fn next(&mut self) -> Option<Self::Item> {
484        self.walker.walk_next(self.context.clone())
485    }
486}
487
488impl<'a, C, W: ?Sized> Walker<C> for &'a mut W
489where
490    W: Walker<C>,
491{
492    type Item = W::Item;
493    fn walk_next(&mut self, context: C) -> Option<Self::Item> {
494        (**self).walk_next(context)
495    }
496}
497
498impl<G> Walker<G> for Dfs<G::NodeId, G::Map>
499where
500    G: IntoNeighbors + Visitable,
501{
502    type Item = G::NodeId;
503    fn walk_next(&mut self, context: G) -> Option<Self::Item> {
504        self.next(context)
505    }
506}
507
508impl<G> Walker<G> for DfsPostOrder<G::NodeId, G::Map>
509where
510    G: IntoNeighbors + Visitable,
511{
512    type Item = G::NodeId;
513    fn walk_next(&mut self, context: G) -> Option<Self::Item> {
514        self.next(context)
515    }
516}
517
518impl<G> Walker<G> for Bfs<G::NodeId, G::Map>
519where
520    G: IntoNeighbors + Visitable,
521{
522    type Item = G::NodeId;
523    fn walk_next(&mut self, context: G) -> Option<Self::Item> {
524        self.next(context)
525    }
526}
527
528impl<G> Walker<G> for Topo<G::NodeId, G::Map>
529where
530    G: IntoNeighborsDirected + Visitable,
531{
532    type Item = G::NodeId;
533    fn walk_next(&mut self, context: G) -> Option<Self::Item> {
534        self.next(context)
535    }
536}