ADR-024: newell-3det — Newell (1993) three-detector interior reconstruction

Status: accepted (implemented) Date: 2026-07-14 Deciders: DNL/estimation tracks — the benchmark’s first traffic-state-estimation task File: docs/design/adr-024-newell-3det.md

Context

Newell’s simplified theory of kinematic waves (1993, a three-part TR-B trilogy) recasts the LWR model in cumulative-count coordinates N(x, t). Under a triangular fundamental diagram the interior state at any point is the lower envelope of two translations of the boundary cumulative curves — one carried forward at the free-flow speed vf, one carried backward at the wave speed w:

N(x, t) = min( N_up(t - x/vf),  N_dn(t - (L - x)/w) + kappa*(L - x) )

on a homogeneous link [0, L] with detectors at x = 0 (upstream, N_up) and x = L (downstream, N_dn), a shared vehicle numbering, and an empty-start record (N0 = 0). The kappa*(L - x) storage term is the maximum vehicle count that can be stored between x and the downstream detector.

Why not a third LinkModel. Newell’s loading content — the sending/receiving evaluation of the two shifted curves at the link ends — already ships as ltm (adr-016, Yperman 2007); dnl/ltm.py lines 15-16 ARE Newell’s minimum principle at x = 0 and x = L, and model-specs.json says LTM “operationalized” it. But LTM deliberately discards the interior field (ltm.py: “no interior discretisation”). Newell’s actual Part-I content — the min at interior x — is therefore unshipped. Shipping it as a second loader would be strictly duplicative; shipping it as the interior reconstruction is a genuinely new task family.

The task family: state estimation. Given measured (noisy / partial) boundary detector curves, reconstruct the interior cumulative field. This is the first traffic-STATE-estimation (TSE) unit in the repo — distinct from assignment (T1), OD estimation (T2), and network loading (DNL). The oracle and certifier are Newell’s exact minimum principle (the paper’s content); the observation dials (Poisson counts, Gaussian reading error, missing windows) are the repo’s own P3 conventions (observe/levels.py) — the paper contains no estimation numerics.

Decision

Ship newell-3det as a parallel module src/tabench/newell/ (the adr-019 bottleneck/ pattern), importing the dnl machinery read-only. Additive: no edit to dnl/scenario.py hashes, observe/levels.py contracts, core/scenario.py, or any existing hash; the golden Braess content hash cf00f411cdccec88019979e8cfbf3d8014ba590688b285a1db667315ac96762d is re-asserted in tests/test_newell.py.

  1. ThreeDetectorScenario (scenario.py, frozen, hashed "tabench-newell3d-scenario-v1;"). Study-link triangular FD (vf, w, kappa) with optional cap, the TimeGrid, the fixed interior query positions x_query, a truth recipe (piecewise-constant corridor inflow + downstream meter_cap), and the observation dials. Arrays are copied read-only; a float64 conditioning gate rejects a storage term kappa*(L - x) whose ULP exceeds the count resolution (the vi-due lesson). The truth boundary curves are never stored — they are regenerated by running LTM on a two-link corridor (_truth_scenario), whose study-link n_in/n_out ARE the two clean detector curves. The constructor validates that the generated pair satisfies the single-link Newell envelopes exactly (realizable LWR data by construction).

  2. Observation (observe.py, module-local so observe/levels.py is untouched). A seeded projection of the clean curves: "none" (oracle), "poisson" (per-interval counts, the LinkCounts precedent — monotone), or "gaussian" (a cumulative reading error N(0, sigma^2), the DayToDayCounts large-population Gaussian limit). up_windows/dn_windows mark unobserved windows (NaN). The DetectorObservation carries ONLY observables — no truth recipe reaches it.

  3. Reference estimators (solve.py). newell_min (naive: running-max monotonization then the min) and newell_min_isotonic (denoised: L2-optimal isotonic regression then the min), both pure functions of the model-visible ThreeDetectorProblem (public physics + grid + observed detectors). The emitted ThreeDetectorField is the (m, K+1) interior reconstruction.

  4. Certificate (P1) (metrics/newell_gaps.py, ThreeDetectorEvaluator). Pure function of (scenario bytes, emitted field). It regenerates the clean detector curves from the hashed recipe (the adr-023 discipline — never a stored array), evaluates the closed-form min at the fixed grid to get the reference M, and scores. Gating certificates (the “valid cumulative field” checks, all guaranteed by any min-of-monotone-boundaries reconstruction, so a legitimate noisy estimate passes while garbage is censored): finite / shape (raise) / hash; zero start; non-negativity; monotonicity via a running-max total-retraction budget (the adr-022 lesson — never per-step, so an eps-creep dip accumulated over K steps is caught by the aggregate mass budget). Ranking is interior_rmse = RMSE(emission − M) over the fixed hashed grid, on noisy/partial levels only.

  5. Fixed hashed query grid. Scoring is at the scenario’s hashed (x_i, t_k) grid, NOT any emitted-grid-dependent sweep — the vi-due CRITICAL (a solver-dilutable window is a false-accept surface). The emission shape is bound by the hash.

The exactness conditions and the sign convention

The two-term min is exact iff: (1) a triangular FD (exactly two wave speeds); (2) a homogeneous segment, no interior sources/sinks (Part II handles ramps by adding net cumulative ramp inflow); (3) FIFO single-pipe single-class flow with conserved numbering; (4) correct N0 offset and drift-free counts; (5) a causally sufficient record (shifted arguments inside the data — extending by 0 before an empty start is valid ONLY for empty starts); (6) LWR first-order dynamics with known (vf, w, kappa). For a general concave FD the two-term form is a majorant bound, not exact (full variational theory, Daganzo 2005, is needed); this unit ships the triangular case only and reconstructs on triangular-FD truth.

Sign convention (w > 0). With w the backward-wave MAGNITUDE the downstream shift is t (L x)/w (Boyles TNA eq. 9.46; Rey-Jin-Ritchie 2019 eq. 10; Daganzo VWP-2006-2 eq. 17). The +(L x)/w variant is non-causal (it reads a future downstream value) and only appears where w is a signed negative velocity (Wikipedia, Yperman) — the same convention note ltm already documents for its receiving flow. The wrong sign is machine-detectable: on anchor A2 it moves the x = 2 min-switch from t = 10 to t = 14 (equality convention; pinned in test_newell.py).

The pairwise Newell envelopes are Tier B (the C5 analog)

Between every emitted position pair x_i < x_j two necessary LWR conditions hold for the exact field: forward free-flow N(x_j, t) <= N(x_i, t (x_j−x_i)/vf) and backward storage N(x_i, t) <= N(x_j, t (x_j−x_i)/w) + kappa*(x_j−x_i) (grid-edge relaxed like dnl_gaps C4/C5). The reference M passes both at 0.

These are reported, non-gating (Tier B), exactly as dnl_gaps C5 (the backward-wave envelope) is non-gating because CTM legitimately violates it. A legitimate NOISY reconstruction violates the physical envelopes at noise scale (a detector reading error above capacity is not capacity-feasible), so gating them would false-censor the honest naive baseline — the design pins both baselines as feasible = 1. Symmetrically, a tolerance loose enough to admit honest noise would excuse a teleport. The residual is therefore the science and the interior_rmse ranking is the plausibility check: a physics-violating field is far from the physical truth, so it cannot both cheat the ranking and pass. Reported with the adr-020 two-scale split (per-cell max residual AND aggregate violated mass) plus envelope_exact / envelope_at_resolution flags. This is the one deliberate deviation from the original sprint sketch (which listed the envelopes as gating): the executed evidence — the honest baseline’s O(noise) backward residual, machine-checked across 180 seed/noise configs — contradicts gating them, and the C4-gating/C5-Tier-B split is the repo’s own precedent for exactly this situation.

The triviality trap: clean is an oracle, never ranked

On clean data the reference estimator IS the closed-form min, so any submission evaluating the formula scores 0. The mitigation is structural, not tolerancing: the clean level is an oracle/validity row flagged rankable = 0 and is never ranked; ranking lives on the noisy/partial levels where the statistical content (denoising, fusing the two directional traces, bridging missing windows via the storage term) genuinely discriminates — the adr-023 pattern. The naive min-on-noisy-curves is the pinned baseline a better estimator must beat.

Analytic anchors

All recomputed in-test (tests/test_newell.py, house style: no trusted digits).

  • A1 free-flow (exactness). Meter above inflow, so the congested branch never binds: N(x, t) = N_up(t x/vf) exactly at every interior x; oracle row.

  • A2 asymmetric spillback (interior RH shock). vf=2, w=1, kappa=3, L=4, inflow 1.0 into a 0.5 meter (adr-016 anchor (c)). q_A=1, k_A=0.5; q_B=0.5, k_B=kappa−q_B/w=2.5; RH shock speed −0.25 born at (x=4, t=2), so it passes x at t = 2 + (4−x)/0.25 (x=1→14, x=2→10, x=3→6) and reaches x=0 at t=18. At x=2 the min-switch is N=9 at t=10, post-shock N(2,t)=0.5t+4; reconstructed density (central x-difference) = k_B = 2.5. Oracle row.

  • A3 symmetric bottleneck (cross-model truth). vf=w=1, kappa=4, L=4, inflow 1.5 into a 0.5 meter (adr-016 anchor (b)). The truth-generating LTM boundary curves reproduce CTM byte-for-byte, doubly validating the truth generator (the lp-so-dta corridor==CTMLink move). Oracle row.

  • A4 noisy dominance (the acceptance test). A3 physics under a seeded Gaussian reading level (dt=0.25, sigma=1.2, seed pinned): the isotonic-then-min estimator strictly beats the naive running-max baseline in interior_rmse by a pinned deterministic margin (naive 1.0928, isotonic 0.4484), both feasible = 1, rankable = 1. Proves the ranked task separates methods and is not a formula evaluation.

  • A5 observability edge. Upstream masked over [11, 17] (clean): the congested branch alone pins the interior EXACTLY wherever it is active (error 0 on every congested-active cell); the ONLY discrepancy is x=1 at t∈{12,13} where the interior is still free-flow but upstream is unobserved (cong overestimates by exactly 1.0). A Newell-specific identifiability statement, reported per config.

Alternatives considered

  • A third LinkModel / second cumulative-curve loader: rejected — Newell’s loading content shipped as ltm; the min structure is byte-similar but the task is categorically different (boundary-curves-in → interior-field-out, closed-form, no time stepping, no node coupling).

  • Gating the pairwise envelopes at tol scale: rejected — false-censors the honest noisy baseline (measured across 180 configs), the C5 dilemma. Kept Tier B.

  • Capacity-projecting both estimators to make the envelopes gate cleanly: rejected — the capacity clip becomes the dominant shared denoiser and collapses the A4 discrimination (min margin turns negative across seeds).

  • Ranking the clean level / tolerancing the triviality: rejected — a formula evaluation with no benchmark content; the clean level is an oracle row.

  • Estimating N0 from data, non-empty starts, ramps between detectors, non-triangular FDs: out of scope (their own literatures); the unit restricts to empty-start, homogeneous, triangular-FD instances and raises/validates otherwise.

Consequences

The benchmark gains its first traffic-state-estimation task and a new task family (scenario space + observation level + evaluator), for one canon reference, single-link, no network. All changes are additive; the golden Braess hash is provably preserved; no output contract changed. Follow-ups: a certifier-upgrade that reuses the exact interior oracle to sharpen the Tier-B C5 backward-wave residual into an exact interior-residual diagnostic for ctm/godunov/ltm (touches the shipped DNLEvaluator, so a separate sprint); a Greenshields-FD variant that reconstructs with the triangular majorant and reports the honest upper-bound bias q*x*(1/v(k) 1/vf); a multi-day Poisson ranked level.

Adversarial review

Three independent lenses (soundness, formulation, numerics), each executing code; every finding below is CONFIRMED by a runnable repro and regression-pinned in test_newell.py (streak: 13/13 sprints with at least one material defect).

MAJOR ×3, one root cause — masked-window branch-dropping. reconstruct_field set a masked branch to +inf: (a) when the masked branch returned, the raw min dipped below the loose single-branch values inside the window, so the honest reconstruction was non-monotone and the C3 retraction gate false-censored both reference baselines on 125/514 fuzzed windowed scenarios (including clean data — A5 escaped only because its mask sits entirely in the congested-active region); (b) time-disjoint up/dn windows can still doubly mask an interior cell after the branch shifts (vf=2, w=1: both branches of x=2 read t−1), yielding min(inf, inf) = inf and a C0 whole-field false-censor, with the constructor accepting such configs (its realizability check runs windowless). FIXED at the root: the reconstruction is now the suffix-minimum of the retained bounds — the tightest nondecreasing upper bound consistent with the data (a bound at t' bounds every t <= t'), which repairs the dip, bridges doubly-masked cells from the next observed bound, and is the identity on fully observed data (the reference M is unchanged).

MAJOR — degenerate-rankable cards. rankable keyed on noise kind alone: a byte-clean gaussian, sigma=0 card was RANKED while the min formula scores exactly 0 (the triviality trap the design exists to avoid), and none + drift degraded the data while staying unranked. Both combinations are now constructor errors.

MINORs, fixed + pinned: (a) total_demand = inf was accepted, making the evaluator’s eps_count infinite and silently neutering every censor gate — it also enabled a confirmed content-hash byte-migration collision (a float64 whose bytes spell a label let one array’s tail masquerade as the next array’s head); finiteness is now required, drift is validated finite, and the hash length-frames every array; (b) meter_cap above the geometric apex crashed three layers deep in LinkDynamics although a never-binding meter is a sanctioned concept — clipped at the apex now (physics-identical, distinct hash); (c) a constructor-accepted extreme card crashed numpy’s Poisson sampler — per-step means above 1e15 are rejected; (d) the C3 budget summed dips over cells, duration-amplifying a sustained sub-eps dip into a censor — now the max total drop from the high-water mark (the adr-022 convention); (e) the truth generator is exact only on grid-aligned recipes (all shipped anchors are, verified to ~4e-15) and carries an O(meter_cap·dt) plateau artifact off that subspace — the docstrings now scope the claim and state that M (identical for every submission), not the continuous-time LWR field, is the scoring reference. NOTEs: the wrong-sign anchor number corrected (t=10 t=14 under the equality convention); the _fill_nan “never scored” claim corrected (bridge values are read within one grid step of window edges); x_query docstring [0, L]; documented that all dial values are public (drift in the observation meta means drift cards test bias-correction under a known gain, not blind robustness) and that gaussian ranked cards need n_days 10 at σ 1.2 before day-averaging collapses the A4 margin (0.64 at 1 day → 0.06 at 10).

Survived (highlights): the sign convention and formula re-derived from LWR characteristics and cross-checked against an independent from-scratch Godunov simulator on 7 hand-built regimes + 200 random instances (reconstruction error does not shrink with simulator refinement — it is the simulator that diffuses); the meter-link truth generator proven uncontaminable for meter_cap <= apex; all anchors recomputed (Rankine-Hugoniot crossings t=6/10/14, x=0 arrival t=18, post-shock density kappa q_B/w); the Tier-B envelope demotion’s “cannot both cheat the ranking and pass” claim verified (ranking is truth-referenced, so a large envelope violation implies a large RMSE); no information leak in ThreeDetectorProblem/DetectorObservation (no seed, no clean curves, no recipe); day-mean denoising is honest 1/sqrt(n_days), never trivially 0; hash coverage complete over all 18 score-affecting dials; 882 no-window baseline evaluations all feasible; the pinned A4 floats judged platform-stable (PCG64 + pure-Python PAVA); golden Braess hash unmoved; full suite green.

Sourcing

The primaries are paywalled (ScienceDirect 403) and attributed unread: Newell 1993 Part I (TR-B 27(4):281-287, DOI 10.1016/0191-2615(93)90038-C — the only part in references.json, newell1993simplified), Part II (289-303, DOI 10.1016/0191-2615(93)90039-D) and Part III (305-313, DOI 10.1016/0191-2615(93)90040-H) — DOIs recovered and Crossref-verified but NOT added to references.json. The operative two-translation min statement is Part II’s (Part I gives the general lower-envelope theory); the trilogy is cited jointly as Rey-Jin-Ritchie and Daganzo do. No equation number of any primary is cited — only abstract-level claims and open restatements. The formulation was cross-verified from three OPEN sources read in full:

  • Boyles, Lownes & Unnikrishnan, Transportation Network Analysis Vol. I (arXiv:2502.05182), §9.4.4 eq. 9.46 (the triangular two-term min), §9.5 (the LTM operationalization), worked Fig-9.23 example.

  • Rey, Jin & Ritchie (2019), An extension of Newell’s simplified kinematic wave model to account for FIFO violation, TR-C 109:79-94, DOI 10.1016/j.trc.2019.10.008 — open eScholarship (qt16r3w53g), eqs. 7-11 (the exact three-detector formula, the N0 offset), the three-detector naming credited to Daganzo (1997) sec. 4.4.

  • Daganzo, On the variational theory of traffic flow, UCB-ITS-VWP-2006-2 — open eScholarship (qt61v1r1qq), eq. 17 (Newell’s queuing formula as a primal of variational theory), footnote 10 (two boundary points suffice given capacity-feasible boundary slopes).

The NOISY three-detector task framing is the repo’s own P3 convention (the LinkCounts/DayToDayCounts precedents), NOT the paper’s — Newell (1993) contains no estimation numerics, no noise model, no benchmark network. The stochastic-TSE lineage (Daganzo 2005 variational theory, Laval-He-Castrillon 2012 stochastic three-detector, Coifman 2002, Deng-Lei-Zhou 2013) is tier-2/3 context, attributed unread. Every anchor is a hand-derived closed form.