routingkit-cch
Rust bindings for the Customizable Contraction Hierarchies (CCH) implementation from RoutingKit. CCH is a three‑phase shortest path acceleration technique for large directed graphs (e.g. road networks) that allows fast re-weighting while keeping very low query latency.
Why CCH?
Traditional Contraction Hierarchies (CH) give extremely fast queries but require rebuilding (slow) when weights change. CCH cleanly separates:
- Preprocessing – topology + node ordering only (expensive but weight agnostic)
- Customization – inject / update edge weights (fast, parallelizable)
- Query – run many multi-source / multi-target shortest paths (microseconds)
This enables scenarios like: per-user cost profiles, frequent traffic updates, dynamic restrictions, or “what-if” analysis without full rebuilds.
Features
- Safe(ish) ergonomic Rust API on top of proven C++ core via
cxx. - Build indices from raw edge lists (tail/head arrays).
- Ordering helpers: nested dissection (inertial separator heuristic) and degree fallback.
- Sequential & parallel customization.
- Reusable query object supporting multi-source / multi-target searches.
- Path extraction: node sequence & original arc id sequence.
- Thread-safe sharing of immutable structures (
CCH,CCHMetric).
Installation
Stable release from crates.io:
[]
= "0.1"
Or track the repository:
[]
= { = "https://github.com/HellOwhatAs/routingkit-cch" }
For the git form ensure the RoutingKit submodule is present:
Requirements: C++17 compiler (MSVC / gcc / clang).
OpenMP is enabled automatically by the build script; ensure your toolchain provides an OpenMP runtime (e.g. install libomp on macOS).
Without it the build may fail or customization will be single‑threaded in a future fallback.
Quick Start
use ;
// Simple chain 0 -> 1 -> 2 -> 3
let tail = vec!;
let head = vec!;
let weights = vec!;
let node_count = 4;
let order = compute_order_degree; // O(m log n) light heuristic
let cch = CCHnew;
let metric = new; // customization inside
let mut q = new;
q.add_source;
q.add_target;
q.run;
assert_eq!;
Building an Order
For production use prefer the inertial nested dissection based order:
use compute_order_inertial;
let order = compute_order_inertial;
Better separators -> faster customization & queries. External advanced orderers (e.g. FlowCutter) could be integrated offline; you only need to supply the permutation.
(Parallel) Customization
use ;
let metric = new; // single thread
let metric = parallel_new; // 0 -> auto threads
Use when graphs are large enough; for tiny graphs overhead may outweigh benefit.
Path Reconstruction
After run():
distance()->Option<u32>(None = unreachable)node_path()->Vec<node_id>(empty = unreachable)arc_path()->Vec<original_arc_id>(empty = unreachable)
Thread Safety
| Type | Send | Sync | Notes |
|---|---|---|---|
CCH |
yes | yes | Immutable after build |
CCHMetric |
yes | yes | Read-only after customization |
CCHQuery |
yes | no | Internal mutable labels; reuse with reset() |
Create separate queries per thread for parallel batch querying.