fera_graph/traverse/
recursive_dfs.rs1use params::*;
6use prelude::*;
7use props::{Color, IgnoreWriteProp};
8use traverse::*;
9
10use std::iter;
11
12pub trait RecursiveDfs: WithEdge {
13 fn recursive_dfs<V>(
14 &self,
15 vis: V,
16 ) -> RecursiveDfsAlg<&Self, V, AllVertices<Self>, NewVertexProp<Self, Color>>
17 where
18 V: Visitor<Self>,
19 {
20 RecursiveDfsAlg(
21 self,
22 vis,
23 AllVertices(self),
24 NewVertexProp(self, Color::White),
25 )
26 }
27}
28
29impl<G: WithEdge> RecursiveDfs for G {}
30
31generic_struct! {
32 #[must_use = "call .run() to execute the algorithm"]
33 pub struct RecursiveDfsAlg(graph, visitor, roots, color)
34}
35
36impl<'a, G, V, R, C> RecursiveDfsAlg<&'a G, V, R, C> {
37 pub fn run(self) -> Control
38 where
39 G: Incidence,
40 V: Visitor<G>,
41 R: IntoIterator<Item = Vertex<G>>,
42 C: ParamDerefMut,
43 C::Target: VertexPropMut<G, Color>,
44 {
45 let RecursiveDfsAlg(g, mut vis, roots, color) = self;
46 return_unless!(vis.start(g));
47 let mut color = color.build();
48 for v in roots {
49 if color[v] == Color::White {
50 color[v] = Color::Gray;
51 return_unless!(vis.discover_root_vertex(g, v));
52 return_unless!(recursive_dfs_visit(
53 g,
54 G::edge_none(),
55 v,
56 &mut *color,
57 &mut vis
58 ));
59 return_unless!(vis.finish_root_vertex(g, v));
60 }
61 }
62 vis.finish(g)
63 }
64
65 pub fn root(self, root: Vertex<G>) -> RecursiveDfsAlg<&'a G, V, iter::Once<Vertex<G>>, C>
66 where
67 G: WithVertex,
68 {
69 self.roots(iter::once(root))
70 }
71
72 pub fn ignore_color_changes(self) -> RecursiveDfsAlg<&'a G, V, R, Owned<IgnoreWriteProp<Color>>>
73 where
74 G: WithVertex,
75 {
76 let color = Owned(self.0.vertex_prop(Color::White));
77 self.color(color)
78 }
79}
80
81pub fn recursive_dfs_visit<G, C, V>(
82 g: &G,
83 from: OptionEdge<G>,
84 u: Vertex<G>,
85 color: &mut C,
86 vis: &mut V,
87) -> Control
88where
89 G: Incidence,
90 C: VertexPropMut<G, Color>,
91 V: Visitor<G>,
92{
93 color[u] = Color::Gray;
94 return_unless!(vis.discover_vertex(g, u));
95 for e in g.out_edges(u) {
96 let v = g.target(e);
97 if g.orientation(e).is_undirected() && color[v] == Color::Black || G::edge_some(e) == from {
98 continue;
99 }
100 return_unless!(vis.discover_edge(g, e));
101 match color[v] {
102 Color::White => {
103 return_unless!(vis.discover_tree_edge(g, e));
104 return_unless!(recursive_dfs_visit(g, e.into(), v, color, vis));
105 return_unless!(vis.finish_tree_edge(g, e));
106 }
107 Color::Gray => {
108 return_unless!(vis.discover_back_edge(g, e));
109 }
110 Color::Black => {
111 return_unless!(vis.discover_cross_or_forward_edge(g, e));
112 }
113 }
114 return_unless!(vis.finish_edge(g, e));
115 }
116 color[u] = Color::Black;
117 return_unless!(vis.finish_vertex(g, u));
118 Control::Continue
119}