Skip to main content

hyperpaths_rs/
lib.rs

1//! Implementation of Spiess, H. and Florian, M. (1989) "Optimal strategies:
2//! A new assignment model for transit networks".
3//! See the ref. at spiess_floarian.tex LaTeX file.
4//!
5//! # Two API tiers
6//!
7//! The same algorithm is offered through two interfaces; they produce
8//! identical results, pick by use case.
9//!
10//! 1. Simple string API - [`compute_sf`], [`find_optimal_strategy`],
11//!    [`assign_demand`]. Nodes are `&str` names, the OD is
12//!    `HashMap<origin, HashMap<dest, f64>>`, and results come back as
13//!    string-keyed maps ([`Strategy::labels`], [`Volumes::links`]). One call,
14//!    nothing to set up. This is the reference / debugging path: it is the
15//!    easiest to read, and setting [`VERBOSE`] to `true` prints a step-by-step
16//!    trace of both phases. Internally it already uses the same integer arena
17//!    as the fast path, so a single solve is fast. Use it for one-off or
18//!    single-destination solves, small networks, debugging.
19//!
20//! 2. Arena API - [`Graph`], [`Workspace`], [`Workspace::assign`],
21//!    [`Workspace::solve_each`]. [`Graph::new`] interns the network into an
22//!    immutable integer arena once; a [`Workspace`] holds reusable buffers so
23//!    each destination is assigned with no further allocation, and results are
24//!    returned in integer (arena) indexing. Use it for assigning many
25//!    destinations, large networks, and multi-threaded services. On a full
26//!    assignment (every stop a destination) it is roughly an order of magnitude
27//!    faster than calling [`compute_sf`] per destination, and allocation-free
28//!    once the workspace is warm.
29//!
30//! # Concurrency
31//!
32//! A [`Graph`] is immutable and `Sync`, so it can be shared across threads by
33//! shared reference; a [`Workspace`] is mutated through `&mut self`, so the
34//! borrow checker guarantees each thread uses its own. Build the graph once and
35//! give each thread its own workspace (see the example on [`Graph`]). The
36//! [`DestResult`] returned by `assign` / `solve_each` borrows the workspace and
37//! is reused on the next call, which the borrow checker also enforces.
38
39mod demand;
40mod hyperpath;
41mod hyperpath_queue;
42mod solver;
43mod spiess_floarian;
44mod transit_network;
45
46#[cfg(test)]
47mod golden_test;
48
49/// Synthetic-network helpers shared by the unit tests and the `bench` example.
50/// Not part of the shipped API: compiled only under `cfg(test)` or the
51/// `testutil` feature.
52#[cfg(any(test, feature = "testutil"))]
53pub mod testutil;
54
55pub use demand::{Volumes, assign_demand};
56pub use hyperpath::{Strategy, VERBOSE, find_optimal_strategy};
57pub use solver::{DestResult, Graph, Workspace};
58pub use spiess_floarian::{SFResult, compute_sf};
59pub use transit_network::Link;