# Implementation Roadmap The tier-1 canon (64 must-implement references from [REFERENCES.md](REFERENCES.md)), staged by version. Checked items ship in the current release (v0 also ships MSA and all-or-nothing as baselines). Version staging: **v0** core harness + link-based solvers -> **v0.x** accelerated FW, logit SUE, Anaheim/Barcelona/Winnipeg rungs (this release; plugin registry and profiles still open) -> **v1** bush-based solvers, SUE variants, static extensions, T2 estimation track -> **v2** DTA, network loading, engine adapters, day-to-day, T3 interventions. ## Foundations — v0-v1 (formulations underpin metrics) - [x] Wardrop (1952) — *Some Theoretical Aspects of Road Traffic Research* (metric/protocol) — **shipped in v0** (equilibrium conditions in the certified gap) - [x] Beckmann et al. (1956) — *Studies in the Economics of Transportation* (white-box solver) — **shipped in v0** (Beckmann objective in metrics) - [x] Bureau of Public Roads (1964) — *Traffic Assignment Manual* (network-loading component) — **shipped in v0** (BPR link performance function (Network.link_cost)) - [x] Dafermos (1972) — *The Traffic Assignment Problem for Multiclass-User Transportation Networks* (white-box solver) — **shipped** as `multiclass` (adr-013) - [ ] Smith (1979) — *The Existence, Uniqueness and Stability of Traffic Equilibria* (metric/protocol) - [x] Dafermos (1980) — *Traffic Equilibrium and Variational Inequalities* (white-box solver) — **shipped** as `vi-asym` ## Link-based UE algorithms — v0 (FW, MSA) / v0.x (CFW, BFW) - [x] Frank & Wolfe (1956) — *An Algorithm for Quadratic Programming* (white-box solver) — **shipped in v0** (Frank-Wolfe solver) - [x] LeBlanc et al. (1975) — *An Efficient Approach to Solving the Road Network Equilibrium Traffic Assignment Problem* (white-box solver) — **shipped in v0** (Frank-Wolfe solver) - [x] Boyce et al. (2004) — *Convergence of Traffic Assignments: How Much Is Enough?* (metric/protocol) — **shipped in v0.x** (convergence target protocol (Budget.target_relative_gap)) - [x] Mitradjieva & Lindberg (2013) — *The Stiff Is Moving—Conjugate Direction Frank-Wolfe Methods with Applications to Traffic Assignment* (white-box solver) — **shipped in v0.x** (conjugate and bi-conjugate FW solvers) ## Path/bush-based UE algorithms — v1 - [x] Jayakrishnan et al. (1994) — *A faster path-based algorithm for traffic assignment* (white-box solver) — **shipped in v1** (path-based gradient projection solver (gp)) - [x] Bar-Gera (2002) — *Origin-based algorithm for the traffic assignment problem* (white-box solver) — **shipped** as `oba` (origin-based M/D-label proportion solver) - [x] Dial (2006) — *A path-based user-equilibrium traffic assignment algorithm that obviates path storage and enumeration* (white-box solver) — **shipped in v1** (Algorithm B bush-based solver (algb)) - [x] Bar-Gera (2010) — *Traffic assignment by paired alternative segments* (white-box solver) — **shipped in v1** (TAPAS paired-alternative-segment solver (tapas) + proportionality diagnostic (ADR-004)) ## Stochastic UE & route choice — v0.x (Dial, logit-SUE MSA) / v1 (probit) - [x] Dial (1971) — *A probabilistic multipath traffic assignment model which obviates path enumeration* (network-loading component) — **shipped in v0.x** (STOCH loading map (models/_stoch.py)) - [x] Daganzo & Sheffi (1977) — *On stochastic models of traffic assignment* (white-box solver) — **shipped in v1** (SUE definition underlying the probit task) - [x] Fisk (1980) — *Some developments in equilibrium traffic assignment* (white-box solver) — **shipped in v0.x** (logit SUE task (fixed-point certificate, ADR-001)) - [x] Powell & Sheffi (1982) — *The convergence of equilibrium algorithms with predetermined step sizes* (white-box solver) — **shipped in v0.x** (MSA-SUE solver step sizes) - [x] Sheffi & Powell (1982) — *An algorithm for the equilibrium assignment problem with random link times* (white-box solver) — **shipped in v1** (probit SUE solver (sue-probit-msa) + MC certificate (ADR-003)) ## System optimum & pricing — v1 - [x] Yang & Huang (1998) — *Principle of Marginal-Cost Pricing: How Does It Work in a General Road Network?* (white-box solver) — **shipped in v1** (first-best marginal-cost tolls (metrics.so)) - [x] Roughgarden & Tardos (2002) — *How Bad Is Selfish Routing?* (metric/protocol) — **shipped in v1** (price-of-anarchy protocol + certified SO gap) ## Static extensions — v1 - [x] Florian & Nguyen (1974) — *A Method for Computing Network Equilibrium with Elastic Demands* (white-box solver) — **shipped in v1** (elastic (variable) demand UE task/problem (ADR-005)) - [x] Evans (1976) — *Derivation and analysis of some models for combining trip distribution and assignment* (white-box solver) — **shipped** as `evans` (ADR-007) - [x] Mahmassani & Chang (1987) — *On Boundedly Rational User Equilibrium in Transportation Systems* (route-choice component) — **shipped** as `br-ue` (indifference-band relaxation, ADR-008) - [x] Spiess & Florian (1989) — *Optimal strategies: A new assignment model for transit networks* (white-box solver) — **shipped** as `transit-strategy` (adr-014, parallel `transit/` module) - [x] Larsson & Patriksson (1995) — *An augmented Lagrangean dual algorithm for link capacity side constrained traffic assignment problems* (white-box solver) — **shipped** as `sc-tap` (ADR-009) ## Analytical DTA — v2 - [x] Vickrey (1969) — *Congestion Theory and Transport Investment* (white-box solver) — **shipped** as `vickrey` (adr-019, the first departure-time equilibrium — a parallel `bottleneck/` module with a closed-form UE/SO and a P1 certifier that recomputes the point queue + generalized costs from the emitted departure curve; `equilibrium_gap=0` for the UE, PoA=2) - [x] Merchant & Nemhauser (1978) — *A Model and an Algorithm for the Dynamic Traffic Assignment Problems* (white-box solver) — **shipped** as `merchant-nemhauser` (adr-020, the first network DTA model — a parallel `dta/` module: exit-function scenario, Carey(1987)-relaxed canonical LP with terminal clearance, and a P1 certifier that recomputes conservation/node-balance/exit-bounds/cost, resolves the LP optimum harness-side, and arithmetically verifies emitted LP-duality certificates; two hand-derived anchors incl. one where holding back is strictly optimal) - [x] Friesz et al. (1993) — *A Variational Inequality Formulation of the Dynamic Network User Equilibrium Problem* (white-box solver) — **shipped** as `vi-due` (adr-022, the simultaneous route-and-departure-time DUE closing the analytical-DTA track — the Friesz VI instantiated with generalized-Vickrey point-queue loading on parallel routes: exact closed form C=(δN+αΣs·f)/Σs with greedy used-set, single-route f=0 reduction certified by the adr-019 BottleneckEvaluator at 1e-13, and a P1 `DUEEvaluator` whose marginal-insertion reference scan catches the all-on-one-route false equilibrium the single-route certifier cannot see) - [x] Ziliaskopoulos (2000) — *A Linear Programming Model for the Single Destination System Optimum Dynamic Traffic Assignment Problem* (white-box solver) — **shipped** as `lp-so-dta` (adr-021, cell-level SO-DTA with finite storage/spillback — the CTM min-flux relaxed to four linear families over `CellSODTAScenario`; hand-derived diverge/spillback anchor J*=26 via the storage pair lemma, holding-on-the-optimal-face demonstrated, and the corridor LP == the repo's own `CTMLink` loading exactly; P1 `CellSODTAEvaluator` with the adr-020 hardening + LP-duality certificates) ## Dynamic network loading — v2 - [x] Newell (1993) — *A simplified theory of kinematic waves in highway traffic, part I: General theory* (network-loading component) — **shipped** as `newell-3det` (adr-024, the interior minimum-principle three-detector reconstruction — the benchmark's FIRST traffic-state-estimation task: given noisy/partial boundary detector curves, reconstruct the interior cumulative field `N(x,t) = min(N_up(t−x/vf), N_dn(t−(L−x)/w) + κ(L−x))` at a fixed hashed query grid, scored against the harness-regenerated closed-form min. Newell's LOADING content — the minimum principle at the link ENDS — already shipped as `ltm` (adr-016), so this ships the unshipped INTERIOR content, NOT a third `LinkModel`; the oracle and certifier are the paper's minimum principle, the observation dials are the repo's own P3 conventions (the paper contains no estimation numerics), and the clean level is an oracle row (ranking lives on the noisy levels where the naive/isotonic pair discriminates)) - [x] Daganzo (1994) — *The cell transmission model: A dynamic representation of highway traffic consistent with the hydrodynamic theory* (network-loading component) — **shipped** as `ctm` (adr-015, the first DNL `LinkModel` on the dnl-core; Godunov cell dynamics at CFL=1, free-flow translation bit-exact + RH shock/spillback anchors) - [ ] Daganzo (1995) — *The cell transmission model, part II: Network traffic* (network-loading component) - [x] Lebacque (1996) — *The Godunov scheme and what it means for first order traffic flow models* (network-loading component) — **shipped** as `godunov` (adr-018, `GodunovLink` + `GreenshieldsFD`; the general-FD Godunov scheme on the first non-triangular FD — the first rarefaction physics in the benchmark, CTM being its triangular special case) - [x] Yperman (2007) — *The Link Transmission Model for dynamic network loading* (network-loading component) — **shipped** as `ltm` (adr-016, the second DNL `LinkModel`; stateless Newell-Daganzo cumulative-curve method, matches CTM byte-for-byte on aligned grids + runs on non-cell-aligned grids CTM rejects) - [x] Tampère et al. (2011) — *A generic class of first order node models for dynamic macroscopic simulation of traffic flows* (network-loading component) — **shipped** as `node-model` (adr-017, `TampereNode`; the general merge/diverge solver — oriented-capacity-proportional with FIFO, satisfies node axioms N1–N6 — that unlocks network loading for `ctm`/`ltm`) ## Simulation-based DTA & software — v2 (adapters) - [ ] Jayakrishnan et al. (1994) — *An evaluation tool for advanced traffic information and management systems in urban networks* (black-box wrapper) — **adapter path deferred ([adr-030](design/adr-030-external-dta-simulators-deferred.md))**: FHWA DYNASMART-P is McTrans/FHWA-licensed with no public artifact, which bars a public CI row; the Peeta & Mahmassani (1995) white-box SO/UE time-dependent row below needs no binary and stays live - [x] Peeta & Mahmassani (1995) — *System optimal and user equilibrium time-dependent traffic assignment in congested networks* (white-box solver) — **shipped** as `pm-td-ue` / `pm-td-so` (parallel `tdta/` module, [adr-031](design/adr-031-peeta-mahmassani.md)): the first iterative, simulation-based time-dependent route-choice equilibrium in the benchmark — fixed-departure TD-UE and its TD-SO twin, MSA over an enumerated per-OD path set, the repo's own CTM/LTM loading substituted for the licensing-deferred DYNASMART (adr-030) as the constraint evaluator. `TDPathFlows` carries only the decision variable (per-path, per-departure-interval flow); the harness reruns its own per-path loading (a private first link per path + `TampereNode` merges, on an interior-diverge-free topology that keeps per-commodity experienced times exactly decidable) and scores `tdue_gap` (the experienced-time route-swap residual, 0 iff the discrete Wardrop conditions hold) and `so_bound_gap` (`(TSTT − Z*)/Z*` against the `lp-so-dta` LP optimum on the CTM-cell instance derived from the same grid). Anchors derived from scratch (the paper's 50-node DYNASMART numerics are engine-bound/irreproducible): a single-path corridor whose loaded TSTT equals the ADR-021 `zil_corridor` optimum 33 exactly through the new code path, a symmetric diamond whose exact TD-UE certifies `tdue_gap=0` (all-on-one control 0.75), an SO≠UE wedge where the SO split attains the LP bound and beats UE TSTT (23 < 24 — the paper's headline made executable), a merge for attribution, `ltm==ctm`, and the aggregate loader passing `dnl_gaps` C0–C8. Primary READ IN FULL (a first for a DTA row); the MSA solvers are non-certified (the certifier arbitrates). Single class, fixed departures, NOT rolling-horizon (reserved for the TR-C sibling) - [ ] Ben-Akiva et al. (2001) — *Network State Estimation and Prediction for Real-Time Traffic Management* (black-box wrapper) — **deferred ([adr-030](design/adr-030-external-dta-simulators-deferred.md))**: no public DynaMIT artifact exists to adapt (historically distributed by the MIT ITS Lab on request; the successor SimMobility is public but SPDX `NOASSERTION`) — artifact-blocked until upstream publishes one - [x] Zhou & Taylor (2014) — *DTALite: A queue-based mesoscopic traffic simulator for fast model evaluation and calibration* (black-box wrapper) — **shipped** as `dtalite-tap` (the second external engine; behind the optional `DTALite` extra, guarded-imported so the numpy/scipy core stays dependency-free, with a fifth CI job pinning `DTALite==0.8.1`): the PyPI `DTALite` wheel's static Frank-Wolfe `assignment()` (a Bar-Gera `FW.zip`-derived *TAPLite* loop, NOT the 2014 paper's mesoscopic queue DUE, which is the separate `simulation()` entry — now shipped on the observational track as `dtalite-simulation`, adr-040), wrapped by compiling a fixed-demand scenario into GMNS CSVs (`dtalite_tap.py`) whose per-link `vdf_fftt/vdf_alpha/vdf_beta` map the repo BPR `t = fft·(1 + b·(v/cap)^power)` **EXACTLY** — the compile map is the *identity*, so unlike marouter there is no mapping floor and BPR `power=4` encodes directly. The emitted flows are certified under the declared BPR (P1): Braess `relative_gap ≈ 1.2e-2` and Sioux Falls power-4 `≈ 5.0e-3`, both frozen at the engine's Armijo line-search stall (the honest ceiling — the wheel-engine-as-shipped, not the mapping; a converged `bfw` beats it by orders of magnitude), with a MANDATORY cost-matched anchor proving the engine's own `travel_time` equals the repo BPR at the emitted flows on every link (max relative ~2e-5, the identity map's payoff). **The first external engine on the power-4 ladder** (Sioux Falls, the marquee — marouter's linear vdf refused it). The subprocess wrapper is mandatory (the engine's `ExitMessage` does `getchar()`+`exit()` in-process — a bad input would hang or kill the host — and a second call in one process doubles the flows), the module never `import`s `DTALite` at scope (banner + in-host OpenMP load), and a read-back verifies the engine parsed every VDF parameter as declared (`returncode==0` is never trusted — the engine exits 0 on missing/garbage input). Refused traps named by field: tolls (unvalidated `vot` conversion), `sue_theta`/elastic/combined/br/side-cap/link-interaction/multiclass, and an `sp_calls`-only budget. `zhou2014dtalite` anchors the software lineage (tool-paper discipline, the lopez2018 precedent) — the row validates ADAPTER + engine fidelity, never the paper's numerics (ADR-029). **A SECOND DTALite row now ships from the same wheel** — `dtalite-simulation`, the third **EDOC-1** external-dynamic observational row ([ADR-036](design/adr-036-external-dynamic-observational-certificate.md) certificate + [ADR-040](design/adr-040-dtalite-simulation.md) row, closing the `simulation()` honest-sourcing loop and the first **deterministic-track** external row): the 2014 paper's actual mesoscopic queue-DNL `simulation()` (Zhou & Taylor 2014), a sub-second `vehicle.csv → trajectory.csv` map where there is no declared cost law, so the engine IS the instance and the certifier re-derives the score by re-running the pinned `OMP_NUM_THREADS=1` engine on the model's emitted MSA plans (G1 replay fidelity, byte-exact on `trajectory.csv`). It scores the **frozen-field best-response gap `RG_D1`** (shipped estimator, 2026-07-17: converged 0.05031 vs the step-0 Frank-Wolfe split 0.37224, **7.40× floor-displayed separation** — declared ≥ 5×), which is **NOT** the Wardrop `relative_gap` of `dtalite-tap` (same wheel, different engine) nor of `sumo-marouter`, and lives on the **same separate EDOC leaderboard table** as the other observational rows (R8 non-comparability). The engine re-seeds an LCG per time step so it consumes no seed (`seedable=False`, `seed_list=()`, no macroreps — the deterministic track, disclosed); byte-determinism pinned on linux-x86_64. Its tutorial notebook ships with the `11-external` tutorials track (`06-dtalite-simulation.ipynb`). **A THIRD DTALite row now ships from the same wheel** — `odme-dtalite`, a **guarded static T2 ESTIMATOR** ([ADR-042](design/adr-042-odme-dtalite.md)): the wheel hides an Origin-Destination Matrix Estimation routine (`performODME`) INSIDE the same static `assignment()` entry `dtalite-tap` wraps (it fires when `settings.csv` carries `odme_mode=1`), a gradient-descent OD calibrator that re-weights the base assignment's route-flows to match sensor `obs_volume` counts. It ships as a guarded estimator in `ESTIMATOR_REGISTRY` riding the EXISTING pinned-`bfw` `ODCertifier` **UNCHANGED** (the adr-028 zero-certifier-change ideal, the `spsa-sumo` precedent — emit an OD, the model-blind certifier re-assigns it under the declared BPR; zero task/runner/certifier changes). Marquee (measured, siouxfalls power-4, sensors cov 0.5 / stale prior cv 0.3): the certifier reports `obs_count_rmse` 994.8→365.3 (0.37×) and the ranking `heldout_count_rmse` 816.5→556.6 (0.68×) over the prior baseline, with the ODME descent running 69 gradient iterations (a real "estimator beats prior" row, not a no-op). The engine envelope is disclosed as a pinned-0.8.1 identity (the marouter-vdf precedent): `route_output=1` is REQUIRED (with the lean `route_output=0` the ODME reconstruction collapses and inflates the OD +40 %, measured — the non-obvious pilot finding); a hardcoded `[0.5,1.5]×`-of-(seed,target) recovery box (`demand_target_frac` is a documented one-sided widening dial); hardcoded penalty weights + an ABSOLUTE `tol=1` convergence floor (so the marquee MUST be Sioux-Falls-scale, not Braess, to clear it); and `link_performance.csv` is CORRUPTED under `odme_mode=1`, so the OD is sourced EXCLUSIVELY from `od_performance.csv` (never the T1 adapter's `odme_mode=0` cost-match/mass gates). Anti-laundering holds by construction (the certifier reads only the emitted OD, never DTALite's rosy self-report — measured self 8 vs certified 365, the engine-in-the-loop bias). Single-mode demand-only (multiclass ODME via `mode_type.csv` deferred); additive, golden Braess hash `cf00f411…` byte-identical; rides the existing `dtalite` CI job. Its tutorial notebook ships with the `03-estimation` track (`09-odme-dtalite.ipynb`). - [x] Horni et al. (2016) — *The Multi-Agent Transport Simulation MATSim* (black-box wrapper) — **shipped** as `matsim` (the third external engine and the second **EDOC-1** observational row — [adr-036](design/adr-036-external-dynamic-observational-certificate.md) certificate / [adr-039](design/adr-039-matsim.md) row, superseding the adr-030 deferral): the **first agent-based, first stochastic-track** external engine. The adr-030 blocker stands in its own terms — QSim has NO static latency function, so the A2 cost-matched anchor stays impossible **in kind**; A2's role is instead played by the pinned engine itself under **G1 replay fidelity** (`lastIteration = firstIteration` on the emitted plans is a zero-replanning replay), and the certifier re-derives the **frozen-field best-response gap `RG_D1`** entirely from its own replay events (per-link flows from entered-link + vehicle-enters-traffic events; `output_links.csv` is never a flow source — it undercounts the arrival link to zero, measured). Java-only engine with **no pip extra** (PyPI `matsim` is an unrelated neuronal simulator, adr-030): pinned `matsim-2025.0-release.zip` (md5 `c65f35ea…`) on Temurin **21.0.11+10**, addressed only via `TABENCH_MATSIM_HOME`/`TABENCH_JAVA_HOME`, with a dedicated CI job installing both against hard checksums (md5/sha256 verified before unzip). Scored on the **R5 stochastic track** — the P8 macrorep harness (`tabench.edoc.macrorep`) over the pinned 5-seed list, mean `RG_D1` + bootstrap CI; measured reference (shipped estimator, 2026-07-17): converged mean **0.0861** (CI **[0.071, 0.102]**) vs the deterministic AON control **0.4591** → **5.33×** displayed-value negative-control separation; `numberOfThreads=1` pinned in global/qsim/eventsManager — the same-timestamp event-tie permutation is a measured **multithreading** artifact (the corrected R10 record, adr-039), and the G1 hash is the tie-sorted canonical stream. **`RG_D1` is a frozen-field BR gap w.r.t. the engine's own frozen realized field, NOT the static Wardrop `relative_gap` — it lives on a separate leaderboard table (R8) and is never compared to the static rows.** Tutorial: `tutorials/11-external/05-matsim.ipynb` - [x] Lopez et al. (2018) — *Microscopic Traffic Simulation using SUMO* (black-box wrapper) — **shipped** as `sumo-marouter` (the first Phase-4 external-simulator adapter; behind the optional `eclipse-sumo` extra, guarded-imported so the numpy/scipy core stays dependency-free, with a fourth CI job pinning `eclipse-sumo==1.27.1`): SUMO's macroscopic `marouter` SUE assignment, wrapped by compiling a fixed-demand `power=1` scenario into a SUMO network (`_sumo_io.py`) whose edges match the repo BPR to machine precision on representable links — marouter's cost law is a *hardcoded* linear-in-flow class function (PTV-Validate / VISUM-Cologne, not the ITSC paper), so two representability floors are documented and measured (a forced intercept `eps=B·(200/6)/s` on zero-intercept links, a parasitic slope `A·K·s/C` on zero-slope links). The per-edge flows are certified under the *declared* BPR costs (P1): Braess `relative_gap ≈ 1.7e-4` (the analytic mapping floor), with a MANDATORY cost-matched anchor separating that floor from solver error. The certified row is act four of the accuracy-vs-certificate story — an industrially converged assignment, perfectly demand-feasible, that certifies a real small gap: the first number for the simulator-to-benchmark model gap practitioners implicitly set to zero (ADR-027). The refused traps are documented: marouter's `UE` silently falls back to SUE, its DEFAULT `incremental` is non-equilibrium, and BPR `power!=1` (Sioux Falls) is UNREPRESENTABLE in its linear vdf. **This overturns the earlier "cannot validate in CI" assumption** — the eclipse-sumo wheel ships the binaries inside the package, so the row is fully CI-validated. **A SECOND SUMO row now ships from the same wheel** — `sumo-duaiterate`, the first **EDOC-1** external-dynamic observational row ([ADR-036](design/adr-036-external-dynamic-observational-certificate.md) certificate + [ADR-037](design/adr-037-sumo-duaiterate.md) row, resolving the ADR-027 `duaIterate` deferral): SUMO's dynamic mesoscopic user-assignment driver `duaIterate.py`, where there is no declared cost law, so the engine IS the instance and the certifier re-derives the score by re-running the pinned engine in zero-replanning replay (G1) on the model's emitted plans. It scores the **frozen-field best-response gap `RG_D1`** (measured converged ≈ 0.02 vs an AON negative control ≈ 0.14, ~6.5× separation), which is **NOT** the Wardrop `relative_gap` of `sumo-marouter` and lives on a **separate leaderboard table** (R8 non-comparability). Its tutorial notebook ships with the `11-external` tutorials track. ## Day-to-day dynamics — v2 - [x] Horowitz (1984) — *The stability of stochastic equilibrium in a two-link transportation network* (white-box solver) — **shipped** as `dtd-horowitz` (the perceived-cost-*state* day-to-day model: travelers carry a perceived link-cost vector exponentially smoothed toward the experienced costs `p ← (1−w)p + w·t(v)` and logit-load at it via the pinned Dial-STOCH map, reaching the same logit-SUE fixed point as `sue-msa`/`dtd-swap-sue`; certified by the existing logit-SUE fixed-point residual (ADR-001, no new scenario field); uniquely among the day-to-day models NO damping is added, so above the task-dependent stability threshold `w* ≈ 0.81` the process settles into a period-2 limit cycle instead of converging — the very (in)stability Horowitz set out to study) - [x] Smith (1984) — *The stability of a dynamic model of traffic assignment — an application of a method of Lyapunov* (white-box solver) — **shipped** as `dtd-swap` (first day-to-day model) - [x] Cascetta (1989) — *A stochastic process approach to the analysis of temporal dynamics in transportation networks* (white-box solver) — **shipped** as `dtd-stochastic` (the benchmark's first genuinely *stochastic* day-to-day model: a finite-population Markov chain — each day `N_od = max(1, round(population_scale·d_od))` travelers per OD pair draw routes by multinomial sampling from the Dial-STOCH logit fractions at the exponentially smoothed perceived costs `p ← (1−w)p + w·t(v)`, driven by the *realized* daily flow, so "equilibrium" is the chain's stationary distribution, not a fixed point; daily flows keep a persistent `O(1/√N)` variability while the emitted burnt-in time average converges (ergodic theorem) to the stationary mean ≈ logit SUE (Davis & Nihan 1993 large-population limit); certified by the existing logit-SUE fixed-point residual (ADR-001, no new scenario field), which honestly floors at O(finite-population bias + sampling SE); `deterministic=False` routes it onto the existing macrorep stochastic track; the exponential filter is the canonical Cantarella & Cascetta (1995) special case of Cascetta's original m-day moving-average filter — a flagged, documented variant) - [x] Friesz et al. (1994) — *Day-to-day dynamic network disequilibria and idealized traveler information systems* (white-box solver) — **shipped** as `dtd-friesz` (route-flow-state day-to-day: the state is per-OD route flows evolved by the projected dynamical system `ḣ = P_K(h, −c(h))`, discretized by the Bertsekas & Gafni (1982) projection step `h_{k+1} = P_K(h_k − α c(h_k))`; because `∂Z/∂h_p = c_p` exactly for the Beckmann objective `Z`, this is projected gradient descent on Beckmann in *route* space, projecting the whole route-flow vector against today's frozen costs at once (Jacobi) via an exact Euclidean simplex projection that conserves each OD's demand every day; reaches the identical certified UE as the route-swap `dtd-swap` and the link-based `dtd-link` via the same monotone Beckmann descent, certified by the standard UE relative gap — no new scenario field) - [x] Cantarella & Cascetta (1995) — *Dynamic processes and equilibrium in transportation networks: towards a unifying theory* (white-box solver) — **shipped** as `dtd-unifying` (the unifying-theory node realized as a per-scenario mode gate: one two-equation process — exponential cost-learning filter `p ← (1−w)p + w·t(v)` plus choice update `v ← v + αₙ(ChoiceLoad(p) − v)` where a fraction `αₙ` of travelers reconsiders at the forecast costs — whose choice map is the all-or-nothing best response on deterministic scenarios (fixed point = Wardrop UE, annealed `α/n` step, standard relative-gap certificate) and the pinned Dial-STOCH logit load on SUE scenarios (fixed point = logit SUE, constant `α`, existing ADR-001 residual — no new scenario field); exact reductions regression-tested to float precision (stochastic `α=1` ≡ `dtd-horowitz`, deterministic `w=1, α=1` ≡ `msa`), and the re-derived joint `(α, w)` flip boundary `(2−w)(2−α) = αw|φ′|` confirms C&C's headline on the anchor: `(1,1)` period-2 limit-cycles while *either* form of inertia — cost memory or choice inertia — restores convergence, reducing at `α=1` to `dtd-horowitz`'s documented `w* ≈ 0.81`) - [x] He et al. (2010) — *A link-based day-to-day traffic assignment model* (white-box solver) — **shipped** as `dtd-link` (link-flow-state day-to-day: the state is the aggregate link-flow vector, adjusted toward the frozen-cost proximal target projected onto the feasible link polytope; reaches the identical certified UE as the route-swap `dtd-swap` via the same monotone Beckmann descent) - [x] Smith & Watling (2016) — *A route-swapping dynamical system and Lyapunov function for stochastic user equilibrium* (white-box solver) — **shipped** as `dtd-swap-sue` (logit-SUE sibling of `dtd-swap`: the same proportional route-swap day-to-day dynamics driven by the Fisk-generalized cost `c_k + (1/θ) ln h_k`, so the rest point is the logit stochastic user equilibrium (Fisk 1980), not deterministic UE; certified by the existing logit-SUE fixed-point residual (ADR-001, no new scenario field) with Fisk's SUE convex objective as the monotone day-to-day Lyapunov function) - [x] Li et al. (2024) — *Wardrop Equilibrium Can Be Boundedly Rational: A New Behavioral Theory of Route Choice* (white-box solver) — **shipped** as `dtd-cumlog` (the cumulative-logit model — the first boundedly-rational logit day-to-day process whose limit is *exact deterministic Wardrop UE* at a **finite** exploitation `r`, filling the empty cell in the shipped matrix where every other logit-choice day-to-day row rests at SUE: travelers carry a per-OD route-**valuation** vector `s` over column-generated working sets, choose by the logit map `p = softmax(−r s)`, and **accumulate** experienced route costs `s ← s + ηₜ c(p)` (Eq. 6) — the one-line change from the classical successive-average scheme `s ← (1−ηₜ)s + ηₜ c(p)` (Eq. 4, whose limit is the logit SUE) with a categorically different limit; the `accumulate` flag makes that Remark 3 contrast executable on one instance and identical machinery — accumulation drives the UE gap to ~0 (f_A → 2.5) while averaging rests at the analytic binary-logit SUE to 6 digits (f_A → 2.3739 at r=1); certified by the **standard UE relative gap** (fixed point = Wardrop UE, no new scenario field, golden Braess hash byte-identical); the harmonic schedule `ηₜ = 1/(t+1)` converges for **any** `r` (Theorem 1(i), asymptotically) while the constant schedule can diverge at a too-large step (preserved not damped) — Theorem 1(ii)'s `eta0 < 1/(2rL)` is sufficient-only and the reported `eta_heuristic_scale` is a flow-independent step-scale reference, not that bound; the divergent cumulative valuations resolve Harsanyi's instability — equal-cost WE routes carry unequal, finitely-differing valuations while dropped routes diverge — and its bounded rationality is **process-level** (the adjustment path is imperfect), disjoint from `br-ue`'s concept-level indifference band (ADR-038 vs ADR-008); the primary was **read in full**, the strongest sourcing in the dtd family) ## ML-based traffic assignment — v1 (baseline wrappers) - [x] Liu et al. (2023) — *End-to-end learning of user equilibrium with implicit neural networks* (black-box wrapper) — **shipped** as `implicit-ue-nn`, the first **torch** model (optional `[torch]` extra, ADR-025). A lean variant (the TR-C primary is paywalled/unread; formulation cross-verified from the authors' open hEART 2024 paper + two posters): a flow-monotone MLP cost head inside a differentiable logit route-choice fixed-point layer over PathEngine column-generated route sets, trained by an exact IMD/adjoint hypergradient on the synthetic-net family against bfw reference equilibria. Its emission `v = Δᵀh` is demand-feasible **by construction**, so it clears the audit the ridge surrogate is censored by (act two of ADR-006: feasibility is architectural, equilibrium quality is not) — bfw still certifies a better gap at matched budget, and the held-out identifiability caveat is documented honestly. Anchors: A1 Braess identity `(4,2,2,2,4)`/route time 92, A2 IMD hypergradient vs central FD `< 1e-5`, A4 feasible=1 at random θ. - [x] Rahman & Hasan (2023) — *Data-Driven Traffic Assignment: A Novel Approach for Learning Traffic Flow Patterns Using Graph Convolutional Neural Network* (black-box wrapper) — **shipped in v1** (learned-model wrapper + a ridge reference surrogate (not the GCN itself) certified by P1 (learned-surrogate, ADR-006)) - [x] Liu & Meidani (2024) — *End-to-end heterogeneous graph neural networks for traffic assignment* (black-box wrapper) — **shipped** as `het-gnn`, the second **torch** model (same optional `[torch]` extra, ADR-026), closing Phase 3. A lean variant (the TR-C primary is paywalled/unread; formulation cross-verified with zero discrepancies from arXiv:2310.13193v3 + the NSF PAR accepted manuscript, both read in full): hand-rolled heterogeneous message passing (V/R-Encoder segment-softmax attention over real + virtual OD edges, plain-torch scatter — no torch-geometric) with **size-agnostic node-kernel features** `[production, attraction, in/out-degree]` replacing the paper's non-permutation-equivariant `|V|+2` OD-row featurization (verified: 21.5 vs 1.1e-16 under relabeling — the property that lets one trained model transfer across graph sizes without the paper's dummy-node homogenization), an edge-MLP flow/capacity-ratio head, and the paper's composite loss `(1.0, 0.005, 0.05)` trained by plain backprop. Two harness-certified checkpoints: the paper-faithful **raw** emission (sp_calls=0) is **censored** — its conservation loss `L_c` *is* the L1 form of the harness `node_balance_residual`, 3–5 orders above tolerance (act three of ADR-006: soft conservation is not a constraint) — and a flagged **repo-extension route-decode** projects the raw flows onto the per-OD scaled-simplex product over `implicit-ue`'s column-generated routes, earning a real certified gap. Honest held-out (scoped in-family): `implicit-ue-nn`'s learned-cost fixed point certifies a better gap than the GNN-regression+projection at matched route sets, and a converged solver beats both. Anchors: A2 raw-censored + decoded-feasible, A4 permutation equivariance `1e-8`, decode-as-projection + no-limit-cycle, in-family loss reduction + conservation ablation. - [x] Xu et al. (2024) — *A unified dataset for the city-scale traffic assignment model in 20 U.S. cities* (data/scenario) — **shipped** as the cross-domain axis (ADR-033): 17 of 20 real US-city instances integrated download-on-demand (HTTP byte-range extraction of only the per-city AequilibraE trio from the CC-BY figshare zip; never vendored, per-file SHA-256), with Honolulu + San Francisco as CI-sized rungs. Shipped AS-PUBLISHED with the dataset's wrong-centroid defect documented (demand injected at node ids `1..Z`, not the tract centroids — the 3 excluded cities are named); the published AequilibraE flows are a **loose** reference (own gap ~1e-3), never a best-known oracle, and cross-solver TransCAD agreement is not claimed (the repo's own `bfw` gives cross-*implementation* agreement instead: Honolulu rgap 1.07e-4, correlation 0.99992). ## Data, estimation & benchmarking — v1 (T2 estimation track) - [x] Van Zuylen & Willumsen (1980) — *The most likely trip matrix estimated from traffic counts* (white-box solver) — **shipped in v1** (T2 entropy estimator (vzw-entropy, ADR-002)) - [x] Cascetta (1984) — *Estimation of trip matrices from traffic counts and survey data: A generalized least squares estimator* (white-box solver) — **shipped in v1** (T2 GLS estimator (gls, ADR-002)) - [x] Spiess (1990) — *A gradient approach for the O-D matrix adjustment problem* (white-box solver) — **shipped in v1** (T2 gradient OD adjustment (spiess, ADR-002)) - [x] Spall (1992) — *Multivariate stochastic approximation using a simultaneous perturbation gradient approximation* (white-box solver) — **shipped in v1** (T2 SPSA calibration baseline (spsa, ADR-002)) - [x] Yang et al. (1992) — *Estimation of origin-destination matrices from link traffic counts on congested networks* (white-box solver) — **shipped** as `od-congested` - [x] Cascetta et al. (1993) — *Dynamic Estimators of Origin-Destination Matrices Using Traffic Counts* (white-box solver) — **shipped** as `od-dynamic-sim` / `od-dynamic-seq` (adr-023, the within-day time-sliced OD estimator — the third leg of the T2 temporal triangle, distinct from `gls` (time = replication) and `od-kalman` (time = day-to-day noise): the estimand is the `(H, Z, Z)` departure-slice profile, recovered from time-sliced link counts linked by a frozen **exogenous** free-flow two-interval-split lag map `M[l]` (congestion feedback out of scope, `cascetta2001fixed`), via the paper's SIMULTANEOUS (all slices jointly, efficient) and SEQUENTIAL (slice-by-slice, earlier estimates frozen, online-capable but provably less efficient) GLS pair; a bfw-free EXACT linear certifier regenerates the full-network map from the hashed recipe and scores per-interval obs/held-out count RMSE (ranking = `heldout_count_rmse`) with descriptive OD/profile columns and an exact stacked-map identifiability report whose new edges are horizon truncation and cross-slice temporal confounding — the latter a genuinely new false-accept surface because held-out sensors share the lag structure; five hand-derived anchors including the fractional-lag instance where simultaneous strictly dominates sequential `(128/35, 142/35)` vs `(16/5, 94/25)` against truth `(4,6)` and a mean-collapse witness proving distinctness from `gls`; additive, golden Braess hash `cf00f411…` byte-identical) - [x] Balakrishna et al. (2007) — *Offline calibration of dynamic traffic assignment: Simultaneous demand-and-supply estimation* (black-box wrapper) — **shipped** as `spsa-sumo` (adr-028, the first guarded T2 estimator: a `SumoSPSAEstimator(SPSAEstimator)` whose inner assignment oracle is the shipped `sumo-marouter` adapter (adr-027) — a subprocess production engine, not the repo's own MSA — making the black-box simulator-in-the-loop calibration loop REAL and certified through the UNCHANGED pinned-bfw certifier (P1, zero task/runner/certifier changes; the certifier recomputes count-fit from the emitted OD regardless of which simulator produced it). Scope is **demand-only** on the unchanged `EstimationTask`: the paper's JOINT demand+supply title contribution is honestly **not shipped** (it changes what truth is, needs a new emitted artifact + certificate surface — an entire task-family ADR of its own), and the "DTA" of the title is the paper's *setting* (`marouter` is static, the within-day `duaIterate` analogue deferred; counts only, not speeds). `marouter` exposes no shortest-path count, so `sp_calls` is DISCLOSED as 0 via a `_sp_cost_per_eval()` hook (the fabricated-`sp_calls` trap) and an `sp_calls`-only budget is refused up front; one wall deadline threads all 2I+1 inner solves (a mid-loop engine RuntimeError aborts — crash discipline, never `feasible=0`); the P1 self-vs-certified honesty diff is reframed as the MEASURED simulator-in-the-loop bias (SPSA descends `marouter`'s mapped law, the certificate re-assigns under the declared BPR — the same ORDER as the ~1.7e-4/5.4e-4 mapping floor, not a hard bound), never estimator dishonesty. Demand is box-projected in BOTH the thesis's evaluation step (parent-loop `_project`, so emitted==evaluated==in-box: the P1 fix a three-lens review confirmed) and the iterate step (`_project_log`, no frozen corner), via identity hooks that leave the `spsa` row byte-identical. 13 two-route-only tests (pinned-seed clean-count recovery with a loose improves-on-prior bound, a poisson negative-control disclosing that anchor's noise fragility, delegated power/toll refusals, bit-reproducibility + macrorep divergence, wall-kill, the box-binding regression that fails under a clip-removal mutation, sparse checkpointing); `spsa.py` gains three behavior-identical hooks, `cli.py` passes T2 iterations/wall_seconds through; additive, golden Braess hash `cf00f411…` byte-identical). **The JOINT demand+supply title contribution is DEFERRED on a measured NEGATIVE** — [ADR-043](design/adr-043-bo4mob-joint-estimation.md), an **ADR-only measured-deferral / under-identifiability record** (the adr-030 precedent) on the BO4Mob D2 track: a sprint that set out to design+validate a separated-evidence joint certificate found, and independently reproduced, that the **joint `(demand, supply)` estimand is UNDER-IDENTIFIED from counts+speeds**. On congested `3junction` the naive "supply→speed, demand→counts" physical separation is **REFUTED** (every meso knob moves counts — `tauff` rel-L2 0.47; a demand error moves speeds ~2 mph mean / ~25 mph max), so BOTH observables are moved by BOTH estimands. The decisive reverse launder: a **substantially wrong supply** (`tauff=0.90`, ~20% off) with **tuned demand** (`od=0.95`) fits both channels to `max(count,speed)=0.0522` (control at true OD/default supply reproduces `max=0.0000`) — a third of the 0.155 an earlier draft mis-read as an "irreducible margin" over the supply axis alone (RETRACTED: that 0.155 was a single 1-D slice, not the estimator's `(OD,supply)` move set). "Report both NRMSE channels, never combine" is thus **necessary but NOT sufficient** — a low pair does not imply correct demand OR correct supply, and `heldout_speed_nrmse` is a jointly-observed speed-fit column, not separated supply evidence. The scored row is **DEFERRED** (not authorized); the named unblocker is **supply evidence taken where demand does not leak into speed** — off-peak/uncongested-window speeds, a free-flow-speed measurement, or a supply-known controlled sub-instance — each **UNMEASURED**, requiring its own pilot. The design SUBSTRATE (composition/type-gate task, two-channel non-combining certifier, mandatory `supply_bounds`, the dead-speed-path port, the swept-supply determinism result) is PRESERVED as what an unblocked row would build on, but is insufficient alone; sim→real is a hypothesis (engine drift + PeMS noise could make laundering EASIER). All numbers `3junction`/seed-0 only, not generalized; dual-benchmark R8/forbidden-clause carried) - [x] Stabler et al. (2016) — *Transportation Networks for Research* (data/scenario) — **shipped in v0.x** (checksummed TNTP fetcher + 4 registered networks) - [x] Eckman et al. (2023) — *SimOpt: A testbed for simulation-optimization experiments* (metric/protocol) — **shipped** as `experiments.profiles` (adr-032, the SimOpt diagnostics layer: progress curves, α-solve-time cdf/quantile solvability profiles, Moré-Wild data profiles, difference profiles, functional bootstrap bands, and a certified `profiles.json` artifact — pure post-hoc arithmetic over already-certified rows, redeeming the P5/P6 progress-curve/solvability-profile promise with zero changes to any solver/certifier/runner. The machinery is defined in the companion Eckman et al. (2023) "Diagnostic Tools" (IJoC 35(2):350-367) and Moré & Wild (2009); strict-`<` crossing, censored-in-denominator cdfs, the SimOpt-exact exclusive β-quantile (checked against `statistics.quantiles`, with a censoring-robust opt-in), inf-honest quantiles/bands/differences, the full-cross-design refusal for incongruent model sets, and the braess {msa:5, fw:24, bfw:4} α-solve anchor are pinned by ~48 closed-form tests; golden Braess hash byte-identical) - [x] Ryu et al. (2025) — *BO4Mob: Bayesian Optimization Benchmarks for High-Dimensional Urban Mobility Problem* (data/scenario) — **stage 1 shipped** as the BO4Mob scenario family ([ADR-034](design/adr-034-bo4mob-scenarios.md)): the lab's OWN NeurIPS-2025 D&B benchmark (`UMN-Choi-Lab/BO4Mob`, MIT) — five San Jose freeway OD-estimation instances scored by NRMSE of mesoscopic-SUMO counts vs real Caltrans PeMS data, integrated as **scenarios/data only** under a central **dual-benchmark honesty contract** (never validation of TABench methods; the paper's numbers never claimed reproduced — the shipped `eclipse-sumo` 1.27.1 wheel drifts from the paper's SUMO 1.12, a MEASURED `edgeData` schema change where meso drops `nVehContrib` but BO4Mob's own `arrived+left` convention still holds, so the *instances* transfer and the *values* do not). Stage 1 = **data availability + pipeline liveness only**: a P9 commit-pinned per-file-SHA-256 fetcher for the four small instances (`1ramp`/`2corridor`/`3junction`/`4smallRegion`, < 1.2 MB of single-evaluation bundles) on a SEPARATE registry never in the CI-prefetched `REGISTRY`, with `5fullRegion` (10,100 OD pairs, 74 MB, ~11 h/eval) registered metadata-only and refusing to fetch (a named HPC-only refusal); the pandas-free BO4Mob count/NRMSE transforms; and a guarded `sumo`-extra smoke test running od2trips + mesoscopic SUMO end-to-end on 1ramp (measured NRMSE **2.4325** with the load-bearing `od_end_time` OD-window fill, byte-identical across seeds 0/1/2, ~0.41 s/run — pinned LOOSE, band 1.5–3.5, as engine-drift provenance, NOT a paper number). BO4Mob keys are NOT `load_scenario` scenarios (a meso net with no BPR network and no true OD — data, never a `Scenario`); NO task/certificate/estimator (the `bo4mob_estimation` T2 family with a pinned-engine held-out-date observational certificate is a NAMED stage-2 follow-up). Additive, no new dependency/CI job, golden Braess hash `cf00f411…` byte-identical. **Stage 2 shipped** as the `bo4mob-estimation` T2 family ([ADR-041](design/adr-041-bo4mob-estimation.md)): a NEW T2 sibling family (the ADR-023 pattern, NOT a guarded estimator — `EstimationTask`/`ODCertifier`/`run_estimation_experiment` all hard-require a BPR network + true OD + `bfw` pin BO4Mob structurally lacks) scored by a **D2 OBSERVATIONAL** certificate — the harness re-runs the pinned `eclipse-sumo` 1.27.1 od2trips+meso pipeline ONCE on the EMITTED OD and scores `heldout_nrmse` (the ranking column: the MEAN of BO4Mob's count NRMSE over 13 same-hour-window `06-07`, different-DATE held-out real PeMS dates `221009`–`221021`; TRAIN = the anchor `221008`), **equilibrium NEVER claimed** (no true OD, no BPR, no `bfw`). Held-out is a SEPARATE checksummed on-demand panel (52 new SHA-256 pins) whose bytes/dates NEVER enter the task — only their `heldout_digest` does (P7). Reuses `assert_engine_pin` (RAISES on engine drift) + the adr-027/029 subprocess discipline verbatim; deliberately does NOT reuse EDOC-1's `EdocEvaluator`/G1 (no per-agent self-report — a category-error boundary). Demand-only; identifiability is provenance-only (no declared assignment for Hazelton's rank test). Rides the EXISTING `sumo` CI job (1ramp full certify + 2corridor/3junction liveness, ~24 s; 4smallRegion opt-in). Same dual-benchmark honesty contract on every surface (extended forbidden clause 3: does NOT reproduce BO4Mob's own SPSA/BO leaderboard rankings) --- *The tier-1 rows are HAND-MAINTAINED: each is flipped to `[x]` with its shipped annotation when its method ships. `tools/generate_references.py` regenerates this skeleton from the verified canon `references.json` and carries the `SHIPPED` dict forward — every shipped bibkey MUST stay in `SHIPPED`, or a regen would uncheck its row. Use the generator to add NEW canon entries; do not let it overwrite the hand-written shipped prose.*