From 3d8202b2cb01cb7db1bf525e4bb0166f992bf34d Mon Sep 17 00:00:00 2001 From: Mohammad <92270125+Mmdabb@users.noreply.github.com> Date: Sun, 26 Jul 2026 18:01:31 -0700 Subject: [PATCH] Add Stage 8 holdout and emission ablation package --- HANDOFF_README.md | 152 +++++ NUMERICAL_EXPERIMENTS_PROGRESS.md | 158 +++++ .../current/figures/fig_A_evidence_ladder.pdf | Bin 0 -> 21197 bytes .../figures/fig_B_representative_episodes.pdf | Bin 0 -> 48361 bytes .../figures/fig_C_structural_validation.pdf | Bin 0 -> 33964 bytes .../fig_D_emission_ablation_forest.pdf | Bin 0 -> 24057 bytes .../figures/fig_E_phase_admissibility.pdf | Bin 0 -> 36108 bytes .../fig_F_heldout_emission_scatter.pdf | Bin 0 -> 30842 bytes .../figures/pigou_cost_intersections.pdf | Bin 0 -> 29638 bytes .../figures/pigou_weight_sensitivity.pdf | Bin 0 -> 26690 bytes QVDFE_paper/current/section_empirical_v12.tex | 610 ++++++++++++++++++ .../qvdfe_cbi/run_emission_supplement.py | 146 +++++ .../codes/qvdfe_cbi/run_holdout_ablation.py | 301 +++++++++ .../codes/qvdfe_cbi/src/ablation_figures.py | 436 +++++++++++++ .../codes/qvdfe_cbi/src/holdout_ablation.py | 398 ++++++++++++ experiments/codes/qvdfe_cbi/src/outliers.py | 68 +- .../emission_ablation_metrics.csv | 81 +++ .../evidence_ladder.csv | 7 + .../pooled_cell_registry.csv | 10 + .../site_selection.csv | 3 + .../stage8_manifest.json | 74 +++ .../structural_validation_metrics.csv | 13 + .../tables/table1_data_evidence.csv | 4 + .../tables/table1_data_evidence.tex | 15 + .../tables/table2_site_parameters.csv | 3 + .../tables/table2_site_parameters.tex | 14 + .../tables/table3_structural_validation.csv | 13 + .../tables/table3_structural_validation.tex | 24 + .../tables/table4_emission_ablation.csv | 81 +++ .../tables/table4_emission_ablation.tex | 92 +++ .../table5_two_branch_decomposition.csv | 5 + .../table5_two_branch_decomposition.tex | 11 + 32 files changed, 2709 insertions(+), 10 deletions(-) create mode 100644 HANDOFF_README.md create mode 100644 NUMERICAL_EXPERIMENTS_PROGRESS.md create mode 100644 QVDFE_paper/current/figures/fig_A_evidence_ladder.pdf create mode 100644 QVDFE_paper/current/figures/fig_B_representative_episodes.pdf create mode 100644 QVDFE_paper/current/figures/fig_C_structural_validation.pdf create mode 100644 QVDFE_paper/current/figures/fig_D_emission_ablation_forest.pdf create mode 100644 QVDFE_paper/current/figures/fig_E_phase_admissibility.pdf create mode 100644 QVDFE_paper/current/figures/fig_F_heldout_emission_scatter.pdf create mode 100644 QVDFE_paper/current/figures/pigou_cost_intersections.pdf create mode 100644 QVDFE_paper/current/figures/pigou_weight_sensitivity.pdf create mode 100644 QVDFE_paper/current/section_empirical_v12.tex create mode 100644 experiments/codes/qvdfe_cbi/run_emission_supplement.py create mode 100644 experiments/codes/qvdfe_cbi/run_holdout_ablation.py create mode 100644 experiments/codes/qvdfe_cbi/src/ablation_figures.py create mode 100644 experiments/codes/qvdfe_cbi/src/holdout_ablation.py create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/emission_ablation_metrics.csv create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/evidence_ladder.csv create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/pooled_cell_registry.csv create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/site_selection.csv create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/stage8_manifest.json create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/structural_validation_metrics.csv create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table1_data_evidence.csv create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table1_data_evidence.tex create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table2_site_parameters.csv create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table2_site_parameters.tex create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table3_structural_validation.csv create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table3_structural_validation.tex create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table4_emission_ablation.csv create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table4_emission_ablation.tex create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table5_two_branch_decomposition.csv create mode 100644 experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table5_two_branch_decomposition.tex diff --git a/HANDOFF_README.md b/HANDOFF_README.md new file mode 100644 index 0000000..224e5e1 --- /dev/null +++ b/HANDOFF_README.md @@ -0,0 +1,152 @@ +# QVDF-E Handoff Package — 2026-07-25 + +For: Mohammad (QVDFE repo owner) +From: Simon's working session (Claude-assisted; all numbers machine-generated and reproducible) + +This package contains everything produced in the empirical-section redesign +round: two bug fixes, the new Stage 8/8b holdout + emission-ablation +experiments, the redesigned LaTeX empirical section (v12 draft) with 8 +figures and 6 tables, and all machine-readable results. Files are laid out +**repo-relative** so you can copy them straight into your working trees. + +--- + +## 1. What goes where + +### `qvdfe_changes/` → drop into `Mmdabb/QVDFE` repo root + +| File | Status | What it does | +|---|---|---| +| `experiments/codes/qvdfe_cbi/src/outliers.py` | **REPLACES existing** | Two-tier outlier screen (see §2) | +| `experiments/codes/qvdfe_cbi/src/holdout_ablation.py` | new | Stage 8 core: site selection, blocked 70/30 date split, QVDF refit, B0–B3 ablation, paired bootstrap | +| `experiments/codes/qvdfe_cbi/src/ablation_figures.py` | new | Figures A–E | +| `experiments/codes/qvdfe_cbi/run_holdout_ablation.py` | new | Stage 8 driver (~10 s, post-processes frozen Stage 0–7 outputs) | +| `experiments/codes/qvdfe_cbi/run_emission_supplement.py` | new | Stage 8b: Figure F + Table 5 | + +Run order (from repo root, after the main pipeline outputs exist): +```bash +python experiments/codes/qvdfe_cbi/run_holdout_ablation.py +python experiments/codes/qvdfe_cbi/run_emission_supplement.py +``` +Outputs land in `experiments/output/qvdfe_cbi/stage8_holdout_ablation/`. + +### `cbi_plus_changes/` → drop into `asu-trans-ai-lab/cbi_plus` repo root + +| File | Status | What it does | +|---|---|---| +| `cbi_pipeline/stage2_episodes.py` | REPLACES existing | Fixed `discharge_window()` (see §2) | +| `cbi_pipeline/stage2b_measured_diagnostics.py` | REPLACES existing | Two-tier outlier screen + hard range rules | + +`tests/test_cbi_plus_fixes.py` verifies both fixes on synthetic episodes +(all passing). Point `PKG_ROOT` at your cbi_plus checkout and run with +plain `python`. + +### `paper/` → the v12 empirical section + +- `section_empirical_v12.tex` — drop-in replacement for + `\section{Empirical evaluation...}` (`sec:numerical`) of + `main_v11_community_narrative.tex`. Notation matches the v11 notation + table exactly. Self-contained numbers (no `\input` of generated tables). +- `figures/` — the 8 PDFs it includes (`fig_A`–`fig_F` + the two Pigou + figures). Copy into the paper's `figures/` directory. +- Needs: `enumerate` label style already used by the S1–S7 lists in v11. + +### `results/` — machine-readable evidence behind every number + +- `site_selection.csv` — the ex-ante rule applied to all candidate cells +- `structural_validation_metrics.csv` — Table 3 source (P, μ_e, v_q: QVDF + vs Vickrey vs fixed-speed, held-out) +- `emission_ablation_metrics.csv` — Table 4 source (B0–B3 + reconstructed + diagnostic, NMAE/MAPE/bias/R² + paired-bootstrap ΔNMAE CIs) +- `pooled_cell_registry.csv` — the 9 blocked-holdout cells and their + train-block QVDF parameters +- `evidence_ladder.csv`, `stage8_manifest.json` +- `tables/table1..5_*.{csv,tex}` — auto-generated table files + +--- + +## 2. The two bug fixes (please review these diffs first) + +**(a) Discharge-window tagging** (cbi_plus `stage2_episodes.py`, +`discharge_window`). Old logic kept bins with `Δq ≤ 0` and spanned a +non-contiguous mask. Queue dissipation moves *up* the congested FD branch +— flow **rises** toward the discharge rate during recovery — so `Δq ≤ 0` +tags the demand-starvation tail, not discharge, and the returned span +contained bins that failed the rule's own criterion. New logic mirrors +your validated `identify_discharge_window` in QVDFE +(`cbi_state_transition.py`): below-v_c bins after t2, accepted only with +positive-Δq share ≥ 0.60 (or non-negative net Δq) plus speed recovery; +speed-only data keeps the relaxed path. + +**(b) Outlier screen** (both repos). Two defects in opposite directions: +- *Too strict:* three 3-MAD Huber screens + MAD z-scores were unioned + flag-by-flag → legitimate heavy-congestion days excluded. Relational + ("soft") flags now need **two agreeing votes**. +- *Out-of-range leak:* every rule was a `>` comparison, so NaN/inf passed + as False → "clean"; no absolute range checks existed. New "hard" rules + (non-finite state, P > period window, D/C > 8 h, speed outside + [0, 90] mph, non-positive μ) exclude outright. +- Log-axis Huber fits no longer clamp non-positives to 1e-6. + +**Measured consequence on the frozen outputs:** 95 of 1,827 evaluated +episodes have z > 8 (impossible demand accumulation) and are removed by +the hard screen; the physically-admissible count drops **403 → 364** +(strict 402 → 363). ~10% of the old admissible set was range leakage. +Corridor split after fix: I-10 EB 151/151 (physical/strict), I-405 SB +212/212, I-17 NB 1/0. + +--- + +## 3. Experiment design and headline results + +Design (per the empirical-section redesign plan): +- **Sites** (rule fixed before any emission error was examined; measured + volume, ≥12 clean episodes — the 27-weekday window caps cells at 18–19, + so the planned 20–30 floor is infeasible — stable FD, ≥50% strict + coverage, top CBI): **I-10 EB `pems::718412` PM** (CBI 3.89) and + **I-405 SB `pems::767053` AM** (CBI 4.36), both 18 episodes. +- **Blocked holdout:** first 70% of dates calibrate, last 30% validate + (13/5 per site); pooled = 9 measured-flow cells, 41 validation episodes + (19 strict). No random episode splits. +- **Ablation:** B0 mean-speed, B1 delay-only, B2 fixed queued speed, B3 + FD-consistent v_e(z), vs observed-speed 5-min MOVES totals; paired + bootstrap (2,000) on ΔNMAE. + +Headlines: +1. QVDF halves Vickrey's held-out duration error (10.5 vs 20.6% NMAE at + I-10; 15.7 vs 34.5% at I-405); μ_e(z) beats μ_e=C^h by 2–4×. +2. **n hits the 1.0 bound at both sites**: the data identify a stable + retention *level* (μ_e/C^h = 1/f_d ≈ 0.72), not a retention *slope*. + Framed honestly in v12; n>1 needs multi-site pooling or longer windows. +3. Delay-only B1 fails by +42% to +245%; every queued-state model removes + 60–90% of that error (all CIs exclude 0). **B3 beats B2 decisively at + the I-405 merge** (NOx 29 vs 77% NMAE); B0 mean-speed is an honest, + strong total-mass baseline but unusable as the assignment primitive. +4. Two-branch decomposition (Table 5): queue branch = 25–38% of totals for + CO2/CO/HC with 5–8% cubic-Γ error; **NOx has negative exact Γ (median + −1.2 g/h) and 38% cubic-Γ error** → v12 states the pollutant scope: + CO2/CO/HC support accounting + assignment; NOx needs trajectory rates. +5. v_e(z) is biased low ~2× vs observed mean queued speed — the dominant + B3 error source; k_j = 220 sensitivity is the top follow-up. +6. Pigou subsection (from your `QVDFE_Pigou_Additional_Results` package) + is integrated after the admissibility figure: z_EUE=13.303, + z_ESO=7.368 at λ=0.4, price of anarchy 1.099, ordering stable in λ. + +--- + +## 4. Open items (suggested order) + +1. Full pipeline re-run (stages 2b–7, ~1.5 h) with the fixed outlier + screen, then regenerate Stage 8/8b → ladder counts in Fig A / Table 1 + will shift slightly. +2. k_j sensitivity (160–220 veh/mi/lane) and/or per-site ω calibration to + attack the v_e low bias. +3. Multi-site pooled (shared-n) fit to test n > 1 identifiability. +4. `DETECTOR = "deepest_queue"` robustness pass of Stage 8 (one constant). +5. Wire `section_empirical_v12.tex` into the master tex and rebuild; + decide what of v11's `sec:numerical` moves to the appendix. +6. PRs: when ready, apply `qvdfe_changes/` on a branch of `Mmdabb/QVDFE` + and `cbi_plus_changes/` on a branch of `asu-trans-ai-lab/cbi_plus` + (deferred by Simon's request — nothing has been pushed anywhere). + +See `NUMERICAL_EXPERIMENTS_PROGRESS.md` (included) for the full ledger. diff --git a/NUMERICAL_EXPERIMENTS_PROGRESS.md b/NUMERICAL_EXPERIMENTS_PROGRESS.md new file mode 100644 index 0000000..4fc57dd --- /dev/null +++ b/NUMERICAL_EXPERIMENTS_PROGRESS.md @@ -0,0 +1,158 @@ +# QVDF-E Numerical Experiments — Progress Log + +Status ledger for the redesigned empirical section (v12). +Last update: **2026-07-25, round 2** (Claude-assisted session; all results machine-generated). + +## 0. Round-2 additions (emission supplement + Pigou) + +| Item | Status | Where | +|---|---|---| +| Stage 8b: Figure F (held-out obs-vs-model emission scatter, 4 pollutants) | DONE | `experiments/codes/qvdfe_cbi/run_emission_supplement.py` → `stage8_holdout_ablation/figures/fig_F_heldout_emission_scatter.*` | +| Stage 8b: Table 5 (two-branch decomposition of B3 on strict held-out set) | DONE | `stage8_holdout_ablation/tables/table5_two_branch_decomposition.{csv,tex}` | +| Pigou two-route subsection integrated into v12 section | DONE | `section_empirical_v12.tex` §"Two-route Pigou assignment illustration" (adapted from `QVDFE_Pigou_Additional_Results/paper/pigou_section_insert.tex`; figures copied into package `figures/`) | + +**Table 5 headline (strict held-out, n=19):** queue-exposure branch carries +25% (CO2) / 38% (CO) / 37% (HC) of episode totals with Γ>0 and cubic-Γ +errors of only 5–8%; **NOx has a NEGATIVE exact Γ (median −1.2 g/h)** and a +38% cubic-Γ error — added queue exposure nominally *reduces* NOx under +zero-acceleration running-exhaust rates. Figure F visualizes the practical +consequence (B2 collapses to a flat total for a NOx episode cluster +spanning ~an order of magnitude observed). v12 now states the pollutant +scope explicitly: accounting + assignment defensible for CO2/CO/HC; NOx +needs trajectory-resolved rates. + +**Pigou headline:** on the calibrated I-10 prototype (α=0.0049, β=1.648, +Γ≈const over z∈[5.2,14]): z_TUE=14.000, z_TSO=7.754, z_EUE=13.303, +z_ESO=7.368 at λ=0.4; emission-weighted price of anarchy 1.099 (exact-rate +sensitivity: 1.086); ordering z_ESO` comparison, so NaN/inf values + compared False and sailed through as clean; there were no absolute range + checks at all. Now "hard" rules (non-finite state, P > period window, + D/C > 8 h, speed outside [0, 90] mph, non-positive μ) exclude outright. +- Also: log-axis Huber fits no longer clamp non-positives to 1e-6 (was + dragging the robust fit toward log(1e-6) = −13.8). + +**Measured consequence:** the hard-range rescreen removes **95 of 1,827** +evaluated episodes (all with z > 8, impossible demand accumulation), and +the "physically admissible" set drops **403 → 364** (strict 402 → 363). +~10% of the old admissible set was out-of-range leakage. Corridor split +after fix: I-10 EB 151 physical/151 strict, I-405 SB 212/212, I-17 NB 1/0. + +## 3. Experiment design (per the redesign plan) + +- **Frozen substrate:** Stage 0–7 outputs of the prior full run (unchanged + on disk); Stage 8 is pure post-processing (~10 s runtime). +- **Site rule (fixed ex ante):** measured volume; ≥ 12 clean episodes per + sensor-period cell (the 27-weekday window caps cells at 18–19, so the + planned 20–30 floor is infeasible — documented deviation); stable FD; + ≥ 50% strict coverage; highest CBI. Bound-free full-sample QVDF fit was + demoted from gate to tiebreaker (it excluded *every* high-CBI cell); + the site refit's own bound status is reported in Table 2. + - Selected: **I-10 EB `pems::718412` PM** (CBI 3.89, 18 eps, strict 1.00) + - Selected: **I-405 SB `pems::767053` AM** (CBI 4.36, 18 eps, strict 1.00) +- **Blocked holdout:** first 70% of dates calibrate, last 30% validate + (13 train / 5 validation episodes per site); pooled run = 9 + measured-flow cells → 41 validation episodes (19 strict). No random + episode splits (temporal leakage). +- **Ablation:** B0 mean-speed, B1 delay-only, B2 fixed queued speed + (train-median), B3 FD-consistent v_e(z); benchmark = observed-speed + 5-min MOVES totals; paired bootstrap (2,000) CIs on ΔNMAE vs B1; + reconstructed-speed MOVES carried as diagnostic. + +## 4. Headline results + +**Structural (held-out, Table 3):** +- QVDF halves Vickrey's duration error: NMAE 10.5% vs 20.6% (I-10), + 15.7% vs 34.5% (I-405); Vickrey bias is negative (episodes outlast the + fixed-capacity prediction). +- μ_e(z) beats μ_e = C^h: 10.0% vs 28.9% (I-10), 27.2% vs 63.4% (I-405). +- **n hits the 1.0 lower bound at both sites**: the data identify a stable + capacity-retention *level* (μ_e/C^h = 1/f_d ≈ 0.72, f_d ≈ 1.38), not a + retention *slope* (n > 1) at single-site scale. Honest framing in v12: + level supported decisively, slope not identifiable in 27 dates. +- FD v_e(z) is biased low ~2× vs observed mean queued speed (−51%/−64%) + — the known within-link-storage/state tension, now quantified OOS. + +**Emission ablation (held-out, Table 4 / Fig D):** +- B1 delay-only fails by construction: +42% to +245% bias (prices queued + hours at the reference-speed rate). Every queued-state model removes + 60–90% of that error; all bootstrap CIs exclude zero. +- **At the I-405 merge site B3 beats B2** (CO2 21.5 vs 28.5, NOx 29.0 vs + 76.9, CO 10.9 vs 25.2 NMAE%); HC tie. Pooled strict: B3 wins CO, B2 wins + NOx, CO2/HC tie. Pollutant pattern matches the plan's prediction + (CO/CO2 support the reduction; NOx exposes rate-curve limits). +- B0 mean-speed is a strong total-mass baseline (10–17% NMAE) — reported + honestly; it is not usable as the assignment primitive (needs the full + rate curve in-loop, no Γ·w̄ decomposition). +- B3's residual is almost pure positive bias ← v_e biased low. Fixing the + congested-branch speed mapping is the highest-leverage refinement. + +**Admissibility (Fig E):** over both sites' calibrated z ranges all +physical/rate/monotone-g conditions hold → separable emission-weighted +assignment is admissible *on the identified domain*. + +## 5. How to reproduce + +```bash +cd C:/source_codes/1_new_source_code/CBI_plus_QVDF_E/QVDFE-main/QVDFE-main +python experiments/codes/qvdfe_cbi/run_holdout_ablation.py +``` +Outputs → `experiments/output/qvdfe_cbi/stage8_holdout_ablation/` +(`site_selection.csv`, `structural_validation_metrics.csv`, +`emission_ablation_metrics.csv`, `pooled_cell_registry.csv`, +`evidence_ladder.csv`, per-site state CSVs, `tables/`, `figures/`, +`stage8_manifest.json`). + +## 6. Open items (next session) + +1. **Full pipeline re-run with the fixed outlier screen** (stages 2b–7, + ~1.5 h; Stage 5 reconstruction is the bottleneck). The two-tier screen + will slightly *grow* the clean set (soft flags now need 2 votes) while + hard rules remove the z > 8 rows at the source; episode counts in the + ladder will shift and Table 1/Fig A should be regenerated afterwards. +2. **n > 1 identifiability**: pool sensor-period cells within a corridor + (mixed-effects or shared-n fit) or extend the observation window; the + single-site 27-date sample cannot separate retention slope from level. +3. **v_e bias**: revisit k_j = 220 veh/mi/lane (sensitivity: k_j 160–220) + and/or calibrate ω per site; this is the dominant error source in B3. +4. **DQ-detector robustness pass**: rerun Stage 8 with + `DETECTOR = "deepest_queue"` and report deltas (script constant). +5. Decide whether v12 section replaces or augments v11 `sec:numerical`; + wire `section_empirical_v12.tex` into the master file and rebuild the + PDF (needs the enumerate label style already used by S1–S7 lists). +6. Optional: per-episode appendix tables (exact-vs-cubic) unchanged from + v11 — move to appendix per the plan's §9. diff --git a/QVDFE_paper/current/figures/fig_A_evidence_ladder.pdf b/QVDFE_paper/current/figures/fig_A_evidence_ladder.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7a2db1aa08fcf002a2d96fdf62512128efd10b24 GIT binary patch literal 21197 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 AyZ`_I literal 0 HcmV?d00001 diff --git a/QVDFE_paper/current/figures/fig_D_emission_ablation_forest.pdf b/QVDFE_paper/current/figures/fig_D_emission_ablation_forest.pdf new file mode 100644 index 0000000000000000000000000000000000000000..35a3b62c139e8b8552f07816d57170f9812393aa GIT binary patch literal 24057 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 F{|D4oL@fXS literal 0 HcmV?d00001 diff --git a/QVDFE_paper/current/figures/fig_E_phase_admissibility.pdf b/QVDFE_paper/current/figures/fig_E_phase_admissibility.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4f43442fa2bd4f23f2aa27e3b1c69f7ebd0e6726 GIT binary patch literal 36108 zcmb@u1yGzpw=IeX3$DQicN^T@CAdp)3C`f|?gV#tcMTTYJ-EBOg-d?9@4RzQ-E->I ztEsN9`|FK&p zB$Po0AQJ%VKVK*qfIub=HUPH2O?XCSa|2@w8#4g=zj_^Pjg(D50PPR6qT(M=Ok6<# zMk(tL2*Uq*iu~&-1dE#(^i>uKI(D`on;ofi}E? zJr6A{?agj#@$0Rb{_Bf+w$Bx^!28iwwa?S-(Ovaqw_A9~#<7n+VeeM+^M*ds)urRx z#b|L(_d4GlYm8CSYWbg6_cxX(&}pS=RPbHQ1~1>+$!xJtA$ixdy7!-3m2G>|7iosU zh2TF|=hRWIh@Hh5Rr&hW`K3qS`Iax8f}G~O4`V)=JtZD6C$U;CzGsIdJ~M|nJkDZ= zyxTvnZOwK|udMghCK4XwP%jqSSvdysDp$N+7BfQoZ>-C5off_JO%hdH-b(mk0)B}^ zo-LV`wJvb&6E``~RTcoB=bHF^Tpn+`gZd`DeNx{mJ`duGNY*#FmJAYV6H?#eWG>%m z97mEj;9PHU)knmAFZJR~nB~0ZeMxZ|vo~)W%Mh2MCwC#bOOckgZc^Ld;(|CP{C-%k zW_tyaWeZZ%lDtE?VYbv}8=p>VZcCCO{)G$GQ$@tHpC&=YUD}+w6k{D(s=sKDJh_$P zDAV{r5&Eo+TxepgmosHcAcE6*fUos{MKp-3blR59j->cNgP$g3cRTTvv7;y$$u_7( z>QQQ?{g_?iEtXRG3#Tn)k(@v~+i`&! zz}xWyD?0591syOPFe58;xNWT^$ty}i-){;Ef0!7$|&p9dPrEO*^74RbfrWQtXBR&ObB&38z$n`1{ zC~;zt@^U9tdH5r^{p1hF3u2GZ$l0U}Mghq&5Kx4w$wKnebey2sgVjH`knQKeiHUxP zqASX${c`RNeT);_;#A#D>jy>xk{!-vaH#-!IiEObld6_2vkYiy25oxN z$7KMfoO~^H2!WbZ3thzAuQSd@#>Sn%c{r+VmgUF56if5vbp1OwTQr#5U`tQYG9?Uu@?`gXR+zx& zA>wS~d~b!3KD)`X(Zso_ZIOyM--&tQcvOndH(qF@cY2GMBJ4kKv&MAu-Dz^b85fUbU5C|`#OLR$C z;rPIXA4yJsP+)rfwh|fR2!;3E-Ae6-61rt2GPqVOcPeGzCMYYhD<53bg5{^ix~aoIEyIXz7bI0Q zezZM6;@+7bLRjb}xevi;!ygd{svkGoUUCbEsb)fOVYQ!t_Qd}u) zB|p~E!63T}_0tklFo|jei;7|h2W>gPS*s-TDww0A%oMe8R#Z*T=l3r)+|HSNn#~uz zp*|GQze?uM2((kyGLa1VR9`msz4zs41P|wqY}h3b*g2vUE0xkvbYRZqL$pDLy_4_~W}Lr*?)2 z8cld9G!hk`NCxJX-PaQ|O}L&$rbq+W%0ftrhfs;DvuGqh7FjC|o0KF&;m>xlhRH8Z zENw2gRV8bmpwfIodRbAGqugquh?j{e;&phwmQbTn0nN!Yh*kjwG)|IOW|Ne68oa6s z4^6~E6wZB&E>I@(K@s6Wa_2z;$#7+1P!YGBHEQtXIn>j;>#j{+l(XPGuqe}P10Wr* zmfisLHkHBtLBvlFWSRlxP^J~S_SUIXX|cw;&AbM*>uaE8p%geRZhLKoe&$UGljCS7h6rHY;3Vjhnlz-bpc?b|V!@UXui0r8u;@GbFq$ zsdo-Tk@@+~=EyH+WzGs@Q&`wZ);Xk-Wm1-lr&Vusd|CzmS*4nn(qV3P-&(k((o%@g zO_DrO|M~6vRlB}6%%5K@B{EA@qxCI1a#l%Zxw&EpP3Te+V>3VS4U$vf) zY>}%5Cs$Z0TDI;Gp`Kv6V4@%+@AvXSRRkL($XO4O3~64HbHY*u)qR#~wE-$6D~r7; zZx0WY0Kn-gSI4AQsll{Q_1em15ZJ(=G0vF2w%L@I6sIk}ZTpVm9Kv&r zWY45946S3|!JrFR75Xd{0k~rV^!1YuR1DZz+7~t~MNf-~0TdrUKpOOiO0Q!%UpoY9BjE z+#kkOf{1aDE;2R~ml=MbxFF&a>-!NsgOd=x(tfoS;oG!*hD>h7`ivZn;{Z4}@Q=`u zBXE<)r{$bQ)VD>p=NxqsC3xZJdWL$9>3|9Vm?%uJ5K+>vL*R}x_2q-frKf0L-UMz< zBk77rdFn%vybc@Oq{;lCF{OBE8(@kMbtGYLH+Knr`2jkxAz42vgR^(U4QmTuo^wGd zyC46O2$wKmM3ZLyona+ZqGF1IBz_DUyIw;u+0S7R4BJ^nN7ueyMn7-S3=Xiou{_3& z66t{{nP&?^gexE^K$%@2hVvhzP?e`>s#cMfTY#3b<>q0O03zpq2j$etFYl9pU*#Tr za=lwc>EQZ49670n5(T6!kZS+pX+g3@@nSM}ZFgoa?leD419P94iCYKzyYW<;rwED~ zk=nPYg8V1~oo!uYCHgyNQDFPHCmL=tS>(8xC5q{2d}uF5m}{xZ47jN1`mgayK5iTy zCd<4OZvU6)7)KOD+Pu`dRv-J0!d)e8R$er5nGs($p{Ybn)^pCXm=x7sGmScA)?fugJ&&L#pWqMv`d%QyT2@X7P#HHWwb zO4wcVB5sF@UVQEZEK#cMZ77yQ_0Fl#@>X~^>k>@j9}+dt-@*!}4d`T5&- ziEd(#0kYN!B3cRg_W&iKZN;}zt)oh;kc5_sKcf?StO%*&;-@5E?w!%>ZKV*fzL#Oa zCXkR;$mF*09N}y{>q4~bf5omAU~u4DPTK3+jGvsK*y4OZq0ByduSpEMK+G`0V8!pkbJRPf0JZ_ z^UslzGPQL~){S>-DMvnKhe$;eNDtzq>)>|3-A}+}5*5VN&(hpAOq$^naWRvCSo^$4 zbvqlQ0oAs?^m>wfPs59Wie4Q{o@hrSIU3DCGSYOmk4xp6(eI&MD)pesx1Bgc96kg+ z0FLMJlOQe?`{WYlI4CsOyhN;lnVMK^1H;eQ*4^^aaE4+nD3n^1dgKYMrmge+w?zL& zRvT_v)FDMKi|qjkQj=ghL#%iyVzK01|7Ct-OlvN*%vBuxeL@w`Y;Wh#TmH_Td&6dp zRpF_=z}5(jvKr@9^KEJUNGwdcq_LDWt0TRc>jHd}L-AFB;VO#l zO{&a%r|h%>o4N+GD&6q8-Lhd^Rwz9n5Bcr#oAq@I5RR^&g?OE*5C-h?La)ysb=DOq_)CHD4fxj8$k!wRTi_%n%w!d5={ z^hRWEyJu28AJ*Wh1|yrWzBxHEWAm82Go_#C8lMST6CK2lpTRb8Gt7EeU?Ol62CHq(iwvu8Dddq5m}iNc?L-P^!0Y%HkT=jMSO9bR<(=Ib%ZOaD32B zw>DY(H<}1-xIBK99xXfog;qqQ?2@{4&fl|(eA>d$G|;~#*LMDvI=m(Wefw!fc!a=OAc0L%D!N#Yg$usccg zo?=Foo_WMq)HFf9#RQE)MQH)&6ax(RMLnprUn z5E)!74PU((DXjf12|8^nzJ7|*WmU7i!<>PbWRLSCm5>RSr<8l;l=?3z=tPEu!=!u^ zX)&I$rwV1FUF>RqoT5`DPbJsW&^#-4_=5f5n9rw9h;Oq zkdy89N`Pq@(S0KX$Zk+r8;4G7{5%UT0)eqU-soMGXRKS{c&J9&&c*MqzeMEL;k)!B zDnpHg(|InvYOpP6$-uIw`x~<w{`&sK8eZh2N352uro*kbi@h0&c2SLLKhXQsOH4?CjVWY4BYxG5NjF^|h7 zpB6O7ZXb>{1!78tbJL@8jcSD^bvWIdoiB=SN<$_i#dJzkLBcX7xw8+=W<8AJqp(;` zXUGHjLI!F)ZcIgzJ`Q7>MZjf02h>pn&%P<;zD4XhRx__|pl^I^acc) zScRY^RuKC7@2HF%DjwBc(Z`B!pC`}h*W%U`p@8(3VrT|QaV#BjGMN5f3M$P`oq|Q_9_?7jo5l767+}D#$^)4N>EA5cSMrASq_)o?(V_Dj9m6Rfe);Ai% zAC>icqFu1HW;AY><1$tEj>-jom&@;HS%A@26NtA_PV@@@JlrmbjG zl)j92bA3|>QOxn`mcyL8%@nItY_3b$qMB&4sOT_2jGdlk-LhuPZCj`sKTV?IfJoWh zvX`5_eJ~os{2GVa+i28taK+o{A%!$kL_2whheAZG2k%Q{OG-s8utEaU-7tpgr#lV> zxW_Z67k`i#mNjZlS_nsHtU67jBvef*FN8TtuDZ*aRA-B z1?J&=L;Q3^bL5R-d@A<7(l()`j+)6@jp^kUP^XPyqN>q*!RQb~XGo|LP=0f(1?Utc zF{&H4_p;k&@hCqI#h_{X*#f~6XCLc%?D0yxXQP4|TiWXxVZ#-w;)}=~7q7*k-3|N3 zO%{!7hew7LfDfEO`jtu-E-?-Yg>)>~g`bTe;prL1Wr!yZrPfeTviV1#Rk>ZTu!$1D zGRbz(&vISEBN<~R`fEk{xniYExzQdGm7QxR;O(yHZqmKV6uREoN`M6y*POutku5>6$Lhk*}8A2--f6H9D-cpJOD`_RhK0zM! z+F4kN1v@{d5fO}9%+U9vXcq*9-^-SDEf#n9mS*A#iN?Gn%^-RNoRZ9K42)8FQzjh0 zV1+u94wof4X=k%F;Uv@>6rI6oqd5}IZ-s#0sIr2Ra*{z6zt2rUrFRiC`NguTXt4|u zJ(<4kSK~F0aFn54WOJk$4gPd%_-j}{b6Wz{?fY5czJOSMLY+YJC({{2dz<0gJSc00 z%^w$1PgWpY*c8;Y#b2er&U)J2lPHu+;xA%ZZ!DUe`k5Oh0 zh~>Go>1T{ifcUx-i|ZM;0#q^ZUnutjEc|A%Dux8e%Yc1iR7F_A=lyVYY3Ik90$zW} zJb3DO(se}^mSdY8kZ4MK<9YPku4MNdE>{au-6x>{Kk)C7 zoO7qiOe=&`x6r9|$0r4)A*^GfL!_*>l;U}biVZeb3!fMaENQGLm zV2ib>Qxo}*=%)j+bXQq%Yf5k89qj`;nj>8McSP?wOMQXJml)gN_!GBfeCTgBuBGFR zR(lghu2cC}U|eN~qx(q013gQ-qNCk z9~ufRwiCin&k5_oDJU1x=TQ7Rx5F*kTBLdF6V6%+*Cmm{dOdwrX2uJhk#dqHRYL9_ zWWsxF*n3>Ik@BHViOL$O=>`+BJbPVh zgM`#P@%d?SWq1>l?{Uv6ZM1oTGn}B|u|VxDg;3FA z#y{I{w-%qhdNYb%V#S9AF3kDOgG8kuemx}p*12+P&x7l<*LSfPk^4h*+%h@`rvOZVb|7d3u>wsj{KV2XF7?fUGIm}LB0;tCT30bbc} znSOTu%V(5u7gePCI>~w(wG&xWk}5h&n2Q{G^1*^}Ee*NZVSI{EhZyBh3S&mpvig3Q zk*#ZxSol-=;TSnddEhuqVN>Tz+KtYwX8%ILC>pQhj~q$bra7s= za?>v5Mqzu^hbp}!$r@?P)R&|q5kdfi645GLadPD5^4JWCSVsh2+gL2WqOf56x0@md zd5g_FwQK-zZ`v?p{5qWahB9W|;f1$VlNu~PPcu0AD|lceEa@JitT`|c$NqEjINx_n zN;U79n4|z%tV+tpIImk_l9b3ZDKyJ4>c{vxS(f-iaO#pe)iGc%t=LQNqmQ~hJ9 z&O41F%rzY*xZ{+r$+?}sm3K9z+R?MtJ3Xsm`^I5d;;$cLq^nSn$@nZ(m8jdnPGFQM`7^f~D#C=3g!)v1A;rFabXthF6PA#fyvPM!p?&Zk|N-JJu(nD>2&} zWlgwBh{YTCPNcOG68gpTLU%Nyg+nef+Skk&IbU?l#3K=9-iFW{FB-$5e{uGc*brED zsQu!uk!gup=0O|a39`izt)#yZ(UBODcQniYAp)6FGS5jdJ_-yXB&;dbym0Mh&XR9J zXni}22Y(`zwVNUb@<)clqHMQ@^6&Jmg~(_NHqDe6@GUaj6*qT@f7PKqVf683yFdE!T<)P7O*dFr~+XS(RO)He%$NjZ;uk5f&9IG3SDA zF1@YYu9PSJAzVxXoFDdy0F6qTvFqNK(0SI50UgpwgEqIe|14j$YUZSQTWdpBB~$c8 z!S;Rn!ndriKtc^=w(nGLR0<57wo`M4B}*||TDhYBEt^$YO7)lu5p^s4kW^*rm@p%G zuq0dNRjbD|9mE>umZHi!`=!aA8Bwd?*KTDrJ1r!{!EsVLHSXNu)*g6})+b)nfsS8K z8WmzYjX`tc@>CZIy-N|$pHt*t1g@((kH%@_$WNvEe!-FgdT?qlE``U_!bPCMaPyy z7z!(;WaQ8ASxAx@=#|tmSI=zz|a{=ng@!g7=;im&|*#X_2^4jZ1Xwm`%);y zQ8>DVm6NPSr&Y4vIm@6tqEMF+u3Q3bkWxoWoqePz+ymY!9%5$(Y08K|-w19Cf8;>+ zbJ}k88FEvQM7emQM;3H2Jp|wZ$;4)UE2fPOjZVPQE}++dR)FGA?0sFHQiz_XGc7wg zBI9=`BearI&7IEPOWuY@sC!dtT{7cHAa4-mHx}kiqlspi;2MkaI=<7P+Of9}A(KNR z8s@JlA|r{Ofkv`D5?_wMDrd6_7ZmhD1Ohy3F)iqAr3OMi6-b1L|7M!%88jp@JmD02 zl}o@{psx{HvBt5Kwd!c&_TRIS#12?E?ZC+jB~QNf-`kx6F>6SnKSgTe0d3C=-nJwo z#sb|adGZRD_Z%BI67(doM{1oK*yoV@)RoRAj$lLyjtR!HMbi6PF}<#Z@TWn%MtR@P zr`yU8zNhD}^vM{8{xq3jbrBk#Hdq%sX5d2ME0nZ#X(dGEMa0QWg_5N9799>Rr_(rW znCb^Rqu0!49^q-{Xpb`$x?}2@8h4AUVHhMwI8y6XkSvP%&hja~0SoO`S0#~^#Fee` zRT`pYh%P52Fd}TAE!mt_3AG}u${3nYDINi3%c)?q648+*FR`yRffnnk8pNJlXMj!)3YZbT4!U@avu<0`(`WDd9`HK?B~yMV1SWAx@02F@(5 z(opPF47&bE*^8vP2TIe98ee^IU-5HdNxt*6AT~?U8OP4J>He6al6rINhWtXAGH9@7 zjhE!6ed1o_WCz~k{Rma*G>@RMNI<7vbAIojJzC4qe7yR8utG~s6dDRGDjU+xW3{A? z>{E-xVaz_OB*fX`BVDvhUy-?(tXCCqvP1v1yFt$DS>5S-zvJ)<*Q=P%w8p`x#Hb1W z1F*S%ekEBj==UEs(&Kiq_NI`0}P;^9$oxBK(0?T!Jy_g(e<(0H}?+wIqo zuf1Q9-fu3;yFH%M^}RT^x-j)Rm23o$wjF++Y-(@aeQU+unjdy4d?1=ftM*fWhP@=& zn7NjBrqmJNfUgZf=z^`sfo(N-m@YhL6Qm`AG@pTz&H-7w{5m;I_q#XmN%l)>H>TCp zP4!);^47csYNcd%y;XA>q$FA zNcRBzxzCGq;z4|t-vRUO$_Un%%rJESn_i47t|v>sp5D1wXdzwW7*N|?raEA05Cyz+ z+LCRm*^zI@>2{pSqhWJYA-@`JzQ18+q}uAGL*=w6Edo z-@^H)_5ly$8EE^i?FbDqxvTV)WZn`m)1Su}`fOpA>oy^3o%o2p#fjn_6Y5ip#N;l} z7xyhSEg*4Rwnca2emjXr=y#@F2iN>QN73mI6bRO9=I#D+xls5(<%sJ;JLfE;m)oR2 z9rDEn={kfc&h&K%0TX*M0(u64;GJC$L!P- za6}8goZY}D9TIRGMAkY*wwF=&S}Ln_F^Lu8S5C1Rn`)TgO#ZQU+>t7Lnlm*u^x|C` zIWVZceQg{!PrQgnN2}y>Am(~}+jtw-6nZB8qLQ-T)%hB++mle|Jk^}#b3b4!@G|K0 zvS-%)vj24PzIRgn=h0T5_kHD}3;wCt$Ln$V0=fIqZmyK}SkegGX}vF*dac&%1WFAr z>$^M2kSP8fHkpU&A@`rVwJUTAuS14vp4Vc?t2;7T*bsf9^^FU_)>xYB^$VyhHZ1pz zeMa9h!inJh`TWtPX2UL{Nnb}}Q?<4Iz;>3;qp293o^m;UA^@*UNckBRp0*o*FWGqPFDQ5N)c?`=7Kfx}g zhuX?X(4x)z?vsJ`;ry8M04D8W?Vu2eO`LaL5iR_LHpc5VvcA{Ni@uNjW1lVm%YH;( zb@%h>sDRh~`DJqTpI1DQk-md$uebT`*Q0s?pSzb0f#1z z*=49nLrIG3vndIwB2?_G;v#T$_xDC`yG^cI;>&nzGRULhWN;MHEXf-b5y^|$&9>Pt zQZDX#k=%5}77{X~HMKXbj7HDwFH~5$?GtnzgUh2j>U49h*Urc1%{OrerKWl=QfsWt z_jjy|wRfv0hq%IvnANczf9~OLP8g~`lFIlUR^|);z@c;7hU$rSiSNkCZ1Qm8u>FDA zar2+CgKn4f_Vu5m;;_c58bT&I4(dPtST$)3@!~z za_e{Qk<)EBbZCLz=SXZ%>d+ZeTW&^kX@aHGVh?`eZ(9aUZoMHl8oB-%x)mkT>MdMf zIi2-TRk^e5u3lGEytU!a!pjS7qBhhR#%93_+A4G&xtq3+KVZUtz${q)fZ3U(t5;*k zHO}qK_uzC3pL-InE~)3^5%lDgytvYuweKD=;pGF?tJUoLNHQWlcs}|5R?J9Zy?Tnn zbk|Ioxqa~ZcAFT{D9h2U(tK_N!o)U($@*E=mlmx5t6OhSJ;F%Sl%UHvSVw?E^|j4- zi(GIU&5YKnp$~Aj(SR!~jcruH*D0?5tk$N)9=8mWiK}LwD6hU~1ua3#nsi0LS~cov zJ9TJg-jLv8?qS;!d?tE?80A5fon!yLvI%1$lo+utXr#o;D$)u53n)8Gf8mQ`Nmov{ zvjNE(jjgV^uEV$@mz+>`)jL>Z)^U4Q%yZ!Cac`JJj&r&Fx>Z+ z!X4(b2Ylp#Kq+43wjoS14|?`O*uvbQ6D|K5*Iv7apk|1hL+GHAjX`6iPjL;+*Jl33 zz6k!s)pS036kCmc;Gc!ZOWGt>b?*X(Jyt!3_j4FN|<~RkE{m#B=X*65U_=Qr9jEW2t}Wns*q6mA_?jxcm?jE^CkG zl3p*PIR8}E>ycX)gQ)6n)$yYGi?Hlt(%d#}N55n5@eqZ~Ojq^1ydn4Y)ey@v0rnD# z>$SU;8X>`1couN&#*iHi4^@JD8H>t>!+Erakmg z+qOvPzFWc8?BOk%7iwPT$64B+x-a=!W8@*ywofiYx8R&kc3-Xx=*glkEHlY4B0NYr zp@tPYxetwLh#F1wD#9gBGX%#ni_2cs+(moEp})kpY8Ayj|8q`xaT*}hT*0(Zoe@Cv z<4+Nm0;kty`z*Bw6|*P@)74t8x!3Oj$9g=p)fKYO#s$a9t}1Spv>HcKIm{08s%Zu^ zh?`sJ2uF8WS{uP(9@k@WRhbjnw`3+AkS&$!_f{B=_hGCfyiN1wkk-(YybOAB21JS0 zF)GxI2K)nlkzXOSKuD-(A^A>>;%CT9V7!9K6%vTegLVZn55@>#?wv_mOteC>;%aPb zQic6jm$G$h7<#=s7C7<9H5b~;!AJR6+_;+yC8UPCmK`wL>WNlNBKq}wNmx|eCv&5l z3~3DztmpzW!H@|0Kas}E?AUnW*I>#7^LGd-+b4OHDX!eN7qB1CFHiEjA6{8q@ENrp zE3+~O4L0fUQT)g0CHDu1^swK(3MDMzbQ#`e@AW9<1@;1&7hk^ zzKQA2hfKvmE2Z$nuFK}V&0#^8-qN}*sBV{4+ZUDCd?FNrP_D?t?7GRY#nZE$$EChOU zdtbBl*Y>L$Ef`VNqeJfDMCvW^p1A_lS!bGfNpy+7I^ zdUG>P)sC%8aMky!iK(@;7+)?6{Vx_KZJkq2*eN?%jQwq^x(l?d-!_>6bM?u(#QGT- zP<7w03~ps?o?;f!ulJU#QD>JPj{^!Pj;<^cmzqJ#X93*;dtKKhyiz%9>jLdky#kaI z#k16I4rw8Dr$NmetM;%p7?Q05Co@Gm^n`Av}1MnBFFYm9bP@4Oc}=>Wy8#*#$d4z(!T1+q`< zi|PE&ix%qp_4E)u6gdIyo&BF~-{Ri)3aP(dXzuCh4FSOCo2)0r)V7EQQRTY?{@i(Y z%mS`hyQ=CVyR*rioFzJwsmUXDHTve~-Ty2{kyK}NukG8sZ*ja|jeoEb?(f!V8^N#q zgnXPe*0S$GMoTY8WQ%>Is|_3UWp!XD++CjxeFw4z7oC!>Y{C0)CZi<;UuVsH{%l{K zY;?bzmT$D$c~&ZKLQJ1vXPtX*MNRl2fQs%+4 z`Rqj8aO@)%V+?ij=bE^hKRHBKrrGeEB&&11#>cd<>*2TD8FYIbhYgxFr7g`jcSct0 zU7O%?e7(4SQp3158rQ0buO+_nzb5<=l@fJHzvlX!{O`N)5xfqIR&GR89AbiygY3X< z?t3=I?VY!$)aFX%&K|wD%jKiq4c41uN4v+llc(H__M$xtcDIPDC$DXt&xnglZXKS! z1BT0qYiq;?bi;buAfSPB21j5$7^-^5R_?RMKs>TiAI;bFA+_d^DZO-@B->5^5oAUb zwv#yRZN=Kv+R3AK&r>)#k#GGKh}rtypRf9+r!&@wP9L%d@m((}y zA;kNDSN_4$w<{UxUJ*?CrWtjmMQT;&*9PL$pbS4mi4zumowLcxB=Xm)Hyp4tKcte5 zPVamjoxzP&rJJkx7%=X^=?s46;wN{)-#&<7x@=E=H0b`Ac2#MwPOm?JM-yq7KRYAR1WU}Z-@ zK;I@z$;aIY`EfTwf832Bg7gFrZs$P~CwdUaU3~{=3T0epI3qq3i{9oAXD)t))iPCU zxDzrC)@NkdNWx%bi%D9|YW%7`l0^zGU!ARGn6-PUixeW$wCLNLB%>sbRkj4>Iq&FN z*}u`Hx&+q*2X^0;Qqt!Yvs>$!7TnTyu;>1knSZt1$^5d8o(Ih}>(=FG@6o2pL)xCS z*9h%AdpJ4p-DAG)yT^FPTd{pKn0egN3x`c?du(Cng_!G55F+|s~Y9*4%CXN?Wpz8=qzNlR88kB^wE#?*~W+$ zrxh713%;>0d0NO9`$_9lM=^|j&h{=03L2jI2pDQ#kCEUb4(>dBdy!)e+L>B0v8#3) zwtJmG92G!u_cIHQ+o3hi{; z`^(-uIGt=iEbJAli0=pNpB7jLLuk8F_FEhSyGVww;*f7WU^cenb)F8kOFU^G39BAS z9&PZmiQHV1juX3wv*Xb+q9x?l43TaX?;9hciOj zT`axEie3<5`9?(8WB!TQxvB*7Y}p6mq8RVvIU%?UfN31IBd7{PO5JBJWo6*e!qA0;68j>1Ca0 z__XWvIPR;Xt^?MpeT52WpU_0$iuUSCOkd>(I_iGrt>coq?_@?#zG~*#Uu07seEs;n z_H!4vlD{Z=M7fVquztg3><2;GyIIl0yMF5WMsx{3-Kha+tg z@lEG|*1ewC7t5lQ%3hxYCF2r9bw@?hYRHdnNz2kGCh{d_U@Llhoi@V92qqm#A4S2g$-A= z!9*uZoaiR+NCOOb1WO$6j;!9Rbuu`f=xP5ykJ2;*MXL{t^-Y#h&{YCGj6ryT9~1 zW>#hv=6@3v|3T9G`&JvE`|o$azofkXMAQRvv461h{u`Dao05zTG&AhV0Y=x)gkFIR zv$A4_-!Hb`ujj;IFbr$Pjft#Uw#kD}1)1OD*({Q_Tuh)z@C0Zxzut?($9(bs(eSIj z*9|>-DO@(_fRcaIWqm9!*87`qq`cTNAEy{SYCnxWOuK-Ld|iNu^iTzWy2h~xZLEVh z>$Jgkt}SJ_>5BdVDC z6+Jh5zSn)8L0c;jhaD8xmwA*6pV6E+w30ZBGvuFXSv_+ppD;z2*gc@2s`&M1J%iOK z-g)sAuKuU|>pRTkv)+Y30i9Xt{}~$KUv}t!aySR;|G?jowV!`7!9sZyeS>0pjC%;n z!*G3PCj)-=abJT}#d0nW02|csq#nPUEjo|)1>%b_$dQ_!#Wz$i$~6%1*zuF|fx7ih zFfRTJM1T3H{|ONb3)6oOi7#Hpre6?N^no858>jT??tnL1TvPVEdpv(-xR=H_hpOZ} zZHBC^V~#vT`kq4HeL%&Y<;g9Nm|1T1Gstel>x{}@0K6(7l}DsO$xy*oH?Pjq`1JMe z?sl)|<=Pp?DlvD)3BQL!>GASMqCvNuUy6^5 zHIJy!&nSjlL;rM-IrTO}QDvlUILn@Og=v8(VDr*3(@zybU}T) z>4wAO&%wM*e>fgXs2ruP>_F@(o3Fvc1fb7cJ!8nN!G@3(QXF2&)t?u z@$blNMUW)2=2$zoKL3J6d?;Pm{KTyj-})k@r;aZ>gAZ|Mk_tMf?v3C%zrjkcXriu5FG{zpR zP>a3I$@k4IXmXClh|=o$L%>>WH9eK`IB(Gdb4{nI61TSRsMJ>qhU&%5R>b;+z|s$S zx~()#t9;Pt;brmh;qFtD4cy*jLg|-_2(chdPN@B*P2%hAKoxRM+Mas zYO?~w@ZMHS?Huhw8=VSQyDl=GysUA;@&h3U-o$#!wtXr`XXi)G3r*XeHzCKB(2xpA zf*UB*6^Z9CE)j0O-)V{(g%55m2FLGj`sPto|1!M)Q*eRI|AUmvr@$N! z$qak)2A>56Tl1FH+1g6-@Xp>lQLuy=5F1GqSORz&rAaNkHX?O|&$$*b44C^K=v_1P z$UBb}C?lKCABGa^B|e5RHZBjh(AILpM7}j=#{hv=`s&PLUL311!C3rfo5ek*sw0zT zAc5OA5>HoUz}YT-L_nq z@>TzZgZ?t+|LvfEQtjb9mn`D<~fj)>wl2Vl%%3RvRV59<{v>a=d$(LnG$5a_wHyZpcjxis3&$urO#sK zk#7zXH)_)0p2&hh);Z7r{PQ>&4Rg-umEo^kIp>;V@dZ9yZR5{0H+r=c1|;SIn)wiF z{FmH1P7pCsHm>#QWKSsKHn5~kq{13J!qoS&X)k!CHQ(jPPObe5Am?2bs<_3KI9R^) zcV0gfdk$@1|7{)q`i8#Zr?#(uH^x@OC84ksN0qw6G!T);){X?07QP{xI zW`mcso7WPgbLJ8s)4vruZa{~te)5jJv_*Wgs#`e+m zA%7rh;%MYxVF$8x05Jbc1>t}1%D=mn1)fpf!1`mJ|C@=AdH$Qd``4750m#APABqeN zOiX`u9X>w)yY^R&;RB??hfu_aD8=924;2S7n-4vOzcLd4k9@`de#IziVQOmfAp-GN z^+6lJ&haq;fb-*4QTaG9%m7A{kH<&+K7=m*iZuWMjPCywmS9x3Fb0`_h&=p5DdIm$ zP5eidhkqW_|Ky;5IPAaohLwTYhoS^K{6B{OU;P4L6mm5BD`UY0{5aEpL-Dsk4`lhs zpCSf!k|q{r=AgfE)A)DwLnPxvzQe*u$i~ddhRpL2MWj$6LkSH+DbK!+`X$bN=Xu}f{k(tNPoK}#wXbdOYp=c5y7pRY z@BQ5eh7rZUL`A_%FesQ98k7|W1OSb~-=V*wzy*#c5d-z1cVfY?j1gbUgYNjwpu{Ml zJ46K3Dd@r=Q24r{pyO-r0A)eD_%sR)7$J_oM8&Z9I~MrU7?6)aAVCM$+C_tQMZrgc z!b0`XFi~(92h4)*_zMY@!{C_!-J$mJLW39xXaJ0*gxVAZb?{92MI3a;>krft8hU_3 zEP}{}x(40Bg_jG|+}cGc3c84|3Gw%L0uZ?N3glYrq7YSp@?UE3OI*M1KxCA^2*Fc@ z7DIpvYjTA2;15!vKH-%KC=^udpSM6n!Qqtnzx{jx7J~&JBIU9q6_~F-T~>xuM6rq1}+X{2xx_LfWU}BC_chL4yi_A;W zYp8ZDp_hz(YvMQKmv!UGTU2l1jCbaTfc(A;&C6^HHC%%A86(PybyxUbDMV-7afjAEJ!O%t~fmxDSTcgp%V;t=#7ie#Mq+=T1D>X$? zF0;qQ^0r~2h4Q;$+{5aDkGJ^SkMs`QOmY46Y-xMaia*`BO9myWLbBGq|sGLQwyUe?Mdd7 zB7U_hqZ7SCp|2%<-5!cI0*mVU=%Lax`1k;~uU*}-)E zuQ)!uix&@w6I`NS(yy}4e+JjR(1H`n@GyHPd*-!q6Kb3?%rsDArsS1zX}L;9AxwV1 zD%T5F`8e$oJ_(-7rxTA?@RjjuBs%rB*YDc&e->q zb@=z`xO5VFIHF8Y*5g=O5|4e$lNyxglSvM9W4%xU{8{gl{^Sn|y#<94#YsN7A-CgQ zjqVh2vf)U_xumv?CAU=!u_Tk=-NVFBh{+Q?gE(__3YU1a;HJFuXCF$1-fF1~H=5VW z;CO&>9Q$rie1I}mNzi|=rJ93h-1FqhK4R(J_Vpp^O0?W0E;ap=-Cj|AS6_Og9W^<4 zRCcD3RUU5$6QM#Xd*K=)Z?4=eB-7uWO5tXy!OeABKWk$78Opes!IC>Wk&JtqVKK*- z&c4}lGM{HBl2vPAwCPUS2crqZ!o6JCW=tKc125_|qax|(?r3f?m)#m{O^-Vb+$wvt zapTpMSEHg#7vrL`YXvxynvCiZ@>+%yR=4FS^a_%QQ27JZaLryNinAvx9twO}_|(ZA z@`BYvUp1=^OFL^Fh4r<%BYD7~er(sL5ozCuc(IybAzy(w?10tRA`ZoU(|)60lk)hA znRoy`PO4~h@9M3W-}p415I8s*O?FScD>T&t9x7|77A}X?{*E&-69cL1x91u@&luy6oZT zs4JJJ=bejgew1|Rwy}9-lol8CCVH}m$znF`!eFP8i6L*(+bcE_Wm7uX-Q*aJ+*^5q znZv@Kv;zl{kAI;%RMnHh-X|(dA?AK8-I@<=nfvYXlk+Pf$X6%TO&oA}=Q*TI6^>3# zksk@#ZyC3Ha!ih5TD9KJC@|)%B8lAW$CCE*6tgczPPX17&xwB|$!Bx-ojXq0Y4=r5 z_STQt^Ka6hojTmTbXS1qv+}b5lq>J7UGqd=>uC6okx){#>xFilpI+T@>K8Vv(v?uO zu+ntRw+}w5xv0(9Ti)=Hde?%3qCB5l#M8GY8Xi%digjT2RQ*cEo<4j)jaGl~MYiT# zfz)8nB8Sm{I|l*Y6IyyeZ^7?TjL>i;baw_0ns=t@s^S(f@}D5- zC1yA>PcJ_c6vM!QydW}#yikUeoR=6(aMpU@WZYogfHFV+N|L`r(p3IzDelnC)ZDqf z*b!lzsJpe*Ew9u>s?PAhLOMftFwG^~8$FAAz1QKmFXMu0KJU#G^b}qD{MqPJ7tSzf z-6*6%(Dqz@q?XH8TTwfbE-F=#1-dHzIo#otpc@n~AQ9Prcy@yg_Y%X}=ROsM- z7xLTeI*BnoQI)p4n-kU86~m69+f-5%|u3Hv_=OX@pZ(eq&mxCF-B8;%!Q~`ek(h*Uq>@mZ$UqkA)={u?S)b z8#uHSDVl!ZlCA5p6+tckBlQKZR2Y5YUYmOOcI<1mK17S+sEX5nl+heT-KvO@mZC#G z%IJ>6#vvwtF z=NG4^;B=gGWNuI8-@5$fgs~6-ei3j8k?5_=qiRcrDR5H1!}^QNbARM=W>?A+vYC5X zNRr5>t$wK##oa^abA%cZeP@iPAf?c!Ciw6Nr_pzQ^{_m79PE+T&OrB>EKCH01X~j7 zkhz#;Sgj&rd(yOfmNfYR?6-Q#D{lL&XY`eMgL3zWy+wubCG(%Z<;g7gz7=zvH&S{W z_8Nx^YRkM8-G0ciJ(^O&<}s-tefcXZ1`Y9!N)=oPOEmH=dzQ!ki}_Nm=@L^`8jte1 z5(ayE%TE|qmb__$HRxxmWcP#&4mp}1MjQWJOKB5}4O zAE}Tx`4zIeav!HI9gg)U57(SerK-P({V^uuT{m!-=D}-eq}*NZ3BJS4PC6`!^m26O zlMzhW8QQlD>tE{3zFS0+oje_qNoC3UnWBX3u%mJ#@mpCUg_&r*g77d~ZiX7BVOtAU zv&qNzwiUAIDa4+iX$j1ElpRu~&?uv&@%3P=x{!XelP=4NmFSSZ3+`n6Ip~kkAA61# z_fQ!GoumJPT~S_|?04V{kZ|h%81#k%)r6#fWTu8SON|>l^6G`*8M;EY@&}LHeK=zJ zoz+X;U20v>`r-by9+pHyU#Dm9&LQMU9O}nVX?}UTK1N_a;^;q3Xrq_&$+`5_A=FfwBLSHb3JJDgvWnrQ+Hh?+8m?)+M^KG?p&fG?%Q_aFmfFeTiz*fFf4IPzh zB)||%GJTchG>xjdEuSDixjN8J>yIU+xDy!_8*f0h6LEz@PrtV*gN8Tdjz8~7zU)_Ba-(t zZ8Sz^13CM2f_(*|`zhSh^c!x(mNwK|W?ITo<@(pFspIfE1JrJIK?y=>~MJmg0TvD5<1aqI8CN;Jc*C>L~ zL;=KoHM-6|%CFQB2~QJ6V+cIakVwcjo0;o=^M*1EV~K0j*(?aIAB zYe|KI%p>M{%PF<|(3yyA##_%nj1_%W${J)cT9|#D*_Ec#)!vG2-IbcmRB`WoAMN10 zm$7oiTyz&FYsad#kD&FiDr9%KYBTNq&cJ?onB@oLeauqYXfr;=q5k#A^GxNmuu!qi4O$p9w;?2ae*B*}U@tWs(HX(AX zFfehR;!K5=NL79E^NGpBQ9I5S5Yd`iH5BBfXUD#umh$~#tLUl}(ibc)!5L}v1nWEc zB!%5*%vh{w)RC*G{MgG`j@L;d#$Vp;R-3ufNI*IS;t0f6=I|85TU^LM95I(m%meqP zT*zWHAc z#~EKenpko_k3Y32Oiwcwk=Re)89A0G%XLBGUQ1MIDeAksDaQ=w9K$L<|D==oHsRb^ z*<~EZhra8BI&TwGuk#C>Vn6x(*cB5x)fY0tw~?B|4@rz(Ka9zfem-}I-9zFdfzA?e z+(ozW!JsfGJunCs>A{g09XJL}Y{3AFy^TJA`2gjF&362RP<2jF`C;MR%G8bR(4@kaaR+J zS)nK)h(&=dX|49z1ej7MDd_baMgS@eRFjOXAN+dg(#l}?|< z>Pzk;V^lmC-*$AWh&WGDw=v;V(8+g}*5eO)CAT;2dt`#mv2sZdIiq)m-&wsoW`x;C$2J%VRY- zE$R2e4DsW^vhS#Un!9vAkJHbLjd@J^n4LaHr#!f;HG*>wo3F=B-0g~PK zSqfR_M$g9gd$gReh-7lx7Cgk4J$XvlXn;jxBns6sp7kx@QMp-MrJwrT@}d6juRloG z`E0%tU?l;60|A!T{^~<2hD*|ua8k>k*G%PF;v$jhwn6e?7EfC~bHLU18o>N28GQSm z`vy(=AVeE|{pSE_k9bIpAhn6vtX%!W1KQdZ|@&_&n%p5hh zH&pAOD7#r{BTF%)i+!FaeTain;tPSk67XbD&@%L2=Ua6u9h>0PGooa>;jl|QU1Koi zh_cH!B%kLf_f~NnHAQ9`3!iD@H#Gm4DSzf#)`eu7tQFdY@UeLILCy-@{@C+-m}7&^ zsj?L%3NAWRVXBD|>D{P4Ebf>W@YbnSNOAhGxU<5LUUo0z3gc8_UaWxyF-@?4!64J9 z{xF}xgS;gV?s9SpSA^k|F0JA>n7-Z#3qx5?>>=gB-U|8}x+Vlv?%uQ;~C=HYlTTlRVvR~sxBv4@l}&zD8FRu zvbE1!%yjCXezwvw)o!EX5FWGec$&6-D22g-{j^o;@q4A;#C8^6T-|np<-8REQ4ny6 zkYJVYucDCFE)OLIOHwBOdkt#6-sjjd2dibRepX)ovi~u&B931)A(BtzOf-+7?uf*N z*hboO0dJhFFg*N&Y-1D22JU?A$|Lm%tFbpITL8`)Z-<^;@RF`(zqE$TLPn(oTr3 z8hrogMsr8^I&Xy2>FQC_q#RljI@ZX)!?ph-u@5(aMANxwUDyU_@ z1U0%O;=)pEPB~|Gi@f30eYTlJU_pM9Kem-&UoiwMn80@^K>Ii^9rywkOzKB!Xm;^9 zJ>VUdHfEzp;B!JX$Zt=k77Q?P@%bDJr!qdG9d>gj-TZ0wThh>lEZnELozclN`J(~v zwh=;N{N z){9)&(`^-RAF+&Bb}PqV^v#kR{>9vYNzoNry{h9$Y6tbXxyp$VUs!M zuNbC#&W}Co<@1@AM%LLBKg7cGq#x0SYd&bc^R`zqhMOb^{LIJUOv-oceLQK`1zyDC zZfXj>*%Nnb>imT;BI%})(4ogI9lJx6?h9o?2oL#z6R5!Jsu7_#tnd+v&<7y-T! z@M{pj@BX{iYhh^{;M6a^Q(l63pD`#MiP}FE{^N4NR0v@5T7-{E3u{nZ z3C9XLR94V0k<06F6I{?4qvCT_PG9Ai%<&|3&iiDh%1ix>Qu{Qle3M%O*&al-O_9vu zju)Mo+V+0eQEroBYRjU63TJ6^Qqd+arilf(Wl-diTSwL2Z6jk?da`_Z)@jb;;x@A; zIDWnQ&rRXLY;4k4#8#HlM6Y+yfbPl9CHhj4_H^Hq(z=#%)qV98&uud5cz7G{AhTaY zh`hSlOuXf59zCrB8E&q!3Ki_G9BnaDEjx8;R8of8tC;C(YpF6%Y(XE{&G6P?Lr1g% zOP5qY`t2De&95SEQQ0vp*0inpy2F~S?Y>O$yZc;Uc0VX^O=Vy&6=+D4YzlO}!D7Gk zeJ(@HuL^p|BaGNw|t^e_Z53bprZs_I}})N|7%BuaB8kiU_+=IrAZ2E ziF{mY+P%W_;c97Ql%f)?*=NL?fFRWihOn~q{>HM!Ghui{Rv$i-9#^z zAKyOCevrKMW1FDc1vdg>A>by0T}XeG3JQhM1u+qvm_92jVDln*r(ma#AQx45EUU0Q zl_lKK!Xd-V#$vmbAq)YlfFiW`LaX-~>FS6U!(B);6w-0WR;1i2mvx|~s! z{F1jIBlWYiVM52tD7DNUHVw_GZB6Y>Dk&x^%P9%*stS>D?=BV{{v1#nDJ63R(dIpa z335y$J21(f$!ixXLE+>Cq{(diJY)A;+kSv)LU!9%qQjU@I778HA5?z;!KB zU*9F`o3OC|y?AY4ZL+C& zlj$c0ENyL|<;_GvYD>EVx4puGYI~B4GtHY@*o_uG?bMsTaFu`{2)J=u3)C^k;6#T_ z)VRnjVK0VSahy%z9j$$&o%kWq*>I2F(KpU4vi9+5tcBEtXrgadXbG(E0R`M_Z?@n= z;>Tm}21a@CX0{0u+~$6PJ!+fZ47O4IRo@k_tI?8jf&eoqEv&YMW6}jV?eDhw-utE# zgQc{;o=>@Nsk6N)ep*RpAfd)DDi{ z8zE%vRObBxLv!z5jBaMw-QaZi^)Dq3OzbDpj_*GcdC0GkUu0;kf~_^Pzj7okxcYL& zHUtHM-Vks*P++0_ue}k)VV!`x2JiqEVct$J<_1CBvr1xXk+TjB%GX-$M#}nSgKzI8Df{ zcojlADy}4QJ1V;cK3}o9{n9c{;OhA5z>aqE?KHu%?na|2A-7a6L?L`% zl3l$dFyLq~E~^JqvD6k#_4wfRnf;kdJVj?z|6OXE{GBTyd_z-BuMsS^WdqiIyJk%8 zNGHg(F(V9VWPReIBO)Aco zFNdQ{aig+tB!()7$hFM|D&>S2Z5yDC%}+z0cDi)H=xxiB=ciITnLdz+MAwX6JAj_osa*w#g4X&eoCN&EC_O zseAD55UI?yGN+xxmiK+)N;xNkU={~i1m(JN6d9NuyLmH2Yrt&6NZkA3R^80z*gZbm zx9N+s4onTq$4F}(c+mXTc#3s+6|j*SzYFrViFN?mv^Rc)$l53@3Kyob9Zg zK(@83{b?&u$HCmq4(zzLc0COfIqhUkDdK(>q}=UXtpPa42K@Rd_}|_Gq}>3kx~r!8Y*DVI^Y~kL<@ig0ICGQ z9$+H+Ff5o~H;0K>z(g!zB7lnZpc)Z-2ps?uIRz7OfQbP3niHi6pvW19K!6YmkmCl( z0}tT69x#!!fW?4-b71c|*ew1FgacqNkOZv8L#=6}IATLa$!{rR5--vFoy1k3q91K$8#5x}$jUx06r{{U|w z0M7qk@Qvud2j7STKokVZS_iy=(!W4AzwZBI;2XU4_=W2{48U4z=1d-jhkW3`&_^s0Xx2$17P)9$`J;DcKAH-!`myc#){8A4IoQU3RoA&iv4WO z8M0^izyG$On4kT`=d77h{4_CO$4@f~HZkDe(zPdGMFH%3 zEseLmKz-Mq@YWkY9{^|qzli>mjx|#Z7Vq(;AnObaD?aT30EBC)vjAeamO2L$`^jm% zNe4&_sOUOF2%dlGh7v#}{_M6A1fSbb6ngisqH>7!SlNGmq+LW_4iplxGzW8CkolEE z{_A4Gki`Zi;ZOo!81-)o13s=51_^v&^uH+##-MdHi2loxz)|>3D&}7n1L)yjq=E## zb+La_7y?b<`vnp*GEn)S2h2bs`N_cFnUHigWkOQ=#cB-*DhZx}c4+`?;!g={AYow4 zSjz>z}IRq|d9%I;^g%(#?x{BRFBg%}AKc)ufAK4qKJxm^dZhKJ6E#@MBj^tNln zYz{Z@68P_O3L`3x0=_>Mj8%YB>z@Ag!#Yl(0W|w>>-mo1kHLD=4u#c(da5LAhpXZO z?xD&@nfSh~mgcakk{x2MK+O?plE-{b=_Yw}FQi%Yrk?BR7Zof8$Z#h9ruA zGRpj{miScj?P1AipMBrbFG-?DJ$UPP9e7E~qFW`9u&z2x&Mp!ucdyd>8H z>UxI#4@A>g;}=X7w7f_zrynD*Ap@_e|6P{-XDZja;Xq`opW!-n`cG7@^@HVBS@s{P zT#(D~=U1q0ZVOJe5K*(Yg3h)8$Z^P^Ku2VpJ_8Pjz}xVjwhM&qzbnhTTAM>Bc^m{s zZ8$rec6YG1fO(*V5pZE~L71JpyR(~wh=}7qe-l3KYRg9{0?yp9I%8@5XEkRl8<>T; zgj52LkUiJ zz*2&<0e=1izLzL4!8Wje@*pz_{ewCE%tN7(Q0V+;9uf(i8nQ7Da%4B;i9*iZ#yl{g zu`v&jz9A2k*i;t|2h?mRhd_%$4&Wbcz~M;Xh5VTZ%0XW9ALUR;F)$OdArA$IPG9-6 z90~>D>^I~=Hhp6r7IF#yD2EV3Z>oy`&2B0Oj&<17H*qvLdSb)-(9jtV8}qP`WBzBm zq6qj#-XlOzwUGx1Q7kx5VnbaF5^|IOd>;k_rl9`JL%}!84F$jm8|g!0#i5|-kN2VQ z2P*xUhY%NqLWw`hA;iVOF%TQ_ut@mE_aU&T%{;)OK_t1cE@rcgu-Hv9N5WB182AS* zNC2|f$OE8hP^|Q4IRudUro7FvL?Xn%6yJur$jx#?B1NG9=Fc{eVw-6O%-_gABnr9d z+XAQBY|?uqN*oIF{%iw<1;=u1$U`HblP3NwhemGh2O16E$a^GOY%@>M&}_tp_lcsQ z@bJ$zz)-SLPr>G2=)G6jX&D}-Plx4482+A zV&YH`yP+-?yGfSf@Xh=ahfWvUP*+@RGf%N#;NMsdi`c9$SZF`ZhWB9!jEO*&>)Lg9 zHMe)LcBO<)1<kxnV;Mmi;xkdp2YknR)&NeSuhMv#^ikPwvry*=kV z&w1a&dOhn~-*U~GxohTEd*=GhTu84bEz8Eq&W%Q2u?#A2M&ks5K~82*(S(IT99rJa zmLLu(Q+HE)CudK?5Wzie~9(0ezAGZy(4yIl6-&zh2f< z`{Po^%Uw>>-PGL@#Qnz&HB)zYOIJq_5A+g^L(|68!q(9m#QWz{S0{5#OLx!{U|4Bc zKomn9MA_UKQO+s zrG>4jq>~pgA{h850On$c@biN?Ir%vG`9WOVJnRDeTzovhSR7J-mOxi-Ab~$*m2h-) z0u^$((-RZLVIyv(t-4f2+pd3XoxT3x_w(!dz+4#PlIqwe%7b&fpSR%jJ;vMX z9gE_zuRCGEovPK?3;hQgT-qla<=^GLnvTkw!OU}u{qW-Vd*OA8!{8k$@rDX(b##H@ zb~I#*qZ<43L8gWZljFD!&$N}0kR95UummRSo9nHUne(Cgy8vbH(Fy(H3D>s|tWqt% zf3y02ytlJAAlKDnx_@;x7M$*nOGM}E=;mn_%&=uOTrt}GuybdRG*A@MlS+OdK7JMQvL`1G9mEN=qZ0uK(Kv<=c5*$*Qyk`Q#oYS51O ztqlkHySaq#X8w%8PEPMO@eg-=J|Tj~Q76v>u=7efi#To5Vyt*`G%=XH>l5;M1kI~) z;Khs0hxySwI#EacU&h9UDbbkNWv(#pB*=cFwLf4*s^~FC>8A`vmXA`-x1_R+$-sN$ zh%tupejo%ttRHm~1&9h%vE$D-p*pO#Wua1h-*3_%oxJ zTv#HkSWGMuIXXMCosg7h;Jg=AB0X6Q|ExqB0{K=4rJ#HUEm6n^Uka{Q!@R+-zMNF= zrSRJ2=u@uLtCNshuz57U|A)R2`iHT1QIkuQ+0 zd`)%W)8p2sD@z!Ko|x0VX9=5_7E;G1+(G?0lpk`Lmrcz{O($j`&+$b!m_IFmo5q;- z3l5`sN6EBWe(4i+RfvZLSb+?zFUR=By8$({Gh61z9-?~V1LDWZYFOO^Pt=PET{`O7 zLts5wzKnLy(~%3?2<8olPiuyHYXlNdtv$<&ap+>iKm#m z#Y|hUzTZkkNz9{m%oG=rI_3=+Z!s z1Y@QpKT0ORItE~cPK0$~X`y`%iB!qAJ&Wog3FmRAXhJ>6tHE@s|A0XfW;g^pEKJ{T zp@zA<9`0^C`U;|i@5V|=7VHCqjNv^HbVkl?6yNNs;Le2MK7}G;G9oO4jPw#?B&17g zDc{5E%ARC#;wuJPm{fd#Q+If(O@I;ts!98r10|=xrf^nf-FnwbCR}}3vqiz0l&?Ae z^mcew&TigUoXqG2wh#y+O7#Rzoj#@E`GUzI2{PgaIa^_+(SSdXa!yhF-dMR66EyUx{zsJ>8$JKVh zbj+4?r#>R)kx^O>r6eyi-QfC$b=0*poihTg_r>RvO-Rk>^Mjji+8ZyQiz(`k5(!*# zc-o&oQk}xi|3CHoqq;}Ntv&Gu<@mO7x+n40At6^Rvl%;-ghQ$t~Pu% zCyC7<+tv2`xFDu+Ur3sWkTQGU5r*X|na;^dc&at)*fS3v)`-l%klese*Tb(!kd3R$ zbRFpwOLz8zOIki7x>&R9Y5gS8KQPt*5Sy2jYacLhMHA6Cm^j6Zn0oIP#6?i*^n z8ah83X>l_CkvpifA9?;E@Fox*=}w67BrklQt;{47?fnWze)EER$4VlWCQ{nz4>uff z-rHR*Ln0M1ZXfB-2QK&*7Q{F^?8b}u^5tz1clvjoj51^ajG1n|4=g7bjFXI|joheD zSkVQzn5!S7g=SgBD;Kk(M*A{wVewB-_1P<_g&!3}!zfdZ=FXb*lB6*gaelhoe0=-)uD8>!!sPvWcI$vJ<-a;sVL0AHw)V3 zFk_p6gTX*@X>ty7sD-hPJ;4^5Z%BTSWc^;pcJX0NCz$fN`D}k(r5g3~UX%t6)h{(# z-RPN~u*4xUH`A;s&z9M}Y#ScKvY>H~C+jX15a=}`a?91QH3(KYJeldl@>;u&gD8AC z+?TS<(Wx`IiE{Q$33MhFDqU+E?H#XmKI;p4Es{x(v+8Aj&6pmyMI_o0!AhHIth7Z0 z_ZA`1Jojpk=o7~W@l5pcU7kwKHr5XTNNb3sTXsKsKBPG5azuX2UgJYwPM>Lgv&J#Y zh2 zzNAmu`dO0=g@^o?J3lk^*ETL^;nKw1^~E*)j49TtW?|p3(MIhKc<9NTPxY8S3)dNR znw)vtVjHm}b6FrjzG;B@_<`;C=c?B~w? zcVh1;P>s5O@pgWMU9fj|I9D&&gxzv}rgb^z#e%VP_o$gFKdYR*6@t{cC)>rYV-H>h z=O!ET@pr{pgil<<9v@*vKO%fV87}^;qPO_DBLF6Upz>>+uY?jQTV{AZ*AW4E_ymq< z+7iE0n@$m&yg5gYY|(@$XR<2TkJPZVAEhFsqgM_+P}}5Z4}VFAncx}+=xt1Q1m*_e zxKNW;X4=BK1;)=7!guZ@=r3I;`v=eIui@%vAILF!Ct*bIYCNK8jWu^|LI~^*#`l`- z@eGhsnAL~#RBr%h_^6nmVn0LcgcxvBXSr15vk6+At_RCo=?h8bFMfn0;1fQ}-+2cY zLsHfUp%^}mE_rHD^PF3#9g6^qG$2toCeWqEj&wN=9m=y z7lxx_e#u}-j0`&R+M!}qbaoH;Ky==bL5iARcz_@xOKLIn(U?35!tM#L4 zZ{1$8lId|Ud6XdCT7$`*pbL{wSc8H_@Fa9zsc9sI_gW>j1GiG zf$@OkAiKu%(I!d@&c(+rSfnA_j{!n@aygi`d<@g`#lE>Wk8Y|cH)^EGF3bA@A_ANt zCUCaY`#C=DDW;iv%stu7DWkesK@qk7*tX`mF(a+}6x36P!OmV``MDngyK7FC4p2xc z(zA%af?F5^ekr(daG z%V|Ppuw8WnKNe{u(nW-&X*=b<&WwqcKcT8)NnJZpG__nq*|+gTl8rMUCg}Sv#s4YC z8?Cs*I@VF4v@|Tox-g|fFUY!bB!2*2vAUzbRdAhwE4hp_|FOAd&C6+dl9ChtTz|81 zoNsBv2y$ks3h2r!n3rPMWAt^B=sP2>m=6)my(Q4i%7^kHjTN@R6CaBTSgB599$6^a zq^ziM%4k>Gmf8pGyir^?CSQ|E4ffB`a^b31*X5}rB9$#jBq7BZM(9bi8Ot5d`Q{Zb zDvpE`6v81TUR6jT)2&%=IitybsNo5 zV#4(F4x}g4B}aQb;vbfHzc1&^Y5W*P<i3ez|3O)cD9)qiZfW@_%nhw^ z-b5-k%W1_(BMBjQuRvgJCl=ZP&^y5bNZhXTX6)a==Tw2CQyK471HjFj2=1BL-* zZSE4D*I5ik0Y1;|C03kXLN}+rx0Qb~3XctTo1q{slqDp*1aRdPTxZ)MS2q zFFUy6rZ_ zuCimp_&9Y+VmCakhRrr`ZOs0oi?X~TqQj!y9IE5U&Vkt1xCL?^dmdEIx563<3(=O9 zDV?#3ggGtxJ=3}lXkWa~7+ELfT^!PFFTcUn_goet$}X4_re+JJWP4FiQ>`b|iK$f(o9dv4XJ?Z3X}{$rh4F_oW>;Jr z5jzuDAbDWb#((v;WlQG73Bqx!Ad1{;2p9ZgVwk=@Od+ZjgqVt~NRL0usueu!gBQ`H zwbaQfZt6QW+_MNjYZeJ7B*3N8w7uo=64t3Ax{N}8J|IQQA)tzF0di7oJ!CZ8-5o^; zk=fB`I@=l{SAELQC*&%;3_qk8zOm;x5HMgNjbjt^@swh=q%VSeca1>WX)5k{;AKsq zLDjYU06IaI_z${#k8Um#oz@4Yh6y#7sD0+n7v}5;s&(b@{@#V0$Y1e>Q&V}AX;)@4 zzkL}*^ms_rmThQE__Df2G3;>0>?f?C{jrHV4r!ac4t7+pT&($fXzImGC0uhN2 zP{TXN0O7ccekF0wdOF|R`1;~WDzQvIj>Fvfha7gFia$I&%-y8gT7J66Aur@bCb=Dk zciDx-Yu)mNCZ5fe<$zP|={)Xk=zLp^T~nO$Ks44{BG23K@Y$0vYG9rwLf=Uk`TjFS znRn7LC){7b(=Q>qUdjjO81*1&dtLpgkb=E@ZO1~^Zb9C+22Pc_|A8;)us)q(lk@dK z0Y%<+?t<$GgJRS1%;`^Lz6EBd5czj;ents`ah3btsT2{1jv>|5?_l4)?m|f=y8T?M;<}4ahI&J|AwV|H4o@u`svHU#%V5r+CnV`` z2)ENO?hHF4?|7;tA#YokJS=)qGhgWFYC}P;Yf?m=i6(1umZPDaS|GD?oa;Hi7Xwap zXh7014Wd%5nkTJzFwX{2-GHF4teuJX%37FO3r3Sqo5;W9%6-^lh8=fpfJFEiUeWXV z5rPGuWRxskn1;p1+C%B}7Ub!St)2i_$6l>z3w4D?cav`|JCt(om0C8mK;dA@>C!dq zT|_-9_Fb#dgCV{yK7M!hg-Xr*+ud=@eOO)Njv)>PMVe)429eOK8by<0ajIMkIfZ@5 za3F;PjtZU*s>4SMvYW@(FD1G1@x&BzXhPm1H9YY-=_C(|j(yZ6yA-Y&KE6<)WWvaH z-q_VcoJI3|1Yh`}ZW%MqDS~IWfLO-sk-juyO5rGqo0O2=dAkZeZ(~b0k2h?r%w5b& z@7Ns2%Y__{GfrHq*}7y1$xUi|h5dZiO>JUo0_YD)+YYL7<|c1}se95u&qcD8IPKIg z2g&-w{*gj$>)e!Q)9m<#wpd;L;}&vpOotY?b?Q2&_KiVEjf|(#Q~p(i*?DNP$^jq7 zrT|RsPtG6u;RmU!MMIkij}f-_t*Ud_d62ZFoPEr{_Uj_mUsH=N&+P5e(P(c)TCJn1*E{b_zVd|KT_-#FQLsGO5@alY zV$}=jS-N&)Z2AVK#9GJL=ROQ(`I>wb$Jo3dKkE=(x>QkE&I-*HGQGWqeI<&iNpHkUb~!-wZl*a& zG$M3FdGQ-UF-C}s&tAR09b)C>6J-}WG|Th!Fr_@Yb`v6;1gotZkoJ7s7I6RvpNX;O zyCm3kYK}JUQ`hKcb|)n(8u{0jIvxFUJ7%AU3ZzH*z1ou-q|b~!ABP4y(MbA|ZKxa* z`i#Y8a8O|BbnS!Cw^8>ineCWoxwf9Wwi|@=6A{vi^POqGs~Trs)EYi(nMv zzfwonkG7%lD~TRc_*zM1r51F;&K%_&Yfoe{Cs*&|lb_T`p+3t9e)1i08%KmnRs17W z`o(}zP#Fb|n%5FBt)zo1Tz&l|Nqe2%Q#0S7qz2<1+~bs?!lz(Sah|H`)^Bo5D68J7 zFhc69<@m6!`k%B9Baq$L%fKu#b5iLuL%fSy9z#bUHtrzAB~mvuSwC+D_9tRpqDb1} zs6{FVvD<~rEeu&x1+;!+_OYqbOb?986h@UADxa;2=;^ANUJbJXyMq-R zi**R(S7v%v=GQuQy$t4uJiLrQ#U3ZD!}Gi_tudP)^yw~2Euiq}{p#q)mNmOnn04*x z!|R#6O6Uzbta$k>yq~aXPv>poMZ&J35XZTSEpjSoTkat@>A1XaPJZ%wZ*=%%q%Uur zF{_1iV%B>WFBrSGv>68$`NEI+XgOL&8M*BK4MLt-S z6NRiyV21L~^cRmGh<^TweAz=c%P!HSWE-mg-E3X~w8QwsoDov-1JiF-UGeT!ShZDf z2N7|O6kM&uV%`H)j$|a>)EKo=K8#U5d`!$)vxdpN>%e7Cl3}frp1om4dj%)BS(wre zWQ%|?e6&yS(SG)=?nio}B*I3hJste4THL9t4D%jO!^y{#1u>uRMVT(rKuQPfV}d=D zhPPs@bdcc>-<`k6bbXj|T>k16iTd)GWZ%e1?eV0NtW}6|H0`D?WmOR5qa%ms9Wrz1 zjKeOYO8RrS1M<4u@Qiebj!+(z3I&2Q7zHJ!cya{yTJ{m?Az0|D#;=Ebd-kiIWvEdh zHeF1Ob-2LPH!!DCUfLu%-b$ROU(Z00>o8yO)>n-_SUXecNbFp$KzWlQWmdz0DDX(H zaFJZVkS+0N9|rY`#x3tDoTFMV6caVg=HPVN+ML#@v+m|v9qO27irPmCTZaz3;qh}D zHY*MI`e7yuK?AI)ipeI^pW{|jQfpI==S&*unYMD5*OX?4eO^Sn9eO;-n`vs58rSO6 z8Miw=2R0HvXNj^Bx9G8<^SJvJ-{rEDQ3ZY3JMY3WOJ=}Y`3rB0$e(NK6p;={90e$8AqcV~(=7GJzi-f|2K`DUL}a@-b3JhC;olXL;FL3pMP->wMZz zm@(?PR@EVI=& z<@58)$kM0h{(c>NL;bHCr;eS9pNXw1Wfh;SjEs%F@cVICeHZ+gYLv2b{SM~YtG-R> z`RkwOg@2yJ{yJQQ9ys!GfqDKqp8a(y3BCCQWcb%Tu6s@ItI`Uhb#<2{|3Pl%7RiL5ZrEJj_yL%tvw|1rr>W&Xr$ ziZ}Z!fh~r_v+j67EJ)u&_?hj{cg1zeDe0e;s#+{vDsXL*W^GH^I_ti8s1K72i?f8- z#AutdNYzOhJ9XbkSa~g}N6D}~_PJ=Sh3o!4f6R2g=1nXV#K*b7w%ezmO&v`58tjo$ z_3Uci+x+l`Nc!wK^FMtDSpOe~#Sk#>zi^3$qH7NbW62H8aBXCb<4SnXy}7^Tu7S(@ z5Uv7LV<})8h^pG^j+948!`N=|p4Gm`SC_=BYcdzz3Ju3Vs{91ahSbPR&HpnG-JC>T z3=CDvDK}zybId#wW3n*4+9#B4(`EwjbHjXcS^7M*XMrC>kJ*`*%}*ybX}4Hd5Qw(u z)QRl}_d4cv`t0U?;>OxLqekX6vz{d@vE);7F^-iI29yp$^WRzz zuin9jO&hkXSKmac_}#(XEjmTqWBR`{2L3#!=i~albXrjNbO$ao!W2wWJvS0*T(>0(??dDwu`rfk7EG8_a@@0f zOQXO=#=Z?~BVzmy^m|Sti6%jK(k5B_zx?#VM%g8NOAz90mTky$c&(d#=J?jR`6yS%EJYgBpum@Z1^6>{NpT zuWsgQ5ZF&Btrh1AF2aK&>w5Um78_Y}tcof2Aa(uqbB_VqOXSbi#0>uwjSI>-`Af7v zNG!jYDIAifZkB(v5Tt209i5jYGxM0qE!d8UpA?@(;2J z8z-2P7sLkP;RJE=@`3>t2`@h|Q~w%D+0@<)Zqxm%32=k}_L8l+grl{+C15`eO?OKN zZD>Q;)a#dKAWjGm`0r{#^@OVR1jGvl|Nl|Y{=fDE0i41OxQQEx3w{Vch!?_(CIAS_ z#}5WUxkwNJ@UOxH$O(N8eILTh`9}@mgTDWN6|}#eLx6Xo1=`17g$DuzBp7M{er})u z9SQJ*`1pWp2p5P47@QAUc(_1Z0z7Cy0rB$if_Qj)(1zB~=MbO( z>?}UuduX2m`~pDz$31BMOBo0s8nlKA0aXfGc!2u z+V{T=K)^q`0DjHT&v>9x0h0d}27kHhuNsgR?Jq%oNyW{_34HK}AE9yZKSYJ<^edQv zfP#MYpI)Fsfx&3Mp8eT@0IvY>gZ!gF1L2PtfX2c9EWd0G#04}a{#Jg)12iW7D!*do z&zOM5!`};3u3y(cAJEwNt3Wm91@i+w1Z0KAz&%9(7~@x5a6&Eh-||;X{8a<70LaIU z_N#`r|5kqa`j6+(cm7kLaRK!zwEi!0{yW>z63`ErD>R_<=P&#Qv^)WC{c+C=1Ss?C zsSglWzgqvL1_C<&cZK>Bb8zu;|9=122I;C+ z3LiYMUDftcBpBWvMo=Pg5UL1xr)S=!g?d6bLOrb?K1?K78GgOFJkiPh*qfB5TO%a+ zP$ZwnV3!nEvHM!S7h(Iu$@hwWhZlD+&NkM~|6KAR_oOsjfcJiz((tIuJHl|HwCoW4 z6fdk{JWenBlKbQCU8p(-JpBAT-EpTZo#@B7qlY?vgI~CZPK5L}d&U&jH`~I|3Yfdl zY>~%YwILYUWa)6Jkgs}HqUnS}glftkT|76rgC)Xk4djOQz*EAzs7<28F6PC0Rc4R& zS2Wt%=T6@+56aE1ur{hJOe?J9Ss%z7cp9lX*cuai;PWBIV^ImUB45*Nv$6}uJ6^nI z3QI1a=4T6_ipbR(!>Yz%cy2}KHJGh(oX_2QAu;u>%~wLsk->twQB9UPyMntnD))P| z4MXYiU10XNw)USeQp#FQ|FjwRJvj&GzY4;*P8=y}6zOB_TKa$haghNF*Q*bAcH)T! z78E9zr9y#m>S2&>>(2whQ?=aAP6SbQDAly*D9Uh&9UnV0yfDyVi%sLr**`r_d0d=a zl@Xmi*Jds;W1Gr@>981hS{WmbYe|YD)%F;6t z;>x1w3O?6`IT693X*DDLo0p?D^*nPt zgz;=9VYszBQS~I6g%8n~IJvcN+!?b>!q6ODbTR6M$Sbd=HPifeDRC3j+*YJ@A@qwc z3yi-HfxFXm`x~nHbgEq2375$u?-A@CxX<@55^O+5^5QRp_>wrt9O@()D3 zA=tWMrQrZpDMgEvh+676OEc5Zk6gU90fRKUNaCdS%2>nawm?o4pvTaQB%V@Q%7lwfgFc0B+PP^`UmGDXjevko zhupx6Z1n_72T6w%W;Tf&;~ue~)bYO%=by7Cu$2B*ERmQY%nmS$)Ui@0%DN`pjn-rA zfuD1seme}P9R{{AbMcQmE?~9%t=)Lk6szDlQI>Y_+rb@QGMM{;}1<` zy~4fHZndnK2W$HEX|NS|n(T{vtQ+(|Hql~?!j%u|*9;n(YV}Nl z^e>z;o-{KxGAd^{P7QWU55?8dh7&6wDXLAqv+2q^EWOG)jrt%MN%XuAi^Y9;eM%GO zn@G2{Xt-iq??uT%x^y!~f811tBC0a?!o+bu{-`itLEI=vLc<`)&NA-DUTQu(E|{~C zRoqi2FO%N3Z}J1gYjTIm)Iclx9;f|1UHsE&5bl35H}Gf(O}>^u+5e!q3zx08I^>-> zP;ljT#|tM!z*-{-HwlNF?iE2@re1YLuL?F|JbBh89Q~%RB~JfDtAOe~ufxU<-8u%e z6j|1gg}!zw`c1E=w`6c4M7CW~O0rmV@Gc)_cgB1YnZiB=a670_(aU4!A+|i}j^RM( zdgPIO-<|0@9 z_PM9J@vHte=eM_I;=R0`QduBOP9RdBVRI+gGXVSYj zpKh+tZhs<2J$z1kk9Y2YO8;tmrVgwQ%tbI}5H|>-8?9mpz7#txIwVJ&Jrz+G6gD(I z{$P-cms11G&5ih0X(T$=3>+=4rx+(8p!P$+fW*KS#+?f{_a1rfK^hS7zxa(qH%|fR zCUq$q!v3J+`$G0v!NcaX)fY>Q^n0(!7YJpZrZg+*X;Q{ZbA z(>&~`eC|5=mQ38{Wj8M-eQ%?<)}AUE+G~{iQVAPLKi=I%mW!Y9s7&T@8Y01e}{=A*!*i{V+{rRK$ zP>3tzkxlRRbpPkLpR3Ubim_ET)Msnej>06}FL&RW8-=r<%IkFdlrf zmyu#}i=X*o+&zkJmts%orSKh*GJl0Z5leevsYKK+td*mE6{*$Tw{*3(y{1=Y{O5%;mMugN*zQb<56+>aqM#W zHF61^2ri^MtG;(M=(g;Jm_At(VjdDQl6uylA(oX}c1$X;%C5oVZfWtxCpQCqI4-;j zN6(!l)kAzL=}2Rp)c#2j{x^jR#;hFfU7W#_XGwN`9(bzNwVPTa)cPZpc%-jt?7bwW z2k3C#VMa2hxKXQLmywkVvYRB*e?AXb&PlfN^U;vU0SEh44A>0A@s209SQGVTC{oJA z=y0di2+8xD1YCY@Xusrji9I8_3VHVFjs?qq4o>t1jN(s2qa+KdM0{}$+ z2*zl+A-L^;nLTP{?8yncxSP`$#77aQZ+K5{W=;#o!FeSRzI>Iylh5$n+EwS4RW(Ge zt8z^qKQMLO$TMh&tk+Tu3qsYJsy$lJn~2db!z&_;!!=L;KoH!5UPr4j zBAYTbhkHKBj4-I#@M$jy*P;Bo+f4CpP~V`>}2m0}0;5?O`5sSlXS$_Xgf z(x}!A+((2zUyK1*{03WvS_|hMgWZSB{>2U_gqK$b*cj$Uh?kW`LMsy2enn06sAIfe znmQGo4#f;WK>!BJ<43My2xEaCMzRelL9PXTiDrw=WyWC*w};}N;(ns)djz@%mT>|3 z=I=eIDv*FcjWOgMA_{&?yd?gixVV9L{`y68Lb^)a3H87f9!0uWIxTIDRo{}n1;}bm zQ>o{}MLjlN+2tA~O;RMfX=uFjY{iCSb_~&-XY!aX@-gq#D?OtJ^Ib}_I)v8jONi#S znI8oP9HR{JYNI_Wi#2uSz_}PN-5a`-KyF$E=L0cZ+q?YnjM3IW$ZX7324udnPdV{_)rz-G6q~uq}&-=k$pmHe<(5Me~xcfm7 zZ#RAu#T*8c&;+d}5Lj`W)-3Rp`G;EMHKIt8xV}&pdD8e-2>0g; z?pi31R?wy|OsOuVUy(aE8ZTO?B=@;f4qs)~j|K}6G+%B+@FFWmFYX>(;@L8DXtYr1 zXFd18OpjS_YFXQ;!T{Nt#7<&(r=`HoR81J?qIQ z#df+@;{Wx#jdrR@$b{lIT`%Jh(X`TZ&!YrMpLJy+nqf+`0xlsomUq4%zc>bd7aP(z z`7v;LMNy4Ca%+%zj|J~R%L4yq36Ac>fgVrYX-S}>p)IO1Bm#>_^aCzGlO3$1mx$;M z-m+AP$qYsWy2uLV%WARWZR@UV1Ivim&WtY>$F(w3rk>fx%RgpXF2MD^!?I?GEAgH% z&$>i6zo8YrN6LFpAhLDM<#(Rym!S$!E4q&<19G&8b>YGUs-q*-J! zSkpvLOE;IK>Q5t8QFP1gN=H+4C69{enH<|^r&tkv5MP4-X7TGr?YV5x0)hUwqlv1{eE8iU%)0-s7EnF!aCL zd6J3ib3p_!^l=#+JvadETSea)_WsZ6(DNw?A7V)iGu5sd105Gr_wLw6HVEbmIg+E^ z?_B1sGrAzgU3iT6i1LYo@18v*W#^kSW>xul1{{JkxWfq><>It{f^Yj08yX-#+>NLX zsE_gPn3;DRO<~!~j>NAusJ>3eE~tOW$c<%Yv7>ytsPobgM`1~ny_id7r43$xy)C(1 zWbs&x(o^vCpUMJwJpbYc1L1{e0WhLg3(Uo<4(8>CGsA=CFgYl|5%aGt9`Q2Q z_c?=ZCP2mYei8nzk(eFWh|0;drYE%Q#CvI5WP(olU#|r7!_ELLkM3W>t(IbqH zgRpfN0rm8mLE+W`X&{FOJs?8q+Vlt#X^KqP_@Olgco_O6!hw6_xd&AJn`2{3kAu_J)+$Muekq3Vh6d;R4EU%*@=``k%!?XQk>Cf zvOANJV4AEk8SfePK9s@(9LN4{Yf>g&(G>v%uyL}3XajCHg%cGlIh*cyF-I+UJyT15 zyi}kq!e!mT_Xhh9oQ_yD>^&3E79vB$mwA{r@OZZtu3Sj-W4c|$(|vQx&G%D6NB}dy zP@vSpB|pkT%Y)fjX)O7h`pUJZUXs5YmL=MJg&Vp3+Mq)>F{AA3$|J1H2#_kHrd-b< zXyF8zG1@=5oW(iI{$fHAjD_$+5-)8tQhXmHuy;iBd=vLzW5aVN(8S3b=h4E0{&;F) ziXhJ{gS*eO*KKz$p+aNtNUF$>KR-*G_3Se?OCWHAja+6b*|B5SpCb`mO@#Dq7Ttu7 zHkqWh1S=h1i_MOG{|QgYWcB?XQ{D$xfb+=Tn=(!a7oHkJ%2y?q_KFr>bj*s2iTBdU zeBNH8V@ekk+=3T0y%-d+8x+<+zk+yNiC}GhyT|LugS&~~5ujbLVUwic-_&E9?Eck; z*Np|e5|6?P%O@$HBMEkv6pa8J zAsL2{>UQ`XmRb`=Di+Pawd;-=s&zc9OKwx z)SSP^ME5|Ie>2y}L;-vLU=(TJA`^t?3>Uzjf7j{<%m?(2?-^G_3@A|3nH(YAQb^et ztf7W3f#)e;bOSlHn5=_*)0y@!2+`k)G|rB(ld=ygK8NnZ!by@^-6PsP_=F2M#QLrG zl+^|t0Po$j07t(ayW}mD$dSTtf4qo)91yqETw5=sjzJkr@qVKPWj)=t>DBnjOky=l6%N;Gw8k|AvBiRFHb>@{1 z43p57*Aab^sYLw_(dg0DEWR+AvPDpKUpU44#DQJ-V~r=Z9=ouI4<6GQ)?t{}RyI3} zm?H4>_z-M=1Di)A$h~>2xDShncQtwa;>hvX(;wEP2mI?)`F~P40rJ2<701yRbS8*7b9Y%fd?2D2!rFJq?Ak!(#+TCwNxub>1Z39 z%;`&$g9Jr-PMubE2iw_7?zH_)GmL!u{ zV)a*OuBh}61`(tYO}l;?dtd3Ai$~eO(w!&N6Ylz&#P;gPaRHy9@v;|q=AZ5Z_yzya zkBj?XOwh{eEtSCL>Apw^AwRHp+V0Kn<<(<($6JtzP%15jFF(+&*=#Xr>aQUCD25%| zfmG4HS(r~!GwfARsa?dEr1JElVNF)$@v~LEs%_#m-^YB@pU%UL;NsPT9-9VY#R8Nkc%U@wFNOgG6=e?7<$+F{jL;wRxWQ3j+?xhP=+E>^M>|K~M(iPJ-Ku^u zNIFptu1?_mPOQ}`6dWagWhAq#&w2P$8eB_qf$Ai~fcP?^wsfI=%p`R95^avZ?+jBZ zh;RQMMeo635P+HSTSeLa%Z1H>Tp@2lxv*YscMS=NGO}1E=bT%i5ej~KpvL^!kB!m8 z;vwtR<-;LkkCyrc!-wJ`-zTtz_)4>Ga()#47<63zm6GzhVtAkqxtC+%88*ws^h-BWegtnJy4pUV= zHA+Hd1vTXMs%}OM#`@Mxf|O&(0~b~EI2tW*_#sV@QMdJnQ`)ligr2;Qo*LLY#r)7! z7!PqYkbOlP_okFaIHzD>m;vo`Y$l~EGrZ}Sj4F3mvd1pP*~2`qBO4*|R{QObYSX*C z4f*SSVrW{u^JW}#&6_SoIj*%<93K~`%5F>1vvGfo*IMv$tXD-F{M z@;tO7L0D9db0FY=H^Lzgkzt3jkbd|hzFa%;Q~?F3K>bC>`{=5=#5iCwR#P z6qOq!3*gluu%=n=dJW?AwwYzn(bfh}byxVIdZJ;s^HIvkGn5INpJarCYvu$A0dmE) zxR|#59pN3>M*KZSXLtfw9pUC#8LSxQHVnl+F%cc(*>#1cy?vDW-_EeL_WZ)`al}0+ z_unOyz`it$q@f}$qB&@3xnG02CvK>J8ew>ND+qPlS&umQF~C|Dw@u6YgBx)366>Bb z7=WAbk171$z)lEny&5>68(#`w9Z+n;YuuyPJ#dW^piccZz+_?-u@C@0%4KF=Oh+Hp zjtkdbh}+#^K$at(xk!jsU{g@82)iA876BDCNyFF1(v%n(Jy9(m4Q=d!wXllbA?oEE z){`K4=1^+2$TZS;HcQ9GfF)kcw{Md*3u9^`^TDwf_4Wjm#(7U@JQBo$KQePHZ!}Z% z7tXe<=0&!@D1hZey+@mS5FP}e-27G>9t{CU0O9TbK=TI$I4&J8fF8x)e!whUz=wBn z*GLl5*YX?+3(Y3wouIfe}YlMD{!miDN zO_zZnvF^fR^uFtc+Ul)-idafr0@_^Z4z8Y$yQC?jM>SSYo~PJ$#CpBVWSM2_(?!%E zTj4)^b(!nU_7*9;Ej{HG8ijTQ;d6Qv{Dhn#r3i)1p(5`pvyX#zdX?&qJb#%pta&PVZm5M zem2_|jLv9*p=?~E3p4|5XRk=IkM+}aiFE7+$^BtlOV*}krTg1=)m@tBN?W*QNh z>XmKHn_cEP$^^wSUkd%&l7;b>k^BW&YXK7+9~TyptQ0Bct3l48mMIL<=dDJEG>TN?To*?HVVhQW||xp zT-_brMP1eFT)I2c^lP5QAY**nMe$O24%XK8mb5c*75lEKeQu1(tH2cfpB?}x%>S51 zxc&{&WmA`Tg_l5S8DlwrX;u8mJe4JE^KK4h5E%(GQruntb57J75UWn>R(!cl_a_Kv z&?m&O=PYv$x|`x!AbE2&o?OqbKIfG4E@`O4iL*5rRu$N{QB2FbJ?oq#){S$P(+>^| zt3}c!1}Y3b(&G^+&6v_!V~M46vDdqa@PT$@byH2_9JNUyxG~%zkElb+UKflaNZ>|Q z$wu?K;@=c<#JYz*jxOOmaAR{Y9#iJG8$ZykINeO5G<0ESB;u$bKmW!H|Nq*%^026` zD=u*#n;=rRepD|i5f|ny^JaNUh=fIujEGnSm$D3uGYT`~%t+Ms`yy)M^0}Z!aZBA( zm-uN#T+kLI?#3zxOZ1c2C=r`TwMuG<5PR;OH!$zLaiLAW{vq>+-gh{6dFP&Y&%Ni~ z-?=>#%%46S5mVY|@%`R$VAai;aW#ML@x|@mTs-%%Y+Tx@4V9J=nya^N9$$F-$&!6F zHT4Z`Q`06c^ddtqvuOs7Kfh2B_4%=HM1Z^F@y4>AJLjuPYeGwQ7n|;v?2YI+Bd?(v z*+N4vPamLkX5L-0Y{-Uy+ogrbaI0MR^xToKlT3Kk){x|a+%wlc@8&3Dnb!_QpSu>i zwbb{_q)y#33;O=46!n|Dyguns%Bs3chlf`!FFt5YeQRs!qI;cA?e`f!r?L11Vkc995j!dC2PG%B>HVhh&X~Zp9|kB5iH^-aBce`!lJ<+;0%m7* zez*Hxn&f553g_Ej*d(?7sNWnKFKb4YE{{3xdnRFie+A0ZXWv@mqs0{#bHxNqJJA6O%qX_)*}xhhtam4E!cB zZ1y_k#^M{5pHJm#)*K9R%sF!CIJI|W=_2F8c_++kkNB()^@*q~-)?~5 z3#hzX`C#>1@o$zpyR#L0)E9bn_K)fpTEFa*tN!0j;I6RUDo*=-I<@Wb;f?g@Hf{W; zUwAEZ)2NRMt4~`0P*>Pt{0~3+Y#KRkja)vkr`bFld4~+WqfbZ>L56VmHbI5pxSt19 z$c1I`fWp90WO5d~$+!@x5E7t5vZAF}7%!#=Y6le2^C3bC4~P&z8=wUWstFGyhX^So z5Fvax#9>P}K+Im4x7ct1-Rvx*Q%Kqg*oK1-&os+s%CaErD|ck4J4}Eb%CcJ#Wwihd z%K4sEK{-wKEJzz6<}Une&V{rCkWJXjZLnrrEl2}<$`IHWV){lRDhl2W;Z2GdK$!qi z2gHP^ctB+Ud`AIL6es!jL3ou zcxC|d(M8QgpkAbunb@`xPGYzL<%b_UOdveFwIUiIpF$ShgRJaNcP z7XVNZ;lM;0(h-B}pu*W_vnlZmp@~uTJVuy^04J>k;3X-Qdk!-oD_zWxAk69)GYgH? zJd+c)X@sVFhz|FYAdhAtVWG*0Sg3Bv=>bV9^tT>xoPwt5S@1mo7xbbY+z>+N>Hz~Q zd@p(!8iWrCj$YvhZH*o!&!wS)Jr;7L5+cW z-3%%O*l@9Ske0ez{yb-jqRE+}RdO89=>R_pSl1BI)3YA{@h*5<7?loYQ!fZsl9LZd z5Cc0!!6LWIZ`&@ry1({7<=TteWAB&L9!%i!mIn5nwQ2cw?ey8@jhm|{6ixl1YfVy7 zY|8rTD{(ddOpN^Ia&BB>a6^8(J);jOvordoRqT53epdsZFS zhWf1VYY4LqH^jH=+v`M1*ROm}Z1Jm4`{3BZ-_^B0za`0ApcW6M5H8v9?tN+&7^Bo_ zX&tN6@Gw7x`#LPONQ^9*S|!#JiOE#V zb^9O{XU-(i%UnJT7=|LOGav>SS)99XB=lTfMZk@EI96LQ?3CEDt4AehJOVTASw;oKxY8&f{FCqlXObGWh>WO-hKD8mLl%L? z>U4NPFQ#!gDw2$beP0qj9!H3i(y+r#O2ZB*5e*)&r%OUpVF#X=rqy6qo|s0nw2Y?J zVE>Vb4}zJ2?UB&b40h;=`P4WRnuMn1X*r)3`{cxVp;tg@#55fXQKlp`jS4%_#C#eJ zc9n@~IyGLEifIreP5Qp9mgS{=L}TBFBrnag*u^I*kJj-rJz!`xcDIW8;B}?-(mMJ3 z(mD>iR>gUBYB9WCukhQqs;5nt zc{MDK{D^vRrW3*cA%*Maw_US;e zWHcOCPs%6%w&40#ylEgVkEeNA`*;o_;Ys=61D4QO2<0h#50;kqIZLbLV>=iYsZ2q2 zA$py-UY6moV_wu|meI)M!h(^K%ARF-d7E`Q&%921x;Z<`PVNX!G|$cgTZX8yRx38c j#El$lF~WueNZhrH;Bcnfoy6?1Jk7C+prEMuXvMz)6|e*u literal 0 HcmV?d00001 diff --git a/QVDFE_paper/current/figures/pigou_cost_intersections.pdf b/QVDFE_paper/current/figures/pigou_cost_intersections.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0ff7154a4589c7380bdd0a47be7a67595c5683d7 GIT binary patch literal 29638 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 literal 0 HcmV?d00001 diff --git a/QVDFE_paper/current/figures/pigou_weight_sensitivity.pdf b/QVDFE_paper/current/figures/pigou_weight_sensitivity.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8b42d4761fc99cdb8d06c1f9486860de0b90742d GIT binary patch literal 26690 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 literal 0 HcmV?d00001 diff --git a/QVDFE_paper/current/section_empirical_v12.tex b/QVDFE_paper/current/section_empirical_v12.tex new file mode 100644 index 0000000..850a4eb --- /dev/null +++ b/QVDFE_paper/current/section_empirical_v12.tex @@ -0,0 +1,610 @@ +% ============================================================================ +% section_empirical_v12.tex — redesigned empirical section (v12 draft) +% +% Drop-in replacement for \section{Empirical evaluation and diagnostic +% results} (sec:numerical) of main_v11_community_narrative.tex. Notation +% follows tab:notation of v11 exactly. All numbers below are generated by +% experiments/codes/qvdfe_cbi/run_holdout_ablation.py (Stage 8) +% on top of the frozen Stage 0-7 outputs; machine-readable sources are in +% experiments/output/qvdfe_cbi/stage8_holdout_ablation/ +% Figures fig_A ... fig_F are copied from the same directory +% (fig_F + Table 5 from run_emission_supplement.py). The Pigou subsection +% and its two figures come from QVDFE_Pigou_Additional_Results/ +% (generate_pigou_example.py; pigou_cost_intersections.pdf, +% pigou_weight_sensitivity.pdf copied into figures/). +% ============================================================================ + +\section{Empirical evaluation: from observed episodes to an admissible +planning function} +\label{sec:numerical_v12} + +The empirical section answers four questions, in this order. +\begin{enumerate}[label=\textbf{Q\arabic*:},leftmargin=2.7em] +\item Can an observed congestion episode be reduced to an identifiable + effective state, + $\mu(t)\rightarrow\mu_e\rightarrow(k_e,v_e)$? +\item Is the derived planning variable + $z=\dfrac{D_Q}{C^hH}=\dfrac{\mu_e}{C^h}\dfrac{P}{H}$ meaningful? +\item Do the local QVDF reductions $P(z)=f_dz^{n}$ and + $\mu_e(z)=C^hHz/P(z)$ reproduce duration and effective state + \emph{outside} the calibration sample? +\item Does the FD-consistent effective speed improve emission analysis over + simpler alternatives? +\end{enumerate} +Questions Q1--Q3 are examined at a measured-flow I-10 eastbound bottleneck; +Q4 at a measured-flow I-405 southbound bottleneck, through a nested +ablation. The I-17 corridor, whose volumes are synthesized from the same +speeds the model is tested on, is retained only as a failure-domain stress +test and contributes no validation evidence. + +\subsection{Evidence architecture and holdout design} +\label{subsec:v12_design} + +\begin{figure}[t] +\centering +\includegraphics[width=0.9\textwidth]{figures/fig_A_evidence_ladder.pdf} +\caption{Evidence architecture. 317 directional sensor/TMC series produce +4{,}270 detected episode rows, of which 2{,}186 survive the two-tier +outlier screen, 1{,}006 lie on the three focus directions with complete +model chains, 364 satisfy every physical-state inequality, and 363 in +addition lie in the cubic-rate domain with measured flow (the strict set). +The final three stages are broken down by corridor; I-17 contributes one +physically admissible and zero strict episodes.} +\label{fig:v12_evidence_ladder} +\end{figure} + +\begin{table}[t] +\centering\small +\caption{Data and evidence levels by focus corridor. ``Physical'' episodes +satisfy the discharge, congested-branch, and within-link storage +inequalities of Eq.~\eqref{eq:physical_domain}; ``strict'' episodes are +physical, lie in the cubic-rate domain, and have measured (not synthesized) +flow.} +\label{tab:v12_data_evidence} +\begin{tabular}{lcccccl} +\hline +Corridor & Meas.\ speed & Meas.\ flow & Evaluated & Physical & Strict & +Intended role \\ +\hline +I-10 E & Yes & Yes & 468 & 151 & 151 & Structural validation \\ +I-405 S & Yes & Yes & 393 & 212 & 212 & Emission/assignment use case \\ +I-17 N & Yes & No & 145 & 1 & 0 & Diagnostic stress test \\ +\hline +\end{tabular} +\end{table} + +Relative to the v11 diagnostic chain, two data-integrity revisions precede +every result reported here. First, the discharge-window tagging rule was +corrected: queue dissipation moves the state \emph{up} the congested branch +of the fundamental diagram, so a valid discharge window must show a +non-negative flow trend ($\Delta q\ge 0$ for at least 60\% of bins, or a +non-negative net change) together with speed recovery; the earlier rule +kept bins with $\Delta q\le 0$, which tags the demand-starvation tail +rather than the discharge itself. Second, the outlier screen was made +two-tier: hard physical range rules (non-finite states, $z>8$, durations +exceeding the period, speeds outside $[0,90]$~mph, non-positive $\mu$) +exclude an episode outright, while relational evidence (robust-regression +residuals, MAD $z$-scores) now requires two agreeing flags, because three +independently unioned 3-MAD screens over-excluded legitimate +heavy-congestion days. The hard range rules remove 95 of the 1{,}827 +evaluated episodes---all with impossible demand accumulations +($z>8$)---and this alone reduces the ``physically admissible'' count from +403 to 364: roughly ten percent of the previously admissible set satisfied +the state inequalities only because an out-of-range $z$ had leaked through +the screen. Figure~\ref{fig:v12_evidence_ladder} and +Table~\ref{tab:v12_data_evidence} report the corrected ladder. + +\paragraph{Site selection.} +The two use-case bottlenecks were selected by a rule fixed before any +emission error was examined: (i) measured volume; (ii) at least 12 clean +episodes for one sensor--period cell (the 27-weekday data window caps a +cell at 18--19 episodes, so the 20--30 floor originally envisioned is +structurally unreachable and 12 is its feasible equivalent); (iii) a +stable fundamental-diagram calibration; (iv) at least half the cell's +episodes inside the strict domain; and (v) the highest CBI score among the +cells satisfying (i)--(iv). The parameter-bound status of the site refit +is reported transparently in Table~\ref{tab:v12_site_parameters} rather +than used as an eligibility gate, because the full-sample bound flags would +have excluded every high-CBI candidate. The rule selects sensor +\texttt{pems::718412} (PM period, CBI 3.89) on I-10~EB and sensor +\texttt{pems::767053} (AM period, CBI 4.36) on I-405~SB, both with 18 +clean episodes and full strict coverage. + +\paragraph{Blocked holdout.} +All out-of-sample results use a blocked date split: the first 70\% of +calendar dates of each cell calibrate $(f_d,n,f_p,s)$, the final 30\% +validate. Random episode splits are not used, because episodes from the +same day on both sides of the split would leak temporally correlated +demand. Every competing model---the fixed-capacity Vickrey benchmark, the +fixed queued speed, and the nested emission baselines---uses the same +split, and all state quantities on validation days are recomputed from +training-block parameters only. + +\begin{table}[t] +\centering\small +\caption{Selected bottleneck sites and calibration-block parameters. +$\omega=C^h/(k_j-k_c)$ with $k_j=220$ veh/mi/lane; $\alpha=\theta f_pf_d^s$, +$\beta=ns$ with $\theta=8/15$. The duration fit reaches the elasticity +lower bound $n=1$ at both sites (see text).} +\label{tab:v12_site_parameters} +\begin{tabular}{lcc} +\hline + & I-10 EB site & I-405 SB site \\ +\hline +Sensor / period & \texttt{pems::718412} / PM & \texttt{pems::767053} / AM \\ +$C^h$ (vphpl) & 1387 & 1265 \\ +$v_{\mathrm{ref}}$ (mph) & 53.0 & 59.8 \\ +$k_c$, $k_j$ (vpmpl) & 26.1, 220 & 21.2, 220 \\ +$\omega$ (mph) & 7.15 & 6.36 \\ +$f_d$, $n$ & 1.381, 1.000$^{\dagger}$ & 1.384, 1.000$^{\dagger}$ \\ +$f_p$, $s$ & 2.007, 0.148 & 1.496, 0.261 \\ +$\alpha$, $\beta$ & 1.123, 0.148 & 0.869, 0.261 \\ +Train / held-out episodes & 13 / 5 & 13 / 5 \\ +Calibrated $z$ range & $[3.50,\,7.85]$ & $[2.75,\,6.85]$ \\ +Train duration / speed $R^2$ & 0.936 / 0.062 & 0.101 / $-0.193$ \\ +\hline +\multicolumn{3}{l}{\footnotesize $^{\dagger}$duration-elasticity lower +bound active; the fitted log--log slope of $P$ against $z$ does not exceed +one at single-site scale.} +\end{tabular} +\end{table} + +\subsection{Use case 1: the structural bridge at I-10 eastbound} +\label{subsec:v12_structural} + +\begin{figure}[t] +\centering +\includegraphics[width=0.99\textwidth]{figures/fig_B_representative_episodes.pdf} +\caption{Representative held-out episodes at the two selected bottlenecks +(top: I-10 EB, bottom: I-405 SB). Column~1: five-minute speed (color) and +flow (gray) with $t_0,t_2,t_3$ and the queued interval shaded. Column~2: +the discharge reduction $\mu(t)\rightarrow\mu_e=\frac1P\int\mu(t)\,dt$, +with the capacity-retention ratio $\mu_e/C^h$ annotated. Column~3: the +projection of $\mu_e$ onto the triangular fundamental diagram, giving +$(k_e,\mu_e)$ and $v_e=\mu_e/k_e$ (dark red), with the observed mean queued +speed as an open marker. Column~4: the episode in the $(z,P/H)$ plane +against the fixed-capacity Vickrey line $P=Hz$ and the calibrated QVDF +curve $P=f_dz^n$ (star: the illustrated episode; open/filled points: +calibration/validation episodes of the site).} +\label{fig:v12_representative} +\end{figure} + +Figure~\ref{fig:v12_representative} traces one held-out episode per site +through the full reduction of Section~\ref{sec:fd_qvdf}: an observed +breakdown--recovery cycle is collapsed to a throughput-preserving +$\mu_e$, projected to an FD state, and located in the $(z,P/H)$ plane. +Both illustrated episodes lie above the Vickrey line: their observed +durations exceed what a fixed-capacity bottleneck of the same demand would +produce, exactly the degradation the effective-discharge reduction is +designed to capture ($\mu_e/C^h=0.78$ and $0.87$ in the two examples). + +\begin{table}[t] +\centering\small +\caption{Held-out structural validation (final 30\% of dates; $n=5$ +episodes per site). NMAE is the mean absolute error normalized by the mean +observed magnitude; bias is the relative error of the totals. $R^2$ over +five episodes is reported for completeness but is dominated by small-sample +noise.} +\label{tab:v12_structural_validation} +\begin{tabular}{llrrrr} +\hline +Site & Quantity & Model & NMAE (\%) & Bias (\%) & $R^2$ \\ +\hline +I-10 EB & $P$ & Vickrey $P=Hz$ & 20.6 & $-20.6$ & $-0.34$ \\ +I-10 EB & $P$ & QVDF $f_dz^n$ & \textbf{10.5} & $+9.7$ & $0.36$ \\ +I-10 EB & $\mu_e$ & Vickrey $\mu_e=C^h$ & 28.9 & $+28.9$ & $-5.32$ \\ +I-10 EB & $\mu_e$ & QVDF $\mu_e(z)$ & \textbf{10.0} & $-6.7$ & $-0.29$ \\ +I-10 EB & $\bar v_q$ & fixed $\tilde v_q$ & \textbf{14.3} & $-2.3$ & $-0.02$ \\ +I-10 EB & $\bar v_q$ & FD $v_e(z)$ & 51.2 & $-51.2$ & $-9.34$ \\ +\hline +I-405 SB & $P$ & Vickrey $P=Hz$ & 34.5 & $-34.5$ & $-4.50$ \\ +I-405 SB & $P$ & QVDF $f_dz^n$ & \textbf{15.7} & $-9.3$ & $-0.15$ \\ +I-405 SB & $\mu_e$ & Vickrey $\mu_e=C^h$ & 63.4 & $+63.4$ & $-8.70$ \\ +I-405 SB & $\mu_e$ & QVDF $\mu_e(z)$ & \textbf{27.2} & $+18.0$ & $-0.70$ \\ +I-405 SB & $\bar v_q$ & fixed $\tilde v_q$ & \textbf{35.4} & $+21.0$ & $-0.53$ \\ +I-405 SB & $\bar v_q$ & FD $v_e(z)$ & 63.8 & $-63.8$ & $-4.85$ \\ +\hline +\end{tabular} +\end{table} + +\begin{figure}[t] +\centering +\includegraphics[width=0.99\textwidth]{figures/fig_C_structural_validation.pdf} +\caption{Structural relationships at the two sites (open markers: +calibration block; filled: validation block; I-10 blue, I-405 orange; +black: theory). Left: the duration closure against the Vickrey $n=1$ +line. Middle: capacity retention $\mu_e/C^h$ against $P/H$; the fitted +retention level $1/f_d\approx0.72$ is drawn per site. Right: observed mean +queued speed against the model $v_e(z)$, which collapses to a near-constant +low speed when $n=1$.} +\label{fig:v12_structural_fig} +\end{figure} + +Three structural findings emerge +(Table~\ref{tab:v12_structural_validation}, +Figure~\ref{fig:v12_structural_fig}). + +\emph{First, the data reject the fixed-capacity benchmark, but through the +retention level, not the elasticity.} On held-out dates the calibrated +QVDF halves the Vickrey duration error at both sites (NMAE 10.5\% versus +20.6\% at I-10; 15.7\% versus 34.5\% at I-405) and the Vickrey bias is +negative---observed episodes systematically outlast the fixed-capacity +prediction---while the QVDF effective discharge $\mu_e(z)$ similarly +halves to quarters the error of assuming $\mu_e=C^h$. However, the fitted +duration elasticity sits at its lower bound $n=1$ at both sites: what the +27-date window identifies is a stable capacity-retention level +$\mu_e/C^h=1/f_d\approx0.72$, not a resolvable dependence of retention on +$z$. The degradation \emph{level} is decisively supported +($f_d\approx1.38\gg1$); the degradation \emph{slope} ($n>1$) is not +identifiable at single-site scale in this sample. + +\emph{Second, the derived variable $z$ organizes the held-out episodes.} +The validation points continue the calibration-block alignment in the +$(z,P/H)$ plane (Figure~\ref{fig:v12_structural_fig}, left), which is the +operational content of Q2: an episode's position on the planning axis, +computed only from $\mu_e$, $P$, and $C^h$, predicts its duration on unseen +days. + +\emph{Third, the FD projection under-predicts the observed queued speed.} +With $n=1$ the model state degenerates to a near-constant queued speed of +12--24~mph, roughly half the observed mean queued speed (bias $-51$\% and +$-64$\%). The effective state is throughput-consistent by construction, +but its congested-branch speed is biased low---the same within-link +storage and state-inequality tension already identified in the +admissibility analysis, now quantified out of sample. + +\subsection{Use case 2: emission ablation and assignment admissibility at +I-405 southbound} +\label{subsec:v12_ablation} + +The nested ablation isolates what each modeling ingredient contributes. +With $\bar w(z)$ the QVDF mean delay and $r(\cdot)$ the age-weighted MOVES +operating-mode rate, the four models are +\begin{align} +e_{\mathrm{avg}}(z) &= r(v_{\mathrm{avg}})\,[T_c+\bar w(z)],\qquad +v_{\mathrm{avg}}=\frac{L}{T_c+\bar w(z)}, \tag{B0}\\ +e_{\mathrm{delay}}(z) &= r(v_{\mathrm{ref}})\,[T_c+\bar w(z)], \tag{B1}\\ +e_{\mathrm{fixed}}(z) &= r(v_{\mathrm{ref}})T_c + +\Gamma(\tilde v_q)\,\bar w(z), \tag{B2}\\ +e_{\mathrm{FD}}(z) &= r(v_{\mathrm{ref}})T_c + +\Gamma[v_e(z)]\,\bar w(z), \tag{B3} +\end{align} +where $\tilde v_q$ is a single queued speed taken from the calibration +block (its median observed mean queued speed) and B3 is the proposed +closure of Eq.~\eqref{eq:two_branch_emission_summary}. All four are +evaluated on validation episodes only, with training-block parameters, +against the observed-speed five-minute MOVES episode totals; the +reconstructed-speed MOVES benchmark is carried as a diagnostic upper +anchor. Confidence intervals are paired episode bootstraps (2{,}000 +resamples). + +\begin{table}[t] +\centering\small +\caption{Nested emission ablation on held-out episodes: NMAE\,\% (bias\,\% +in parentheses). ``Pooled strict'' aggregates the blocked-holdout +validation episodes of all nine measured-flow sensor--period cells with at +least eight episodes, restricted to the strict domain ($n=19$); the I-405 +site column is the selected bottleneck alone ($n=5$). R is the +reconstructed-speed MOVES diagnostic. All $\Delta$NMAE improvements of +B0/B2/B3 over B1 have paired-bootstrap 95\% intervals excluding zero.} +\label{tab:v12_emission_ablation} +\begin{tabular}{llrrrrr} +\hline +Subset & Poll. & B0 mean-$v$ & B1 delay & B2 fixed $\tilde v_q$ & +B3 FD $v_e(z)$ & R recon.\ \\ +\hline +I-405 site & CO$_2$ & 9.9 ($-2$) & 97.4 ($+97$) & 28.5 ($-28$) & \textbf{21.5} ($+21$) & 10.6 \\ + & NO$_x$ & 16.6 ($-17$)& 186.7 ($+187$)& 76.9 ($-77$) & \textbf{29.0} ($+29$) & 16.2 \\ + & CO & 10.1 ($+1$) & 41.7 ($+42$) & 25.2 ($+25$) & \textbf{10.9} ($+6$) & 17.7 \\ + & HC & 11.1 ($+4$) & 53.2 ($+53$) & \textbf{11.0} ($+3$) & 14.0 ($+13$) & 17.9 \\ +\hline +Pooled strict & CO$_2$ & 10.3 ($-5$) & 101.2 ($+101$) & \textbf{16.3} ($-14$) & 19.0 ($+19$) & 10.6 \\ + & NO$_x$ & 15.0 ($-12$)& 244.8 ($+245$) & \textbf{34.6} ($-34$) & 42.5 ($+43$) & 11.5 \\ + & CO & 10.2 ($-3$) & 42.4 ($+42$) & 14.0 ($+4$) & \textbf{10.7} ($+5$) & 14.1 \\ + & HC & 11.1 ($-1$) & 50.9 ($+51$) & \textbf{11.4} ($-1$) & 12.6 ($+8$) & 15.0 \\ +\hline +\multicolumn{7}{l}{\footnotesize Bold: best of the two queued-state +closures (B2 vs.\ B3). B0 is reported separately because it requires the +full rate curve $r(v)$ at}\\ +\multicolumn{7}{l}{\footnotesize arbitrary speeds and provides no +delay--emission decomposition usable in the assignment primitive.} +\end{tabular} +\end{table} + +\begin{figure}[t] +\centering +\includegraphics[width=0.95\textwidth]{figures/fig_D_emission_ablation_forest.pdf} +\caption{Change in normalized MAE relative to the delay-only model B1 on +held-out episodes, with paired 95\% bootstrap intervals (left: the I-405 +site; right: pooled strict validation). Every queued-state representation +improves decisively on delay alone; at the I-405 merge bottleneck the +FD-consistent state (dark red) also dominates the fixed queued speed for +CO$_2$, NO$_x$, and CO.} +\label{fig:v12_ablation_forest} +\end{figure} + +Table~\ref{tab:v12_emission_ablation} and +Figure~\ref{fig:v12_ablation_forest} support four conclusions. + +\emph{(i) Delay alone is not enough.} The delay-only model B1 +over-predicts episode emissions by roughly a factor of 1.4--3.5 (NMAE +42--245\%), because it prices queued hours at the reference-speed emission +rate. Every queued-state model removes 60--90\% of that error, with +paired bootstrap intervals excluding zero everywhere: the two-regime +\emph{geometry}---separating free-flow traversal from queue exposure---is +the single most valuable ingredient in the closure. + +\emph{(ii) State dependence earns its keep where degradation is strong.} +At the I-405 merge bottleneck, replacing the fixed queued speed by the +FD-consistent $v_e(z)$ cuts NMAE from 28.5\% to 21.5\% (CO$_2$), 76.9\% to +29.0\% (NO$_x$), and 25.2\% to 10.9\% (CO); HC is a statistical tie. In +the pooled panel, which mixes cells with milder degradation, B2 and B3 are +statistically indistinguishable for CO$_2$ and HC, B3 wins for CO, and B2 +wins for NO$_x$. CO and CO$_2$ support the effective-state reduction, +NO$_x$ exposes the rate-curve and operating-mode limitations flagged in +Section~\ref{sec:v8_reconstructed_benchmark}---precisely the +pollutant-dependence pattern a running-exhaust approximation predicts. + +\emph{(iii) The whole-link mean-speed model is a strong total-mass +baseline.} B0 attains 10--17\% NMAE throughout: evaluating the full MOVES +curve at the delay-consistent mean speed largely averages out the rate +nonlinearity for episode totals. B0, however, is not a competitor for the +paper's purpose: it requires the entire rate curve at arbitrary speeds +inside the assignment loop, offers no separation of free-flow and queue +contributions, and supplies no $\Gamma\cdot\bar w$ structure through which +delay and emission enter the generalized cost jointly. Its accuracy is +the appropriate honesty check: the FD closure approaches (and for CO +matches) B0's accuracy with a two-point rate evaluation and an explicit +queue-exposure decomposition. + +\emph{(iv) The systematic sign structure mirrors the state bias.} B3's +residual error is almost purely positive bias (its $v_e$ is biased low, so +$\Gamma[v_e(z)]$ is biased high), while B2's error at the strongly +degraded site is negative (its $\tilde v_q$, an episode-mean speed, sits +too close to $v_{\mathrm{ref}}$). Correcting the congested-branch speed +mapping is therefore the highest-leverage refinement, consistent with the +structural finding of Section~\ref{subsec:v12_structural}. + +\begin{figure}[t] +\centering +\includegraphics[width=0.99\textwidth]{figures/fig_F_heldout_emission_scatter.pdf} +\caption{Held-out episode emission totals against the observed-speed +five-minute MOVES benchmark, one panel per pollutant (log--log; dashed: +one-to-one). Filled dark-red markers: the FD-consistent closure B3 on the +strict validation set; open purple: the fixed-queued-speed closure B2; +faded: B3 outside the strict domain. In the NO$_x$ panel the fixed-speed +model collapses to a nearly constant total for an entire cluster of +episodes whose observed totals span almost an order of magnitude, while +the state-dependent closure tracks the diagonal with the positive offset +diagnosed in Table~\ref{tab:v12_emission_ablation}.} +\label{fig:v12_heldout_scatter} +\end{figure} + +\begin{table}[t] +\centering\small +\caption{Two-branch decomposition of the FD-consistent closure +$e_{\mathrm{FD}}(z)=r(v_{\mathrm{ref}})T_c+\Gamma[v_e(z)]\bar w(z)$ on the +strict held-out episodes ($n=19$): median free-flow and queue-branch +per-lane totals, the queue share of the episode total, the exact +delay-to-emission factor $\Gamma$, and the cubic-surrogate error in +$\Gamma$.} +\label{tab:v12_two_branch} +\begin{tabular}{lrrrrrr} +\hline +Poll. & Free-flow br.\ (g) & Queue br.\ (g) & Queue share (\%) & +$\Gamma$ exact (g/h) & $|\Delta\Gamma|/\Gamma$ cubic (\%) & +Total bias (\%) \\ +\hline +CO$_2$ & 631{,}475 & 187{,}414 & 25.1 \ (9--27) & $+4152$ & 8.3 & $+18.7$ \\ +NO$_x$ & 832 & $-64$ & $-9.2$ \ ($-21$--$-1$) & $-1.17$ & 38.5 & $+42.5$ \\ +CO & 3{,}932 & 2{,}313 & 38.1 \ (22--42) & $+51.5$ & 5.1 & $+4.6$ \\ +HC & 179 & 98 & 36.8 \ (20--41) & $+2.21$ & 5.2 & $+8.2$ \\ +\hline +\multicolumn{7}{l}{\footnotesize Queue share reported as median +(p10--p90). Total bias is $\sum$model$/\sum$observed$-1$ on the strict +validation set.} +\end{tabular} +\end{table} + +\emph{(v) The decomposition shows where the physics lives---and where the +rate curve fails.} Table~\ref{tab:v12_two_branch} splits every held-out +strict episode into its free-flow and queue-exposure branches. For CO and +HC the queue branch carries 37--38\% of the episode total with a stable +positive $\Gamma$ and a cubic-surrogate error of only $\sim$5\%: for these +pollutants the two-regime closure is both accurate and smoothly +differentiable. CO$_2$ sits between (queue share 25\%, cubic error 8\%). +NO$_x$ is the structural outlier: the exact $\Gamma$ is \emph{negative} +(median $-1.2$~g/h)---the age-weighted operating-mode rate at the queued +speed falls below the reference-speed rate, so added queue exposure +nominally \emph{reduces} NO$_x$---and the cubic surrogate misses this +factor by 38\%. Figure~\ref{fig:v12_heldout_scatter} shows the practical +consequence. This is the running-exhaust limitation surfacing exactly +where Section~\ref{sec:v8_reconstructed_benchmark} predicted: a +five-minute, zero-acceleration operating-mode approximation cannot +represent the acceleration-dominated NO$_x$ emissions of stop-and-go +queues, and a negative $\Gamma$ also invalidates the monotone +generalized-cost argument for NO$_x$-weighted assignment. The pollutant +scope of the closure is therefore explicit: CO, HC, and CO$_2$ support +both accounting and assignment use; NO$_x$ requires trajectory-resolved +rates before either. + +\begin{figure}[t] +\centering +\includegraphics[width=0.99\textwidth]{figures/fig_E_phase_admissibility.pdf} +\caption{Left: episode phase diagram in $(z,\mu_e/C^h)$ for the three +focus directions (solid: physically admissible; faded: inadmissible), with +the two site calibration paths at the fitted retention level +$1/f_d\approx0.72$. Right: response curves over each site's calibrated +$z$ range---total time $T(z)=T_c+\bar w(z)$ and per-vehicle CO$_2$ +emission $e(z)$---with the observed-$z$ span (blue band) and the physical, +cubic-rate, and monotone generalized-cost domains (bottom ribbons). Over +the calibrated ranges of both sites all admissibility conditions hold, so +the emission-augmented cost can support separable assignment on this +explicitly identified domain.} +\label{fig:v12_phase} +\end{figure} + +Figure~\ref{fig:v12_phase} converts the admissibility discussion into the +planning statement of Section~\ref{sec:assignment}: on the two calibrated +sites the response curves $T(z)$ and $e(z)$ are increasing and the +generalized cost is monotone over the entire calibrated $z$ range, so the +closed-form function is usable for separable emission-weighted assignment +\emph{on the explicitly identified domain}---while the phase diagram makes +equally explicit how much of the wider episode population (all of I-17, +and the low-retention tail of the PeMS corridors) falls outside it. + +\subsection{Two-route Pigou assignment illustration} +\label{subsec:v12_pigou} + +A small two-route example closes the chain from the calibrated link +function to equilibrium and optimal assignment, and clarifies that the +QVDF delay parameters $\alpha$ and $\beta$ are retained rather than +replaced by a second set of emission-specific power parameters. Consider +one origin--destination pair with a constant bypass route~A and a +congestible route~B. Route~B uses +\begin{equation} +\label{eq:v12_pigou_time_emission} +T_B(z)=T_c+T_c\alpha z^\beta, +\qquad +e_B(z)=e_0+\Gamma[v_e(z)]\,T_c\alpha z^\beta . +\end{equation} +Thus $\alpha$ and $\beta$ continue to govern queue-delay exposure; the +emission model adds only the pollutant-specific factor $\Gamma[v_e(z)]$ +converting one unit of delay exposure into an emission increment. No new +$\alpha_e$ or $\beta_e$ is introduced. + +The numerical constants reproduce the calibrated I-10 prototype curve to +plotting precision: over the assignment domain $5.2\le z\le 14$, +$\bar w(z)=0.00489809\,z^{1.64836}$ minutes with $T_c$ normalized to one +minute (hence $\alpha=0.00489809$, $\beta=1.64836$), an approximately +constant effective queued speed of $20.4$~mph, and the differentiable +cubic-rate emission implementation +$e_B(z)=37.1701+({2915.253}/{60})\,\bar w(z)$ grams per vehicle (the +exact-rate sensitivity case uses $e_0=32.7335$~g and +$\Gamma=4425.665$~g/h). Because $v_e$---and therefore $\Gamma$---is +approximately constant over this local domain, emissions rescale the +coefficient on $z^\beta$ but do not alter its shape. Route~A's constant +time is set to $T_A=T_B(14)=1.37954$ minutes, producing the conventional +Pigou benchmark in which all flexible flow uses route~B at the time-only +user equilibrium; total normalized demand is 14 units. With $\theta_t=1$ +and $\theta_e=\lambda T_c/e_0$ for a dimensionless environmental weight +$\lambda$, the generalized cost on route~B is +\begin{equation} +\label{eq:v12_pigou_generalized_cost} +g_B(z;\lambda) += T_c+\lambda T_c ++ T_c\alpha\!\left[1+\lambda\frac{\Gamma}{60e_0}\right]\!z^\beta , +\end{equation} +which shows directly that the emission term preserves $\beta$ and changes +only the effective coefficient multiplying the existing QVDF exposure +term. With both routes used, the average-cost (user-equilibrium) and +marginal-cost (system-optimal) conditions have closed forms in the +constant-$\Gamma$ case, with +$z_{\mathrm{ESO}}=z_{\mathrm{EUE}}/(1+\beta)^{1/\beta}$; when +$\Gamma[v_e(z)]$ varies with $z$ both remain scalar monotone root problems +on the admissible domain identified in Figure~\ref{fig:v12_phase}. + +\begin{figure}[t] +\centering +\includegraphics[width=0.98\textwidth]{figures/pigou_cost_intersections.pdf} +\caption{Two-route Pigou illustration on the calibrated I-10 prototype +curve. (a)~The time-only user equilibrium equates average route costs, +whereas the time system optimum equates the bypass cost to the marginal +cost on the QVDF link. (b)~The same distinction after adding the +normalized emission term: because the effective queued speed is +approximately constant over the domain, emissions rescale the $z^\beta$ +term without introducing a new power exponent.} +\label{fig:v12_pigou_costs} +\end{figure} + +\begin{table}[t] +\centering\small +\caption{Two-route results for the differentiable cubic-rate I-10 +prototype. Total travel time and total emissions are normalized aggregate +quantities over 14 demand units; the final column evaluates every solution +under the common $\lambda=0.4$ generalized system objective.} +\label{tab:v12_pigou_results} +\begin{tabular}{lrrrrrr} +\hline +Case & $z_B$ & $x_A$ & $\bar w_B$ (min) & Total time & Total CO$_2$ (g) & +$Z_{\lambda=0.4}$ \\ +\hline +T--UE & 14.000 & 0.000 & 0.380 & 19.314 & 778.55 & 27.692 \\ +T--SO & 7.754 & 6.246 & 0.143 & 17.482 & 662.49 & 24.611 \\ +E--UE & 13.303 & 0.697 & 0.349 & 18.906 & 755.74 & 27.039 \\ +E--SO & 7.368 & 6.632 & 0.132 & 17.488 & 661.11 & 24.602 \\ +\hline +\end{tabular} +\end{table} + +\begin{figure}[t] +\centering +\includegraphics[width=0.98\textwidth]{figures/pigou_weight_sensitivity.pdf} +\caption{Sensitivity of the two-route solution to the dimensionless +emission weight $\lambda$. Solid curves use the differentiable cubic-rate +implementation, dashed curves the exact-rate I-10 prototype; the vertical +dotted line marks the reported $\lambda=0.4$ case. The ordering +$z_{\mathrm{ESO}} None: + """Observed-speed MOVES totals vs the queued-state closures, held-out.""" + _style() + strict = panel["physically_admissible"].astype(bool) \ + & panel["cubic_rate_domain_ok"].astype(bool) + fig, axes = plt.subplots(1, 4, figsize=(12.6, 3.3)) + for ax, pollutant in zip(axes, POLLUTANTS): + obs = pd.to_numeric( + panel[f"observed_emission_{pollutant}_g_per_lane"], errors="coerce") + b3 = pd.to_numeric( + panel[f"B3_fd_state_{pollutant}_g_per_lane"], errors="coerce") + b2 = pd.to_numeric( + panel[f"B2_fixed_vq_{pollutant}_g_per_lane"], errors="coerce") + ax.scatter(obs[strict], b2[strict], s=22, facecolors="none", + edgecolors="#7B52A1", lw=1.0, alpha=0.8, + label=r"B2 fixed $\tilde v_q$") + ax.scatter(obs[strict], b3[strict], s=24, color=QUEUED_RED, + alpha=0.85, label=r"B3 FD $v_e(z)$") + ax.scatter(obs[~strict], b3[~strict], s=14, color=QUEUED_RED, + alpha=0.25, lw=0) + lim = [min(obs.min(), b3.min(), b2.min()) * 0.85, + max(obs.max(), b3.max(), b2.max()) * 1.15] + ax.plot(lim, lim, color="black", ls="--", lw=1.0) + ax.set_xscale("log"); ax.set_yscale("log") + ax.set_xlim(lim); ax.set_ylim(lim) + ax.set_xlabel("observed-speed MOVES (g/lane)") + if pollutant == "CO2": + ax.set_ylabel("model episode total (g/lane)") + ax.legend(frameon=False, loc="upper left", fontsize=7) + ax.set_title(POLLUTANT_LABELS[pollutant]) + fig.suptitle("Held-out episode emission totals: queued-state closures " + "vs the observed-speed benchmark", y=1.02, fontsize=10) + fig.tight_layout() + _save(fig, FIGURE_DIR, "fig_F_heldout_emission_scatter") + + +def table5_two_branch(panel: pd.DataFrame, moves, surrogates: pd.DataFrame) -> pd.DataFrame: + """Two-branch decomposition of B3 on the strict held-out episodes.""" + strict = panel[panel["physically_admissible"].astype(bool) + & panel["cubic_rate_domain_ok"].astype(bool)].copy() + v_ref = strict["v_ref_mph"].to_numpy(float) + v_e = strict["v_q_model_mph"].to_numpy(float) + tc = strict["reference_time_hr"].to_numpy(float) + wbar = strict["w_bar_model_hr"].to_numpy(float) + demand = strict["demand_model_veh_per_lane"].to_numpy(float) + surrogate_map = surrogates.set_index("pollutant") + rows = [] + for pollutant in POLLUTANTS: + rate = lambda speed, p=pollutant: exact_rate_for_speed(moves, speed, p) + coeff = surrogate_map.loc[pollutant, ["c0", "c1", "c2", "c3"]].to_numpy(float) + gamma_exact = gamma_from_rate(v_e, v_ref, rate) + gamma_cubic = gamma_from_cubic(v_e, v_ref, coeff) + base = rate(v_ref) * tc * demand + queue = gamma_exact * wbar * demand + total = base + queue + obs = pd.to_numeric( + strict[f"observed_emission_{pollutant}_g_per_lane"], errors="coerce" + ).to_numpy(float) + share = queue / np.maximum(total, 1e-9) + gamma_gap = np.abs(gamma_cubic - gamma_exact) / np.maximum(np.abs(gamma_exact), 1e-9) + rows.append({ + "Pollutant": pollutant, + "n": int(np.isfinite(total).sum()), + "Free-flow branch (g/lane, median)": float(np.nanmedian(base)), + "Queue branch (g/lane, median)": float(np.nanmedian(queue)), + "Queue share (%, median)": float(100 * np.nanmedian(share)), + "Queue share (%, p10-p90)": ( + f"{100 * np.nanpercentile(share, 10):.0f}-" + f"{100 * np.nanpercentile(share, 90):.0f}" + ), + "Gamma exact (g/h, median)": float(np.nanmedian(gamma_exact)), + "|cubic-exact|/exact Gamma (%, median)": float(100 * np.nanmedian(gamma_gap)), + "Model/observed total (%)": float( + 100 * np.nansum(total) / np.nansum(obs)), + }) + return pd.DataFrame(rows) + + +def main() -> None: + panel = pd.read_csv(STAGE8 / "pooled_validation_panel.csv", + dtype={"sensor_uid": str}, low_memory=False) + moves = load_moves_rates(REPO_ROOT / "experiments" / "emission_input") + surrogates = pd.read_csv( + OUTPUT_ROOT / "stage6_emissions" / "moves_cubic_surrogates.csv") + + figure_f_scatter(panel) + table5 = table5_two_branch(panel, moves, surrogates) + table5.to_csv(TABLE_DIR / "table5_two_branch_decomposition.csv", index=False) + body = table5.round(1).to_latex(index=False, escape=True) + (TABLE_DIR / "table5_two_branch_decomposition.tex").write_text( + "% Auto-generated by run_emission_supplement.py\n" + body, + encoding="utf-8") + print(table5.round(2).to_string(index=False)) + print("Stage 8b complete: fig_F + table5 written") + + +if __name__ == "__main__": + main() diff --git a/experiments/codes/qvdfe_cbi/run_holdout_ablation.py b/experiments/codes/qvdfe_cbi/run_holdout_ablation.py new file mode 100644 index 0000000..4a3c7d8 --- /dev/null +++ b/experiments/codes/qvdfe_cbi/run_holdout_ablation.py @@ -0,0 +1,301 @@ +"""Stage 8 driver — blocked holdout, nested emission ablation, Figures A-E, +Tables 1-4 for the redesigned empirical section. + +Post-processes the frozen Stage 0-7 outputs; run after the main pipeline: + + python experiments/codes/qvdfe_cbi/run_holdout_ablation.py +""" +from __future__ import annotations + +import json +import logging +import sys +import time +from pathlib import Path + +import numpy as np +import pandas as pd + +CODE_ROOT = Path(__file__).resolve().parent +sys.path.insert(0, str(CODE_ROOT / "src")) + +from emissions import POLLUTANTS, load_moves_rates # noqa: E402 +from logging_utils import configure_logging # noqa: E402 +import holdout_ablation as ha # noqa: E402 +import ablation_figures as af # noqa: E402 + +REPO_ROOT = CODE_ROOT.parents[2] +OUTPUT_ROOT = REPO_ROOT / "experiments" / "output" / "qvdfe_cbi" +STAGE8 = OUTPUT_ROOT / "stage8_holdout_ablation" +FIGURE_DIR = STAGE8 / "figures" +TABLE_DIR = STAGE8 / "tables" +DETECTOR = "state_transition" +FOCUS = ("10-E", "405-S", "I-17-NB") +SITE_LABELS = {"10-E": "I-10 EB site", "405-S": "I-405 SB site"} + + +def _tex_table(df: pd.DataFrame, path: Path, caption: str, label: str, + float_format: str = "%.3f") -> None: + body = df.to_latex(index=False, float_format=lambda v: float_format % v, + na_rep="--", escape=True) + path.write_text( + "% Auto-generated by run_holdout_ablation.py\n" + "\\begin{table}[t]\n\\centering\\small\n" + f"\\caption{{{caption}}}\n\\label{{{label}}}\n" + + body + "\\end{table}\n", + encoding="utf-8", + ) + + +def build_evidence_ladder(wide: pd.DataFrame) -> tuple[pd.DataFrame, pd.DataFrame]: + scored = pd.read_csv(OUTPUT_ROOT / "stage2b_outliers" / "episodes_scored.csv", + usecols=["corridor", "is_clean_valid_episode"], + low_memory=False) + qc = pd.read_csv(OUTPUT_ROOT / "dataset_qc_summary.csv") + n_series = int(qc["raw_sensors"].sum()) + focus = wide[wide["corridor"].isin(FOCUS)] + physical = focus[focus["physically_admissible"].astype(bool) & focus["hard_range_ok"]] + strict = physical[physical["cubic_rate_domain_ok"].astype(bool) + & ~physical["flow_synthetic"].astype(bool)] + ladder = pd.DataFrame([ + {"stage": f"{n_series} directional series", "count": n_series}, + {"stage": "episode rows detected", "count": len(scored)}, + {"stage": "clean valid episodes", "count": int(scored["is_clean_valid_episode"].sum())}, + {"stage": "focus-direction evaluated", "count": len(focus)}, + {"stage": "physically admissible", "count": len(physical)}, + {"stage": "strict measured-physical", "count": len(strict)}, + ]) + breakdown_rows = [] + for stage, frame in (("focus-direction evaluated", focus), + ("physically admissible", physical), + ("strict measured-physical", strict)): + for corridor, group in frame.groupby("corridor"): + breakdown_rows.append({"stage": stage, "corridor": corridor, + "count": len(group)}) + return ladder, pd.DataFrame(breakdown_rows) + + +def build_table1(wide: pd.DataFrame) -> pd.DataFrame: + rows = [] + roles = {"10-E": "Structural validation + ablation", + "405-S": "Emission/assignment use case", + "I-17-NB": "Diagnostic stress test (synthetic flow)"} + for corridor in FOCUS: + group = wide[wide["corridor"].eq(corridor)] + physical = group[group["physically_admissible"].astype(bool) + & group["hard_range_ok"]] + strict = physical[physical["cubic_rate_domain_ok"].astype(bool) + & ~physical["flow_synthetic"].astype(bool)] + rows.append({ + "Corridor": corridor, + "Measured speed": "Yes", + "Measured flow": "No" if group["flow_synthetic"].astype(bool).all() else "Yes", + "Evaluated episodes": len(group), + "Physical": len(physical), + "Strict": len(strict), + "Intended role": roles[corridor], + }) + return pd.DataFrame(rows) + + +def build_table2(site_results: dict, sites: pd.DataFrame) -> pd.DataFrame: + rows = [] + for corridor, result in site_results.items(): + state = result["state"] + fit = result["fit"] + site = sites[sites["corridor"].eq(corridor)].iloc[0] + z = pd.to_numeric(state["demand_capacity_ratio"], errors="coerce") + k_j = float(state["jam_density_vpmpl"].iloc[0]) + k_c = float(state["critical_density_vpmpl"].iloc[0]) + cap = float(state["capacity_vphpl"].iloc[0]) + rows.append({ + "Site": SITE_LABELS[corridor], + "Sensor": site["sensor_uid"], "Period": site["period"], + "C^h (vphpl)": cap, + "v_ref (mph)": float(state["v_ref_mph"].iloc[0]), + "k_c (vpmpl)": k_c, "k_j (vpmpl)": k_j, + "omega (mph)": cap / (k_j - k_c), + "f_d": fit.f_d, "n": fit.n, "f_p": fit.f_p, "s": fit.s, + "alpha": fit.alpha, "beta": fit.beta, + "Train episodes": int((state["split"] == "calibration").sum()), + "Held-out episodes": int((state["split"] == "validation").sum()), + "z range": f"[{z.min():.2f}, {z.max():.2f}]", + "Duration bound active": fit.duration_bound_active, + "Speed bound active": fit.speed_bound_active, + "Train duration R2": fit.duration_r2, + "Train speed R2": fit.speed_r2, + }) + return pd.DataFrame(rows) + + +def pick_representative_episode(state: pd.DataFrame) -> pd.Series: + validation = state[state["split"].eq("validation")].copy() + pool = validation[validation["P_obs_hr"] >= 1.0] + if pool.empty: + pool = validation + z = pd.to_numeric(pool["demand_capacity_ratio"], errors="coerce") + return pool.loc[(z - z.median()).abs().idxmin()] + + +def load_day_trace(dataset_key: str, sensor_uid: str, date: str) -> pd.DataFrame: + path = OUTPUT_ROOT / "datasets" / dataset_key / "stage1" / "qc_repaired.csv.gz" + qc = pd.read_csv(path, parse_dates=["datetime"], + usecols=["sensor_uid", "datetime", + "speed_mph_clean_repaired", "flow_vph"], + dtype={"sensor_uid": str}) + mask = qc["sensor_uid"].eq(sensor_uid) & qc["datetime"].dt.date.astype(str).eq(date) + return qc[mask].sort_values("datetime").reset_index(drop=True) + + +def main() -> dict: + STAGE8.mkdir(parents=True, exist_ok=True) + TABLE_DIR.mkdir(parents=True, exist_ok=True) + logger = configure_logging(OUTPUT_ROOT) + started = time.perf_counter() + logger.info("Stage 8 holdout + ablation started (detector=%s)", DETECTOR) + + wide = ha.load_wide_panel(OUTPUT_ROOT) + ranking = pd.read_csv(OUTPUT_ROOT / "stage4_ranking" / "bottleneck_ranking.csv", + dtype={"sensor_uid": str}) + calibration = pd.read_csv(OUTPUT_ROOT / "stage3_qvdf" / "qvdf_calibration.csv", + dtype={"sensor_uid": str}) + fd_frames = [pd.read_csv(p, dtype={"sensor_uid": str}) + for p in OUTPUT_ROOT.glob("datasets/*/stage2_fd/sensor_s3_fd.csv")] + fd_summary = pd.concat(fd_frames, ignore_index=True) + moves = load_moves_rates(REPO_ROOT / "experiments" / "emission_input") + + # ---------------------------------------------------------------- sites -- + sites = ha.select_sites(wide, ranking, calibration, fd_summary, + corridors=("10-E", "405-S"), detector=DETECTOR) + sites.to_csv(STAGE8 / "site_selection.csv", index=False) + logger.info("Stage 8 site selection:\n%s", sites.to_string()) + + site_results, site_states, structural, site_metrics = {}, {}, [], [] + episode_specs = [] + for _, site in sites.iterrows(): + corridor = site["corridor"] + episodes = wide[ + wide["detector"].eq(DETECTOR) + & wide["corridor"].eq(corridor) + & wide["sensor_uid"].eq(site["sensor_uid"]) + & wide["calibration_period"].eq(site["period"]) + & wide["hard_range_ok"] + ].copy() + train_dates, validation_dates = ha.blocked_split(episodes["date"]) + result = ha.refit_and_predict(episodes, train_dates, validation_dates) + if result is None: + logger.warning("Site %s failed the holdout guards", corridor) + continue + state = ha.ablation_emissions(result["state"], moves) + label = SITE_LABELS[corridor] + site_results[corridor] = {**result, "state": state} + site_states[label] = state + state.to_csv(STAGE8 / f"site_state_{corridor.replace('-', '')}.csv", index=False) + structural.append(ha.structural_metrics(state, label)) + site_metrics.append(ha.ablation_metrics( + state[state["split"].eq("validation")], f"{label} (validation)" + )) + episode = pick_representative_episode(state) + episode_specs.append(dict( + corridor=corridor, label=label, episode=episode, + site_state=state, + trace=load_day_trace(episode["dataset"], episode["sensor_uid"], + episode["date"]), + )) + logger.info("Site %s: n=%d train=%d validation=%d | f_d=%.3f n=%.3f " + "f_p=%.3f s=%.3f", corridor, len(episodes), + len(result["train"]), len(result["validation"]), + result["fit"].f_d, result["fit"].n, + result["fit"].f_p, result["fit"].s) + + # --------------------------------------------------------------- pooled -- + pooled, cells = ha.pooled_holdout(wide, moves, corridors=("10-E", "405-S"), + detector=DETECTOR) + cells.to_csv(STAGE8 / "pooled_cell_registry.csv", index=False) + pooled.to_csv(STAGE8 / "pooled_validation_panel.csv", index=False) + pooled_metrics = [] + if not pooled.empty: + strict_mask = (pooled["physically_admissible"].astype(bool) + & pooled["cubic_rate_domain_ok"].astype(bool)) + pooled_metrics.append(ha.ablation_metrics( + pooled[strict_mask], "Pooled strict (validation)")) + pooled_metrics.append(ha.ablation_metrics( + pooled, "Pooled all-domain (validation)")) + logger.info("Pooled holdout: %d cells, %d validation episodes " + "(%d strict)", len(cells), len(pooled), int(strict_mask.sum())) + + metrics = pd.concat(site_metrics + pooled_metrics, ignore_index=True) + metrics.to_csv(STAGE8 / "emission_ablation_metrics.csv", index=False) + structural_df = pd.concat(structural, ignore_index=True) + structural_df.to_csv(STAGE8 / "structural_validation_metrics.csv", index=False) + + # --------------------------------------------------------------- tables -- + table1 = build_table1(wide) + table1.to_csv(TABLE_DIR / "table1_data_evidence.csv", index=False) + _tex_table(table1, TABLE_DIR / "table1_data_evidence.tex", + "Data and evidence levels by focus corridor.", + "tab:v12_data_evidence", "%.0f") + + table2 = build_table2(site_results, sites) + table2.to_csv(TABLE_DIR / "table2_site_parameters.csv", index=False) + _tex_table(table2, TABLE_DIR / "table2_site_parameters.tex", + "Selected bottleneck sites and calibration-block parameters.", + "tab:v12_site_parameters") + + table3 = structural_df.round(3) + table3.to_csv(TABLE_DIR / "table3_structural_validation.csv", index=False) + _tex_table(table3, TABLE_DIR / "table3_structural_validation.tex", + "Held-out structural validation on the final 30\\% of dates.", + "tab:v12_structural_validation") + + table4 = metrics[["subset", "pollutant", "model_label", "n", "NMAE_pct", + "MAPE_pct", "bias_pct", "R2", "delta_NMAE_vs_delay_pct", + "delta_NMAE_ci_lo", "delta_NMAE_ci_hi"]].round(2) + table4.to_csv(TABLE_DIR / "table4_emission_ablation.csv", index=False) + _tex_table(table4, TABLE_DIR / "table4_emission_ablation.tex", + "Nested emission-model ablation on held-out episodes " + "(paired bootstrap 95\\% CIs on $\\Delta$NMAE vs the " + "delay-only model).", + "tab:v12_emission_ablation", "%.2f") + + # -------------------------------------------------------------- figures -- + ladder, breakdown = build_evidence_ladder(wide) + ladder.to_csv(STAGE8 / "evidence_ladder.csv", index=False) + af.figure_a_evidence_ladder(ladder, breakdown, FIGURE_DIR) + if episode_specs: + af.figure_b_representative_episodes(episode_specs, FIGURE_DIR) + if site_states: + af.figure_c_structural(site_states, FIGURE_DIR) + forest_subsets = [f"{SITE_LABELS['405-S']} (validation)", + "Pooled strict (validation)"] + forest = metrics[metrics["subset"].isin(forest_subsets)] + if not forest.empty: + af.figure_d_ablation_forest(forest, FIGURE_DIR) + site_grids = {label: af.build_site_grid(state, moves) + for label, state in site_states.items()} + for label, grid in site_grids.items(): + grid.to_csv(STAGE8 / f"response_grid_{label.replace(' ', '_')}.csv", + index=False) + if site_grids: + af.figure_e_phase_admissibility(wide, site_states, site_grids, FIGURE_DIR) + + manifest = { + "detector": DETECTOR, + "sites": sites.to_dict("records"), + "n_pooled_cells": int(len(cells)), + "n_pooled_validation_episodes": int(len(pooled)), + "n_metric_rows": int(len(metrics)), + "elapsed_seconds": time.perf_counter() - started, + "n_bootstrap": ha.N_BOOTSTRAP, + "train_fraction": ha.TRAIN_FRACTION, + "outputs": sorted(str(p.relative_to(STAGE8)) for p in STAGE8.rglob("*") + if p.is_file()), + } + (STAGE8 / "stage8_manifest.json").write_text( + json.dumps(manifest, indent=2, default=str), encoding="utf-8") + logger.info("Stage 8 complete in %.1f s", manifest["elapsed_seconds"]) + return manifest + + +if __name__ == "__main__": + main() diff --git a/experiments/codes/qvdfe_cbi/src/ablation_figures.py b/experiments/codes/qvdfe_cbi/src/ablation_figures.py new file mode 100644 index 0000000..3034b2f --- /dev/null +++ b/experiments/codes/qvdfe_cbi/src/ablation_figures.py @@ -0,0 +1,436 @@ +"""Stage 8 principal figures A-E for the redesigned empirical section. + +One corridor color throughout (I-10 blue, I-405 orange, I-17 muted gray); +black for theory/reference curves; dark red for queued states; open markers +for calibration episodes, filled for validation; direct labels over legends. +""" +from __future__ import annotations + +import logging +from pathlib import Path + +import matplotlib +if not str(matplotlib.get_backend()).lower().startswith(("agg",)): + matplotlib.use("Agg") +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd + +from emissions import MovesRates +from two_regime_emissions import ( + DEFAULT_JAM_DENSITY_VPMPL, + DEFAULT_LOADING_PERIOD_HR, + evaluate_state, + exact_rate_for_speed, + gamma_from_rate, +) + +LOGGER = logging.getLogger("qvdfe_cbi") + +CORRIDOR_COLORS = {"10-E": "#0072B2", "405-S": "#D55E00", "I-17-NB": "#7F7F7F", + "I-17-SB": "#B0B0B0", "10-W": "#69A8D6", "405-N": "#E89A66"} +QUEUED_RED = "#8B0000" +THEORY_BLACK = "#000000" + + +def _style() -> None: + plt.rcParams.update({ + "figure.dpi": 150, "savefig.dpi": 300, + "font.size": 9, "axes.titlesize": 9.5, "axes.labelsize": 9, + "xtick.labelsize": 8, "ytick.labelsize": 8, "legend.fontsize": 7.5, + "axes.spines.top": False, "axes.spines.right": False, + "axes.grid": True, "grid.alpha": 0.25, "grid.linewidth": 0.5, + }) + + +def _save(fig, directory: Path, name: str) -> None: + directory.mkdir(parents=True, exist_ok=True) + for ext in ("pdf", "png"): + fig.savefig(directory / f"{name}.{ext}", bbox_inches="tight") + plt.close(fig) + LOGGER.info("Stage 8 figure written: %s", name) + + +# ------------------------------------------------------------------ Figure A -- +def figure_a_evidence_ladder(ladder: pd.DataFrame, corridor_breakdown: pd.DataFrame, + figure_dir: Path) -> None: + """Attrition funnel with corridor breakdown at the final stages.""" + _style() + fig, ax = plt.subplots(figsize=(7.4, 3.4)) + stages = ladder["stage"].tolist() + counts = ladder["count"].to_numpy(float) + y = np.arange(len(stages))[::-1] + breakdown_stages = set(corridor_breakdown["stage"]) + for yi, stage, count in zip(y, stages, counts): + if stage in breakdown_stages: + left = 0.0 + for _, row in corridor_breakdown[corridor_breakdown["stage"].eq(stage)].iterrows(): + ax.barh(yi, row["count"], left=left, height=0.62, + color=CORRIDOR_COLORS.get(row["corridor"], "#999999"), + edgecolor="white", linewidth=0.4) + if row["count"] > 0.04 * counts.max(): + ax.text(left + row["count"] / 2, yi, f"{int(row['count'])}", + ha="center", va="center", fontsize=7, color="white") + left += row["count"] + else: + ax.barh(yi, count, height=0.62, color="#5B5B5B", + edgecolor="white", linewidth=0.4) + ax.text(count + 0.01 * counts.max(), yi, f"{int(count):,}", + va="center", fontsize=8.5, fontweight="bold") + ax.set_yticks(y) + ax.set_yticklabels(stages, fontsize=8.5) + ax.set_xlabel("episodes (series at the first stage)") + ax.set_xlim(0, 1.14 * counts.max()) + handles = [plt.Rectangle((0, 0), 1, 1, color=CORRIDOR_COLORS[c]) + for c in ("10-E", "405-S", "I-17-NB")] + ax.legend(handles, ["I-10 EB", "I-405 SB", "I-17 NB"], + loc="lower right", frameon=False, title=None) + ax.set_title("Evidence architecture: detection to strict measured-physical domain") + _save(fig, figure_dir, "fig_A_evidence_ladder") + + +# ------------------------------------------------------------------ Figure B -- +def _fd_triangle(ax, v_ref, capacity, k_j): + k_c = capacity / v_ref + omega = capacity / (k_j - k_c) + ax.plot([0, k_c], [0, capacity], color=THEORY_BLACK, lw=1.4) + ax.plot([k_c, k_j], [capacity, 0.0], color=THEORY_BLACK, lw=1.4) + return k_c, omega + + +def figure_b_representative_episodes(episode_specs: list[dict], + figure_dir: Path) -> None: + """One row per site: observed trajectory, discharge reduction, FD + projection, and the (z, P/H) plane with Vickrey and QVDF curves.""" + _style() + n_rows = len(episode_specs) + fig, axes = plt.subplots(n_rows, 4, figsize=(12.6, 3.1 * n_rows)) + axes = np.atleast_2d(axes) + for i, spec in enumerate(episode_specs): + color = CORRIDOR_COLORS.get(spec["corridor"], "#333333") + trace = spec["trace"] + ep = spec["episode"] + t = pd.to_datetime(trace["datetime"]) + hours = t.dt.hour + t.dt.minute / 60.0 + v = pd.to_numeric(trace["speed_mph_clean_repaired"], errors="coerce") + q = pd.to_numeric(trace["flow_vph"], errors="coerce") + t0 = pd.Timestamp(ep["t0_timestamp"]); t2 = pd.Timestamp(ep["t2_timestamp"]) + t3 = pd.Timestamp(ep["t3_timestamp"]) + h0 = t0.hour + t0.minute / 60; h2 = t2.hour + t2.minute / 60 + h3 = t3.hour + t3.minute / 60 + v_ref = float(ep["v_ref_mph"]); cap = float(ep["capacity_vphpl"]) + k_j = float(ep.get("jam_density_vpmpl", DEFAULT_JAM_DENSITY_VPMPL)) + + # Panel 1 — observed trajectory + ax = axes[i, 0] + ax.plot(hours, v, color=color, lw=1.0) + ax.axvspan(h0, h3, color=color, alpha=0.12) + for h, label in ((h0, r"$t_0$"), (h2, r"$t_2$"), (h3, r"$t_3$")): + ax.axvline(h, color=QUEUED_RED, lw=0.7, ls=":") + ax.text(h, ax.get_ylim()[1] * 0.02 + v.max() * 1.02, label, + ha="center", fontsize=8, color=QUEUED_RED) + ax.axhline(float(ep["threshold_used"]), color=THEORY_BLACK, lw=0.8, ls="--") + ax.text(5.3, float(ep["threshold_used"]) + 1.2, r"$v_c$", fontsize=8) + ax2 = ax.twinx() + ax2.plot(hours, q, color="#888888", lw=0.7, alpha=0.7) + ax2.set_ylabel("flow (vphpl)", fontsize=7.5, color="#666666") + ax2.tick_params(labelsize=7, colors="#666666") + ax2.spines["right"].set_visible(True) + ax2.grid(False) + ax.set_xlim(5, 22) + ax.set_xlabel("hour of day"); ax.set_ylabel("speed (mph)") + ax.set_title(f"{spec['label']} {ep['date']} " + f"$P$={float(ep['P_obs_hr']):.2f} h", loc="right", fontsize=8.5) + + # Panel 2 — discharge reduction mu(t) -> mu_e + ax = axes[i, 1] + in_ep = (hours >= h0) & (hours <= h3) + mu_t = q[in_ep] + mu_e = float(np.nanmean(mu_t)) + ax.plot(hours[in_ep], mu_t, color=color, lw=1.1) + ax.axhline(mu_e, color=QUEUED_RED, lw=1.4) + ax.axhline(cap, color=THEORY_BLACK, lw=0.9, ls="--") + ax.text(h0 + 0.05, cap * 1.01, r"$C^h$", fontsize=8) + ax.text(h3, mu_e * 0.93, rf"$\mu_e$={mu_e:.0f}", fontsize=8, + ha="right", color=QUEUED_RED) + ax.set_title(rf"$\mu_e/C^h = {mu_e / cap:.2f}$") + ax.set_xlabel("hour of day"); ax.set_ylabel(r"$\mu(t)$ (vphpl)") + + # Panel 3 — FD projection + ax = axes[i, 2] + k_c, omega = _fd_triangle(ax, v_ref, cap, k_j) + k_e = k_j - mu_e / omega + v_e = mu_e / k_e + ax.scatter([k_e], [mu_e], s=45, color=QUEUED_RED, zorder=5) + ax.plot([0, k_e], [0, mu_e], color=QUEUED_RED, lw=0.8, ls="--") + ax.annotate(rf"$(k_e,\mu_e)$, $v_e$={v_e:.0f} mph", + (k_e, mu_e), textcoords="offset points", xytext=(6, 8), + fontsize=8, color=QUEUED_RED) + v_obs = float(ep["mean_speed_mph"]) + if np.isfinite(v_obs) and v_obs > 0: + k_obs = mu_e / v_obs + ax.scatter([k_obs], [mu_e], s=40, facecolors="none", + edgecolors=color, lw=1.4, zorder=5) + ax.annotate(rf"observed $\bar v_q$={v_obs:.0f}", + (k_obs, mu_e), textcoords="offset points", + xytext=(6, -14), fontsize=8, color=color) + ax.set_xlabel("density (veh/mi/lane)"); ax.set_ylabel("flow (vphpl)") + ax.set_title("effective FD state") + ax.set_xlim(0, k_j * 1.02); ax.set_ylim(0, cap * 1.18) + + # Panel 4 — (z, P/H) plane + ax = axes[i, 3] + site = spec["site_state"] + cal = site[site["split"].eq("calibration")] + val = site[site["split"].eq("validation")] + H = float(ep.get("loading_period_hr", DEFAULT_LOADING_PERIOD_HR)) + ax.scatter(cal["demand_capacity_ratio"], cal["P_obs_hr"] / H, + s=18, facecolors="none", edgecolors=color, lw=0.8, alpha=0.7) + ax.scatter(val["demand_capacity_ratio"], val["P_obs_hr"] / H, + s=20, color=color, alpha=0.85) + z_grid = np.linspace(max(site["demand_capacity_ratio"].min() * 0.9, 1e-3), + site["demand_capacity_ratio"].max() * 1.05, 100) + f_d = float(site["f_d"].iloc[0]); n_exp = float(site["n"].iloc[0]) + ax.plot(z_grid, z_grid, color=THEORY_BLACK, ls="--", lw=1.0) + ax.plot(z_grid, f_d * z_grid ** n_exp, color=THEORY_BLACK, lw=1.3) + ax.text(z_grid[-1], z_grid[-1] * 0.99, "Vickrey $n$=1", fontsize=7.5, + ha="right", va="top") + ax.text(z_grid[0], f_d * z_grid[0] ** n_exp * 1.05, + rf"QVDF $f_d$={f_d:.2f}, $n$={n_exp:.2f}", + fontsize=7.5, ha="left", va="bottom") + z_ep = float(ep["demand_capacity_ratio"]); p_ep = float(ep["P_obs_hr"]) / H + ax.scatter([z_ep], [p_ep], s=60, color=QUEUED_RED, marker="*", zorder=6) + ax.set_xlabel(r"$z=\mu_e P / (C^h H)$"); ax.set_ylabel(r"$P/H$") + ax.set_title("derived $z$ and QVDF duration") + fig.tight_layout() + _save(fig, figure_dir, "fig_B_representative_episodes") + + +# ------------------------------------------------------------------ Figure C -- +def figure_c_structural(site_states: dict[str, pd.DataFrame], + figure_dir: Path) -> None: + """P/H vs z; mu_e/C^h vs P/H; observed queued speed vs v_e(z).""" + _style() + fig, axes = plt.subplots(1, 3, figsize=(11.4, 3.5)) + H = DEFAULT_LOADING_PERIOD_HR + for label, site in site_states.items(): + corridor = site["corridor"].iloc[0] + color = CORRIDOR_COLORS.get(corridor, "#333333") + cal = site[site["split"].eq("calibration")] + val = site[site["split"].eq("validation")] + z_grid = np.linspace(max(site["demand_capacity_ratio"].min() * 0.9, 1e-3), + site["demand_capacity_ratio"].max() * 1.05, 120) + f_d = float(site["f_d"].iloc[0]); n_exp = float(site["n"].iloc[0]) + p_grid = f_d * z_grid ** n_exp + + ax = axes[0] + ax.scatter(cal["demand_capacity_ratio"], cal["P_obs_hr"] / H, s=16, + facecolors="none", edgecolors=color, lw=0.8, alpha=0.65) + ax.scatter(val["demand_capacity_ratio"], val["P_obs_hr"] / H, s=18, + color=color, alpha=0.85, label=label) + ax.plot(z_grid, p_grid, color=color, lw=1.3) + + ax = axes[1] + mu_ratio_obs = site["mu_obs_vphpl"] / site["capacity_vphpl"] + ax.scatter(cal["P_obs_hr"] / H, mu_ratio_obs.loc[cal.index], s=16, + facecolors="none", edgecolors=color, lw=0.8, alpha=0.65) + ax.scatter(val["P_obs_hr"] / H, mu_ratio_obs.loc[val.index], s=18, + color=color, alpha=0.85) + ax.plot(p_grid, z_grid ** (1.0 - n_exp) / f_d, color=color, lw=1.3) + + ax = axes[2] + ax.scatter(cal["v_q_model_mph"], cal["mean_speed_mph"], s=16, + facecolors="none", edgecolors=color, lw=0.8, alpha=0.65) + ax.scatter(val["v_q_model_mph"], val["mean_speed_mph"], s=18, + color=color, alpha=0.85) + + z_line = np.linspace(0, axes[0].get_xlim()[1], 10) + axes[0].plot(z_line, z_line, color=THEORY_BLACK, ls="--", lw=1.0) + axes[0].text(z_line[-2], z_line[-2], "Vickrey $n$=1", fontsize=7.5, + va="bottom", ha="right") + axes[0].set_xlabel(r"$z$"); axes[0].set_ylabel(r"$P/H$") + axes[0].set_title("duration closure $P(z)=f_d z^n$") + axes[0].legend(frameon=False, loc="upper left") + + axes[1].axhline(1.0, color=THEORY_BLACK, ls="--", lw=1.0) + axes[1].text(axes[1].get_xlim()[1] * 0.98, 1.005, r"Vickrey $\mu_e=C^h$", + fontsize=7.5, ha="right", va="bottom") + axes[1].set_xlabel(r"$P/H$"); axes[1].set_ylabel(r"$\mu_e/C^h$") + axes[1].set_title("capacity retention vs duration") + + lim = [0, max(axes[2].get_xlim()[1], axes[2].get_ylim()[1])] + axes[2].plot(lim, lim, color=THEORY_BLACK, ls="--", lw=1.0) + axes[2].set_xlabel(r"model $v_e(z)$ (mph)") + axes[2].set_ylabel(r"observed mean queued speed (mph)") + axes[2].set_title("effective queued speed") + fig.tight_layout() + _save(fig, figure_dir, "fig_C_structural_validation") + + +# ------------------------------------------------------------------ Figure D -- +def figure_d_ablation_forest(metrics: pd.DataFrame, figure_dir: Path) -> None: + """Delta NMAE relative to the delay-only model, with paired bootstrap CIs.""" + _style() + subsets = list(dict.fromkeys(metrics["subset"])) + models = ["B0_mean_speed", "B2_fixed_vq", "B3_fd_state"] + model_style = { + "B0_mean_speed": {"color": "#888888", "marker": "o", "label": "B0 mean speed"}, + "B2_fixed_vq": {"color": "#7B52A1", "marker": "s", "label": r"B2 fixed $\tilde v_q$"}, + "B3_fd_state": {"color": QUEUED_RED, "marker": "D", "label": r"B3 FD $v_e(z)$"}, + } + pollutants = ["CO2", "NOX", "CO", "HC"] + fig, axes = plt.subplots(1, len(subsets), figsize=(4.3 * len(subsets), 3.6), + sharey=True) + axes = np.atleast_1d(axes) + for ax, subset in zip(axes, subsets): + sub = metrics[metrics["subset"].eq(subset)] + for pi, pollutant in enumerate(pollutants): + for mi, model in enumerate(models): + row = sub[sub["pollutant"].eq(pollutant) & sub["model"].eq(model)] + if row.empty: + continue + row = row.iloc[0] + y = len(pollutants) - 1 - pi + (mi - 1) * 0.22 + style = model_style[model] + ax.errorbar( + row["delta_NMAE_vs_delay_pct"], y, + xerr=[[row["delta_NMAE_vs_delay_pct"] - row["delta_NMAE_ci_lo"]], + [row["delta_NMAE_ci_hi"] - row["delta_NMAE_vs_delay_pct"]]], + fmt=style["marker"], color=style["color"], ms=5, + capsize=2.5, lw=1.1, + ) + ax.axvline(0.0, color=THEORY_BLACK, lw=1.0) + ax.set_yticks(range(len(pollutants))) + ax.set_yticklabels([{"CO2": r"CO$_2$", "NOX": r"NO$_x$"}.get(p, p) + for p in pollutants[::-1]]) + ax.set_xlabel(r"$\Delta$NMAE vs delay-only B1 (pp; $<0$ is better)") + ax.set_title(subset, fontsize=9) + handles = [plt.Line2D([], [], color=s["color"], marker=s["marker"], ls="", + label=s["label"]) for s in model_style.values()] + axes[-1].legend(handles=handles, frameon=False, loc="best") + fig.tight_layout() + _save(fig, figure_dir, "fig_D_emission_ablation_forest") + + +# ------------------------------------------------------------------ Figure E -- +def build_site_grid(site_state: pd.DataFrame, moves: MovesRates, + pollutant: str = "CO2", points: int = 141) -> pd.DataFrame: + """z-grid response curves T(z), e(z), g(z) + admissibility classification + using the site's TRAIN-block parameters.""" + z_obs = pd.to_numeric(site_state["demand_capacity_ratio"], errors="coerce").dropna() + z_grid = np.linspace(max(z_obs.min() * 0.85, 1e-3), z_obs.max() * 1.10, points) + first = site_state.iloc[0] + grid = pd.DataFrame({ + "demand_capacity_ratio": z_grid, + "episode_demand": np.nan, + "length_mi": float(site_state["length_mi"].median()), + "v_ref_mph": float(site_state["v_ref_mph"].median()), + "capacity_vphpl": float(site_state["capacity_vphpl"].median()), + "f_d": float(first["f_d"]), "n": float(first["n"]), + "f_p": float(first["f_p"]), "s": float(first["s"]), + }) + grid["episode_demand"] = (grid["capacity_vphpl"] * DEFAULT_LOADING_PERIOD_HR + * grid["demand_capacity_ratio"]) + grid = evaluate_state(grid, jam_density_vpmpl=DEFAULT_JAM_DENSITY_VPMPL, + loading_period_hr=DEFAULT_LOADING_PERIOD_HR) + rate = lambda speed: exact_rate_for_speed(moves, speed, pollutant) + v_ref = grid["v_ref_mph"].to_numpy(float) + tc = grid["reference_time_hr"].to_numpy(float) + wbar = grid["w_bar_model_hr"].to_numpy(float) + gamma = gamma_from_rate(grid["v_q_model_mph"].to_numpy(float), v_ref, rate) + grid["T_hr"] = tc + wbar + grid["e_g_per_vehicle"] = rate(v_ref) * tc + gamma * wbar + z_mid_idx = len(grid) // 2 + t_ref = float(grid["T_hr"].iloc[z_mid_idx]) + e_ref = float(grid["e_g_per_vehicle"].iloc[z_mid_idx]) + grid["g_normalized"] = 0.5 * grid["T_hr"] / t_ref + 0.5 * grid["e_g_per_vehicle"] / e_ref + dg = np.gradient(grid["g_normalized"].to_numpy(float), z_grid, edge_order=2) + tol = 1e-7 * max(1.0, float(np.nanmax(np.abs(dg)))) + grid["g_monotone_ok"] = dg >= -tol + grid["z_observed_lo"] = float(z_obs.min()) + grid["z_observed_hi"] = float(z_obs.max()) + grid["pollutant"] = pollutant + return grid + + +def _shade_intervals(ax, z, ok, y0, y1, color, label): + ok = np.asarray(ok, dtype=bool) + started = None + labeled = False + for i, flag in enumerate(ok): + if flag and started is None: + started = z[i] + if (not flag or i == len(ok) - 1) and started is not None: + end = z[i] if flag else z[max(i - 1, 0)] + ax.axvspan(started, end, ymin=y0, ymax=y1, color=color, alpha=0.35, + lw=0, label=label if not labeled else None) + labeled = True + started = None + + +def figure_e_phase_admissibility(wide: pd.DataFrame, + site_states: dict[str, pd.DataFrame], + site_grids: dict[str, pd.DataFrame], + figure_dir: Path) -> None: + """Phase diagram (z, mu_e/C^h) + per-site response curves with the + admissible-domain bands.""" + _style() + fig = plt.figure(figsize=(12.2, 4.1)) + gs = fig.add_gridspec(2, 3, width_ratios=[1.5, 1, 1], hspace=0.55, wspace=0.33) + + # Left — phase diagram + ax = fig.add_subplot(gs[:, 0]) + focus = wide[wide["corridor"].isin(("10-E", "405-S", "I-17-NB")) + & wide["detector"].eq("state_transition")] + for corridor, group in focus.groupby("corridor"): + color = CORRIDOR_COLORS.get(corridor, "#999999") + mu_ratio = (pd.to_numeric(group["mu_obs_vphpl"], errors="coerce") + / pd.to_numeric(group["capacity_vphpl"], errors="coerce")) + admissible = group["physically_admissible"].astype(bool) + ax.scatter(group.loc[~admissible, "demand_capacity_ratio"], + mu_ratio[~admissible], s=8, color=color, alpha=0.18, lw=0) + ax.scatter(group.loc[admissible, "demand_capacity_ratio"], + mu_ratio[admissible], s=11, color=color, alpha=0.65, lw=0, + label=f"{corridor} (admissible)") + for k, (label, grid) in enumerate(site_grids.items()): + z = grid["demand_capacity_ratio"].to_numpy(float) + mu_ratio = (grid["mu_model_vphpl"] / grid["capacity_vphpl"]).to_numpy(float) + ax.plot(z, mu_ratio, color=THEORY_BLACK, lw=1.6, + ls="-" if k == 0 else (0, (5, 2))) + # both site paths sit near mu_e/C^h = 1/f_d ~= 0.72 — dodge the labels + anchor = -1 if k == 0 else 0 + ax.annotate(label, (z[anchor], mu_ratio[anchor]), fontsize=7.5, + textcoords="offset points", + xytext=(4, -3) if k == 0 else (-4, 8), + ha="left" if k == 0 else "right") + ax.axhline(1.0, color=THEORY_BLACK, ls="--", lw=0.9) + ax.text(0.02, 1.01, r"$\mu_e=C^h$ (Vickrey)", fontsize=7.5, + transform=ax.get_yaxis_transform()) + ax.set_xlabel(r"$z$"); ax.set_ylabel(r"$\mu_e/C^h$") + ax.set_ylim(0, 1.35) + ax.set_title("episode phase diagram with site calibration paths") + ax.legend(frameon=False, loc="lower left", fontsize=7) + + # Right — response curves per site + for column, (label, grid) in enumerate(site_grids.items()): + z = grid["demand_capacity_ratio"].to_numpy(float) + ax_t = fig.add_subplot(gs[0, column + 1]) + ax_e = fig.add_subplot(gs[1, column + 1]) + ax_t.plot(z, 60.0 * grid["T_hr"], color=THEORY_BLACK, lw=1.3) + ax_t.set_ylabel(r"$T(z)$ (min)") + ax_t.set_title(label, fontsize=9) + ax_e.plot(z, grid["e_g_per_vehicle"], color=QUEUED_RED, lw=1.3) + ax_e.set_ylabel(r"$e(z)$ (g CO$_2$/veh)") + ax_e.set_xlabel(r"$z$") + for ax_i in (ax_t, ax_e): + lo = float(grid["z_observed_lo"].iloc[0]) + hi = float(grid["z_observed_hi"].iloc[0]) + ax_i.axvspan(lo, hi, color="#0072B2", alpha=0.08, lw=0) + _shade_intervals(ax_i, z, grid["physically_admissible"], 0, 0.06, + "#009E73", "physical") + _shade_intervals(ax_i, z, grid["cubic_rate_domain_ok"], 0.06, 0.12, + "#E6C300", "rate domain") + _shade_intervals(ax_i, z, grid["g_monotone_ok"], 0.12, 0.18, + "#7B52A1", "monotone $g$") + ax_e.legend(frameon=False, fontsize=6.5, loc="upper left") + _save(fig, figure_dir, "fig_E_phase_admissibility") diff --git a/experiments/codes/qvdfe_cbi/src/holdout_ablation.py b/experiments/codes/qvdfe_cbi/src/holdout_ablation.py new file mode 100644 index 0000000..7045d64 --- /dev/null +++ b/experiments/codes/qvdfe_cbi/src/holdout_ablation.py @@ -0,0 +1,398 @@ +"""Stage 8 — blocked holdout validation and nested emission ablation. + +Post-processes the frozen Stage 2b-7 outputs (no pipeline re-run): + +1. Site selection under a rule fixed BEFORE any emission error is examined + (measured flow, episode count, FD stability, no active QVDF bounds, + strict-domain coverage, then highest CBI score). +2. Blocked 70/30 date split (first 70% of dates calibrate, last 30% + validate) — never random episodes from the same day on both sides. +3. QVDF refit on the calibration block only; the fixed-capacity Vickrey + line (mu_e = C^h => P = Hz, n = 1) and a fixed queued speed are the + structural benchmarks. +4. Nested emission models on the validation block: + B0 mean-speed e = r(v_avg) [T_c + w(z)], v_avg = L/(T_c+w(z)) + B1 delay-only e = r(v_ref) [T_c + w(z)] + B2 fixed v_q e = r(v_ref) T_c + Gamma(v_q_tilde) w(z) + B3 FD-consistent e = r(v_ref) T_c + Gamma(v_e(z)) w(z) + all against the observed-speed five-minute MOVES episode totals, with + paired bootstrap confidence intervals on Delta NMAE. +""" +from __future__ import annotations + +import logging +from pathlib import Path + +import numpy as np +import pandas as pd + +from calibration import fit_qvdf +from emissions import POLLUTANTS, MovesRates +from two_regime_emissions import ( + THETA_MEAN_TO_MAX_DELAY, + DEFAULT_JAM_DENSITY_VPMPL, + DEFAULT_LOADING_PERIOD_HR, + evaluate_state, + exact_rate_for_speed, + gamma_from_rate, +) + +LOGGER = logging.getLogger("qvdfe_cbi") + +TRAIN_FRACTION = 0.70 +MIN_TRAIN_EPISODES = 8 +MIN_VALIDATION_EPISODES = 4 +MIN_CELL_EPISODES = 8 # pooled run: smallest sensor-period cell +# The 27-date PeMS window caps a sensor-period cell at 18-19 clean episodes, +# so the plan's 20-30 floor is structurally unreachable; 12 is the feasible +# equivalent and is fixed here BEFORE any emission error is examined. +MIN_SITE_EPISODES = 12 +MIN_STRICT_COVERAGE = 0.50 # >= 50% of site episodes in the strict domain +N_BOOTSTRAP = 2000 +BOOTSTRAP_SEED = 20260725 + +MODEL_LABELS = { + "B0_mean_speed": "B0 whole-link mean speed", + "B1_delay_only": "B1 delay-only / reference rate", + "B2_fixed_vq": "B2 fixed queued state", + "B3_fd_state": "B3 FD-consistent effective state", +} +ALL_MODEL_LABELS = { + **MODEL_LABELS, + "R_reconstructed_speed": "Reconstructed-speed MOVES (diagnostic)", +} + + +# --------------------------------------------------------------------- panel -- +def load_wide_panel(output_root: Path) -> pd.DataFrame: + """Load the Stage 7 per-episode effective-state table and re-screen it + with the hard range rules (out-of-range points previously passed every + ``>`` comparison as False).""" + wide = pd.read_csv( + Path(output_root) / "stage7_two_regime_emissions" + / "episode_two_regime_emissions_wide.csv", + dtype={"sensor_uid": str}, + low_memory=False, + ) + z = pd.to_numeric(wide["demand_capacity_ratio"], errors="coerce") + p_obs = pd.to_numeric(wide["P_obs_hr"], errors="coerce") + vt2 = pd.to_numeric(wide["vt2_obs_mph"], errors="coerce") + mu = pd.to_numeric(wide["mu_obs_vphpl"], errors="coerce") + cap = pd.to_numeric(wide["capacity_vphpl"], errors="coerce") + hard_ok = ( + np.isfinite(z) & (z > 0) & (z <= 8.0) + & np.isfinite(p_obs) & (p_obs > 0) & (p_obs <= 24.0) + & np.isfinite(vt2) & (vt2 >= 0) & (vt2 <= 90.0) + & (~np.isfinite(mu) | ((mu > 0) & (mu <= 1.05 * cap))) + ) + wide["hard_range_ok"] = hard_ok + n_dropped = int((~hard_ok).sum()) + if n_dropped: + LOGGER.info("Stage 8 hard-range rescreen drops %d of %d episodes", + n_dropped, len(wide)) + wide["strict_eligible"] = ( + wide["physically_admissible"].astype(bool) + & wide["cubic_rate_domain_ok"].astype(bool) + & ~wide["flow_synthetic"].astype(bool) + & hard_ok + ) + wide["date"] = wide["date"].astype(str) + return wide + + +# ------------------------------------------------------------ site selection -- +def select_sites( + wide: pd.DataFrame, + ranking: pd.DataFrame, + calibration: pd.DataFrame, + fd_summary: pd.DataFrame, + corridors=("10-E", "405-S"), + detector: str = "state_transition", +) -> pd.DataFrame: + """Apply the six-step ex-ante selection rule; return one row per corridor.""" + cal = calibration.loc[ + calibration["calibration_scope"].eq("sensor_period") + & calibration["status"].eq("ok") + & calibration["detector"].eq(detector) + ] + fd_r2 = fd_summary.set_index("sensor_uid")["r2"] if "r2" in fd_summary.columns else None + rows = [] + sub = wide[wide["detector"].eq(detector) & wide["hard_range_ok"]] + for corridor in corridors: + group = sub[sub["corridor"].eq(corridor)] + candidates = [] + for (sensor, period), cell in group.groupby(["sensor_uid", "calibration_period"]): + n_clean = len(cell) + measured = not bool(cell["flow_synthetic"].astype(bool).any()) + strict_cov = float(cell["strict_eligible"].mean()) + cal_row = cal[ + cal["corridor"].eq(corridor) + & cal["sensor_uid"].eq(sensor) + & cal["calibration_period"].eq(period) + ] + bounds_free = bool( + len(cal_row) + and not cal_row["duration_bound_active"].iloc[0] + and not cal_row["speed_bound_active"].iloc[0] + ) + fd_stable = True + if fd_r2 is not None and sensor in fd_r2.index: + fd_stable = bool(pd.to_numeric(fd_r2.loc[sensor]) >= 0.70) + rank_row = ranking[ + ranking["detector"].eq(detector) + & ranking["corridor"].eq(corridor) + & ranking["sensor_uid"].eq(sensor) + & (ranking["calibration_period"].eq(period) + if "calibration_period" in ranking.columns else True) + ] + cbi = float(rank_row["CBI_score"].max()) if len(rank_row) else np.nan + n_dates = cell["date"].nunique() + candidates.append(dict( + corridor=corridor, sensor_uid=sensor, period=period, + n_clean_episodes=n_clean, n_dates=n_dates, + measured_volume=measured, fd_stable=fd_stable, + bounds_free=bounds_free, strict_coverage=strict_cov, + cbi_score=cbi, + # bounds_free is a TIEBREAKER, not an eligibility gate: the + # full-sample stage-3 bound flags exclude every high-CBI + # strict-covered cell, and the holdout refits on the training + # block anyway (its own bound status is reported in Table 2). + passes_rule=bool( + measured and fd_stable + and n_clean >= MIN_SITE_EPISODES + and strict_cov >= MIN_STRICT_COVERAGE + ), + )) + cand = pd.DataFrame(candidates) + eligible = cand[cand["passes_rule"]] + pool = eligible if len(eligible) else cand + best = pool.sort_values( + ["cbi_score", "bounds_free", "n_clean_episodes"], ascending=False + ).iloc[0] + rows.append({**best.to_dict(), "selected": True, + "n_candidates": len(cand), "n_eligible": int(cand["passes_rule"].sum())}) + return pd.DataFrame(rows) + + +# ------------------------------------------------------------- blocked split -- +def blocked_split(dates: pd.Series, train_fraction: float = TRAIN_FRACTION): + """First 70% of DATES calibrate, last 30% validate (no temporal leakage).""" + unique = np.sort(dates.unique()) + n_train = int(np.ceil(train_fraction * len(unique))) + n_train = min(max(n_train, 1), len(unique) - 1) + return set(unique[:n_train]), set(unique[n_train:]) + + +def refit_and_predict( + episodes: pd.DataFrame, + train_dates: set, + validation_dates: set, + jam_density: float = DEFAULT_JAM_DENSITY_VPMPL, + loading_period_hr: float = DEFAULT_LOADING_PERIOD_HR, +): + """Refit QVDF on the calibration block; rebuild the full effective-state + chain on ALL episodes with the train-block parameters.""" + train = episodes[episodes["date"].isin(train_dates)] + validation = episodes[episodes["date"].isin(validation_dates)] + if len(train) < MIN_TRAIN_EPISODES or len(validation) < MIN_VALIDATION_EPISODES: + return None + vc = float(pd.to_numeric(train["threshold_used"], errors="coerce").median()) + fit = fit_qvdf( + train["demand_capacity_ratio"], train["P_obs_hr"], + train["vt2_obs_mph"], vc, min_episodes=3, + ) + if fit.status != "ok": + return None + frame = episodes.copy() + for column, value in (("f_d", fit.f_d), ("n", fit.n), ("f_p", fit.f_p), ("s", fit.s)): + frame[column] = value + state = evaluate_state( + frame, jam_density_vpmpl=jam_density, loading_period_hr=loading_period_hr + ) + state["split"] = np.where(state["date"].isin(train_dates), "calibration", "validation") + # Vickrey fixed-capacity benchmark: mu_e = C^h => P = H z (n = 1) + state["P_vickrey_hr"] = loading_period_hr * state["demand_capacity_ratio"] + # Fixed queued-state benchmark speed: one train-block queued speed + state["v_q_fixed_mph"] = float( + pd.to_numeric(train["mean_speed_mph"], errors="coerce").median() + ) + state["train_vc_mph"] = vc + return dict(state=state, fit=fit, train=train, validation=validation, vc=vc) + + +# ------------------------------------------------------- emission ablation --- +def ablation_emissions( + state: pd.DataFrame, + moves: MovesRates, +) -> pd.DataFrame: + """Attach B0-B3 per-lane episode totals for every pollutant.""" + out = state.copy() + v_ref = out["v_ref_mph"].to_numpy(float) + tc = out["reference_time_hr"].to_numpy(float) + wbar = out["w_bar_model_hr"].to_numpy(float) + length = out["length_mi"].to_numpy(float) + demand = out["demand_model_veh_per_lane"].to_numpy(float) + v_e = out["v_q_model_mph"].to_numpy(float) + v_fixed = out["v_q_fixed_mph"].to_numpy(float) + with np.errstate(divide="ignore", invalid="ignore"): + v_avg = np.where(tc + wbar > 0, length / (tc + wbar), np.nan) + out["v_avg_model_mph"] = v_avg + + for pollutant in POLLUTANTS: + rate = lambda speed, p=pollutant: exact_rate_for_speed(moves, speed, p) + r_ref = rate(v_ref) + gamma_fixed = gamma_from_rate(v_fixed, v_ref, rate) + gamma_fd = gamma_from_rate(v_e, v_ref, rate) + e_b0 = rate(np.clip(v_avg, 1.0, None)) * (tc + wbar) + e_b1 = r_ref * (tc + wbar) + e_b2 = r_ref * tc + gamma_fixed * wbar + e_b3 = r_ref * tc + gamma_fd * wbar + out[f"B0_mean_speed_{pollutant}_g_per_lane"] = demand * e_b0 + out[f"B1_delay_only_{pollutant}_g_per_lane"] = demand * e_b1 + out[f"B2_fixed_vq_{pollutant}_g_per_lane"] = demand * e_b2 + out[f"B3_fd_state_{pollutant}_g_per_lane"] = demand * e_b3 + return out + + +# ---------------------------------------------------------------- metrics ---- +def _metrics(observed: np.ndarray, predicted: np.ndarray) -> dict: + mask = np.isfinite(observed) & np.isfinite(predicted) + if mask.sum() < 3: + return dict(n=int(mask.sum()), NMAE_pct=np.nan, MAPE_pct=np.nan, + bias_pct=np.nan, R2=np.nan) + o, p = observed[mask], predicted[mask] + mae = float(np.mean(np.abs(p - o))) + nmae = 100.0 * mae / float(np.mean(np.abs(o))) + mape = 100.0 * float(np.mean(np.abs(p - o) / np.maximum(np.abs(o), 1e-9))) + bias = 100.0 * float((p.sum() - o.sum()) / max(o.sum(), 1e-9)) + ss = float(np.sum((o - o.mean()) ** 2)) + r2 = float(1.0 - np.sum((p - o) ** 2) / ss) if ss > 0 else np.nan + return dict(n=int(mask.sum()), NMAE_pct=nmae, MAPE_pct=mape, bias_pct=bias, R2=r2) + + +def ablation_metrics( + validation: pd.DataFrame, + label: str, + reference_model: str = "B1_delay_only", +) -> pd.DataFrame: + """Per-pollutant metrics for B0-B3 plus paired bootstrap CIs on + Delta NMAE relative to the delay-only model.""" + rng = np.random.default_rng(BOOTSTRAP_SEED) + rows = [] + for pollutant in POLLUTANTS: + observed = pd.to_numeric( + validation[f"observed_emission_{pollutant}_g_per_lane"], errors="coerce" + ).to_numpy(float) + model_values = { + model: pd.to_numeric( + validation[f"{model}_{pollutant}_g_per_lane"], errors="coerce" + ).to_numpy(float) + for model in MODEL_LABELS + } + recon_col = f"reconstructed_emission_{pollutant}_g_per_lane" + if recon_col in validation.columns: + model_values["R_reconstructed_speed"] = pd.to_numeric( + validation[recon_col], errors="coerce" + ).to_numpy(float) + mask = np.isfinite(observed) + for model in MODEL_LABELS: + mask &= np.isfinite(model_values[model]) + o = observed[mask] + if len(o) < MIN_VALIDATION_EPISODES: + continue + clean = {model: values[mask] for model, values in model_values.items()} + ref = clean[reference_model] + + def _nmae(obs, pred): + return 100.0 * np.mean(np.abs(pred - obs)) / np.mean(np.abs(obs)) + + boot_idx = rng.integers(0, len(o), size=(N_BOOTSTRAP, len(o))) + for model, values in clean.items(): + finite = np.isfinite(values) + met = _metrics(o[finite], values[finite]) + delta = met["NMAE_pct"] - _metrics(o[finite], ref[finite])["NMAE_pct"] + if model == reference_model: + lo = hi = 0.0 + elif finite.all(): + deltas = np.array([ + _nmae(o[idx], values[idx]) - _nmae(o[idx], ref[idx]) + for idx in boot_idx + ]) + lo, hi = np.percentile(deltas, [2.5, 97.5]) + else: + lo = hi = np.nan + rows.append(dict( + subset=label, pollutant=pollutant, model=model, + model_label=ALL_MODEL_LABELS[model], **met, + delta_NMAE_vs_delay_pct=float(delta), + delta_NMAE_ci_lo=float(lo), delta_NMAE_ci_hi=float(hi), + )) + return pd.DataFrame(rows) + + +# ------------------------------------------------- structural validation ----- +def structural_metrics(state: pd.DataFrame, site_label: str) -> pd.DataFrame: + """Held-out P and queued-speed validation: QVDF vs Vickrey, FD v_e(z) vs + fixed speed (Table 3).""" + validation = state[state["split"].eq("validation")] + rows = [] + p_obs = pd.to_numeric(validation["P_obs_hr"], errors="coerce").to_numpy(float) + rows.append(dict(site=site_label, quantity="P_hr", model="Vickrey_linear", + **_metrics(p_obs, validation["P_vickrey_hr"].to_numpy(float)))) + rows.append(dict(site=site_label, quantity="P_hr", model="QVDF", + **_metrics(p_obs, validation["P_model_hr"].to_numpy(float)))) + v_obs = pd.to_numeric(validation["mean_speed_mph"], errors="coerce").to_numpy(float) + rows.append(dict(site=site_label, quantity="v_q_mph", model="fixed_speed", + **_metrics(v_obs, validation["v_q_fixed_mph"].to_numpy(float)))) + rows.append(dict(site=site_label, quantity="v_q_mph", model="FD_v_e_of_z", + **_metrics(v_obs, validation["v_q_model_mph"].to_numpy(float)))) + mu_obs = pd.to_numeric(validation["mu_obs_vphpl"], errors="coerce").to_numpy(float) + rows.append(dict(site=site_label, quantity="mu_e_vphpl", model="Vickrey_capacity", + **_metrics(mu_obs, validation["capacity_vphpl"].to_numpy(float)))) + rows.append(dict(site=site_label, quantity="mu_e_vphpl", model="QVDF_mu_e_of_z", + **_metrics(mu_obs, validation["mu_model_vphpl"].to_numpy(float)))) + return pd.DataFrame(rows) + + +# --------------------------------------------------------- pooled holdout ---- +def pooled_holdout( + wide: pd.DataFrame, + moves: MovesRates, + corridors=("10-E", "405-S"), + detector: str = "state_transition", +): + """Blocked holdout in every measured-flow sensor-period cell with enough + dates; returns the pooled validation panel with B0-B3 totals and the + per-cell refit registry.""" + sub = wide[ + wide["detector"].eq(detector) + & wide["corridor"].isin(corridors) + & wide["hard_range_ok"] + & ~wide["flow_synthetic"].astype(bool) + ] + cell_rows, validation_frames = [], [] + for (corridor, sensor, period), cell in sub.groupby( + ["corridor", "sensor_uid", "calibration_period"] + ): + if len(cell) < MIN_CELL_EPISODES or cell["date"].nunique() < 6: + continue + train_dates, validation_dates = blocked_split(cell["date"]) + result = refit_and_predict(cell, train_dates, validation_dates) + if result is None: + continue + state = ablation_emissions(result["state"], moves) + validation_frames.append(state[state["split"].eq("validation")]) + fit = result["fit"] + cell_rows.append(dict( + corridor=corridor, sensor_uid=sensor, period=period, + n_train=len(result["train"]), n_validation=len(result["validation"]), + n_train_dates=len(train_dates), n_validation_dates=len(validation_dates), + f_d=fit.f_d, n=fit.n, f_p=fit.f_p, s=fit.s, + duration_r2_train=fit.duration_r2, speed_r2_train=fit.speed_r2, + duration_bound_active=fit.duration_bound_active, + speed_bound_active=fit.speed_bound_active, + )) + cells = pd.DataFrame(cell_rows) + pooled = (pd.concat(validation_frames, ignore_index=True) + if validation_frames else pd.DataFrame()) + return pooled, cells diff --git a/experiments/codes/qvdfe_cbi/src/outliers.py b/experiments/codes/qvdfe_cbi/src/outliers.py index f2d9c1d..710cdaa 100644 --- a/experiments/codes/qvdfe_cbi/src/outliers.py +++ b/experiments/codes/qvdfe_cbi/src/outliers.py @@ -5,9 +5,23 @@ from sklearn.linear_model import HuberRegressor +# HARD rules: physical impossibility or out-of-range measurement. +# One hit excludes the episode outright. NaN-safe: nonfinite inputs are +# caught by the dedicated state_nonfinite rule instead of silently passing +# every ">" comparison as False. PHYSICAL_RULES = { + "state_nonfinite": lambda d: ~( + np.isfinite(pd.to_numeric(d["duration_min"], errors="coerce")) + & np.isfinite(pd.to_numeric(d["demand_capacity_ratio"], errors="coerce")) + & np.isfinite(pd.to_numeric(d["min_speed_mph"], errors="coerce")) + ), + "duration_exceeds_day": lambda d: d["duration_min"] > 1440.0, + "doc_above_physical": lambda d: d["demand_capacity_ratio"] > 8.0, + "speed_out_of_range": lambda d: (d["min_speed_mph"] < 0.0) | (d["min_speed_mph"] > 90.0), + "mu_nonpositive": lambda d: np.isfinite( + pd.to_numeric(d["mu_obs_vphpl"], errors="coerce") + ) & (d["mu_obs_vphpl"] <= 0.0), "doc_high_P_zero": lambda d: (d["demand_capacity_ratio"] > 1.0) & (d["duration_min"] < 15.0), - "doc_low_P_high": lambda d: (d["demand_capacity_ratio"] < 0.5) & (d["duration_min"] > 60.0), "mu_above_capacity": lambda d: d["mu_obs_vphpl"] > 1.05 * d["per_lane_hourly_capacity"], "mu_starved": lambda d: ( (d["demand_capacity_ratio"] > 1.5) @@ -17,6 +31,20 @@ "vt2_too_low": lambda d: d["min_speed_mph"] < 5.0, } +# SOFT rules (MAD z-scores and Huber residuals) are relational evidence only: +# a single 3-3.5 MAD flag over-excluded legitimate heavy-congestion days, so +# two independent soft flags must agree before an episode is dropped. +MIN_SOFT_FLAGS_TO_EXCLUDE = 2 + +SOFT_RULE_COLUMNS = ( + "flag_doc_low_P_high", + "flag_duration_mad_outlier", + "flag_demand_capacity_ratio_mad_outlier", + "flag_huber_resid_doc_P", + "flag_huber_resid_doc_mu", + "flag_huber_resid_P_vt2", +) + def _robust_z(values: pd.Series, reference: pd.Series) -> pd.Series: reference = pd.to_numeric(reference, errors="coerce").dropna() @@ -32,8 +60,17 @@ def _robust_z(values: pd.Series, reference: pd.Series) -> pd.Series: def _huber_flags(x, y, *, log_x=False, log_y=False, threshold=3.0) -> np.ndarray: x = np.asarray(x, dtype=float) y = np.asarray(y, dtype=float) - tx = np.log(np.maximum(x, 1e-6)) if log_x else x - ty = np.log(np.maximum(y, 1e-6)) if log_y else y + # Non-positive values under a log axis are excluded from the fit (hard + # range rules catch them) instead of being clamped to log(1e-6) = -13.8, + # which previously dragged the robust fit toward the clamp point. + if log_x: + tx = np.where(x > 0, np.log(np.where(x > 0, x, 1.0)), np.nan) + else: + tx = x + if log_y: + ty = np.where(y > 0, np.log(np.where(y > 0, y, 1.0)), np.nan) + else: + ty = y valid = np.isfinite(tx) & np.isfinite(ty) flags = np.zeros(len(x), dtype=bool) if valid.sum() < 8: @@ -52,11 +89,17 @@ def apply_outlier_screen(episodes: pd.DataFrame) -> pd.DataFrame: pieces = [] for (_detector, _corridor), group in episodes.groupby(["detector", "corridor"], sort=False): out = group.copy() - reason_columns = [] + hard_columns = [] for name, rule in PHYSICAL_RULES.items(): col = f"flag_{name}" out[col] = rule(out).fillna(False) - reason_columns.append(col) + hard_columns.append(col) + # Speed-only corridors have no measured mu; keep the flag semantics of + # PHYSICAL_RULES (only finite non-positive mu is flagged). + + out["flag_doc_low_P_high"] = ( + (out["demand_capacity_ratio"] < 0.5) & (out["duration_min"] > 60.0) + ).fillna(False) valid = out["is_valid_for_mu"].fillna(False).astype(bool) out["duration_mad_zscore"] = _robust_z(out["duration_min"], out.loc[valid, "duration_min"]) @@ -65,7 +108,6 @@ def apply_outlier_screen(episodes: pd.DataFrame) -> pd.DataFrame: ) out["flag_duration_mad_outlier"] = out["duration_mad_zscore"] > 3.5 out["flag_demand_capacity_ratio_mad_outlier"] = out["demand_capacity_ratio_mad_zscore"] > 3.5 - reason_columns += ["flag_duration_mad_outlier", "flag_demand_capacity_ratio_mad_outlier"] out["flag_huber_resid_doc_P"] = _huber_flags( out["demand_capacity_ratio"], out["duration_min"] / 60.0, log_x=True, log_y=True @@ -76,10 +118,16 @@ def apply_outlier_screen(episodes: pd.DataFrame) -> pd.DataFrame: out["flag_huber_resid_P_vt2"] = _huber_flags( out["duration_min"] / 60.0, out["min_speed_mph"], log_x=True, log_y=True ) - reason_columns += [ - "flag_huber_resid_doc_P", "flag_huber_resid_doc_mu", "flag_huber_resid_P_vt2" - ] - out["measured_outlier_flag"] = out[reason_columns].fillna(False).any(axis=1) + + soft_columns = [c for c in SOFT_RULE_COLUMNS if c in out.columns] + reason_columns = hard_columns + soft_columns + out["n_hard_flags"] = out[hard_columns].fillna(False).sum(axis=1) + out["n_soft_flags"] = out[soft_columns].fillna(False).sum(axis=1) + # Two-tier decision: hard hit -> out; otherwise >= 2 agreeing soft flags. + out["measured_outlier_flag"] = ( + (out["n_hard_flags"] > 0) + | (out["n_soft_flags"] >= MIN_SOFT_FLAGS_TO_EXCLUDE) + ) out["measured_outlier_reasons"] = out.apply( lambda row: ";".join(col.replace("flag_", "") for col in reason_columns if bool(row[col])), axis=1, diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/emission_ablation_metrics.csv b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/emission_ablation_metrics.csv new file mode 100644 index 0000000..e106554 --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/emission_ablation_metrics.csv @@ -0,0 +1,81 @@ +subset,pollutant,model,model_label,n,NMAE_pct,MAPE_pct,bias_pct,R2,delta_NMAE_vs_delay_pct,delta_NMAE_ci_lo,delta_NMAE_ci_hi +I-10 EB site (validation),CO2,B0_mean_speed,B0 whole-link mean speed,5,13.314229534725165,13.24920552378158,-4.471037971155183,-0.45965138349021917,-105.05570714307342,-135.0947635647387,-72.1121764226902 +I-10 EB site (validation),CO2,B1_delay_only,B1 delay-only / reference rate,5,118.36993667779859,114.761336102457,118.36993667779862,-99.07285180383552,0.0,0.0,0.0 +I-10 EB site (validation),CO2,B2_fixed_vq,B2 fixed queued state,5,12.035481514904891,12.110408646002083,-5.294470128877178,-0.131309402161228,-106.3344551628937,-137.82010766570238,-72.96460094131524 +I-10 EB site (validation),CO2,B3_fd_state,B3 FD-consistent effective state,5,23.54449824852483,21.683622078094007,23.544498248524846,-5.060533564874208,-94.82543842927376,-109.81475716586783,-81.00113729531034 +I-10 EB site (validation),CO2,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),5,14.555067216392205,13.31917738306978,5.353190817541331,-1.3293820294616516,-103.81486946140639,-125.27232542143398,-79.43543353992862 +I-10 EB site (validation),NOX,B0_mean_speed,B0 whole-link mean speed,5,24.549202665159708,25.27863672874974,-24.549202665159715,-0.23023562499290895,-262.07644192882873,-286.5528167894824,-228.79346553914422 +I-10 EB site (validation),NOX,B1_delay_only,B1 delay-only / reference rate,5,286.62564459398845,282.88787209871913,286.6256445939885,-177.64886578973167,0.0,0.0,0.0 +I-10 EB site (validation),NOX,B2_fixed_vq,B2 fixed queued state,5,21.29136028755502,21.06032387978797,-21.291360287555015,0.015045878888496178,-265.33428430643346,-286.00190821371604,-234.7241790903891 +I-10 EB site (validation),NOX,B3_fd_state,B3 FD-consistent effective state,5,46.41840589505382,45.776716474619484,46.41840589505384,-3.7700275983846003,-240.20723869893465,-256.58004230855397,-220.6371379332819 +I-10 EB site (validation),NOX,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),5,6.420166572942015,6.371900402526872,4.165225554463591,0.8632588550721827,-280.2054780210464,-300.18993679070917,-254.86016403856243 +I-10 EB site (validation),CO,B0_mean_speed,B0 whole-link mean speed,5,13.022392887173913,12.759944487119382,-2.4355145189840552,-0.32632973028683687,-40.538032341706725,-59.35660992551551,-19.62142895145526 +I-10 EB site (validation),CO,B1_delay_only,B1 delay-only / reference rate,5,53.56042522888064,50.990242809706444,53.560425228880625,-21.03071648925638,0.0,0.0,0.0 +I-10 EB site (validation),CO,B2_fixed_vq,B2 fixed queued state,5,12.597267016967626,11.612010295669654,4.084336413799509,-0.5631560724033646,-40.96315821191301,-54.79586536414374,-25.122290105319575 +I-10 EB site (validation),CO,B3_fd_state,B3 FD-consistent effective state,5,14.171300258253515,12.663357178927615,10.335112567331427,-1.443544959863472,-39.38912497062712,-48.54920886675333,-28.683496162588106 +I-10 EB site (validation),CO,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),5,15.280412860162265,14.160392793615811,4.872248378369462,-1.1694165711616598,-38.280012368718374,-51.23924782977747,-23.015132694028924 +I-10 EB site (validation),HC,B0_mean_speed,B0 whole-link mean speed,5,14.547794979111732,14.045507434616425,-0.6089565822480664,-1.2323507690089084,-48.00281545233628,-68.05120366520066,-23.261307899131964 +I-10 EB site (validation),HC,B1_delay_only,B1 delay-only / reference rate,5,62.55061043144801,59.909420450083616,62.55061043144801,-37.82514855488354,0.0,0.0,0.0 +I-10 EB site (validation),HC,B2_fixed_vq,B2 fixed queued state,5,13.93224503180855,12.969138473795311,4.256178377136568,-1.4650238895471315,-48.61836539963946,-64.98030012526165,-28.125247647369974 +I-10 EB site (validation),HC,B3_fd_state,B3 FD-consistent effective state,5,16.366964512709554,14.71914695738218,13.795432037657612,-3.575923118046912,-46.18364591873845,-55.513524602015494,-34.50979012581517 +I-10 EB site (validation),HC,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),5,16.965983673019274,15.830469912186334,5.239837396145607,-2.5207776908840396,-45.58462675842873,-60.745034775128424,-26.833013030220222 +I-405 SB site (validation),CO2,B0_mean_speed,B0 whole-link mean speed,5,9.893464162670849,10.613385265947176,-2.1783467834519996,0.630504487167411,-87.4517583685697,-107.53353080202157,-70.56994023125861 +I-405 SB site (validation),CO2,B1_delay_only,B1 delay-only / reference rate,5,97.34522253124055,98.76323392903484,97.34522253124057,-28.868435740222463,0.0,0.0,0.0 +I-405 SB site (validation),CO2,B2_fixed_vq,B2 fixed queued state,5,28.446252400611225,27.63511280720842,-28.446252400611222,-1.8333057219206323,-68.89897013062932,-99.51720948043362,-47.52165736820408 +I-405 SB site (validation),CO2,B3_fd_state,B3 FD-consistent effective state,5,21.46516362791703,22.517097210883225,21.465163627917015,-0.8012435737223709,-75.88005890332352,-84.70760129609147,-68.93508448943969 +I-405 SB site (validation),CO2,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),5,10.641847101895186,11.807496761983957,2.817789883845879,0.44791012362010096,-86.70337542934537,-100.97554227947413,-74.07929131279415 +I-405 SB site (validation),NOX,B0_mean_speed,B0 whole-link mean speed,5,16.627953819715046,15.714587748742929,-16.627953819715056,0.15616761616611785,-170.10598125627615,-200.69218675686346,-140.90148683707613 +I-405 SB site (validation),NOX,B1_delay_only,B1 delay-only / reference rate,5,186.73393507599118,189.8751923641764,186.7339350759912,-79.7633833656598,0.0,0.0,0.0 +I-405 SB site (validation),NOX,B2_fixed_vq,B2 fixed queued state,5,76.85511103847777,75.66717435753037,-76.85511103847779,-13.341831249402535,-109.87882403751341,-138.41316085999472,-85.6152808647246 +I-405 SB site (validation),NOX,B3_fd_state,B3 FD-consistent effective state,5,28.993309205463113,30.96563318752971,28.993309205463124,-1.066277288638159,-157.74062587052808,-170.23856100245462,-145.3224796603847 +I-405 SB site (validation),NOX,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),5,16.237964796769813,16.408582262521296,2.142428210223426,0.16693645724131623,-170.49597027922138,-193.67596653903675,-141.408375585761 +I-405 SB site (validation),CO,B0_mean_speed,B0 whole-link mean speed,5,10.072842117497299,11.991549673325915,1.025287109579136,0.42150139059342107,-31.602059273363697,-44.81706504496291,-18.2365759183933 +I-405 SB site (validation),CO,B1_delay_only,B1 delay-only / reference rate,5,41.674901390860995,43.639492522978365,41.67490139086098,-5.131380343335518,0.0,0.0,0.0 +I-405 SB site (validation),CO,B2_fixed_vq,B2 fixed queued state,5,25.204030096189577,26.97409484958634,25.204030096189562,-1.6383817912320553,-16.47087129467142,-18.97934814137419,-14.634049314461972 +I-405 SB site (validation),CO,B3_fd_state,B3 FD-consistent effective state,5,10.921480436085865,12.817121252736904,6.363025672640056,0.29212834227577855,-30.75342095477513,-39.23240540651228,-21.506665360439285 +I-405 SB site (validation),CO,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),5,17.738881084376082,19.98831543551483,-1.9832336665285661,-0.3528143878074763,-23.936020306484913,-35.4689185614168,-11.980561919227323 +I-405 SB site (validation),HC,B0_mean_speed,B0 whole-link mean speed,5,11.12789092862743,13.735993776896265,4.296972029176889,0.3267492789925729,-42.10668426997036,-56.3929537749115,-28.962402232829298 +I-405 SB site (validation),HC,B1_delay_only,B1 delay-only / reference rate,5,53.23457519859779,56.31635119911289,53.2345751985978,-7.385254568050598,0.0,0.0,0.0 +I-405 SB site (validation),HC,B2_fixed_vq,B2 fixed queued state,5,10.951955215496442,13.414527824165948,3.3913883121279764,0.3666871033258202,-42.28261998310135,-56.70019115364167,-29.445528925693388 +I-405 SB site (validation),HC,B3_fd_state,B3 FD-consistent effective state,5,13.949024949523713,16.442430392679142,12.537992326357324,-0.05593062179339947,-39.28555024907408,-48.063630095753105,-32.528452746779145 +I-405 SB site (validation),HC,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),5,17.86135078097382,20.944943498782358,0.11537341849149037,-0.3631046893928749,-35.37322441762397,-48.405900102655195,-22.818593065894845 +Pooled strict (validation),CO2,B0_mean_speed,B0 whole-link mean speed,19,10.283587428710602,9.736344990977349,-4.707229725652097,0.9322520976803129,-90.9083008944347,-107.58256569603253,-75.76725367109493 +Pooled strict (validation),CO2,B1_delay_only,B1 delay-only / reference rate,19,101.1918883231453,98.97923110321169,101.19188832314533,-3.3363956312708654,0.0,0.0,0.0 +Pooled strict (validation),CO2,B2_fixed_vq,B2 fixed queued state,19,16.25658027413536,14.045881837166979,-13.771847457614935,0.8532957469320397,-84.93530804900995,-104.5927340095573,-68.11684697122487 +Pooled strict (validation),CO2,B3_fd_state,B3 FD-consistent effective state,19,19.023666015201147,21.22045468548773,18.70715402464838,0.7880174278487597,-82.16822230794416,-91.03077192947623,-75.08863650180605 +Pooled strict (validation),CO2,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),19,10.639611526760211,9.078051367690652,0.2652705241573144,0.9106047859135701,-90.5522767963851,-104.27990079502553,-77.2231310346511 +Pooled strict (validation),NOX,B0_mean_speed,B0 whole-link mean speed,19,14.967600502479167,14.894353897433623,-12.23521887560238,0.8588802664473614,-229.80222581116428,-252.0856786247695,-204.79725219055524 +Pooled strict (validation),NOX,B1_delay_only,B1 delay-only / reference rate,19,244.76982631364345,232.65768193665176,244.76982631364353,-28.61440080415225,0.0,0.0,0.0 +Pooled strict (validation),NOX,B2_fixed_vq,B2 fixed queued state,19,34.59160190765594,31.42308041984931,-34.10381862001341,0.20133110432396883,-210.17822440598752,-242.0644351252052,-172.8874254303887 +Pooled strict (validation),NOX,B3_fd_state,B3 FD-consistent effective state,19,42.535074863371214,45.505121323306916,42.53507486337119,0.10528556492538199,-202.23475145027223,-220.12890624352,-183.21633641905788 +Pooled strict (validation),NOX,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),19,11.510703085954027,10.502284792156194,6.473392339952268,0.8920076141015046,-233.25912322768943,-258.0588628814181,-206.66928240337526 +Pooled strict (validation),CO,B0_mean_speed,B0 whole-link mean speed,19,10.185793334891988,9.894583738882424,-2.6183354522358133,0.9313329626643373,-32.25881795803975,-43.6178038002942,-21.057550263205435 +Pooled strict (validation),CO,B1_delay_only,B1 delay-only / reference rate,19,42.44461129293174,41.35751677336085,42.44461129293173,0.1573337658209697,0.0,0.0,0.0 +Pooled strict (validation),CO,B2_fixed_vq,B2 fixed queued state,19,13.993436354409546,13.18290776009317,4.2239195067321464,0.8748611249729675,-28.451174938522193,-39.208290465150384,-18.008230143586147 +Pooled strict (validation),CO,B3_fd_state,B3 FD-consistent effective state,19,10.665715937386427,9.573288391756872,4.588503157966605,0.9074275838363616,-31.778895355545313,-39.36090801930288,-23.296783705600244 +Pooled strict (validation),CO,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),19,14.126146922519638,12.092023164398555,-2.13333303917243,0.8627159934468409,-28.3184643704121,-38.77334475736931,-17.0750547219068 +Pooled strict (validation),HC,B0_mean_speed,B0 whole-link mean speed,19,11.1254954539369,10.572021982371245,-1.2355991225975407,0.9184721428793652,-39.789507553661984,-52.46763797029708,-28.189767758449772 +Pooled strict (validation),HC,B1_delay_only,B1 delay-only / reference rate,19,50.915003007598884,50.56560066267167,50.915003007598884,-0.14675845596268933,0.0,0.0,0.0 +Pooled strict (validation),HC,B2_fixed_vq,B2 fixed queued state,19,11.41446960975617,9.874566629254762,-0.9687789443530348,0.903219007232682,-39.500533397842716,-51.623516421619975,-27.38804247734006 +Pooled strict (validation),HC,B3_fd_state,B3 FD-consistent effective state,19,12.615873550069683,12.315011355556688,8.178826578905978,0.8760576684179264,-38.299129457529205,-46.284244107093144,-29.485745912761 +Pooled strict (validation),HC,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),19,14.96463739660783,12.997208989640576,-2.0258425845399763,0.8452563616365646,-35.95036561099106,-48.080292891520784,-23.390370598288733 +Pooled all-domain (validation),CO2,B0_mean_speed,B0 whole-link mean speed,41,9.878216434272723,9.591869179783616,2.140674443880551,0.9551381154242685,-85.82663286077815,-101.36430322242063,-66.95500360460461 +Pooled all-domain (validation),CO2,B1_delay_only,B1 delay-only / reference rate,41,95.70484929505088,82.05526684887893,95.7048492950509,-2.892895604979647,0.0,0.0,0.0 +Pooled all-domain (validation),CO2,B2_fixed_vq,B2 fixed queued state,41,14.70890102023874,13.00765591638707,-8.8140320102648,0.906228136065343,-80.99594827481214,-98.1788761495499,-61.43176546412256 +Pooled all-domain (validation),CO2,B3_fd_state,B3 FD-consistent effective state,41,14.443698666678289,15.389673630884126,13.535826503916997,0.9012102947518744,-81.26115062837259,-94.63239708976901,-64.53343767209425 +Pooled all-domain (validation),CO2,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),41,9.973090576385962,9.18986257107336,5.132583981556335,0.9519879349584417,-85.73175871866492,-100.95917231878154,-67.35613033540074 +Pooled all-domain (validation),NOX,B0_mean_speed,B0 whole-link mean speed,41,13.516692370283746,13.399553099966715,-10.554436363825182,0.9262029759153259,-207.2002416127666,-252.44118027561578,-157.92977616205604 +Pooled all-domain (validation),NOX,B1_delay_only,B1 delay-only / reference rate,41,220.71693398305035,191.98840939824154,220.71693398305032,-21.742606319288146,0.0,0.0,0.0 +Pooled all-domain (validation),NOX,B2_fixed_vq,B2 fixed queued state,41,42.58935071477595,36.01080707229447,-37.8406942701926,0.09523851703761976,-178.1275832682744,-217.43933787216451,-135.7634577604246 +Pooled all-domain (validation),NOX,B3_fd_state,B3 FD-consistent effective state,41,27.557991763075666,30.52924325156436,16.46276599182829,0.7325239937873274,-193.15894221997468,-235.17847604435622,-146.7693853009695 +Pooled all-domain (validation),NOX,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),41,10.412002942257493,10.151141835183292,8.037809767436507,0.9440694053873534,-210.30493104079287,-253.2769234017156,-163.34117174355453 +Pooled all-domain (validation),CO,B0_mean_speed,B0 whole-link mean speed,41,10.348649038385053,10.005214254995897,3.7971693474431465,0.9492036828802437,-51.908106202748314,-65.29102619580338,-38.67529247932477 +Pooled all-domain (validation),CO,B1_delay_only,B1 delay-only / reference rate,41,62.25675524113337,52.995647976403546,62.256755241133376,-0.7175904157883994,0.0,0.0,0.0 +Pooled all-domain (validation),CO,B2_fixed_vq,B2 fixed queued state,41,12.07283996789762,11.99116974783931,0.887265465918847,0.9479032670308922,-50.18391527323575,-65.08556555931378,-34.38211631134945 +Pooled all-domain (validation),CO,B3_fd_state,B3 FD-consistent effective state,41,11.394706977622198,10.229370005814802,8.054443301458711,0.9333375740099036,-50.86204826351117,-64.28144132996935,-38.03579321553607 +Pooled all-domain (validation),CO,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),41,11.029133750704966,10.760927085535862,2.8368880839483754,0.9484242956067865,-51.227621490428405,-64.66155087054024,-37.34712724962699 +Pooled all-domain (validation),HC,B0_mean_speed,B0 whole-link mean speed,41,11.676290146808554,10.988474598306087,5.65223130108103,0.9365887624642384,-48.68909162065572,-57.336336210010046,-37.90601173500042 +Pooled all-domain (validation),HC,B1_delay_only,B1 delay-only / reference rate,41,60.36538176746427,51.55052362684673,60.365381767464264,-0.4858556594846464,0.0,0.0,0.0 +Pooled all-domain (validation),HC,B2_fixed_vq,B2 fixed queued state,41,11.352334888740865,10.61156264489666,0.9846502990956201,0.9521059431181945,-49.01304687872341,-60.37603781977808,-36.24571220231505 +Pooled all-domain (validation),HC,B3_fd_state,B3 FD-consistent effective state,41,12.754190368436348,11.881841402009478,10.663521209367174,0.9173563380258283,-47.61119139902792,-55.478334382832024,-37.62715810737257 +Pooled all-domain (validation),HC,R_reconstructed_speed,Reconstructed-speed MOVES (diagnostic),41,11.62054006333518,11.309478019238531,3.5541791483780365,0.9432512841429734,-48.74484170412909,-58.21968867949432,-36.925985427650616 diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/evidence_ladder.csv b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/evidence_ladder.csv new file mode 100644 index 0000000..fa7c0e8 --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/evidence_ladder.csv @@ -0,0 +1,7 @@ +stage,count +317 directional series,317 +episode rows detected,4270 +clean valid episodes,2186 +focus-direction evaluated,1006 +physically admissible,364 +strict measured-physical,363 diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/pooled_cell_registry.csv b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/pooled_cell_registry.csv new file mode 100644 index 0000000..42faf9e --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/pooled_cell_registry.csv @@ -0,0 +1,10 @@ +corridor,sensor_uid,period,n_train,n_validation,n_train_dates,n_validation_dates,f_d,n,f_p,s,duration_r2_train,speed_r2_train,duration_bound_active,speed_bound_active +10-E,pems::716087,PM,10,4,10,4,0.9554894187625612,1.059444185556943,0.07774215194892604,1.3253775589590375,0.9923765606513087,0.4109563161820524,False,False +10-E,pems::718412,PM,13,5,13,5,1.3810217695967646,1.0000000000747662,2.0074153674263626,0.1475272258697773,0.9360008328717311,0.06180096248768219,True,False +10-E,pems::737344,PM,10,4,10,4,1.3240750852471703,1.0000008141857777,1.7311785580513823,0.31977899505162544,0.9960363662959705,0.5017240939234986,True,False +10-E,pems::763346,AM,12,5,12,5,1.1528371765648882,1.040643271805973,1.159949101506658,0.7864941786486165,0.9215779412537357,0.25274195219672435,False,False +10-E,pems::764125,PM,10,4,10,4,1.1359537735670628,1.057300645250962,1.0676840514950758,0.05000020919406089,0.9045701029495337,-0.006644613310774483,False,True +405-S,pems::717816,AM,12,5,12,5,1.433341263427989,1.0000000000000002,2.0089343241622997,0.3632579572784709,0.9194611950768875,0.18898639526080419,True,False +405-S,pems::767053,AM,13,5,13,5,1.3842547433185177,1.0000000000220721,1.4963509658964391,0.2605457542226264,0.10086339178087123,-0.1928180233282848,True,False +405-S,pems::771925,PM,10,4,10,4,1.016267316377876,1.088347548515718,0.3180201226114495,0.8743962117915642,0.9861212414796662,0.43550764759699845,False,False +405-S,pems::772025,PM,14,5,14,5,1.2702272865703685,1.000000000430517,1.692355452839153,0.05000000000000605,0.926649311823523,-0.05774928274040625,True,True diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/site_selection.csv b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/site_selection.csv new file mode 100644 index 0000000..9229224 --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/site_selection.csv @@ -0,0 +1,3 @@ +corridor,sensor_uid,period,n_clean_episodes,n_dates,measured_volume,fd_stable,bounds_free,strict_coverage,cbi_score,passes_rule,selected,n_candidates,n_eligible +10-E,pems::718412,PM,18,18,True,True,False,1.0,3.894307853909528,True,True,23,3 +405-S,pems::767053,AM,18,18,True,True,False,1.0,4.358572415018306,True,True,26,3 diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/stage8_manifest.json b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/stage8_manifest.json new file mode 100644 index 0000000..90bf361 --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/stage8_manifest.json @@ -0,0 +1,74 @@ +{ + "detector": "state_transition", + "sites": [ + { + "corridor": "10-E", + "sensor_uid": "pems::718412", + "period": "PM", + "n_clean_episodes": 18, + "n_dates": 18, + "measured_volume": true, + "fd_stable": true, + "bounds_free": false, + "strict_coverage": 1.0, + "cbi_score": 3.894307853909528, + "passes_rule": true, + "selected": true, + "n_candidates": 23, + "n_eligible": 3 + }, + { + "corridor": "405-S", + "sensor_uid": "pems::767053", + "period": "AM", + "n_clean_episodes": 18, + "n_dates": 18, + "measured_volume": true, + "fd_stable": true, + "bounds_free": false, + "strict_coverage": 1.0, + "cbi_score": 4.358572415018306, + "passes_rule": true, + "selected": true, + "n_candidates": 26, + "n_eligible": 3 + } + ], + "n_pooled_cells": 9, + "n_pooled_validation_episodes": 41, + "n_metric_rows": 80, + "elapsed_seconds": 9.834442000021227, + "n_bootstrap": 2000, + "train_fraction": 0.7, + "outputs": [ + "emission_ablation_metrics.csv", + "evidence_ladder.csv", + "figures\\fig_A_evidence_ladder.pdf", + "figures\\fig_A_evidence_ladder.png", + "figures\\fig_B_representative_episodes.pdf", + "figures\\fig_B_representative_episodes.png", + "figures\\fig_C_structural_validation.pdf", + "figures\\fig_C_structural_validation.png", + "figures\\fig_D_emission_ablation_forest.pdf", + "figures\\fig_D_emission_ablation_forest.png", + "figures\\fig_E_phase_admissibility.pdf", + "figures\\fig_E_phase_admissibility.png", + "pooled_cell_registry.csv", + "pooled_validation_panel.csv", + "response_grid_I-10_EB_site.csv", + "response_grid_I-405_SB_site.csv", + "site_selection.csv", + "site_state_10E.csv", + "site_state_405S.csv", + "stage8_manifest.json", + "structural_validation_metrics.csv", + "tables\\table1_data_evidence.csv", + "tables\\table1_data_evidence.tex", + "tables\\table2_site_parameters.csv", + "tables\\table2_site_parameters.tex", + "tables\\table3_structural_validation.csv", + "tables\\table3_structural_validation.tex", + "tables\\table4_emission_ablation.csv", + "tables\\table4_emission_ablation.tex" + ] +} \ No newline at end of file diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/structural_validation_metrics.csv b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/structural_validation_metrics.csv new file mode 100644 index 0000000..1232098 --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/structural_validation_metrics.csv @@ -0,0 +1,13 @@ +site,quantity,model,n,NMAE_pct,MAPE_pct,bias_pct,R2 +I-10 EB site,P_hr,Vickrey_linear,5,20.565577876744193,21.47976071089424,-20.565577876744193,-0.34392016432564176 +I-10 EB site,P_hr,QVDF,5,10.525502214069666,9.334720687176677,9.700666220950394,0.3580539912962438 +I-10 EB site,v_q_mph,fixed_speed,5,14.33405491361831,13.684321357922707,-2.3421351136461386,-0.019519876184479035 +I-10 EB site,v_q_mph,FD_v_e_of_z,5,51.228002795841405,49.975347399233385,-51.22800279584138,-9.338304205082332 +I-10 EB site,mu_e_vphpl,Vickrey_capacity,5,28.879766511127382,30.752543085096605,28.879766511127386,-5.324029425224964 +I-10 EB site,mu_e_vphpl,QVDF_mu_e_of_z,5,10.031795574311726,9.036257435412313,-6.677961685136842,-0.2846694995627663 +I-405 SB site,P_hr,Vickrey_linear,5,34.49704826930466,33.54743117360231,-34.49704826930466,-4.496484119479538 +I-405 SB site,P_hr,QVDF,5,15.660196078490602,16.232650000183554,-9.327228362906654,-0.14530390116729563 +I-405 SB site,v_q_mph,fixed_speed,5,35.42180522693722,38.021820135818274,21.04359235195562,-0.5280062698744641 +I-405 SB site,v_q_mph,FD_v_e_of_z,5,63.76504058332475,61.42423828179264,-63.76504058332476,-4.848022201938159 +I-405 SB site,mu_e_vphpl,Vickrey_capacity,5,63.386622997774985,69.82869654708145,63.386622997774985,-8.704478360814669 +I-405 SB site,mu_e_vphpl,QVDF_mu_e_of_z,5,27.17590493379718,29.17591114525566,18.032192977455097,-0.7044409811909658 diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table1_data_evidence.csv b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table1_data_evidence.csv new file mode 100644 index 0000000..bb3a2b5 --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table1_data_evidence.csv @@ -0,0 +1,4 @@ +Corridor,Measured speed,Measured flow,Evaluated episodes,Physical,Strict,Intended role +10-E,Yes,Yes,468,151,151,Structural validation + ablation +405-S,Yes,Yes,393,212,212,Emission/assignment use case +I-17-NB,Yes,No,145,1,0,Diagnostic stress test (synthetic flow) diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table1_data_evidence.tex b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table1_data_evidence.tex new file mode 100644 index 0000000..e4820ec --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table1_data_evidence.tex @@ -0,0 +1,15 @@ +% Auto-generated by run_holdout_ablation.py +\begin{table}[t] +\centering\small +\caption{Data and evidence levels by focus corridor.} +\label{tab:v12_data_evidence} +\begin{tabular}{lllrrrl} +\toprule +Corridor & Measured speed & Measured flow & Evaluated episodes & Physical & Strict & Intended role \\ +\midrule +10-E & Yes & Yes & 468 & 151 & 151 & Structural validation + ablation \\ +405-S & Yes & Yes & 393 & 212 & 212 & Emission/assignment use case \\ +I-17-NB & Yes & No & 145 & 1 & 0 & Diagnostic stress test (synthetic flow) \\ +\bottomrule +\end{tabular} +\end{table} diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table2_site_parameters.csv b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table2_site_parameters.csv new file mode 100644 index 0000000..2398bda --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table2_site_parameters.csv @@ -0,0 +1,3 @@ +Site,Sensor,Period,C^h (vphpl),v_ref (mph),k_c (vpmpl),k_j (vpmpl),omega (mph),f_d,n,f_p,s,alpha,beta,Train episodes,Held-out episodes,z range,Duration bound active,Speed bound active,Train duration R2,Train speed R2 +I-10 EB site,pems::718412,PM,1386.6431838465217,53.04677933061858,26.140007015395785,220.0,7.152807355959435,1.3810217695967646,1.0000000000747662,2.0074153674263626,0.1475272258697773,1.1228438558306617,0.14752722588080733,13,5,"[3.50, 7.85]",True,False,0.9360008328717311,0.06180096248768219 +I-405 SB site,pems::767053,AM,1264.6124620027783,59.765048971742495,21.15973271603441,220.0,6.3599414709937685,1.3842547433185177,1.0000000000220721,1.4963509658964391,0.2605457542226264,0.8686112117187771,0.26054575422837717,13,5,"[2.75, 6.85]",True,False,0.10086339178087123,-0.1928180233282848 diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table2_site_parameters.tex b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table2_site_parameters.tex new file mode 100644 index 0000000..d91a57a --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table2_site_parameters.tex @@ -0,0 +1,14 @@ +% Auto-generated by run_holdout_ablation.py +\begin{table}[t] +\centering\small +\caption{Selected bottleneck sites and calibration-block parameters.} +\label{tab:v12_site_parameters} +\begin{tabular}{lllrrrrrrrrrrrrrlrrrr} +\toprule +Site & Sensor & Period & C\textasciicircum h (vphpl) & v\_ref (mph) & k\_c (vpmpl) & k\_j (vpmpl) & omega (mph) & f\_d & n & f\_p & s & alpha & beta & Train episodes & Held-out episodes & z range & Duration bound active & Speed bound active & Train duration R2 & Train speed R2 \\ +\midrule +I-10 EB site & pems::718412 & PM & 1386.643 & 53.047 & 26.140 & 220.000 & 7.153 & 1.381 & 1.000 & 2.007 & 0.148 & 1.123 & 0.148 & 13 & 5 & [3.50, 7.85] & True & False & 0.936 & 0.062 \\ +I-405 SB site & pems::767053 & AM & 1264.612 & 59.765 & 21.160 & 220.000 & 6.360 & 1.384 & 1.000 & 1.496 & 0.261 & 0.869 & 0.261 & 13 & 5 & [2.75, 6.85] & True & False & 0.101 & -0.193 \\ +\bottomrule +\end{tabular} +\end{table} diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table3_structural_validation.csv b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table3_structural_validation.csv new file mode 100644 index 0000000..2e28c1e --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table3_structural_validation.csv @@ -0,0 +1,13 @@ +site,quantity,model,n,NMAE_pct,MAPE_pct,bias_pct,R2 +I-10 EB site,P_hr,Vickrey_linear,5,20.566,21.48,-20.566,-0.344 +I-10 EB site,P_hr,QVDF,5,10.526,9.335,9.701,0.358 +I-10 EB site,v_q_mph,fixed_speed,5,14.334,13.684,-2.342,-0.02 +I-10 EB site,v_q_mph,FD_v_e_of_z,5,51.228,49.975,-51.228,-9.338 +I-10 EB site,mu_e_vphpl,Vickrey_capacity,5,28.88,30.753,28.88,-5.324 +I-10 EB site,mu_e_vphpl,QVDF_mu_e_of_z,5,10.032,9.036,-6.678,-0.285 +I-405 SB site,P_hr,Vickrey_linear,5,34.497,33.547,-34.497,-4.496 +I-405 SB site,P_hr,QVDF,5,15.66,16.233,-9.327,-0.145 +I-405 SB site,v_q_mph,fixed_speed,5,35.422,38.022,21.044,-0.528 +I-405 SB site,v_q_mph,FD_v_e_of_z,5,63.765,61.424,-63.765,-4.848 +I-405 SB site,mu_e_vphpl,Vickrey_capacity,5,63.387,69.829,63.387,-8.704 +I-405 SB site,mu_e_vphpl,QVDF_mu_e_of_z,5,27.176,29.176,18.032,-0.704 diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table3_structural_validation.tex b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table3_structural_validation.tex new file mode 100644 index 0000000..5cbe6cf --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table3_structural_validation.tex @@ -0,0 +1,24 @@ +% Auto-generated by run_holdout_ablation.py +\begin{table}[t] +\centering\small +\caption{Held-out structural validation on the final 30\% of dates.} +\label{tab:v12_structural_validation} +\begin{tabular}{lllrrrrr} +\toprule +site & quantity & model & n & NMAE\_pct & MAPE\_pct & bias\_pct & R2 \\ +\midrule +I-10 EB site & P\_hr & Vickrey\_linear & 5 & 20.566 & 21.480 & -20.566 & -0.344 \\ +I-10 EB site & P\_hr & QVDF & 5 & 10.526 & 9.335 & 9.701 & 0.358 \\ +I-10 EB site & v\_q\_mph & fixed\_speed & 5 & 14.334 & 13.684 & -2.342 & -0.020 \\ +I-10 EB site & v\_q\_mph & FD\_v\_e\_of\_z & 5 & 51.228 & 49.975 & -51.228 & -9.338 \\ +I-10 EB site & mu\_e\_vphpl & Vickrey\_capacity & 5 & 28.880 & 30.753 & 28.880 & -5.324 \\ +I-10 EB site & mu\_e\_vphpl & QVDF\_mu\_e\_of\_z & 5 & 10.032 & 9.036 & -6.678 & -0.285 \\ +I-405 SB site & P\_hr & Vickrey\_linear & 5 & 34.497 & 33.547 & -34.497 & -4.496 \\ +I-405 SB site & P\_hr & QVDF & 5 & 15.660 & 16.233 & -9.327 & -0.145 \\ +I-405 SB site & v\_q\_mph & fixed\_speed & 5 & 35.422 & 38.022 & 21.044 & -0.528 \\ +I-405 SB site & v\_q\_mph & FD\_v\_e\_of\_z & 5 & 63.765 & 61.424 & -63.765 & -4.848 \\ +I-405 SB site & mu\_e\_vphpl & Vickrey\_capacity & 5 & 63.387 & 69.829 & 63.387 & -8.704 \\ +I-405 SB site & mu\_e\_vphpl & QVDF\_mu\_e\_of\_z & 5 & 27.176 & 29.176 & 18.032 & -0.704 \\ +\bottomrule +\end{tabular} +\end{table} diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table4_emission_ablation.csv b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table4_emission_ablation.csv new file mode 100644 index 0000000..7917b60 --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table4_emission_ablation.csv @@ -0,0 +1,81 @@ +subset,pollutant,model_label,n,NMAE_pct,MAPE_pct,bias_pct,R2,delta_NMAE_vs_delay_pct,delta_NMAE_ci_lo,delta_NMAE_ci_hi +I-10 EB site (validation),CO2,B0 whole-link mean speed,5,13.31,13.25,-4.47,-0.46,-105.06,-135.09,-72.11 +I-10 EB site (validation),CO2,B1 delay-only / reference rate,5,118.37,114.76,118.37,-99.07,0.0,0.0,0.0 +I-10 EB site (validation),CO2,B2 fixed queued state,5,12.04,12.11,-5.29,-0.13,-106.33,-137.82,-72.96 +I-10 EB site (validation),CO2,B3 FD-consistent effective state,5,23.54,21.68,23.54,-5.06,-94.83,-109.81,-81.0 +I-10 EB site (validation),CO2,Reconstructed-speed MOVES (diagnostic),5,14.56,13.32,5.35,-1.33,-103.81,-125.27,-79.44 +I-10 EB site (validation),NOX,B0 whole-link mean speed,5,24.55,25.28,-24.55,-0.23,-262.08,-286.55,-228.79 +I-10 EB site (validation),NOX,B1 delay-only / reference rate,5,286.63,282.89,286.63,-177.65,0.0,0.0,0.0 +I-10 EB site (validation),NOX,B2 fixed queued state,5,21.29,21.06,-21.29,0.02,-265.33,-286.0,-234.72 +I-10 EB site (validation),NOX,B3 FD-consistent effective state,5,46.42,45.78,46.42,-3.77,-240.21,-256.58,-220.64 +I-10 EB site (validation),NOX,Reconstructed-speed MOVES (diagnostic),5,6.42,6.37,4.17,0.86,-280.21,-300.19,-254.86 +I-10 EB site (validation),CO,B0 whole-link mean speed,5,13.02,12.76,-2.44,-0.33,-40.54,-59.36,-19.62 +I-10 EB site (validation),CO,B1 delay-only / reference rate,5,53.56,50.99,53.56,-21.03,0.0,0.0,0.0 +I-10 EB site (validation),CO,B2 fixed queued state,5,12.6,11.61,4.08,-0.56,-40.96,-54.8,-25.12 +I-10 EB site (validation),CO,B3 FD-consistent effective state,5,14.17,12.66,10.34,-1.44,-39.39,-48.55,-28.68 +I-10 EB site (validation),CO,Reconstructed-speed MOVES (diagnostic),5,15.28,14.16,4.87,-1.17,-38.28,-51.24,-23.02 +I-10 EB site (validation),HC,B0 whole-link mean speed,5,14.55,14.05,-0.61,-1.23,-48.0,-68.05,-23.26 +I-10 EB site (validation),HC,B1 delay-only / reference rate,5,62.55,59.91,62.55,-37.83,0.0,0.0,0.0 +I-10 EB site (validation),HC,B2 fixed queued state,5,13.93,12.97,4.26,-1.47,-48.62,-64.98,-28.13 +I-10 EB site (validation),HC,B3 FD-consistent effective state,5,16.37,14.72,13.8,-3.58,-46.18,-55.51,-34.51 +I-10 EB site (validation),HC,Reconstructed-speed MOVES (diagnostic),5,16.97,15.83,5.24,-2.52,-45.58,-60.75,-26.83 +I-405 SB site (validation),CO2,B0 whole-link mean speed,5,9.89,10.61,-2.18,0.63,-87.45,-107.53,-70.57 +I-405 SB site (validation),CO2,B1 delay-only / reference rate,5,97.35,98.76,97.35,-28.87,0.0,0.0,0.0 +I-405 SB site (validation),CO2,B2 fixed queued state,5,28.45,27.64,-28.45,-1.83,-68.9,-99.52,-47.52 +I-405 SB site (validation),CO2,B3 FD-consistent effective state,5,21.47,22.52,21.47,-0.8,-75.88,-84.71,-68.94 +I-405 SB site (validation),CO2,Reconstructed-speed MOVES (diagnostic),5,10.64,11.81,2.82,0.45,-86.7,-100.98,-74.08 +I-405 SB site (validation),NOX,B0 whole-link mean speed,5,16.63,15.71,-16.63,0.16,-170.11,-200.69,-140.9 +I-405 SB site (validation),NOX,B1 delay-only / reference rate,5,186.73,189.88,186.73,-79.76,0.0,0.0,0.0 +I-405 SB site (validation),NOX,B2 fixed queued state,5,76.86,75.67,-76.86,-13.34,-109.88,-138.41,-85.62 +I-405 SB site (validation),NOX,B3 FD-consistent effective state,5,28.99,30.97,28.99,-1.07,-157.74,-170.24,-145.32 +I-405 SB site (validation),NOX,Reconstructed-speed MOVES (diagnostic),5,16.24,16.41,2.14,0.17,-170.5,-193.68,-141.41 +I-405 SB site (validation),CO,B0 whole-link mean speed,5,10.07,11.99,1.03,0.42,-31.6,-44.82,-18.24 +I-405 SB site (validation),CO,B1 delay-only / reference rate,5,41.67,43.64,41.67,-5.13,0.0,0.0,0.0 +I-405 SB site (validation),CO,B2 fixed queued state,5,25.2,26.97,25.2,-1.64,-16.47,-18.98,-14.63 +I-405 SB site (validation),CO,B3 FD-consistent effective state,5,10.92,12.82,6.36,0.29,-30.75,-39.23,-21.51 +I-405 SB site (validation),CO,Reconstructed-speed MOVES (diagnostic),5,17.74,19.99,-1.98,-0.35,-23.94,-35.47,-11.98 +I-405 SB site (validation),HC,B0 whole-link mean speed,5,11.13,13.74,4.3,0.33,-42.11,-56.39,-28.96 +I-405 SB site (validation),HC,B1 delay-only / reference rate,5,53.23,56.32,53.23,-7.39,0.0,0.0,0.0 +I-405 SB site (validation),HC,B2 fixed queued state,5,10.95,13.41,3.39,0.37,-42.28,-56.7,-29.45 +I-405 SB site (validation),HC,B3 FD-consistent effective state,5,13.95,16.44,12.54,-0.06,-39.29,-48.06,-32.53 +I-405 SB site (validation),HC,Reconstructed-speed MOVES (diagnostic),5,17.86,20.94,0.12,-0.36,-35.37,-48.41,-22.82 +Pooled strict (validation),CO2,B0 whole-link mean speed,19,10.28,9.74,-4.71,0.93,-90.91,-107.58,-75.77 +Pooled strict (validation),CO2,B1 delay-only / reference rate,19,101.19,98.98,101.19,-3.34,0.0,0.0,0.0 +Pooled strict (validation),CO2,B2 fixed queued state,19,16.26,14.05,-13.77,0.85,-84.94,-104.59,-68.12 +Pooled strict (validation),CO2,B3 FD-consistent effective state,19,19.02,21.22,18.71,0.79,-82.17,-91.03,-75.09 +Pooled strict (validation),CO2,Reconstructed-speed MOVES (diagnostic),19,10.64,9.08,0.27,0.91,-90.55,-104.28,-77.22 +Pooled strict (validation),NOX,B0 whole-link mean speed,19,14.97,14.89,-12.24,0.86,-229.8,-252.09,-204.8 +Pooled strict (validation),NOX,B1 delay-only / reference rate,19,244.77,232.66,244.77,-28.61,0.0,0.0,0.0 +Pooled strict (validation),NOX,B2 fixed queued state,19,34.59,31.42,-34.1,0.2,-210.18,-242.06,-172.89 +Pooled strict (validation),NOX,B3 FD-consistent effective state,19,42.54,45.51,42.54,0.11,-202.23,-220.13,-183.22 +Pooled strict (validation),NOX,Reconstructed-speed MOVES (diagnostic),19,11.51,10.5,6.47,0.89,-233.26,-258.06,-206.67 +Pooled strict (validation),CO,B0 whole-link mean speed,19,10.19,9.89,-2.62,0.93,-32.26,-43.62,-21.06 +Pooled strict (validation),CO,B1 delay-only / reference rate,19,42.44,41.36,42.44,0.16,0.0,0.0,0.0 +Pooled strict (validation),CO,B2 fixed queued state,19,13.99,13.18,4.22,0.87,-28.45,-39.21,-18.01 +Pooled strict (validation),CO,B3 FD-consistent effective state,19,10.67,9.57,4.59,0.91,-31.78,-39.36,-23.3 +Pooled strict (validation),CO,Reconstructed-speed MOVES (diagnostic),19,14.13,12.09,-2.13,0.86,-28.32,-38.77,-17.08 +Pooled strict (validation),HC,B0 whole-link mean speed,19,11.13,10.57,-1.24,0.92,-39.79,-52.47,-28.19 +Pooled strict (validation),HC,B1 delay-only / reference rate,19,50.92,50.57,50.92,-0.15,0.0,0.0,0.0 +Pooled strict (validation),HC,B2 fixed queued state,19,11.41,9.87,-0.97,0.9,-39.5,-51.62,-27.39 +Pooled strict (validation),HC,B3 FD-consistent effective state,19,12.62,12.32,8.18,0.88,-38.3,-46.28,-29.49 +Pooled strict (validation),HC,Reconstructed-speed MOVES (diagnostic),19,14.96,13.0,-2.03,0.85,-35.95,-48.08,-23.39 +Pooled all-domain (validation),CO2,B0 whole-link mean speed,41,9.88,9.59,2.14,0.96,-85.83,-101.36,-66.96 +Pooled all-domain (validation),CO2,B1 delay-only / reference rate,41,95.7,82.06,95.7,-2.89,0.0,0.0,0.0 +Pooled all-domain (validation),CO2,B2 fixed queued state,41,14.71,13.01,-8.81,0.91,-81.0,-98.18,-61.43 +Pooled all-domain (validation),CO2,B3 FD-consistent effective state,41,14.44,15.39,13.54,0.9,-81.26,-94.63,-64.53 +Pooled all-domain (validation),CO2,Reconstructed-speed MOVES (diagnostic),41,9.97,9.19,5.13,0.95,-85.73,-100.96,-67.36 +Pooled all-domain (validation),NOX,B0 whole-link mean speed,41,13.52,13.4,-10.55,0.93,-207.2,-252.44,-157.93 +Pooled all-domain (validation),NOX,B1 delay-only / reference rate,41,220.72,191.99,220.72,-21.74,0.0,0.0,0.0 +Pooled all-domain (validation),NOX,B2 fixed queued state,41,42.59,36.01,-37.84,0.1,-178.13,-217.44,-135.76 +Pooled all-domain (validation),NOX,B3 FD-consistent effective state,41,27.56,30.53,16.46,0.73,-193.16,-235.18,-146.77 +Pooled all-domain (validation),NOX,Reconstructed-speed MOVES (diagnostic),41,10.41,10.15,8.04,0.94,-210.3,-253.28,-163.34 +Pooled all-domain (validation),CO,B0 whole-link mean speed,41,10.35,10.01,3.8,0.95,-51.91,-65.29,-38.68 +Pooled all-domain (validation),CO,B1 delay-only / reference rate,41,62.26,53.0,62.26,-0.72,0.0,0.0,0.0 +Pooled all-domain (validation),CO,B2 fixed queued state,41,12.07,11.99,0.89,0.95,-50.18,-65.09,-34.38 +Pooled all-domain (validation),CO,B3 FD-consistent effective state,41,11.39,10.23,8.05,0.93,-50.86,-64.28,-38.04 +Pooled all-domain (validation),CO,Reconstructed-speed MOVES (diagnostic),41,11.03,10.76,2.84,0.95,-51.23,-64.66,-37.35 +Pooled all-domain (validation),HC,B0 whole-link mean speed,41,11.68,10.99,5.65,0.94,-48.69,-57.34,-37.91 +Pooled all-domain (validation),HC,B1 delay-only / reference rate,41,60.37,51.55,60.37,-0.49,0.0,0.0,0.0 +Pooled all-domain (validation),HC,B2 fixed queued state,41,11.35,10.61,0.98,0.95,-49.01,-60.38,-36.25 +Pooled all-domain (validation),HC,B3 FD-consistent effective state,41,12.75,11.88,10.66,0.92,-47.61,-55.48,-37.63 +Pooled all-domain (validation),HC,Reconstructed-speed MOVES (diagnostic),41,11.62,11.31,3.55,0.94,-48.74,-58.22,-36.93 diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table4_emission_ablation.tex b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table4_emission_ablation.tex new file mode 100644 index 0000000..1a14a71 --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table4_emission_ablation.tex @@ -0,0 +1,92 @@ +% Auto-generated by run_holdout_ablation.py +\begin{table}[t] +\centering\small +\caption{Nested emission-model ablation on held-out episodes (paired bootstrap 95\% CIs on $\Delta$NMAE vs the delay-only model).} +\label{tab:v12_emission_ablation} +\begin{tabular}{lllrrrrrrrr} +\toprule +subset & pollutant & model\_label & n & NMAE\_pct & MAPE\_pct & bias\_pct & R2 & delta\_NMAE\_vs\_delay\_pct & delta\_NMAE\_ci\_lo & delta\_NMAE\_ci\_hi \\ +\midrule +I-10 EB site (validation) & CO2 & B0 whole-link mean speed & 5 & 13.31 & 13.25 & -4.47 & -0.46 & -105.06 & -135.09 & -72.11 \\ +I-10 EB site (validation) & CO2 & B1 delay-only / reference rate & 5 & 118.37 & 114.76 & 118.37 & -99.07 & 0.00 & 0.00 & 0.00 \\ +I-10 EB site (validation) & CO2 & B2 fixed queued state & 5 & 12.04 & 12.11 & -5.29 & -0.13 & -106.33 & -137.82 & -72.96 \\ +I-10 EB site (validation) & CO2 & B3 FD-consistent effective state & 5 & 23.54 & 21.68 & 23.54 & -5.06 & -94.83 & -109.81 & -81.00 \\ +I-10 EB site (validation) & CO2 & Reconstructed-speed MOVES (diagnostic) & 5 & 14.56 & 13.32 & 5.35 & -1.33 & -103.81 & -125.27 & -79.44 \\ +I-10 EB site (validation) & NOX & B0 whole-link mean speed & 5 & 24.55 & 25.28 & -24.55 & -0.23 & -262.08 & -286.55 & -228.79 \\ +I-10 EB site (validation) & NOX & B1 delay-only / reference rate & 5 & 286.63 & 282.89 & 286.63 & -177.65 & 0.00 & 0.00 & 0.00 \\ +I-10 EB site (validation) & NOX & B2 fixed queued state & 5 & 21.29 & 21.06 & -21.29 & 0.02 & -265.33 & -286.00 & -234.72 \\ +I-10 EB site (validation) & NOX & B3 FD-consistent effective state & 5 & 46.42 & 45.78 & 46.42 & -3.77 & -240.21 & -256.58 & -220.64 \\ +I-10 EB site (validation) & NOX & Reconstructed-speed MOVES (diagnostic) & 5 & 6.42 & 6.37 & 4.17 & 0.86 & -280.21 & -300.19 & -254.86 \\ +I-10 EB site (validation) & CO & B0 whole-link mean speed & 5 & 13.02 & 12.76 & -2.44 & -0.33 & -40.54 & -59.36 & -19.62 \\ +I-10 EB site (validation) & CO & B1 delay-only / reference rate & 5 & 53.56 & 50.99 & 53.56 & -21.03 & 0.00 & 0.00 & 0.00 \\ +I-10 EB site (validation) & CO & B2 fixed queued state & 5 & 12.60 & 11.61 & 4.08 & -0.56 & -40.96 & -54.80 & -25.12 \\ +I-10 EB site (validation) & CO & B3 FD-consistent effective state & 5 & 14.17 & 12.66 & 10.34 & -1.44 & -39.39 & -48.55 & -28.68 \\ +I-10 EB site (validation) & CO & Reconstructed-speed MOVES (diagnostic) & 5 & 15.28 & 14.16 & 4.87 & -1.17 & -38.28 & -51.24 & -23.02 \\ +I-10 EB site (validation) & HC & B0 whole-link mean speed & 5 & 14.55 & 14.05 & -0.61 & -1.23 & -48.00 & -68.05 & -23.26 \\ +I-10 EB site (validation) & HC & B1 delay-only / reference rate & 5 & 62.55 & 59.91 & 62.55 & -37.83 & 0.00 & 0.00 & 0.00 \\ +I-10 EB site (validation) & HC & B2 fixed queued state & 5 & 13.93 & 12.97 & 4.26 & -1.47 & -48.62 & -64.98 & -28.13 \\ +I-10 EB site (validation) & HC & B3 FD-consistent effective state & 5 & 16.37 & 14.72 & 13.80 & -3.58 & -46.18 & -55.51 & -34.51 \\ +I-10 EB site (validation) & HC & Reconstructed-speed MOVES (diagnostic) & 5 & 16.97 & 15.83 & 5.24 & -2.52 & -45.58 & -60.75 & -26.83 \\ +I-405 SB site (validation) & CO2 & B0 whole-link mean speed & 5 & 9.89 & 10.61 & -2.18 & 0.63 & -87.45 & -107.53 & -70.57 \\ +I-405 SB site (validation) & CO2 & B1 delay-only / reference rate & 5 & 97.35 & 98.76 & 97.35 & -28.87 & 0.00 & 0.00 & 0.00 \\ +I-405 SB site (validation) & CO2 & B2 fixed queued state & 5 & 28.45 & 27.64 & -28.45 & -1.83 & -68.90 & -99.52 & -47.52 \\ +I-405 SB site (validation) & CO2 & B3 FD-consistent effective state & 5 & 21.47 & 22.52 & 21.47 & -0.80 & -75.88 & -84.71 & -68.94 \\ +I-405 SB site (validation) & CO2 & Reconstructed-speed MOVES (diagnostic) & 5 & 10.64 & 11.81 & 2.82 & 0.45 & -86.70 & -100.98 & -74.08 \\ +I-405 SB site (validation) & NOX & B0 whole-link mean speed & 5 & 16.63 & 15.71 & -16.63 & 0.16 & -170.11 & -200.69 & -140.90 \\ +I-405 SB site (validation) & NOX & B1 delay-only / reference rate & 5 & 186.73 & 189.88 & 186.73 & -79.76 & 0.00 & 0.00 & 0.00 \\ +I-405 SB site (validation) & NOX & B2 fixed queued state & 5 & 76.86 & 75.67 & -76.86 & -13.34 & -109.88 & -138.41 & -85.62 \\ +I-405 SB site (validation) & NOX & B3 FD-consistent effective state & 5 & 28.99 & 30.97 & 28.99 & -1.07 & -157.74 & -170.24 & -145.32 \\ +I-405 SB site (validation) & NOX & Reconstructed-speed MOVES (diagnostic) & 5 & 16.24 & 16.41 & 2.14 & 0.17 & -170.50 & -193.68 & -141.41 \\ +I-405 SB site (validation) & CO & B0 whole-link mean speed & 5 & 10.07 & 11.99 & 1.03 & 0.42 & -31.60 & -44.82 & -18.24 \\ +I-405 SB site (validation) & CO & B1 delay-only / reference rate & 5 & 41.67 & 43.64 & 41.67 & -5.13 & 0.00 & 0.00 & 0.00 \\ +I-405 SB site (validation) & CO & B2 fixed queued state & 5 & 25.20 & 26.97 & 25.20 & -1.64 & -16.47 & -18.98 & -14.63 \\ +I-405 SB site (validation) & CO & B3 FD-consistent effective state & 5 & 10.92 & 12.82 & 6.36 & 0.29 & -30.75 & -39.23 & -21.51 \\ +I-405 SB site (validation) & CO & Reconstructed-speed MOVES (diagnostic) & 5 & 17.74 & 19.99 & -1.98 & -0.35 & -23.94 & -35.47 & -11.98 \\ +I-405 SB site (validation) & HC & B0 whole-link mean speed & 5 & 11.13 & 13.74 & 4.30 & 0.33 & -42.11 & -56.39 & -28.96 \\ +I-405 SB site (validation) & HC & B1 delay-only / reference rate & 5 & 53.23 & 56.32 & 53.23 & -7.39 & 0.00 & 0.00 & 0.00 \\ +I-405 SB site (validation) & HC & B2 fixed queued state & 5 & 10.95 & 13.41 & 3.39 & 0.37 & -42.28 & -56.70 & -29.45 \\ +I-405 SB site (validation) & HC & B3 FD-consistent effective state & 5 & 13.95 & 16.44 & 12.54 & -0.06 & -39.29 & -48.06 & -32.53 \\ +I-405 SB site (validation) & HC & Reconstructed-speed MOVES (diagnostic) & 5 & 17.86 & 20.94 & 0.12 & -0.36 & -35.37 & -48.41 & -22.82 \\ +Pooled strict (validation) & CO2 & B0 whole-link mean speed & 19 & 10.28 & 9.74 & -4.71 & 0.93 & -90.91 & -107.58 & -75.77 \\ +Pooled strict (validation) & CO2 & B1 delay-only / reference rate & 19 & 101.19 & 98.98 & 101.19 & -3.34 & 0.00 & 0.00 & 0.00 \\ +Pooled strict (validation) & CO2 & B2 fixed queued state & 19 & 16.26 & 14.05 & -13.77 & 0.85 & -84.94 & -104.59 & -68.12 \\ +Pooled strict (validation) & CO2 & B3 FD-consistent effective state & 19 & 19.02 & 21.22 & 18.71 & 0.79 & -82.17 & -91.03 & -75.09 \\ +Pooled strict (validation) & CO2 & Reconstructed-speed MOVES (diagnostic) & 19 & 10.64 & 9.08 & 0.27 & 0.91 & -90.55 & -104.28 & -77.22 \\ +Pooled strict (validation) & NOX & B0 whole-link mean speed & 19 & 14.97 & 14.89 & -12.24 & 0.86 & -229.80 & -252.09 & -204.80 \\ +Pooled strict (validation) & NOX & B1 delay-only / reference rate & 19 & 244.77 & 232.66 & 244.77 & -28.61 & 0.00 & 0.00 & 0.00 \\ +Pooled strict (validation) & NOX & B2 fixed queued state & 19 & 34.59 & 31.42 & -34.10 & 0.20 & -210.18 & -242.06 & -172.89 \\ +Pooled strict (validation) & NOX & B3 FD-consistent effective state & 19 & 42.54 & 45.51 & 42.54 & 0.11 & -202.23 & -220.13 & -183.22 \\ +Pooled strict (validation) & NOX & Reconstructed-speed MOVES (diagnostic) & 19 & 11.51 & 10.50 & 6.47 & 0.89 & -233.26 & -258.06 & -206.67 \\ +Pooled strict (validation) & CO & B0 whole-link mean speed & 19 & 10.19 & 9.89 & -2.62 & 0.93 & -32.26 & -43.62 & -21.06 \\ +Pooled strict (validation) & CO & B1 delay-only / reference rate & 19 & 42.44 & 41.36 & 42.44 & 0.16 & 0.00 & 0.00 & 0.00 \\ +Pooled strict (validation) & CO & B2 fixed queued state & 19 & 13.99 & 13.18 & 4.22 & 0.87 & -28.45 & -39.21 & -18.01 \\ +Pooled strict (validation) & CO & B3 FD-consistent effective state & 19 & 10.67 & 9.57 & 4.59 & 0.91 & -31.78 & -39.36 & -23.30 \\ +Pooled strict (validation) & CO & Reconstructed-speed MOVES (diagnostic) & 19 & 14.13 & 12.09 & -2.13 & 0.86 & -28.32 & -38.77 & -17.08 \\ +Pooled strict (validation) & HC & B0 whole-link mean speed & 19 & 11.13 & 10.57 & -1.24 & 0.92 & -39.79 & -52.47 & -28.19 \\ +Pooled strict (validation) & HC & B1 delay-only / reference rate & 19 & 50.92 & 50.57 & 50.92 & -0.15 & 0.00 & 0.00 & 0.00 \\ +Pooled strict (validation) & HC & B2 fixed queued state & 19 & 11.41 & 9.87 & -0.97 & 0.90 & -39.50 & -51.62 & -27.39 \\ +Pooled strict (validation) & HC & B3 FD-consistent effective state & 19 & 12.62 & 12.32 & 8.18 & 0.88 & -38.30 & -46.28 & -29.49 \\ +Pooled strict (validation) & HC & Reconstructed-speed MOVES (diagnostic) & 19 & 14.96 & 13.00 & -2.03 & 0.85 & -35.95 & -48.08 & -23.39 \\ +Pooled all-domain (validation) & CO2 & B0 whole-link mean speed & 41 & 9.88 & 9.59 & 2.14 & 0.96 & -85.83 & -101.36 & -66.96 \\ +Pooled all-domain (validation) & CO2 & B1 delay-only / reference rate & 41 & 95.70 & 82.06 & 95.70 & -2.89 & 0.00 & 0.00 & 0.00 \\ +Pooled all-domain (validation) & CO2 & B2 fixed queued state & 41 & 14.71 & 13.01 & -8.81 & 0.91 & -81.00 & -98.18 & -61.43 \\ +Pooled all-domain (validation) & CO2 & B3 FD-consistent effective state & 41 & 14.44 & 15.39 & 13.54 & 0.90 & -81.26 & -94.63 & -64.53 \\ +Pooled all-domain (validation) & CO2 & Reconstructed-speed MOVES (diagnostic) & 41 & 9.97 & 9.19 & 5.13 & 0.95 & -85.73 & -100.96 & -67.36 \\ +Pooled all-domain (validation) & NOX & B0 whole-link mean speed & 41 & 13.52 & 13.40 & -10.55 & 0.93 & -207.20 & -252.44 & -157.93 \\ +Pooled all-domain (validation) & NOX & B1 delay-only / reference rate & 41 & 220.72 & 191.99 & 220.72 & -21.74 & 0.00 & 0.00 & 0.00 \\ +Pooled all-domain (validation) & NOX & B2 fixed queued state & 41 & 42.59 & 36.01 & -37.84 & 0.10 & -178.13 & -217.44 & -135.76 \\ +Pooled all-domain (validation) & NOX & B3 FD-consistent effective state & 41 & 27.56 & 30.53 & 16.46 & 0.73 & -193.16 & -235.18 & -146.77 \\ +Pooled all-domain (validation) & NOX & Reconstructed-speed MOVES (diagnostic) & 41 & 10.41 & 10.15 & 8.04 & 0.94 & -210.30 & -253.28 & -163.34 \\ +Pooled all-domain (validation) & CO & B0 whole-link mean speed & 41 & 10.35 & 10.01 & 3.80 & 0.95 & -51.91 & -65.29 & -38.68 \\ +Pooled all-domain (validation) & CO & B1 delay-only / reference rate & 41 & 62.26 & 53.00 & 62.26 & -0.72 & 0.00 & 0.00 & 0.00 \\ +Pooled all-domain (validation) & CO & B2 fixed queued state & 41 & 12.07 & 11.99 & 0.89 & 0.95 & -50.18 & -65.09 & -34.38 \\ +Pooled all-domain (validation) & CO & B3 FD-consistent effective state & 41 & 11.39 & 10.23 & 8.05 & 0.93 & -50.86 & -64.28 & -38.04 \\ +Pooled all-domain (validation) & CO & Reconstructed-speed MOVES (diagnostic) & 41 & 11.03 & 10.76 & 2.84 & 0.95 & -51.23 & -64.66 & -37.35 \\ +Pooled all-domain (validation) & HC & B0 whole-link mean speed & 41 & 11.68 & 10.99 & 5.65 & 0.94 & -48.69 & -57.34 & -37.91 \\ +Pooled all-domain (validation) & HC & B1 delay-only / reference rate & 41 & 60.37 & 51.55 & 60.37 & -0.49 & 0.00 & 0.00 & 0.00 \\ +Pooled all-domain (validation) & HC & B2 fixed queued state & 41 & 11.35 & 10.61 & 0.98 & 0.95 & -49.01 & -60.38 & -36.25 \\ +Pooled all-domain (validation) & HC & B3 FD-consistent effective state & 41 & 12.75 & 11.88 & 10.66 & 0.92 & -47.61 & -55.48 & -37.63 \\ +Pooled all-domain (validation) & HC & Reconstructed-speed MOVES (diagnostic) & 41 & 11.62 & 11.31 & 3.55 & 0.94 & -48.74 & -58.22 & -36.93 \\ +\bottomrule +\end{tabular} +\end{table} diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table5_two_branch_decomposition.csv b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table5_two_branch_decomposition.csv new file mode 100644 index 0000000..2c181b5 --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table5_two_branch_decomposition.csv @@ -0,0 +1,5 @@ +Pollutant,n,"Free-flow branch (g/lane, median)","Queue branch (g/lane, median)","Queue share (%, median)","Queue share (%, p10-p90)","Gamma exact (g/h, median)","|cubic-exact|/exact Gamma (%, median)",Model/observed total (%) +CO2,19,631474.7122177125,187414.43227965466,25.115896944701554,9-27,4152.19482047007,8.323446865082238,118.70715402464735 +NOX,19,832.3334306157766,-64.04952363814078,-9.177904972082128,-21--1,-1.16609858582733,38.493063922899836,142.53507486336977 +CO,19,3931.6073313612496,2312.8746080499764,38.08516535302796,22-42,51.46221712996654,5.1189389438519655,104.58850315796579 +HC,19,179.32688787090265,97.54436633721451,36.76225578830392,20-41,2.2061765763366323,5.197315967840086,108.17882657890512 diff --git a/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table5_two_branch_decomposition.tex b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table5_two_branch_decomposition.tex new file mode 100644 index 0000000..e7de851 --- /dev/null +++ b/experiments/output/qvdfe_cbi/stage8_holdout_ablation/tables/table5_two_branch_decomposition.tex @@ -0,0 +1,11 @@ +% Auto-generated by run_emission_supplement.py +\begin{tabular}{lrrrrlrrr} +\toprule +Pollutant & n & Free-flow branch (g/lane, median) & Queue branch (g/lane, median) & Queue share (\%, median) & Queue share (\%, p10-p90) & Gamma exact (g/h, median) & |cubic-exact|/exact Gamma (\%, median) & Model/observed total (\%) \\ +\midrule +CO2 & 19 & 631474.700000 & 187414.400000 & 25.100000 & 9-27 & 4152.200000 & 8.300000 & 118.700000 \\ +NOX & 19 & 832.300000 & -64.000000 & -9.200000 & -21--1 & -1.200000 & 38.500000 & 142.500000 \\ +CO & 19 & 3931.600000 & 2312.900000 & 38.100000 & 22-42 & 51.500000 & 5.100000 & 104.600000 \\ +HC & 19 & 179.300000 & 97.500000 & 36.800000 & 20-41 & 2.200000 & 5.200000 & 108.200000 \\ +\bottomrule +\end{tabular}