Skip to content

Commit

Permalink
perf(idastar): use set for nodes encountered in path
Browse files Browse the repository at this point in the history
  • Loading branch information
samueltardieu committed Jan 3, 2025
1 parent c7f6270 commit 263e2e4
Showing 1 changed file with 21 additions and 6 deletions.
27 changes: 21 additions & 6 deletions src/directed/idastar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
//! algorithm](https://en.wikipedia.org/wiki/Iterative_deepening_A*).
use num_traits::Zero;
use rustc_hash::FxHashSet;
use std::hash::Hash;

/// Compute a shortest path using the [IDA* search
/// algorithm](https://en.wikipedia.org/wiki/Iterative_deepening_A*).
Expand Down Expand Up @@ -76,7 +78,7 @@ pub fn idastar<N, C, FN, IN, FH, FS>(
mut success: FS,
) -> Option<(Vec<N>, C)>
where
N: Eq + Clone,
N: Eq + Clone + Hash,
C: Zero + Ord + Copy,
FN: FnMut(&N) -> IN,
IN: IntoIterator<Item = (N, C)>,
Expand All @@ -85,6 +87,8 @@ where
{
let mut bound = heuristic(start);
let mut path = vec![start.clone()];
let mut seen = FxHashSet::default();
seen.insert(start.clone());
loop {
match search(
&mut path,
Expand All @@ -93,6 +97,7 @@ where
&mut successors,
&mut heuristic,
&mut success,
&mut seen,
) {
Path::Found(path, cost) => return Some((path, cost)),
Path::Minimum(min) => {
Expand All @@ -119,9 +124,10 @@ fn search<N, C, FN, IN, FH, FS>(
successors: &mut FN,
heuristic: &mut FH,
success: &mut FS,
seen: &mut FxHashSet<N>,
) -> Path<N, C>
where
N: Eq + Clone,
N: Eq + Clone + Hash,
C: Zero + Ord + Copy,
FN: FnMut(&N) -> IN,
IN: IntoIterator<Item = (N, C)>,
Expand All @@ -137,10 +143,10 @@ where
if success(start) {
return Path::Found(path.clone(), f);
}
let mut neighbs = successors(start)
let mut neighbs: Vec<(N, C, C)> = successors(start)
.into_iter()
.filter_map(|(n, c)| {
(!path.contains(&n)).then(|| {
(!seen.contains(&n)).then(|| {
let h = heuristic(&n);
(n, c, c + h)
})
Expand All @@ -151,13 +157,22 @@ where
};
let mut min = None;
for (node, extra, _) in neighbs {
seen.insert(node.clone());
path.push(node);
match search(path, cost + extra, bound, successors, heuristic, success) {
match search(
path,
cost + extra,
bound,
successors,
heuristic,
success,
seen,
) {
found_path @ Path::Found(_, _) => return found_path,
Path::Minimum(m) if !min.is_some_and(|n| n < m) => min = Some(m),
_ => (),
}
path.pop();
seen.remove(&path.pop().unwrap());
}
min.map_or(Path::Impossible, Path::Minimum)
}

0 comments on commit 263e2e4

Please sign in to comment.