1use crate::graph::{EdgeID, Graph, INVALID_NODE_ID, NodeID};
2use bitvec::vec::BitVec;
3use log::{debug, info};
4use std::{collections::VecDeque, time::Instant};
5
6pub struct BFS {
7 sources: Vec<NodeID>,
8 target_set: BitVec,
9 parents: Vec<NodeID>,
10 target: NodeID,
11 queue: VecDeque<usize>,
12 empty_target_set: bool,
13}
14
15impl BFS {
16 pub fn new(source_list: &[NodeID], target_list: &[NodeID], number_of_nodes: usize) -> Self {
18 let mut temp = Self {
19 sources: source_list.to_vec(),
20 target_set: BitVec::with_capacity(number_of_nodes),
21 parents: Vec::new(),
22 target: INVALID_NODE_ID,
23 queue: VecDeque::new(),
24 empty_target_set: target_list.is_empty(),
25 };
26
27 temp.target_set.resize(number_of_nodes, false);
29 for i in target_list {
30 temp.target_set.set(*i, true);
31 }
32
33 temp.populate_sources(number_of_nodes);
34 temp
35 }
36
37 fn populate_sources(&mut self, number_of_nodes: usize) {
38 self.parents.resize(number_of_nodes, INVALID_NODE_ID);
39 for s in &self.sources {
40 self.parents[*s] = *s;
41 }
42 }
43
44 pub fn run<T, G: Graph<T>>(&mut self, graph: &G) -> bool {
45 self.run_with_filter(graph, |_graph, _edge| false)
46 }
47
48 pub fn run_with_filter<T, F, G: Graph<T>>(&mut self, graph: &G, filter: F) -> bool
51 where
52 F: Fn(&G, EdgeID) -> bool,
53 {
54 let start = Instant::now();
55 self.queue.clear();
57 self.queue.extend(self.sources.iter().copied());
58
59 self.parents.fill(INVALID_NODE_ID);
61 for s in &self.sources {
62 self.parents[*s] = *s;
63 }
64
65 while let Some(node) = self.queue.pop_front() {
66 let node_is_source = self.parents[node] == node;
67 for edge in graph.edge_range(node) {
69 if filter(graph, edge) {
70 continue;
71 }
72 let target = graph.target(edge);
73 if self.parents[target] != INVALID_NODE_ID
74 || (node_is_source && self.parents[target] == target)
75 {
76 continue;
79 }
80 self.parents[target] = node;
81 unsafe {
82 if *self.target_set.get_unchecked(target) {
84 self.target = target;
85 debug!("setting target {}", self.target);
86 let duration = start.elapsed();
88 info!("D/BFS took: {duration:?} (done)");
89 return true;
90 }
91 }
92 self.queue.push_back(target);
93 }
94 }
95
96 let duration = start.elapsed();
97 info!("BFS took: {duration:?} (done)");
98
99 self.empty_target_set
101 }
102
103 pub fn fetch_node_path(&self) -> Vec<NodeID> {
106 self.fetch_node_path_from_node(self.target)
107 }
108
109 pub fn fetch_node_path_from_node(&self, t: NodeID) -> Vec<NodeID> {
113 let mut id = t;
114 let mut path = Vec::new();
115 while id != self.parents[id] {
116 path.push(id);
117 id = self.parents[id];
118 }
119 path.push(id);
120 path.reverse();
121 path
122 }
123
124 pub fn fetch_edge_path<T>(&self, graph: &impl Graph<T>) -> Vec<EdgeID> {
126 let mut id = self.target;
128 let mut path = Vec::new();
129 while id != self.parents[id] {
130 let edge_id = graph.find_edge(self.parents[id], id).unwrap();
131 path.push(edge_id);
132 id = self.parents[id];
133 }
134
135 path.reverse();
136 path
137 }
138
139 pub fn path_iter(&self) -> PathIter {
141 PathIter::new(self)
142 }
143}
144
145pub struct PathIter<'a> {
146 bfs: &'a BFS,
147 id: usize,
148}
149
150impl PathIter<'_> {
151 pub fn new(bfs: &BFS) -> PathIter {
152 debug!("init: {}", bfs.target);
153 PathIter {
154 bfs,
155 id: bfs.target,
156 }
157 }
158}
159
160impl Iterator for PathIter<'_> {
161 type Item = NodeID;
162 fn next(&mut self) -> Option<NodeID> {
163 if self.id == INVALID_NODE_ID {
164 return None;
166 }
167
168 let result = self.id;
170 self.id = self.bfs.parents[self.id];
171 if result == self.bfs.parents[result] {
172 self.id = INVALID_NODE_ID;
173 }
174 Some(result)
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use crate::edge::InputEdge;
181 use crate::graph::Graph;
182 use crate::{bfs::BFS, static_graph::StaticGraph};
183
184 #[test]
185 fn s_t_query_fetch_node_string() {
186 type Graph = StaticGraph<i32>;
187 let edges = vec![
188 InputEdge::new(0, 1, 3),
189 InputEdge::new(1, 2, 3),
190 InputEdge::new(4, 2, 1),
191 InputEdge::new(2, 3, 6),
192 InputEdge::new(0, 4, 2),
193 InputEdge::new(4, 5, 2),
194 InputEdge::new(5, 3, 7),
195 InputEdge::new(1, 5, 2),
196 ];
197 let graph = Graph::new(edges);
198 let mut bfs = BFS::new(&[0], &[5], graph.number_of_nodes());
199 assert!(bfs.run(&graph));
200
201 let path = bfs.fetch_node_path();
202 assert_eq!(path, vec![0, 1, 5]);
203
204 let path: Vec<usize> = bfs.path_iter().collect();
205 assert_eq!(path, vec![5, 1, 0]);
206 }
207
208 #[test]
209 fn s_t_query_edge_list() {
210 type Graph = StaticGraph<i32>;
211 let edges = vec![
212 InputEdge::new(0, 1, 3),
213 InputEdge::new(1, 2, 3),
214 InputEdge::new(4, 2, 1),
215 InputEdge::new(2, 3, 6),
216 InputEdge::new(0, 4, 2),
217 InputEdge::new(4, 5, 2),
218 InputEdge::new(5, 3, 7),
219 InputEdge::new(1, 5, 2),
220 ];
221 let graph = Graph::new(edges);
222 let mut bfs = BFS::new(&[0], &[5], graph.number_of_nodes());
223 assert!(bfs.run(&graph));
224 let path = bfs.fetch_edge_path(&graph);
225 assert_eq!(path, vec![0, 3]);
226 }
227
228 #[test]
229 fn s_all_query() {
230 type Graph = StaticGraph<i32>;
231 let edges = vec![
232 InputEdge::new(0, 1, 3),
233 InputEdge::new(1, 2, 3),
234 InputEdge::new(4, 2, 1),
235 InputEdge::new(2, 3, 6),
236 InputEdge::new(0, 4, 2),
237 InputEdge::new(4, 5, 2),
238 InputEdge::new(5, 3, 7),
239 InputEdge::new(1, 5, 2),
240 ];
241 let graph = Graph::new(edges);
242 let mut bfs = BFS::new(&[0], &[], graph.number_of_nodes());
243 assert!(bfs.run(&graph));
244
245 let path = bfs.fetch_node_path_from_node(3);
246 assert_eq!(path, vec![0, 1, 2, 3]);
247
248 let path: Vec<usize> = bfs.path_iter().collect();
249 assert!(path.is_empty());
250 }
251
252 #[test]
253 fn multi_s_all_query() {
254 type Graph = StaticGraph<i32>;
255 let edges = vec![
256 InputEdge::new(0, 1, 3),
257 InputEdge::new(1, 2, 3),
258 InputEdge::new(4, 2, 1),
259 InputEdge::new(2, 3, 6),
260 InputEdge::new(0, 4, 2),
261 InputEdge::new(4, 5, 2),
262 InputEdge::new(5, 3, 7),
263 InputEdge::new(1, 5, 2),
264 ];
265 let graph = Graph::new(edges);
266 let mut bfs = BFS::new(&[0, 1], &[], graph.number_of_nodes());
267 assert!(bfs.run(&graph));
268
269 let path = bfs.fetch_node_path_from_node(3);
271 assert_eq!(path, vec![1, 2, 3]);
272
273 let path: Vec<usize> = bfs.path_iter().collect();
274 assert!(path.is_empty());
275 }
276}