use hashbrown::HashMap;
use std::collections::BinaryHeap;
use crate::traits::{CommonProperties, GraphBasics, GraphType};
use super::MinScored;
use super::measures::Measure;
pub fn k_shortest_path<'a, G: ?Sized, F, K, T: GraphType>(
graph: &'a G,
start: usize,
goal: Option<usize>,
k: usize,
edge_cost: F,
) -> HashMap<usize, K>
where
G: CommonProperties<'a, T, NodeIndex = usize>,
F: Fn(<G as GraphBasics>::EdgeIndex) -> K,
K: Measure + Copy,
{
let mut counter: Vec<usize> = vec![0; graph.node_count()];
let mut scores = HashMap::new();
let mut visit_next = BinaryHeap::new();
let zero_score = K::default();
visit_next.push(MinScored(zero_score, start));
while let Some(MinScored(node_score, node)) = visit_next.pop() {
counter[node] += 1;
let current_counter = counter[node];
if current_counter > k {
continue;
}
if current_counter == k {
scores.insert(node, node_score);
}
if goal.as_ref() == Some(&node) && current_counter == k {
break;
}
for (cost, nodes) in
graph.costed_neighbours(node, |edge_index| node_score + edge_cost(edge_index))
{
for next in nodes {
if next == node {
continue; }
visit_next.push(MinScored(cost, next));
}
}
}
scores
}