@@ -13,16 +13,17 @@ use itertools::Itertools;
1313use radix_heap:: RadixHeapMap ;
1414use rustc_hash:: FxHashMap ;
1515
16- type PredecessorInfo < ' a , ' b > = ( u64 , & ' b Vertex < ' a > , Edge ) ;
16+ type PredecessorInfo < ' a , ' b > = ( u64 , & ' b Vertex < ' a > ) ;
1717
18- fn shortest_path ( start : Vertex , size_hint : usize ) -> Vec < ( Edge , Vertex ) > {
18+ /// Return the shortest route from `start` to the end vertex.
19+ fn shortest_vertex_path ( start : Vertex , size_hint : usize ) -> Vec < Vertex > {
1920 // We want to visit nodes with the shortest distance first, but
2021 // RadixHeapMap is a max-heap. Ensure nodes are wrapped with
2122 // Reverse to flip comparisons.
2223 let mut heap: RadixHeapMap < Reverse < _ > , & Vertex > = RadixHeapMap :: new ( ) ;
2324
2425 let vertex_arena = Bump :: new ( ) ;
25- heap. push ( Reverse ( 0 ) , vertex_arena. alloc ( start) ) ;
26+ heap. push ( Reverse ( 0 ) , vertex_arena. alloc ( start. clone ( ) ) ) ;
2627
2728 // TODO: this grows very big. Consider using IDA* to reduce memory
2829 // usage.
@@ -44,12 +45,12 @@ fn shortest_path(start: Vertex, size_hint: usize) -> Vec<(Edge, Vertex)> {
4445 if let Some ( ( edge, next) ) = neighbour. take ( ) {
4546 let distance_to_next = distance + edge. cost ( ) ;
4647 let found_shorter_route = match predecessors. get ( & next) {
47- Some ( ( prev_shortest, _, _ ) ) => distance_to_next < * prev_shortest,
48+ Some ( ( prev_shortest, _) ) => distance_to_next < * prev_shortest,
4849 _ => true ,
4950 } ;
5051
5152 if found_shorter_route {
52- predecessors. insert ( next, ( distance_to_next, current, edge ) ) ;
53+ predecessors. insert ( next, ( distance_to_next, current) ) ;
5354
5455 heap. push ( Reverse ( distance_to_next) , next) ;
5556 }
@@ -69,18 +70,61 @@ fn shortest_path(start: Vertex, size_hint: usize) -> Vec<(Edge, Vertex)> {
6970 ) ;
7071 let mut current = end;
7172
72- let mut route: Vec < ( Edge , Vertex ) > = vec ! [ ] ;
73+ let mut vertex_route: Vec < Vertex > = vec ! [ end. clone( ) ] ;
74+ while let Some ( ( _, node) ) = predecessors. remove ( & current) {
75+ vertex_route. push ( node. clone ( ) ) ;
76+ current = node;
77+ }
78+
79+ vertex_route. reverse ( ) ;
80+ vertex_route
81+ }
82+
83+ fn shortest_path_with_edges < ' a > ( route : & [ Vertex < ' a > ] ) -> Vec < ( Edge , Vertex < ' a > ) > {
84+ let mut prev = route. first ( ) . expect ( "Expected non-empty route" ) ;
85+
7386 let mut cost = 0 ;
74- while let Some ( ( _, node, edge) ) = predecessors. remove ( & current) {
75- route. push ( ( edge, node. clone ( ) ) ) ;
87+ let mut res = vec ! [ ] ;
88+ for vertex in route. iter ( ) . skip ( 1 ) {
89+ let edge = edge_between ( prev, vertex) ;
90+ res. push ( ( edge, prev. clone ( ) ) ) ;
7691 cost += edge. cost ( ) ;
7792
78- current = node ;
93+ prev = vertex ;
7994 }
8095 debug ! ( "Found a path of {} with cost {}." , route. len( ) , cost) ;
8196
82- route. reverse ( ) ;
83- route
97+ res
98+ }
99+
100+ /// Return the shortest route from the `start` to the end vertex.
101+ ///
102+ /// The vec returned does not return the very last vertex. This is
103+ /// necessary because a route of N vertices only has N-1 edges.
104+ fn shortest_path ( start : Vertex , size_hint : usize ) -> Vec < ( Edge , Vertex ) > {
105+ let vertex_path = shortest_vertex_path ( start, size_hint) ;
106+ shortest_path_with_edges ( & vertex_path)
107+ }
108+
109+ fn edge_between < ' a > ( before : & Vertex < ' a > , after : & Vertex < ' a > ) -> Edge {
110+ let mut neighbour_buf = [
111+ None , None , None , None , None , None , None , None , None , None , None , None ,
112+ ] ;
113+
114+ let vertex_arena = Bump :: new ( ) ;
115+ neighbours ( before, & mut neighbour_buf, & vertex_arena) ;
116+ for neighbour in & mut neighbour_buf {
117+ if let Some ( ( edge, next) ) = neighbour. take ( ) {
118+ if next == after {
119+ return edge;
120+ }
121+ }
122+ }
123+
124+ panic ! (
125+ "Expected a route between the two vertices {:#?} and {:#?}" ,
126+ before, after
127+ ) ;
84128}
85129
86130/// What is the total number of AST nodes?
0 commit comments