artistpath_core/pathfinding/
mod.rs1pub mod bfs;
2pub mod dijkstra;
3pub mod utils;
4
5use crate::{Algorithm, pathfinding_config::PathfindingConfig};
6use bfs::neighborhood::explore_path_neighborhood;
7use rustc_hash::FxHashMap;
8use std::time::Instant;
9use uuid::Uuid;
10
11type GraphData<'a> = (&'a memmap2::Mmap, &'a FxHashMap<Uuid, u64>);
13
14pub struct BiDirectionalGraphs<'a> {
16 pub forward: GraphData<'a>,
17 pub reverse: GraphData<'a>,
18}
19
20pub use bfs::bfs_find_path;
22pub use dijkstra::dijkstra_find_path;
23pub use utils::{EnhancedPathResult, get_artist_connections};
24
25pub fn find_paths_with_exploration(
26 start: Uuid,
27 target: Uuid,
28 algorithm: Algorithm,
29 budget: usize,
30 graphs: BiDirectionalGraphs,
31 config: &PathfindingConfig,
32) -> utils::EnhancedPathResult {
33 let search_timer = Instant::now();
34
35 let (forward_data, forward_index) = graphs.forward;
37 let (reverse_data, reverse_index) = graphs.reverse;
38
39 let (primary_path, artists_visited, _) = match algorithm {
40 Algorithm::Dijkstra => dijkstra_find_path(
41 start,
42 target,
43 forward_data,
44 forward_index,
45 reverse_data,
46 reverse_index,
47 config,
48 ),
49 Algorithm::Bfs => bfs_find_path(
50 start,
51 target,
52 forward_data,
53 forward_index,
54 reverse_data,
55 reverse_index,
56 config,
57 ),
58 };
59
60 match primary_path {
61 Some(path) => handle_successful_path_generic(
62 path,
63 budget,
64 artists_visited,
65 BiDirectionalGraphs {
66 forward: (forward_data, forward_index),
67 reverse: (reverse_data, reverse_index),
68 },
69 config,
70 search_timer,
71 ),
72 None => utils::EnhancedPathResult::NoPath {
73 artists_visited,
74 duration_ms: search_timer.elapsed().as_millis() as u64,
75 },
76 }
77}
78
79fn handle_successful_path_generic(
80 path: Vec<(Uuid, f32)>,
81 budget: usize,
82 artists_visited: usize,
83 graphs: BiDirectionalGraphs,
84 config: &PathfindingConfig,
85 start_time: Instant,
86) -> utils::EnhancedPathResult {
87 let path_length = path.len();
88
89 if path_length > budget {
90 utils::EnhancedPathResult::PathTooLong {
91 primary_path: path,
92 path_length,
93 minimum_budget_needed: path_length,
94 artists_visited,
95 duration_ms: start_time.elapsed().as_millis() as u64,
96 }
97 } else {
98 let (related_artists, connections) =
99 explore_path_neighborhood(&path, budget, graphs, config);
100
101 utils::EnhancedPathResult::Success {
102 primary_path: path,
103 related_artists,
104 connections,
105 artists_visited,
106 duration_ms: start_time.elapsed().as_millis() as u64,
107 }
108 }
109}