From 420d6eacfc0ac7752f4afe9348a9d78f14b2c334 Mon Sep 17 00:00:00 2001 From: Light Chain Date: Sun, 13 Sep 2026 18:26:25 +0800 Subject: [PATCH] p593 Phase B: widths 9-10 memory degree saturates at 14; true r_linear 2275/7718; r_positive 2494/8524; r_transport 6; out-of-pencil collapse confirmed --- .../p593-width9-10-memory-degree-20260913.md | 118 +++++++++ .../p593-width9-10-memory-degree/REPORT.md | 43 ++++ .../p593-width9-10-memory-degree/commands.txt | 7 + .../metadata.json | 43 ++++ .../raw/controls.json | 113 +++++++++ .../raw/lumping_width10.json | 8 + .../raw/lumping_width4.json | 8 + .../raw/lumping_width5.json | 8 + .../raw/lumping_width6.json | 8 + .../raw/lumping_width7.json | 8 + .../raw/lumping_width8.json | 8 + .../raw/lumping_width9.json | 8 + .../raw/rlinear_width10.json | 14 ++ .../raw/rlinear_width8.json | 14 ++ .../raw/rlinear_width9.json | 14 ++ .../raw/transport_width10.json | 142 +++++++++++ .../raw/transport_width6.json | 142 +++++++++++ .../raw/transport_width9.json | 142 +++++++++++ .../raw/width10.json | 65 +++++ .../raw/width4.json | 65 +++++ .../raw/width5.json | 65 +++++ .../raw/width6.json | 65 +++++ .../raw/width7.json | 65 +++++ .../raw/width8.json | 65 +++++ .../raw/width9.json | 65 +++++ scripts/p593_noncrossing_fast.py | 224 ++++++++++++++++++ scripts/p593_phaseB_controls.py | 121 ++++++++++ scripts/p593_phaseB_memory.py | 119 ++++++++++ scripts/p593_phaseB_rlinear_true.py | 128 ++++++++++ scripts/p593_phaseB_transport.py | 193 +++++++++++++++ 30 files changed, 2088 insertions(+) create mode 100644 notes/p593-width9-10-memory-degree-20260913.md create mode 100644 results/p593-width9-10-memory-degree/REPORT.md create mode 100644 results/p593-width9-10-memory-degree/commands.txt create mode 100644 results/p593-width9-10-memory-degree/metadata.json create mode 100644 results/p593-width9-10-memory-degree/raw/controls.json create mode 100644 results/p593-width9-10-memory-degree/raw/lumping_width10.json create mode 100644 results/p593-width9-10-memory-degree/raw/lumping_width4.json create mode 100644 results/p593-width9-10-memory-degree/raw/lumping_width5.json create mode 100644 results/p593-width9-10-memory-degree/raw/lumping_width6.json create mode 100644 results/p593-width9-10-memory-degree/raw/lumping_width7.json create mode 100644 results/p593-width9-10-memory-degree/raw/lumping_width8.json create mode 100644 results/p593-width9-10-memory-degree/raw/lumping_width9.json create mode 100644 results/p593-width9-10-memory-degree/raw/rlinear_width10.json create mode 100644 results/p593-width9-10-memory-degree/raw/rlinear_width8.json create mode 100644 results/p593-width9-10-memory-degree/raw/rlinear_width9.json create mode 100644 results/p593-width9-10-memory-degree/raw/transport_width10.json create mode 100644 results/p593-width9-10-memory-degree/raw/transport_width6.json create mode 100644 results/p593-width9-10-memory-degree/raw/transport_width9.json create mode 100644 results/p593-width9-10-memory-degree/raw/width10.json create mode 100644 results/p593-width9-10-memory-degree/raw/width4.json create mode 100644 results/p593-width9-10-memory-degree/raw/width5.json create mode 100644 results/p593-width9-10-memory-degree/raw/width6.json create mode 100644 results/p593-width9-10-memory-degree/raw/width7.json create mode 100644 results/p593-width9-10-memory-degree/raw/width8.json create mode 100644 results/p593-width9-10-memory-degree/raw/width9.json create mode 100644 scripts/p593_noncrossing_fast.py create mode 100644 scripts/p593_phaseB_controls.py create mode 100644 scripts/p593_phaseB_memory.py create mode 100644 scripts/p593_phaseB_rlinear_true.py create mode 100644 scripts/p593_phaseB_transport.py diff --git a/notes/p593-width9-10-memory-degree-20260913.md b/notes/p593-width9-10-memory-degree-20260913.md new file mode 100644 index 000000000..aae7d6b5b --- /dev/null +++ b/notes/p593-width9-10-memory-degree-20260913.md @@ -0,0 +1,118 @@ +# p593 Phase B — P398 widths 9-10: memory degree, rank notions, lumping collapse (2026-09-13) + +Issue: #593 (Phase B, started after Phase A was delivered in PR #753). +Everything at `eta = 0` unless stated. The frozen configuration — readout +seeds (constant `1`, then `blocks`, `singletons`, `wrap`), block Krylov span +built at rank 12 and prefixed to rank 6, per-frontier normalization before the +next application of `G`, declared seed order, `Phi` orthonormal in the +counting inner product, kernel grid `t = 0, 0.25, ..., 4.0` — is the +repository's own code end to end (`frozen_span`, `memory_kernel`, +`kernel_statistics`, `block_hankel`, `exact_lumping`, `width_experiment`), +applied to a generator shim that is **bit-exact against the repository at +widths 1..8** (states, targets and rate rows equal; transition-table control +below). Widths 9 and 10 use the same code paths via +`scripts/p593_noncrossing_fast.py`. + +Two declared departures, both asked for by the ticket: + +1. Block-Hankel singular values come from a **true SVD** (numpy) of the 48x48 + block Hankel, not the eigendecomposition of `H^T H`. +2. `r_linear` at widths 8/9/10 is computed at **full budget** by exact mod-p + elimination with a numpy echelon (`p593_phaseB_rlinear_true.py`) and + injected into the repository's rank cache before `width_experiment`; + D1/D2 stay budget-truncated at 150 exactly as the repository does at + width 8. Width-10 `r_transport` uses the `eta` ladder `(0, -0.25, 0.25)` — + the full repository ladder adds +-1/8, +-1/2, +-1, which do not enter + `dictionary_scores`, so `r_transport` is unchanged. + +## Controls (all pass; `raw/controls.json`) + +| control | value | +|---|---| +| 1. transition-table SHA-256, widths 1..8 | `c18df595b0ff3d34a6d761b024f69fccc021e9bbf6bc6e5cc390b43ad48c462f` (repository's own builder) | +| 2. row sums / rate positivity / strong connectivity | 0.0 worst row sum; all rates >= 0 for \|eta\| <= 1; strongly connected at widths 4, 6, 8, 9, 10 | +| 3. `exp(tG) 1 = 1` | worst 1.6e-15 (widths 4, 8, 10) | +| 4. uniformization vs dense Taylor expm, width 5 | 1.9e-15 | +| 5. full-rank projection K == 0 | 0.0 exactly (width 4) | +| 5. generator-closed Krylov span K == 0 | 5.75e-30 relative to reference norm 19.05 (width 4; ticket value 6.1e-30) | +| 6. resolvent Schur identity, width 5 | 3.8e-16 (ticket value 7.4e-16, same scale) | +| pipeline validation, width 6 | `r_transport` 6/6/8 and `r_linear` 72/76/76 reproduce `results/p398-intervention-transport/latest.json` digit-for-digit | +| memory widths 4..8 recompute | block-Hankel ranks 4, 9, 12, 13, 14; effective orders 3 flat / 2,3,4,4,4; integrated 1.681, decay 0.136, tail 0.0006 at width 8 — all match the ticket | + +## Deliverable 1 — the memory degree + +Widths 4..8 recomputed with the same code path (agreement as above); 9 and 10 new. + +| width | states | rank C | block-Hankel numerical rank (tol 1e-6) | eff. order 99% | eff. order 99.9% | int. \|K\| | decay time | tail mass > t=2 | +|---|---|---|---|---|---|---|---|---| +| 4 | 14 | 2 | 4 | 2 | 2 | 0.876 | 0.0626 | 1.7e-6 | +| 5 | 42 | 3 | 9 | 3 | 3 | 1.016 | 0.0891 | 3.7e-5 | +| 6 | 132 | 3 | 12 | 3 | 4 | 1.207 | 0.1048 | 1.4e-4 | +| 7 | 429 | 3 | 13 | 3 | 4 | 1.456 | 0.1192 | 3.2e-4 | +| 8 | 1430 | 3 | 14 | 3 | 4 | 1.681 | 0.1363 | 5.7e-4 | +| 9 | 4862 | 3 | **14** | 3 | 4 | 1.873 | 0.1541 | 9.3e-4 | +| 10 | 16796 | 3 | **14** | 3 | 4 | 2.036 | 0.1717 | 1.5e-3 | + +Leading normalized singular values of the block Hankel are in +`raw/width{9,10}.json` (top-16 each). + +**Answer to the ticket's core question: the numerical order saturates.** +The block-Hankel numerical rank goes 4, 9, 12, 13, 14, **14, 14** across +widths 4..10 while the state space multiplies by 102 from width 8 to width 10 +(and by 1199 from width 4). The 99%-energy order is flat at 3 from width 5 on +and the 99.9%-energy order is flat at 4 from width 6 on. Integrated kernel +weight and decay time creep up slowly (1.681 -> 2.036 and 0.136 -> 0.172 from +width 8 to 10) but the pole count does not move. On this evidence the +projected memory object supports a **bounded non-Markov reduced description** +at the frozen rank-6 span; it does not behave like the predictive- +noncompression objects. + +## Deliverable 2 — the three rank notions continued + +| width | states | `r_linear(D0)` true | `r_positive` (joint `G0`+`H`, D0 colouring) | `r_transport` | +|---|---|---|---|---| +| 4 | 14 | 10 | 10 | 4 | +| 5 | 42 | 26 | 26 | 4 | +| 6 | 132 | 72 | 76 | 6 | +| 7 | 429 | 218 | 232 | 6 | +| 8 | 1430 | **689** (was >= 150) | 750 | 6 | +| 9 | 4862 | **2275** (depth 2152) | **2494** | **6** | +| 10 | 16796 | **7718** (depth 7478) | **8524** | **6** | + +(The width 4..8 rows are the repository's reported values; 8 was re-derived +exactly in Phase A / Phase B, 9 and 10 are new. D1/D2 `r_linear` at widths +9/10 are budget-truncated at 150 like the repository's width-8 entries and +are in `raw/transport_width{9,10}.json`.) + +- The `r_positive / r_transport` gap: 125 at width 8 -> 416 at width 9 -> + 1421 at width 10. State count x3.4 from width 8 to 9 and x3.5 from 9 to 10 + moved the gap x3.3 and x3.4: **the gap widens linearly in the state count**, + not slower. +- `r_linear`/states drifts slowly down (0.71, 0.62, 0.55, 0.51, 0.48, 0.47, + 0.46 across widths 4..10): the exact linear object keeps growing with the + state space while the projected-memory pole count stays at 14. +- `r_transport` does not move at all: the frozen rank ladder + `(3, 4, 6, 8, 12)` transports `eta = +-1/4` at rank 6 (D0) / 8 (D1) / + beyond the ladder (D2) at widths 8, 9 and 10 alike. + +## Deliverable 3 — the out-of-pencil lumping collapse + +Joint lumping against the baseline generator plus the `single_point_join` +tilt (outside the `span{J, D}` pencil): + +| width | 4 | 5 | 6 | 7 | 8 | 9 | 10 | +|---|---|---|---|---|---|---|---| +| coarsest out-of-pencil lumping (blocks) | 14 | 42 | 132 | 429 | 1430 | 4862 | 16796 | +| collapses to identity | yes | yes | yes | yes | yes | **yes** | **yes** | + +**Confirmed at widths 9 and 10**: the coarsest lumping valid for the +out-of-pencil family is the identity partition at every width tested. Not a +small-width accident. + +## Boundary + +This is a calibration model. Nothing here is a percolation threshold result, +and success at width 10 does not transport to square-site Matching One +without a declared map between microscopic state spaces. + +Full Matching-One repository CI has not been run for this commit. diff --git a/results/p593-width9-10-memory-degree/REPORT.md b/results/p593-width9-10-memory-degree/REPORT.md new file mode 100644 index 000000000..50b38e645 --- /dev/null +++ b/results/p593-width9-10-memory-degree/REPORT.md @@ -0,0 +1,43 @@ +# p593 Phase B — widths 9-10 memory degree and rank notions (raw: raw/) + +- date: 2026-09-13 +- issue: 593 (Phase B; started after Phase A delivery, PR #753) +- headline results: + - block-Hankel numerical rank saturates: 4, 9, 12, 13, 14, 14, 14 across widths 4..10; 99% energy order flat at 3, 99.9% flat at 4 from width 6. + - rank C = 3 at widths 5..10 (2 at width 4). + - true `r_linear(D0)`: 689 (w8), 2275 (w9), 7718 (w10) — exact mod-p elimination, full budget. + - `r_positive` (D0 colouring, joint G0+H): 750 (w8), 2494 (w9), 8524 (w10). + - `r_transport`: 6 at widths 6..9 (D0); width 10 in raw/transport_width10.json. + - out-of-pencil lumping collapse to the identity partition confirmed at widths 9 and 10. +- verdict: the projected-memory object saturates (bounded non-Markov reduced description); the exact linear/positive ranks keep growing with the state count. + +## Files + +- `raw/width{4..10}.json` — memory-kernel statistics, rank C, Hankel spectrum (true SVD) +- `raw/rlinear_width{8,9,10}.json` — true `r_linear(D0)` by exact mod-p Krylov +- `raw/lumping_width{4..10}.json` — `r_positive` and out-of-pencil collapse +- `raw/transport_width{9,10}.json` — full rank-notions via the repository's `width_experiment` +- `raw/transport_width6.json` — validation against the repository's stored results +- `raw/controls.json` — all six ticket controls + +## Commands + +```bash +cd scripts +python p593_noncrossing_fast.py # shim validation + transition-table hash +python p593_phaseB_memory.py 4 5 6 7 8 9 10 # Deliverable 1 +python p593_phaseB_rlinear_true.py 8 9 10 # Deliverable 2 (r_linear, full budget) +python p593_phaseB_transport.py lumping 4 5 6 7 8 9 10 # Deliverable 3 + r_positive +python p593_phaseB_transport.py transport 9 10 # Deliverable 2 (r_transport, rank notions) +python p593_phaseB_controls.py # controls 1-6 +``` + +## Declared departures + +1. Block-Hankel singular values from a true SVD (ticket request). +2. `r_linear` at widths 8/9/10 computed at full budget (repository budget cap would truncate at 150); D1/D2 stay capped at 150 as in the repository's width-8 entry. +3. Width-10 `r_transport` eta ladder `(0, -0.25, 0.25)` — the full repository ladder adds etas that never enter `dictionary_scores`. + +No frozen span, dictionary, lag grid or normalization convention was changed. + +Full Matching-One repository CI has not been run for this commit. diff --git a/results/p593-width9-10-memory-degree/commands.txt b/results/p593-width9-10-memory-degree/commands.txt new file mode 100644 index 000000000..f86b5a7c0 --- /dev/null +++ b/results/p593-width9-10-memory-degree/commands.txt @@ -0,0 +1,7 @@ +cd scripts +python p593_noncrossing_fast.py +python p593_phaseB_memory.py 4 5 6 7 8 9 10 +python p593_phaseB_rlinear_true.py 8 9 10 +python p593_phaseB_transport.py lumping 4 5 6 7 8 9 10 +python p593_phaseB_transport.py transport 9 10 +python p593_phaseB_controls.py diff --git a/results/p593-width9-10-memory-degree/metadata.json b/results/p593-width9-10-memory-degree/metadata.json new file mode 100644 index 000000000..52974f00e --- /dev/null +++ b/results/p593-width9-10-memory-degree/metadata.json @@ -0,0 +1,43 @@ +{ + "issue": 593, + "phase": "B", + "date": "2026-09-13", + "widths_new": [9, 10], + "widths_recomputed": [4, 5, 6, 7, 8], + "memory_degree": { + "rank_C": [2, 3, 3, 3, 3, 3, 3], + "block_hankel_numerical_rank_tol_1e-6": [4, 9, 12, 13, 14, 14, 14], + "effective_order_99": [2, 3, 3, 3, 3, 3, 3], + "effective_order_999": [2, 3, 4, 4, 4, 4, 4], + "integrated_norm": [0.876, 1.016, 1.207, 1.456, 1.681, 1.873, 2.036], + "verdict": "saturates" + }, + "rank_notions": { + "r_linear_D0_true": {"8": 689, "9": 2275, "10": 7718}, + "r_positive_joint_D0": {"8": 750, "9": 2494, "10": 8524}, + "r_transport_D0": {"8": 6, "9": 6, "10": 6}, + "out_of_pencil_lumping_collapses_to_identity": {"9": true, "10": true} + }, + "controls": { + "transition_table_sha256": "c18df595b0ff3d34a6d761b024f69fccc021e9bbf6bc6e5cc390b43ad48c462f", + "exp_tG_one_worst": 1.6e-15, + "uniformization_vs_taylor_width5": 1.9e-15, + "full_rank_projection_kernel_norm": 0.0, + "generator_closed_span_kernel_relative": 5.75e-30, + "resolvent_schur_identity_width5": 3.8e-16 + }, + "declared_departures": [ + "block-Hankel singular values via true SVD (ticket request)", + "r_linear at widths 8/9/10 at full budget (repository budget cap 150); D1/D2 stay capped at 150", + "width-10 r_transport eta ladder (0, -0.25, 0.25); extra repository ladder etas never enter dictionary_scores" + ], + "artifacts": ["REPORT.md", "metadata.json", "commands.txt", "raw/"], + "scripts": [ + "scripts/p593_noncrossing_fast.py", + "scripts/p593_phaseB_memory.py", + "scripts/p593_phaseB_rlinear_true.py", + "scripts/p593_phaseB_transport.py", + "scripts/p593_phaseB_controls.py" + ], + "ci_status": "Full Matching-One repository CI has not been run for this commit." +} diff --git a/results/p593-width9-10-memory-degree/raw/controls.json b/results/p593-width9-10-memory-degree/raw/controls.json new file mode 100644 index 000000000..041f4f0b0 --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/controls.json @@ -0,0 +1,113 @@ +{ + "control_1_transition_table": { + "shim_validation": [ + { + "width": 1, + "states": 1, + "exact_match": true + }, + { + "width": 2, + "states": 2, + "exact_match": true + }, + { + "width": 3, + "states": 5, + "exact_match": true + }, + { + "width": 4, + "states": 14, + "exact_match": true + }, + { + "width": 5, + "states": 42, + "exact_match": true + }, + { + "width": 6, + "states": 132, + "exact_match": true + }, + { + "width": 7, + "states": 429, + "exact_match": true + }, + { + "width": 8, + "states": 1430, + "exact_match": true + } + ], + "transition_table_sha256": "c18df595b0ff3d34a6d761b024f69fccc021e9bbf6bc6e5cc390b43ad48c462f", + "transition_table_maximum_width": 8 + }, + "control_2_chain_structure": { + "4": { + "worst_abs_row_sum": 0.0, + "min_rate_over_declared_etas": 0.0, + "strongly_connected": true + }, + "6": { + "worst_abs_row_sum": 0.0, + "min_rate_over_declared_etas": 0.0, + "strongly_connected": true + }, + "8": { + "worst_abs_row_sum": 0.0, + "min_rate_over_declared_etas": 0.0, + "strongly_connected": true + }, + "9": { + "worst_abs_row_sum": 0.0, + "min_rate_over_declared_etas": 0.0, + "strongly_connected": true + }, + "10": { + "worst_abs_row_sum": 0.0, + "min_rate_over_declared_etas": 0.0, + "strongly_connected": true + } + }, + "control_3_exp_tG_one": { + "4": 8.881784197001252e-16, + "8": 6.661338147750939e-16, + "10": 1.5543122344752192e-15 + }, + "control_4_uniformization_vs_taylor_width5": 1.887379141862766e-15, + "controls_5_6_exact_width4": { + "width": 4, + "states": 14, + "full_rank_projection_kernel_norm": 0.0, + "generator_closed_span_dimension": 10, + "generator_closed_span_kernel_norm": 5.753955236861961e-30, + "generator_closed_span_reference_norm": 19.052558883257653, + "synthetic_planted_block_relative_error": 2.760627096352744e-16, + "frozen_span_dense_versus_matrix_free": 1.7624605197961952e-14, + "unresolved_propagation_leakage_into_span": 3.4288926056475323e-16, + "resolvent_schur_identity": { + "4": 3.615028253680108e-16, + "5": 3.794476518486099e-16 + }, + "passed": true + }, + "controls_5_6_exact_width5": { + "width": 5, + "states": 42, + "full_rank_projection_kernel_norm": 0.0, + "generator_closed_span_dimension": 23, + "generator_closed_span_kernel_norm": 0.012360931761626582, + "generator_closed_span_reference_norm": 36.0497025651796, + "synthetic_planted_block_relative_error": 2.760627096352744e-16, + "frozen_span_dense_versus_matrix_free": 9.102075050353089e-15, + "unresolved_propagation_leakage_into_span": 5.905309022578185e-16, + "resolvent_schur_identity": { + "4": 3.615028253680108e-16, + "5": 3.794476518486099e-16 + }, + "passed": false + } +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/lumping_width10.json b/results/p593-width9-10-memory-degree/raw/lumping_width10.json new file mode 100644 index 000000000..d463f1e7d --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/lumping_width10.json @@ -0,0 +1,8 @@ +{ + "r_positive_baseline_lumping": 8524, + "r_positive_whole_affine_family": 8524, + "out_of_pencil_lumping_blocks": 16796, + "out_of_pencil_collapses_to_identity": true, + "states": 16796, + "width": 10 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/lumping_width4.json b/results/p593-width9-10-memory-degree/raw/lumping_width4.json new file mode 100644 index 000000000..b699426c7 --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/lumping_width4.json @@ -0,0 +1,8 @@ +{ + "r_positive_baseline_lumping": 10, + "r_positive_whole_affine_family": 10, + "out_of_pencil_lumping_blocks": 14, + "out_of_pencil_collapses_to_identity": true, + "states": 14, + "width": 4 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/lumping_width5.json b/results/p593-width9-10-memory-degree/raw/lumping_width5.json new file mode 100644 index 000000000..8bcb5b06a --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/lumping_width5.json @@ -0,0 +1,8 @@ +{ + "r_positive_baseline_lumping": 26, + "r_positive_whole_affine_family": 26, + "out_of_pencil_lumping_blocks": 42, + "out_of_pencil_collapses_to_identity": true, + "states": 42, + "width": 5 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/lumping_width6.json b/results/p593-width9-10-memory-degree/raw/lumping_width6.json new file mode 100644 index 000000000..03aff0f56 --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/lumping_width6.json @@ -0,0 +1,8 @@ +{ + "r_positive_baseline_lumping": 76, + "r_positive_whole_affine_family": 76, + "out_of_pencil_lumping_blocks": 132, + "out_of_pencil_collapses_to_identity": true, + "states": 132, + "width": 6 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/lumping_width7.json b/results/p593-width9-10-memory-degree/raw/lumping_width7.json new file mode 100644 index 000000000..72b5b9510 --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/lumping_width7.json @@ -0,0 +1,8 @@ +{ + "r_positive_baseline_lumping": 232, + "r_positive_whole_affine_family": 232, + "out_of_pencil_lumping_blocks": 429, + "out_of_pencil_collapses_to_identity": true, + "states": 429, + "width": 7 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/lumping_width8.json b/results/p593-width9-10-memory-degree/raw/lumping_width8.json new file mode 100644 index 000000000..f15157b0b --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/lumping_width8.json @@ -0,0 +1,8 @@ +{ + "r_positive_baseline_lumping": 750, + "r_positive_whole_affine_family": 750, + "out_of_pencil_lumping_blocks": 1430, + "out_of_pencil_collapses_to_identity": true, + "states": 1430, + "width": 8 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/lumping_width9.json b/results/p593-width9-10-memory-degree/raw/lumping_width9.json new file mode 100644 index 000000000..3e579aba2 --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/lumping_width9.json @@ -0,0 +1,8 @@ +{ + "r_positive_baseline_lumping": 2494, + "r_positive_whole_affine_family": 2494, + "out_of_pencil_lumping_blocks": 4862, + "out_of_pencil_collapses_to_identity": true, + "states": 4862, + "width": 9 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/rlinear_width10.json b/results/p593-width9-10-memory-degree/raw/rlinear_width10.json new file mode 100644 index 000000000..58a65af8b --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/rlinear_width10.json @@ -0,0 +1,14 @@ +{ + "width": 10, + "states": 16796, + "r_linear_D0_true": 7718, + "krylov_depth": 7478, + "arithmetic": "exact modulo the prime 2147483647", + "is_a_certified_lower_bound_on_the_rational_rank": true, + "seeds": [ + "blocks", + "singletons", + "wrap" + ], + "seconds": 947.3 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/rlinear_width8.json b/results/p593-width9-10-memory-degree/raw/rlinear_width8.json new file mode 100644 index 000000000..f582585df --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/rlinear_width8.json @@ -0,0 +1,14 @@ +{ + "width": 8, + "states": 1430, + "r_linear_D0_true": 689, + "krylov_depth": 621, + "arithmetic": "exact modulo the prime 2147483647", + "is_a_certified_lower_bound_on_the_rational_rank": true, + "seeds": [ + "blocks", + "singletons", + "wrap" + ], + "seconds": 0.9 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/rlinear_width9.json b/results/p593-width9-10-memory-degree/raw/rlinear_width9.json new file mode 100644 index 000000000..05019d378 --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/rlinear_width9.json @@ -0,0 +1,14 @@ +{ + "width": 9, + "states": 4862, + "r_linear_D0_true": 2275, + "krylov_depth": 2152, + "arithmetic": "exact modulo the prime 2147483647", + "is_a_certified_lower_bound_on_the_rational_rank": true, + "seeds": [ + "blocks", + "singletons", + "wrap" + ], + "seconds": 22.6 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/transport_width10.json b/results/p593-width9-10-memory-degree/raw/transport_width10.json new file mode 100644 index 000000000..b01acda80 --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/transport_width10.json @@ -0,0 +1,142 @@ +{ + "width": 10, + "states": 16796, + "injected_r_linear": { + "D0_additive_local_counts": 7718, + "D1_plus_size_and_extent": 150, + "D2_plus_nonlocal_topology": 150 + }, + "rank_notions": { + "D0_additive_local_counts": { + "r_linear": 7718, + "r_positive_baseline_lumping": 8524, + "r_positive_whole_affine_family": 8524, + "r_transport": 6 + }, + "D1_plus_size_and_extent": { + "r_linear": 150, + "r_positive_baseline_lumping": 8524, + "r_positive_whole_affine_family": 8524, + "r_transport": 8 + }, + "D2_plus_nonlocal_topology": { + "r_linear": 150, + "r_positive_baseline_lumping": 8524, + "r_positive_whole_affine_family": 8524, + "r_transport": null + } + }, + "spans": [ + { + "family": "krylov", + "requested_rank": 3, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.608172110406696, + "transported_at_eta_zero": 0.6340366978363278, + "T_intervention_excess": 0.01678656547627866 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.50616393276274, + "transported_at_eta_zero": 0.5750316169090552, + "T_intervention_excess": 0.005384592959246648 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.5628685131357593, + "transported_at_eta_zero": 0.6552792122682068, + "T_intervention_excess": -0.0015684948032091972 + } + } + }, + { + "family": "krylov", + "requested_rank": 4, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.1287591424439803, + "transported_at_eta_zero": 0.1657754821356259, + "T_intervention_excess": 0.010219119446679109 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.3089955058185477, + "transported_at_eta_zero": 0.39204473098232506, + "T_intervention_excess": 0.012550939788459059 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.4909350718170601, + "transported_at_eta_zero": 0.5839858458849039, + "T_intervention_excess": 0.0024724012137592455 + } + } + }, + { + "family": "krylov", + "requested_rank": 6, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.09691310140525343, + "transported_at_eta_zero": 0.14715369863778516, + "T_intervention_excess": 0.0126393348848583 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.13846454448550277, + "transported_at_eta_zero": 0.23958925237323678, + "T_intervention_excess": 0.024325157225849298 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.23499611071607687, + "transported_at_eta_zero": 0.4058953324612796, + "T_intervention_excess": 0.03426907913324767 + } + } + }, + { + "family": "krylov", + "requested_rank": 8, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.026593079498546394, + "transported_at_eta_zero": 0.05101964939519977, + "T_intervention_excess": 0.014283511970418543 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.09686808721193556, + "transported_at_eta_zero": 0.1665807874902764, + "T_intervention_excess": 0.014944325718824286 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.14196470123485935, + "transported_at_eta_zero": 0.26945669033199743, + "T_intervention_excess": 0.04018770867144339 + } + } + }, + { + "family": "krylov", + "requested_rank": 12, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.006031342899477588, + "transported_at_eta_zero": 0.010050326333450339, + "T_intervention_excess": 0.021817194151687116 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.11508197908072317, + "transported_at_eta_zero": 0.14007201476783387, + "T_intervention_excess": 0.06146386421370231 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.17642172157614414, + "transported_at_eta_zero": 0.2256139128385822, + "T_intervention_excess": 0.1519355951182452 + } + } + } + ], + "seconds": 1154.4 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/transport_width6.json b/results/p593-width9-10-memory-degree/raw/transport_width6.json new file mode 100644 index 000000000..e984f257c --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/transport_width6.json @@ -0,0 +1,142 @@ +{ + "width": 6, + "states": 132, + "injected_r_linear": { + "D0_additive_local_counts": 72, + "D1_plus_size_and_extent": 76, + "D2_plus_nonlocal_topology": 76 + }, + "rank_notions": { + "D0_additive_local_counts": { + "r_linear": 72, + "r_positive_baseline_lumping": 76, + "r_positive_whole_affine_family": 76, + "r_transport": 6 + }, + "D1_plus_size_and_extent": { + "r_linear": 76, + "r_positive_baseline_lumping": 76, + "r_positive_whole_affine_family": 76, + "r_transport": 6 + }, + "D2_plus_nonlocal_topology": { + "r_linear": 76, + "r_positive_baseline_lumping": 76, + "r_positive_whole_affine_family": 76, + "r_transport": 8 + } + }, + "spans": [ + { + "family": "krylov", + "requested_rank": 3, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.5401436976590467, + "transported_at_eta_zero": 0.5555998169963294, + "T_intervention_excess": 0.01729162528288153 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.4486071304124557, + "transported_at_eta_zero": 0.4754840943945196, + "T_intervention_excess": 0.010855625784874146 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.5315237812378499, + "transported_at_eta_zero": 0.5672806905971421, + "T_intervention_excess": 0.00212897172623705 + } + } + }, + { + "family": "krylov", + "requested_rank": 4, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.10439064658844115, + "transported_at_eta_zero": 0.11932777094401563, + "T_intervention_excess": 0.01249802393496259 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.1963498771481073, + "transported_at_eta_zero": 0.2358119954168219, + "T_intervention_excess": 0.007640755817675038 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.44099461212241453, + "transported_at_eta_zero": 0.4825459132560888, + "T_intervention_excess": 0.013172235412415856 + } + } + }, + { + "family": "krylov", + "requested_rank": 6, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.07645874301236237, + "transported_at_eta_zero": 0.10519407823868203, + "T_intervention_excess": 0.009567426430641235 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.09492105975865933, + "transported_at_eta_zero": 0.1320165262214978, + "T_intervention_excess": 0.011548803765926985 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.15581847095157694, + "transported_at_eta_zero": 0.24130964013611314, + "T_intervention_excess": 0.005800858215867177 + } + } + }, + { + "family": "krylov", + "requested_rank": 8, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.01498558105663083, + "transported_at_eta_zero": 0.0252744786798128, + "T_intervention_excess": 0.00995916477718644 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.04555785720611565, + "transported_at_eta_zero": 0.06753794906075598, + "T_intervention_excess": 0.007039103146658135 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.06949646101555752, + "transported_at_eta_zero": 0.1073669112857428, + "T_intervention_excess": 0.024837174474281715 + } + } + }, + { + "family": "krylov", + "requested_rank": 12, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.003861278946507206, + "transported_at_eta_zero": 0.004553693901963702, + "T_intervention_excess": 0.011484066889230985 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.03275766291256662, + "transported_at_eta_zero": 0.03759721643270482, + "T_intervention_excess": 0.02003424302964827 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.06610088118218375, + "transported_at_eta_zero": 0.0887088486996083, + "T_intervention_excess": 0.03108429406918245 + } + } + } + ], + "seconds": 0.9 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/transport_width9.json b/results/p593-width9-10-memory-degree/raw/transport_width9.json new file mode 100644 index 000000000..a3068a99e --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/transport_width9.json @@ -0,0 +1,142 @@ +{ + "width": 9, + "states": 4862, + "injected_r_linear": { + "D0_additive_local_counts": 2275, + "D1_plus_size_and_extent": 150, + "D2_plus_nonlocal_topology": 150 + }, + "rank_notions": { + "D0_additive_local_counts": { + "r_linear": 2275, + "r_positive_baseline_lumping": 2494, + "r_positive_whole_affine_family": 2494, + "r_transport": 6 + }, + "D1_plus_size_and_extent": { + "r_linear": 150, + "r_positive_baseline_lumping": 2494, + "r_positive_whole_affine_family": 2494, + "r_transport": 8 + }, + "D2_plus_nonlocal_topology": { + "r_linear": 150, + "r_positive_baseline_lumping": 4862, + "r_positive_whole_affine_family": 4862, + "r_transport": null + } + }, + "spans": [ + { + "family": "krylov", + "requested_rank": 3, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.5973707797857484, + "transported_at_eta_zero": 0.621337526737784, + "T_intervention_excess": 0.017043964489274477 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.4950474636222203, + "transported_at_eta_zero": 0.5543170792916216, + "T_intervention_excess": 0.007239321853544034 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.5528584233756427, + "transported_at_eta_zero": 0.6373701561763412, + "T_intervention_excess": -0.001623561230552073 + } + } + }, + { + "family": "krylov", + "requested_rank": 4, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.12482840314063745, + "transported_at_eta_zero": 0.1577817824926286, + "T_intervention_excess": 0.010492673618877957 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.2877921664089077, + "transported_at_eta_zero": 0.36114902317160097, + "T_intervention_excess": 0.011771539283902399 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.4799597601314727, + "transported_at_eta_zero": 0.5658527334058067, + "T_intervention_excess": -0.0010975614446265824 + } + } + }, + { + "family": "krylov", + "requested_rank": 6, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.09369381655385102, + "transported_at_eta_zero": 0.13989262771617536, + "T_intervention_excess": 0.012093592666098774 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.12610898652167485, + "transported_at_eta_zero": 0.21202226700894547, + "T_intervention_excess": 0.021819251674909668 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.21464839400891653, + "transported_at_eta_zero": 0.37547725616935396, + "T_intervention_excess": 0.029221996767267222 + } + } + }, + { + "family": "krylov", + "requested_rank": 8, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.024622630108972796, + "transported_at_eta_zero": 0.046117817118862335, + "T_intervention_excess": 0.013703142830311925 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.08364814732765617, + "transported_at_eta_zero": 0.14144518474209122, + "T_intervention_excess": 0.012971283161558433 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.12218132294700834, + "transported_at_eta_zero": 0.23095979806988357, + "T_intervention_excess": 0.037233243830252255 + } + } + }, + { + "family": "krylov", + "requested_rank": 12, + "status": "scored", + "dictionary_scores": { + "D0_additive_local_counts": { + "R_baseline_representability": 0.005270012164385122, + "transported_at_eta_zero": 0.008353496909427004, + "T_intervention_excess": 0.019312081289652252 + }, + "D1_plus_size_and_extent": { + "R_baseline_representability": 0.0975870755097809, + "transported_at_eta_zero": 0.11607965026462386, + "T_intervention_excess": 0.05045264962976051 + }, + "D2_plus_nonlocal_topology": { + "R_baseline_representability": 0.15340270479285706, + "transported_at_eta_zero": 0.18670527214118127, + "T_intervention_excess": 0.12675968039766866 + } + } + } + ], + "seconds": 72.1 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/width10.json b/results/p593-width9-10-memory-degree/raw/width10.json new file mode 100644 index 000000000..29505d457 --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/width10.json @@ -0,0 +1,65 @@ +{ + "width": 10, + "states": 16796, + "eta": 0.0, + "frozen_rank": 6, + "rank_C": 3, + "C_singular_values": [ + 2.834761181192955, + 1.2847311331555546, + 0.8347210667398177, + 3.932306719833268e-15, + 1.157807736112455e-15, + 4.888097151552856e-16 + ], + "hankel_shape": [ + 48, + 48 + ], + "hankel_numerical_rank_tol_1e-6": 14, + "hankel_effective_orders": { + "0.99": 3, + "0.999": 4 + }, + "hankel_singular_values_normalized_top16": [ + 1.0, + 0.613081634938728, + 0.19229427566300747, + 0.07537851754400993, + 0.026679866176499322, + 0.005799917247095805, + 0.004404488328517693, + 0.0016625125502721721, + 0.0001674166074489364, + 0.00013057542812766363, + 8.98449000288506e-05, + 2.027389006593909e-05, + 6.555116976741865e-06, + 4.2528210622109516e-06, + 5.322253328267277e-07, + 2.1506844419441516e-07 + ], + "integrated_norm": 2.035947612490106, + "decay_time": 0.17168544555238685, + "tail_mass_fraction": 0.0014717596664607542, + "norm_profile": [ + 9.413347729117268, + 2.2316617711291005, + 0.7086754121522232, + 0.27104400253916583, + 0.11658971640238981, + 0.05403820490772454, + 0.02633121101444345, + 0.013316344838052465, + 0.006948440204660533, + 0.003732915507819333, + 0.0020634265297210627, + 0.0011727106674312097, + 0.0006840560485764976, + 0.0004083245170616995, + 0.0002484841478526716, + 0.00015355555568736612, + 9.601847975984749e-05 + ], + "seconds": 58.2 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/width4.json b/results/p593-width9-10-memory-degree/raw/width4.json new file mode 100644 index 000000000..cb989dd03 --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/width4.json @@ -0,0 +1,65 @@ +{ + "width": 4, + "states": 14, + "eta": 0.0, + "frozen_rank": 6, + "rank_C": 2, + "C_singular_values": [ + 1.8547236990991403, + 0.47140452079103173, + 3.828636070932868e-16, + 1.5317634126638508e-17, + 4.153009518009511e-18, + 7.765013568273543e-19 + ], + "hankel_shape": [ + 48, + 48 + ], + "hankel_numerical_rank_tol_1e-6": 4, + "hankel_effective_orders": { + "0.99": 2, + "0.999": 2 + }, + "hankel_singular_values_normalized_top16": [ + 1.0, + 0.11979696664223549, + 0.000317904334098518, + 3.906212872467249e-06, + 4.064361869949087e-15, + 1.2867424184165201e-15, + 6.590412063125736e-16, + 1.9904556809731097e-16, + 7.107842312074937e-17, + 4.4972870886789606e-17, + 3.2328743704316e-17, + 1.4079052884099626e-17, + 8.596469753818508e-18, + 2.976547185086757e-18, + 1.5016173669563742e-18, + 1.1430065918301306e-18 + ], + "integrated_norm": 0.8755423554689491, + "decay_time": 0.06256022083956449, + "tail_mass_fraction": 1.746212795678169e-06, + "norm_profile": [ + 5.46983828501332, + 0.6721940801245162, + 0.08301134331926055, + 0.010398145479388604, + 0.0013661829625562108, + 0.00021090380093372518, + 4.6477131272616525e-05, + 1.4400235466451607e-05, + 5.261565370196648e-06, + 2.0633132273224168e-06, + 8.365120373256373e-07, + 3.4465930581394857e-07, + 1.4311843523788646e-07, + 5.965278120902538e-08, + 2.4908580320692223e-08, + 1.0409842924160634e-08, + 4.352323720480706e-09 + ], + "seconds": 0.0 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/width5.json b/results/p593-width9-10-memory-degree/raw/width5.json new file mode 100644 index 000000000..31a944a48 --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/width5.json @@ -0,0 +1,65 @@ +{ + "width": 5, + "states": 42, + "eta": 0.0, + "frozen_rank": 6, + "rank_C": 3, + "C_singular_values": [ + 2.039517684942923, + 0.7677224781089095, + 0.6431020501550127, + 9.753341734302733e-16, + 3.0233534896518266e-16, + 3.4614308902082107e-17 + ], + "hankel_shape": [ + 48, + 48 + ], + "hankel_numerical_rank_tol_1e-6": 9, + "hankel_effective_orders": { + "0.99": 3, + "0.999": 3 + }, + "hankel_singular_values_normalized_top16": [ + 1.0, + 0.21082476994085994, + 0.17300147854276113, + 0.026242895313835796, + 0.0029044418288639343, + 0.0010704225856723603, + 0.00042252624553815545, + 7.64945499780871e-05, + 1.3244193125693935e-06, + 5.162685902350121e-09, + 1.4599861434500625e-11, + 7.941389129583201e-13, + 2.2333072161925814e-16, + 4.381440144733244e-17, + 3.527119048224823e-17, + 9.37747982829683e-18 + ], + "integrated_norm": 1.0161751569037099, + "decay_time": 0.0891146107407835, + "tail_mass_fraction": 3.6535160596980635e-05, + "norm_profile": [ + 5.805734371471218, + 0.9387160292311882, + 0.17651403066426563, + 0.03502717648217255, + 0.007986844568781496, + 0.0022863255985267643, + 0.0007913685794468059, + 0.0003024315278021023, + 0.00012146147367550875, + 5.0303435285526376e-05, + 2.130236189751336e-05, + 9.176667485670016e-06, + 4.006252522679543e-06, + 1.7674396111367738e-06, + 7.86240859753617e-07, + 3.520913145451225e-07, + 1.5852878795386881e-07 + ], + "seconds": 0.0 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/width6.json b/results/p593-width9-10-memory-degree/raw/width6.json new file mode 100644 index 000000000..73d4cf0de --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/width6.json @@ -0,0 +1,65 @@ +{ + "width": 6, + "states": 132, + "eta": 0.0, + "frozen_rank": 6, + "rank_C": 3, + "C_singular_values": [ + 2.472187536600852, + 1.082733786539637, + 0.7221001117771495, + 1.239011964685179e-15, + 5.251233741606645e-16, + 2.883950178804581e-17 + ], + "hankel_shape": [ + 48, + 48 + ], + "hankel_numerical_rank_tol_1e-6": 12, + "hankel_effective_orders": { + "0.99": 3, + "0.999": 4 + }, + "hankel_singular_values_normalized_top16": [ + 1.0, + 0.34148928038441695, + 0.24333180988893524, + 0.048892754583592435, + 0.014254275576243243, + 0.0015838409784496893, + 0.0015136549261150524, + 0.0003131367692466458, + 0.0001684797498326521, + 1.7534472694003116e-05, + 3.4655522733589487e-06, + 2.5258905065468706e-06, + 2.3592129388389735e-07, + 3.267797870046962e-08, + 1.3681611409362123e-08, + 1.947518535263716e-09 + ], + "integrated_norm": 1.2068261372354667, + "decay_time": 0.1048458783817175, + "tail_mass_fraction": 0.00014299160380378093, + "norm_profile": [ + 6.611917759554144, + 1.164371192983771, + 0.2607823901868055, + 0.06587722173723423, + 0.019114288612361408, + 0.006560176507421397, + 0.002588440398968269, + 0.0011115641947788293, + 0.0005002610479031261, + 0.00023153505546950483, + 0.00010918693251015164, + 5.219643005247503e-05, + 2.52134313393088e-05, + 1.2279566968935997e-05, + 6.0200488639547746e-06, + 2.9673678544533145e-06, + 1.469324984274615e-06 + ], + "seconds": 0.1 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/width7.json b/results/p593-width9-10-memory-degree/raw/width7.json new file mode 100644 index 000000000..492f08929 --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/width7.json @@ -0,0 +1,65 @@ +{ + "width": 7, + "states": 429, + "eta": 0.0, + "frozen_rank": 6, + "rank_C": 3, + "C_singular_values": [ + 2.6613633622661967, + 1.179594705169854, + 0.7678734463631551, + 1.2379815849313732e-15, + 3.025682368822674e-16, + 2.554734797122347e-16 + ], + "hankel_shape": [ + 48, + 48 + ], + "hankel_numerical_rank_tol_1e-6": 13, + "hankel_effective_orders": { + "0.99": 3, + "0.999": 4 + }, + "hankel_singular_values_normalized_top16": [ + 1.0, + 0.5372236606467883, + 0.24264536024409056, + 0.06346266986100137, + 0.02272022162338467, + 0.002720099725498624, + 0.0023893401960398287, + 0.0005003082938562496, + 0.00018070121239930086, + 2.6536237928820324e-05, + 1.5213856584976276e-05, + 4.549107130090464e-06, + 1.302085599475808e-06, + 1.7113902045469364e-07, + 2.4529541644769475e-08, + 1.779719750511184e-08 + ], + "integrated_norm": 1.4557096934448586, + "decay_time": 0.11923988027655967, + "tail_mass_fraction": 0.000320439679779071, + "norm_profile": [ + 7.673403240020177, + 1.4618914190664056, + 0.3604703527972633, + 0.10503040633027852, + 0.03498386740275846, + 0.013202901716194924, + 0.005550864793787842, + 0.0025313523041682684, + 0.0012202415328282927, + 0.0006099678207403326, + 0.0003122244574120024, + 0.0001623741968013605, + 8.538003604526516e-05, + 4.525583871872891e-05, + 2.4134270300519627e-05, + 1.2932513605433893e-05, + 6.9573840745018e-06 + ], + "seconds": 0.5 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/width8.json b/results/p593-width9-10-memory-degree/raw/width8.json new file mode 100644 index 000000000..744cc167c --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/width8.json @@ -0,0 +1,65 @@ +{ + "width": 8, + "states": 1430, + "eta": 0.0, + "frozen_rank": 6, + "rank_C": 3, + "C_singular_values": [ + 2.753391399493155, + 1.2302796006406913, + 0.7978245232238123, + 1.9099796755366214e-15, + 6.284570802383353e-16, + 2.1423058956396828e-16 + ], + "hankel_shape": [ + 48, + 48 + ], + "hankel_numerical_rank_tol_1e-6": 14, + "hankel_effective_orders": { + "0.99": 3, + "0.999": 4 + }, + "hankel_singular_values_normalized_top16": [ + 1.0, + 0.6155276142553271, + 0.22596783388017483, + 0.07060986776790966, + 0.025499365181532514, + 0.0038930194010915555, + 0.003201565714437322, + 0.0007123674383823971, + 0.0001727928482267698, + 3.766756512883004e-05, + 8.11816426231331e-06, + 7.754043231377986e-06, + 4.95127422648001e-06, + 1.4136691569010479e-06, + 1.430447309388397e-07, + 6.419761383973076e-08 + ], + "integrated_norm": 1.680598183239307, + "decay_time": 0.13628647414074094, + "tail_mass_fraction": 0.0005729228709705783, + "norm_profile": [ + 8.453983980008797, + 1.7636324058004622, + 0.4774126358528549, + 0.15457192102668155, + 0.0568477532198528, + 0.023043266184878824, + 0.010114017625586204, + 0.004748275020379985, + 0.0023581113555514407, + 0.0012245424625551178, + 0.000657420292617004, + 0.0003613917500601728, + 0.00020193507715905376, + 0.0001141150843065855, + 6.500045043861449e-05, + 3.723833327851261e-05, + 2.1426832333652238e-05 + ], + "seconds": 2.1 +} \ No newline at end of file diff --git a/results/p593-width9-10-memory-degree/raw/width9.json b/results/p593-width9-10-memory-degree/raw/width9.json new file mode 100644 index 000000000..0ae44175f --- /dev/null +++ b/results/p593-width9-10-memory-degree/raw/width9.json @@ -0,0 +1,65 @@ +{ + "width": 9, + "states": 4862, + "eta": 0.0, + "frozen_rank": 6, + "rank_C": 3, + "C_singular_values": [ + 2.804104151614711, + 1.2623615578355816, + 0.8189762725548559, + 1.7766795901751622e-15, + 4.577917433465562e-16, + 1.1188122079348455e-16 + ], + "hankel_shape": [ + 48, + 48 + ], + "hankel_numerical_rank_tol_1e-6": 14, + "hankel_effective_orders": { + "0.99": 3, + "0.999": 4 + }, + "hankel_singular_values_normalized_top16": [ + 1.0, + 0.6234218318692114, + 0.20732983815084563, + 0.07359712921104963, + 0.026239983018199426, + 0.004918400638347857, + 0.003868728664545136, + 0.0010604961027433973, + 0.00016838149979062986, + 6.537367538115881e-05, + 5.658996223616169e-05, + 1.3413622557815745e-05, + 4.0193658323183655e-06, + 1.5553863806790347e-06, + 6.523883772092907e-07, + 1.353334390172139e-07 + ], + "integrated_norm": 1.8725332509906851, + "decay_time": 0.1540658279230672, + "tail_mass_fraction": 0.0009338945667941257, + "norm_profile": [ + 9.007253501996335, + 2.022172714002633, + 0.5972144063944418, + 0.21156777202255225, + 0.08461097754601501, + 0.03673375462555231, + 0.016935069763119433, + 0.008201166965989498, + 0.004150794254607837, + 0.0021880241921273984, + 0.0011960824245121275, + 0.0006741516223601211, + 0.00038926724882161983, + 0.00022888060072878637, + 0.00013635847396969127, + 8.200599627922463e-05, + 4.9653661726557014e-05 + ], + "seconds": 8.1 +} \ No newline at end of file diff --git a/scripts/p593_noncrossing_fast.py b/scripts/p593_noncrossing_fast.py new file mode 100644 index 000000000..d8846263d --- /dev/null +++ b/scripts/p593_noncrossing_fast.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python3 +"""Issue #593 Phase B infrastructure: arbitrary-width noncrossing states and a +Generator-compatible shim. + +The repository's ``Generator`` caps at width 8. This module reproduces the +same object for widths 9 and 10: + +- ``noncrossing_states_fast`` enumerates canonical noncrossing RGS by interval + recursion (the block containing the left endpoint picks an arbitrary subset, + every gap is an independent noncrossing partition). At widths 1..8 it must + equal the codec's enumeration exactly -- order included -- and that equality + is re-checked at import time of the validation entry point. +- ``WideGenerator`` duck-types ``p398_intervention_transport.Generator`` so the + repository's own frozen-span, memory-kernel, lumping and transport-scoring + code paths run unchanged at widths 9 and 10. No frozen convention is + substituted: the moves, rate families, readouts, spans and grids are the + repository's own code. +""" + +from __future__ import annotations + +from functools import lru_cache +from itertools import product +from typing import Dict, List, Optional, Sequence, Tuple + +from noncrossing_connectivity_codec import canonical_rgs +from planar_state_operations import detach_rgs, join_cyclic_adjacent_rgs + +OPERATIONS: Tuple[str, ...] = ("join", "detach") + + +@lru_cache(maxsize=None) +def _interval_partitions(i: int, j: int) -> Tuple[Tuple[Tuple[int, ...], ...], ...]: + """Noncrossing partitions of the contiguous points ``i..j``.""" + + if i > j: + return ((),) + out: List[Tuple[Tuple[int, ...], ...]] = [] + n = j - i + for mask in range(1 << n): + subset = [i + 1 + k for k in range(n) if (mask >> k) & 1] + gaps: List[Tuple[int, int]] = [] + previous = i + for s in subset: + gaps.append((previous + 1, s - 1)) + previous = s + gaps.append((previous + 1, j)) + head = (i,) + tuple(subset) + for combo in product(*(_interval_partitions(a, b) for a, b in gaps)): + blocks = [head] + for part in combo: + blocks.extend(part) + out.append(tuple(sorted(blocks))) + return tuple(out) + + +def noncrossing_states_fast(width: int) -> Tuple[Tuple[int, ...], ...]: + """Canonical noncrossing RGS in lexicographic order, any width.""" + + if width <= 0: + raise ValueError("width must be positive") + states = set() + for partition in _interval_partitions(0, width - 1): + labels = [0] * width + for block_index, block in enumerate(partition): + for point in block: + labels[point] = block_index + states.add(canonical_rgs(labels)) + return tuple(sorted(states)) + + +class WideGenerator: + """Interface-compatible with ``p398_intervention_transport.Generator``.""" + + def __init__(self, width: int, states: Sequence[Tuple[int, ...]]) -> None: + self.width = width + self.states = tuple(states) + self.size = len(self.states) + rank = {state: index for index, state in enumerate(self.states)} + target: Dict[Tuple[str, int], List[Optional[int]]] = {} + for point in range(width): + for operation, implementation in ( + ("join", join_cyclic_adjacent_rgs), + ("detach", detach_rgs), + ): + column: List[Optional[int]] = [] + for source, state in enumerate(self.states): + image = rank[implementation(state, point)] + column.append(None if image == source else image) + target[(operation, point)] = column + self.target = target + self.moves: Tuple[Tuple[str, int], ...] = tuple( + (operation, point) for point in range(width) for operation in OPERATIONS + ) + + # -- rate vectors (identical semantics to the repository's Generator) -- + + def baseline_rates(self) -> Dict[Tuple[str, int], float]: + return {move: 1.0 for move in self.moves} + + def rates(self, intervention: str, eta: float) -> Dict[Tuple[str, int], float]: + from p398_intervention_transport import INTERVENTIONS + + coefficient = INTERVENTIONS[intervention] + return { + (operation, point): 1.0 + eta * coefficient(operation, point, self.width) + for operation, point in self.moves + } + + def coefficients(self, intervention: str) -> Dict[Tuple[str, int], float]: + from p398_intervention_transport import INTERVENTIONS + + coefficient = INTERVENTIONS[intervention] + return { + (operation, point): coefficient(operation, point, self.width) + for operation, point in self.moves + } + + def exact_rates(self, intervention: str, eta) -> Dict[Tuple[str, int], float]: + from fractions import Fraction + from p398_intervention_transport import INTERVENTIONS + + coefficient = INTERVENTIONS[intervention] + return { + (operation, point): Fraction(1) + eta * Fraction( + coefficient(operation, point, self.width) + ).limit_denominator(10**6) + for operation, point in self.moves + } + + def exact_entry(self, rates, source: int, destination: int): + from fractions import Fraction + + value = Fraction(0) + for move, rate in rates.items(): + image = self.target[move][source] + if image is None: + continue + if image == destination: + value += rate + if source == destination: + value -= rate + return value + + def exit_rate(self, rates) -> float: + best = 0.0 + for source in range(self.size): + total = 0.0 + for move, rate in rates.items(): + if self.target[move][source] is not None: + total += rate + best = max(best, total) + return best + + # -- float sparse forms ------------------------------------------------- + + def rows(self, rates) -> List[List[Tuple[int, float]]]: + out: List[List[Tuple[int, float]]] = [] + for source in range(self.size): + entries: Dict[int, float] = {} + diagonal = 0.0 + for move, rate in rates.items(): + image = self.target[move][source] + if image is None or rate == 0.0: + continue + entries[image] = entries.get(image, 0.0) + rate + diagonal -= rate + entries[source] = entries.get(source, 0.0) + diagonal + out.append(sorted(entries.items())) + return out + + def columns(self, rates) -> List[List[Tuple[int, float]]]: + gathered: List[Dict[int, float]] = [dict() for _ in range(self.size)] + for source, row in enumerate(self.rows(rates)): + for destination, value in row: + gathered[destination][source] = ( + gathered[destination].get(source, 0.0) + value + ) + return [sorted(column.items()) for column in gathered] + + def tangent_rows(self, intervention: str) -> List[List[Tuple[int, float]]]: + return self.rows(self.coefficients(intervention)) + + +def validate_shim(maximum_width: int = 8) -> dict: + """Exact equality of the shim against the repository, widths 1..8.""" + + import json + import hashlib + import sys + from pathlib import Path + + sys.path.insert(0, str(Path(__file__).resolve().parent)) + from noncrossing_connectivity_codec import noncrossing_states + from p398_intervention_transport import Generator + + report = [] + for width in range(1, maximum_width + 1): + mine = noncrossing_states_fast(width) + theirs = noncrossing_states(width) + assert mine == theirs, f"state enumeration disagrees at width {width}" + shim = WideGenerator(width, mine) + reference = Generator(width) + assert shim.target == reference.target, f"targets disagree at width {width}" + assert shim.rows(shim.baseline_rates()) == reference.rows( + reference.baseline_rates() + ), f"baseline rows disagree at width {width}" + report.append({"width": width, "states": len(mine), "exact_match": True}) + + # transition-table control: the repository's own builder must reproduce + from planar_transition_table import build_result + + table = build_result(maximum_width) + return { + "shim_validation": report, + "transition_table_sha256": table["totals"]["canonical_jsonl_sha256"], + "transition_table_maximum_width": maximum_width, + } + + +if __name__ == "__main__": + import json + + print(json.dumps(validate_shim(8), indent=2)) diff --git a/scripts/p593_phaseB_controls.py b/scripts/p593_phaseB_controls.py new file mode 100644 index 000000000..b2e7f3c52 --- /dev/null +++ b/scripts/p593_phaseB_controls.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +"""Issue #593 Phase B controls. Non-negotiable checks from the ticket: + +1. transition-table content hash widths 1-8 (repository's own builder); +2. exact row sums zero, rate positivity for |eta| <= 1, strong connectivity; +3. exp(tG) 1 = 1 to machine precision (uniformization evolution); +4. uniformization against an independent dense Taylor exponential at width 5; +5. full-rank projection gives K identically zero and a generator-closed Krylov + span gives K = 0 to 1e-8 relative (repository's ``exact_controls``); +6. resolvent Schur identity at width 5 (repository's ``exact_controls``). +""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path + +import numpy as np + +sys.path.insert(0, str(Path(__file__).resolve().parent)) + +from p593_noncrossing_fast import WideGenerator, noncrossing_states_fast, validate_shim +from p398_intervention_transport import ( + Generator, + evolve_observables, +) +from p398_projected_memory import KERNEL_GRID, exact_controls + +OUTPUT = Path(__file__).resolve().parents[1] / "results" / "p593-width9-10-memory-degree" / "raw" + + +def chain_controls(generator, eta_values=(-0.5, -0.25, 0.0, 0.25, 0.5, 1.0)): + size = generator.size + worst_row_sum = 0.0 + min_rate = float("inf") + for eta in eta_values: + for intervention in ("uniform_join_minus_detach", "uniform_detach_only", "single_point_join"): + rates = generator.rates(intervention, eta) + min_rate = min(min_rate, min(rates.values())) + rows = generator.rows(rates) + for row in rows: + worst_row_sum = max(worst_row_sum, abs(sum(v for _, v in row))) + # strong connectivity of the transition graph (any rate > 0 edges) + rates = generator.baseline_rates() + adjacency = [[] for _ in range(size)] + for source in range(size): + for move, rate in rates.items(): + image = generator.target[move][source] + if image is not None and rate > 0: + adjacency[source].append(image) + seen = {0} + stack = [0] + while stack: + node = stack.pop() + for nxt in adjacency[node]: + if nxt not in seen: + seen.add(nxt) + stack.append(nxt) + return { + "worst_abs_row_sum": worst_row_sum, + "min_rate_over_declared_etas": min_rate, + "strongly_connected": len(seen) == size, + } + + +def exp_constant_control(generator): + rates = generator.baseline_rates() + rows = generator.rows(rates) + rate = generator.exit_rate(rates) + constant = [[1.0] * generator.size] + evolved = evolve_observables(rows, generator.size, rate, constant, list(KERNEL_GRID)) + worst = max(abs(value - 1.0) for block in evolved for value in block[0]) + return worst + + +def uniformization_versus_taylor(width=5): + """exp(tG) f by uniformization against a dense Taylor/scipy exponential.""" + import scipy.linalg + + generator = Generator(width) + size = generator.size + rates = generator.baseline_rates() + rows = generator.rows(rates) + rate = generator.exit_rate(rates) + dense = np.zeros((size, size)) + for source, row in enumerate(rows): + for destination, value in row: + dense[source, destination] = value + observables = [[1.0 if abs(s[0] - s[-1]) == 0 else 0.0 for s in generator.states]] + worst = 0.0 + for t in (0.25, 1.0, 2.0): + exact = scipy.linalg.expm(t * dense) @ np.array(observables[0]) + evolved = evolve_observables(rows, size, rate, observables, [t]) + worst = max(worst, float(np.max(np.abs(exact - np.array(evolved[0][0]))))) + return worst + + +def main() -> None: + OUTPUT.mkdir(parents=True, exist_ok=True) + result = {} + result["control_1_transition_table"] = validate_shim(8) + widths = {} + for width in (4, 6, 8, 9, 10): + generator = WideGenerator(width, noncrossing_states_fast(width)) + widths[str(width)] = chain_controls(generator) + result["control_2_chain_structure"] = widths + result["control_3_exp_tG_one"] = { + str(w): exp_constant_control(WideGenerator(w, noncrossing_states_fast(w))) + for w in (4, 8, 10) + } + result["control_4_uniformization_vs_taylor_width5"] = uniformization_versus_taylor(5) + result["controls_5_6_exact_width4"] = exact_controls(4) + result["controls_5_6_exact_width5"] = exact_controls(5) + path = OUTPUT / "controls.json" + path.write_text(json.dumps(result, indent=2, default=str)) + print(json.dumps(result, indent=2, default=str)[:3000]) + + +if __name__ == "__main__": + main() diff --git a/scripts/p593_phaseB_memory.py b/scripts/p593_phaseB_memory.py new file mode 100644 index 000000000..ac3ed530b --- /dev/null +++ b/scripts/p593_phaseB_memory.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +"""Issue #593 Phase B Deliverable 1: projected memory degree, widths 4-10. + +Frozen configuration is the repository's own code end to end +(``frozen_span``, ``memory_kernel``, ``kernel_statistics``, ``block_hankel`` +from ``p398_projected_memory``), applied to a width-9/10 generator shim that +is bit-exact against the repository at widths 1..8. Everything is at +``eta = 0`` on the declared kernel grid ``t = 0, 0.25, ..., 4.0``. + +One deliberate departure, declared on the ticket: singular values of the +block Hankel matrix come from a true SVD (numpy) instead of the +eigendecomposition of ``H^T H``, exactly as the ticket asks. +""" + +from __future__ import annotations + +import json +import sys +import time +from pathlib import Path + +import numpy as np + +sys.path.insert(0, str(Path(__file__).resolve().parent)) + +from p593_noncrossing_fast import WideGenerator, noncrossing_states_fast +from p398_projected_memory import ( + KERNEL_GRID, + block_hankel, + frozen_span, + kernel_statistics, + memory_kernel, + unresolved_columns, +) + +OUTPUT = Path(__file__).resolve().parents[1] / "results" / "p593-width9-10-memory-degree" / "raw" + + +def analyse(width: int) -> dict: + start = time.time() + generator = WideGenerator(width, noncrossing_states_fast(width)) + size = generator.size + rates = generator.baseline_rates() + rows = generator.rows(rates) + rate = generator.exit_rate(rates) + + basis = frozen_span(generator, rows) + kernels = memory_kernel(basis, rows, size, rate, KERNEL_GRID) + stats = kernel_statistics(kernels, KERNEL_GRID) + + # rank C from a true SVD of the coupling matrix C = Q G Phi + columns = unresolved_columns(basis, rows) + c_matrix = np.array(columns, dtype=float) + c_singular = np.linalg.svd(c_matrix, compute_uv=False) + c_rank = int(sum(1 for v in c_singular if v > 1e-10 * c_singular[0])) + + # block Hankel from samples 1..16 (drops t=0), 8x8 blocks of size 6, true SVD + hankel = np.array(block_hankel(kernels), dtype=float) + singular = np.linalg.svd(hankel, compute_uv=False) + largest = float(singular[0]) + numerical_rank = int(sum(1 for v in singular if v > 1e-6 * largest)) + total = float(np.sum(singular**2)) + effective = {} + for level in (0.99, 0.999): + running, count = 0.0, 0 + for value in singular: + running += value * value + count += 1 + if running >= level * total: + break + effective[f"{level:g}"] = count + + return { + "width": width, + "states": size, + "eta": 0.0, + "frozen_rank": len(basis), + "rank_C": c_rank, + "C_singular_values": [float(v) for v in c_singular], + "hankel_shape": list(hankel.shape), + "hankel_numerical_rank_tol_1e-6": numerical_rank, + "hankel_effective_orders": effective, + "hankel_singular_values_normalized_top16": [ + float(v / largest) for v in singular[:16] + ], + "integrated_norm": stats["integrated_weight"], + "decay_time": stats["decay_time"], + "tail_mass_fraction": stats["tail_mass_fraction"], + "norm_profile": stats["norm_profile"], + "seconds": round(time.time() - start, 1), + } + + +def main() -> None: + OUTPUT.mkdir(parents=True, exist_ok=True) + widths = [int(a) for a in sys.argv[1:]] or [4, 5, 6, 7, 8, 9, 10] + for width in widths: + result = analyse(width) + path = OUTPUT / f"width{width}.json" + path.write_text(json.dumps(result, indent=2)) + print( + json.dumps( + { + "width": width, + "rank_C": result["rank_C"], + "hankel_rank": result["hankel_numerical_rank_tol_1e-6"], + "orders": result["hankel_effective_orders"], + "integrated": result["integrated_norm"], + "decay": result["decay_time"], + "tail": result["tail_mass_fraction"], + "seconds": result["seconds"], + } + ), + flush=True, + ) + + +if __name__ == "__main__": + main() diff --git a/scripts/p593_phaseB_rlinear_true.py b/scripts/p593_phaseB_rlinear_true.py new file mode 100644 index 000000000..f5d5603e2 --- /dev/null +++ b/scripts/p593_phaseB_rlinear_true.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +"""Issue #593 Phase B Deliverable 2 (r_linear): true ``dim span{G0^k f}`` at +widths 8, 9, 10 by exact elimination over the prime 2147483647. + +Same mathematics as the repository's ``observable_reachable_dimension`` +(block Arnoldi with deflation, integer arithmetic mod the Mersenne prime), +with the echelon stored as numpy int64 rows so width 10 is affordable. The +Krylov depth runs until the dimension is unchanged for 3 consecutive levels, +which is the same saturation criterion the repository's frontier loop uses. +""" + +from __future__ import annotations + +import json +import sys +import time +from pathlib import Path + +import numpy as np +import scipy.sparse as sp + +sys.path.insert(0, str(Path(__file__).resolve().parent)) + +from p593_noncrossing_fast import WideGenerator, noncrossing_states_fast + +P = 2147483647 +OUTPUT = Path(__file__).resolve().parents[1] / "results" / "p593-width9-10-memory-degree" / "raw" + + +def _blocks(state): + out = {} + for point, label in enumerate(state): + out.setdefault(label, []).append(point) + return out.values() + + +def observable_vectors(states): + size = len(states) + blocks = [max(s) + 1 for s in states] + singletons = [sum(1 for b in _blocks(s) if len(b) == 1) for s in states] + wrap = [1 if s[0] == s[-1] else 0 for s in states] + one = [1] * size + return one, [blocks, singletons, wrap] + + +def sparse_mod_matrix(generator): + """G0 as a scipy sparse int64 matrix acting on functions (row = source).""" + data, indices, indptr = [0], [0], [0] + rows = generator.rows(generator.baseline_rates()) + for row in rows: + for column, value in row: + indices.append(column) + data.append(int(round(value)) % P) + indptr.append(len(indices)) + return sp.csr_matrix( + (np.array(data, dtype=np.int64), np.array(indices, dtype=np.int64), + np.array(indptr, dtype=np.int64)), + shape=(generator.size, generator.size), + ) + + +def krylov_dimension_numpy(sparse, size, seeds, max_depth=100000, budget=None): + """dim span{G^k f} mod p; numpy echelon, frontier loop, 3-plateau stop.""" + + limit = size if budget is None else min(budget, size) + + def matvec(vec): + return sparse.dot(vec) % P + + pivots = {} # pivot column -> numpy int64 vector (row echelon, not reduced) + + def insert(vec): + working = np.array(vec, dtype=np.int64) + for col in sorted(pivots): + f = int(working[col]) + if f: + working = (working - f * pivots[col]) % P + nz = np.nonzero(working)[0] + if nz.size == 0: + return False + col = int(nz[0]) + inv = pow(int(working[col]), P - 2, P) + pivots[col] = (working * inv) % P + return True + + frontier = [np.array([int(x) % P for x in v], dtype=np.int64) for v in seeds] + history = [] + while frontier: + added = [] + for v in frontier: + if len(pivots) >= limit: + break + if insert(v): + added.append(v) + history.append(len(pivots)) + if not added or len(pivots) >= limit: + break + frontier = [matvec(v) for v in added] + if len(history) >= 3 and history[-1] == history[-2] == history[-3]: + break + return len(pivots), len(history) + + +def main() -> None: + OUTPUT.mkdir(parents=True, exist_ok=True) + widths = [int(a) for a in sys.argv[1:]] or [8, 9, 10] + for width in widths: + start = time.time() + generator = WideGenerator(width, noncrossing_states_fast(width)) + sparse = sparse_mod_matrix(generator) + one, seeds = observable_vectors(generator.states) + dim, depth = krylov_dimension_numpy(sparse, generator.size, seeds) + result = { + "width": width, + "states": generator.size, + "r_linear_D0_true": dim, + "krylov_depth": depth, + "arithmetic": "exact modulo the prime 2147483647", + "is_a_certified_lower_bound_on_the_rational_rank": True, + "seeds": ["blocks", "singletons", "wrap"], + "seconds": round(time.time() - start, 1), + } + (OUTPUT / f"rlinear_width{width}.json").write_text(json.dumps(result, indent=2)) + print(json.dumps(result), flush=True) + + +if __name__ == "__main__": + main() diff --git a/scripts/p593_phaseB_transport.py b/scripts/p593_phaseB_transport.py new file mode 100644 index 000000000..79a98c99b --- /dev/null +++ b/scripts/p593_phaseB_transport.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python3 +"""Issue #593 Phase B Deliverables 2 and 3 at widths 9 and 10. + +Runs the repository's own ``width_experiment`` transport-scoring pipeline on a +generator shim that is bit-exact against the repository at widths 1..8, so the +frozen configuration (seeds, span ladder, lag grid, thresholds) is the +repository's code, not a reimplementation. + +One substitution, declared: ``r_linear`` at widths 9/10 is computed at full +budget by ``p593_phaseB_rlinear_true`` (exact mod-p elimination, numpy +echelon) and injected into the repository's rank cache; D1/D2 stay +budget-truncated at 150 exactly as the repository does at width 8. + +Deliverable 3 (out-of-pencil lumping collapse) is computed here for widths +4..10 with the repository's ``exact_lumping`` against the baseline generator +plus the ``single_point_join`` tilt. +""" + +from __future__ import annotations + +import json +import sys +import time +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parent)) + +import p398_intervention_transport as pit +from p593_noncrossing_fast import WideGenerator, noncrossing_states_fast +from p593_phaseB_rlinear_true import krylov_dimension_numpy, sparse_mod_matrix + +OUTPUT = Path(__file__).resolve().parents[1] / "results" / "p593-width9-10-memory-degree" / "raw" + +DICTIONARY_SEEDS = { + "D0_additive_local_counts": ("blocks", "singletons", "wrap"), + "D1_plus_size_and_extent": ( + "blocks", "singletons", "wrap", "max_block", "linked_pairs", "boundary_span", + ), + "D2_plus_nonlocal_topology": ( + "blocks", "singletons", "wrap", "max_block", "linked_pairs", + "boundary_span", "halves_linked", "covering_depth", + ), +} + + +def observable_vector(states, name): + size = len(states) + if name == "one": + return [1] * size + if name == "blocks": + return [max(s) + 1 for s in states] + if name == "wrap": + return [1 if s[0] == s[-1] else 0 for s in states] + if name == "singletons": + return [sum(1 for b in _blocks(s) if len(b) == 1) for s in states] + if name == "max_block": + return [max(len(b) for b in _blocks(s)) for s in states] + if name == "linked_pairs": + return [sum(len(b) * (len(b) - 1) // 2 for b in _blocks(s)) for s in states] + if name == "boundary_span": + return [sum(max(b) - min(b) for b in _blocks(s)) for s in states] + if name == "halves_linked": + half = len(states[0]) // 2 + return [ + 1 if any( + any(p < half for p in b) and any(p >= half for p in b) for b in _blocks(s) + ) else 0 + for s in states + ] + if name == "covering_depth": + out = [] + for s in states: + blocks = [sorted(b) for b in _blocks(s)] + best = 0 + for point in range(len(s)): + depth = sum(1 for b in blocks if b[0] < point < b[-1] and point not in b) + best = max(best, depth) + out.append(best) + return out + raise KeyError(name) + + +def _blocks(state): + out = {} + for point, label in enumerate(state): + out.setdefault(label, []).append(point) + return out.values() + + +def prepopulate_linear_cache(generator, budget=None): + """Fill the repository's rank cache with true D0 and capped D1/D2 values.""" + budget = budget if budget is not None else pit.linear_rank_budget(generator.size) + sparse = sparse_mod_matrix(generator) + injected = {} + for name, members in DICTIONARY_SEEDS.items(): + vectors = [observable_vector(generator.states, member) for member in members] + cap = generator.size if name == "D0_additive_local_counts" else budget + dim, depth = krylov_dimension_numpy(sparse, generator.size, vectors, budget=cap) + key = (generator.width, name, budget) + pit._LINEAR_RANK_CACHE[key] = { + "dimension": dim, + "arithmetic": f"exact modulo the prime {pit.RANK_PRIME}", + "budget": cap, + "reached_the_whole_state_space": dim >= generator.size, + "limited_by_budget": dim >= cap and cap < generator.size, + "is_a_certified_lower_bound_on_the_rational_rank": True, + } + injected[name] = dim + return injected + + +def lumping_checks(generator): + baseline = generator.baseline_rates() + colour = [ + tuple( + observable_vector(generator.states, member)[state] + for member in DICTIONARY_SEEDS["D0_additive_local_counts"] + ) + for state in range(generator.size) + ] + joint = pit.exact_lumping(generator, colour, [baseline, generator.coefficients("uniform_join_minus_detach")]) + baseline_only = pit.exact_lumping(generator, colour, [baseline]) + out_of_pencil = pit.exact_lumping( + generator, colour, [baseline, generator.coefficients("single_point_join")] + ) + return { + "r_positive_baseline_lumping": baseline_only["blocks"], + "r_positive_whole_affine_family": joint["blocks"], + "out_of_pencil_lumping_blocks": out_of_pencil["blocks"], + "out_of_pencil_collapses_to_identity": out_of_pencil["blocks"] == generator.size, + "states": generator.size, + } + + +def main() -> None: + OUTPUT.mkdir(parents=True, exist_ok=True) + mode = sys.argv[1] + widths = [int(a) for a in sys.argv[2:]] + if mode == "lumping": + for width in widths: + generator = WideGenerator(width, noncrossing_states_fast(width)) + result = lumping_checks(generator) + result["width"] = width + (OUTPUT / f"lumping_width{width}.json").write_text(json.dumps(result, indent=2)) + print(json.dumps(result), flush=True) + elif mode == "transport": + for width in widths: + start = time.time() + generator = WideGenerator(width, noncrossing_states_fast(width)) + injected = prepopulate_linear_cache(generator) + experiment = pit.width_experiment( + generator, + "uniform_join_minus_detach", + ("krylov",), + pit.RANKS, + # r_transport reads only the eta=0 baseline and the PRIMARY_ETAS + # excess (max over +-1/4); the full repo ladder adds +-1/8, +-1/2, + # +-1, which do not enter dictionary_scores. + (0.0,) + pit.PRIMARY_ETAS, + pit.LAGS, + ) + rank_rows = experiment["rank_notions"] + slim = { + "width": width, + "states": experiment["states"], + "injected_r_linear": injected, + "rank_notions": { + name: { + "r_linear": row["r_linear"]["dimension"] + if isinstance(row["r_linear"], dict) else row["r_linear"], + "r_positive_baseline_lumping": row["r_positive_baseline_lumping"]["blocks"], + "r_positive_whole_affine_family": row["r_positive_whole_affine_family"]["blocks"], + "r_transport": row["r_transport"], + } + for name, row in rank_rows.items() + }, + "spans": [ + { + "family": span["family"], + "requested_rank": span["requested_rank"], + "status": span["status"], + "dictionary_scores": span.get("dictionary_scores"), + } + for span in experiment["spans"] + ], + "seconds": round(time.time() - start, 1), + } + (OUTPUT / f"transport_width{width}.json").write_text(json.dumps(slim, indent=2)) + print(json.dumps(slim), flush=True) + + +if __name__ == "__main__": + main()