1use alloc::{collections::VecDeque, vec::Vec};
2
3use super::{
4 GraphRef, IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers, Reversed, VisitMap,
5 Visitable,
6};
7use crate::Incoming;
8
9#[derive(Clone, Debug)]
40pub struct Dfs<N, VM> {
41 pub stack: Vec<N>,
43 pub discovered: VM,
45}
46
47impl<N, VM> Default for Dfs<N, VM>
48where
49 VM: Default,
50{
51 fn default() -> Self {
52 Dfs {
53 stack: Vec::new(),
54 discovered: VM::default(),
55 }
56 }
57}
58
59impl<N, VM> Dfs<N, VM>
60where
61 N: Copy + PartialEq,
62 VM: VisitMap<N>,
63{
64 pub fn new<G>(graph: G, start: N) -> Self
67 where
68 G: GraphRef + Visitable<NodeId = N, Map = VM>,
69 {
70 let mut dfs = Dfs::empty(graph);
71 dfs.move_to(start);
72 dfs
73 }
74
75 pub fn from_parts(stack: Vec<N>, discovered: VM) -> Self {
77 Dfs { stack, discovered }
78 }
79
80 pub fn reset<G>(&mut self, graph: G)
82 where
83 G: GraphRef + Visitable<NodeId = N, Map = VM>,
84 {
85 graph.reset_map(&mut self.discovered);
86 self.stack.clear();
87 }
88
89 pub fn empty<G>(graph: G) -> Self
91 where
92 G: GraphRef + Visitable<NodeId = N, Map = VM>,
93 {
94 Dfs {
95 stack: Vec::new(),
96 discovered: graph.visit_map(),
97 }
98 }
99
100 pub fn move_to(&mut self, start: N) {
103 self.stack.clear();
104 self.stack.push(start);
105 }
106
107 pub fn next<G>(&mut self, graph: G) -> Option<N>
109 where
110 G: IntoNeighbors<NodeId = N>,
111 {
112 while let Some(node) = self.stack.pop() {
113 if self.discovered.visit(node) {
114 for succ in graph.neighbors(node) {
115 if !self.discovered.is_visited(&succ) {
116 self.stack.push(succ);
117 }
118 }
119 return Some(node);
120 }
121 }
122 None
123 }
124}
125
126#[derive(Clone, Debug)]
134pub struct DfsPostOrder<N, VM> {
135 pub stack: Vec<N>,
137 pub discovered: VM,
139 pub finished: VM,
141}
142
143impl<N, VM> Default for DfsPostOrder<N, VM>
144where
145 VM: Default,
146{
147 fn default() -> Self {
148 DfsPostOrder {
149 stack: Vec::new(),
150 discovered: VM::default(),
151 finished: VM::default(),
152 }
153 }
154}
155
156impl<N, VM> DfsPostOrder<N, VM>
157where
158 N: Copy + PartialEq,
159 VM: VisitMap<N>,
160{
161 pub fn new<G>(graph: G, start: N) -> Self
164 where
165 G: GraphRef + Visitable<NodeId = N, Map = VM>,
166 {
167 let mut dfs = Self::empty(graph);
168 dfs.move_to(start);
169 dfs
170 }
171
172 pub fn empty<G>(graph: G) -> Self
174 where
175 G: GraphRef + Visitable<NodeId = N, Map = VM>,
176 {
177 DfsPostOrder {
178 stack: Vec::new(),
179 discovered: graph.visit_map(),
180 finished: graph.visit_map(),
181 }
182 }
183
184 pub fn reset<G>(&mut self, graph: G)
186 where
187 G: GraphRef + Visitable<NodeId = N, Map = VM>,
188 {
189 graph.reset_map(&mut self.discovered);
190 graph.reset_map(&mut self.finished);
191 self.stack.clear();
192 }
193
194 pub fn move_to(&mut self, start: N) {
197 self.stack.clear();
198 self.stack.push(start);
199 }
200
201 pub fn next<G>(&mut self, graph: G) -> Option<N>
203 where
204 G: IntoNeighbors<NodeId = N>,
205 {
206 while let Some(&nx) = self.stack.last() {
207 if self.discovered.visit(nx) {
208 for succ in graph.neighbors(nx) {
210 if !self.discovered.is_visited(&succ) {
211 self.stack.push(succ);
212 }
213 }
214 } else {
215 self.stack.pop();
216 if self.finished.visit(nx) {
217 return Some(nx);
219 }
220 }
221 }
222 None
223 }
224}
225
226#[derive(Clone)]
256pub struct Bfs<N, VM> {
257 pub stack: VecDeque<N>,
259 pub discovered: VM,
261}
262
263impl<N, VM> Default for Bfs<N, VM>
264where
265 VM: Default,
266{
267 fn default() -> Self {
268 Bfs {
269 stack: VecDeque::new(),
270 discovered: VM::default(),
271 }
272 }
273}
274
275impl<N, VM> Bfs<N, VM>
276where
277 N: Copy + PartialEq,
278 VM: VisitMap<N>,
279{
280 pub fn new<G>(graph: G, start: N) -> Self
283 where
284 G: GraphRef + Visitable<NodeId = N, Map = VM>,
285 {
286 let mut discovered = graph.visit_map();
287 discovered.visit(start);
288 let mut stack = VecDeque::new();
289 stack.push_front(start);
290 Bfs { stack, discovered }
291 }
292
293 pub fn next<G>(&mut self, graph: G) -> Option<N>
295 where
296 G: IntoNeighbors<NodeId = N>,
297 {
298 if let Some(node) = self.stack.pop_front() {
299 for succ in graph.neighbors(node) {
300 if self.discovered.visit(succ) {
301 self.stack.push_back(succ);
302 }
303 }
304
305 return Some(node);
306 }
307 None
308 }
309}
310
311#[derive(Clone)]
318pub struct Topo<N, VM> {
319 tovisit: Vec<N>,
320 ordered: VM,
321}
322
323impl<N, VM> Default for Topo<N, VM>
324where
325 VM: Default,
326{
327 fn default() -> Self {
328 Topo {
329 tovisit: Vec::new(),
330 ordered: VM::default(),
331 }
332 }
333}
334
335impl<N, VM> Topo<N, VM>
336where
337 N: Copy + PartialEq,
338 VM: VisitMap<N>,
339{
340 pub fn new<G>(graph: G) -> Self
343 where
344 G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
345 {
346 let mut topo = Self::empty(graph);
347 topo.extend_with_initials(graph);
348 topo
349 }
350
351 pub fn with_initials<G, I>(graph: G, initials: I) -> Self
355 where
356 G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
357 I: IntoIterator<Item = N>,
358 {
359 Topo {
360 tovisit: initials
361 .into_iter()
362 .filter(|&n| graph.neighbors_directed(n, Incoming).next().is_none())
363 .collect(),
364 ordered: graph.visit_map(),
365 }
366 }
367
368 fn extend_with_initials<G>(&mut self, g: G)
369 where
370 G: IntoNodeIdentifiers + IntoNeighborsDirected<NodeId = N>,
371 {
372 self.tovisit.extend(
374 g.node_identifiers()
375 .filter(move |&a| g.neighbors_directed(a, Incoming).next().is_none()),
376 );
377 }
378
379 fn empty<G>(graph: G) -> Self
383 where
384 G: GraphRef + Visitable<NodeId = N, Map = VM>,
385 {
386 Topo {
387 ordered: graph.visit_map(),
388 tovisit: Vec::new(),
389 }
390 }
391
392 pub fn reset<G>(&mut self, graph: G)
394 where
395 G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
396 {
397 graph.reset_map(&mut self.ordered);
398 self.tovisit.clear();
399 self.extend_with_initials(graph);
400 }
401
402 pub fn next<G>(&mut self, g: G) -> Option<N>
408 where
409 G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
410 {
411 while let Some(nix) = self.tovisit.pop() {
413 if self.ordered.is_visited(&nix) {
414 continue;
415 }
416 self.ordered.visit(nix);
417 for neigh in g.neighbors(nix) {
418 if Reversed(g)
421 .neighbors(neigh)
422 .all(|b| self.ordered.is_visited(&b))
423 {
424 self.tovisit.push(neigh);
425 }
426 }
427 return Some(nix);
428 }
429 None
430 }
431}
432
433pub trait Walker<Context> {
439 type Item;
440 fn walk_next(&mut self, context: Context) -> Option<Self::Item>;
442
443 fn iter(self, context: Context) -> WalkerIter<Self, Context>
445 where
446 Self: Sized,
447 Context: Clone,
448 {
449 WalkerIter {
450 walker: self,
451 context,
452 }
453 }
454}
455
456#[derive(Clone, Debug)]
458pub struct WalkerIter<W, C> {
459 walker: W,
460 context: C,
461}
462
463impl<W, C> WalkerIter<W, C>
464where
465 W: Walker<C>,
466 C: Clone,
467{
468 pub fn context(&self) -> C {
469 self.context.clone()
470 }
471
472 pub fn inner_ref(&self) -> &W {
473 &self.walker
474 }
475
476 pub fn inner_mut(&mut self) -> &mut W {
477 &mut self.walker
478 }
479}
480
481impl<W, C> Iterator for WalkerIter<W, C>
482where
483 W: Walker<C>,
484 C: Clone,
485{
486 type Item = W::Item;
487 fn next(&mut self) -> Option<Self::Item> {
488 self.walker.walk_next(self.context.clone())
489 }
490}
491
492impl<C, W: ?Sized> Walker<C> for &mut W
493where
494 W: Walker<C>,
495{
496 type Item = W::Item;
497 fn walk_next(&mut self, context: C) -> Option<Self::Item> {
498 (**self).walk_next(context)
499 }
500}
501
502impl<G> Walker<G> for Dfs<G::NodeId, G::Map>
503where
504 G: IntoNeighbors + Visitable,
505{
506 type Item = G::NodeId;
507 fn walk_next(&mut self, context: G) -> Option<Self::Item> {
508 self.next(context)
509 }
510}
511
512impl<G> Walker<G> for DfsPostOrder<G::NodeId, G::Map>
513where
514 G: IntoNeighbors + Visitable,
515{
516 type Item = G::NodeId;
517 fn walk_next(&mut self, context: G) -> Option<Self::Item> {
518 self.next(context)
519 }
520}
521
522impl<G> Walker<G> for Bfs<G::NodeId, G::Map>
523where
524 G: IntoNeighbors + Visitable,
525{
526 type Item = G::NodeId;
527 fn walk_next(&mut self, context: G) -> Option<Self::Item> {
528 self.next(context)
529 }
530}
531
532impl<G> Walker<G> for Topo<G::NodeId, G::Map>
533where
534 G: IntoNeighborsDirected + Visitable,
535{
536 type Item = G::NodeId;
537 fn walk_next(&mut self, context: G) -> Option<Self::Item> {
538 self.next(context)
539 }
540}