reddb_server/storage/engine/pathfinding/
bfs_impl.rs1use super::*;
2
3impl BFS {
4 pub fn shortest_path(graph: &GraphStore, source: &str, target: &str) -> ShortestPathResult {
6 if source == target {
7 return ShortestPathResult {
8 path: Some(Path::start(source)),
9 nodes_visited: 1,
10 };
11 }
12
13 let mut visited: HashSet<String> = HashSet::new();
14 let mut queue: VecDeque<Path> = VecDeque::new();
15 let mut nodes_visited = 0;
16
17 queue.push_back(Path::start(source));
18 visited.insert(source.to_string());
19
20 while let Some(current_path) = queue.pop_front() {
21 let current = current_path.nodes.last().unwrap();
22 nodes_visited += 1;
23
24 for (edge_type, neighbor, weight) in graph.outgoing_edges(current) {
25 if neighbor == target {
26 return ShortestPathResult {
27 path: Some(current_path.extend(&neighbor, edge_type, weight as f64)),
28 nodes_visited,
29 };
30 }
31
32 if !visited.contains(&neighbor) {
33 visited.insert(neighbor.clone());
34 queue.push_back(current_path.extend(&neighbor, edge_type, weight as f64));
35 }
36 }
37 }
38
39 ShortestPathResult {
40 path: None,
41 nodes_visited,
42 }
43 }
44
45 pub fn reachable(graph: &GraphStore, source: &str, max_depth: usize) -> Vec<(String, usize)> {
47 let mut visited: HashMap<String, usize> = HashMap::new();
48 let mut queue: VecDeque<(String, usize)> = VecDeque::new();
49
50 queue.push_back((source.to_string(), 0));
51 visited.insert(source.to_string(), 0);
52
53 while let Some((current, depth)) = queue.pop_front() {
54 if depth >= max_depth {
55 continue;
56 }
57
58 for (_, neighbor, _) in graph.outgoing_edges(¤t) {
59 if !visited.contains_key(&neighbor) {
60 visited.insert(neighbor.clone(), depth + 1);
61 queue.push_back((neighbor, depth + 1));
62 }
63 }
64 }
65
66 let mut result: Vec<_> = visited.into_iter().collect();
67 result.sort_by_key(|(_, depth)| *depth);
68 result
69 }
70
71 pub fn traverse(graph: &GraphStore, source: &str) -> Vec<String> {
73 let mut visited: HashSet<String> = HashSet::new();
74 let mut queue: VecDeque<String> = VecDeque::new();
75 let mut result: Vec<String> = Vec::new();
76
77 queue.push_back(source.to_string());
78 visited.insert(source.to_string());
79
80 while let Some(current) = queue.pop_front() {
81 result.push(current.clone());
82
83 for (_, neighbor, _) in graph.outgoing_edges(¤t) {
84 if !visited.contains(&neighbor) {
85 visited.insert(neighbor.clone());
86 queue.push_back(neighbor);
87 }
88 }
89 }
90
91 result
92 }
93}