reddb_server/storage/engine/pathfinding/
all_shortest_impl.rs1use super::*;
2
3impl AllShortestPaths {
4 pub fn find(graph: &GraphStore, source: &str, target: &str) -> AllPathsResult {
6 if source == target {
7 return AllPathsResult {
8 paths: vec![Path::start(source)],
9 nodes_visited: 1,
10 };
11 }
12
13 let first_result = BFS::shortest_path(graph, source, target);
15 let min_distance = match &first_result.path {
16 Some(p) => p.len(),
17 None => {
18 return AllPathsResult {
19 paths: Vec::new(),
20 nodes_visited: first_result.nodes_visited,
21 }
22 }
23 };
24
25 let mut paths: Vec<Path> = Vec::new();
27 let mut nodes_visited = 0;
28
29 fn find_all(
30 graph: &GraphStore,
31 current_path: Path,
32 target: &str,
33 remaining_depth: usize,
34 visited_in_path: &mut HashSet<String>,
35 paths: &mut Vec<Path>,
36 nodes_visited: &mut usize,
37 ) {
38 let current = current_path.nodes.last().unwrap().clone();
39 *nodes_visited += 1;
40
41 if remaining_depth == 0 {
42 if current == target {
43 paths.push(current_path);
44 }
45 return;
46 }
47
48 for (edge_type, neighbor, weight) in graph.outgoing_edges(¤t) {
49 if !visited_in_path.contains(&neighbor) {
50 visited_in_path.insert(neighbor.clone());
51 let new_path = current_path.extend(&neighbor, edge_type, weight as f64);
52 find_all(
53 graph,
54 new_path,
55 target,
56 remaining_depth - 1,
57 visited_in_path,
58 paths,
59 nodes_visited,
60 );
61 visited_in_path.remove(&neighbor);
62 }
63 }
64 }
65
66 let mut visited_in_path: HashSet<String> = HashSet::new();
67 visited_in_path.insert(source.to_string());
68 find_all(
69 graph,
70 Path::start(source),
71 target,
72 min_distance,
73 &mut visited_in_path,
74 &mut paths,
75 &mut nodes_visited,
76 );
77
78 AllPathsResult {
79 paths,
80 nodes_visited,
81 }
82 }
83}