fera_graph/traverse/
visitor.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use std::marker::PhantomData;
6use std::ops::AddAssign;
7
8use num_traits::{one, zero, One, Zero};
9
10use super::control::*;
11use prelude::*;
12use props::*;
13
14// TODO: check if event names make sense for both dfs and bfs
15pub trait Visitor<G: WithEdge> {
16    fn start(&mut self, _g: &G) -> Control {
17        Control::Continue
18    }
19
20    fn finish(&mut self, _g: &G) -> Control {
21        Control::Continue
22    }
23
24    fn discover_root_vertex(&mut self, _g: &G, _v: Vertex<G>) -> Control {
25        Control::Continue
26    }
27
28    fn finish_root_vertex(&mut self, _g: &G, _v: Vertex<G>) -> Control {
29        Control::Continue
30    }
31
32    fn discover_vertex(&mut self, _g: &G, _v: Vertex<G>) -> Control {
33        Control::Continue
34    }
35
36    fn finish_vertex(&mut self, _g: &G, _v: Vertex<G>) -> Control {
37        Control::Continue
38    }
39
40    fn discover_edge(&mut self, _g: &G, _e: Edge<G>) -> Control {
41        Control::Continue
42    }
43
44    fn finish_edge(&mut self, _g: &G, _e: Edge<G>) -> Control {
45        Control::Continue
46    }
47
48    fn discover_tree_edge(&mut self, _g: &G, _e: Edge<G>) -> Control {
49        Control::Continue
50    }
51
52    fn finish_tree_edge(&mut self, _g: &G, _e: Edge<G>) -> Control {
53        Control::Continue
54    }
55
56    fn discover_back_edge(&mut self, _g: &G, _e: Edge<G>) -> Control {
57        Control::Continue
58    }
59
60    fn discover_cross_or_forward_edge(&mut self, _g: &G, _e: Edge<G>) -> Control {
61        Control::Continue
62    }
63}
64
65impl<'a, G, V> Visitor<G> for &'a mut V
66where
67    G: WithEdge,
68    V: Visitor<G>,
69{
70    fn start(&mut self, g: &G) -> Control {
71        V::start(self, g)
72    }
73
74    fn finish(&mut self, g: &G) -> Control {
75        V::start(self, g)
76    }
77
78    fn discover_root_vertex(&mut self, g: &G, v: Vertex<G>) -> Control {
79        V::discover_root_vertex(self, g, v)
80    }
81
82    fn finish_root_vertex(&mut self, g: &G, v: Vertex<G>) -> Control {
83        V::finish_root_vertex(self, g, v)
84    }
85
86    fn discover_vertex(&mut self, g: &G, v: Vertex<G>) -> Control {
87        V::discover_vertex(self, g, v)
88    }
89
90    fn finish_vertex(&mut self, g: &G, v: Vertex<G>) -> Control {
91        V::finish_vertex(self, g, v)
92    }
93
94    fn discover_edge(&mut self, g: &G, e: Edge<G>) -> Control {
95        V::discover_edge(self, g, e)
96    }
97
98    fn finish_edge(&mut self, g: &G, e: Edge<G>) -> Control {
99        V::finish_edge(self, g, e)
100    }
101
102    fn discover_tree_edge(&mut self, g: &G, e: Edge<G>) -> Control {
103        V::discover_tree_edge(self, g, e)
104    }
105
106    fn finish_tree_edge(&mut self, g: &G, e: Edge<G>) -> Control {
107        V::finish_tree_edge(self, g, e)
108    }
109
110    fn discover_back_edge(&mut self, g: &G, e: Edge<G>) -> Control {
111        V::discover_back_edge(self, g, e)
112    }
113
114    fn discover_cross_or_forward_edge(&mut self, g: &G, e: Edge<G>) -> Control {
115        V::discover_cross_or_forward_edge(self, g, e)
116    }
117}
118
119#[derive(Clone, Copy, Debug, PartialEq, Eq)]
120pub struct EmptyVisitor;
121
122impl<G: WithEdge> Visitor<G> for EmptyVisitor {}
123
124macro_rules! def_visitor_tuple_m {
125    ($m:ident ; $($name:ident),*) => (
126        #[allow(non_snake_case)]
127        #[cfg_attr(feature = "cargo-clippy", allow(let_and_return))]
128        fn $m(&mut self, g: &G) -> Control {
129            let ($(ref mut $name),*) = *self;
130            let r = Control::Continue;
131            $(
132                let r = if r == Control::Continue {
133                    $name.$m(g)
134                } else {
135                    return Control::Break;
136                };
137            )*
138            r
139        }
140    );
141    ($t:ident, $m:ident, $($name:ident),*) => (
142        #[allow(non_snake_case)]
143        #[cfg_attr(feature = "cargo-clippy", allow(let_and_return))]
144        fn $m(&mut self, g: &G, item: $t<G>) -> Control {
145            let ($(ref mut $name),*) = *self;
146            let r = Control::Continue;
147            $(
148                let r = if r == Control::Continue {
149                    $name.$m(g, item)
150                } else {
151                    return Control::Break;
152                };
153            )*
154            r
155        }
156    )
157}
158
159macro_rules! def_visitor_tuple {
160    ($($name:ident),*) => (
161        impl<G, $($name),*> Visitor<G> for ($($name),*)
162            where G: WithEdge,
163                  $($name: Visitor<G>),*
164        {
165            def_visitor_tuple_m!{start ; $($name),*}
166            def_visitor_tuple_m!{finish ; $($name),*}
167
168            def_visitor_tuple_m!{Vertex, discover_root_vertex, $($name),*}
169            def_visitor_tuple_m!{Vertex, finish_root_vertex, $($name),*}
170
171            def_visitor_tuple_m!{Vertex, discover_vertex, $($name),*}
172            def_visitor_tuple_m!{Vertex, finish_vertex, $($name),*}
173
174            def_visitor_tuple_m!{Edge, discover_edge, $($name),*}
175            def_visitor_tuple_m!{Edge, finish_edge, $($name),*}
176
177            def_visitor_tuple_m!{Edge, discover_tree_edge, $($name),*}
178            def_visitor_tuple_m!{Edge, finish_tree_edge, $($name),*}
179
180            def_visitor_tuple_m!{Edge, discover_back_edge, $($name),*}
181            def_visitor_tuple_m!{Edge, discover_cross_or_forward_edge, $($name),*}
182        }
183    )
184}
185
186def_visitor_tuple!(A, B);
187def_visitor_tuple!(A, B, C);
188def_visitor_tuple!(A, B, C, D);
189
190#[derive(Clone, Copy, PartialEq, Eq, Debug)]
191pub enum TraverseEvent<G: WithEdge> {
192    Start,
193    Finish,
194    DiscoverRootVertex(Vertex<G>),
195    FinishRootVertex(Vertex<G>),
196    DiscoverVertex(Vertex<G>),
197    FinishVertex(Vertex<G>),
198    DiscoverEdge(Edge<G>),
199    FinishEdge(Edge<G>),
200    DiscoverTreeEdge(Edge<G>),
201    FinishTreeEdge(Edge<G>),
202    DiscoverBackEdge(Edge<G>),
203    DiscoverCrossOrForwardEdge(Edge<G>),
204}
205
206pub struct OnTraverseEvent<F>(pub F);
207
208impl<G, F, R> Visitor<G> for OnTraverseEvent<F>
209where
210    G: WithEdge,
211    F: FnMut(TraverseEvent<G>) -> R,
212    R: Into<Control>,
213{
214    fn start(&mut self, _g: &G) -> Control {
215        (self.0)(TraverseEvent::Start).into()
216    }
217
218    fn finish(&mut self, _g: &G) -> Control {
219        (self.0)(TraverseEvent::Finish).into()
220    }
221
222    fn discover_root_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
223        (self.0)(TraverseEvent::DiscoverRootVertex(v)).into()
224    }
225
226    fn finish_root_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
227        (self.0)(TraverseEvent::FinishRootVertex(v)).into()
228    }
229
230    fn discover_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
231        (self.0)(TraverseEvent::DiscoverVertex(v)).into()
232    }
233
234    fn finish_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
235        (self.0)(TraverseEvent::FinishVertex(v)).into()
236    }
237
238    fn discover_edge(&mut self, _g: &G, e: Edge<G>) -> Control {
239        (self.0)(TraverseEvent::DiscoverEdge(e)).into()
240    }
241
242    fn finish_edge(&mut self, _g: &G, e: Edge<G>) -> Control {
243        (self.0)(TraverseEvent::FinishEdge(e)).into()
244    }
245
246    fn discover_tree_edge(&mut self, _g: &G, e: Edge<G>) -> Control {
247        (self.0)(TraverseEvent::DiscoverTreeEdge(e)).into()
248    }
249
250    fn finish_tree_edge(&mut self, _g: &G, e: Edge<G>) -> Control {
251        (self.0)(TraverseEvent::FinishTreeEdge(e)).into()
252    }
253
254    fn discover_back_edge(&mut self, _g: &G, e: Edge<G>) -> Control {
255        (self.0)(TraverseEvent::DiscoverBackEdge(e)).into()
256    }
257
258    fn discover_cross_or_forward_edge(&mut self, _g: &G, e: Edge<G>) -> Control {
259        (self.0)(TraverseEvent::DiscoverCrossOrForwardEdge(e)).into()
260    }
261}
262
263// Vertex
264
265pub trait VisitVertex<G: WithEdge> {
266    fn visit_vertex(&mut self, g: &G, v: Vertex<G>) -> Control;
267}
268
269impl<G, F, R> VisitVertex<G> for F
270where
271    G: WithEdge,
272    F: FnMut(Vertex<G>) -> R,
273    R: Into<Control>,
274{
275    fn visit_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
276        self(v).into()
277    }
278}
279
280macro_rules! def_on_vertex_visitor {
281    ($name:ident, $event:ident) => {
282        pub struct $name<V>(pub V);
283
284        impl<G, V> Visitor<G> for $name<V>
285        where
286            G: WithEdge,
287            V: VisitVertex<G>,
288        {
289            fn $event(&mut self, g: &G, v: Vertex<G>) -> Control {
290                self.0.visit_vertex(g, v)
291            }
292        }
293    };
294}
295
296def_on_vertex_visitor!(OnDiscoverRootVertex, discover_root_vertex);
297def_on_vertex_visitor!(OnFinishRootVertex, finish_root_vertex);
298
299def_on_vertex_visitor!(OnDiscoverVertex, discover_vertex);
300def_on_vertex_visitor!(OnFinishVertex, finish_vertex);
301
302// Edge
303
304pub trait VisitEdge<G: WithEdge> {
305    fn visit_edge(&mut self, g: &G, e: Edge<G>) -> Control;
306}
307
308impl<G, F, R> VisitEdge<G> for F
309where
310    G: WithEdge,
311    F: FnMut(Edge<G>) -> R,
312    R: Into<Control>,
313{
314    fn visit_edge(&mut self, _g: &G, e: Edge<G>) -> Control {
315        self(e).into()
316    }
317}
318
319macro_rules! def_on_edge_visitor {
320    ($name:ident, $event:ident) => {
321        pub struct $name<V>(pub V);
322
323        impl<G, V> Visitor<G> for $name<V>
324        where
325            G: WithEdge,
326            V: VisitEdge<G>,
327        {
328            fn $event(&mut self, g: &G, e: Edge<G>) -> Control {
329                self.0.visit_edge(g, e)
330            }
331        }
332    };
333}
334
335def_on_edge_visitor!(OnDiscoverEdge, discover_edge);
336def_on_edge_visitor!(OnFinishEdge, finish_edge);
337
338def_on_edge_visitor!(OnDiscoverTreeEdge, discover_tree_edge);
339def_on_edge_visitor!(OnFinishTreeEdge, finish_tree_edge);
340
341def_on_edge_visitor!(OnDiscoverBackEdge, discover_back_edge);
342def_on_edge_visitor!(OnDiscoverCrossOrBackEdge, discover_cross_or_forward_edge);
343
344// Some visitors
345
346use std::cell::Cell;
347
348pub trait Counter {
349    fn add1(&mut self);
350}
351
352impl<T> Counter for T
353where
354    T: One + AddAssign,
355{
356    fn add1(&mut self) {
357        *self += one();
358    }
359}
360
361pub struct Add1<'a, T: 'a>(pub &'a mut T);
362
363impl<'a, G, T> VisitVertex<G> for Add1<'a, T>
364where
365    G: WithEdge,
366    T: Counter,
367{
368    fn visit_vertex(&mut self, _g: &G, _v: Vertex<G>) -> Control {
369        self.0.add1();
370        Control::Continue
371    }
372}
373
374impl<'a, G, T> VisitEdge<G> for Add1<'a, T>
375where
376    G: WithEdge,
377    T: Counter,
378{
379    fn visit_edge(&mut self, _g: &G, _e: Edge<G>) -> Control {
380        self.0.add1();
381        Control::Continue
382    }
383}
384
385#[derive(Default)]
386pub struct Time<T> {
387    cur: Cell<T>,
388}
389
390impl<T> Time<T>
391where
392    T: Copy + Counter,
393{
394    #[inline]
395    fn get_and_inc(&self) -> T {
396        let mut t = self.cur.get();
397        t.add1();
398        self.cur.replace(t)
399    }
400}
401
402pub struct StampTime<'a, T: 'a, P: 'a>(pub &'a Time<T>, pub &'a mut P);
403
404impl<'a, G, T, P> VisitVertex<G> for StampTime<'a, T, P>
405where
406    G: WithEdge,
407    T: Copy + Counter,
408    P: VertexPropMut<G, T>,
409{
410    fn visit_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
411        self.1[v] = self.0.get_and_inc();
412        Control::Continue
413    }
414}
415
416pub struct RecordDistance<'a, P: 'a, T> {
417    dist: &'a mut P,
418    _marker: PhantomData<T>,
419}
420
421#[allow(non_snake_case)]
422pub fn RecordDistance<P, T>(dist: &mut P) -> RecordDistance<P, T> {
423    RecordDistance {
424        dist: dist,
425        _marker: PhantomData,
426    }
427}
428
429impl<'a, G, P, T> Visitor<G> for RecordDistance<'a, P, T>
430where
431    G: WithEdge,
432    P: VertexPropMut<G, T>,
433    T: Counter + Copy + Zero,
434{
435    fn discover_root_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
436        self.dist[v] = zero();
437        Control::Continue
438    }
439
440    fn discover_tree_edge(&mut self, g: &G, e: Edge<G>) -> Control {
441        let (u, v) = g.ends(e);
442        self.dist[v] = self.dist[u];
443        self.dist[v].add1();
444        Control::Continue
445    }
446}
447
448pub struct RecordParent<'a, P: 'a>(pub &'a mut P);
449
450impl<'a, G, P> Visitor<G> for RecordParent<'a, P>
451where
452    G: WithEdge,
453    P: VertexPropMut<G, OptionVertex<G>>,
454{
455    fn discover_root_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
456        self.0[v] = G::vertex_none();
457        Control::Continue
458    }
459
460    fn discover_tree_edge(&mut self, g: &G, e: Edge<G>) -> Control {
461        let (u, v) = g.ends(e);
462        self.0[v] = u.into();
463        Control::Continue
464    }
465}
466
467pub struct RecordParentEdge<'a, P: 'a>(pub &'a mut P);
468
469impl<'a, G, P> Visitor<G> for RecordParentEdge<'a, P>
470where
471    G: WithEdge<Kind = Undirected>,
472    P: VertexPropMut<G, OptionEdge<G>>,
473{
474    fn discover_root_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
475        self.0[v] = G::edge_none();
476        Control::Continue
477    }
478
479    fn discover_tree_edge(&mut self, g: &G, e: Edge<G>) -> Control {
480        self.0[g.target(e)] = g.reverse(e).into();
481        Control::Continue
482    }
483}
484
485pub struct FarthestVertex<'a, G: WithVertex> {
486    cur_dist: usize,
487    dist: &'a mut usize,
488    v: &'a mut OptionVertex<G>,
489}
490
491#[allow(non_snake_case)]
492pub fn FarthestVertex<'a, G>(
493    v: &'a mut OptionVertex<G>,
494    dist: &'a mut usize,
495) -> FarthestVertex<'a, G>
496where
497    G: WithVertex,
498{
499    FarthestVertex {
500        cur_dist: 0,
501        dist: dist,
502        v: v,
503    }
504}
505
506impl<'a, G> Visitor<G> for FarthestVertex<'a, G>
507where
508    G: 'a + WithEdge,
509{
510    fn start(&mut self, _: &G) -> Control {
511        *self.dist = 0;
512        Control::Continue
513    }
514
515    fn finish_tree_edge(&mut self, _: &G, _: Edge<G>) -> Control {
516        self.cur_dist -= 1;
517        Control::Continue
518    }
519
520    fn discover_tree_edge(&mut self, g: &G, e: Edge<G>) -> Control {
521        self.cur_dist += 1;
522        if self.cur_dist > *self.dist {
523            *self.dist = self.cur_dist;
524            *self.v = g.target(e).into();
525        }
526        Control::Continue
527    }
528}
529
530// TODO: write tests