Use a radix heap to speed up Dijkstra implementation

edge_only_predecessors
Wilfred Hughes 2021-09-12 22:04:15 +07:00
parent 41fe6561f1
commit ea3cb7737a
3 changed files with 83 additions and 14 deletions

76
Cargo.lock generated

@ -31,6 +31,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.2.1"
@ -113,6 +119,7 @@ dependencies = [
"mimalloc",
"pretty_assertions",
"pretty_env_logger",
"radix-heap",
"regex",
"rustc-hash",
"strsim 0.10.0",
@ -158,6 +165,12 @@ dependencies = [
"quick-error",
]
[[package]]
name = "ieee754"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9007da9cacbd3e6343da136e98b0d2df013f553d35bdec8b518f07bea768e19c"
[[package]]
name = "itertools"
version = "0.8.2"
@ -212,6 +225,43 @@ dependencies = [
"libmimalloc-sys",
]
[[package]]
name = "num-traits"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
dependencies = [
"num-traits 0.2.14",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "ordered-float"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb5259643245d3f292c7a146b2df53bba24d7eab159410e648eb73dc164669d"
dependencies = [
"num-traits 0.1.43",
"unreachable",
]
[[package]]
name = "ordered-float"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7"
dependencies = [
"num-traits 0.2.14",
]
[[package]]
name = "output_vt100"
version = "0.1.2"
@ -267,6 +317,17 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "radix-heap"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48d37c34f4ea428bfd19095e2f93fe5319f31f28651b806b1370e727cc552cf"
dependencies = [
"ieee754",
"ordered-float 0.5.2",
"ordered-float 1.1.1",
]
[[package]]
name = "regex"
version = "1.5.4"
@ -369,12 +430,27 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "unreachable"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
dependencies = [
"void",
]
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "winapi"
version = "0.3.9"

@ -33,6 +33,7 @@ libc = "0.2.99"
log = "0.4.14"
pretty_env_logger = "0.4.0"
mimalloc = { version = "0.1.26", default-features = false }
radix-heap = "0.3.8"
[dev-dependencies]
pretty_assertions = "0.6.1"

@ -1,15 +1,13 @@
//! Implements Dijkstra's algorithm for shortest path, to find an
//! optimal and readable diff between two ASTs.
use std::{
cmp::{Ordering, Reverse},
collections::BinaryHeap,
};
use std::cmp::{Ordering, Reverse};
use crate::{
graph::{mark_route, neighbours, Edge, Vertex},
syntax::Syntax,
};
use radix_heap::RadixHeapMap;
use rustc_hash::FxHashMap;
/// A vertex with a distance.
@ -55,12 +53,9 @@ fn shortest_path(start: Vertex) -> Vec<(Edge, Vertex)> {
// We want to visit nodes with the shortest distance first, but
// BinaryHeap is a max-heap. Ensure nodes are wrapped with Reverse
// to flip comparisons.
let mut heap: BinaryHeap<Reverse<_>> = BinaryHeap::new();
let mut heap: RadixHeapMap<Reverse<_>, Vertex> = RadixHeapMap::new();
heap.push(Reverse(OrdVertex {
distance: 0,
current: start,
}));
heap.push(Reverse(0), start);
// TODO: this grows very big. Consider using IDA* to reduce memory
// usage.
@ -69,7 +64,7 @@ fn shortest_path(start: Vertex) -> Vec<(Edge, Vertex)> {
let end;
loop {
match heap.pop() {
Some(Reverse(OrdVertex { distance, current })) => {
Some((Reverse(distance), current)) => {
if current.is_end() {
end = current;
break;
@ -86,10 +81,7 @@ fn shortest_path(start: Vertex) -> Vec<(Edge, Vertex)> {
predecessors
.insert(next.clone(), (distance_to_next, current.clone(), edge));
heap.push(Reverse(OrdVertex {
distance: distance_to_next,
current: next,
}));
heap.push(Reverse(distance_to_next), next);
}
}
}