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;