webgraph_algo/visits/depth_first/mod.rs
1/*
2 * SPDX-FileCopyrightText: 2024 Matteo Dell'Acqua
3 * SPDX-FileCopyrightText: 2025 Sebastiano Vigna
4 *
5 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
6 */
7
8//! Depth-first visits.
9//!
10//! Implementations must accept a callback function with argument
11//! [`EventNoPred`], or [`EventPred`] if the visit keeps track of parent nodes.
12//! The associated filter argument types are [`FilterArgsNoPred`] and
13//! [`FilterArgsPred`], respectively.
14//!
15//! Note that since [`EventPred`] contains the predecessor of the visited node,
16//! all post-initialization visit events can be interpreted as arc events. The
17//! only exception are the previsit and postvisit events of the root.
18
19mod seq;
20pub use seq::*;
21
22/// Types of callback events generated during depth-first visits
23/// not keeping track of parent nodes.
24#[derive(Debug, Clone, Hash, PartialEq, Eq)]
25pub enum EventNoPred {
26 /// This event should be used to set up state at the start of the visit.
27 ///
28 /// Note that this event will not happen if the visit is empty, that
29 /// is, all of the roots are already visited or filtered.
30 Init {
31 /// The root of the current visit tree, that is, the first node that
32 /// will be visited.
33 root: usize,
34 },
35 /// The node has been encountered for the first time: we are traversing a
36 /// new tree arc, unless all fields are equal to the root.
37 Previsit {
38 /// The current node.
39 node: usize,
40 /// The root of the current visit tree.
41 root: usize,
42 /// The depth of the visit, that is, the length of the visit path from
43 /// the [root](`EventNoPred::Previsit::root`) to
44 /// [node](`EventNoPred::Previsit::node`).
45 depth: usize,
46 },
47 /// The node has been encountered before: we are traversing a back arc, a
48 /// forward arc, or a cross arc.
49 Revisit {
50 /// The current node.
51 node: usize,
52 /// The root of the current visit tree.
53 root: usize,
54 /// The depth of the visit, that is, the length of the visit path from
55 /// the [root](`EventNoPred::Revisit::root`) to
56 /// [node](`EventNoPred::Revisit::node`).
57 depth: usize,
58 },
59 /// The visit has been completed.
60 ///
61 /// Note that this event will not happen if the visit is empty (that is, if
62 /// the root has already been visited) or if the visit is stopped by a
63 /// callback returning an error.
64 Done {
65 /// The root of the current visit tree.
66 root: usize,
67 },
68}
69
70/// Filter arguments for visits that do not keep track of predecessors.
71#[derive(Debug, Clone, Hash, PartialEq, Eq)]
72pub struct FilterArgsNoPred {
73 /// The current node.
74 pub node: usize,
75 /// The root of the current visit tree.
76 pub root: usize,
77 /// The depth of the visit, that is, the length of the visit path from the
78 /// [root](`Self::root`) to [node](`Self::node`).
79 pub depth: usize,
80}
81
82impl super::Event for EventNoPred {
83 type FilterArgs = FilterArgsNoPred;
84}
85
86/// Types of callback events generated during depth-first visits
87/// keeping track of parent nodes (and possibly of the visit path).
88#[derive(Debug, Clone, Hash, PartialEq, Eq)]
89pub enum EventPred {
90 /// This event should be used to set up state at the start of the visit.
91 ///
92 /// Note that this event will not happen if the visit is empty, that
93 /// is, all of the roots are already visited or filtered.
94 Init {
95 /// The root of the current visit tree, that is, the first node that
96 /// will be visited.
97 root: usize,
98 },
99 /// The node has been encountered for the first time: we are traversing a
100 /// new tree arc, unless all node fields are equal to the root.
101 Previsit {
102 /// The current node.
103 node: usize,
104 /// The parent of [node](`EventPred::Previsit::node`) in the visit tree.
105 pred: usize,
106 /// The root of the current visit tree.
107 root: usize,
108 /// The depth of the visit, that is, the length of the visit path from the
109 /// [root](`EventPred::Previsit::root`) to [node](`EventPred::Previsit::node`).
110 depth: usize,
111 },
112 /// The node has been encountered before: we are traversing a back arc, a
113 /// forward arc, or a cross arc.
114 Revisit {
115 /// The current node.
116 node: usize,
117 /// The parent of [node](`EventPred::Revisit::node`) in the visit tree.
118 pred: usize,
119 /// The root of the current visit tree.
120 root: usize,
121 /// The depth of the visit, that is, the length of the visit path from the
122 /// [root](`EventPred::Revisit::root`) to [curr](`EventPred::Revisit::node`).
123 depth: usize,
124 /// Whether the node is currently on the visit path, that is, if we are
125 /// traversing a back arc, and retreating from it. This might be always
126 /// false if the visit does not keep track of the visit path.
127 on_stack: bool,
128 },
129 /// The enumeration of the successors of the node has been completed: we are
130 /// retreating from a tree arc, unless all node fields are equal to
131 /// the root.
132 Postvisit {
133 /// The current node.
134 node: usize,
135 /// The parent of [curr](`EventPred::Postvisit::node`) in the visit tree.
136 pred: usize,
137 /// The root of the current visit tree.
138 root: usize,
139 /// The depth of the visit, that is, the length of the visit path from
140 /// the [root](`EventPred::Postvisit::root`) to
141 /// [node](`EventPred::Postvisit::node`).
142 depth: usize,
143 },
144 /// The visit has been completed.
145 ///
146 /// Note that this event will not happen if the visit is empty (that is, if
147 /// the root has already been visited) or if the visit is stopped by a
148 /// callback returning an error.
149 Done {
150 /// The root of the current visit tree.
151 root: usize,
152 },
153}
154
155/// Filter arguments for visit that keep track of predecessors.
156#[derive(Debug, Clone, Hash, PartialEq, Eq)]
157pub struct FilterArgsPred {
158 /// The current node.
159 pub node: usize,
160 /// The parent of [node](`Self::node`) in the visit tree.
161 pub pred: usize,
162 /// The root of the current visit tree.
163 pub root: usize,
164 /// The depth of the visit, that is, the length of the visit path from the
165 /// [root](`Self::root`) to [node](`Self::node`).
166 pub depth: usize,
167}
168
169impl super::Event for EventPred {
170 type FilterArgs = FilterArgsPred;
171}