Constraints define the feasible graph
A mobility graph G = (V, E) stores public-path nodes and directed connections across floors. Each node carries a map ID, longitude, latitude and optional floor. Each edge carries length, travel mode, indoor and shelter flags, accessibility attributes and an optional facility ID. A bidirectional edge contributes one arc in each direction.
The query context contains endpoints s, t, user constraints u, objective o, weather w and the events active at time τ. A blocking policy excludes an edge; each remaining policy contributes a finite, nonnegative penalty.
An event without an expiry has end(a) = ∞.
Hard constraints
Policies check step-free access, slope and width limits, opening times, facility closures and explicit exclusions. Strict accessibility mode also rejects unknown accessibility attributes and missing dimensions required by the query.
Event overlays
Events target facility IDs or edge IDs. The planner constructs a fresh adjacency list for each query, so closures and restorations leave the stored base graph intact.
Exposure takes priority when the objective requires it
For sheltered routing, the primary weight counts outdoor distance without shelter. For indoor routing, it counts all outdoor distance. Other objectives use a zero primary weight. The secondary weight combines an objective-dependent base cost with policy penalties.
| Objective | Primary weight |
|---|---|
| Sheltered | Edge length if outdoor and uncovered; zero otherwise. |
| Indoor | Edge length if outdoor; zero otherwise. |
| Balanced, shortest, least effort, fastest | Zero. |
The base cost bo is edge length, except that fastest mode uses estimated traversal and waiting time. Policy penalties depend on the objective: shortest mode suppresses soft penalties; least-effort mode increases stair, escalator and slope penalties. The fastest score combines time with policy penalties. It therefore expresses a routing preference score. Balanced mode switches to sheltered ordering when rain or a covered-route preference applies.
Lexicographic order compares the first component, then breaks ties with the second. Every edge weight has nonnegative components.
A priority queue orders two-component path labels
Algorithm 1 Policy-Constrained Lexicographic Dijkstra
Input: Graph G, endpoints s, t, context (u, o, w, Aτ).
Output: A feasible node / edge sequence, or no_route with policy reason codes.
- Build adjacency over Eτ; attach weights (qo, co) to each arc.
- Set D[v] ← (∞, ∞) and pred[v] ← ∅ for every node.
- Set D[s] ← (0, 0); push (D[s], s) into min-heap Q; settled ← ∅.
- while Q is nonempty do
- (d, v) ← extract-minlex(Q).
- if v ∈ settled or d ≠ D[v] then continue.
- if v = t then break; otherwise add v to settled.
- for each feasible outgoing arc e = (v, z) do
- d′ ← D[v] + (qo(e), co(e)).
- if d′ <lex D[z] then
- D[z] ← d′; pred[z] ← (v, e); push (d′, z) into Q.
- if D[t] = (∞, ∞) then return
no_route. - Backtrack pred from t to s; aggregate distance, metrics, reasons and warnings.
- return the reconstructed route.
The binary heap avoids a linear scan of unsettled nodes. On the stored mobility graphs, search takes O((|V| + |E|) log |V|). Context changes trigger a fresh search from the current anchor; the session retains completed journey stages.
Route outputs retain policy decisions
The route returns node IDs, edge IDs, distance, preference cost, exposure and time metrics, policy reasons and data-quality warnings. A segmentation pass converts its edge sequence into floor, transition, bridge and outdoor instructions.
- Search and multi-objective route generation ↗
shared/routing/route.ts - Accessibility, event and weather policies ↗
shared/routing/policies.ts - Travel-time estimates and route metrics ↗
shared/routing/metrics.ts - Path segmentation ↗
shared/journey/segment.ts