use std::hash::Hash;
pub struct HCS<STATE, SUCCESSORS, SUCCESS, HEURISTIC, ITER>
where
STATE: Eq + Hash + Clone,
SUCCESSORS: FnMut(&STATE) -> ITER,
SUCCESS: FnMut(&STATE) -> bool,
HEURISTIC: FnMut(&STATE) -> usize,
ITER: IntoIterator<Item = STATE>,
{
path: Vec<STATE>,
successors: SUCCESSORS,
success: SUCCESS,
heuristic: HEURISTIC,
}
impl<STATE, SUCCESSORS, SUCCESS, HEURISTIC, ITER> HCS<STATE, SUCCESSORS, SUCCESS, HEURISTIC, ITER>
where
STATE: Eq + Hash + Clone,
SUCCESSORS: FnMut(&STATE) -> ITER,
SUCCESS: FnMut(&STATE) -> bool,
HEURISTIC: FnMut(&STATE) -> usize,
ITER: IntoIterator<Item = STATE>,
{
pub fn new(
init: &STATE,
successors: SUCCESSORS,
success: SUCCESS,
heuristic: HEURISTIC,
) -> Self {
Self {
path: vec![init.clone()],
successors,
success,
heuristic,
}
}
}
impl<STATE, SUCCESSORS, SUCCESS, HEURISTIC, ITER> Iterator
for HCS<STATE, SUCCESSORS, SUCCESS, HEURISTIC, ITER>
where
STATE: Eq + Hash + Clone,
SUCCESSORS: FnMut(&STATE) -> ITER,
SUCCESS: FnMut(&STATE) -> bool,
HEURISTIC: FnMut(&STATE) -> usize,
ITER: IntoIterator<Item = STATE>,
{
type Item = Option<Vec<STATE>>;
fn next(&mut self) -> Option<Self::Item> {
let node = self.path.last().unwrap();
if (self.success)(node) {
return Some(Some(self.path.to_owned()));
}
let best_successor = (self.successors)(node)
.into_iter()
.map(|s| ((self.heuristic)(&s), s))
.min_by(|a, b| a.0.cmp(&b.0));
if let Some((v, s)) = best_successor {
let p_v = (self.heuristic)(node);
if v < p_v {
self.path.push(s);
return Some(None);
}
}
None
}
}
pub fn solve<STATE, SUCCESSORS, SUCCESS, HEURISTIC, ITER>(
init: &STATE,
successors: SUCCESSORS,
success: SUCCESS,
heuristic: HEURISTIC,
) -> Option<Vec<STATE>>
where
STATE: Eq + Hash + Clone,
SUCCESSORS: FnMut(&STATE) -> ITER,
SUCCESS: FnMut(&STATE) -> bool,
HEURISTIC: FnMut(&STATE) -> usize,
ITER: IntoIterator<Item = STATE>,
{
HCS::new(init, successors, success, heuristic)
.into_iter()
.find(|i| i.is_some())?
}
pub fn paths<STATE, SUCCESSORS, SUCCESS, HEURISTIC, ITER>(
init: &STATE,
successors: SUCCESSORS,
success: SUCCESS,
heuristic: HEURISTIC,
) -> impl Iterator<Item = Vec<STATE>>
where
STATE: Eq + Hash + Clone,
SUCCESSORS: FnMut(&STATE) -> ITER,
SUCCESS: FnMut(&STATE) -> bool,
HEURISTIC: FnMut(&STATE) -> usize,
ITER: IntoIterator<Item = STATE>,
{
HCS::new(init, successors, success, heuristic)
.into_iter()
.filter_map(|i| i)
}