Skip to main content

Python bindings for the Customizable Contraction Hierarchies (CCH) implementation from RoutingKit.

Project description

routingkit-cch

Crates.io Pypi Docs License

Rust/Python 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?

CustomizableContractionHierarchies (CCH) are an index-based speedup technique for shortest paths in directed graphs that can quickly be adapted to new weights. CCHs use, contrary to regulars CHs, a three phase setup:

  1. Preprocessing
  2. Customization
  3. Query

The preprocessing is slow but does not rely on the arc weights. The Customization introduces the weights and is reasonably fast. Finally, the actual paths are computed in the query phase. A common setup consists of doing the preprocessing once and the customization per user upon login. Further one can use a customization to incorporate live-traffic updates.

Features

  • Safe 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, and partial weight update afterwards.
  • Cheap full re-customization via CCHMetric::reset (reuses internal buffers).
  • Reusable query object supporting multi-source / multi-target searches.
  • Batched one-to-many / many-to-one queries with pinned targets/sources (CCHOneToMany, CCHManyToOne).
  • Path extraction: node sequence & original arc id sequence.
  • Thread-safe sharing of immutable structures (CCH, CCHMetric).

Installation


Rust stable release from crates.io:

[dependencies]
routingkit-cch = "0.1"

Or track the repository:

[dependencies]
routingkit-cch = { git = "https://github.com/HellOwhatAs/routingkit-cch" }

Python stable release from pypi:

pip install routingkit-cch

Or track the repository:

pip install git+https://github.com/HellOwhatAs/routingkit-cch

For the git form ensure the RoutingKit submodule is present:

git submodule update --init --recursive

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 when CCHMetric::parallel_new is called.

Quick Start

For python examples, see examples folder.

use routingkit_cch::{CCH, CCHMetric, CCHQuery, compute_order_degree};

// Small toy graph: 0 -> 1 -> 2 -> 3
let tail = vec![0, 1, 2];
let head = vec![1, 2, 3];
let weights = vec![10, 5, 7]; // total 22 from 0 to 3
let node_count = 4u32;

// 1) Compute a (cheap) order; for real data prefer compute_order_inertial (requires lat,lon).
let order = compute_order_degree(node_count, &tail, &head);
let cch = CCH::new(&order, &tail, &head, |_| {}, false);

// 2) Bind weights & customize (done inside CCHMetric::new here).
let metric = CCHMetric::new(&cch, weights.clone());

// 3) Run a shortest path query 0 -> 3.
let mut q = CCHQuery::new(&metric);
q.add_source(0, 0);
q.add_target(3, 0);
let res = q.run();
assert_eq!(res.distance(), Some(22));
let node_path = res.node_path();
assert_eq!(node_path, vec![0, 1, 2, 3]);
let arc_path = res.arc_path();
assert_eq!(arc_path, vec![0, 1, 2]);

Building an Order

For production use prefer the inertial nested dissection based order:

use routingkit_cch::compute_order_inertial;
let order = compute_order_inertial(node_count, &tail, &head, &latitude, &longitude);

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 routingkit_cch::{CCH, CCHMetric};
let metric = CCHMetric::new(&cch, weights.clone()); // single thread
let metric = CCHMetric::parallel_new(&cch, weights.clone(), 0); // 0 -> auto threads

Use when graphs are large enough; for tiny graphs overhead may outweigh benefit.

Full Re-Customization (Metric Reset)

When all (or most) weights change (e.g. periodic traffic refresh), rebind the existing metric instead of building a new one; internal shortcut-weight buffers are reused:

let mut metric = CCHMetric::new(&cch, weights);
// ... later, new weights for the same CCH ...
metric.reset(new_weights); // re-customizes in place
// or, with the `openmp` feature:
metric.parallel_reset(new_weights, 0); // 0 -> auto threads

Requires exclusive access: drop all queries borrowing the metric first (enforced by the borrow checker).

Incremental (Partial) Weight Updates

If only a small subset of arc weights change (e.g. traffic incidents), you can avoid a full re-customization:

let mut metric = CCHMetric::parallel_new(&cch, weights.clone(), 0);
let mut updater = CCHMetricPartialUpdater::new(&cch);
// ... run queries ...
// Update two arcs (id 12 -> 900, id 77 -> 450)
updater.apply(&mut metric, &BTreeMap::from_iter([(12, 900), (77, 450)]));
// New queries now see updated weights.

Query

let mut q = CCHQuery::new(&metric);
q.add_source(0, 0);
q.add_target(3, 0);
{
    let res = q.run();
    printf("{:?}", res.distance());
} // drop res before reusing q since res takes &mut q
q.add_source(2, 0);
q.add_target(5, 0);
{
    let res = q.run();
    // ...
}

CCHQuery is not thread-safe; create one instance per thread and reuse it is far cheaper than constructing a new one.

One-to-Many / Many-to-One (Batched) Queries

When you need distances from one node to many fixed destinations (distance tables, matrices, k-nearest), pin the destination set once and query it in a single sweep — much faster than a point-to-point query per destination:

use routingkit_cch::{CCHOneToMany, CCHManyToOne};

let mut otm = CCHOneToMany::new(&metric, &targets); // pin once (moderately expensive)
for s in sources {
    let dist: Vec<Option<u32>> = otm.distances_from(s); // aligned with `targets`; None = unreachable
}

// Mirror image: distances from many fixed sources to a target.
let mut mto = CCHManyToOne::new(&metric, &sources);
let dist = mto.distances_to(target); // aligned with `sources`

Multi-source/-target variants with initial distance offsets are available (distances_from_multi, distances_to_multi). Note: batched queries return distances only (no path reconstruction), matching the underlying RoutingKit API.

Path Reconstruction

After run() -> CCHQueryResult:

  • CCHQueryResult::distance() -> Option<u32> (None = unreachable)
  • CCHQueryResult::node_path() -> Vec<node_id> (empty = unreachable)
  • CCHQueryResult::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 / partial-update
CCHQuery yes no Internal mutable labels; reuse it within thread
CCHQueryResult yes no Runned state of CCHQuery, actually &mut of it
CCHOneToMany yes no Internal mutable labels; reuse it within thread
CCHManyToOne yes no Internal mutable labels; reuse it within thread
CCHMetricPartialUpdater no no Should have nothing to do with parallel

Create separate queries per thread for parallel batch querying.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

routingkit_cch-0.1.4.tar.gz (185.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

routingkit_cch-0.1.4-cp39-abi3-win_amd64.whl (233.6 kB view details)

Uploaded CPython 3.9+Windows x86-64

routingkit_cch-0.1.4-cp39-abi3-musllinux_1_2_x86_64.whl (7.1 MB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ x86-64

routingkit_cch-0.1.4-cp39-abi3-musllinux_1_2_aarch64.whl (6.8 MB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ ARM64

routingkit_cch-0.1.4-cp39-abi3-manylinux_2_34_x86_64.whl (417.6 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.34+ x86-64

routingkit_cch-0.1.4-cp39-abi3-manylinux_2_34_aarch64.whl (403.6 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.34+ ARM64

routingkit_cch-0.1.4-cp39-abi3-macosx_11_0_arm64.whl (347.6 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

routingkit_cch-0.1.4-cp39-abi3-macosx_10_12_x86_64.whl (359.8 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file routingkit_cch-0.1.4.tar.gz.

File metadata

  • Download URL: routingkit_cch-0.1.4.tar.gz
  • Upload date:
  • Size: 185.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.14.1

File hashes

Hashes for routingkit_cch-0.1.4.tar.gz
Algorithm Hash digest
SHA256 32fcf13cd645884fb05f13508c33336218d78e832db2affe8671d0ac2874cc52
MD5 70c2a159b2592e27052f183cebae2949
BLAKE2b-256 3dd334e30b48d62b273a2a01a1727eff7456b75ab9456dac3a5fbd746360ceeb

See more details on using hashes here.

File details

Details for the file routingkit_cch-0.1.4-cp39-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for routingkit_cch-0.1.4-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 b76918129b99bf5e7ec805dabd2199f8faa5c6e9544bba89a3779b66f748a7bf
MD5 c776621991df9dc1a3dee862ba4131bf
BLAKE2b-256 8800aa1151951038f93bddb7dc0bca5a2876709e1423d8a3309fc950272a1234

See more details on using hashes here.

File details

Details for the file routingkit_cch-0.1.4-cp39-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for routingkit_cch-0.1.4-cp39-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 efa6673a0fda1059cb67e5fc7ed2772c371cb3d9dfac3cb4b7e75289dc3c988d
MD5 d9da5088bcee2c0dc0ddd3aa2d39a77b
BLAKE2b-256 81046182eef4302d8f09c3369a432d2d4bf069dd2b088c87e20369de60e6bd26

See more details on using hashes here.

File details

Details for the file routingkit_cch-0.1.4-cp39-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for routingkit_cch-0.1.4-cp39-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 2c9859317da14b0d36175a06dddaaeaa262debca6e120a0e57d420c986fc978c
MD5 668e2f41c8888929ef8117e8394e1def
BLAKE2b-256 74548c4566810b89dd6919efab387d18c8697a2274fd1ebcb23fe89b40fc22fa

See more details on using hashes here.

File details

Details for the file routingkit_cch-0.1.4-cp39-abi3-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for routingkit_cch-0.1.4-cp39-abi3-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 f78f3e5c089ccd30715833c396f23d3607f8f5790180ae9769525e7de1274e40
MD5 62e4b67f2591320975c86cefe8de73db
BLAKE2b-256 28e3b2e6c41f3e5b2fff150734ddc61dfb9ce74573a4955dbe07c6fb8439ee0d

See more details on using hashes here.

File details

Details for the file routingkit_cch-0.1.4-cp39-abi3-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for routingkit_cch-0.1.4-cp39-abi3-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 c2f91fdd3d11d5b891eb5a3f6d52686223d7a4c97222f7ed916ed63789b36e75
MD5 f42fa206209de7d8916dc44b938d729f
BLAKE2b-256 878188beb276c796a884eef9157ddef8910ab45be8adce2cc3a101c0ce250842

See more details on using hashes here.

File details

Details for the file routingkit_cch-0.1.4-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for routingkit_cch-0.1.4-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a0ffeed0458046ec241b2de0035d25034cb09d5df5064ce5092c594be2b105a1
MD5 4530edcd589125285b7dee73c2d847df
BLAKE2b-256 b4f1449c6eb137d7cd03e6f8412b69ab1f4503e436a739c6002f69bea7c6bcb6

See more details on using hashes here.

File details

Details for the file routingkit_cch-0.1.4-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for routingkit_cch-0.1.4-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 7bc4a6d92f33d700d56139f0fa1148489ef376e3ecfe6010158ed03df8f29161
MD5 5b7525910eb1193e663bc9d9ac61809f
BLAKE2b-256 7d7d4a0a6da127cb8a2aa395ba4a6c061e40d860aeeb2098a7bcf7d206562e75

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page