reddb_server/storage/engine/pathfinding/
dfs_impl.rs1use super::*;
2
3impl DFS {
4 pub fn find_path(graph: &GraphStore, source: &str, target: &str) -> ShortestPathResult {
6 let mut visited: HashSet<String> = HashSet::new();
7 let mut nodes_visited = 0;
8
9 fn dfs_recursive(
10 graph: &GraphStore,
11 current: &str,
12 target: &str,
13 path: Path,
14 visited: &mut HashSet<String>,
15 nodes_visited: &mut usize,
16 ) -> Option<Path> {
17 *nodes_visited += 1;
18 visited.insert(current.to_string());
19
20 if current == target {
21 return Some(path);
22 }
23
24 for (edge_type, neighbor, weight) in graph.outgoing_edges(current) {
25 if !visited.contains(&neighbor) {
26 let new_path = path.extend(&neighbor, edge_type, weight as f64);
27 if let Some(result) =
28 dfs_recursive(graph, &neighbor, target, new_path, visited, nodes_visited)
29 {
30 return Some(result);
31 }
32 }
33 }
34
35 None
36 }
37
38 let path = dfs_recursive(
39 graph,
40 source,
41 target,
42 Path::start(source),
43 &mut visited,
44 &mut nodes_visited,
45 );
46
47 ShortestPathResult {
48 path,
49 nodes_visited,
50 }
51 }
52
53 pub fn traverse(graph: &GraphStore, source: &str) -> Vec<String> {
55 let mut visited: HashSet<String> = HashSet::new();
56 let mut result: Vec<String> = Vec::new();
57
58 fn dfs_visit(
59 graph: &GraphStore,
60 current: &str,
61 visited: &mut HashSet<String>,
62 result: &mut Vec<String>,
63 ) {
64 visited.insert(current.to_string());
65 result.push(current.to_string());
66
67 for (_, neighbor, _) in graph.outgoing_edges(current) {
68 if !visited.contains(&neighbor) {
69 dfs_visit(graph, &neighbor, visited, result);
70 }
71 }
72 }
73
74 dfs_visit(graph, source, &mut visited, &mut result);
75 result
76 }
77
78 pub fn all_paths(
80 graph: &GraphStore,
81 source: &str,
82 target: &str,
83 max_depth: usize,
84 ) -> AllPathsResult {
85 let mut paths: Vec<Path> = Vec::new();
86 let mut nodes_visited = 0;
87
88 fn dfs_all(
89 graph: &GraphStore,
90 target: &str,
91 path: Path,
92 max_depth: usize,
93 paths: &mut Vec<Path>,
94 visited_in_path: &mut HashSet<String>,
95 nodes_visited: &mut usize,
96 ) {
97 let current = path.nodes.last().unwrap().clone();
98 *nodes_visited += 1;
99
100 if current == target {
101 paths.push(path);
102 return;
103 }
104
105 if path.len() >= max_depth {
106 return;
107 }
108
109 for (edge_type, neighbor, weight) in graph.outgoing_edges(¤t) {
110 if !visited_in_path.contains(&neighbor) {
111 visited_in_path.insert(neighbor.clone());
112 let new_path = path.extend(&neighbor, edge_type, weight as f64);
113 dfs_all(
114 graph,
115 target,
116 new_path,
117 max_depth,
118 paths,
119 visited_in_path,
120 nodes_visited,
121 );
122 visited_in_path.remove(&neighbor);
123 }
124 }
125 }
126
127 let mut visited_in_path: HashSet<String> = HashSet::new();
128 visited_in_path.insert(source.to_string());
129 dfs_all(
130 graph,
131 target,
132 Path::start(source),
133 max_depth,
134 &mut paths,
135 &mut visited_in_path,
136 &mut nodes_visited,
137 );
138
139 AllPathsResult {
140 paths,
141 nodes_visited,
142 }
143 }
144
145 pub fn topological_sort(graph: &GraphStore) -> Option<Vec<String>> {
147 let nodes: Vec<String> = graph.iter_nodes().map(|n| n.id.clone()).collect();
148 let mut visited: HashSet<String> = HashSet::new();
149 let mut temp_marks: HashSet<String> = HashSet::new();
150 let mut result: Vec<String> = Vec::new();
151
152 fn visit(
153 graph: &GraphStore,
154 node: &str,
155 visited: &mut HashSet<String>,
156 temp_marks: &mut HashSet<String>,
157 result: &mut Vec<String>,
158 ) -> bool {
159 if temp_marks.contains(node) {
160 return false; }
162 if visited.contains(node) {
163 return true;
164 }
165
166 temp_marks.insert(node.to_string());
167
168 for (_, neighbor, _) in graph.outgoing_edges(node) {
169 if !visit(graph, &neighbor, visited, temp_marks, result) {
170 return false;
171 }
172 }
173
174 temp_marks.remove(node);
175 visited.insert(node.to_string());
176 result.push(node.to_string());
177 true
178 }
179
180 for node in &nodes {
181 if !visited.contains(node)
182 && !visit(graph, node, &mut visited, &mut temp_marks, &mut result)
183 {
184 return None; }
186 }
187
188 result.reverse();
189 Some(result)
190 }
191}