|
|
@ -9,12 +9,12 @@
|
|
|
|
use std::cmp::{Ordering, Reverse};
|
|
|
|
use std::cmp::{Ordering, Reverse};
|
|
|
|
use std::collections::{BTreeMap, BTreeSet};
|
|
|
|
use std::collections::{BTreeMap, BTreeSet};
|
|
|
|
use std::iter;
|
|
|
|
use std::iter;
|
|
|
|
|
|
|
|
use graph::prelude::{DirectedCsrGraph, DirectedNeighborsWithValues, Graph};
|
|
|
|
|
|
|
|
|
|
|
|
use itertools::Itertools;
|
|
|
|
use itertools::Itertools;
|
|
|
|
use miette::Result;
|
|
|
|
use miette::Result;
|
|
|
|
use ordered_float::OrderedFloat;
|
|
|
|
use ordered_float::OrderedFloat;
|
|
|
|
use priority_queue::PriorityQueue;
|
|
|
|
use priority_queue::PriorityQueue;
|
|
|
|
#[cfg(feature = "rayon")]
|
|
|
|
|
|
|
|
use rayon::prelude::*;
|
|
|
|
use rayon::prelude::*;
|
|
|
|
use smallvec::{smallvec, SmallVec};
|
|
|
|
use smallvec::{smallvec, SmallVec};
|
|
|
|
use smartstring::{LazyCompact, SmartString};
|
|
|
|
use smartstring::{LazyCompact, SmartString};
|
|
|
@ -42,8 +42,8 @@ impl FixedRule for ShortestPathDijkstra {
|
|
|
|
let undirected = payload.bool_option("undirected", Some(false))?;
|
|
|
|
let undirected = payload.bool_option("undirected", Some(false))?;
|
|
|
|
let keep_ties = payload.bool_option("keep_ties", Some(false))?;
|
|
|
|
let keep_ties = payload.bool_option("keep_ties", Some(false))?;
|
|
|
|
|
|
|
|
|
|
|
|
let (graph, indices, inv_indices, _) =
|
|
|
|
let (graph, indices, inv_indices) =
|
|
|
|
edges.convert_edge_to_weighted_graph(undirected, false)?;
|
|
|
|
edges.to_directed_weighted_graph(undirected, false)?;
|
|
|
|
|
|
|
|
|
|
|
|
let mut starting_nodes = BTreeSet::new();
|
|
|
|
let mut starting_nodes = BTreeSet::new();
|
|
|
|
for tuple in starting.iter()? {
|
|
|
|
for tuple in starting.iter()? {
|
|
|
@ -88,22 +88,19 @@ impl FixedRule for ShortestPathDijkstra {
|
|
|
|
};
|
|
|
|
};
|
|
|
|
for (target, cost, path) in res {
|
|
|
|
for (target, cost, path) in res {
|
|
|
|
let t = vec![
|
|
|
|
let t = vec![
|
|
|
|
indices[start].clone(),
|
|
|
|
indices[start as usize].clone(),
|
|
|
|
indices[target].clone(),
|
|
|
|
indices[target as usize].clone(),
|
|
|
|
DataValue::from(cost),
|
|
|
|
DataValue::from(cost as f64),
|
|
|
|
DataValue::List(path.into_iter().map(|u| indices[u].clone()).collect_vec()),
|
|
|
|
DataValue::List(path.into_iter().map(|u| indices[u as usize].clone()).collect_vec()),
|
|
|
|
];
|
|
|
|
];
|
|
|
|
out.put(t)
|
|
|
|
out.put(t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
#[cfg(feature = "rayon")]
|
|
|
|
|
|
|
|
let it = starting_nodes.into_par_iter();
|
|
|
|
let it = starting_nodes.into_par_iter();
|
|
|
|
#[cfg(not(feature = "rayon"))]
|
|
|
|
|
|
|
|
let it = starting_nodes.into_iter();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let all_res: Vec<_> = it
|
|
|
|
let all_res: Vec<_> = it
|
|
|
|
.map(|start| -> Result<(usize, Vec<(usize, f64, Vec<usize>)>)> {
|
|
|
|
.map(|start| -> Result<(u32, Vec<(u32, f32, Vec<u32>)>)> {
|
|
|
|
Ok((
|
|
|
|
Ok((
|
|
|
|
start,
|
|
|
|
start,
|
|
|
|
if let Some(tn) = &termination_nodes {
|
|
|
|
if let Some(tn) = &termination_nodes {
|
|
|
@ -135,10 +132,10 @@ impl FixedRule for ShortestPathDijkstra {
|
|
|
|
for (start, res) in all_res {
|
|
|
|
for (start, res) in all_res {
|
|
|
|
for (target, cost, path) in res {
|
|
|
|
for (target, cost, path) in res {
|
|
|
|
let t = vec![
|
|
|
|
let t = vec![
|
|
|
|
indices[start].clone(),
|
|
|
|
indices[start as usize].clone(),
|
|
|
|
indices[target].clone(),
|
|
|
|
indices[target as usize].clone(),
|
|
|
|
DataValue::from(cost),
|
|
|
|
DataValue::from(cost as f64),
|
|
|
|
DataValue::List(path.into_iter().map(|u| indices[u].clone()).collect_vec()),
|
|
|
|
DataValue::List(path.into_iter().map(|u| indices[u as usize].clone()).collect_vec()),
|
|
|
|
];
|
|
|
|
];
|
|
|
|
out.put(t)
|
|
|
|
out.put(t)
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -182,41 +179,41 @@ impl Ord for HeapState {
|
|
|
|
impl Eq for HeapState {}
|
|
|
|
impl Eq for HeapState {}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) trait ForbiddenEdge {
|
|
|
|
pub(crate) trait ForbiddenEdge {
|
|
|
|
fn is_forbidden(&self, src: usize, dst: usize) -> bool;
|
|
|
|
fn is_forbidden(&self, src: u32, dst: u32) -> bool;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl ForbiddenEdge for () {
|
|
|
|
impl ForbiddenEdge for () {
|
|
|
|
fn is_forbidden(&self, _src: usize, _dst: usize) -> bool {
|
|
|
|
fn is_forbidden(&self, _src: u32, _dst: u32) -> bool {
|
|
|
|
false
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl ForbiddenEdge for BTreeSet<(usize, usize)> {
|
|
|
|
impl ForbiddenEdge for BTreeSet<(u32, u32)> {
|
|
|
|
fn is_forbidden(&self, src: usize, dst: usize) -> bool {
|
|
|
|
fn is_forbidden(&self, src: u32, dst: u32) -> bool {
|
|
|
|
self.contains(&(src, dst))
|
|
|
|
self.contains(&(src, dst))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) trait ForbiddenNode {
|
|
|
|
pub(crate) trait ForbiddenNode {
|
|
|
|
fn is_forbidden(&self, node: usize) -> bool;
|
|
|
|
fn is_forbidden(&self, node: u32) -> bool;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl ForbiddenNode for () {
|
|
|
|
impl ForbiddenNode for () {
|
|
|
|
fn is_forbidden(&self, _node: usize) -> bool {
|
|
|
|
fn is_forbidden(&self, _node: u32) -> bool {
|
|
|
|
false
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl ForbiddenNode for BTreeSet<usize> {
|
|
|
|
impl ForbiddenNode for BTreeSet<u32> {
|
|
|
|
fn is_forbidden(&self, node: usize) -> bool {
|
|
|
|
fn is_forbidden(&self, node: u32) -> bool {
|
|
|
|
self.contains(&node)
|
|
|
|
self.contains(&node)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) trait Goal {
|
|
|
|
pub(crate) trait Goal {
|
|
|
|
fn is_exhausted(&self) -> bool;
|
|
|
|
fn is_exhausted(&self) -> bool;
|
|
|
|
fn visit(&mut self, node: usize);
|
|
|
|
fn visit(&mut self, node: u32);
|
|
|
|
fn iter(&self, total: usize) -> Box<dyn Iterator<Item = usize> + '_>;
|
|
|
|
fn iter(&self, total: u32) -> Box<dyn Iterator<Item = u32> + '_>;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Goal for () {
|
|
|
|
impl Goal for () {
|
|
|
@ -224,19 +221,19 @@ impl Goal for () {
|
|
|
|
false
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn visit(&mut self, _node: usize) {}
|
|
|
|
fn visit(&mut self, _node: u32) {}
|
|
|
|
|
|
|
|
|
|
|
|
fn iter(&self, total: usize) -> Box<dyn Iterator<Item = usize> + '_> {
|
|
|
|
fn iter(&self, total: u32) -> Box<dyn Iterator<Item = u32> + '_> {
|
|
|
|
Box::new(0..total)
|
|
|
|
Box::new(0..total)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Goal for Option<usize> {
|
|
|
|
impl Goal for Option<u32> {
|
|
|
|
fn is_exhausted(&self) -> bool {
|
|
|
|
fn is_exhausted(&self) -> bool {
|
|
|
|
self.is_none()
|
|
|
|
self.is_none()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn visit(&mut self, node: usize) {
|
|
|
|
fn visit(&mut self, node: u32) {
|
|
|
|
if let Some(u) = &self {
|
|
|
|
if let Some(u) = &self {
|
|
|
|
if *u == node {
|
|
|
|
if *u == node {
|
|
|
|
self.take();
|
|
|
|
self.take();
|
|
|
@ -244,7 +241,7 @@ impl Goal for Option<usize> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn iter(&self, _total: usize) -> Box<dyn Iterator<Item = usize> + '_> {
|
|
|
|
fn iter(&self, _total: u32) -> Box<dyn Iterator<Item = u32> + '_> {
|
|
|
|
if let Some(u) = self {
|
|
|
|
if let Some(u) = self {
|
|
|
|
Box::new(iter::once(*u))
|
|
|
|
Box::new(iter::once(*u))
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -253,51 +250,55 @@ impl Goal for Option<usize> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Goal for BTreeSet<usize> {
|
|
|
|
impl Goal for BTreeSet<u32> {
|
|
|
|
fn is_exhausted(&self) -> bool {
|
|
|
|
fn is_exhausted(&self) -> bool {
|
|
|
|
self.is_empty()
|
|
|
|
self.is_empty()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn visit(&mut self, node: usize) {
|
|
|
|
fn visit(&mut self, node: u32) {
|
|
|
|
self.remove(&node);
|
|
|
|
self.remove(&node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn iter(&self, _total: usize) -> Box<dyn Iterator<Item = usize> + '_> {
|
|
|
|
fn iter(&self, _total: u32) -> Box<dyn Iterator<Item = u32> + '_> {
|
|
|
|
Box::new(self.iter().cloned())
|
|
|
|
Box::new(self.iter().cloned())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn dijkstra<FE: ForbiddenEdge, FN: ForbiddenNode, G: Goal + Clone>(
|
|
|
|
pub(crate) fn dijkstra<FE: ForbiddenEdge, FN: ForbiddenNode, G: Goal + Clone>(
|
|
|
|
edges: &[Vec<(usize, f64)>],
|
|
|
|
edges: &DirectedCsrGraph<u32, (), f32>,
|
|
|
|
start: usize,
|
|
|
|
start: u32,
|
|
|
|
goals: &G,
|
|
|
|
goals: &G,
|
|
|
|
forbidden_edges: &FE,
|
|
|
|
forbidden_edges: &FE,
|
|
|
|
forbidden_nodes: &FN,
|
|
|
|
forbidden_nodes: &FN,
|
|
|
|
) -> Vec<(usize, f64, Vec<usize>)> {
|
|
|
|
) -> Vec<(u32, f32, Vec<u32>)> {
|
|
|
|
let mut distance = vec![f64::INFINITY; edges.len()];
|
|
|
|
let graph_size = edges.node_count();
|
|
|
|
|
|
|
|
let mut distance = vec![f32::INFINITY; graph_size as usize];
|
|
|
|
let mut pq = PriorityQueue::new();
|
|
|
|
let mut pq = PriorityQueue::new();
|
|
|
|
let mut back_pointers = vec![usize::MAX; edges.len()];
|
|
|
|
let mut back_pointers = vec![u32::MAX; graph_size as usize];
|
|
|
|
distance[start] = 0.;
|
|
|
|
distance[start as usize] = 0.;
|
|
|
|
pq.push(start, Reverse(OrderedFloat(0.)));
|
|
|
|
pq.push(start, Reverse(OrderedFloat(0.)));
|
|
|
|
let mut goals_remaining = goals.clone();
|
|
|
|
let mut goals_remaining = goals.clone();
|
|
|
|
|
|
|
|
|
|
|
|
while let Some((node, Reverse(OrderedFloat(cost)))) = pq.pop() {
|
|
|
|
while let Some((node, Reverse(OrderedFloat(cost)))) = pq.pop() {
|
|
|
|
if cost > distance[node] {
|
|
|
|
if cost > distance[node as usize] {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (nxt_node, path_weight) in &edges[node] {
|
|
|
|
for target in edges.out_neighbors_with_values(node) {
|
|
|
|
if forbidden_nodes.is_forbidden(*nxt_node) {
|
|
|
|
let nxt_node = target.target;
|
|
|
|
|
|
|
|
let path_weight = target.value;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if forbidden_nodes.is_forbidden(nxt_node) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if forbidden_edges.is_forbidden(node, *nxt_node) {
|
|
|
|
if forbidden_edges.is_forbidden(node, nxt_node) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let nxt_cost = cost + *path_weight;
|
|
|
|
let nxt_cost = cost + path_weight;
|
|
|
|
if nxt_cost < distance[*nxt_node] {
|
|
|
|
if nxt_cost < distance[nxt_node as usize] {
|
|
|
|
pq.push_increase(*nxt_node, Reverse(OrderedFloat(nxt_cost)));
|
|
|
|
pq.push_increase(nxt_node, Reverse(OrderedFloat(nxt_cost)));
|
|
|
|
distance[*nxt_node] = nxt_cost;
|
|
|
|
distance[nxt_node as usize] = nxt_cost;
|
|
|
|
back_pointers[*nxt_node] = node;
|
|
|
|
back_pointers[nxt_node as usize] = node;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -308,9 +309,9 @@ pub(crate) fn dijkstra<FE: ForbiddenEdge, FN: ForbiddenNode, G: Goal + Clone>(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let ret = goals
|
|
|
|
let ret = goals
|
|
|
|
.iter(edges.len())
|
|
|
|
.iter(edges.node_count())
|
|
|
|
.map(|target| {
|
|
|
|
.map(|target| {
|
|
|
|
let cost = distance[target];
|
|
|
|
let cost = distance[target as usize];
|
|
|
|
if !cost.is_finite() {
|
|
|
|
if !cost.is_finite() {
|
|
|
|
(target, cost, vec![])
|
|
|
|
(target, cost, vec![])
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -318,7 +319,7 @@ pub(crate) fn dijkstra<FE: ForbiddenEdge, FN: ForbiddenNode, G: Goal + Clone>(
|
|
|
|
let mut current = target;
|
|
|
|
let mut current = target;
|
|
|
|
while current != start {
|
|
|
|
while current != start {
|
|
|
|
path.push(current);
|
|
|
|
path.push(current);
|
|
|
|
current = back_pointers[current];
|
|
|
|
current = back_pointers[current as usize];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
path.push(start);
|
|
|
|
path.push(start);
|
|
|
|
path.reverse();
|
|
|
|
path.reverse();
|
|
|
@ -331,41 +332,44 @@ pub(crate) fn dijkstra<FE: ForbiddenEdge, FN: ForbiddenNode, G: Goal + Clone>(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn dijkstra_keep_ties<FE: ForbiddenEdge, FN: ForbiddenNode, G: Goal + Clone>(
|
|
|
|
pub(crate) fn dijkstra_keep_ties<FE: ForbiddenEdge, FN: ForbiddenNode, G: Goal + Clone>(
|
|
|
|
edges: &[Vec<(usize, f64)>],
|
|
|
|
edges: &DirectedCsrGraph<u32, (), f32>,
|
|
|
|
start: usize,
|
|
|
|
start: u32,
|
|
|
|
goals: &G,
|
|
|
|
goals: &G,
|
|
|
|
forbidden_edges: &FE,
|
|
|
|
forbidden_edges: &FE,
|
|
|
|
forbidden_nodes: &FN,
|
|
|
|
forbidden_nodes: &FN,
|
|
|
|
poison: Poison,
|
|
|
|
poison: Poison,
|
|
|
|
) -> Result<Vec<(usize, f64, Vec<usize>)>> {
|
|
|
|
) -> Result<Vec<(u32, f32, Vec<u32>)>> {
|
|
|
|
let mut distance = vec![f64::INFINITY; edges.len()];
|
|
|
|
let mut distance = vec![f32::INFINITY; edges.node_count() as usize];
|
|
|
|
let mut pq = PriorityQueue::new();
|
|
|
|
let mut pq = PriorityQueue::new();
|
|
|
|
let mut back_pointers: Vec<SmallVec<[usize; 1]>> = vec![smallvec![]; edges.len()];
|
|
|
|
let mut back_pointers: Vec<SmallVec<[u32; 1]>> = vec![smallvec![]; edges.node_count() as usize];
|
|
|
|
distance[start] = 0.;
|
|
|
|
distance[start as usize] = 0.;
|
|
|
|
pq.push(start, Reverse(OrderedFloat(0.)));
|
|
|
|
pq.push(start, Reverse(OrderedFloat(0.)));
|
|
|
|
let mut goals_remaining = goals.clone();
|
|
|
|
let mut goals_remaining = goals.clone();
|
|
|
|
|
|
|
|
|
|
|
|
while let Some((node, Reverse(OrderedFloat(cost)))) = pq.pop() {
|
|
|
|
while let Some((node, Reverse(OrderedFloat(cost)))) = pq.pop() {
|
|
|
|
if cost > distance[node] {
|
|
|
|
if cost > distance[node as usize] {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (nxt_node, path_weight) in &edges[node] {
|
|
|
|
for target in edges.out_neighbors_with_values(node) {
|
|
|
|
if forbidden_nodes.is_forbidden(*nxt_node) {
|
|
|
|
let nxt_node = target.target;
|
|
|
|
|
|
|
|
let path_weight = target.value;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if forbidden_nodes.is_forbidden(nxt_node) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if forbidden_edges.is_forbidden(node, *nxt_node) {
|
|
|
|
if forbidden_edges.is_forbidden(node, nxt_node) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let nxt_cost = cost + *path_weight;
|
|
|
|
let nxt_cost = cost + path_weight;
|
|
|
|
if nxt_cost < distance[*nxt_node] {
|
|
|
|
if nxt_cost < distance[nxt_node as usize] {
|
|
|
|
pq.push_increase(*nxt_node, Reverse(OrderedFloat(nxt_cost)));
|
|
|
|
pq.push_increase(nxt_node, Reverse(OrderedFloat(nxt_cost)));
|
|
|
|
distance[*nxt_node] = nxt_cost;
|
|
|
|
distance[nxt_node as usize] = nxt_cost;
|
|
|
|
back_pointers[*nxt_node].clear();
|
|
|
|
back_pointers[nxt_node as usize].clear();
|
|
|
|
back_pointers[*nxt_node].push(node);
|
|
|
|
back_pointers[nxt_node as usize].push(node);
|
|
|
|
} else if nxt_cost == distance[*nxt_node] {
|
|
|
|
} else if nxt_cost == distance[nxt_node as usize] {
|
|
|
|
pq.push_increase(*nxt_node, Reverse(OrderedFloat(nxt_cost)));
|
|
|
|
pq.push_increase(nxt_node, Reverse(OrderedFloat(nxt_cost)));
|
|
|
|
back_pointers[*nxt_node].push(node);
|
|
|
|
back_pointers[nxt_node as usize].push(node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
poison.check()?;
|
|
|
|
poison.check()?;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -377,27 +381,27 @@ pub(crate) fn dijkstra_keep_ties<FE: ForbiddenEdge, FN: ForbiddenNode, G: Goal +
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let ret = goals
|
|
|
|
let ret = goals
|
|
|
|
.iter(edges.len())
|
|
|
|
.iter(edges.node_count())
|
|
|
|
.flat_map(|target| {
|
|
|
|
.flat_map(|target| {
|
|
|
|
let cost = distance[target];
|
|
|
|
let cost = distance[target as usize];
|
|
|
|
if !cost.is_finite() {
|
|
|
|
if !cost.is_finite() {
|
|
|
|
vec![(target, cost, vec![])]
|
|
|
|
vec![(target, cost, vec![])]
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
struct CollectPath {
|
|
|
|
struct CollectPath {
|
|
|
|
collected: Vec<(usize, f64, Vec<usize>)>,
|
|
|
|
collected: Vec<(u32, f32, Vec<u32>)>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl CollectPath {
|
|
|
|
impl CollectPath {
|
|
|
|
fn collect(
|
|
|
|
fn collect(
|
|
|
|
&mut self,
|
|
|
|
&mut self,
|
|
|
|
chain: &[usize],
|
|
|
|
chain: &[u32],
|
|
|
|
start: usize,
|
|
|
|
start: u32,
|
|
|
|
target: usize,
|
|
|
|
target: u32,
|
|
|
|
cost: f64,
|
|
|
|
cost: f32,
|
|
|
|
back_pointers: &[SmallVec<[usize; 1]>],
|
|
|
|
back_pointers: &[SmallVec<[u32; 1]>],
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
let last = chain.last().unwrap();
|
|
|
|
let last = chain.last().unwrap();
|
|
|
|
let prevs = &back_pointers[*last];
|
|
|
|
let prevs = &back_pointers[*last as usize];
|
|
|
|
for nxt in prevs {
|
|
|
|
for nxt in prevs {
|
|
|
|
let mut ret = chain.to_vec();
|
|
|
|
let mut ret = chain.to_vec();
|
|
|
|
ret.push(*nxt);
|
|
|
|
ret.push(*nxt);
|
|
|
|