diff --git a/research/format-limits/DEPENDS.json b/research/format-limits/DEPENDS.json new file mode 100644 index 0000000000..276212957a --- /dev/null +++ b/research/format-limits/DEPENDS.json @@ -0,0 +1,48 @@ +{ + "description": "Files of the main branch read by the checks (read-only), pinned by sha256; checked by scripts/provenance.py. The census anchors (data/census/anchors.json) are checked by content instead.", + "base_commit": "7dfa22b", + "files": [ + { + "path": "research/direct-delivery504-global/vendor/clifford/clifford_exact.py", + "sha256": "2982ead07721e83358dc67c6f49c2b4c16a236a6bebdfd72f58221be1f5d0962", + "from_pr": "#531 (icekylinx)", + "used_for": "exact Gaussian-dyadic Clifford compiler (toys c1, c2, c3_gate0, c7)" + }, + { + "path": "research/direct-delivery504-global/vendor/gk/gk_word.py", + "sha256": "f027a9273bcf4e0971258c160b7d3b3c196366b32a529cff6e6a0e666b03826b", + "from_pr": "#531 (icekylinx)", + "used_for": "complex word helpers (a4, e1, e2)" + }, + { + "path": "research/direct-delivery504-global/vendor/gk/gk_common.py", + "sha256": "e68d190fd436b2f3955decb590adb53344d5d4ea0a19d62d86df1e4b55ecd198", + "from_pr": "#531 (icekylinx)", + "used_for": "complex word helpers (a4, e1, e2)" + }, + { + "path": "research/direct-delivery504-global/evidence/local/FULL-WORD.json.gz", + "sha256": "bd6b004c4948d5ce80d4f81477338fe30434c2a94586463fdcc531df0dbc9509", + "from_pr": "#531 (icekylinx)", + "used_for": "the #531 complex word (c3_taint, d1)" + }, + { + "path": "research/direct-delivery504-global/inputs/hamming/PROTOTYPE.json", + "sha256": "327d2a868043e846381aa58a33053c24425e8cad522ff401b10ec8af1d649a3f", + "from_pr": "#531 (icekylinx)", + "used_for": "P112 port geometry (d1, d3)" + }, + { + "path": "research/punctured112-global/inputs/ASYNC112-PLAN.json", + "sha256": "a26acfea7ba8179130633b51a4c559e4dab179ddbae0578ff0809397efa09b55", + "from_pr": "#523 (icekylinx)", + "used_for": "idle hosting windows of the 112-port unit (e2)" + }, + { + "path": "research/e8-r480-nine-stage/EXPECTED.json", + "sha256": "883f7a1a84f31d9e4430e348bc8d9c1ec10210b206ff602dbe126349056af13d", + "from_pr": "#510 (DreamingOfClouds)", + "used_for": "R480 nine-stage profile and bit c (a3)" + } + ] +} \ No newline at end of file diff --git a/research/format-limits/LICENSE b/research/format-limits/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/research/format-limits/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/research/format-limits/MANIFEST.sha256 b/research/format-limits/MANIFEST.sha256 new file mode 100644 index 0000000000..847f929c23 --- /dev/null +++ b/research/format-limits/MANIFEST.sha256 @@ -0,0 +1,50 @@ +31f6e8be64f321cc58730c4fbbdba0d2f7f8b704fb3d5da23303e219d754c47d DEPENDS.json +c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4 LICENSE +d16991367957b1de0cb3c9d4b61667482c3d4985903f15846051c65812c81611 NOTICE.md +0fa0d6b2df96ddc06b876c41c5fa8d2335b97f36bc8f17d1371296d23199c263 README.md +ecdc9cb66e0631cd311ffae9c742dd1173efb99803a537778c76cdd4ea0bda1e SOURCES.json +810e9c5c3222811ee5d4b52b3429f7700ab578836f76418bada521bea98b1001 data/ceiling/gap568-inputs.json +5445f842587ab968c5001491e6479e7cc691b5114ab234652ce25b9272e2092f data/census/anchors.json +e92a4a7a23455c1aa8ba0aa93518627235d872f4fff11505f276d2789bd924d3 data/prices/helper-price-table.json +90d2e216d5c0807c22c4c8b772d0b2c4bde08c8810a2688136fd4385b4a9c470 data/prices/k1-specs.json +5a2a06f515a60cdda2b9743dfc6b9322ada30a743dc99385cc55fe938f2f132f data/prices/pr569-provider-calls.json +fe3ad604eec43845747603414222fc6a82ed16168ef64909440c0a72eba97dc9 data/toys/sol_p3_cone_R16.json +06eccee9f6b77e140833df83407e7996dc948c17d49b0779ab171fbe463fd28d data/vendor/pr543/EXPECTED.json +dd078d075b153ea2ed02a4bbd1fe467315930f4d7dc90f2c34cd2c33e06a5029 data/vendor/pr545/EXPECTED.json +7c2675fd49afd7e328606399a4421fd49c43fe8a6c5b57154cc908c00588abe2 data/vendor/pr555/EXPECTED.json +1bc3c53d4baf4927c6a00c339ea3975516471a48074d4d97c6addaded2a4d858 data/vendor/pr555/bitE8mut-p111.json.gz +cde64e210720e0cafbea5a242ee3747d3f34447bfdbc53c62114d6c34c71feeb data/vendor/pr568/PLAN.json.gz +4bb27af5d2142114ac59d24c8fc9bb638b932cf1cdffaf17733b5372ee101f3b data/vendor/pr569/fourcold-eight-FULL-WORD.json.gz +6f99cffd73076a768d39c21bf97ced42b6a5d3228b1dcef79d6f072dd35c0ee5 data/vendor/pr569/width7-eight-FULL-WORD.json.gz +ee0fecf86bddcc5f4e675c60fbd5c572bd48269368a37a38c070346eefa3dd4a data/vendor/pr571/combined-eight-local-FULL-WORD.json.gz +6a080563ee39cc2c1c527bb6fb9c822253a7ee7202b7c5e53030e5526f973817 requirements.txt +d763514fc92933875b8cef8535b881cae4536937918f2a3a5d8dc87dda207dff scripts/a1_ceiling_roots.py +1628325b8c15519a6fb5850461344b90a88d950948d8c47d8d19c00a95c17a1d scripts/a2_ceiling_sup.py +1dc82914bf5a6ee5d1f27ea5cfbe404b83279c327cac2f56142a47a443a87159 scripts/a3_axioms.py +b2e90cbb329bfebd954166637ed04488479dd7acca32e0c6102d4a3631c347f4 scripts/a4_gap.py +6479c189696f53cc505febb2c81c4b69a5bf54f211ee4ae64ff841041244b060 scripts/a5_scope_multipliers.py +49983e533cec16f72009bc5f0c57f1fe0811c96cdf0391ac8b4e44ba3e42eb91 scripts/b_census_anchors.py +23a57ea454773b09a407c383581efc32868d885a574ed59cde444ad804d10b6d scripts/c1_sandwich_toy.py +588709cb843477d435f00a3242c6eb6700f01bc88d060cbaf290b7fa27fc0d2f scripts/c2_port_gauge.py +da9f655c9292d0be25db6559f13069513c29a181e2664dcb3fdae1a072976d4b scripts/c3_complement_gate0.py +7aac51bc3819b89661d5f78f21a81a68b573073b4b1f837364a17d3b8ec2bbb2 scripts/c3_complement_taint.py +f3ece572a2c96b03139bff751ad2ab343be9edf4e0f84b2351772779e7bd8f31 scripts/c4_quotient.py +1ebc26e942785da50a354d34a55f487a00fc5a191570623fb8613da3a6a85aba scripts/c5_lambda.py +a9e17c1cf50a8403734a0e35863776a5ec7e60b44e9556f7b0206163c7f18cd0 scripts/c6_asym.py +9853b2f5a7cc9e8fe9db337ada7b669c3fb5404ce44ff23f48734454269270bb scripts/c7_descent_price.py +b59d52a954590aa35ddf1a495e61fa0b7c3edc4a91cbe4c232620d27079f8ce6 scripts/c7_descent_toy.py +cab1c055cf4dbad6a89b4527e2ef3d138131b6742eaf21bd8b4338a9ee2febf4 scripts/cert.py +67c40caeac7baf3156b2b863d185dedc2fc7a96ef6422b3571909099bc47eb75 scripts/d1_cover_numbers.py +85e05bfb9c380ecd6cd479a4e615735e7b377011e4aa8fb379367c224fd217cf scripts/d2_coupled_count.py +72bf9fb0479c2910413e34fe8e1ac050013df30b7751aaabea88241e086c7f55 scripts/d3_carrier_ledger.py +8699bcd1e00d08903b6dade00251947344e2ca53ece36a62aa98aa821d598241 scripts/d_geometry.py +17b521fd60adb6237114dcc632823e48771f3dca67f61d6766c74c9b1a7daddd scripts/e1_run_census.py +743ea47f90c189931bbc2add8c7c477be2db40d823e612f1c3112390cd477f5c scripts/e2_helper_prices.py +3134443d8327d0bf2a8a66c26327cf5268cec6b7ffd85dde750b7e197ce63ef1 scripts/e8units.py +de0c4091e98a724eb20f50abb546edfe94206d66d63dc56718f858c4c774b33f scripts/e_hosting.py +bf79e88c99f5632a01957008d52a00233b4135b211c9e6a26a9180a6bbb58423 scripts/minrank_sat.py +55d8bc41b48025dfa5a7c07a1b59338ab53733ee261bf75f1cc6da2f3f0a862e scripts/provenance.py +96fbb236eb58bd471be33ccafbd128cd0590e5dc6f160ad9b9e85bcc2680b437 scripts/report.py +616cd927168b9bea5675ce6241d9574a222761ef267e8b688c8d7a1ef9e1e887 scripts/run_all.py +9cfbc1316389a46922765cdae85fdde2042f7681986d1c97a19174c4922ea29c scripts/skel.py +ac74b228875bec9c4212e12e2a773e8cc0746d2f85fac743b10dbc4004b5bb24 verify.sh diff --git a/research/format-limits/NOTICE.md b/research/format-limits/NOTICE.md new file mode 100644 index 0000000000..1c45fbefdb --- /dev/null +++ b/research/format-limits/NOTICE.md @@ -0,0 +1,81 @@ +# Notice + +Prepared by DreamingOfClouds with Claude Opus 5.5 (Anthropic), via Claude Code; Apache-2.0 (`LICENSE`, copied from +the repository root). + +## New in this package + +Everything under `scripts/` and `data/` except `data/vendor/`, plus `README.md`, `verify.sh`, `SOURCES.json`, +`DEPENDS.json`, `requirements.txt` and `MANIFEST.sha256`. + +## Vendored, unchanged (git blob ids in `SOURCES.json`, checked by `scripts/provenance.py`) + +- **#555 (eumemic), commit 65a6bc1**: the p111 bit word `bitE8mut-p111.json.gz` and its `EXPECTED.json`. +- **#569 (DominikScholz), commit 1424da8**: the width-7 and four-cold provider words (`FULL-WORD.json.gz`). +- **#571 (DominikScholz), commit b7bdc5a**: the combined-eight-local provider word. +- **#568 (jeremykothe2), commit 71c99ac**: `research/complex-multicold/data/PLAN.json`, stored gzip-compressed (the + blob id is of the decompressed file). +- **#543 (eumemic), commit 2065fe4**: `research/e8-bit-r420/EXPECTED.json`. +- **#545 (DreamingOfClouds), commit 376426f**: `research/e8-punctured111-star/EXPECTED.json`. + +## Other inputs + +- `data/toys/sol_p3_cone_R16.json`: the p = 3 paired-cube program (h = 6, v = 8, R = 16) in the gcert/1 format of Jacob + Sussman's checker, the same toy instance as #446's. +- `data/prices/pr569-provider-calls.json`: the 72 (time, provider) pairs of #569's `research/larger-gain/global/width7/ + PLAN.json` (blob id recorded in the file). + +## Used from main, unchanged (pinned by sha256 in `DEPENDS.json`) + +- #531 (icekylinx): + - the exact Clifford compiler `research/direct-delivery504-global/vendor/clifford/clifford_exact.py`; + - the word helpers `vendor/gk/gk_word.py` and `gk_common.py`; + - the word `evidence/local/FULL-WORD.json.gz`; + - the geometry `inputs/hamming/PROTOTYPE.json`. +- #523 (icekylinx): the hosting windows `research/punctured112-global/inputs/ASYNC112-PLAN.json`. +- #510 (DreamingOfClouds): `research/e8-r480-nine-stage/EXPECTED.json`. +- The census anchors (`data/census/anchors.json`) cite, read-only: + - the upstream paper (`upstream/build/sections/*.tex`); + - #493's checkers (eumemic and contributors); + - #509 / #516's Lean files (DreamingOfClouds); + - #442's hosting proof (DaysSky); + - #130's general frame lemma note (icekylinx); + - the five-stage bank files (#276 lineage); + - the maintainer's review documents. + +## Results and constructions this package builds on (credit) + +**Interfaces, lemmas and checkers:** + +- the upstream paper (`upstream/build/sections`); +- **#130** (icekylinx): the general Clifford frame lemma for arbitrary binary subspaces; +- **#370** (utcorvusvolat-dotcom): the first E8 bit word and its checker; +- **#386** (jacklightChen): compressed windows; +- **#425** (jacklightChen): the mutable-basis interface and scalar-interface lemma; +- **#433** (icekylinx): split centres; +- **#442** (DaysSky): idle-axis whole-residual hosting and its stream model; +- **#446** (DreamingOfClouds, open): Theorems A–C, used as premises; +- **#458** (chafreaky): the one-helper-per-family rule; +- **#493** (eumemic): the bit carrier skeleton, checkers and outer assembly; +- **#509 / #516** (DreamingOfClouds): Lemmas G and A in Lean; +- **#514** (Dugongue): the repeated-axis identities C_v² = X_v. + +**Words and pipelines read by the checks:** + +- **#510** and **#545** (DreamingOfClouds); +- **#543** and **#555** (eumemic); +- **#523** and **#531** (icekylinx): the punctured 112-port complex unit and direct delivery; +- **#568** (jeremykothe2); +- **#569** and **#571** (DominikScholz). + +**Lineage the measured words build on (credited, not read by any script):** + +- **#535** (icekylinx): post-centre kernels; +- **#552** (Dugongue): the static44 harness lineage of the complex words; +- **#558** and **#564** (eumemic): rank-5 pivots and cold kernels; +- **#588** (jeremykothe2): frame coalescences on the #569 regime (cited in C.8, not reproduced). + +**Split-residual hosting:** + +- **#448** (higherbeing): the cross-copy split-residual construction; +- **#451** (chafreaky): its trace obstruction. diff --git a/research/format-limits/README.md b/research/format-limits/README.md new file mode 100644 index 0000000000..2f7aaf5b82 --- /dev/null +++ b/research/format-limits/README.md @@ -0,0 +1,805 @@ +# Format limits (no κ claim): a certified ceiling, a spec census, structural lemmas and helper bounds + +This package states results about the limits of the current construction format (B_K compressed windows, star +copies, whole-residual hosting) and checks the ones that can be checked. **It makes no κ claim and ships no word.** +Each result comes with its scope and assumptions. Each is marked: + +- **checked**: `verify.sh` recomputes it from the files listed below (exact or certified arithmetic unless stated); +- **argued**: a proof or proof sketch in this README; +- **recorded**: an input taken from a run or a PR that `verify.sh` does not repeat (the file and its source are named). + +```sh +python3 -m pip install -r research/format-limits/requirements.txt +bash research/format-limits/verify.sh /fresh/output/dir # from a checkout or `git archive` of the whole repository +``` + +Python ≥ 3.11 with numpy, scipy, sympy, python-sat and ortools (`requirements.txt` pins a tested set). Step 0 +checks the package against `MANIFEST.sha256`, the vendored inputs against the git blob ids of their PR commits +(`SOURCES.json`) and the files of main it reads (`DEPENDS.json`). Steps A–E print one `PASS`/`FAIL` line per claim. +About 2 minutes on 12 cores (six checks at a time). + +**Tested environments** (fresh `git archive`, every claim PASS): + +| Python | numpy | scipy | sympy | python-sat | ortools | how installed | +|---|---|---|---|---|---|---| +| 3.11.17 | 2.4.6 | 1.17.1 | 1.14.0 | 1.9.dev15 | 9.15.6755 | fresh venv from `requirements.txt` | +| 3.14.7 | 2.4.6 | 1.17.1 | 1.14.0 | 1.9.dev15 | 9.15.6755 | fresh venv from `requirements.txt` | +| 3.14.7 | 2.5.4 | 1.18.1 | 1.14.0 | 1.9.dev15 | 9.15.6755 | fresh venv, latest releases | +| 3.14.7 | 2.3.5 | 1.17.0 | 1.14.0 | 1.9.dev15 | 9.15.6755 | development venv | + +Values that come from floating-point solvers (the hosting LP, the coupled-cover MILP) are compared with explicit +tolerances; the certified roots are rational intervals. + +## Results at a glance + +| id | result | status | +|---|---|---| +| A | **Format ceiling, rev. 2.** Under the accounting axioms of §A.1, every supplier in the format has saving a ≤ X(s, h/k, x) (root of the slot-domination bound). On the realised units, X* = 6.0005·10⁻³ (bit, 111 lines, decoder constant 63) and 5.1863·10⁻³ (complex, 112 ports, copy cost 64), both at s = 5, so **κ ≤ 5.1595·10⁻³** (complex binds). | theorem argued; every number checked (`a1`–`a5`) | +| A.4 | The axioms hold on the frontier words #555 (bit) and #568 (complex): published values reproduced from their profiles, deficit identity with equality, B_K idle windows literal, slot domination at nine values of q. | checked (`a3`); (Bat)/(Hst) for #568 argued from its README | +| A.5 | At s = 9 the frontier sits 2.66× (bit) / 2.50× (complex) under the ceiling; 87% / 93% of the log-gap is helper cost, 19% / 25% data-run fragmentation, and hosting recovers 7% / 18%. | checked (`a4`); #568 uses a recorded idle remainder | +| A.6 | The rev. 1 scope x = 3/5 (κ ≤ 4.5151·10⁻³) is superseded: the punctured units have x = 63/111 and 64/112. | checked (`a1`) | +| B | 25 format rules classified as spec / proved / convention, with file:line evidence in the upstream paper and the hub's checkers, and the corrections the census found. | anchors checked (`b`); classification argued | +| C.1 | Frame sandwich: a register's frame lies between the span of what it carries and the orthogonal of what it will serve; the three complex frame walls are its faces; leaving it is exact and costs d(f, g). | argued; toy checked (`c1`) | +| C.2 | Lemma N: the per-target rank-1 port factor is a gauge of the endpoint frames, always paid; any detour off the geodesic interval costs exactly 2. | proof argued; toys checked (`c2`) | +| C.3 | Lemma R: complement sinks w_t^⊥ (w·u = 1) are legal at zero rank and port cost, and forced to w_t = u_t on every target of the four complex words checked (#531; #569 width-7 and four-cold; #571 combined). | checked (`c3_gate0`, `c3_taint`) | +| C.4 | Lemma Q: a degenerate-label unit is dominated by its quotient (copy cost and window), so degenerate spans give no new (w, x) points. | proof argued; toys and families checked (`c4`) | +| C.5 | Lemma λ: a phase-frame butterfly needs λ = ±i (and 2 invertible) in its payload ring; b < c is the price of √−1, and the outer already uses shift twiddles. | argued; instances checked (`c5`), anchors (`b`) | +| C.6 | At the E8 decoder pattern with window ≤ 9 the label pairing B = W·Uᵀ is unique (= B0); every W ≠ U is a gauge. Window 8 is impossible. | checked (`c6`, SAT without proof logs) | +| C.7 | A rank-r descent costs 2r data mass in every call (−5.63% c on #555, −5.65% b on #568 per rank-1 descent); within that price class a schedule with a paid descent is dominated. | toy and prices checked (`c7`); dominance argued | +| C.8 | Splitting one helper residual across two hosting streams meets a trace obstruction under every invertible storage change; uncharged, it is worth at most +0.67% b on the current complex frontier. | argued | +| D | Design-free helper floors in the drop-free monotone-chain model: bit ≥ 212 (sink-only targets) / 138 (strict) vs 439 shipped; complex ≥ 107 / 0 vs 496. Coupling the levels adds 0. The "224 carriers" complex floor is a design choice, and carriers are register-neutral in the calibrated ledger. | checked (`d1`–`d3`), given the argued crossing lemma | +| E | Complex helper price by class and width on #569 (0.039–0.140% b per helper at k = 1; the hosting offset depends on width only), and the moment-cost census by class on #555 and #569. | k = 1 prices, control and census checked (`e1`, `e2`); k > 1 rows recorded | +| F | Cost structure: a change paid in every local word must buy about 2.8% of the supplier value per rank unit; open problems: per-word enablers, a non-star decoder, the schedule/ρ freedom, new skeletons. | conclusion from checked prices | + +Earlier statements this package relies on: Theorems A–C of #446 (DreamingOfClouds, open; content-frame invariant, +stage-window additivity, pairing-rank copy floor). They are cited as premises and are not re-proved here. #446 states +Theorem B for rank-1 labels (every number in this package is at k = 1), and its Theorem C value 72 for the bit E8 +unit is computed there and not replayed here. + +## A. Format ceiling, rev. 2 + +### A.1 Scope S2 (accounting axioms) + +A word is a B_K compressed-window block for one supplier (bit or complex), replicated T times, with s = 2K + 1 +stages, v ports of label rank k and stage window h, copy rank cst per stage, and any helper network (any R, widths, +local programs), any banking or hosting rule and any halving depth. Writing z_r for the number of paid children of rank +r and g_q(r) = r((m/r)^q − 1): + +- **(P) pressure identity.** The supplier saving a is the root q of Σ_r z_r g_q(r) = D. (The hub pricers add a + nonnegative fallback term, which only lowers their root.) +- **(Dfc) deficit.** D = T[(s − 1)vk − s·cst], with cst ≥ cst_min(U), the star floor of the unit U (the pairing-rank + floor of #446 Theorem C holds for any copy tree; the star form β_j ≥ k·w_in is the scope assumption). +- **(Win) window.** Every data register climbs a ≥ h − k per stage and m = k + s·a (#446 Theorem B gives + m ≥ k + s(h − k); #386's compressed windows attain it). X is non-increasing in a, so a = h − k is the extreme case. +- **(Sch) B_K schedule.** Stage j activates one bank pair (2 data registers per port per replica); pair 0 is active at + stages 0, 1, 2 and pair p ≥ 1 at 2p + 1, 2p + 2. Idle frame changes per copy (2v copies): pair 0 has [(2K − 2)a]; + pair p ∈ 1..K − 1 has [2pa, a, (2K − 2p − 2)a] (a bridge read splits the pre-stretch). +- **(Bat) batching.** A paid child executes part of one frame change Δ and has rank ≤ rank Δ (Δ is a register's + frame change, or, as in #448, one idle change across the copies of one idle child). Local children have rank ≤ a + (data registers) and ≤ h (helpers, copies). +- **(Hst) hosting is accounting.** A hosted helper child is a local child (rank ≤ h) that executes coordinates of an + idle frame change; the rest of that change is paid in children of rank ≤ its rank; an unhosted helper lives on a bank + wire. + +### A.2 Theorem and proof sketch + +Per port (v and T cancel), the **forced slots** are: the active climbs (mass 2sa, cap a), the copy drops (mass s·x, +x = cst/v, cap h) and each idle frame change of rank r of the schedule (mass 2r, cap max(r, h)). Let +F_s(q) = Σ_slots mass · ((m/cap)^q − 1) and D_s = (s − 1)k − s·x. + +**Theorem.** For every word in S2 on a unit U, a ≤ X(s, h/k, x_U) := the root q of F_s(q) = D_s, with +x_U = cst_min(U)/v(U). Since e^y − 1 ≥ y, also X ≤ D_s/Cost_s with Cost_s = Σ_slots mass · ln(m/cap). + +*Proof sketch.* (1) Monotonicity: each g_q(r) increases in q for r < m, so a(z, D) ≤ a(z', D') whenever f_z ≥ f_z' +pointwise and D ≤ D'. (2) Slot domination: by (P) the paid mass executes every coordinate of every forced slot; by +(Win), (Sch), (Bat) and (Hst) every child touching a slot has rank ≤ its cap; φ_q(r) = (m/r)^q − 1 decreases in r, so +splitting each child's mass over the slots it touches gives f_N(q) ≥ F_s(q; cst_N); children touching no slot +contribute ≥ 0. (3) Helpers never shift D or m (call this Lemma H): Theorem B bounds m with target frames only; a bank wire is restored +scratch, so its saving is ≤ 0; a data register saves ≤ k whoever executes its coordinates; copies cost ≥ cst_min for +any tree. X is non-increasing in a (d/da of each slot term is ≥ 0 by Bernoulli's inequality). The cap max(r, h) on +idle slots absorbs the one place where hosting lowers paid cost (a width-h helper child on a single-stage idle slot); +it costs 1% against the literal R = 0 profile. (4) F_s increases and D_s decreases in cst, so cst_N may be replaced by +cst_min. Apply (1). + +**General k (argued; no number here uses it).** Scaling every rank by k (a = k(w − 1), h = kw, m = k(1 + s(w − 1)), +every slot mass and D multiplied by k at fixed x/k) leaves each ratio m/cap unchanged, so X depends only on +(s, w = h/k, x/k). Every number in this package is at k = 1. + +**κ.** The outer assembly seeds s0 = min(c, (1 − β)b) − 10⁻²⁴ and bootstraps x ↦ (1 − s0)s0 + s0·x from below; the map +is increasing with fixed point s0, so κ ≤ X/(1 + X) with X = min(X_bit*, X_cx*), each side at its own best s. + +### A.3 Numbers (certified; `a1_ceiling_roots.py`, `a2_ceiling_sup.py`) + +| unit | x | s = 3 | **s = 5** | s = 7 | s = 9 | s = 11 | s = 13 | +|---|---|---|---|---|---|---|---| +| bit, 111 live lines, decoder constant 63 (#545, #555), h = 8 | 0.5676 | 5.9474e-3 | **6.0005e-3** | 5.2095e-3 | 4.6072e-3 | 4.1490e-3 | 3.7879e-3 | +| complex, 112 ports, copy cost 64 (#523 → #569), h = 9 | 0.5714 | 5.0474e-3 | **5.1863e-3** | 4.5130e-3 | 3.9946e-3 | 3.5989e-3 | 3.2865e-3 | + +Roots are rational-interval brackets of width < 10⁻¹⁵; the upper end is the certified value. + +- **κ ≤ 5.1594938·10⁻³ < 5.1595·10⁻³**; the complex side binds. The bit-only corollary is c/(1 + c) ≤ 5.9647·10⁻³. +- **The supremum over s is at s = 5** on both units. For odd s = 7..401, the certified D_s/Cost_s stays below X(5); + the largest values are 5.2311·10⁻³ (bit) and 4.5292·10⁻³ (complex), both at s = 7. For s ≥ 403 a tail bound applies: + Cost_s/v ≥ 2Σ_{p 2Ka), and + Σ_{p=1}^{K−1} p ln(K/p) ≥ K²/4 − K/e − K/2. Then X ≤ D_s/Cost_s < (1 − x)s/(4a(K²/4 − K/e − K/2)), which is + decreasing in K and equals 6.27·10⁻⁴ (bit) / 5.44·10⁻⁴ (complex) at s = 403. + - *Proof of the inequality (erratum to rev. 1, which invoked "trapezoid error for a concave function", the wrong + direction).* f(p) = p ln(K/p) is concave, so by Hermite–Hadamard f(p) ≥ ∫_{p−1/2}^{p+1/2} f. Summing gives + Σ_{p=1}^{K−1} f(p) ≥ ∫_{1/2}^{K−1/2} f = K²/4 − ∫_0^{1/2} f − ∫_{K−1/2}^K f. Both removed pieces are small: + the first is (1/8)(ln K + ln 2 + 1/2), and the second is ≤ (K/2)·ln(K/(K − 1/2)) ≤ K/(4K − 2) ≤ 1/3. Their sum is + ≤ K/e + K/2 for every K ≥ 2. The script also checks the inequality numerically for K = 2..5000. +- **Frontier against the ceiling at s = 9.** X(9)/c = 2.658 for #555 (c = 1.733053·10⁻³), and X(9)/b = 2.499 for + #568 (b = 1.598685·10⁻³). +- **Copy charge.** One copy-rank unit per stage (bit cst 63 → 62) raises X by +3.90% (s = 5), +2.82% (s = 9) and + +2.65% (s = 11). + +### A.4 The axioms on the frontier words (`a3_axioms.py`, checked) + +| check | words | result | +|---|---|---| +| (P): certified root of the published global profile at the word's (m, D) vs its published value | #510 R480 s9, #543 R420 s9/s11, #545 p111 s11, #555 p111 s9/s11, #568 | root ≥ published; relative difference 1.2–1.7·10⁻⁹ on the bit pipelines (consistent with their nonnegative 10⁻¹⁶ fallback term), 5·10⁻¹⁸ on #568 | +| (Dfc): m·W − rank mass = T[(s − 1)v − s·cst] with integral W | same seven profiles | equality (e.g. #555: 64·28416 − 1,808,352 = 10,272; #568: 73·7168 − 520,704 = 2,560) | +| (Win): m = k + s(h − k); largest child = literal idle remainder (2K − 2)a | same | m = 64/78/73; largest child 42/56/48 on #543, #545, #555, #568 (#510's largest child is 8) | +| (Sch): active + copies + idle slot mass = rank mass | #555, #568 | 447,552 + 18,144 + 1,342,656 = 1,808,352; 129,024 + 4,608 + 387,072 = 520,704 | +| (Sch): idle windows per replica = idle_slots(K = 4, a = 8) on both banks | #568 PLAN, 8 replicas | {8: 6, 16: 4, 32: 4, 48: 4} on every replica | +| (Hst): helpers hosted whole, no banks | #555 | bank assignments 0; hosted residuals 126,432 = 439·288 | +| Lemma 2 on a grid: min of f_N(q)/F_s(q; cst_N) over nine values of q in [10⁻⁵, 1] | all seven | 2.29–2.66 (≥ 1) | + +**(Bat) at child level.** #555's helper runs have rank ≤ 5 ≤ h (checked by the replay in `a4_gap.py`). #568's helper +children have rank ≤ 6 ≤ h (its implied helper histogram in `a4_gap.py`). #568's README (commit 71c99ac, +research/complex-multicold/README.md:22) reports one whole owner for all 36,288 helpers, no auxiliary banks and 27,679 +cross-replica roles; a cross-replica role hosts helper children of one idle change at rank ≤ h, so it falls inside +(Bat)/(Hst) (argued). No structural axiom is violated by #555 or #568. + +### A.5 Gap decomposition at s = 9 (`a4_gap.py`, checked) + +| step | #555 bit | #568 complex | +|---|---|---| +| A: theorem skeleton (R-free; idle slots at cap max(r, h)) | 4.6072e-3 | 3.9946e-3 | +| B: literal R = 0 (each idle slot one child of its own rank) | 4.5661e-3 | 3.9631e-3 | +| C: B with the real data-register runs and copy children | 3.7868e-3 | 3.1544e-3 | +| D: C plus every helper run paid unhosted (the only step with more rank mass) | 1.6183e-3 | 1.3517e-3 | +| E: the real word (helpers hosted whole, idle remainders paid) | 1.7331e-3 | 1.5987e-3 | + +Shares of ln(A/E) (0.978 / 0.916): + +| component | #555 | #568 | +|---|---|---| +| helpers | 87% | 93% | +| data fragmentation | 19% | 25% | +| literal vs cap | 1% | 1% | +| hosting | −7% | −18% | + +Steps A, B, C and E have the same rank mass, m·W − D (1,808,352 and 520,704). + +Inputs: + +- **#555.** Data, helper and copy runs are replayed from the published word. The replay matches #555's local + histogram, and the helper mass is 8R. The idle remainder is the published profile minus 288 × the local profile; + 75.3% of the skeleton idle mass is hosted. +- **#568.** The data-register runs per call come from #569's four-cold provider word (the same x/y ladders). The paid + idle remainder {1: 93, 2: 93, 3: 2118, 7: 1, 48: 1713} is **recorded** from our replay of #568's hosting + (`data/ceiling/gap568-inputs.json`). Its 4,018 children match the "4,018 positive idle remainders" of #568's README + (checked), and the implied helper histogram is nonnegative (checked). + +The headroom under S2 is therefore almost entirely helper cost. Even with zero helper cost and real data +fragmentation, the words would sit 2.19× (bit) / 1.97× (complex) above today. + +### A.6 The superseded numeric scope of (Dfc) + +Rev. 1 of this ceiling fixed cst_min = 72 and x = 3/5 (the full 120-line E8 unit) on both sides. That gave X_bit* = +5.1598·10⁻³, X_cx* = 4.5356·10⁻³ and κ ≤ 4.5151·10⁻³ (checked, `A1.rev1-superseded`). + +The punctured units that the frontier now uses have smaller x: + +- bit: #545/#555 keep 111 live lines with decoder constant 63; +- complex: the #523 lineage has 112 ports with copy cost 64. + +So x = 63/111 = 0.5676 and 64/112 = 0.5714. With x_U taken from the realised units the ceiling is §A.3's +κ ≤ 5.1595·10⁻³. The structural axioms are unchanged. + +Status of cst_min per unit: + +| unit | cst_min | status | +|---|---|---| +| bit 120/72 | 72 | proved given #446 Theorem C: the F2 decoder of the E8 pattern needs 9 totals (its F2 minrank is 9; c = 8 is UNSAT, checked in `c6`), and each star total costs β = 8, the Gram rank of an 8-line in-cap clique (premise, not replayed) | +| bit 111/63 | 63 | the star floor among punctures of p ≤ 25 lines: Δcst ≤ min(p, 9), from an exact matroid-greedy search over the 9-dimensional code that this package does not reproduce (**argued**, not checked here). For 26 ≤ p ≤ 52 only the total D gain s·Δcst − (s − 1)p ≤ 9 is bounded, which does not pin x. | +| complex 112/64 | 64 | 8 × 8, the star floor at w_in = 8, attained (**argued**) | + +A unit with smaller x would move X by about +2.8% per copy-rank unit at s = 9 (§A.3). For scale, two units with +smaller x that no word realises are checked as well (`A1.outside-scope`): bit x = 54/102 gives X* = 8.2457·10⁻³ and +complex x = 56/104 gives X* = 6.8000·10⁻³, both at s = 3. They lie outside the realised-unit scope of the theorem. + +### A.7 What each scope rule is worth (`a5_scope_multipliers.py`, checked) + +Multiplier of the ceiling if one rule is dropped. Each cell is best-s multiplier / s = 9 multiplier. + +| rule dropped | bit 111/63 | complex 112/64 | +|---|---|---| +| star scope (copy charge x → 0) | ×6.77 / ×2.79 | ×6.91 / ×2.83 | +| B_K idle frame changes free | ×1.67 / ×2.14 | ×1.68 / ×2.15 | +| all idle changes of a copy in one child | ×1.19 / ×1.55 | ×1.20 / ×1.55 | +| bridges off the idle stretches (no split) | ×1.15 / ×1.18 | ×1.15 / ×1.18 | +| data local climbs batched to h (cross-register) | ×1.12 / ×1.03 | ×1.08 / ×1.02 | +| idle free and local batching together | ×1.79 / ×2.28 | ×1.79 / ×2.27 | +| family window one smaller at the same x | ×1.16 / ×1.16 | ×1.14 / ×1.14 | + +Hosting cannot raise the ceiling (step (3) of the proof in §A.2). Full relaxation of (Bat), with arbitrary batching up to rank m, +would give no bound, because rank-m children cost 0. + +**Not covered:** + +- non-B_K schedules (a different number of active pairs per stage changes (Sch) and (Dfc)); +- non-star decoders (totals with β_j < k·w_in), and units with smaller x than the realised ones (see A.6); +- labels outside the cross-field unit; +- any change to (P), such as children of rank larger than their frame change, or a new outer assembly. + +## B. Spec versus convention census + +`b_census_anchors.py` checks every file:line anchor of the rule table (B.2), 73 in all, and the four corrections +marked "checked" in B.3. Line numbers are as of the base commit 7dfa22b. Each anchor's quoted text must lie within two +lines of the cited line, except in docs/research/ (the hub's ledgers and reviews, which main rewrites often), where it +is matched by text anywhere in the file. The line ranges cited in the prose of B.1 and B.3 were read by hand at +7dfa22b and are not machine-checked. Paths are relative to the repository root, and `U/` is +`upstream/build/sections/`. The classification is argued: + +- **S**: mandated by the upstream paper or interfaces; +- **P**: proved necessary given the cited S/C rules; +- **C**: a convention of the paper's instance or of the hub's checkers and templates, changeable if the replacement is + proved. + +### B.1 What upstream imposes + +- **Bit contract** (the only bit-side interface), U/04-swap.tex:105-123. A finite circuit of W wires whose pointwise + bit gates induce a *permutation* ρ. There is one rational m×m matrix per terminal and per gate, common to every wire + at that gate. The cost is s = Σ rank_Q(M_head − M_tail), with M_out(ρ(w)) − M_in(w) = I_m on every role and s < Wm. + The recurrence is F_k ≤ (s/W)F_{k−1} + O(1) (:197-211). No subspaces, nesting, banks, pairs or nondegeneracy appear. +- **Complex interface**: + - frames C_U = H^m diag(i^{q_U}) H^m, with q_U(x) = wt(P_U x) mod 4 for nondegenerate binary U (U/03-motifs.tex:528-561); + - an edge is a product of one kernel (aI + bX_v)^{±1} per vector of an orthonormal basis of the residual of + comparable labels (:568-583); + - endpoint C^{⊗m} on every role after free per-role corrections (:579-582, :641-668; U/05-layers.tex:127-154); + - the implementation P_M conjugation needs only invertible M (U/05-layers.tex:86-103). +- **Common-frame identity** for any invertible D_v: U/03-motifs.tex:154-186. +- **The paper's instance**: + - nondegenerate nested labels (U/03-motifs.tex:199-208, 351-364); + - terminal labels X_a: U_a → F, Y_a: 0 → U_a^⊥ (:235-243); + - the signed exchange of X_a and Y_a (:89-100); + - arbitrary, restored scratch (:34-46). +- **Outer.** Two suppliers are composed through 08-assembly.tex (:16-48, κ at :849-866, :995-1000). The transforms + are Nussbaumer synthetic transforms whose roots are signed shifts (U/00-introduction.tex:44-56, U/06-transforms.tex). +- **The maintainer's interface list**, docs/research/community-pr531-review.md:116-125: + - all-size compilation; + - common-label and mutable-basis realization; + - normalized residual wrappers as uniformly priced operations; + - whole-call correlated-helper hosting; + - compressed windows and restored rows; + - grids, tape, precision; + - the analytic transfer. + + The same review of #531's integration says the fixed-word ceiling and family-optimality discussions it carries + were "not independently certified" (:130-134). + +### B.2 Rule table + +Multipliers are from §A.7 (best s / s = 9, bit unit unless stated). + +| # | rule | class | anchors (file:line) | evidence and history | ceiling multiplier if relaxed | +|---|---|---|---|---|---| +| 1 | Common frame at every gate | S | U/03-motifs.tex:157; U/04-swap.tex:111; legality_h.cpp:11; audit_local.py:64; LemmaG/Stream.lean:106 | never changed; an ADD across frames needs an adapter edge priced d(f, g) | 1.00 | +| 2 | Frames are nondegenerate subspaces | spec: any invertible D_v (S); nondegenerate subspaces: the paper's instance (C) | U/03-motifs.tex:154, :203; U/04-swap.tex:110; gram_frames.py:46; notes/general-clifford-frames.tex:21 | #130's general frame lemma covers arbitrary (also degenerate) binary subspaces, d = dim U + dim V − 2 dim(U ∩ V); main has its TeX note and Python checks, its Lean proof is in an external repository (a conditional interface); degenerate labels are dominated by their quotient (C.4) | none by itself (only through x) | +| 3 | Nesting: climbs along a register's life; drops only as copies or centre steps | C (priced, not forbidden) | U/03-motifs.tex:352 (the paper has decreasing edges); U/05-layers.tex:83; legality_h.cpp:11; audit_local.py:45, :128; LemmaG/Stream.lean:111 | #425's full → 0 centre copies; a non-nested step is exact and costs d(f, g) (C.1, C.7) | 1.00 (two nested edges) | +| 4 | Exact restoration of helpers and dirty registers | S (same endpoint operator on every role; scratch arbitrary); "ρ fixes scratch" is C | U/03-motifs.tex:46, :98, :581; U/05-layers.tex:150; columns_k.cpp:57; audit_local.py:101 | no PR permutes scratch | 1.00 | +| 5 | ρ = signed exchange of X_a and Y_a, pairwise | C (any permutation ρ is legal) | U/04-swap.tex:107; U/03-motifs.tex:99, :628; bit_global.py:55; columns_k.cpp:56 | never varied | not quantified | +| 6 | Terminal labels X_a: U_a → F, Y_a: 0 → U_a^⊥; targets inside u_t^⊥ | C (the paper's choice; the ⊥ relations then follow from #446 Thm A) | U/03-motifs.tex:235, :240; U/05-layers.tex:128, :146 | complement sinks are legal at zero cost but forced on every current decoder (C.3) | 1.00 on current decoders | +| 7 | Rank-1 labels (k = 1) | C | U/03-motifs.tex:233 | X depends only on (s, h/k, x/k) (§A.2) | through (w, x) | +| 8 | Star copies (cst = Σβ_j, β_j ≥ k·w_in) | scope assumption of the ceiling; the pairing-rank floor itself is proved for any copy tree (#446 Thm C) | legality_h.cpp:1; columns_k.cpp:39 | every PR's totals are star | ×6.77 / ×2.79 (complex ×6.91 / ×2.83); +2.8% per copy-rank unit at s = 9 | +| 9 | E8 cross-field unit (h = 8 bit, 9 complex) | C (family) | U/03-motifs.tex:221, :225 ("the scalar domain need not equal the label field") | — | window one smaller: ×1.16 (complex ×1.14) | +| 10 | Window m = k + s(h − k) | P (#446 Thm B) | — | attained by #386 | 1.00 in model | +| 11 | Deficit D = T[(s − 1)vk − s·cst] | P given rows 8 and 12; spec form D = mW − s | U/04-swap.tex:122; U/03-motifs.tex:360 | equality on seven profiles (§A.4) | through rows 8, 12 | +| 12 | B_K schedule (one dependency chain, alternating locals, bridges, idle children) | P given row 13 | bit_global.py:49; columns_k.cpp:46; Work__Bridge__Net.lean:56 | no other schedule on record | idle free ×1.67 / ×2.14; one idle child ×1.19 / ×1.55; no split ×1.15 / ×1.18 | +| 13 | One (X, Y) bank pair per invocation (LOCAL = 2V + R) | C | bit_global.py:12; columns_k.cpp:31; Work__Bridge__Net.lean:55 (one I : Inv for all stages) | no local on two pairs on record | feeds row 12 | +| 14 | (Bat): a paid child executes one frame change | axiom of the ceiling: one register across a local/bridge is the equal-frame rule; cross-register batching is open | docs/research/pr-ledger.md:403, :405 (#448 and #451 unreviewed) | #451's trace obstruction to #448's split residuals (C.8) | local batching ×1.12 / ×1.03; with idle free ×1.79 / ×2.28 | +| 15 | Whole-residual hosting | accepted conditional interface | community-pr531-review.md:122; idle-axis-hosting/PROOF.md:43 | #442 accepted; split residuals disputed (C.8) | 1.00 (Lemma H, §A.2) | +| 16 | One owner per stream (#458) | P inside #442's stream model | LemmaA/Realize.lean:95 (`one_owner_needed`) | relaxed to disjoint footprints | 1.00 | +| 17 | Source registers never destinations | C (#370's checker assertion) | e8-bit-carrier-skeleton/README.md:67-68 | sufficient, not necessary (#425); relaxed by #433, #493 | already taken | +| 18 | Payload bounds (2^104 bit, 2^192 complex prefix, 2^80 prime witnesses) | C, never binding | columns_h.cpp:25; columns_k.cpp:34; finite_check.py:98; audit_local.py:103; gram_frames.py:17 | — | 1.00 | +| 19 | F2 payload coefficients | C | columns_h.cpp:27 | — | 1.00 | +| 20 | Replication T | C | bit_global.py:11; finite_check.py:86 | #505 asynchronous replicas | 1.00 (T cancels) | +| 21 | 47-inequality outer assembly | structure S, constants C | outer.py:27; U/08-assembly.tex:37; assembly-domain-audit.md:21 | the 1/32 domain cap is conservative and not binding | 1.00 | +| 22 | κ is the composition of the two suppliers | S | U/08-assembly.tex:37; outer.py:29, :30 | — | — | +| 23 | Two suppliers: complex butterfly layer, bit address shear | S | U/00-introduction.tex:48, :56, :118; U/06-transforms.tex:12 | shift twiddles are already in the outer (C.5) | — | +| 24 | Pressure identity (a rank-r child priced as a fraction of a call) | inherited conditional ("normalized residual wrappers as uniformly priced operations") on the paper's rank-1 recurrence | U/04-swap.tex:197; community-pr531-review.md:122 | — | defines the ceiling | +| 25 | Bridges X → X and Y → Y only | P (X wires contain q, Y wires do not) | columns_k.cpp:43 | — | — | + +Abbreviations: + +- `legality_h.cpp`, `columns_h.cpp`, `columns_k.cpp` and `gram_frames.py` are in + research/e8-bit-carrier-skeleton/code/bit/checkers/; +- `audit_local.py` is research/direct-delivery504-global/code/audit_local.py; +- `bit_global.py` is research/e8-early-reset-kernel/bit_global.py; +- `Work__Bridge__Net.lean` is in research/five-stage-gen4-banks/inputs/complex/sources/; +- `finite_check.py` is research/five-stage-gen4-banks/finite_check.py; +- `outer.py` is research/e8-bit-carrier-skeleton/code/pricing/outer.py; +- `LemmaG/`, `LemmaA/` are under research/e8-lemma-g-lean/ and research/e8-lemma-a-lean/; +- `community-pr531-review.md` and `assembly-domain-audit.md` are under docs/research/. + +### B.3 Corrections, as the census found them + +1. **The bit interface is the shear contract alone** (U/04-swap.tex:105-123). Subspace labels, nesting, Gram + orthogonality, bank pairs and the pair exchange are construction-layer choices of the paper's instance + (:199-243, 351-364), not interface requirements. +2. **Nesting is priced, not forbidden.** + - The paper itself has decreasing edges (U/03-motifs.tex:352-353). + - The paper counts kernels on decreasing edges (U/05-layers.tex:83). + - #130's frame lemma prices non-comparable labels by d(f, g). + - The checkers enforce nesting as a pricing rule. +3. **The bit legality checker** keeps its MOVE (nested and exactly priced), ADD (common frame) and COPY-lifecycle rules + on legality_h.cpp:11; line 10 holds the containment helper and the owner/helper selection (checked). +4. **The invariant `Inv`/`GInv`** used by the complex five-stage bridge is imported (`import Work.Bridge.Inv`) and + defined nowhere in main (checked). "One X bank and one Y bank per invariant" therefore rests on its use in + `Bridge2` and in bit_global.py / columns_k.cpp, not on a definition in the repository. +5. **#370's assertion "x registers are never destinations"** is a sufficient, not a necessary, condition (#425's + scalar-interface lemma; #493's README) (checked). +6. **The outer already uses shift twiddles** (Nussbaumer synthetic transforms; U/00-introduction.tex:44-50); the + complex supplier is the H_0 butterfly layer (:114-121). A ring change does not remove it (C.5). +7. **Complement sinks** (sink = any complement of the source label, w·u = 1) are not covered by the earlier phase-frame + null result: the sink stays a plain label with a new projection. They are legal (C.3, gate 0), and Lemma R closes + them on every current decoder. +8. **The only untested spec freedom with a ceiling term ≥ ×1.15** is the schedule/ρ family (rows 5, 12, 13). The + large multipliers (×6.8 copy charge, ×1.16 window) are scope and family terms, not rules. + +Caveats of the census itself: + +- "Sink = any complement of the source label" (row 6) was the census's own reading of U/05-layers.tex:145-148; it is now + settled by C.3. +- "A plain swap of two scratch roles cannot gain" (row 4: shared gate frames give ≥ 2m on the swapped pair) is the + census's own argument and is not re-derived here. +- #448 and #451 are unreviewed in the hub's ledger, so the "conceded" status of split-residual hosting rests on the + contributors' own record. + +## C. Structural lemmas + +### C.1 Frame sandwich and the complex frame walls (argued; toy `c1_sandwich_toy.py` checked) + +**Lemma (sandwich).** Let R be a register at time t, and consider paths that carry no priced drop. Then + + span{frame(r, t′) : r's content reached R drop-free by t} ⊆ frame(R, t) ⊆ (span{L_q : target q that R's content reaches drop-free after t})^⊥. + +*Proof sketch.* The lower side is #446 Theorem A, applied with any register as origin. For the upper side, a target q +ends at L_q^⊥ because its terminal label absorbs the port gate (T_{u^⊥} = F·C_u^{−1} up to monomials). Chains are +monotone, and a copy taken at t sits at its parent's frame (common frame at the copy gate), so it inherits the +parent's future. Exactness uses neither side: both are accounting. + +**Consequences** on the complex unit (labels in F_2^9, 112 ports): + +- **(W1)** The common station of a term whose readers span u_a^⊥ is the point ⟨u_a⟩. A cut shared by all readers of a + term is therefore one point per term. +- **(W2)** A copy serving a face of four targets of rank-3 span has frame dimension ≤ 6. A group of eight copies whose + faces span rank 4 has a common frame of dimension ≤ 5. +- **(W3)** Run backwards on the cleanup, the lower side gives end(X) ≥ the join of the frames of every register that + X's restoration reads. + +**Leaving the sandwich is legal and priced.** The toy (n = 4) puts three readers whose labels span u_a^⊥ at a station +⟨w⟩ outside every u_i^⊥ and then takes a non-nested step to u_i^⊥: + +- both networks are exact on 64/64 basis columns; +- every child's Clifford rank equals d(A, B) = dim A + dim B − 2 dim(A ∩ B), including the non-nested rank-4 steps; +- the charge is 18 = 13 + 3·2 − 1 against the standard network's 13. + +Relaxing "targets avoid u_t" costs +2 data mass per relaxed target per call (C.7 prices this). + +### C.2 Lemma N: the port factor is a gauge, always paid (`c2_port_gauge.py`) + +**Setting.** C_v = ((1 + i)I + (1 − i)X_v)/2, so C_v² = X_v. The full transform is F = Π_{w ∈ orthonormal basis} C_w, +and T_{q^⊥} = F·C_q^{−1} (#514's repeated-axis identities). In the hub's controller a source family runs +⟨q⟩ → … → F and a target family runs 0 → … → q^⊥. Each data family saves exactly one unit (m − 1 instead of m), which +is the C_q gauge: (s − 1)vkT = 8·112·8 = 7168 on the complex side, of which copies take 4608 and D = 2560 remains. + +**Lemma N.** For a parent child Z = C^{⊗A}, + +- rank(C_q^{±1}Z) = rank Z − 1 if q ∈ span(A) with odd support; +- rank(C_q^{±1}Z) = rank Z + 1 if q ∉ span(A) and q ⊥ A. + +**Theorem N (proof).** With d(f, g) = dim f + dim g − 2 dim(f ∩ g), any path f0 → G → f1 costs at least d(f0, f1), +with excess + +- **target** (0 → q^⊥): d(0, G) + d(G, q^⊥) − d(0, q^⊥) = 2(dim G − dim(G ∩ q^⊥)) ∈ {0, 2}, which is 0 iff G ⊆ q^⊥; +- **source** (⟨q⟩ → L): 2(1 − dim(⟨q⟩ ∩ G)) ∈ {0, 2}, which is 0 iff q ∈ G. + +(dim G − dim(G ∩ q^⊥) ≤ 1 because q^⊥ is a hyperplane.) + +The route T_{fY}·T_{fX}^{−1} equals F modulo monomials *only if* dim fX + dim fY = n and fX ∩ fY = 0. The source's +saving and the target's saving are therefore tied: un-labelling one side alone leaves a rank-1 mismatch on the pair. + +**Consequence.** "y avoids u_t" is the geodesic condition of the endpoint frames, not an artifact of where the +factor is paid. Moving the rank-1 factor to the parent costs at least d(0, L) − d(0, q^⊥) = 1 per family. Leaving +the interval costs exactly 2. + +**Checks (exact Clifford).** + +- The F2 rank of B = Σqqᵀ equals the tableau child rank on 240 random C-products (n = 4..7). +- Detour excess is 0 on the geodesic set and exactly 2 otherwise: + + | n | geodesic | off-geodesic | + |---|---|---| + | 3 | 20 | 44 | + | 4 | 128 | 408 | + | 5 | 1072 | 4912 | + | 6 | 3740 | 24510 | + + The source and target families give the same counts. +- The rigid pairs at n = 3, 4 are a subset of the complementary pairs. The converse fails: complementary pairs need + not be rigid. +- The gauge descent rank − 1 holds in 9/9 controls. + +**Not reproduced here.** A run on the 112 retained ports of the #523 controller found rank(C_q Z) = rank Z + 1 on +2016/2016 idle children and 2016/2016 stage climbs (no parent object absorbs the gauge). It needs the controller's +generated data-phase files, which this package does not ship, so it is reported, not checked. + +### C.3 Lemma R: complement sinks are legal but pinned + +**Legal (gate 0, `c3_complement_gate0.py`, checked).** For an odd w with w·u = 1, the route T_{w^⊥}·T_{⟨u⟩}^{−1} has +Clifford rank n: + +- for every complement w at n = 3..6, and on 40 seeded samples at n = 9; +- it equals C^{⊗n} after monomial wrappers of the same class as the standard sink, on the tableau and on every basis + column (n ≤ 6); +- non-complements (w·u = 0) give rank n − 2. + +The port price is unchanged: Y: 0 → w^⊥ and X: ⟨u⟩ → F both cost n − 1. The geodesic interval is G ⊆ w^⊥, with +excess exactly 2 outside it. A corrector that the standard sink forbids is exact and correctly priced. So the sink +stays a plain label with a new projection, and the port gate stays a gauge (C_w instead of C_u). + +**Lemma R.** If the sources whose content reaches target t drop-free span u_t^⊥, the only admissible complement sink +of t is w_t = u_t. + +*Proof.* By #446 Theorem A the sink V_t = w_t^⊥ contains u_t^⊥, and V_t is a hyperplane. + +**Pinned (`c3_complement_taint.py`, checked).** The checks run on four complex words: main's #531 word, the width-7 +and four-cold provider words of #569, and the combined-eight-local word of #571. The closure starts every helper at frame 0, the most permissive choice, +so the result holds for every frame assignment of the same scalar word; the words' own entrance frames are not +needed (on the three vendored words the closure with them gives the same result). + +- The most permissive lower closure (helpers enter at 0; every centre may drop to 0 at the cut) has dimension 8 on + 112/112 targets, so w_t = u_t is forced on 112/112. +- The pure drop-free source taint of every target is exactly its Gram-orthogonal neighbourhood: 52 sources, span + u_t^⊥. Phase A contributes nothing to any target. +- Any w ≠ u_t breaks at least 20 of t's 52 lossless corrections (112/112 targets). + +A positive control removes the 4 correction gates of one target. The closure then reports dimension 7 and 2 +admissible sinks, so the instrument sees freedom when it exists. + +On these four words the obstruction is the decoder's lossless pattern, not the endpoint rule. A decoder whose pairing is not symmetric +would be needed, and C.6 shows the E8 pattern admits none at window ≤ 9. + +### C.4 Lemma Q: a degenerate unit is dominated by its quotient (`c4_quotient.py`) + +**Setting.** The ports span W (dim d), with radical rad = W ∩ W^⊥ (dim ρ) and Gram rank r = d − ρ. Write +π: W → W/rad. + +**Lemma Q.** + +- A copy of total j read at a common cut g (g lies in every target sink, so WLOG g ⊆ rad) costs + d(f_j, g) ≥ dim π(f_j). +- Summed over j, this is the quotient unit's reads-at-0 cost, which is ≥ Σ_j rank G[S_j, R_j] (#446 Theorem C at + Gram level). +- Every stage window contains W and is nondegenerate, so h ≥ r + 2ρ. + +Since X is non-increasing in a and in cst (§A.2), X_deg(s) ≤ X(s, r/k, x_quot) ≤ X(s, r/k, x_ThmC) for every s. +Star scope is Gram-level (an in-cap clique inside S_j has a nonsingular diagonal Gram block in every realisation), so +degenerate spans are not outside the ceiling's scope and add no (w, x) points. + +**Checks (exact ranks).** + +- **The paired-cube p = 3 toy:** d 4, ρ 2; copy cost 18 (reads at 0), 16 (optimum over all flags of rad), 12 + (quotient = Theorem C bound); window 6 vs quotient 2. +- **Paired cubes p = 3..12:** only the complex p = 3 cube is degenerate. +- **E8 + an extra vector (bit):** 81 → 72 = quotient 72, window 10 vs 8. +- **E8 + weight-2 isotropic decorations (complex), ρ = 1, 2, 3:** 80 / 88 / 96 → 72 = quotient, windows 11 / 13 / 15 + vs 9. +- **Random radicals:** 0 violations of "cut cost ≥ quotient cost" on 737 seeded instances. +- **Certified X:** each realisation sits below its quotient. + + | unit | quotient | realisation(s) | + |---|---|---| + | bit | 5.1598e-3 | 4.0462e-3 | + | complex (ρ = 1 / 2 / 3) | 4.5356e-3 | 3.6522e-3 / 3.0570e-3 / 2.6286e-3 | + +**Out of scope.** Repeated-label (vector-linear) decoders are a Gram-level class that Lemma Q does not close. + +### C.5 Lemma λ: a phase-frame butterfly needs √−1 (argued; instances checked by `c5_lambda.py`) + +**Lemma λ.** Let K be a directional kernel defined by its direction alone. If P_N(K ⊗ I)P_N^{−1} = K ⊗ I for the +e₁-fixing N, then K = aI + bX. If moreover H_0 = [[1, 1], [1, −1]] satisfies u·H_0 = D₁(aI + bX)D₂ with D₁, D₂ +invertible diagonal and u a unit, then (b/a)² = −1, i.e. the Walsh eigenvalue ratio λ = (a − b)/(a + b) = ±i. + +*Proof.* The first part is a 2 × 2 symbolic computation (T5). For the second, write D₁ = diag(d, d′) and +D₂ = diag(e, e′). Entrywise, d·a·e = u, d·b·e′ = u, d′·b·e = u and d′·a·e′ = −u. Multiplying the first and last +equations gives dd′ee′·a² = −u², and multiplying the middle two gives dd′ee′·b² = u². Hence a² = −b², so a and b are +units and (b/a)² = −1. With b = ±i·a, λ = (1 ∓ i)/(1 ± i) = ∓i. Writing λ needs a + b = a(1 ± i) invertible, and +(1 + i)(1 − i) = 2, so the ring must also make 2 invertible (H_0 itself has determinant −2). ∎ + +**Consequences.** + +- A payload ring in which −1 is not a square (Z[1/2]; Z/M with a prime factor ≡ 3 mod 4) or in which 2 is not + invertible (F2; even M) carries no phase-frame butterfly supplier. +- In a ring with √−1, such as the Fermat ring Z/(2^N + 1) where i = 2^{N/2} is a shift, the ring hosts the identical + C-network with the same paid Fourier-rank histogram and the same b. +- The odd-weight residuals that the phase calculus needs (U/03-motifs.tex:600) force an odd-form unit. For E8 this + means F2 rank 9 and h = 9, which is the structural part of b < c. +- Bit networks have signed-permutation endpoints per role for any payload alphabet. Each two-point butterfly level at + most doubles row support, so a length-8 transform needs ≥ 3 butterfly levels, with the same Fourier-rank mass as the + complex DFT₈. +- The outer already uses shift twiddles (B.3, item 6). + +**Checks (exact, sympy / modular).** + +- **T1–T3:** the product of three H_0 factors and three monomial twiddles equals the bit-reversed DFT₈. Over Z/17 it is + the length-8 NTT with root 2. Row support 8 needs 3 levels. +- **T4:** brute force over Z/M for the 16 odd moduli M ∈ {3, 5, 7, 9, 11, 13, 15, 17, 21, 25, 29, 33, 37, 41, 45, 65}: + solutions exist iff −1 is a square mod M, and λ² = −1 in every solution. +- **T5:** the commutation forces K = aI + bX. +- **T6:** C² = X and H_0 = b·S·C·S in Z/17 with i = 4. +- **T7:** there is no real solution. +- **T8:** weight-2-mod-4 residuals act as translations. + +### C.6 Asymmetric pairing uniqueness at the E8 pattern (`c6_asym.py`) + +**Setting.** A unit is (N over Q, B = W·Uᵀ over F2): + +- window = rank B (the pairing version of Lemma Q); +- a correction N_TS is lossless iff B_TS = 0 (#446 Theorem A, directed); +- β_j = rank B[R_j, A_j] (Theorem C); +- exactness is N∘B = diag. + +The gauge (U, W) ↦ (UP, WP^{−T}) fixes B, so "W ≠ U" means nothing by itself. A symmetric unit-diagonal F2 matrix of +rank r is congruent to I_r. + +**Result (SAT).** At the E8-linear decoder pattern (B_TS = 0 where G_TS ≠ 0, B_TT = 1), gauge-fixed on 8 +pairwise non-orthogonal lines (where the pattern forces B[K, K] = I, so U_K = W_K = [I_8 | 0]): + +- P112 at c = 9: "B ≠ Bᵀ" and "B ≠ B0 = (J + G) mod 2" are UNSAT with U and W both free; with U fixed to the E8 + labels and W free, "B ≠ Bᵀ" is UNSAT too (the "B ≠ B0" question was not run with U fixed); +- P120 at c = 9: the same two questions are UNSAT; +- c = 8: UNSAT, symmetric and non-symmetric (P120), and non-symmetric on P112; +- calibration: c = 9 without the extra constraint is SAT, with B = B0. + +So at window ≤ 9 the pairing is unique and every W ≠ U is a gauge. The UNSAT answers come from CaDiCaL (through +python-sat) without proof logs; the SAT calibration runs show that each encoding is satisfiable where it should be. + +**Off the E8 pattern.** An exact asymmetric P112 unit exists at copy cost 65 (+1) and window 9: N′∘B = diag on all +112 × 112 entries. Two of its targets take sinks w ≠ u and need 28 corrections instead of 52. In this verified unit one extra copy-rank +unit (65 instead of 64) frees exactly two sinks; no lower bound on the price of a freed sink is claimed. A directed +3-cycle toy (B non-symmetric, rank 2, +exact on 343 inputs) shows that the asymmetric class is larger in general. + +### C.7 Per-call descent pricing (`c7_descent_toy.py`, `c7_descent_price.py`) + +**Statement.** A descent of rank r followed by its re-climb costs exactly 2r rank units in the local word. It +therefore costs 2r units of data mass in every call, which is 2r copy-rank units by the deficit identity. There is no +fixed cost to share between uses. + +**Checks.** + +- **Exact toy (n = 5).** One reader reads three cheap terms at point stations ⟨u_a⟩, ⟨u_b⟩, ⟨u_c⟩, and each term's + readers span u_j^⊥. + - Four networks (standard, clones, direct descents, descents through 0) are exact on 224/224 basis columns. + - Every child, including the rank-2 non-comparable ones, has Clifford rank d(A, B). + - Each rank-1 descent costs +2, whether direct or through 0, and a reader at k point stations pays 2(k − 1). +- **Prices on the published profiles** (certified root, hosting held fixed): one rank-1 descent per local word costs + **−5.630% c on #555** (288 stage-replicas) and **−5.646% b on #568** (72 calls); two cost −11.26% / −11.29%. + +**Dominance within the price class (argued).** In the known designs (the complex factory, face and M-copy ledger and +the bit pair-term and star units; this list is a census of those designs, not a theorem), each use of a descent buys at +most one of the following: + +- one target removed from one last-read antichain (≤ |T_t| ≤ 7 private copies); +- two monotone arms for a copy register; +- two fixed pair-split conflicts; +- one supplied retired row. + +That is at most about 7 helpers' work. One rank-1 descent costs −5.65% b on #568, about 40 width-9 complex helpers +at 0.14% b each (§E.1). So within the class where every non-comparable step is one child of rank d(f, g) +paid in every call, a schedule with ≥ 1 paid descent is dominated by the best schedule without one. + +This is price-class dominance, not an impossibility. It does not cover a descent paid once per word. + +### C.8 Split residuals across hosting streams (argued) + +Split a helper residual of width w = a + b over two streams. #451 (chafreaky) shows that the identity +trace(D_{a+b} + I) − trace(D_a + D_b) = q^{2m−a−b}(q^a − 1)(q^b − 1) ≠ 0 is invariant under every invertible linear +change of storage; there is a complex analogue. So no relabelling makes an uncharged split exact. An exact split +needs one of: + +- a cross-term repair (≥ min(a, b) doubly paid coordinates); +- one helper per piece; +- a new hub primitive that prices split routing. + +The "one further route factor per helper selector" of #448 (higherbeing) is the last kind. + +Even uncharged, the gain is small on the current complex frontier. #569 hosts all residual supply and pays the idle +remainder {3: 1200, 7: 48, 48: 1808} (90,720 coordinates; checked in `e2`). #588 uses the same hosting regime, but +its remainder differs and is not reproduced here. φ(r) = r((m/r)^q − 1) is concave, so with free +splitting the best case puts the whole remainder in rank-48 children: 1890·φ(48) = 60.98 against 78.06 today, a +saving of 17.08 D-units. That is **at most +0.67% b**, and it ignores windows and timing. + +Status: argued (concavity bound on #569's reproduced hosting profile; the profile itself is checked in `e2`). + +## D. Design-free helper bounds (`d1_cover_numbers.py`, `d2_coupled_count.py`, `d3_carrier_ledger.py`) + +**Model.** Registers are monotone frame chains: + +- helpers 0 → F; +- sources ⟨u_s⟩ → F; +- targets 0 → u_t^⊥. + +Gates act at a common frame. The only drops are the decoder copies: 9 totals at p^⊥ (bit), 8 rank-8 centres +(complex). The demand is the drop-free source → terminal map. + +**Crossing lemma (argued; #446 Thm A plus the sandwich).** Fix a level d. Every drop-free path s → q crosses level d +exactly once, inside one register's climb a → b, so N = Σ_e α_e β_eᵀ over the level-d crossing events, with +supp β_e ⊆ S(a_e) and supp α_e ⊆ Q(b_e^⊥). Each register crosses each level at most once. Only the extreme levels +bind: at the middle levels the rectangle areas are below the free data crossings. + +**Cover numbers (exact).** + +| side | per-source cover | per-terminal cover | evidence | +|---|---|---|---| +| complex P112 (F2^9) | 2 | 2 | two proper hyperplane sections cover every source's 52 readers (112/112; max section 32; 26 with port-spanned frames only, still 2 sections) | +| bit #555 (Q^8, E7 = the 63 lines ⊥ a source) | 3 | 3 | exhaustive census of the 8821 hyperplane flats of E7: two cover at most 52 of 63 (≥ 11 left), three D6 flats (30 lines each) cover all; on the terminal side at least 6 live sources stay uncovered by any two flats (all 120 terminals) | + +**Floors.** + +| side | sink-only targets | strict (y → y mixing allowed) | shipped | +|---|---|---|---| +| bit | 2·111 − ⌊111/11⌋ = **212** | max(3·111 − 222, 3·120 − 222) = **138** | 439 | +| complex | 112 − ⌊112/20⌋ = **107** (108 with port-spanned frames) | 2·112 − 224 = **0** | 496 (+ 8 centres) | + +**Coupling adds 0 (checked).** The coupled cover model (hop areas through all levels, exact unit rectangle caps +32/32/32/36/32/32/32 for complex d = 2..8, exhaustive for d = 2..5 and by the symmetry d ↔ 10 − d above; end +patterns; bit flat sizes 1, 3, 6, 12, 20, 36, 63 per rank, enumerated in E7, with maximality in E8 from the +root-subsystem chain A1 ⊂ A2 ⊂ A3 ⊂ D4 ⊂ D5 ⊂ E6 ⊂ E7) has integer count optima 212 / 138 / 107 / 0 (HiGHS, zero gap), +identical to the single-cut bounds. The shipped words are feasible in it. With the shipped data ladders held fixed the +floors rise to 222 (bit) and 146 / 123 (complex). + +**Corrections.** + +- **The census of E7's hyperplane flats.** An earlier sampled census found 2258 flats; the exhaustive census has 8821 + (5040 / 2016 / 1008 / 666 / 63 / 28 of sizes 10 / 13 / 16 / 21 / 30 / 36). The sampled set is reproduced (seed 1) and + undercounts the small types; the cover number 3 is unchanged. +- **The "224 carriers = 2 per source" complex floor is a design choice.** #531 gives every source exactly 3 level-2 + crossings (X_s + 2 helpers) into port-spanned 2-dim frames whose section is 20 (3 × 20 = 60 ≥ 52), while two + sections already cover every source. The 224 is a property of the section type, not of the format. +- **Carriers are register-neutral in the calibrated ledger (checked).** The register ledger rebuilt from #531's real + tile objects (168 block-local planes, 168 keys, mate matching 2) reproduces 224 scratch + 168 face copies + 112 M + copies = 504, with B = N2 + K + R − 112 + waste. The carrier stage and the face stage together cost 2·N2 − 112 + + waste for any edge cover. The cover axis therefore only enters through wasted single-variant butterflies: + - rebuilding the same planes from cross-tetrad edges costs +168 (12 per block, exact); + - tetrad edges give waste 0 (CP-SAT over all three splits). + +**What the floors certify.** At most 48% (bit, sink-only, 212/439) / 22% (complex, 107/496 helpers without the 8 +centres) of the shipped helper count is design-free necessary. No single-cut or coupled cover argument closes the helper gap that §A.5 identifies as the whole headroom. + +## E. Complex helper prices and the moment-cost census (`e1_run_census.py`, `e2_helper_prices.py`) + +### E.1 Price per helper by class and width on #569 + +The b gain per deleted helper is measured as follows: + +- the helper is removed in all 72 calls; +- its width returns to the idle remainders; +- hosting is re-solved (the LP relaxation of the whole-owner model; integer CP-SAT spot checks at k = 1, not + reproduced here, agreed with it to < 0.002% b). + +The control reproduces #569's hosting (remainder {3: 1200, 7: 48, 48: 1808}, b = 1.602631811·10⁻³). + +| cell (count) | width | % b per helper, k = 1 (checked) | k = 8 / 14 / whole cell (recorded) | +|---|---|---|---| +| factory scratch (216) | 9 | 0.140 | 0.142 / 0.143 / 0.179 | +| face copy (64) | 9 | 0.134 | 0.140 / 0.141 / 0.151 | +| face-copy entrant (72) | 8 | 0.105 | 0.102 / 0.101 / 0.081 | +| face-copy provider (32) | 7 | 0.075 | 0.069 / 0.062 / 0.050 | +| M-copy entrant (56) | 8 | 0.111 | 0.111 / 0.109 / 0.098 | +| rank-4 pivot (48) | 5 | 0.039 | 0.039 / 0.036 / 0.032 | +| rank-5 pivot (8) | 4 | 0.042 | 0.041 / – / – | + +**Width law.** Price = local fee saved − hosting offset, where the offset is the increase of the hosting LP objective. +The offset depends on width only: cells of equal width have identical LP objective increases (checked). Its share of +the local fee at k = 1 (checked) is: + +| width | 9 | 8 | 7 | 5 | 4 | +|---|---|---|---|---|---| +| offset share, k = 1 | 6.3–6.6% | 17.0–17.9% | 31.5% | 57.4% | 45.4% | + +The share is not monotone in width (w4 sits between w7 and w5). At larger k the w7 share rises to 55% and the w5 share +to 65% (recorded in `data/prices/helper-price-table.json`). One conversion constant links all cells: fee saved minus offset is 25.64–25.66 moment units per 1% b. + +A count-based "0.11% per helper" is therefore about right for the width-8 entrants (0.105–0.111), overprices the +width-7 providers by about 1.5× (0.075) and the rank-4/5 pivots by 2.6–2.8× (0.039–0.042), and underprices the +width-9 scratch and face copies by about 25% (0.134–0.140). Summed k = 1 marginals give: + +| class | share of the marginal helper cost | % b | +|---|---|---| +| factory scratch | 53% | 30.2 | +| face copies | 32% | 18.5 | +| M copies | 15% | 8.4 | + +Full table, including the mixed-class runs: `data/prices/helper-price-table.json` (k > 1 rows recorded). + +### E.2 Moment-cost census by class (checked) + +The F-share of a class is its share of Σφ = D at the word's own root. The all-single-run ceiling is the supplier value +if each register of the class climbed in one child, with hosting proportional. + +**#555** (R = 439; 288 stage-replicas): + +| class | n | runs | mean run | stops/register | F-share | all-single-run ceiling | +|---|---|---|---|---|---|---| +| line-born carriers (0,1,2,…) | 205 | 1120 | 1.46 | 4.46 | 29.5% | +14.75% c | +| cell-born (0,2,…) | 153 | 686 | 1.78 | 3.48 | 21.2% | +9.60% | +| line → quad/D6 keepers and totals | 80 | 349 | 1.83 | 3.36 | 10.7% | +4.35% | +| quad-born | 1 | 4 | 2.00 | 3.00 | 0.1% | +0.05% | +| data x / data y | 111 / 111 | 539 / 213 | 1.44 / 3.65 | – | 14.1% / 10.4% | – | + +Copies take 0.7% and the idle remainder 13.4%. + +**#569** (R = 504; width-7 provider word for all 72 calls): + +| class | n | runs | mean run | stops/register | F-share | all-single-run ceiling | +|---|---|---|---|---|---|---| +| factory scratch | 216 | 1304 | 1.49 | 5.04 | 32.5% | +16.4% b | +| face copies | 168 | 696 | 1.98 | 3.14 | 21.9% | +9.1% | +| M copies | 112 | 504 | 1.43 | 3.50 | 12.4% | +4.9% | + +Data take 28.3%, centres 1.8% and the idle remainder 3.0%. The published global profile is reproduced exactly from +63 width-7 calls, 9 four-cold calls and the remainder. + +## F. What the results imply + +**Cost structure (result).** Under S2 the ceiling is set by the copy charge and the B_K idle structure (A.7); on the +real words the headroom is helper cost, 87–93% of the log-gap (A.5). A change inside the local word is paid in every +call: the local word runs 288 times (stage-replicas) in #555's bit pipeline and 72 times in #568's complex pipeline, +and by the deficit identity each rank unit added per local word lowers D by one per call. On the published profiles one +rank unit per local word costs 2.82% of c (#555) and 2.82% of b (#568): half the checked price of a rank-1 descent +(C.7), and the same size as one copy-rank unit per stage (+2.8% of X at s = 9, A.3). What such a change unlocks (a +shared station, a freed sink, a removed copy, a supplied row) is a gain fixed per word. + +**Break-even.** A change that costs Δ rank units in every local word pays only if its per-word gain exceeds about +2.8·Δ % of the supplier value. On the complex side that is about 20·Δ width-9 helpers (0.14% b each, E.1). The +per-call prices of C.1, C.2, C.6 and C.7 are all of this form: +2 per relaxed target per call, at least 1 per +un-gauged family per call, one copy-rank unit for the two sinks freed in the verified asymmetric unit, and 2r per +rank-r descent per call. + +**Open problems.** + +1. **Per-word enablers.** A mechanism charged once per word or per outer level instead of per call, such as a descent, + gauge change or station hoisted out of the local word. At 1/72 of its per-call price a rank-1 descent would cost + about 0.08% b, roughly half a width-9 helper. The current interface has no such primitive (B.2 rows 1, 3, 24). +2. **A non-star decoder.** The copy charge is the largest scope term (×6.8 at the best s, ×2.8 at s = 9; A.7). On the + E8 pattern the pairing is unique at window ≤ 9 (C.6), and on the four complex words checked the lossless pattern + pins every sink (C.3). Lowering x therefore needs a different unit or decoder; for scale, x = 54/102 (bit) and + 56/104 (complex) would give X* = 8.25·10⁻³ and 6.80·10⁻³ (A.6). +3. **The schedule/ρ freedom.** Any permutation ρ is spec-legal, and one bank pair per invocation is a convention (B.2 + rows 5, 12, 13). The B_K idle terms are worth ×1.15 to ×2.15 (A.7). +4. **New skeletons.** The design-free floors certify at most 48% (bit, 212/439) and 22% (complex, 107/496) of today's + helper counts (D). The other 52% and 78% of the helpers are not shown necessary by any argument here. + +## Files + +- `scripts/`: one check per claim group, plus shared code. + - Shared: `report.py` (PASS/FAIL, paths), `cert.py` (rational-interval ln/expm1, certified roots), `skel.py` + (skeleton slots, variants), `e8units.py` and `minrank_sat.py` (E8 geometry, SAT encodings), `d_geometry.py`, + `e_hosting.py` (the hosting LP and the moment root). + - Driver and step 0: `run_all.py`, `provenance.py`. +- `data/vendor/`: inputs copied from open PRs (`SOURCES.json` gives PR, author, commit, path, git blob id). +- `data/ceiling/`, `data/census/`, `data/toys/`, `data/prices/`: small inputs (#568's recorded idle remainder, the + census anchors, the p = 3 paired-cube instance, #569's call dispatch with its source blob id, the deleted-helper + specs and the recorded price table). +- `DEPENDS.json`: files of main read by the checks, by sha256. +- `MANIFEST.sha256`: every file of the package. + +## Credits + +Prepared by DreamingOfClouds with Claude Opus 5.5 (Anthropic), via Claude Code; Apache-2.0. See `NOTICE.md` for the +PRs whose words, pipelines and results are used. diff --git a/research/format-limits/SOURCES.json b/research/format-limits/SOURCES.json new file mode 100644 index 0000000000..140316e5c4 --- /dev/null +++ b/research/format-limits/SOURCES.json @@ -0,0 +1,77 @@ +{ + "description": "Files copied unchanged (or gzip-compressed) from open PRs of CrocSwap/integer-mult-bounds. blob = git blob id of the file at the cited commit (for a .gz copy of a non-.gz source: of the decompressed content); scripts/provenance.py recomputes it.", + "files": [ + { + "file": "data/vendor/pr543/EXPECTED.json", + "pr": 543, + "author": "eumemic", + "commit": "2065fe4f72a914d907f1046603f5a36f17018535", + "source_path": "research/e8-bit-r420/EXPECTED.json", + "blob": "b61d859826246e0c3dabbe096e57ad7015eadfd5", + "used_for": "profiles and bit c of the R420 word (nine and eleven stages): axiom (P), Lemma 2" + }, + { + "file": "data/vendor/pr545/EXPECTED.json", + "pr": 545, + "author": "DreamingOfClouds", + "commit": "376426f3b2b26ab430d10baf16bbd9ff42990a7c", + "source_path": "research/e8-punctured111-star/EXPECTED.json", + "blob": "ac7f102363a64ae19ba4a3edda9176f0b17ae9dc", + "used_for": "profile and bit c of the punctured R489 word (eleven stages): axiom (P), Lemma 2" + }, + { + "file": "data/vendor/pr555/EXPECTED.json", + "pr": 555, + "author": "eumemic", + "commit": "65a6bc19f820c8b1873f65a517bcf70cd6887223", + "source_path": "research/e8-bit-p111/EXPECTED.json", + "blob": "c8ad4439e83f07bcda437598d6a4c31f4e65f2a9", + "used_for": "profiles, bit c, rank mass, hosting counts and local histogram of the p111 word" + }, + { + "file": "data/vendor/pr555/bitE8mut-p111.json.gz", + "pr": 555, + "author": "eumemic", + "commit": "65a6bc19f820c8b1873f65a517bcf70cd6887223", + "source_path": "research/e8-bit-p111/data/bitE8mut-p111.json.gz", + "blob": "bdbb95aa970647bd52895c120b494f0f591f3f87", + "used_for": "the bit word (v = 111, R = 439): run replay, cover numbers, run census" + }, + { + "file": "data/vendor/pr568/PLAN.json.gz", + "pr": 568, + "author": "jeremykothe2", + "commit": "71c99ac935a33bb7b59a1b4a7af8725a939b0b90", + "source_path": "research/complex-multicold/data/PLAN.json", + "blob": "c1b711faccd5ea2f635b31e0e06bfe3a5ccc1948", + "used_for": "global profile and idle windows of the complex word (gzip of the original; blob id of the decompressed file)" + }, + { + "file": "data/vendor/pr569/width7-eight-FULL-WORD.json.gz", + "pr": 569, + "author": "DominikScholz", + "commit": "1424da81263a5305b35e4cf74ef686c275f03f3f", + "source_path": "research/larger-gain/providers/width7/eight/FULL-WORD.json.gz", + "blob": "d4f2dae82814ae4c7553c08e0dc39a1c383e3e3d", + "used_for": "width-7 provider word (63 of 72 calls): taint rigidity, run census, helper prices" + }, + { + "file": "data/vendor/pr569/fourcold-eight-FULL-WORD.json.gz", + "pr": 569, + "author": "DominikScholz", + "commit": "1424da81263a5305b35e4cf74ef686c275f03f3f", + "source_path": "research/larger-gain/providers/fourcold-eight/word/FULL-WORD.json.gz", + "blob": "cdf6203dc4f542bf1bfcdc802646c1da418fea4b", + "used_for": "four-cold provider word (9 of 72 calls): taint rigidity, data runs, helper prices" + }, + { + "file": "data/vendor/pr571/combined-eight-local-FULL-WORD.json.gz", + "pr": 571, + "author": "DominikScholz", + "commit": "b7bdc5a8de18fcf418cfb9c7d83a2b1097a5e4a3", + "source_path": "research/structural-gain/frontier-composition/combined-eight-local/FULL-WORD.json.gz", + "blob": "f12928699315f163629b08b67c4be2678e9cf3d0", + "used_for": "combined provider word: taint rigidity" + } + ] +} \ No newline at end of file diff --git a/research/format-limits/data/ceiling/gap568-inputs.json b/research/format-limits/data/ceiling/gap568-inputs.json new file mode 100644 index 0000000000..1406ab33ca --- /dev/null +++ b/research/format-limits/data/ceiling/gap568-inputs.json @@ -0,0 +1,10 @@ +{ + "description": "Paid idle remainder of #568's whole-residual hosting (global, all 72 calls): rank -> number of children, recorded from our replay of #568's PLAN (jeremykothe2, commit 71c99ac, research/complex-multicold/data/PLAN.json). Its 4,018 children match the '4,018 positive idle remainders' of #568's README (research/complex-multicold/README.md:22); 88,864 of the 387,072 skeleton idle mass stay paid, the rest is hosted by helper runs. Used only for steps D/E of the #568 gap decomposition (scripts/a4_gap.py).", + "idle_remainder": { + "1": 93, + "2": 93, + "3": 2118, + "7": 1, + "48": 1713 + } +} \ No newline at end of file diff --git a/research/format-limits/data/census/anchors.json b/research/format-limits/data/census/anchors.json new file mode 100644 index 0000000000..941d1ef8a7 --- /dev/null +++ b/research/format-limits/data/census/anchors.json @@ -0,0 +1,440 @@ +[ + { + "row": 0, + "path": "docs/research/community-pr531-review.md", + "line": 120, + "needle": "the following remain explicit interface assumptions" + }, + { + "row": 0, + "path": "docs/research/community-pr531-review.md", + "line": 134, + "needle": "independently certified** in this integration" + }, + { + "row": 1, + "path": "research/direct-delivery504-global/code/audit_local.py", + "line": 64, + "needle": "('common frame',r,cur[r[1]],f)" + }, + { + "row": 1, + "path": "research/e8-bit-carrier-skeleton/code/bit/checkers/legality_h.cpp", + "line": 11, + "needle": "ADD not in common frame" + }, + { + "row": 1, + "path": "research/e8-lemma-g-lean/LemmaG/Stream.lean", + "line": 106, + "needle": "WellLabelled" + }, + { + "row": 1, + "path": "upstream/build/sections/03-motifs.tex", + "line": 157, + "needle": "All incoming and outgoing" + }, + { + "row": 1, + "path": "upstream/build/sections/04-swap.tex", + "line": 111, + "needle": "assignment being common to every wire at that gate" + }, + { + "row": 2, + "path": "notes/general-clifford-frames.tex", + "line": 21, + "needle": "degenerate" + }, + { + "row": 2, + "path": "research/e8-bit-carrier-skeleton/code/bit/checkers/gram_frames.py", + "line": 46, + "needle": "'degenerate frame'" + }, + { + "row": 2, + "path": "upstream/build/sections/03-motifs.tex", + "line": 154, + "needle": "assign an invertible" + }, + { + "row": 2, + "path": "upstream/build/sections/03-motifs.tex", + "line": 203, + "needle": "A label is a nondegenerate subspace of a fixed bilinear space" + }, + { + "row": 2, + "path": "upstream/build/sections/04-swap.tex", + "line": 110, + "needle": "rational $m\\times m$ matrix to each terminal" + }, + { + "row": 3, + "path": "research/direct-delivery504-global/code/audit_local.py", + "line": 45, + "needle": "contains(frames[a],frames[b]) and rank==len(frames[b])-len(frames[a])>0" + }, + { + "row": 3, + "path": "research/direct-delivery504-global/code/audit_local.py", + "line": 128, + "needle": "centre_step_not_nested" + }, + { + "row": 3, + "path": "research/e8-bit-carrier-skeleton/code/bit/checkers/legality_h.cpp", + "line": 11, + "needle": "illegal or mispriced MOVE" + }, + { + "row": 3, + "path": "research/e8-lemma-g-lean/LemmaG/Stream.lean", + "line": 111, + "needle": "RecipesExact" + }, + { + "row": 3, + "path": "upstream/build/sections/03-motifs.tex", + "line": 352, + "needle": "The only decreasing" + }, + { + "row": 3, + "path": "upstream/build/sections/05-layers.tex", + "line": 83, + "needle": "including on decreasing edges" + }, + { + "row": 4, + "path": "research/direct-delivery504-global/code/audit_local.py", + "line": 101, + "needle": "assert rows['L',r]==expected" + }, + { + "row": 4, + "path": "research/e8-bit-carrier-skeleton/code/bit/checkers/columns_k.cpp", + "line": 57, + "needle": "need(row(i)[w]==want" + }, + { + "row": 4, + "path": "upstream/build/sections/03-motifs.tex", + "line": 46, + "needle": "their initial values may be arbitrary" + }, + { + "row": 4, + "path": "upstream/build/sections/03-motifs.tex", + "line": 98, + "needle": "and restores every auxiliary value" + }, + { + "row": 4, + "path": "upstream/build/sections/03-motifs.tex", + "line": 581, + "needle": "on every role, including auxiliary roles" + }, + { + "row": 4, + "path": "upstream/build/sections/05-layers.tex", + "line": 150, + "needle": "including roles whose initial scratch" + }, + { + "row": 5, + "path": "research/e8-bit-carrier-skeleton/code/bit/checkers/columns_k.cpp", + "line": 56, + "needle": "std::swap(row(bank*v+i)[w],row((bank+1)*v+i)[w])" + }, + { + "row": 5, + "path": "research/e8-early-reset-kernel/bit_global.py", + "line": 55, + "needle": "out.append(dict(kind='exchange'))" + }, + { + "row": 5, + "path": "upstream/build/sections/03-motifs.tex", + "line": 99, + "needle": "permutation exchanging $X_a$ and $Y_a$" + }, + { + "row": 5, + "path": "upstream/build/sections/03-motifs.tex", + "line": 628, + "needle": "exchanges $X_a,Y_a$ and fixes each scratch role" + }, + { + "row": 5, + "path": "upstream/build/sections/04-swap.tex", + "line": 107, + "needle": "induce a permutation $\\rho$" + }, + { + "row": 6, + "path": "upstream/build/sections/03-motifs.tex", + "line": 235, + "needle": "The prescribed terminal labels are" + }, + { + "row": 6, + "path": "upstream/build/sections/03-motifs.tex", + "line": 240, + "needle": "Y_a&0&U_a^\\perp" + }, + { + "row": 6, + "path": "upstream/build/sections/05-layers.tex", + "line": 128, + "needle": "so they add no recursive calls" + }, + { + "row": 6, + "path": "upstream/build/sections/05-layers.tex", + "line": 146, + "needle": "turn every endpoint kernel into a" + }, + { + "row": 7, + "path": "upstream/build/sections/03-motifs.tex", + "line": 233, + "needle": "U_a=\\langle u_a\\rangle" + }, + { + "row": 8, + "path": "research/e8-bit-carrier-skeleton/code/bit/checkers/columns_k.cpp", + "line": 39, + "needle": "copies==NCOPY" + }, + { + "row": 8, + "path": "research/e8-bit-carrier-skeleton/code/bit/checkers/legality_h.cpp", + "line": 1, + "needle": "the copied-centre count is the macro NCOPY" + }, + { + "row": 9, + "path": "upstream/build/sections/03-motifs.tex", + "line": 221, + "needle": "For the complex network, take instead" + }, + { + "row": 9, + "path": "upstream/build/sections/03-motifs.tex", + "line": 225, + "needle": "The scalar domain need not equal the label field" + }, + { + "row": 11, + "path": "upstream/build/sections/03-motifs.tex", + "line": 360, + "needle": "=Wm-2N+2L" + }, + { + "row": 11, + "path": "upstream/build/sections/04-swap.tex", + "line": 122, + "needle": "s_k; suffix _q = re-solved at the deleted profile's own b", + "deleted_helpers": "helper indices h (register 224 + h) deleted in every call", + "lp_objective": "optimal value of the hosting LP (sum of idle-remainder fees)", + "idle_remainder": "idle remainder ranks of the LP solution: rank -> (fractional) count", + "b": "moment root b_float of local profiles plus idle remainders, W = 7168", + "pct_b_total": "100 (b / b_control - 1)", + "pct_b_per_helper": "pct_b_total / k", + "local_fee_saved": "sum over the 72 calls of r ((73 / r)^q - 1) over the deleted helpers' paid climbs, q = b_control", + "hosting_offset": "lp_objective - control lp_objective (cost of returning the deleted widths to the idle remainders)", + "offset_share_pct": "100 hosting_offset / local_fee_saved" + }, + "q_published": 0.00160263181098207, + "status_recomputed": "recomputed by verify.sh (scripts/e2_helper_prices.py)", + "status_recorded": "recorded (not re-run by verify.sh)", + "control": { + "name": "ctl", + "k": 0, + "lp_objective": 78.0585701066651, + "idle_remainder": { + "3": 1200.0, + "7": 47.99999999999999, + "48": 1808.0000000000002 + }, + "b": 0.0016026318109820283, + "mass": 520704.0, + "status": "recomputed by verify.sh (scripts/e2_helper_prices.py)" + }, + "rows": [ + {"name": "F9_k1", "cell": "F9", "class_description": "factory scratch register, width 9", "class_size": 216, "k": 1, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [16], "lp_objective": 78.30160559083036, "idle_remainder": {"3": 1185.6, "7": 48.0, "48": 1822.4}, "b": 0.0016048723869705752, "mass": 520704.0, "pct_b_total": 0.13980603487298016, "pct_b_per_helper": 0.13980603487298016, "local_fee_saved": 3.8274643062908424, "hosting_offset": 0.24303548416526155, "offset_share_pct": 6.349777939556668, "status": "recomputed by verify.sh (scripts/e2_helper_prices.py)"}, + {"name": "F9_k8", "cell": "F9", "class_description": "factory scratch register, width 9", "class_size": 216, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [16, 47, 74, 101, 128, 155, 182, 209], "lp_objective": 80.00285397998694, "idle_remainder": {"3": 1084.8, "7": 48.0, "48": 1923.2000000000003}, "b": 0.0016208426535987194, "mass": 520704.0, "pct_b_total": 1.1363085701844522, "pct_b_per_helper": 0.14203857127305652, "local_fee_saved": 30.79043849690584, "hosting_offset": 1.9442838733218366, "offset_share_pct": 6.3145702634836445, "status": "recorded (not re-run by verify.sh)"}, + {"name": "F9_k14", "cell": "F9", "class_description": "factory scratch register, width 9", "class_size": 216, "k": 14, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [12, 29, 47, 62, 78, 93, 108, 124, 139, 155, 170, 186, 201, 216], "lp_objective": 81.46106688497837, "idle_remainder": {"3": 998.3999999999999, "7": 48.0, "48": 2009.6}, "b": 0.0016347175166030905, "mass": 520704.0, "pct_b_total": 2.002063443468116, "pct_b_per_helper": 0.143004531676294, "local_fee_saved": 53.79497323902656, "hosting_offset": 3.402496778313264, "offset_share_pct": 6.324934419420548, "status": "recorded (not re-run by verify.sh)"}, + {"name": "F9_k28", "cell": "F9", "class_description": "factory scratch register, width 9", "class_size": 216, "k": 28, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [11, 20, 28, 38, 45, 53, 61, 69, 76, 84, 92, 99, 107, 115, 123, 130, 138, 146, 153, 161, 169, 177, 184, 192, 200, 207, 215, 223], "lp_objective": 84.86356366329149, "idle_remainder": {"3": 796.8000000000001, "7": 48.0, "48": 2211.2}, "b": 0.0016681143627928093, "mass": 520704.0, "pct_b_total": 4.08593860187112, "pct_b_per_helper": 0.14592637863825428, "local_fee_saved": 107.58918598929226, "hosting_offset": 6.8049935566263855, "offset_share_pct": 6.324979126901887, "status": "recorded (not re-run by verify.sh)"}, + {"name": "F9_k216", "cell": "F9", "class_description": "factory scratch register, width 9", "class_size": 216, "k": 216, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223], "lp_objective": 193.3759093686693, "idle_remainder": {"1": 30.0, "32": 1832.0625000000002, "48": 3584.0}, "b": 0.002220939773836586, "mass": 520704.0, "pct_b_total": 38.5807868418438, "pct_b_per_helper": 0.178614753897425, "local_fee_saved": 829.9218475782271, "hosting_offset": 115.31733926200421, "offset_share_pct": 13.894963676219474, "status": "recorded (not re-run by verify.sh)"}, + {"name": "F9_k216_q", "cell": "F9", "class_description": "factory scratch register, width 9", "class_size": 216, "k": 216, "whole_class": true, "q": 0.002220939773836586, "deleted_helpers": [2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223], "lp_objective": 268.0304197146809, "idle_remainder": {"1": 30.0, "32": 1832.0625, "48": 3584.0}, "b": 0.002220939773836586, "mass": 520704.0, "pct_b_total": 38.5807868418438, "pct_b_per_helper": 0.178614753897425, "local_fee_saved": 829.9218475782271, "hosting_offset": null, "offset_share_pct": null, "status": "recorded (not re-run by verify.sh)", "note": "re-solved at q = this row's own b (the hosting LP at the deleted profile's own pressure root); the objective is not comparable with the fixed-q rows, b is the same as in the fixed-q row"}, + {"name": "P9_k1", "cell": "P9", "class_description": "face copy, width 9", "class_size": 64, "k": 1, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [318], "lp_objective": 78.30160559083036, "idle_remainder": {"3": 1185.6, "7": 48.0, "48": 1822.4}, "b": 0.0016047716270276408, "mass": 520704.0, "pct_b_total": 0.1335188800664966, "pct_b_per_helper": 0.1335188800664966, "local_fee_saved": 3.666486229436238, "hosting_offset": 0.24303548416526155, "offset_share_pct": 6.628566670019402, "status": "recomputed by verify.sh (scripts/e2_helper_prices.py)"}, + {"name": "P9_k8", "cell": "P9", "class_description": "face copy, width 9", "class_size": 64, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [240, 252, 268, 286, 295, 318, 342, 362], "lp_objective": 80.00285397998694, "idle_remainder": {"3": 1084.8, "7": 48.0, "48": 1923.2000000000003}, "b": 0.0016205242294818414, "mass": 520704.0, "pct_b_total": 1.1164397447501972, "pct_b_per_helper": 0.13955496809377466, "local_fee_saved": 30.291651938768798, "hosting_offset": 1.9442838733218366, "offset_share_pct": 6.418546856579463, "status": "recorded (not re-run by verify.sh)"}, + {"name": "P9_k14", "cell": "P9", "class_description": "face copy, width 9", "class_size": 64, "k": 14, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [239, 243, 252, 256, 269, 280, 288, 293, 302, 318, 334, 343, 355, 364], "lp_objective": 81.46106688497837, "idle_remainder": {"3": 998.3999999999999, "7": 48.0, "48": 2009.6}, "b": 0.0016342239152122373, "mass": 520704.0, "pct_b_total": 1.9712640179562424, "pct_b_per_helper": 0.14080457271116018, "local_fee_saved": 53.03484549124345, "hosting_offset": 3.402496778313264, "offset_share_pct": 6.415587236650001, "status": "recorded (not re-run by verify.sh)"}, + {"name": "P9_k64", "cell": "P9", "class_description": "face copy, width 9", "class_size": 64, "k": 64, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [238, 239, 240, 241, 242, 243, 244, 245, 250, 251, 252, 253, 254, 255, 256, 257, 266, 267, 268, 269, 271, 278, 279, 280, 281, 283, 286, 287, 288, 289, 290, 291, 292, 293, 295, 298, 300, 302, 303, 304, 305, 307, 318, 319, 330, 331, 334, 335, 336, 337, 342, 343, 346, 348, 354, 355, 358, 360, 362, 363, 364, 365, 374, 376], "lp_objective": 93.61284109323972, "idle_remainder": {"3": 278.40000000000003, "7": 48.0, "48": 2729.6}, "b": 0.0017579830181498803, "mass": 520704.0, "pct_b_total": 9.693505776143251, "pct_b_per_helper": 0.1514610277522383, "local_fee_saved": 242.42854536937412, "hosting_offset": 15.554270986574622, "offset_share_pct": 6.416022899809713, "status": "recorded (not re-run by verify.sh)"}, + {"name": "P8_k1", "cell": "P8", "class_description": "face copy of an entrant, width 8", "class_size": 72, "k": 1, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [224], "lp_objective": 78.64325928997846, "idle_remainder": {"1": 12.600000000000128, "3": 1201.62, "7": 52.5, "48": 1818.98}, "b": 0.0016043095787383996, "mass": 520704.0, "pct_b_total": 0.10468828491201343, "pct_b_per_helper": 0.10468828491201343, "local_fee_saved": 3.2696910771915357, "hosting_offset": 0.5846891833133583, "offset_share_pct": 17.882092513020236, "status": "recomputed by verify.sh (scripts/e2_helper_prices.py)"}, + {"name": "P8_k8", "cell": "P8", "class_description": "face copy of an entrant, width 8", "class_size": 72, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [224, 233, 258, 285, 320, 357, 372, 383], "lp_objective": 82.73608357317183, "idle_remainder": {"1": 100.79999999999998, "3": 1212.96, "7": 84.0, "48": 1895.8399999999995}, "b": 0.0016156812055760665, "mass": 520704.0, "pct_b_total": 0.8142478206545789, "pct_b_per_helper": 0.10178097758182236, "local_fee_saved": 25.413989004777555, "hosting_offset": 4.677513466506724, "offset_share_pct": 18.405270678394494, "status": "recorded (not re-run by verify.sh)"}, + {"name": "P8_k14", "cell": "P8", "class_description": "face copy of an entrant, width 8", "class_size": 72, "k": 14, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [225, 230, 235, 249, 270, 285, 301, 321, 347, 361, 371, 378, 383, 388], "lp_objective": 87.15428796054395, "idle_remainder": {"1": 173.0, "2": 45.0, "3": 1437.6666666666667, "48": 1962.6666666666667}, "b": 0.0016252010857745894, "mass": 520704.0, "pct_b_total": 1.4082632478592538, "pct_b_per_helper": 0.1005902319899467, "local_fee_saved": 44.74988564622837, "hosting_offset": 9.095717853878853, "offset_share_pct": 20.325678429181554, "status": "recorded (not re-run by verify.sh)"}, + {"name": "P8_k72", "cell": "P8", "class_description": "face copy of an entrant, width 8", "class_size": 72, "k": 72, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 246, 247, 248, 249, 258, 259, 260, 261, 270, 272, 273, 282, 284, 285, 294, 296, 297, 299, 301, 306, 308, 309, 320, 321, 332, 333, 344, 345, 347, 349, 356, 357, 359, 361, 366, 367, 368, 369, 370, 371, 372, 373, 375, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391], "lp_objective": 166.35289339023453, "idle_remainder": {"1": 128.0, "3": 1328.0, "7": 1328.0, "8": 1312.0, "48": 2256.0}, "b": 0.001696336551844271, "mass": 520704.0, "pct_b_total": 5.8469287967536365, "pct_b_per_helper": 0.08120734439935606, "local_fee_saved": 230.11335296316986, "hosting_offset": 88.29432328356943, "offset_share_pct": 38.36992601541951, "status": "recorded (not re-run by verify.sh)"}, + {"name": "P7_k1", "cell": "P7", "class_description": "face copy of a width-7 provider", "class_size": 32, "k": 1, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [262], "lp_objective": 78.9431695444484, "idle_remainder": {"1": 23.599999999999998, "3": 1215.62, "7": 56.5, "48": 1815.9800000000002}, "b": 0.001603832889308516, "mass": 520704.0, "pct_b_total": 0.07494412117976523, "pct_b_per_helper": 0.07494412117976523, "local_fee_saved": 2.807306914794056, "hosting_offset": 0.8845994377832938, "offset_share_pct": 31.510606593158624, "status": "recomputed by verify.sh (scripts/e2_helper_prices.py)"}, + {"name": "P7_k8", "cell": "P7", "class_description": "face copy of a width-7 provider", "class_size": 32, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [262, 274, 310, 314, 322, 326, 338, 350], "lp_objective": 86.36895154859006, "idle_remainder": {"1": 178.0, "2": 50.0, "3": 1571.8666666666666, "48": 1871.4666666666667}, "b": 0.0016115121614485874, "mass": 520704.0, "pct_b_total": 0.5541104579172007, "pct_b_per_helper": 0.06926380723965009, "local_fee_saved": 22.458455318352513, "hosting_offset": 8.31038144192496, "offset_share_pct": 37.00335274231401, "status": "recorded (not re-run by verify.sh)"}, + {"name": "P7_k14", "cell": "P7", "class_description": "face copy of a width-7 provider", "class_size": 32, "k": 14, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [262, 264, 274, 276, 311, 313, 315, 322, 324, 326, 328, 339, 341, 351], "lp_objective": 95.38865623219716, "idle_remainder": {"1": 230.0, "2": 102.0, "3": 2026.2, "7": 1.0, "48": 1903.8}, "b": 0.0016164655564406575, "mass": 520704.0, "pct_b_total": 0.8631892468272229, "pct_b_per_helper": 0.06165637477337306, "local_fee_saved": 39.30229680711651, "hosting_offset": 17.330086125532063, "offset_share_pct": 44.0943342588418, "status": "recorded (not re-run by verify.sh)"}, + {"name": "P7_k32", "cell": "P7", "class_description": "face copy of a width-7 provider", "class_size": 32, "k": 32, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [262, 263, 264, 265, 274, 275, 276, 277, 310, 311, 312, 313, 314, 315, 316, 317, 322, 323, 324, 325, 326, 327, 328, 329, 338, 339, 340, 341, 350, 351, 352, 353], "lp_objective": 127.36533803647909, "idle_remainder": {"1": 128.0, "3": 2112.0, "7": 1216.0, "48": 1920.0}, "b": 0.0016283353569115045, "mass": 520704.0, "pct_b_total": 1.6038335039491258, "pct_b_per_helper": 0.05011979699841018, "local_fee_saved": 89.833821273407, "hosting_offset": 49.30676792981399, "offset_share_pct": 54.88664205850719, "status": "recorded (not re-run by verify.sh)"}, + {"name": "M8_k1", "cell": "M8", "class_description": "M copy of an entrant, width 8", "class_size": 56, "k": 1, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [392], "lp_objective": 78.64325928997846, "idle_remainder": {"1": 12.600000000000128, "3": 1201.62, "7": 52.5, "48": 1818.98}, "b": 0.0016044102805557185, "mass": 520704.0, "pct_b_total": 0.11097181283332702, "pct_b_per_helper": 0.11097181283332702, "local_fee_saved": 3.4306691540461403, "hosting_offset": 0.5846891833133583, "offset_share_pct": 17.04300697791783, "status": "recomputed by verify.sh (scripts/e2_helper_prices.py)"}, + {"name": "M8_k8", "cell": "M8", "class_description": "M copy of an entrant, width 8", "class_size": 56, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [394, 409, 424, 436, 450, 465, 480, 492], "lp_objective": 82.73608357317183, "idle_remainder": {"1": 100.79999999999998, "3": 1212.96, "7": 84.0, "48": 1895.8399999999995}, "b": 0.001616907477959993, "mass": 520704.0, "pct_b_total": 0.8907639845996407, "pct_b_per_helper": 0.11134549807495508, "local_fee_saved": 27.3453684774846, "hosting_offset": 4.677513466506724, "offset_share_pct": 17.105322498609063, "status": "recorded (not re-run by verify.sh)"}, + {"name": "M8_k14", "cell": "M8", "class_description": "M copy of an entrant, width 8", "class_size": 56, "k": 14, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [392, 400, 408, 416, 424, 432, 440, 448, 456, 464, 472, 480, 488, 496], "lp_objective": 87.15428796054395, "idle_remainder": {"1": 173.0, "2": 45.0, "3": 1437.6666666666667, "48": 1962.6666666666667}, "b": 0.0016271803930528418, "mass": 520704.0, "pct_b_total": 1.5317668039904309, "pct_b_per_helper": 0.10941191457074506, "local_fee_saved": 47.829398646876925, "hosting_offset": 9.095717853878853, "offset_share_pct": 19.017002327443578, "status": "recorded (not re-run by verify.sh)"}, + {"name": "M8_k56", "cell": "M8", "class_description": "M copy of an entrant, width 8", "class_size": 56, "k": 56, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [392, 393, 394, 396, 400, 401, 402, 404, 408, 409, 410, 412, 416, 417, 418, 420, 424, 425, 426, 428, 432, 433, 434, 436, 440, 441, 442, 444, 448, 449, 450, 452, 456, 457, 458, 460, 464, 465, 466, 468, 472, 473, 474, 476, 480, 481, 482, 484, 488, 489, 490, 492, 496, 497, 498, 500], "lp_objective": 136.12886612209252, "idle_remainder": {"1": 128.0, "3": 1346.4, "7": 1236.0, "8": 344.0, "48": 2237.6}, "b": 0.001690363267552532, "mass": 520704.0, "pct_b_total": 5.474211604270196, "pct_b_per_helper": 0.09775377864768207, "local_fee_saved": 191.31759458752092, "hosting_offset": 58.07029601542742, "offset_share_pct": 30.35282569835068, "status": "recorded (not re-run by verify.sh)"}, + {"name": "M5_k1", "cell": "M5", "class_description": "M copy of a rank-4 pivot, width 5", "class_size": 48, "k": 1, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [395], "lp_objective": 79.39079928540599, "idle_remainder": {"1": 57.599999999999966, "3": 1254.72, "7": 48.0, "48": 1810.8799999999999}, "b": 0.0016032504527875107, "mass": 520704.0, "pct_b_total": 0.03860161774171811, "pct_b_per_helper": 0.03860161774171811, "local_fee_saved": 2.3229214587904465, "hosting_offset": 1.3322291787408886, "offset_share_pct": 57.35145171178474, "status": "recomputed by verify.sh (scripts/e2_helper_prices.py)"}, + {"name": "M5_k8", "cell": "M5", "class_description": "M copy of a rank-4 pivot, width 5", "class_size": 48, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [395, 406, 427, 438, 459, 470, 483, 494], "lp_objective": 88.71640353659193, "idle_remainder": {"1": 460.8, "3": 1637.7600000000002, "7": 48.0, "48": 1831.0399999999997}, "b": 0.0016075943697525037, "mass": 520704.0, "pct_b_total": 0.30965058452412375, "pct_b_per_helper": 0.03870632306551547, "local_fee_saved": 18.583371670323714, "hosting_offset": 10.657833429926825, "offset_share_pct": 57.35145171178277, "status": "recorded (not re-run by verify.sh)"}, + {"name": "M5_k14", "cell": "M5", "class_description": "M copy of a rank-4 pivot, width 5", "class_size": 48, "k": 14, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [395, 399, 406, 414, 429, 437, 443, 459, 463, 470, 478, 485, 493, 499], "lp_objective": 97.58140742546013, "idle_remainder": {"1": 576.0, "3": 1747.2, "5": 288.0, "7": 48.0, "48": 1836.8}, "b": 0.0016107867141125247, "mass": 520704.0, "pct_b_total": 0.5088444566378136, "pct_b_per_helper": 0.03634603261698669, "local_fee_saved": 32.52090042306716, "hosting_offset": 19.522837318795027, "offset_share_pct": 60.03166291468187, "status": "recorded (not re-run by verify.sh)"}, + {"name": "M5_k48", "cell": "M5", "class_description": "M copy of a rank-4 pivot, width 5", "class_size": 48, "k": 48, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [395, 397, 398, 399, 403, 405, 406, 407, 411, 413, 414, 415, 427, 429, 430, 431, 435, 437, 438, 439, 443, 445, 446, 447, 459, 461, 462, 463, 467, 469, 470, 471, 475, 477, 478, 479, 483, 485, 486, 487, 491, 493, 494, 495, 499, 501, 502, 503], "lp_objective": 150.28604444224518, "idle_remainder": {"1": 576.0, "3": 1747.1999999999998, "5": 2736.0, "7": 48.0, "48": 1836.8}, "b": 0.0016275280317628567, "mass": 520704.0, "pct_b_total": 1.553458543018249, "pct_b_per_helper": 0.03236371964621352, "local_fee_saved": 111.50023002194669, "hosting_offset": 72.22747433558008, "offset_share_pct": 64.77787025314969, "status": "recorded (not re-run by verify.sh)"}, + {"name": "M4_k1", "cell": "M4", "class_description": "M copy of a rank-5 pivot, width 4", "class_size": 8, "k": 1, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [419], "lp_objective": 78.96089292243292, "idle_remainder": {"2": 17.999999999999986, "3": 1268.3999999999999, "7": 30.000000000000014, "48": 1811.6}, "b": 0.0016033092416224345, "mass": 520704.0, "pct_b_total": 0.042269886056445216, "pct_b_per_helper": 0.042269886056445216, "local_fee_saved": 1.9871196285160408, "hosting_offset": 0.9023228157678176, "offset_share_pct": 45.40858048096794, "status": "recomputed by verify.sh (scripts/e2_helper_prices.py)"}, + {"name": "M4_k8", "cell": "M4", "class_description": "M copy of a rank-5 pivot, width 4", "class_size": 8, "k": 8, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [419, 421, 422, 423, 451, 453, 454, 455], "lp_objective": 85.60411891355172, "idle_remainder": {"2": 48.0, "3": 1689.5999999999995, "48": 1830.4}, "b": 0.0016078619035174678, "mass": 520704.0, "pct_b_total": 0.326343986160782, "pct_b_per_helper": 0.04079299827009775, "local_fee_saved": 15.896957028128327, "hosting_offset": 7.545548806886615, "offset_share_pct": 47.465365815202254, "status": "recorded (not re-run by verify.sh)"}, + {"name": "XEnt_k8", "cell": "XEnt", "class_description": "all entrants (width < 9: P8, P7, M8, M5, M4), stratified selection", "class_size": 216, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [258, 262, 347, 386, 395, 400, 456, 459], "lp_objective": 84.53107381849674, "idle_remainder": {"1": 201.8, "3": 1333.1599999999999, "7": 79.0, "48": 1876.64}, "b": 0.0016135858878998195, "mass": 520704.0, "pct_b_total": 0.6835055215258068, "pct_b_per_helper": 0.08543819019072585, "local_fee_saved": 23.90194742276502, "hosting_offset": 6.472503711831635, "offset_share_pct": 27.079399001886365, "status": "recorded (not re-run by verify.sh)"}, + {"name": "XEnt_k14", "cell": "XEnt", "class_description": "all entrants (width < 9: P8, P7, M8, M5, M4), stratified selection", "class_size": 216, "k": 14, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [227, 249, 262, 299, 322, 359, 380, 394, 395, 424, 435, 450, 475, 480], "lp_objective": 89.21766357755996, "idle_remainder": {"1": 330.0, "3": 1407.6, "7": 114.0, "48": 1930.3999999999999}, "b": 0.0016221884395397094, "mass": 520704.0, "pct_b_total": 1.2202820650176527, "pct_b_per_helper": 0.08716300464411805, "local_fee_saved": 42.111297554663956, "hosting_offset": 11.15909347089486, "offset_share_pct": 26.499049231169927, "status": "recorded (not re-run by verify.sh)"}, + {"name": "XEnt_k216", "cell": "XEnt", "class_description": "all entrants (width < 9: P8, P7, M8, M5, M4), stratified selection", "class_size": 216, "k": 216, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 246, 247, 248, 249, 258, 259, 260, 261, 262, 263, 264, 265, 270, 272, 273, 274, 275, 276, 277, 282, 284, 285, 294, 296, 297, 299, 301, 306, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 332, 333, 338, 339, 340, 341, 344, 345, 347, 349, 350, 351, 352, 353, 356, 357, 359, 361, 366, 367, 368, 369, 370, 371, 372, 373, 375, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503], "lp_objective": 418.30037062967733, "idle_remainder": {"3": 1280.0000000000002, "5": 3584.0, "7": 3584.0, "8": 5376.0, "48": 2303.9999999999995}, "b": 0.0018134503204100582, "mass": 520704.0, "pct_b_total": 13.154519209178117, "pct_b_per_helper": 0.06090055189434313, "local_fee_saved": 638.6619558741733, "hosting_offset": 340.2418005230122, "offset_share_pct": 53.27416129825735, "status": "recorded (not re-run by verify.sh)"}, + {"name": "XFc_k8", "cell": "XFc", "class_description": "all face copies (P9, P8, P7), stratified selection", "class_size": 168, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [255, 258, 262, 295, 322, 347, 355, 386], "lp_objective": 82.31094298466734, "idle_remainder": {"1": 84.99999999999999, "3": 1192.9, "7": 78.5, "48": 1900.1}, "b": 0.001616675363954683, "mass": 520704.0, "pct_b_total": 0.8762806825885594, "pct_b_per_helper": 0.10953508532356993, "local_fee_saved": 26.554899902764998, "hosting_offset": 4.252372878002234, "offset_share_pct": 16.013514995624067, "status": "recorded (not re-run by verify.sh)"}, + {"name": "XFc_k14", "cell": "XFc", "class_description": "all face copies (P9, P8, P7), stratified selection", "class_size": 168, "k": 14, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [224, 236, 243, 262, 267, 273, 290, 312, 319, 320, 327, 358, 366, 380], "lp_objective": 85.605008468824, "idle_remainder": {"1": 141.0, "2": 13.0, "3": 1314.5, "7": 23.5, "48": 1972.4999999999995}, "b": 0.0016272892527645906, "mass": 520704.0, "pct_b_total": 1.5385593630175887, "pct_b_per_helper": 0.10989709735839918, "local_fee_saved": 46.449387207890624, "hosting_offset": 7.546438362158895, "offset_share_pct": 16.246583250676206, "status": "recorded (not re-run by verify.sh)"}, + {"name": "XFc_k28", "cell": "XFc", "class_description": "all face copies (P9, P8, P7), stratified selection", "class_size": 168, "k": 28, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [227, 233, 241, 247, 251, 257, 261, 262, 271, 276, 285, 286, 292, 303, 306, 314, 325, 330, 333, 339, 342, 355, 357, 365, 369, 377, 383, 389], "lp_objective": 95.5088607211357, "idle_remainder": {"1": 206.5, "2": 78.5, "3": 1591.9666666666667, "48": 2128.866666666667}, "b": 0.0016521151918888989, "mass": 520704.0, "pct_b_total": 3.0876325159519435, "pct_b_per_helper": 0.11027258985542655, "local_fee_saved": 94.34845219992408, "hosting_offset": 17.450290614470603, "offset_share_pct": 18.495576988898016, "status": "recorded (not re-run by verify.sh)"}, + {"name": "XFc_k168", "cell": "XFc", "class_description": "all face copies (P9, P8, P7), stratified selection", "class_size": 168, "k": 168, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391], "lp_objective": 242.77752020278996, "idle_remainder": {"1": 128.0, "3": 403.2, "7": 3360.0, "8": 1568.0, "48": 3180.7999999999997}, "b": 0.001896381783299722, "mass": 520704.0, "pct_b_total": 18.329223861948396, "pct_b_per_helper": 0.10910252298778807, "local_fee_saved": 562.3757196059283, "hosting_offset": 164.71895009612484, "offset_share_pct": 29.28984028889935, "status": "recorded (not re-run by verify.sh)"}, + {"name": "XFc_k168_q", "cell": "XFc", "class_description": "all face copies (P9, P8, P7), stratified selection", "class_size": 168, "k": 168, "whole_class": true, "q": 0.001896381783299722, "deleted_helpers": [224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391], "lp_objective": 287.34157240603844, "idle_remainder": {"1": 128.0, "3": 403.19999999999993, "7": 3360.0, "8": 1568.0, "48": 3180.7999999999997}, "b": 0.001896381783299722, "mass": 520704.0, "pct_b_total": 18.329223861948396, "pct_b_per_helper": 0.10910252298778807, "local_fee_saved": 562.3757196059283, "hosting_offset": null, "offset_share_pct": null, "status": "recorded (not re-run by verify.sh)", "note": "re-solved at q = this row's own b (the hosting LP at the deleted profile's own pressure root); the objective is not comparable with the fixed-q rows, b is the same as in the fixed-q row"}, + {"name": "XMc_k8", "cell": "XMc", "class_description": "all M copies (M8, M5, M4), stratified selection", "class_size": 112, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [394, 395, 419, 424, 435, 450, 475, 480], "lp_objective": 85.22946364775281, "idle_remainder": {"1": 208.8, "3": 1425.3600000000001, "7": 66.0, "48": 1863.44}, "b": 0.0016123075894029924, "mass": 520704.0, "pct_b_total": 0.6037430652917841, "pct_b_per_helper": 0.07546788316147302, "local_fee_saved": 22.57857586618764, "hosting_offset": 7.1708935410877075, "offset_share_pct": 31.7597247212851, "status": "recorded (not re-run by verify.sh)"}, + {"name": "XMc_k14", "cell": "XMc", "class_description": "all M copies (M8, M5, M4), stratified selection", "class_size": 112, "k": 14, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [392, 395, 408, 411, 419, 424, 435, 440, 456, 459, 472, 475, 488, 491], "lp_objective": 90.98021873391541, "idle_remainder": {"1": 419.4, "3": 1594.38, "7": 79.5, "48": 1905.02}, "b": 0.0016196760763867186, "mass": 520704.0, "pct_b_total": 1.06351722759368, "pct_b_per_helper": 0.07596551625669143, "local_fee_saved": 39.93933245958186, "hosting_offset": 12.921648627250306, "offset_share_pct": 32.3531912816191, "status": "recorded (not re-run by verify.sh)"}, + {"name": "XMc_k28", "cell": "XMc", "class_description": "all M copies (M8, M5, M4), stratified selection", "class_size": 112, "k": 28, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [392, 395, 400, 403, 408, 411, 416, 419, 424, 427, 432, 435, 440, 443, 448, 451, 456, 459, 464, 467, 472, 475, 480, 483, 488, 491, 496, 499], "lp_objective": 105.64932257474904, "idle_remainder": {"1": 432.0, "3": 1603.8, "5": 501.0, "7": 126.0, "48": 1980.2}, "b": 0.001635819636789334, "mass": 520704.0, "pct_b_total": 2.070832837579184, "pct_b_per_helper": 0.073958315627828, "local_fee_saved": 79.67869540939571, "hosting_offset": 27.590752468083934, "offset_share_pct": 34.62751533056656, "status": "recorded (not re-run by verify.sh)"}, + {"name": "XMc_k56", "cell": "XMc", "class_description": "all M copies (M8, M5, M4), stratified selection", "class_size": 112, "k": 56, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [392, 394, 395, 398, 400, 402, 403, 406, 408, 410, 411, 414, 416, 418, 419, 422, 424, 426, 427, 430, 432, 434, 435, 438, 440, 442, 443, 446, 448, 450, 451, 454, 456, 458, 459, 462, 464, 466, 467, 470, 472, 474, 475, 478, 480, 482, 483, 486, 488, 490, 491, 494, 496, 498, 499, 502], "lp_objective": 139.70005108739647, "idle_remainder": {"1": 288.0, "3": 1491.2, "5": 1568.0, "7": 512.0, "48": 2092.8}, "b": 0.0016660432112652946, "mass": 520704.0, "pct_b_total": 3.9567042067142344, "pct_b_per_helper": 0.07065543226275418, "local_fee_saved": 159.3573908187893, "hosting_offset": 61.64148098073137, "offset_share_pct": 38.68128152953131, "status": "recorded (not re-run by verify.sh)"}, + {"name": "XMc_k112", "cell": "XMc", "class_description": "all M copies (M8, M5, M4), stratified selection", "class_size": 112, "k": 112, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503], "lp_objective": 218.76916786377555, "idle_remainder": {"3": 1346.4, "5": 3584.0, "7": 1236.0, "8": 568.0, "48": 2237.6000000000004}, "b": 0.0017220331830326008, "mass": 520704.0, "pct_b_total": 7.450330839084507, "pct_b_per_helper": 0.06652081106325453, "local_fee_saved": 318.71478163755944, "hosting_offset": 140.71059775711046, "offset_share_pct": 44.14937927702573, "status": "recorded (not re-run by verify.sh)"}, + {"name": "XMc_k112_q", "cell": "XMc", "class_description": "all M copies (M8, M5, M4), stratified selection", "class_size": 112, "k": 112, "whole_class": true, "q": 0.0017220331830326008, "deleted_helpers": [392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503], "lp_objective": 235.0948550924295, "idle_remainder": {"3": 1346.3999999999999, "5": 3584.0, "7": 1236.0, "8": 568.0, "48": 2237.6000000000004}, "b": 0.0017220331830326008, "mass": 520704.0, "pct_b_total": 7.450330839084507, "pct_b_per_helper": 0.06652081106325453, "local_fee_saved": 318.71478163755944, "hosting_offset": null, "offset_share_pct": null, "status": "recorded (not re-run by verify.sh)", "note": "re-solved at q = this row's own b (the hosting LP at the deleted profile's own pressure root); the objective is not comparable with the fixed-q rows, b is the same as in the fixed-q row"}, + {"name": "SFcar_k1", "cell": "SFcar", "class_description": "factory scratch: packet carriers", "class_size": 98, "k": 1, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [2], "lp_objective": 78.30160559083036, "idle_remainder": {"3": 1185.6, "7": 48.0, "48": 1822.4}, "b": 0.0016049349759488852, "mass": 520704.0, "pct_b_total": 0.14371142211671017, "pct_b_per_helper": 0.14371142211671017, "local_fee_saved": 3.9274490611751522, "hosting_offset": 0.24303548416526155, "offset_share_pct": 6.188125686155727, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFcar_k8", "cell": "SFcar", "class_description": "factory scratch: packet carriers", "class_size": 98, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [14, 40, 70, 98, 126, 152, 182, 210], "lp_objective": 80.00285397998694, "idle_remainder": {"3": 1084.8, "7": 48.0, "48": 1923.2000000000003}, "b": 0.0016218684075593715, "mass": 520704.0, "pct_b_total": 1.2003129131422874, "pct_b_per_helper": 0.15003911414278592, "local_fee_saved": 32.39592572073481, "hosting_offset": 1.9442838733218366, "offset_share_pct": 6.001630853466891, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFcar_k14", "cell": "SFcar", "class_description": "factory scratch: packet carriers", "class_size": 98, "k": 14, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [2, 18, 34, 50, 66, 82, 98, 114, 130, 146, 162, 178, 194, 210], "lp_objective": 81.46106688497837, "idle_remainder": {"3": 998.3999999999999, "7": 48.0, "48": 2009.6}, "b": 0.0016360103461670666, "mass": 520704.0, "pct_b_total": 2.082732599984105, "pct_b_per_helper": 0.14876661428457894, "local_fee_saved": 55.78394485562201, "hosting_offset": 3.402496778313264, "offset_share_pct": 6.0994194424927874, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFcar_k98", "cell": "SFcar", "class_description": "factory scratch: packet carriers", "class_size": 98, "k": 98, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [2, 4, 6, 7, 8, 12, 14, 18, 20, 22, 23, 24, 28, 30, 34, 36, 38, 39, 40, 44, 46, 50, 52, 54, 55, 56, 60, 62, 66, 68, 70, 71, 72, 76, 78, 82, 84, 86, 87, 88, 92, 94, 98, 100, 102, 103, 104, 108, 110, 114, 116, 118, 119, 120, 124, 126, 130, 132, 134, 135, 136, 140, 142, 146, 148, 150, 151, 152, 156, 158, 162, 164, 166, 167, 168, 172, 174, 178, 180, 182, 183, 184, 188, 190, 194, 196, 198, 199, 200, 204, 206, 210, 212, 214, 215, 216, 220, 222], "lp_objective": 103.89216241884438, "idle_remainder": {"1": 18.776470588235227, "2": 11.22352941176477, "48": 3212.1411764705886}, "b": 0.0018738503231193427, "mass": 520704.0, "pct_b_total": 16.92332014619893, "pct_b_per_helper": 0.172686940267336, "local_fee_saved": 397.4056647703472, "hosting_offset": 25.833592312179277, "offset_share_pct": 6.500559655360724, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFtot_k1", "cell": "SFtot", "class_description": "factory scratch: block totals (retired donors)", "class_size": 48, "k": 1, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [16], "lp_objective": 78.30160559083036, "idle_remainder": {"3": 1185.6, "7": 48.0, "48": 1822.4}, "b": 0.0016048723869705752, "mass": 520704.0, "pct_b_total": 0.13980603487298016, "pct_b_per_helper": 0.13980603487298016, "local_fee_saved": 3.8274643062908424, "hosting_offset": 0.24303548416526155, "offset_share_pct": 6.349777939556668, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFtot_k8", "cell": "SFtot", "class_description": "factory scratch: block totals (retired donors)", "class_size": 48, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [16, 51, 80, 99, 128, 147, 176, 195], "lp_objective": 80.00285397998694, "idle_remainder": {"3": 1084.8, "7": 48.0, "48": 1923.2000000000003}, "b": 0.001620733655024353, "mass": 520704.0, "pct_b_total": 1.1295073464960614, "pct_b_per_helper": 0.14118841831200768, "local_fee_saved": 30.619714450326363, "hosting_offset": 1.9442838733218366, "offset_share_pct": 6.34977793955591, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFtot_k14", "cell": "SFtot", "class_description": "factory scratch: block totals (retired donors)", "class_size": 48, "k": 14, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [16, 37, 51, 67, 81, 97, 112, 128, 133, 147, 163, 177, 193, 208], "lp_objective": 81.46106688497837, "idle_remainder": {"3": 998.3999999999999, "7": 48.0, "48": 2009.6}, "b": 0.0016345808183062089, "mass": 520704.0, "pct_b_total": 1.9935338301193095, "pct_b_per_helper": 0.1423952735799507, "local_fee_saved": 53.584500288071034, "hosting_offset": 3.402496778313264, "offset_share_pct": 6.349777939556015, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFtot_k48", "cell": "SFtot", "class_description": "factory scratch: block totals (retired donors)", "class_size": 48, "k": 48, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [16, 21, 32, 37, 48, 49, 51, 53, 64, 65, 67, 69, 80, 81, 83, 85, 96, 97, 99, 101, 112, 113, 115, 117, 128, 129, 131, 133, 144, 145, 147, 149, 160, 161, 163, 165, 176, 177, 179, 181, 192, 193, 195, 197, 208, 209, 211, 213], "lp_objective": 89.72427334659609, "idle_remainder": {"3": 508.80000000000007, "7": 47.99999999999997, "48": 2499.1999999999994}, "b": 0.0017177473613902688, "mass": 520704.0, "pct_b_total": 7.182906867279915, "pct_b_per_helper": 0.14964389306833156, "local_fee_saved": 183.71828670195862, "hosting_offset": 11.665703239930991, "offset_share_pct": 6.349777939555879, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFopc_k1", "cell": "SFopc", "class_description": "factory scratch: own partial plus later packet carrier", "class_size": 28, "k": 1, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [11], "lp_objective": 78.30160559083036, "idle_remainder": {"3": 1185.6, "7": 48.0, "48": 1822.4}, "b": 0.0016049349759488852, "mass": 520704.0, "pct_b_total": 0.14371142211671017, "pct_b_per_helper": 0.14371142211671017, "local_fee_saved": 3.9274490611751522, "hosting_offset": 0.24303548416526155, "offset_share_pct": 6.188125686155727, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFopc_k8", "cell": "SFopc", "class_description": "factory scratch: own partial plus later packet carrier", "class_size": 28, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [15, 43, 75, 95, 127, 155, 187, 207], "lp_objective": 80.00285397998694, "idle_remainder": {"3": 1084.8, "7": 48.0, "48": 1923.2000000000003}, "b": 0.001621091598212793, "mass": 520704.0, "pct_b_total": 1.1518420578119803, "pct_b_per_helper": 0.14398025722649754, "local_fee_saved": 31.180274097170454, "hosting_offset": 1.9442838733218366, "offset_share_pct": 6.235621493456584, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFopc_k14", "cell": "SFopc", "class_description": "factory scratch: own partial plus later packet carrier", "class_size": 28, "k": 14, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [11, 27, 43, 59, 75, 91, 107, 123, 139, 155, 171, 187, 203, 219], "lp_objective": 81.46106688497837, "idle_remainder": {"3": 998.3999999999999, "7": 48.0, "48": 2009.6}, "b": 0.0016362255585855726, "mass": 520704.0, "pct_b_total": 2.0961612875361135, "pct_b_per_helper": 0.14972580625257953, "local_fee_saved": 56.11471594144006, "hosting_offset": 3.402496778313264, "offset_share_pct": 6.063466100165286, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFopc_k28", "cell": "SFopc", "class_description": "factory scratch: own partial plus later packet carrier", "class_size": 28, "k": 28, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [11, 15, 27, 31, 43, 47, 59, 63, 75, 79, 91, 95, 107, 111, 123, 127, 139, 143, 155, 159, 171, 175, 187, 191, 203, 207, 219, 223], "lp_objective": 84.86356366329149, "idle_remainder": {"3": 796.8000000000001, "7": 48.0, "48": 2211.2}, "b": 0.0016690766942306164, "mass": 520704.0, "pct_b_total": 4.145985546603703, "pct_b_per_helper": 0.14807091237870368, "local_fee_saved": 109.01130014398161, "hosting_offset": 6.8049935566263855, "offset_share_pct": 6.242466191705247, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFops_k1", "cell": "SFops", "class_description": "factory scratch: own partials stranded at a late read", "class_size": 28, "k": 1, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [9], "lp_objective": 78.30160559083036, "idle_remainder": {"3": 1185.6, "7": 48.0, "48": 1822.4}, "b": 0.0016044945743324893, "mass": 520704.0, "pct_b_total": 0.11623152228081857, "pct_b_per_helper": 0.11623152228081857, "local_fee_saved": 3.223750421530255, "hosting_offset": 0.24303548416526155, "offset_share_pct": 7.538905075967298, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFops_k8", "cell": "SFops", "class_description": "factory scratch: own partials stranded at a late read", "class_size": 28, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [9, 29, 61, 89, 121, 141, 173, 201], "lp_objective": 80.00285397998694, "idle_remainder": {"3": 1084.8, "7": 48.0, "48": 1923.2000000000003}, "b": 0.0016176561737476758, "mass": 520704.0, "pct_b_total": 0.9374806279703884, "pct_b_per_helper": 0.11718507849629856, "local_fee_saved": 25.790003372242424, "hosting_offset": 1.9442838733218366, "offset_share_pct": 7.538905075966194, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFops_k14", "cell": "SFops", "class_description": "factory scratch: own partials stranded at a late read", "class_size": 28, "k": 14, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [9, 25, 41, 57, 73, 89, 105, 121, 137, 153, 169, 185, 201, 217], "lp_objective": 81.46106688497837, "idle_remainder": {"3": 998.3999999999999, "7": 48.0, "48": 2009.6}, "b": 0.0016291106439120322, "mass": 520704.0, "pct_b_total": 1.6522093688992046, "pct_b_per_helper": 0.11801495492137175, "local_fee_saved": 45.13250590142472, "hosting_offset": 3.402496778313264, "offset_share_pct": 7.538905075966223, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFops_k28", "cell": "SFops", "class_description": "factory scratch: own partials stranded at a late read", "class_size": 28, "k": 28, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [9, 13, 25, 29, 41, 45, 57, 61, 73, 77, 89, 93, 105, 109, 121, 125, 137, 141, 153, 157, 169, 173, 185, 189, 201, 205, 217, 221], "lp_objective": 84.86356366329149, "idle_remainder": {"3": 796.8000000000001, "7": 48.0, "48": 2211.2}, "b": 0.0016564792602351479, "mass": 520704.0, "pct_b_total": 3.359938875799795, "pct_b_per_helper": 0.11999781699284982, "local_fee_saved": 90.26501180284592, "hosting_offset": 6.8049935566263855, "offset_share_pct": 7.538905075966361, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFwst_k1", "cell": "SFwst", "class_description": "factory scratch: retired extra rows (exact source copies, waste)", "class_size": 14, "k": 1, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [10], "lp_objective": 78.30160559083036, "idle_remainder": {"3": 1185.6, "7": 48.0, "48": 1822.4}, "b": 0.001604690748262451, "mass": 520704.0, "pct_b_total": 0.12847225833867437, "pct_b_per_helper": 0.12847225833867437, "local_fee_saved": 3.5372560113625795, "hosting_offset": 0.24303548416526155, "offset_share_pct": 6.870734925167103, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFwst_k8", "cell": "SFwst", "class_description": "factory scratch: retired extra rows (exact source copies, waste)", "class_size": 14, "k": 8, "whole_class": false, "q": 0.00160263181098207, "deleted_helpers": [10, 26, 58, 90, 122, 138, 170, 202], "lp_objective": 80.00285397998694, "idle_remainder": {"3": 1084.8, "7": 48.0, "48": 1923.2000000000003}, "b": 0.001619252829461201, "mass": 520704.0, "pct_b_total": 1.037107735243814, "pct_b_per_helper": 0.12963846690547676, "local_fee_saved": 28.298048090901002, "hosting_offset": 1.9442838733218366, "offset_share_pct": 6.87073492516611, "status": "recorded (not re-run by verify.sh)"}, + {"name": "SFwst_k14", "cell": "SFwst", "class_description": "factory scratch: retired extra rows (exact source copies, waste)", "class_size": 14, "k": 14, "whole_class": true, "q": 0.00160263181098207, "deleted_helpers": [10, 26, 42, 58, 74, 90, 106, 122, 138, 154, 170, 186, 202, 218], "lp_objective": 81.46106688497837, "idle_remainder": {"3": 998.3999999999999, "7": 48.0, "48": 2009.6}, "b": 0.0016319466855075886, "mass": 520704.0, "pct_b_total": 1.829170887828413, "pct_b_per_helper": 0.13065506341631522, "local_fee_saved": 49.521584159075594, "hosting_offset": 3.402496778313264, "offset_share_pct": 6.870734925166371, "status": "recorded (not re-run by verify.sh)"} + ] +} diff --git a/research/format-limits/data/prices/k1-specs.json b/research/format-limits/data/prices/k1-specs.json new file mode 100644 index 0000000000..29ff8e86ae --- /dev/null +++ b/research/format-limits/data/prices/k1-specs.json @@ -0,0 +1,12 @@ +{ + "what": "The helper deleted in each k = 1 price run of e2_helper_prices.py: for every cell (role, width in the width7_eight word) the single helper whose local fee at q = 1.6026e-3 is closest to the cell mean (ties: lowest index). Helper index h is register 224 + h of the unit (0..223 factory scratch, 224..391 face copies, 392..503 M copies; the eight centre accumulators 0,1,3,5,17,19,33,35 are not priced).", + "cells": { + "F9": {"description": "factory scratch register", "role": "F", "width": 9, "deleted_helpers": [16]}, + "P9": {"description": "face copy of width 9", "role": "P", "width": 9, "deleted_helpers": [318]}, + "P8": {"description": "face copy of an entrant, width 8", "role": "P", "width": 8, "deleted_helpers": [224]}, + "P7": {"description": "face copy of a width-7 provider", "role": "P", "width": 7, "deleted_helpers": [262]}, + "M8": {"description": "M copy of an entrant, width 8", "role": "M", "width": 8, "deleted_helpers": [392]}, + "M5": {"description": "M copy of a rank-4 pivot, width 5", "role": "M", "width": 5, "deleted_helpers": [395]}, + "M4": {"description": "M copy of a rank-5 pivot, width 4", "role": "M", "width": 4, "deleted_helpers": [419]} + } +} diff --git a/research/format-limits/data/prices/pr569-provider-calls.json b/research/format-limits/data/prices/pr569-provider-calls.json new file mode 100644 index 0000000000..0fe303801b --- /dev/null +++ b/research/format-limits/data/prices/pr569-provider-calls.json @@ -0,0 +1,91 @@ +{ + "what": "Per-call provider dispatch of PR #569: which of the 72 calls of the global word use the width7_eight local word and which the fourcold_eight local word. Only the time and provider of each call are kept; the rest of the plan is not needed here.", + "source": { + "pull_request": 569, + "author": "DominikScholz", + "repository": "https://github.com/CrocSwap/integer-mult-bounds (head of pull request 569)", + "commit": "1424da81263a5305b35e4cf74ef686c275f03f3f", + "path": "research/larger-gain/global/width7/PLAN.json", + "key": "provider_calls", + "git_blob_id": "54c7ae22839dcb87f37194b2354ba9268edc48d7" + }, + "provider_words": { + "width7_eight": "data/vendor/pr569/width7-eight-FULL-WORD.json.gz", + "fourcold_eight": "data/vendor/pr569/fourcold-eight-FULL-WORD.json.gz" + }, + "calls_format": "[time, provider] for time 0..71", + "calls": [ + [0, "width7_eight"], + [1, "width7_eight"], + [2, "width7_eight"], + [3, "width7_eight"], + [4, "width7_eight"], + [5, "width7_eight"], + [6, "width7_eight"], + [7, "width7_eight"], + [8, "fourcold_eight"], + [9, "width7_eight"], + [10, "width7_eight"], + [11, "width7_eight"], + [12, "width7_eight"], + [13, "width7_eight"], + [14, "width7_eight"], + [15, "width7_eight"], + [16, "width7_eight"], + [17, "width7_eight"], + [18, "width7_eight"], + [19, "width7_eight"], + [20, "width7_eight"], + [21, "fourcold_eight"], + [22, "width7_eight"], + [23, "width7_eight"], + [24, "width7_eight"], + [25, "width7_eight"], + [26, "width7_eight"], + [27, "width7_eight"], + [28, "width7_eight"], + [29, "width7_eight"], + [30, "width7_eight"], + [31, "width7_eight"], + [32, "fourcold_eight"], + [33, "fourcold_eight"], + [34, "width7_eight"], + [35, "width7_eight"], + [36, "fourcold_eight"], + [37, "width7_eight"], + [38, "width7_eight"], + [39, "fourcold_eight"], + [40, "width7_eight"], + [41, "width7_eight"], + [42, "width7_eight"], + [43, "width7_eight"], + [44, "width7_eight"], + [45, "width7_eight"], + [46, "width7_eight"], + [47, "width7_eight"], + [48, "width7_eight"], + [49, "width7_eight"], + [50, "fourcold_eight"], + [51, "width7_eight"], + [52, "width7_eight"], + [53, "width7_eight"], + [54, "width7_eight"], + [55, "width7_eight"], + [56, "fourcold_eight"], + [57, "width7_eight"], + [58, "width7_eight"], + [59, "width7_eight"], + [60, "width7_eight"], + [61, "width7_eight"], + [62, "width7_eight"], + [63, "width7_eight"], + [64, "width7_eight"], + [65, "width7_eight"], + [66, "width7_eight"], + [67, "width7_eight"], + [68, "width7_eight"], + [69, "width7_eight"], + [70, "fourcold_eight"], + [71, "width7_eight"] + ] +} diff --git a/research/format-limits/data/toys/sol_p3_cone_R16.json b/research/format-limits/data/toys/sol_p3_cone_R16.json new file mode 100644 index 0000000000..8908f77525 --- /dev/null +++ b/research/format-limits/data/toys/sol_p3_cone_R16.json @@ -0,0 +1 @@ +{"format": "gcert/1", "derived_from": "p3 cone-A + B0", "p": 0, "h": 6, "v": 8, "R": 16, "ports": [21, 37, 25, 41, 22, 38, 26, 42], "frames": [[], [32, 16, 8, 4, 2, 1], [21], [37], [25], [41], [22], [38], [26], [42], [37, 21], [25, 3], [41, 3], [38, 12], [21, 12], [37, 12], [22, 12], [21, 12, 3], [37, 21, 12], [38, 22], [37, 12, 3], [38, 22, 12], [37, 21, 12, 3], [41, 25, 3], [37, 21, 3], [21, 15], [42, 25], [37, 22], [51, 15], [38, 15], [38, 21, 15], [37, 22, 15], [35, 16, 9, 6], [33, 18, 11, 4], [33, 18, 8, 7], [34, 17, 11, 4], [33, 17, 8, 4, 3], [33, 16, 8, 5, 2], [34, 16, 10, 4, 1], [34, 16, 8, 6, 1], [32, 17, 8, 5, 2], [32, 17, 9, 4, 2], [33, 16, 9, 4, 2], [32, 18, 8, 6, 1], [32, 18, 10, 4, 1]], "start": [2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "final": [1, 1, 1, 1, 1, 1, 1, 1, 40, 37, 41, 42, 43, 39, 44, 38, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], "ext": [], "ret": [[0, 16, 18], [1, 17, 21], [2, 18, 24], [3, 19, 23], [4, 20, 17], [5, 21, 20]], "scat": {"inside": [1, 3], "outside": [-1, 6]}, "A": [["out", 2, 0, [[26, -1, 1]], []], ["out", 2, 0, [[27, 1, 1]], []], ["out", 3, 1, [[16, 1, 1]], []], ["out", 3, 1, [[29, 1, 1]], []], ["out", 4, 2, [[20, 1, 1]], []], ["out", 4, 2, [[24, 1, 1]], []], ["out", 5, 3, [[19, 1, 1]], []], ["out", 5, 3, [[30, -1, 1]], []], ["out", 6, 4, [[22, 1, 1]], []], ["out", 7, 5, [[18, 1, 1]], []], ["out", 7, 5, [[25, -1, 1]], []], ["out", 8, 6, [[23, -1, 1]], []], ["out", 8, 6, [[31, 1, 1]], []], ["out", 9, 7, [[17, 1, 1]], []], ["out", 9, 7, [[21, 1, 1]], []], ["out", 10, 16, [[26, -1, 1]], []], ["out", 11, 20, [[23, -1, 1]], []], ["out", 12, 21, [[19, 1, 1]], []], ["out", 13, 25, [[17, -1, 1]], []], ["out", 14, 27, [[24, 1, 1]], []], ["out", 15, 30, [[29, -1, 1]], []], ["out", 16, 31, [[22, 1, 1]], []], ["out", 6, 4, [[28, 1, 1]], []], ["out", 17, 22, [[20, 1, 1]], []], ["out", 18, 24, [[30, -1, 1]], []], ["out", 19, 28, [[18, 1, 1]], []], ["out", 20, 29, [[25, -1, 1]], []], ["out", 21, 31, [[17, 1, 1]], []], ["out", 22, 22, [[29, -1, 1]], []], ["out", 23, 23, [[19, -1, 1]], []], ["out", 20, 25, [[21, -1, 1]], []], ["out", 24, 26, [[18, -1, 1]], []], ["out", 17, 27, [[20, 1, 1]], []], ["out", 21, 28, [[17, 1, 1]], []], ["out", 18, 30, [[16, -1, 1]], []]], "B": [["out", 8, 6, [[10, -1, 2]], []], ["out", 8, 6, [[9, 1, 2]], []], ["out", 8, 6, [[12, -1, 2]], []], ["out", 8, 6, [[15, 1, 2]], []], ["out", 25, 0, [[9, 1, 2]], []], ["out", 26, 2, [[7, 1, 1]], []], ["out", 27, 4, [[1, -1, 1]], []], ["out", 27, 4, [[11, 1, 2]], []], ["out", 25, 6, [[15, -1, 2]], []], ["out", 28, 13, [[14, -1, 1]], []], ["out", 25, 0, [[6, -1, 1]], []], ["out", 29, 5, [[3, -1, 1]], []], ["out", 26, 7, [[2, -1, 1]], []], ["out", 28, 8, [[14, 1, 1]], []], ["out", 25, 15, [[10, 1, 1]], []], ["out", 30, 0, [[5, 1, 1]], []], ["out", 30, 0, [[10, 1, 2]], []], ["out", 30, 0, [[12, -1, 2]], []], ["out", 30, 0, [[15, 1, 1]], []], ["out", 31, 1, [[8, -1, 2]], []], ["out", 31, 2, [[8, -1, 1]], []], ["out", 31, 2, [[14, -1, 1]], []], ["out", 30, 3, [[10, -1, 1]], []], ["out", 30, 3, [[15, -1, 2]], []], ["out", 31, 4, [[8, -1, 1]], []], ["out", 31, 4, [[14, -1, 1]], []], ["out", 31, 7, [[8, -1, 2]], []], ["out", 31, 7, [[14, -1, 1]], []], ["out", 31, 1, [[4, 1, 1]], []], ["out", 31, 2, [[4, -1, 1]], []], ["out", 31, 2, [[11, -1, 2]], []], ["out", 31, 2, [[14, 1, 2]], []], ["out", 30, 3, [[0, -1, 1]], []], ["out", 30, 3, [[9, -1, 1]], []], ["out", 30, 5, [[0, -1, 1]], []], ["out", 30, 5, [[9, -1, 1]], []], ["out", 31, 7, [[4, -1, 1]], []], ["out", 31, 7, [[11, -1, 1]], []], ["out", 31, 8, [[14, -1, 1]], []], ["out", 30, 12, [[9, 1, 1]], []], ["out", 31, 13, [[14, 1, 1]], []], ["out", 30, 15, [[10, -1, 1]], []], ["out", 32, 1, [[13, 1, 2]], []], ["out", 33, 2, [[14, 1, 2]], []], ["out", 34, 3, [[12, 1, 2]], []], ["out", 32, 4, [[13, -1, 2]], []], ["out", 35, 5, [[6, 1, 1]], []], ["out", 35, 5, [[15, -1, 2]], []], ["out", 33, 2, [[14, -1, 1]], []], ["out", 34, 3, [[0, 1, 1]], []], ["out", 32, 4, [[1, -1, 1]], []], ["out", 32, 4, [[7, 1, 1]], []], ["out", 32, 4, [[11, -1, 2]], []], ["out", 35, 5, [[15, 1, 1]], []], ["out", 35, 6, [[15, -1, 2]], []], ["out", 34, 12, [[9, -1, 1]], []], ["out", 36, 0, [[6, 1, 1]], []], ["out", 37, 3, [[9, 1, 1]], []], ["out", 38, 5, [[15, -1, 1]], []], ["out", 39, 7, [[13, 1, 2]], []], ["out", 36, 0, [[2, 1, 1]], []], ["out", 36, 0, [[6, -1, 1]], []], ["out", 39, 7, [[13, -1, 1]], []], ["out", 1, 3, [[1, -1, 1]], []], ["out", 1, 3, [[2, -1, 1]], []], ["out", 1, 4, [[1, 1, 1]], []], ["out", 1, 4, [[2, -1, 1]], []], ["out", 1, 5, [[0, 1, 1]], []], ["out", 1, 5, [[1, -1, 1]], []], ["out", 1, 7, [[2, 1, 1]], []], ["out", 1, 0, [[3, -1, 1]], []], ["out", 1, 0, [[4, -1, 1]], []], ["out", 1, 0, [[6, 1, 1]], []], ["out", 1, 0, [[7, -1, 1]], []], ["out", 1, 1, [[4, -1, 1]], []], ["out", 1, 1, [[7, -1, 1]], []], ["out", 1, 2, [[4, 1, 1]], []], ["out", 1, 5, [[3, 1, 1]], []], ["out", 1, 5, [[6, -1, 1]], []], ["out", 1, 0, [[1, 1, 1]], []], ["out", 1, 0, [[5, -1, 1]], []], ["out", 1, 3, [[1, 1, 1]], []], ["out", 1, 3, [[2, 1, 1]], []], ["out", 1, 3, [[7, -1, 1]], []], ["out", 1, 4, [[1, 1, 1]], []], ["out", 1, 4, [[7, -1, 1]], []]], "blocks": {"x": {"1": 34, "2": 3}, "y": {"1": 26, "2": 7}, "s": {"1": 50, "2": 2, "3": 14}, "c": {"3": 6}}, "N": 194, "cst": 18} \ No newline at end of file diff --git a/research/format-limits/data/vendor/pr543/EXPECTED.json b/research/format-limits/data/vendor/pr543/EXPECTED.json new file mode 100644 index 0000000000..b61d859826 --- /dev/null +++ b/research/format-limits/data/vendor/pr543/EXPECTED.json @@ -0,0 +1,239 @@ +{ + "word": { + "file": "data/bitE8mut-r420.json.gz", + "file_sha256": "9721a3819efd68307f66f00d84a952eb28eb7c3ad2ce79653ce295c98a764784", + "content_sha256": "e597e3885c0a8daa262afa5985ee2930443329126aece76d33159d81882bdcc2", + "plan_sha256": "d5c2494b4baae801143049e172db303b3c8e25a002e9d9715a1d79dcb2d74c58", + "R": 420, + "retained_totals": 9, + "gates": { + "D": 120, + "A": 2064, + "B": 837, + "C": 2661 + }, + "local_histogram": { + "1": 1320, + "2": 1440, + "4": 60, + "5": 120, + "8": 9 + }, + "legality": { + "records": 29874, + "common_frame_ADDs": 26916, + "rank_mass": 5112 + }, + "five_stage_columns": 900, + "five_stage_payload_bits": 100, + "nine_stage_columns": 1380, + "nine_stage_payload_bits": 100, + "eleven_stage_columns": 1620, + "eleven_stage_payload_bits": 100 + }, + "interface": { + "hypotheses": { + "H1_no_target_feeds_z": true, + "H2_D_frame0_targets_from_helpers": true, + "H3_A_z_only_scatter_targets_B_split": true, + "H4_C_literal_reverse_at_full": true, + "H5_V_identity": true + }, + "conclusion": { + "U_block_form": true, + "J_identity": true, + "K_equals_D": true, + "C_is_U_inverse": true + }, + "interleaving": { + "z_gates_A": 2064, + "source_writes_A": 0, + "z_gates_B": 597, + "source_writes_B": 597, + "helper_writes_B": 0, + "sources_rewritten_B": 120, + "B_z_write_frame_dims": { + "4": 477, + "6": 120 + }, + "B_z_operand_kinds": { + "source<-helper": 120, + "source<-source": 477 + }, + "B_z_operand_kinds_by_dim": { + "dim4:source<-source": 477, + "dim6:source<-helper": 120 + }, + "B_z_writes_after_a_target_read_of_the_same_register": 597, + "B_target_reads_of_registers_rewritten_earlier_in_B": 120, + "target_reads_of_targets": 0, + "cleanup_gates": 2661 + } + }, + "nine": { + "pipeline": "PR #510 (PR #463 nine-stage template, 32 replicas, PR #442 hosting, PR #493 outer assembly)", + "bit_lower": "413456747036699736067/250000000000000000000000", + "bit_lower_decimal": "0.001653826988146798944268", + "profile": { + "1": 380160, + "2": 426624, + "4": 32640, + "5": 34560, + "6": 15360, + "7": 23040, + "8": 2592, + "42": 3456 + }, + "bit": { + "live": 30720, + "physical": 30729, + "maxchild": 42, + "rank_mass": 1956096, + "hosted_residuals": 120960, + "bank_assignments": 0, + "prefix_bits": 189, + "charged_prefix_bits": 192, + "coefficient_bits": 189, + "two_level_coefficient_bits": 416, + "charged_two_level_coefficient_bits": 512, + "row_coefficient": 18355, + "halving_depth": 2 + }, + "kappa": { + "pr535": { + "kappa": "793733736881443/500000000000000000", + "kappa_decimal": "0.001587467473762886", + "complex_lower": "1589991533606044174031/1000000000000000000000000", + "binding_component": "complex" + }, + "pr531": { + "kappa": "1517760977820331/1000000000000000000", + "kappa_decimal": "0.001517760977820331", + "complex_lower": "304013615566499291631/200000000000000000000000", + "binding_component": "complex" + } + } + }, + "eleven": { + "pipeline": "PR #493 (PR #445 geometry, PR #472 emitter, audit and invoice, PR #442 hosting)", + "bit_lower": "82015816228313440961/50000000000000000000000", + "bit_lower_decimal": "0.00164031632456626881922", + "profile": { + "1": 116160, + "2": 130560, + "4": 9120, + "5": 10560, + "6": 3839, + "7": 7680, + "8": 792, + "14": 1, + "56": 3497 + }, + "bit": { + "live": 9600, + "physical": 9609, + "maxchild": 56, + "rank_mass": 745536, + "hosted_residuals": 36960, + "prefix_bits": 4710, + "charged_prefix_bits": 4736, + "coefficient_bits": 4710, + "three_level_coefficient_bits": 14185, + "charged_three_level_coefficient_bits": 14208, + "row_coefficient": 19431, + "halving_depth": 3 + }, + "emitted_program_sha256": "3de4325e0df33ca85116d05cbcc6810f025d6083e5134d128236769c97699f51", + "kappa": { + "pr535": { + "kappa": "793733736881443/500000000000000000", + "kappa_decimal": "0.001587467473762886", + "complex_lower": "1589991533606044174031/1000000000000000000000000", + "binding_component": "complex" + }, + "pr531": { + "kappa": "1517760977820331/1000000000000000000", + "kappa_decimal": "0.001517760977820331", + "complex_lower": "304013615566499291631/200000000000000000000000", + "binding_component": "complex" + } + } + }, + "controls": { + "pr510_r480_nine": { + "word": "vendor/pr510/e8-r480-dead-totals/data/bitE8mut-r480.json.gz", + "bit_lower": "396861776523137034277/250000000000000000000000", + "bit_lower_decimal": "0.001587447106092548137108", + "kappa": { + "pr535": { + "kappa": "1584931111785787/1000000000000000000", + "kappa_decimal": "0.001584931111785787", + "complex_lower": "1589991533606044174031/1000000000000000000000000", + "binding_component": "bit" + }, + "pr531": { + "kappa": "1517760977820331/1000000000000000000", + "kappa_decimal": "0.001517760977820331", + "complex_lower": "304013615566499291631/200000000000000000000000", + "binding_component": "complex" + }, + "pr484": { + "kappa": "662515748707749/500000000000000000", + "kappa_decimal": "0.001325031497415498", + "complex_lower": "663394767670133/500000000000000000", + "binding_component": "complex" + }, + "pr471": { + "kappa": "260706019542937/200000000000000000", + "kappa_decimal": "0.001303530097714685", + "complex_lower": "1305231506267591/1000000000000000000", + "binding_component": "complex" + }, + "pr458": { + "kappa": "323880830669511/250000000000000000", + "kappa_decimal": "0.001295523322678044", + "complex_lower": "1297203880559577927527/1000000000000000000000000", + "binding_component": "complex" + } + } + }, + "pr493_r489_eleven": { + "word": "../e8-bit-carrier-skeleton/data/bit/bitE8mut-r489.json.gz", + "bit_lower": "391360506745414227149/250000000000000000000000", + "bit_lower_decimal": "0.001565442026981656908596", + "emitted_program_sha256": "e37b52e4861c39154b5891460fb45df8651c92cd68961078f8f06596f057c822", + "kappa": { + "pr535": { + "kappa": "97687203033227/62500000000000000", + "kappa_decimal": "0.001562995248531632", + "complex_lower": "1589991533606044174031/1000000000000000000000000", + "binding_component": "bit" + }, + "pr531": { + "kappa": "1517760977820331/1000000000000000000", + "kappa_decimal": "0.001517760977820331", + "complex_lower": "304013615566499291631/200000000000000000000000", + "binding_component": "complex" + }, + "pr484": { + "kappa": "662515748707749/500000000000000000", + "kappa_decimal": "0.001325031497415498", + "complex_lower": "663394767670133/500000000000000000", + "binding_component": "complex" + }, + "pr471": { + "kappa": "260706019542937/200000000000000000", + "kappa_decimal": "0.001303530097714685", + "complex_lower": "1305231506267591/1000000000000000000", + "binding_component": "complex" + }, + "pr458": { + "kappa": "323880830669511/250000000000000000", + "kappa_decimal": "0.001295523322678044", + "complex_lower": "1297203880559577927527/1000000000000000000000000", + "binding_component": "complex" + } + } + } + } +} diff --git a/research/format-limits/data/vendor/pr545/EXPECTED.json b/research/format-limits/data/vendor/pr545/EXPECTED.json new file mode 100644 index 0000000000..ac7f102363 --- /dev/null +++ b/research/format-limits/data/vendor/pr545/EXPECTED.json @@ -0,0 +1,127 @@ +{ + "word": { + "v": 111, + "R": 489, + "cst": 63, + "copy_ranks": [ + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7 + ], + "punctured": [ + 39, + 52, + 57, + 71, + 76, + 78, + 103, + 109, + 114 + ], + "content_sha256": "599dbe2184a0b99f01345543a6523e41df7b164513fc25dc7b5dadab548205d3", + "local_histogram": { + "1": 1182, + "2": 1332, + "3": 63, + "4": 153, + "5": 9, + "6": 129, + "7": 9 + }, + "five_stage_payload_bits": 91, + "eleven_stage_payload_bits": 91, + "source_destination_gates_A": 501 + }, + "eleven": { + "bit_lower": "165947204563779652541/100000000000000000000000", + "bit_lower_decimal": "0.00165947204563779652541", + "profile": { + "1": 104016, + "2": 120768, + "3": 5544, + "4": 17015, + "5": 792, + "6": 14904, + "7": 7896, + "28": 1, + "56": 1971 + }, + "emitted_program_sha256": "80c4e0f4d635a0c09a3e1a0ef81cc7e0590233410840d5b26d1149daa049718b", + "bit": { + "live": 8880, + "physical": 8889, + "maxchild": 56, + "rank_mass": 689304, + "hosted_residuals": 43032, + "prefix_bits": 1843, + "charged_prefix_bits": 1856, + "coefficient_bits": 1843, + "three_level_coefficient_bits": 5583, + "charged_three_level_coefficient_bits": 5632, + "row_coefficient": 19431, + "halving_depth": 3 + } + }, + "kappa": { + "pr535": { + "kappa": "793733736881443/500000000000000000", + "kappa_decimal": "0.001587467473762886", + "binding_component": "complex", + "complex_lower": "1589991533606044174031/1000000000000000000000000" + } + }, + "control": { + "word_content_sha256": "8639e22008c24a5690dd250eba702fe5fca85ddd036dcbec20baba77b7e213ba", + "five_stage_payload_bits": 102, + "bit_lower": "393688338238452162729/250000000000000000000000", + "bit_lower_decimal": "0.001574753352953808650916", + "profile": { + "1": 105600, + "2": 130560, + "4": 19680, + "6": 14400, + "7": 7680, + "8": 792, + "48": 1, + "56": 2742 + }, + "emitted_program_sha256": "7da5e3cb8daa231104f4e55f16c560fa56a59f10b8b2789e173923d9d2ca46fc", + "kappa": { + "pr484": "662515748707749/500000000000000000", + "pr471": "260706019542937/200000000000000000", + "pr458": "323880830669511/250000000000000000" + }, + "stacking": { + "calls": 88, + "calls_with_stacked_helpers": 80, + "max_helpers_on_one_family": 7 + } + }, + "live_bit": { + "source": "PR #510 (R480, nine stages), the bit c of PR #535", + "bit_lower": "396861776523137034277/250000000000000000000000", + "bit_lower_decimal": "0.001587447106092548137108" + }, + "pr535": { + "kappa": "1584931111785787/1000000000000000000", + "kappa_decimal": "0.001584931111785787", + "complex_lower": "1589991533606044174031/1000000000000000000000000" + }, + "hosting": { + "rule": "PR #442's pooled whole-residual integer programme (hosting_core.solve), eight replicas pooled, as in #472 / #493 / #503 / #510", + "stacking": { + "calls": 88, + "calls_with_stacked_helpers": 82, + "max_helpers_on_one_family": 7 + }, + "c_strict_per_stage": "0.001651282591289915996071", + "note": "strict = one helper per family copy per STAGE (stricter than #458 per invocation): a lower bound on the c of any #458-compliant hosting; kappa unchanged (complex-bound)" + } +} diff --git a/research/format-limits/data/vendor/pr555/EXPECTED.json b/research/format-limits/data/vendor/pr555/EXPECTED.json new file mode 100644 index 0000000000..c8ad4439e8 --- /dev/null +++ b/research/format-limits/data/vendor/pr555/EXPECTED.json @@ -0,0 +1,221 @@ +{ + "word": { + "file": "data/bitE8mut-p111.json.gz", + "file_sha256": "1bc3c53d4baf4927c6a00c339ea3975516471a48074d4d97c6addaded2a4d858", + "content_sha256": "d0df3c89ae84989f4045ba1681a5e2e9fcdfa38ed0301c8abf5185537155cbe3", + "plan_sha256": "d5c2494b4baae801143049e172db303b3c8e25a002e9d9715a1d79dcb2d74c58", + "params_sha256": "dd371e1d6fe57602f242920b582ec4c133efc8ede4a849fd701ac90b7f6e1853", + "v": 111, + "R": 439, + "punctured": [ + 10, + 15, + 51, + 53, + 56, + 66, + 72, + 89, + 111 + ], + "retained_totals": 9, + "copy_ranks": [ + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7 + ], + "decoder_constant": 63, + "gates": { + "D": 111, + "A": 2073, + "B": 712, + "C": 2572 + }, + "stats": { + "extra_carriers": 10, + "junk_wires": 0, + "rcv_flips": 10 + }, + "local_histogram": { + "1": 1321, + "2": 1342, + "3": 80, + "4": 47, + "5": 102, + "6": 10, + "7": 18 + }, + "legality": { + "records": 27234, + "common_frame_ADDs": 24305, + "rank_mass": 5129 + }, + "five_stage_columns": 883, + "five_stage_payload_bits": 93, + "nine_stage_columns": 1327, + "nine_stage_payload_bits": 93, + "eleven_stage_columns": 1549, + "eleven_stage_payload_bits": 93 + }, + "interface": { + "hypotheses": { + "H1_no_target_feeds_z": true, + "H2_D_frame0_targets_from_helpers": true, + "H3_A_z_only_scatter_targets_B_split": true, + "H4_C_literal_reverse_at_full": true, + "H5_V_identity": true + }, + "conclusion": { + "U_block_form": true, + "J_identity": true, + "K_equals_D": true, + "C_is_U_inverse": true + }, + "interleaving": { + "z_gates_A": 2073, + "source_writes_A": 0, + "z_gates_B": 499, + "source_writes_B": 483, + "helper_writes_B": 16, + "sources_rewritten_B": 108, + "B_z_write_frame_dims": { + "4": 388, + "6": 111 + }, + "B_z_operand_kinds": { + "helper<-helper": 3, + "helper<-source": 13, + "source<-helper": 108, + "source<-source": 375 + }, + "B_z_operand_kinds_by_dim": { + "dim4:helper<-source": 13, + "dim4:source<-source": 375, + "dim6:helper<-helper": 3, + "dim6:source<-helper": 108 + }, + "B_z_writes_after_a_target_read_of_the_same_register": 454, + "B_target_reads_of_registers_rewritten_earlier_in_B": 111, + "target_reads_of_targets": 0, + "cleanup_gates": 2572 + } + }, + "nine": { + "pipeline": "PR #510 (PR #463 nine-stage template, 32 replicas, PR #442 hosting, PR #493 outer assembly), parameterised for v <= 120 by code/adapt9p.py", + "bit_lower": "1733052823330162099157/1000000000000000000000000", + "bit_lower_decimal": "0.001733052823330162099157", + "profile": { + "1": 380448, + "2": 400416, + "3": 23040, + "4": 27744, + "5": 29376, + "6": 17088, + "7": 26496, + "42": 288 + }, + "bit": { + "live": 28416, + "physical": 28425, + "maxchild": 42, + "rank_mass": 1808352, + "hosted_residuals": 126432, + "bank_assignments": 0, + "prefix_bits": 177, + "charged_prefix_bits": 192, + "coefficient_bits": 177, + "two_level_coefficient_bits": 393, + "charged_two_level_coefficient_bits": 512, + "row_coefficient": 18355, + "halving_depth": 2 + }, + "kappa": { + "pr548": { + "kappa": "49718254847979/31250000000000000", + "kappa_decimal": "0.001590984155135328", + "complex_lower": "796759709641153381751/500000000000000000000000", + "binding_component": "complex" + }, + "pr544": { + "kappa": "397677800014309/250000000000000000", + "kappa_decimal": "0.001590711200057236", + "complex_lower": "31864911873350496687/20000000000000000000000", + "binding_component": "complex" + }, + "pr535": { + "kappa": "793733736881443/500000000000000000", + "kappa_decimal": "0.001587467473762886", + "complex_lower": "1589991533606044174031/1000000000000000000000000", + "binding_component": "complex" + }, + "pr531": { + "kappa": "1517760977820331/1000000000000000000", + "kappa_decimal": "0.001517760977820331", + "complex_lower": "304013615566499291631/200000000000000000000000", + "binding_component": "complex" + } + } + }, + "eleven": { + "pipeline": "PR #493 (PR #445 geometry, PR #472 emitter, audit and invoice, PR #442 hosting), parameterised by PR #545's code/adapt.py", + "bit_lower": "427652201524503168379/250000000000000000000000", + "bit_lower_decimal": "0.001710608806098012673516", + "profile": { + "1": 116248, + "2": 121648, + "3": 7040, + "4": 7688, + "5": 8976, + "6": 4432, + "7": 8688, + "56": 2600 + }, + "bit": { + "live": 8880, + "physical": 8889, + "maxchild": 56, + "rank_mass": 689304, + "hosted_residuals": 38632, + "prefix_bits": 4304, + "charged_prefix_bits": 4352, + "coefficient_bits": 4304, + "three_level_coefficient_bits": 12966, + "charged_three_level_coefficient_bits": 12992, + "row_coefficient": 19431, + "halving_depth": 3 + }, + "emitted_program_sha256": "790bbd2d8ef4e1169fca344c76b1965ee2fe78e34e74d16d458e4849cc2ba3b6", + "kappa": { + "pr548": { + "kappa": "49718254847979/31250000000000000", + "kappa_decimal": "0.001590984155135328", + "complex_lower": "796759709641153381751/500000000000000000000000", + "binding_component": "complex" + }, + "pr544": { + "kappa": "397677800014309/250000000000000000", + "kappa_decimal": "0.001590711200057236", + "complex_lower": "31864911873350496687/20000000000000000000000", + "binding_component": "complex" + }, + "pr535": { + "kappa": "793733736881443/500000000000000000", + "kappa_decimal": "0.001587467473762886", + "complex_lower": "1589991533606044174031/1000000000000000000000000", + "binding_component": "complex" + }, + "pr531": { + "kappa": "1517760977820331/1000000000000000000", + "kappa_decimal": "0.001517760977820331", + "complex_lower": "304013615566499291631/200000000000000000000000", + "binding_component": "complex" + } + } + } +} diff --git a/research/format-limits/data/vendor/pr555/bitE8mut-p111.json.gz b/research/format-limits/data/vendor/pr555/bitE8mut-p111.json.gz new file mode 100644 index 0000000000..bdbb95aa97 Binary files /dev/null and b/research/format-limits/data/vendor/pr555/bitE8mut-p111.json.gz differ diff --git a/research/format-limits/data/vendor/pr568/PLAN.json.gz b/research/format-limits/data/vendor/pr568/PLAN.json.gz new file mode 100644 index 0000000000..de3f43eb5a Binary files /dev/null and b/research/format-limits/data/vendor/pr568/PLAN.json.gz differ diff --git a/research/format-limits/data/vendor/pr569/fourcold-eight-FULL-WORD.json.gz b/research/format-limits/data/vendor/pr569/fourcold-eight-FULL-WORD.json.gz new file mode 100644 index 0000000000..cdf6203dc4 Binary files /dev/null and b/research/format-limits/data/vendor/pr569/fourcold-eight-FULL-WORD.json.gz differ diff --git a/research/format-limits/data/vendor/pr569/width7-eight-FULL-WORD.json.gz b/research/format-limits/data/vendor/pr569/width7-eight-FULL-WORD.json.gz new file mode 100644 index 0000000000..d4f2dae828 Binary files /dev/null and b/research/format-limits/data/vendor/pr569/width7-eight-FULL-WORD.json.gz differ diff --git a/research/format-limits/data/vendor/pr571/combined-eight-local-FULL-WORD.json.gz b/research/format-limits/data/vendor/pr571/combined-eight-local-FULL-WORD.json.gz new file mode 100644 index 0000000000..f129286993 Binary files /dev/null and b/research/format-limits/data/vendor/pr571/combined-eight-local-FULL-WORD.json.gz differ diff --git a/research/format-limits/requirements.txt b/research/format-limits/requirements.txt new file mode 100644 index 0000000000..b010097e9d --- /dev/null +++ b/research/format-limits/requirements.txt @@ -0,0 +1,7 @@ +# Tested set (a fresh venv from this file passes verify.sh on Python 3.11.17 and 3.14.7). +# Also tested and passing: numpy 2.3.5 / scipy 1.17.0 and numpy 2.5.4 / scipy 1.18.1 (see README, "Tested environments"). +numpy==2.4.6 +scipy==1.17.1 +sympy==1.14.0 +python-sat==1.9.dev15 +ortools==9.15.6755 diff --git a/research/format-limits/scripts/a1_ceiling_roots.py b/research/format-limits/scripts/a1_ceiling_roots.py new file mode 100644 index 0000000000..99d470c031 --- /dev/null +++ b/research/format-limits/scripts/a1_ceiling_roots.py @@ -0,0 +1,81 @@ +"""A. Format ceiling, rev. 2: certified skeleton roots X(s, w, x) and the kappa ceiling. + +X(s, w, x) is the root q of F_s(q) = D_s for the R-free B_K skeleton (skel.profile, theorem variant: active climbs at +cap a = h - k, copies at cap h, idle slots of rank r at cap max(r, h)); D_s/v = (s-1)k - s x, m = k + s(h-k). +Roots are bracketed with rational-interval arithmetic (cert.root_bracket); the upper end 'hi' is the certified value. + +Units (k = 1): + bit, punctured star unit of #545/#555: v = 111 live lines, decoder constant 63 (x = 63/111), window h = 8; + complex, punctured unit of #523 and its descendants (#531 ... #569): v = 112, copy cost 64 (x = 64/112), h = 9; + superseded rev. 1 scope: the full E8 unit v = 120, copy cost 72 (x = 3/5) on both sides. +kappa <= X/(1+X) with X = min(X_bit*, X_cx*) (README section A.4 for the outer form). +""" +from fractions import Fraction as Fr + +from report import check, finish, near +from skel import X + +S_LIST = (3, 5, 7, 9, 11, 13) +UNITS = { # name: (h, cst, v) + 'bit-111/63': (8, 63, 111), + 'cx-112/64': (9, 64, 112), + 'bit-120/72': (8, 72, 120), + 'cx-120/72': (9, 72, 120), +} +# certified upper ends (hi) recorded by the original runs; compared to relative 1e-12 +EXPECTED = { + 'bit-111/63': {3: 5.947449820544458e-3, 5: 6.00049473312529e-3, 7: 5.2094781808670505e-3, + 9: 4.607152286783883e-3, 11: 4.1489567374021555e-3, 13: 3.7878851034153518e-3}, + 'cx-112/64': {3: 5.047389571662491e-3, 5: 5.186252252886545e-3, 7: 4.512993851037537e-3, + 9: 3.994628507503969e-3, 11: 3.5988803552243387e-3, 13: 3.2864689075796437e-3}, + 'bit-120/72': {3: 3.997571235241277e-3, 5: 5.159798631791548e-3, 7: 4.623205298039335e-3, + 9: 4.139748562309081e-3, 11: 3.752885369025204e-3, 13: 3.440493799826091e-3}, + 'cx-120/72': {3: 3.5307429201300307e-3, 5: 4.535607180902823e-3, 7: 4.059761375276634e-3, + 9: 3.6334780884322328e-3, 11: 3.2929429181725836e-3, 13: 3.0181922014469375e-3}, +} +KAPPA_CEILING = 5.1595e-3 # rev. 2, complex binds +KAPPA_BIT_ONLY = 5.9647e-3 # bit-only corollary c/(1+c) +KAPPA_REV1 = 4.5151e-3 # superseded rev. 1 value (x = 3/5) +FRONTIER = {'bit': 1.733052823330162e-3, 'cx': 0.00159868506668458107128} # #555 c (s = 9), #568 b (s = 9) +HEADROOM_S9 = {'bit': 2.658, 'cx': 2.499} +COPY_UNIT = {5: 3.9, 9: 2.8, 11: 2.65} # % gain of bit X per copy-rank unit per stage (63 -> 62) + +tab = {} +for name, (h, cst, v) in UNITS.items(): + row = {} + for s in S_LIST: + r = X(s, h, 1, Fr(cst, v)) + row[s] = r + tab[name] = row + ok = all(abs(float(row[s]['hi']) / EXPECTED[name][s] - 1) < 1e-12 and row[s]['hi'] - row[s]['lo'] < Fr(1, 10**15) + for s in S_LIST) + check('A1.roots.' + name, ok, ' '.join('s%d:%.5e' % (s, float(row[s]['hi'])) for s in S_LIST)) + best = max(S_LIST, key=lambda s: row[s]['hi']) + check('A1.best-s.' + name, best == 5, 'max over s in %s at s = %d' % (list(S_LIST), best)) + +xb, xc = tab['bit-111/63'][5]['hi'], tab['cx-112/64'][5]['hi'] +Xmin = min(xb, xc) +kap = Xmin / (1 + Xmin) +check('A1.kappa-ceiling', xc < xb and near(kap, KAPPA_CEILING, 7), + 'X_bit* %.5e, X_cx* %.5e (complex binds); kappa <= X/(1+X) = %.7e' % (xb, xc, float(kap))) +check('A1.kappa-bit-only', near(xb / (1 + xb), KAPPA_BIT_ONLY, 7), 'c/(1+c) <= %.7e' % float(xb / (1 + xb))) +x1 = min(tab['bit-120/72'][5]['hi'], tab['cx-120/72'][5]['hi']) +check('A1.rev1-superseded', near(x1 / (1 + x1), KAPPA_REV1, 7), + 'the x = 3/5 scope gives %.7e; the punctured units have x = 63/111, 64/112 < 3/5' % float(x1 / (1 + x1))) +for side, name in (('bit', 'bit-111/63'), ('cx', 'cx-112/64')): + ratio = float(tab[name][9]['hi']) / FRONTIER[side] + check('A1.headroom-s9.' + side, near(ratio, HEADROOM_S9[side], 3), + 'X(s=9) / frontier value = %.3f' % ratio) +for s, pct in COPY_UNIT.items(): + up = X(s, 8, 1, Fr(62, 111))['hi'] + g = 100 * float(up / tab['bit-111/63'][s]['hi'] - 1) + check('A1.copy-unit.s%d' % s, abs(g - pct) < 0.05, 'bit X gain for cst 63 -> 62 at s = %d: +%.2f%%' % (s, g)) +# Units with smaller copy ratio x are outside the realised-unit scope; their ceilings show what a cheaper decoder would +# move (no word exists on either unit). Best s = 3 on both. +HYPO = {'bit-102/54': (8, 54, 102, 8.245729422632946e-3), 'cx-104/56': (9, 56, 104, 6.799964322294041e-3)} +for name, (h, cst, v, exp) in HYPO.items(): + rr = {s: X(s, h, 1, Fr(cst, v))['hi'] for s in S_LIST} + sb = max(rr, key=rr.get) + check('A1.outside-scope.' + name, sb == 3 and abs(float(rr[3]) / exp - 1) < 1e-12, + 'x = %d/%d: X* = %.5e at s = %d (not a realised unit)' % (cst, v, rr[sb], sb)) +finish() diff --git a/research/format-limits/scripts/a2_ceiling_sup.py b/research/format-limits/scripts/a2_ceiling_sup.py new file mode 100644 index 0000000000..dc6a7d0050 --- /dev/null +++ b/research/format-limits/scripts/a2_ceiling_sup.py @@ -0,0 +1,43 @@ +"""A. Format ceiling, rev. 2: the supremum over the stage count s is attained at s = 5 on both realised units. + +For every odd s the root obeys X(s) <= D_s / Cost_s, Cost_s = sum over the skeleton slots of mass * ln(m / cap) +(because e^y - 1 >= y). This script certifies D_s/Cost_s < X(5) for every odd s = 7 .. 401 with rational-interval +logarithms (cost_iv's lower end, so D/Cost is an upper bound), on the bit unit 111/63 and the complex unit 112/64. +For s >= 403 the README (section A.3) gives the analytic tail Cost_s/v >= 4a(K^2/4 - K/e - K/2), K = (s-1)/2; the +value of that bound at s = 403 is printed, and the elementary inequality sum_{p= K^2/4 - K/e - K/2 +that it uses is checked numerically for K = 2 .. 5000 (its proof is in the README). +""" +import math +from fractions import Fraction as Fr + +from cert import cost_iv +from report import check, finish, near +from skel import X, profile + +UNITS = {'bit-111/63': (8, 63, 111), 'cx-112/64': (9, 64, 112)} +EXPECTED_WORST = {'bit-111/63': (5.231066e-3, 7), 'cx-112/64': (4.529190e-3, 7)} # max D/Cost over s = 7..401 +EXPECTED_TAIL = {'bit-111/63': 6.270e-4, 'cx-112/64': 5.438e-4} # analytic tail value at s = 403 + +for name, (h, cst, v) in UNITS.items(): + x = Fr(cst, v) + x5 = X(5, h, 1, x)['hi'] + worst, sworst, allbelow = Fr(0), None, True + for s in range(7, 402, 2): + prof, m, D = profile(s, h, 1, x) + clo, _ = cost_iv(prof, m) + ub = D / clo + allbelow &= ub < x5 + if ub > worst: + worst, sworst = ub, s + ew, es = EXPECTED_WORST[name] + check('A2.sup.' + name, allbelow and sworst == es and abs(float(worst) / ew - 1) < 1e-6, + 'D/Cost < X(5) = %.6e for all odd s in 7..401; largest %.6e at s = %d' % (float(x5), float(worst), sworst)) + a = h - 1 + K = 201 + s = 2 * K + 1 + tail = float(1 - x) * s / (4 * a * (K * K / 4 - K / math.e - K / 2)) + check('A2.tail.' + name, tail < float(x5) and near(tail, EXPECTED_TAIL[name], 7), + 'analytic tail bound at s = 403: %.3e (decreasing in s)' % tail) +bad = [K for K in range(2, 5001) if sum(p * math.log(K / p) for p in range(1, K)) < K * K / 4 - K / math.e - K / 2] +check('A2.tail-inequality', not bad, 'sum_{p= K^2/4 - K/e - K/2 for K = 2..5000') +finish() diff --git a/research/format-limits/scripts/a3_axioms.py b/research/format-limits/scripts/a3_axioms.py new file mode 100644 index 0000000000..5076d8e613 --- /dev/null +++ b/research/format-limits/scripts/a3_axioms.py @@ -0,0 +1,86 @@ +"""A. Format ceiling, rev. 2: the accounting axioms checked on the published profiles of the frontier words. + +(P) pressure identity: the certified root of sum_r z_r r((m/r)^q - 1) = D on a word's published global profile + reproduces the word's published supplier value (bit c or complex b); +(Dfc) deficit identity: m * live - rank mass = D = T[(s-1) v k - s cst] (equality, not just <=); +(Win) m = k + s (h - k) (for #543/#545/#555/#568 the largest child is the literal idle remainder (2K - 2) a); +(Sch) the B_K idle schedule: #568's per-replica idle windows are exactly skel.idle_slots(K, a) on both banks, and the + skeleton mass (active climbs + copies + idle slots) equals each word's real rank mass; +(Hst) #555 hosts every helper residual whole (no bank assignments); +Lemma 2 (slot domination) pointwise: f_N(q) >= F_s(q; cst_N) for q in [1e-5, 1] on every profile (min ratio printed). +Profiles are read from the published files: #510 (main), #543, #545, #555 (EXPECTED.json), #568 (PLAN.json). +""" +from collections import Counter +from fractions import Fraction as Fr + +from cert import root_bracket +from report import VENDOR, check, finish, load_json, main_file, near +from skel import X, idle_slots, profile + +e510 = load_json(main_file('research/e8-r480-nine-stage/EXPECTED.json')) +e543 = load_json(VENDOR / 'pr543' / 'EXPECTED.json') +e545 = load_json(VENDOR / 'pr545' / 'EXPECTED.json') +e555 = load_json(VENDOR / 'pr555' / 'EXPECTED.json') +p568 = load_json(VENDOR / 'pr568' / 'PLAN.json.gz') + + +def prof(d): + return {int(r): z for r, z in d.items()} + + +# name: (profile, h, v, cst, s, T, published value) +WORDS = { + '#510-R480-s9': (prof(e510['nine']['profile']), 8, 120, 72, 9, 32, Fr(e510['nine']['bit_lower'])), + '#543-R420-s9': (prof(e543['nine']['profile']), 8, 120, 72, 9, 32, Fr(e543['nine']['bit_lower'])), + '#543-R420-s11': (prof(e543['eleven']['profile']), 8, 120, 72, 11, 8, Fr(e543['eleven']['bit_lower'])), + '#545-p111-s11': (prof(e545['eleven']['profile']), 8, 111, 63, 11, 8, Fr(e545['eleven']['bit_lower'])), + '#555-p111-s9': (prof(e555['nine']['profile']), 8, 111, 63, 9, 32, Fr(e555['nine']['bit_lower'])), + '#555-p111-s11': (prof(e555['eleven']['profile']), 8, 111, 63, 11, 8, Fr(e555['eleven']['bit_lower'])), + '#568-cx-s9': (prof(p568['profile']), 9, 112, 64, 9, 8, Fr('0.00159868506668458107128')), # #568 README +} +# (min over q of f_N/F_s, X(s, x)/root): recorded values, compared to 3 decimals +EXPECTED_RATIOS = {'#555-p111-s9': (2.66, 2.658), '#568-cx-s9': (2.50, 2.499)} + +for name, (P, h, v, cst, s, T, pub) in WORDS.items(): + k, a, K = 1, h - 1, (s - 1) // 2 + m = k + s * a + D = T * ((s - 1) * v * k - s * cst) + mass = sum(r * z for r, z in P.items()) + W = Fr(mass + D, m) + lo, hi = root_bracket(P, m, D, hi=Fr(1, 100)) + rel = float(hi / pub - 1) + check('A3.P.' + name, hi >= pub and rel < 2e-9, + 'certified root in [%.12e, %.12e]; published %.12e (root - published = %.1e relative)' % (lo, hi, pub, rel)) + check('A3.Dfc.' + name, W.denominator == 1 and m * W - mass == D, + 'm = %d, W = %s, rank mass %d, m W - mass = %d = T[(s-1)v - s cst]' % (m, W, mass, D)) + check('A3.Win.' + name, m == k + s * a, 'm = k + s(h-k) = %d; largest child %d%s' % ( + m, max(P), ' = (2K-2)a: the B_K idle remainders are literal' if max(P) == (2 * K - 2) * a else '')) + pp, mm, Ds = profile(s, h, k, Fr(cst, v)) + ratios = [] + for qq in (1e-5, 1e-4, 1e-3, 3e-3, 1e-2, 0.05, 0.2, 0.5, 1.0): + fN = sum(z * r * ((m / r) ** qq - 1) for r, z in P.items()) + Fs = v * T * sum(float(z) * float(r) * ((m / float(r)) ** qq - 1) for r, z in pp.items()) + ratios.append(fN / Fs) + head = float(X(s, h, k, Fr(cst, v))['hi'] / hi) + ok = min(ratios) >= 1 + if name in EXPECTED_RATIOS: + er, eh = EXPECTED_RATIOS[name] + ok = ok and near(min(ratios), er, 2) and near(head, eh, 3) + check('A3.lemma2.' + name, ok, 'min_q f_N(q)/F_s(q) = %.3f; X(s,x)/root = %.3f' % (min(ratios), head)) + +# (Sch): skeleton mass = real rank mass, and #568's windows are the B_K idle slots +for name, h, v, cst, T, real in (('#555-p111-s9', 8, 111, 63, 32, e555['nine']['bit']['rank_mass']), + ('#568-cx-s9', 9, 112, 64, 8, sum(r * z for r, z in prof(p568['profile']).items()))): + s, a, K = 9, h - 1, 4 + data, copies, idle = 2 * v * s * a * T, cst * s * T, 2 * v * T * sum(idle_slots(K, a)) + check('A3.Sch-mass.' + name, data + copies + idle == real, + 'active %d + copies %d + idle %d = %d = rank mass' % (data, copies, idle, real)) +reps = sorted({int(k.split(',')[0]) for k in p568['windows']}) +want = Counter(idle_slots(4, 8)) + Counter(idle_slots(4, 8)) +okw = all(Counter(r for kk, (r, _) in p568['windows'].items() if int(kk.split(',')[0]) == rep) == want for rep in reps) +check('A3.Sch-windows.#568', okw and len(reps) == p568['T'], + '%d replicas, each with idle windows %s = idle_slots(K=4, a=8) on both banks' % (len(reps), dict(sorted(want.items())))) +b = e555['nine']['bit'] +check('A3.Hst.#555', b['bank_assignments'] == 0 and b['hosted_residuals'] == 439 * 9 * 32, + 'bank assignments 0; hosted residuals %d = R * s * T = 439 * 288' % b['hosted_residuals']) +finish() diff --git a/research/format-limits/scripts/a4_gap.py b/research/format-limits/scripts/a4_gap.py new file mode 100644 index 0000000000..05ffc10d76 --- /dev/null +++ b/research/format-limits/scripts/a4_gap.py @@ -0,0 +1,175 @@ +"""A. Format ceiling, rev. 2: where the frontier words lose against the s = 9 skeleton (gap decomposition). + +All roots are certified upper ends of the pressure root at the word's own (m, D); every step keeps the rank mass +m W - D fixed. Steps: + A theorem skeleton (R-free, idle slots charged at cap max(r, h)); + B literal R = 0 profile (each idle slot one child of its own rank); + C B with the real data-register runs and the real copy children; + D C plus every helper run paid as its own child, unhosted (the idle slots stay paid in full; this is the only step + whose rank mass differs: it adds the helper mass, as if helpers lived on their own bank wires at the same D); + E the real word (helpers hosted whole into idle frame changes; the idle remainders paid). +#555 (bit): data, helper and copy runs are replayed from the published word (bitE8mut-p111.json.gz) and the idle +remainder is the published global profile minus s T times the per-stage local profile. +#568 (complex): the data-register runs per call are measured on the four-cold provider word of #569 (the same x/y +ladders as #568's providers); the paid idle remainder is an input recorded from #568's hosting (data/ceiling/ +gap568-inputs.json); the helper runs are the published global profile minus data, centres and idle remainder. +""" +from collections import Counter, defaultdict +from fractions import Fraction as Fr +import sys + +import numpy as np + +from cert import root_bracket +from report import DATA, REPO, VENDOR, check, finish, load_json, main_file +from skel import idle_slots + +EXPECTED = { + '#555': {'A': 4.6072e-3, 'B': 4.5661e-3, 'C': 3.7868e-3, 'D': 1.6183e-3, 'E': 1.7331e-3}, + '#568': {'A': 3.9946e-3, 'B': 3.9631e-3, 'C': 3.1544e-3, 'D': 1.3517e-3, 'E': 1.5987e-3}, +} +EXPECTED_555_RUNS = {'x': {1: 317, 2: 209, 3: 10, 4: 3}, 'y': {1: 10, 2: 92, 5: 92, 6: 10, 7: 9}, + 'h': {1: 994, 2: 1041, 3: 70, 4: 44, 5: 10}} +EXPECTED_568_DATA = {1: 718, 2: 74, 3: 60, 4: 92, 5: 42, 6: 28} + + +def add(*ds): + c = Counter() + for d in ds: + for r, z in d.items(): + c[r] += z + return c + + +def mul(d, n): + return {r: z * n for r, z in d.items()} + + +def skeleton(s, h, v, T, cst): + a, K = h - 1, (s - 1) // 2 + idle_r, idle_cap = Counter(), Counter() + for r in idle_slots(K, a): + idle_r[r] += 2 * v * T + cap = max(r, h) + idle_cap[Fr(cap)] += Fr(2 * r * v * T, cap) + return {a: 2 * v * s * T}, {h: Fr(s * T * cst, h)}, idle_r, idle_cap + + +def roots(name, cases, m, D): + out = {} + for key, p in cases.items(): + lo, hi = root_bracket(dict(p), m, D, hi=Fr(1, 50)) + out[key] = float(hi) + masses = {key: sum(r * z for r, z in p.items()) for key, p in cases.items()} + hosted = sum(r * z for r, z in cases['D'].items()) - sum(r * z for r, z in cases['C'].items()) + ok = (all(abs(out[k] / EXPECTED[name][k] - 1) < 1.2e-4 for k in out) # 5 significant digits + and masses['A'] == masses['B'] == masses['C'] == masses['E'] + and masses['D'] == masses['E'] + hosted) + check('A4.gap.' + name, ok, ' '.join('%s %.4e' % (k, out[k]) for k in out) + ' (rank mass %s)' % {k: int(v) for k, v in masses.items()}) + lnAE = np.log(out['A'] / out['E']) + shares = {'literal': np.log(out['A'] / out['B']), 'fragmentation': np.log(out['B'] / out['C']), + 'helpers': np.log(out['C'] / out['D']), 'hosting': np.log(out['D'] / out['E'])} + print(' log shares of ln(A/E) = %.3f: ' % lnAE + ', '.join('%s %.0f%%' % (k, 100 * v / lnAE) for k, v in shares.items())) + return out + + +# ---- #555 (bit, s = 9, v = 111, cst = 63, T = 32, h = 8, m = 64) +s, h, v, T, m = 9, 8, 111, 32, 64 +D = T * ((s - 1) * v - s * 63) +e555 = load_json(VENDOR / 'pr555' / 'EXPECTED.json') +w = load_json(VENDOR / 'pr555' / 'bitE8mut-p111.json.gz') +lines = np.array(w['lines'], float) +dims = [int(np.linalg.matrix_rank(lines[F])) if F else 0 for F in w['frames']] +cur = list(w['start']) +runs = defaultdict(list) +for ph in 'DABC': + for f, dst, srcs in w[ph]: + for r in [dst] + list(srcs): + if cur[r] != f: + runs[r].append(abs(dims[f] - dims[cur[r]])) + cur[r] = f +for r in range(len(cur)): + if cur[r] != w['final'][r]: + runs[r].append(abs(dims[w['final'][r]] - dims[cur[r]])) +cls = lambda r: 'x' if r < v else ('y' if r < 2 * v else 'h') +H = {c: Counter() for c in 'xyh'} +for r, L in runs.items(): + for d in L: + H[cls(r)][d] += 1 +check('A4.runs.#555', all(dict(H[c]) == EXPECTED_555_RUNS[c] for c in 'xyh') + and sum(r * z for r, z in H['h'].items()) == 8 * w['R'], + 'per-stage runs x %s, y %s, helpers %s (helper mass 8R = %d)' % (dict(sorted(H['x'].items())), + dict(sorted(H['y'].items())), + dict(sorted(H['h'].items())), 8 * w['R'])) +S = s * T +local = add(H['x'], H['y'], H['h'], {7: 9}) +check('A4.local.#555', dict(local) == {int(k): z for k, z in e555['word']['local_histogram'].items()}, + 'replayed runs + 9 copy children of rank 7 = the published per-stage local histogram') +real = {int(r): z for r, z in e555['nine']['profile'].items()} +rem = Counter(real) +for r, z in mul(local, S).items(): + rem[r] -= z +rem = {r: z for r, z in rem.items() if z} +data1, cop, idle_r, idle_cap = skeleton(s, h, v, T, 63) +datareal = mul(add(H['x'], H['y']), S) +helpers = mul(H['h'], S) +cases = {'A': add(data1, cop, idle_cap), 'B': add(data1, cop, idle_r), 'C': add(datareal, {7: 9 * S}, idle_r), + 'D': add(datareal, {7: 9 * S}, idle_r, helpers), 'E': add(datareal, {7: 9 * S}, helpers, rem)} +hosted = sum(r * z for r, z in helpers.items()) +idlemass = sum(r * z for r, z in idle_r.items()) +check('A4.hosted.#555', hosted == 288 * 3512 and idlemass == 1342656, + 'hosted helper mass %d = 75.3%% of the skeleton idle mass %d; paid idle remainder %s' % (hosted, idlemass, rem)) +roots('#555', cases, m, D) + +# ---- #568 (complex, s = 9, v = 112, cst = 64, T = 8, h = 9, m = 73) +s, h, v, T, m = 9, 9, 112, 8, 73 +D = T * ((s - 1) * v - s * 64) +S = s * T +sys.path.insert(0, str(main_file('research/direct-delivery504-global/vendor/gk/gk_word.py').parent)) +import gk_common as co # noqa: E402 (#531's word helpers on main) +import gk_word as g # noqa: E402 +g.V = co.V = 112 +co.DATA = g.DATA = 7168 +word = load_json(VENDOR / 'pr569' / 'fourcold-eight-FULL-WORD.json.gz') +V = 112 +cur = {r: ((word['ports'][r],) if r < V else ()) for r in range(2 * V)} +paid = Counter() + + +def climb(r, F): + if r >= 2 * V: + return + F = g.basis(F) + o = cur[r] + assert g.basis(list(o) + list(F)) == F, 'frame violation' + if o != F: + paid[len(F) - len(o)] += 1 + cur[r] = F + + +for seq in (word['A'], word['B']): + for e in seq: + for r in [e[1]] + ([e[2]] if e[0] == 'add' else []): + climb(r, e[-1]) +for r in range(2 * V): + climb(r, g.FULL if r < V else g.perp(word['ports'][r - V])) +check('A4.data.#568', dict(paid) == EXPECTED_568_DATA and sum(r * z for r, z in paid.items()) == 2 * 112 * 8, + 'data-register runs per call %s (mass 2 v a = 1792)' % dict(sorted(paid.items()))) +p568 = load_json(VENDOR / 'pr568' / 'PLAN.json.gz') +real = {int(r): z for r, z in p568['profile'].items()} +inp = load_json(DATA / 'ceiling' / 'gap568-inputs.json') +idle_rem = {int(r): z for r, z in inp['idle_remainder'].items()} +datareal = mul(dict(paid), S) +cent = {8: 8 * S} +hel = Counter(real) +for r, z in add(datareal, cent, idle_rem).items(): + hel[r] -= z +check('A4.inputs.#568', sum(idle_rem.values()) == 4018 and all(z >= 0 for z in hel.values()) and max(r for r, z in hel.items() if z) <= 6, + 'recorded idle remainder has 4018 children (= the "4,018 positive idle remainders" of #568\'s README); implied helper ' + 'histogram %s is nonnegative with ranks <= 6 <= h' % dict(sorted((r, z) for r, z in hel.items() if z))) +hel = {r: z for r, z in hel.items() if z} +data1, cop, idle_r, idle_cap = skeleton(s, h, v, T, 64) +cases = {'A': add(data1, cop, idle_cap), 'B': add(data1, cop, idle_r), 'C': add(datareal, cent, idle_r), + 'D': add(datareal, cent, idle_r, hel), 'E': add(datareal, cent, hel, idle_rem)} +roots('#568', cases, m, D) +finish() diff --git a/research/format-limits/scripts/a5_scope_multipliers.py b/research/format-limits/scripts/a5_scope_multipliers.py new file mode 100644 index 0000000000..e45f8882ec --- /dev/null +++ b/research/format-limits/scripts/a5_scope_multipliers.py @@ -0,0 +1,53 @@ +"""A. Format ceiling, rev. 2: how much each scope assumption is worth (ceiling multipliers if it is relaxed). + +Each variant of skel.profile drops one rule of the scope and recomputes the certified root at s = 3, 5, ..., 13: + copyfree copy charge x -> 0 (non-star totals with no pairing-rank floor; star scope broken); + idlefree the B_K idle frame changes cost nothing; + idle_onechild all idle frame changes of one copy batched into one child (cross-stretch batching); + nosplit bridges moved off the idle stretches (no split pre-stretch); + loc_h data local climbs batched up to the window h (cross-register batching inside a stage); + idlefree_loch idle free and local batching to h at once; + window w-1 a family whose stage window is one smaller at the same copy ratio x. +Multiplier = (best-s root of the variant) / (best-s root of the theorem), and the same at s = 9. +These are the multipliers quoted in the rule table of README section B. +""" +from fractions import Fraction as Fr + +from report import check, finish, near +from skel import X + +S_LIST = (3, 5, 7, 9, 11, 13) +UNITS = {'bit-111/63': (8, 63, 111), 'cx-112/64': (9, 64, 112)} +VARIANTS = ('copyfree', 'idlefree', 'idle_onechild', 'nosplit', 'loc_h', 'idlefree_loch', 'window-1') +# (best-s multiplier, s = 9 multiplier), two decimals +EXPECTED = { + 'bit-111/63': {'copyfree': (6.77, 2.79), 'idlefree': (1.67, 2.14), 'idle_onechild': (1.19, 1.55), + 'nosplit': (1.15, 1.18), 'loc_h': (1.12, 1.03), 'idlefree_loch': (1.79, 2.28), + 'window-1': (1.16, 1.16)}, + 'cx-112/64': {'copyfree': (6.91, 2.83), 'idlefree': (1.68, 2.15), 'idle_onechild': (1.20, 1.55), + 'nosplit': (1.15, 1.18), 'loc_h': (1.08, 1.02), 'idlefree_loch': (1.79, 2.27), + 'window-1': (1.14, 1.14)}, +} + + +def roots(h, x, variant): + out = {} + for s in S_LIST: + r = X(s, h, 1, x, variant) + out[s] = r['hi'] if r else Fr(0) + return out + + +for name, (h, cst, v) in UNITS.items(): + x = Fr(cst, v) + base = roots(h, x, 'thm') + b_best = max(base.values()) + for var in VARIANTS: + rr = roots(h - 1, x, 'thm') if var == 'window-1' else roots(h, x, var) + best = max(rr.values()) + sb = max(rr, key=rr.get) + mult = (float(best / b_best), float(rr[9] / base[9])) + exp = EXPECTED[name][var] + check('A5.%s.%s' % (name, var), near(mult[0], exp[0], 2) and near(mult[1], exp[1], 2), + 'best %.4e (s = %d): x%.2f; s = 9: x%.2f' % (best, sb, mult[0], mult[1])) +finish() diff --git a/research/format-limits/scripts/b_census_anchors.py b/research/format-limits/scripts/b_census_anchors.py new file mode 100644 index 0000000000..2d63106ee5 --- /dev/null +++ b/research/format-limits/scripts/b_census_anchors.py @@ -0,0 +1,57 @@ +"""B. Spec versus convention census: every file:line anchor of the rule table (README section B.2) is checked here. + +data/census/anchors.json lists, per table row, (path, line, needle), with line numbers as of the base commit 7dfa22b. +The needle must occur within two lines of the cited line (paths relative to the repository root; the upstream paper is +upstream/build/sections). Files under docs/research/ (the hub's ledgers and reviews, which main rewrites often) are +matched by their text anywhere in the file, and the line where it now sits is printed. The line ranges cited in the +prose of README sections B.1 and B.3 are not in this list. +The classification of each rule (spec / proved / convention) is argued in the README; this script only checks that +the cited text says what the table quotes, plus four corrections that are statements about the repository itself. +""" +import json +import re + +from report import DATA, REPO, check, finish + +WINDOW = 2 +anchors = json.loads((DATA / 'census' / 'anchors.json').read_text()) +by_row = {} +for a in anchors: + lines = (REPO / a['path']).read_text(encoding='utf-8').split('\n') + if a['path'].startswith('docs/research/'): + hits = [i + 1 for i, ln in enumerate(lines) if a['needle'] in ln] + ok = bool(hits) + where = '%s:%d (7dfa22b), text now at %s' % (a['path'], a['line'], ','.join(map(str, hits)) or '-') + else: + lo, hi = max(0, a['line'] - 1 - WINDOW), min(len(lines), a['line'] + WINDOW) + ok = any(a['needle'] in lines[i] for i in range(lo, hi)) + where = '%s:%d' % (a['path'], a['line']) + by_row.setdefault(a['row'], []).append((ok, where)) +for row in sorted(by_row): + res = by_row[row] + check('B.row%02d' % row, all(ok for ok, _ in res), + '%d anchors: %s' % (len(res), ', '.join(loc + ('' if ok else ' MISSING') for ok, loc in res))) + +# Correction 1: in the bit legality checker, the nested-and-priced MOVE rule, the common-frame ADD rule and the COPY +# lifecycle are all on line 11; line 10 holds the containment helper and the owner/helper selection. +L = (REPO / 'research/e8-bit-carrier-skeleton/code/bit/checkers/legality_h.cpp').read_text().split('\n') +check('B.corr.legality-line11', + all(t in L[10] for t in ('illegal or mispriced MOVE', 'ADD not in common frame', 'invalid COPY lifecycle')) + and 'owners' in L[9] and 'illegal or mispriced MOVE' not in L[9], + 'MOVE / ADD / COPY rules on legality_h.cpp:11; owner selection on :10') +# Correction 2: the invocation invariant Inv used by the complex five-stage bridge is imported, not defined, in main. +lean = [p for p in REPO.rglob('*.lean') if '.git' not in p.parts] +defs = [p for p in lean if re.search(r'^\s*(structure|def|class|abbrev|inductive)\s+G?Inv\b', p.read_text(errors='ignore'), re.M)] +imps = [p for p in lean if 'import Work.Bridge.Inv' in p.read_text(errors='ignore')] +check('B.corr.inv-not-defined', not defs and len(imps) >= 1, + '%d Lean files import Work.Bridge.Inv; no Lean file of main defines Inv or GInv' % len(imps)) +# Correction 3: PR #370's assertion 'x registers are never destinations' is sufficient, not necessary (#425, #493). +R = (REPO / 'research/e8-bit-carrier-skeleton/README.md').read_text() +check('B.corr.x-destinations', '"x registers are never destinations"' in R and 'sufficient condition, not a necessary one' in R, + "#493's README records the #370 assertion as sufficient, not necessary (#425's scalar-interface lemma)") +# Correction 4: the maintainer's review lists whole-call hosting and normalized wrappers as interface assumptions and +# says the fixed-word ceiling discussions were not independently certified. +D = (REPO / 'docs/research/community-pr531-review.md').read_text() +check('B.corr.scope-note', 'whole-call correlated-helper hosting' in D and 'independently certified** in this integration' in D, + 'docs/research/community-pr531-review.md, "Scope and research notes"') +finish() diff --git a/research/format-limits/scripts/c1_sandwich_toy.py b/research/format-limits/scripts/c1_sandwich_toy.py new file mode 100644 index 0000000000..97e8a67a23 --- /dev/null +++ b/research/format-limits/scripts/c1_sandwich_toy.py @@ -0,0 +1,237 @@ +"""Exact toy: a source read at its own frame, sandwiched between two non-nested frame steps (n = 4 labels over F2). + +Setting. Labels live in F2^4 with the standard dot product. A port anchor u_a = 0111 is odd (u_a.u_a = 1). Three +reader labels u1 = 1000, u2 = 1011, u3 = 1101 are odd and orthogonal to u_a; they span u_a^perp, so the only subspace +orthogonal to all three readers is : the only frame that is common to the readers' natural read frames is the +point station (asserted below). One source x has label with w not orthogonal to any reader (w.u_i = 1), +so every reader must see x across a drop. + +Two networks compute the SAME linear operator on the registers (x, y1, y2, y3): + x -> T_FULL l_x , y_i -> T_{u_i^perp} ( l_{y_i} + q_i l_x ) , q = (1, -1, 1/2), +where l is the logical content, T_F is the canonical Clifford frame operator of a subspace F, and the physical +registers hold x = T_ l_x and y_i = l_{y_i}. + + standard : one shared copy of x is dropped -> 0 (the shared station), each reader reads it at frame 0 and then + climbs 0 -> u_i^perp (nested). Charged steps: copy -> 0 ; y_i : 0 -> u_i^perp ; x : -> FULL. + relaxed : no copy. Each reader climbs 0 -> (a frame that contains a vector w outside u_i^perp), reads x at x's + own frame , then takes a NON-nested step -> u_i^perp. Charged steps: y_i : 0 -> and + -> u_i^perp ; x : -> FULL. + +Checks. + * The operator is exact on all 4 * 16 = 64 basis columns of the 4 registers (exact Gaussian-dyadic arithmetic). + * For every transition A -> B the Clifford child rank (clifford_exact.lower_child of T_A^-1 then T_B) equals the + frame distance d(A, B) = dim A + dim B - 2 dim (A cap B), in both networks, including the non-nested steps. + * Charged rank total: standard 13 (of which 1 is the copy), relaxed 18 = 13 + 3*2 - 1. +""" +import functools +import sys +from fractions import Fraction as Fr + +from report import check, finish, main_file + +sys.path.insert(0, str(main_file('research/direct-delivery504-global/vendor/clifford/clifford_exact.py').parent)) +import clifford_exact as ce # noqa: E402 (the repository's exact Clifford compiler, unmodified) + +# ---------------------------------------------------------------------------------------------------------------- +# Expected values (from the exact run of the toy; every one is re-derived below and compared). +EXPECTED = { + 'w_candidates': [0b1000], # odd w with w.u_i = 1 for all three readers: unique + 'common_reader_frame': [0, 0b0111], # {z : z.u_i = 0 for all i} = {0, u_a}: the point station + 'columns': 64, # 4 registers x 16 basis vectors, per network + 'std_total': 13, 'std_copy': 1, # standard network: charged rank total, copy part + 'relaxed_total': 18, 'relaxed_copy': 0, # relaxed network: 13 + 3*2 - 1 = 18 + # transitions (register, dim A, dim B, child rank, distance d) + 'std_transitions': [('copy', 1, 0, 1, 1), ('y0', 0, 3, 3, 3), ('y1', 0, 3, 3, 3), ('y2', 0, 3, 3, 3), + ('x', 1, 4, 3, 3)], + 'relaxed_transitions': [('y0', 0, 1, 1, 1), ('y0', 1, 3, 4, 4), ('y1', 0, 1, 1, 1), ('y1', 1, 3, 4, 4), + ('y2', 0, 1, 1, 1), ('y2', 1, 3, 4, 4), ('x', 1, 4, 3, 3)], +} + +n = 4 +N = 1 << n + + +def par(x): + return bin(x).count('1') & 1 + + +def span(vs): + out = {0} + for v in vs: + out |= {o ^ v for o in out} + return out + + +def perp(vs): + return [z for z in range(N) if all(par(z & v) == 0 for v in vs)] + + +def basis(vs): + b = [] + for v in vs: + if ce.rank(b + [v]) > len(b): + b.append(v) + return b + + +def dist(A, B): + """frame distance d(A,B) = dim A + dim B - 2 dim(A cap B).""" + a, b = basis(A), basis(B) + return len(a) + len(b) - 2 * (len(a) + len(b) - ce.rank(a + b)) + + +def T(F): + return ce.canonical_frame(n, tuple(basis(F))) + + +# exact complex dyadic linear algebra: a number is a pair (re, im) of Fractions +def mat(op): + cols = [] + for bidx in range(N): + vec, den = op.zero_state(bidx) + cols.append([(Fr(a, 1 << den), Fr(c, 1 << den)) for a, c in vec]) + return [[cols[j][i] for j in range(N)] for i in range(N)] + + +def cm(a, b): + return (a[0] * b[0] - a[1] * b[1], a[0] * b[1] + a[1] * b[0]) + + +def ca(a, b): + return (a[0] + b[0], a[1] + b[1]) + + +Z = (Fr(0), Fr(0)) + + +def mv(M, v): + return [functools.reduce(ca, [cm(M[i][j], v[j]) for j in range(N)], Z) for i in range(N)] + + +def sc(q, v): + return [(q * a, q * b) for a, b in v] + + +def add(u, v): + return [ca(a, b) for a, b in zip(u, v)] + + +cache = {} + + +def Tm(F): + k = tuple(sorted(span(F))) + if k not in cache: + cache[k] = (mat(T(F)), mat(T(F).adjoint())) + return cache[k] + + +def step(h, A, B, log, who): + """apply T_B T_A^-1 to the physical vector h and record (register, dim A, dim B, child rank, distance).""" + op = T(A).adjoint().then(T(B)) if basis(A) else T(B) + r = ce.lower_child(op)[0]['rank'] + dd = dist(A, B) + log.append((who, len(basis(A)), len(basis(B)), r, dd)) + return mv(Tm(B)[0], mv(Tm(A)[1], h)) + + +ua = 0b0111 +U = [0b1000, 0b1011, 0b1101] +q = [Fr(1), Fr(-1), Fr(1, 2)] + +# ---- C1.c0-station: the readers' labels span u_a^perp, hence the only common reader frame is +labels_ok = par(ua & ua) == 1 and all(par(u & u) == 1 and par(u & ua) == 0 for u in U) +spans_perp = span(U) == set(perp([ua])) and ce.rank(U) == n - 1 +common = sorted(perp(U)) +cands = [w for w in range(1, N) if par(w & w) == 1 and all(par(w & u) == 1 for u in U)] +check('C1.c0-station', + labels_ok and spans_perp and common == EXPECTED['common_reader_frame'] and cands == EXPECTED['w_candidates'], + 'readers odd and orthogonal to u_a; span(u1,u2,u3) = u_a^perp (dim %d); frames orthogonal to all readers = %s; ' + 'source label w = %s (unique odd w with w.u_i = 1 for all i)' + % (ce.rank(U), [format(z, '04b') for z in common], [format(c, '04b') for c in cands])) +w = EXPECTED['w_candidates'][0] +FULL = list(range(1, N)) +W = [w] + + +def run(mode, hx, hy): + """hx: physical source (frame ); hy: physical targets (frame 0). Returns final x, final ys, transition log.""" + log = [] + ys = list(hy) + if mode == 'standard': + C = list(hx) # copy of x taken at its own frame + C = step(C, W, [], log, 'copy') # shared station: -> 0 + for i in range(3): + ys[i] = add(ys[i], sc(q[i], C)) # read at frame 0 + ys[i] = step(ys[i], [], perp([U[i]]), log, 'y%d' % i) # nested climb 0 -> u_i^perp + x = step(hx, W, FULL, log, 'x') + else: + for i in range(3): + ys[i] = step(ys[i], [], W, log, 'y%d' % i) # 0 -> : frame containing a vector outside u_i^perp + ys[i] = add(ys[i], sc(q[i], hx)) # read x at x's own frame, no copy + ys[i] = step(ys[i], W, perp([U[i]]), log, 'y%d' % i) # non-nested step -> u_i^perp + x = step(hx, W, FULL, log, 'x') + return x, ys, log + + +def expect(lx, ly): + ex = mv(Tm(FULL)[0], lx) + ey = [mv(Tm(perp([U[i]]))[0], add(ly[i], sc(q[i], lx))) for i in range(3)] + return ex, ey + + +zero = [Z] * N + + +def e(b): + v = [Z] * N + v[b] = (Fr(1), Fr(0)) + return v + + +results = {} +for mode in ('standard', 'relaxed'): + good = 0 + logs = [] + for reg in range(4): + for b in range(N): + l = [zero] * 4 + l[reg] = e(b) # logical input: one basis vector of one register + hx = mv(Tm(W)[0], l[0]) # physical source = T_ l_x + hy = [l[1], l[2], l[3]] # physical targets start at frame 0 + x, ys, log = run(mode, hx, hy) + ex, ey = expect(l[0], l[1:]) + good += (x == ex and ys == ey) + logs.append(log) + assert all(lg == logs[0] for lg in logs) # the transition costs do not depend on the input column + log = logs[0] + total = sum(r for *_, r, _ in log) + copy = sum(r for who, *_, r, _ in log if who == 'copy') + results[mode] = dict(cols=good, log=log, total=total, copy=copy) + +std, rel = results['standard'], results['relaxed'] + +check('C1.std-exact', + std['cols'] == EXPECTED['columns'] and std['total'] == EXPECTED['std_total'] + and std['copy'] == EXPECTED['std_copy'] and std['log'] == EXPECTED['std_transitions'], + 'standard network exact on %d/%d columns; charged rank %d (copy part %d)' + % (std['cols'], EXPECTED['columns'], std['total'], std['copy'])) + +check('C1.relaxed-exact', + rel['cols'] == EXPECTED['columns'] and rel['total'] == EXPECTED['relaxed_total'] + and rel['copy'] == EXPECTED['relaxed_copy'] and rel['log'] == EXPECTED['relaxed_transitions'] + and rel['total'] == std['total'] + 3 * 2 - 1, + 'relaxed network exact on %d/%d columns; charged rank %d = %d + 3*2 - 1 (copy part %d)' + % (rel['cols'], EXPECTED['columns'], rel['total'], std['total'], rel['copy'])) + + +# the relaxed network's final reader steps -> u_i^perp (dim 1 -> 3) are not nested: w is not orthogonal to u_i +nonnested_ok = all(w not in perp([u]) for u in U) +n_nonnested = sum(1 for who, a, b, r, dd in rel['log'] if who != 'x' and (a, b) == (1, 3)) +all_eq = all(r == dd for m in results.values() for _, _, _, r, dd in m['log']) +n_steps = sum(len(m['log']) for m in results.values()) +check('C1.child-eq-d', all_eq and nonnested_ok and n_nonnested == 3, + 'lower_child rank == d(A,B) on all %d transitions of both networks (including %d non-nested steps -> u_i^perp, ' + 'rank 4 = d)' % (n_steps, n_nonnested)) + +finish() diff --git a/research/format-limits/scripts/c2_port_gauge.py b/research/format-limits/scripts/c2_port_gauge.py new file mode 100644 index 0000000000..31c27d32cc --- /dev/null +++ b/research/format-limits/scripts/c2_port_gauge.py @@ -0,0 +1,227 @@ +"""Exact checks of the port-gauge rank calculus: C_q gates, frame detours and route rigidity (over F2^n). + +Notation. Labels are vectors of F2^n with the standard dot product; q is an ODD vector (q.q = 1). C_a denotes the +single-axis Clifford gate cgate(n, a) and Z a product of such gates. T_F is the canonical Clifford frame operator of +a subspace F, with T_0 = identity and T_FULL = the Fourier transform F on all n axes. The frame distance is +d(F, G) = dim F + dim G - 2 dim(F cap G). The Clifford rank of an operator is the rank reported by +clifford_exact.lower_child (the rank of the Fourier part of its normal form). + +A. Cost instrument. For a product Z = C_{q_1}^{s_1} ... C_{q_k}^{s_k} (s_i = +-1) let B = sum_i q_i q_i^T over F2. + Claim: rank_{F2}(B) equals the exact Clifford rank of Z (240 random products, n = 4..7, seeded). +B. Detour theorem, exhaustive over all subspaces G of F2^n (n = 3..6), with q odd, L = FULL, q^perp the hyperplane: + Y family 0 -> G -> q^perp : extra cost d(0,G) + d(G,q^perp) - d(0,q^perp) is 0 iff G <= q^perp, else exactly 2; + X family -> G -> L : extra cost d(,G) + d(G,L) - d(,L) is 0 iff q in G, else exactly 2. +C. Route rigidity (exact, n = 3, 4, exhaustive over all pairs of subspaces). For frames f_X, f_Y the route + R = T_{f_Y} T_{f_X}^{-1} is compared with F (matrix products, R acting after T_{f_X}^{-1}): the right mismatch rank is + rank(F^{-1} R) (zero iff R = F M with M monomial) and the left mismatch rank is rank(R F^{-1}) (zero iff R = M F), + M a monomial operator (permutation x diagonal x translation). Claim: R equals F modulo a monomial on at least one + side only for pairs with dim f_X + dim f_Y = n and f_X cap f_Y = 0 (a necessary condition: the pairs where it + holds are a proper subset of these complementary pairs), and the number of such pairs by (dim f_X, dim f_Y) is + as logged below. Mismatch ranks are also given for the boundary pairs of a port with label q. +D. Gauge descent. If q lies in span(axes of Z) with odd support (q = sum of an odd subset of the axes of + Z = C^{(x)k}) then multiplying by C_q lowers the rank by exactly one, T_E C_q^{-1} = T_{E cap q^perp}; + if q is outside span(axes) and orthogonal to it the rank rises by exactly one. +""" +import collections +import random +import sys + +from report import check, finish, main_file + +sys.path.insert(0, str(main_file('research/direct-delivery504-global/vendor/clifford/clifford_exact.py').parent)) +import clifford_exact as ce # noqa: E402 (the repository's exact Clifford compiler, unmodified) +from clifford_exact import rank, parity, cgate, ident, canonical_frame, lower_child, fourier # noqa: E402 + +# ---------------------------------------------------------------------------------------------------------------- +# Expected values (from the exact run; each is re-derived below and compared). +EXPECTED = { + # A: number of random products tested and number of mismatches between rank(B) and the exact Clifford rank + 'instrument': dict(products=240, mismatches=0), + # B: per n: number of subspaces of F2^n, number of odd q tested (the first ones in increasing order; all odd q + # for n <= 5, the first 10 for n = 6), and the histogram {(family, G on the geodesic?, extra cost): count} + 'detour': { + 3: dict(subspaces=16, qs=4, geo=20, off=44), + 4: dict(subspaces=67, qs=8, geo=128, off=408), + 5: dict(subspaces=374, qs=16, geo=1072, off=4912), + 6: dict(subspaces=2825, qs=10, geo=3740, off=24510), + }, + # C: mismatch ranks (right, left) for q = 1 and the number of pairs with route == F on a side, by + # (dim f_X, dim f_Y, dim f_X cap f_Y); 'sides' = how many of those pairs are monomial-equal to F on both sides / + # only on the left (R = M F) / only on the right (R = F M); 'complementary' = number of all pairs with + # dim f_X + dim f_Y = n and f_X cap f_Y = 0 (a superset of the rigid pairs); both are extra details of the run + 'route': { + 3: dict(sides=dict(both=8, left=8, right=8), complementary=58, + mism={',q^perp': (0, 0), ',L': (1, 1), '0,L': (0, 0), '0,q^perp': (1, 1), 'L,q^perp': (2, 2)}, + rigid={(0, 3, 0): 1, (1, 2, 0): 11, (2, 1, 0): 11, (3, 0, 0): 1}), + 4: dict(sides=dict(both=16, left=51, right=51), complementary=802, + mism={',q^perp': (0, 0), ',L': (1, 1), '0,L': (0, 0), '0,q^perp': (1, 1), 'L,q^perp': (3, 3)}, + rigid={(0, 4, 0): 1, (1, 3, 0): 26, (2, 2, 0): 64, (3, 1, 0): 26, (4, 0, 0): 1}), + }, + # D: n = 7, Z = C^{(x)k}, q = sum of the first sz axes (sz odd, sz <= k): (k, sz) -> (rank Z, rank C_q Z) + 'descent': {(3, 1): (3, 2), (3, 3): (3, 2), (5, 1): (5, 4), (5, 3): (5, 4), (5, 5): (5, 4), + (7, 1): (7, 6), (7, 3): (7, 6), (7, 5): (7, 6), (7, 7): (7, 6)}, + # D: Z = C^{(x)3} on axes e0,e1,e2 and q = e5 (outside and orthogonal): rank 3 -> 4 + 'outside': (3, 4), +} + +# ---- A: the F2 cost instrument --------------------------------------------------------------------------------- + + +def brank(terms, n): + """rank over F2 of B = sum_i q_i q_i^T (row j of B is the xor of the q_i whose bit j is set).""" + B = [0] * n + for q, _s in terms: + for j in range(n): + if q >> j & 1: + B[j] ^= q + return rank(B) + + +rng = random.Random(14) +bad = 0 +tot = 0 +for n in (4, 5, 6, 7): + for _ in range(60): + k = rng.randrange(1, 8) + terms = [(rng.randrange(1, 1 << n), rng.choice((-1, 1))) for _ in range(k)] + op = ident(n) + for q, s in terms: + op = op.then(cgate(n, q, s)) + r_ex = lower_child(op)[0]['rank'] + r_b = brank(terms, n) + tot += 1 + bad += (r_ex != r_b) +check('C2.instrument', (tot, bad) == (EXPECTED['instrument']['products'], EXPECTED['instrument']['mismatches']), + 'rank_F2(sum q q^T) vs exact Clifford child rank: %d random C-products, n=4..7, mismatches = %d' % (tot, bad)) + + +# ---- B: detour theorem ----------------------------------------------------------------------------------------- +def subspaces(n): + """all subspaces of F2^n, as frozensets of vectors (breadth-first closure under adding one vector).""" + vecs = range(1, 1 << n) + layer = {frozenset({0})} + seen = {frozenset({0})} + while layer: + nxt = set() + for S in layer: + for v in vecs: + if v not in S: + T = frozenset(S | {x ^ v for x in S}) + if T not in seen: + seen.add(T) + nxt.add(T) + layer = nxt + return list(seen) + + +def dim(S): + return len(S).bit_length() - 1 + + +def dd(f, g): + return dim(f) + dim(g) - 2 * dim(f & g) + + +for n in (3, 4, 5, 6): + subs = subspaces(n) + full = frozenset(range(1 << n)) + qs = [q for q in range(1, 1 << n) if parity(q)] + qsel = qs if n <= 5 else qs[:10] + counts = collections.Counter() + theorem = True + for q in qsel: + perp = frozenset(x for x in range(1 << n) if parity(x & q) == 0) + zero = frozenset({0}) + line = frozenset({0, q}) + for G in subs: + ex_y = dd(zero, G) + dd(G, perp) - dd(zero, perp) + ex_x = dd(line, G) + dd(G, full) - dd(line, full) + geo_y = G <= perp + geo_x = q in G + counts[('Y', geo_y, ex_y)] += 1 + counts[('X', geo_x, ex_x)] += 1 + theorem &= (ex_y == (0 if geo_y else 2)) and (ex_x == (0 if geo_x else 2)) + e = EXPECTED['detour'][n] + want = {('Y', True, 0): e['geo'], ('Y', False, 2): e['off'], ('X', True, 0): e['geo'], ('X', False, 2): e['off']} + ok = theorem and dict(counts) == want and len(subs) == e['subspaces'] and len(qsel) == e['qs'] + check('C2.detour-n%d' % n, ok, + '%d subspaces x %d odd q: extra cost of a detour via G is 0 on the geodesic set (%d per family) and exactly 2 ' + 'off it (%d per family) for Y: 0->G->q^perp (G <= q^perp) and X: ->G->L (q in G)' + % (len(subs), len(qsel), counts[('Y', True, 0)], counts[('Y', False, 2)])) + + +# ---- C: route rigidity ----------------------------------------------------------------------------------------- +def frame_op(n, S): + b = [] + for v in sorted(S): + if v and rank(b + [v]) > len(b): + b.append(v) + return canonical_frame(n, tuple(b)) + + +for n in (3, 4): + subs = subspaces(n) + full = frozenset(range(1 << n)) + zero = frozenset({0}) + F = fourier(n) + Fi = F.adjoint() + ops = {S: frame_op(n, S) for S in subs} + q = next(x for x in range(1, 1 << n) if parity(x)) + perp = frozenset(x for x in range(1 << n) if parity(x & q) == 0) + line = frozenset({0, q}) + + def mism(fx, fy): + R = ops[fx].adjoint().then(ops[fy]) + return lower_child(R.then(Fi))[0]['rank'], lower_child(Fi.then(R))[0]['rank'] + + got_mism = {',q^perp': mism(line, perp), ',L': mism(line, full), '0,L': mism(zero, full), + '0,q^perp': mism(zero, perp), 'L,q^perp': mism(full, perp)} + rigid = collections.Counter() + rigid_pairs = set() + sides = collections.Counter() + for fx in subs: + for fy in subs: + a, b = mism(fx, fy) # (right, left) mismatch ranks + if a == 0 or b == 0: + rigid[(dim(fx), dim(fy), dim(fx & fy))] += 1 + rigid_pairs.add((fx, fy)) + sides['both' if a == 0 and b == 0 else 'right' if a == 0 else 'left'] += 1 + # necessary condition: dims sum to n and the frames meet only in 0 + complementary = {(fx, fy) for fx in subs for fy in subs if dim(fx) + dim(fy) == n and dim(fx & fy) == 0} + e = EXPECTED['route'][n] + ok = (got_mism == e['mism'] and dict(rigid) == e['rigid'] and rigid_pairs <= complementary + and len(complementary) == e['complementary'] and dict(sides) == e['sides']) + check('C2.route-n%d' % n, ok, + 'q=%d: route == F modulo monomials on a side for %d pairs, all with dim fX + dim fY = %d and fX cap fY = 0 ' + '(of %d such pairs; by (dim fX, dim fY): %s; monomial-equal on both sides / only left / only right: %d/%d/%d); ' + 'mismatch ranks (right,left): (,q^perp)=%s (,L)=%s (0,L)=%s (0,q^perp)=%s (L,q^perp)=%s' + % (q, len(rigid_pairs), n, len(complementary), dict(sorted((k[:2], v) for k, v in rigid.items())), + sides['both'], sides['left'], sides['right'], got_mism[',q^perp'], + got_mism[',L'], got_mism['0,L'], got_mism['0,q^perp'], got_mism['L,q^perp'])) + +# ---- D: gauge descent ------------------------------------------------------------------------------------------ +n = 7 +descent = {} +for k in (3, 5, 7): + for sz in (1, 3, 5, 7): + if sz > k: + continue + q = sum(1 << i for i in range(sz)) # odd support: q is a sum of an odd number of the axes of Z + op = ident(n) + for a in [1 << i for i in range(k)]: + op = op.then(cgate(n, a)) + r0 = lower_child(op)[0]['rank'] + r1 = lower_child(op.then(cgate(n, q)))[0]['rank'] + descent[(k, sz)] = (r0, r1) +op = ident(n) +for a in (1, 2, 4): + op = op.then(cgate(n, a)) +outside = (lower_child(op)[0]['rank'], lower_child(op.then(cgate(n, 1 << 5)))[0]['rank']) +n_down = sum(1 for r0, r1 in descent.values() if r1 == r0 - 1) +check('C2.gauge-descent', + descent == EXPECTED['descent'] and outside == EXPECTED['outside'] and n_down == len(descent) == 9, + 'n=7, Z = C^(x)k (k=3,5,7), q = sum of an odd number of the axes: rank(C_q Z) = rank(Z) - 1 in %d/%d cases; ' + 'q = e5 outside and orthogonal to the axes e0,e1,e2: rank %d -> %d (+1)' + % (n_down, len(descent), outside[0], outside[1])) + +finish() diff --git a/research/format-limits/scripts/c3_complement_gate0.py b/research/format-limits/scripts/c3_complement_gate0.py new file mode 100644 index 0000000000..2f462d3e8e --- /dev/null +++ b/research/format-limits/scripts/c3_complement_gate0.py @@ -0,0 +1,319 @@ +"""Exact checks for complement (oblique) sinks: the sink hyperplane w^perp with w odd and w.u = 1 for a rank-1 source . + +Notation. Labels are vectors of F2^n with the standard dot product; u is odd (u.u = 1). For a subspace F, T_F is the +canonical Clifford frame operator of F (T_0 = identity, T_FULL = F = the Fourier transform on all n axes, "C^(x)n"), +and d(A, B) = dim A + dim B - 2 dim(A cap B) is the frame distance. The Clifford rank of an operator is the rank +reported by clifford_exact.lower_child (rank of the Fourier part of its normal form). A monomial operator is an +address-linear permutation times a Z4 diagonal phase times a translation times a global phase. A weight-odd vector w +is a COMPLEMENT of u when w.u = 1, i.e. u is not in w^perp, so that F2^n = (+) w^perp. + +(E) Endpoint. For every odd w with w.u = 1 the route R = T_{w^perp} T_^{-1} has Clifford rank n, and + R = Lmon . F . Rmon with Lmon, Rmon monomial (Rmon acts first): the explicit check is + Lmon^{-1} R Rmon^{-1} == F on the Clifford tableau and on every basis column (n <= 6; 6 sampled columns at n = 9). + Controls: w = u (the format's own sink u^perp) has the same property; a non-complement w (w.u = 0, so u is in + w^perp) gives rank n - 2. The wrapper class of each monomial is reported as 'id' or 'perm' (trivial or nontrivial + address map) plus '+quad' if its phase has an off-diagonal (quadratic) part: Lmon is always 'perm+quad', Rmon has + trivial address map ('id', or 'id+quad'). +(P) Port price. A target (Y) climbing 0 -> w^perp costs n - 1 = d(0, w^perp), the same as 0 -> u^perp; a source (X) + climbing -> FULL costs n - 1. A detour station G (Y: 0 -> G -> w^perp) costs +0 exactly when G <= w^perp and + exactly +2 otherwise (exhaustive over all subspaces G, n = 3, 4, 5). +(N) Newly lossless corrector. A source with label s, s.u = 1 and s.w = 0 cannot be read drop-free by the sink u^perp + (s is not in u^perp) but lies on the geodesic of the sink w^perp. Network on two registers: the target y climbs + 0 -> (read c * x there, c = 1/2) -> w^perp ; the source x climbs -> FULL. The operator is + x -> T_FULL l_x , y -> T_{w^perp}(l_y + c l_x) (exact on every basis column of x and sampled columns of y, with + exact Gaussian-dyadic arithmetic), and every step's child rank equals d(A, B) (n = 3, 4, 5). +""" +import random +import sys +from fractions import Fraction as Fr + +from report import check, finish, main_file + +sys.path.insert(0, str(main_file('research/direct-delivery504-global/vendor/clifford/clifford_exact.py').parent)) +import clifford_exact as ce # noqa: E402 (the repository's exact Clifford compiler, unmodified) + +# ---------------------------------------------------------------------------------------------------------------- +# Expected values (from the exact run; every one is re-derived below and compared). +# ENDPOINT[n]: histogram of (kind, Clifford rank, tableau equal to F, columns equal to F, Lmon class, Rmon class) over +# the odd w tested (kind 'compl': w.u = 1, 'noncompl': w.u = 0, 'u': w = u). For n <= 6 every odd w is tested; +# for n = 9 a sample of 160 vectors w (random.Random(1), same draw sequence as the run below) plus w = u is tested, so +# the counts at n = 9 (41 complements, 50 non-complements, w = u drawn twice) are properties of that seeded sample. + +def _hist(n, n_id, n_idq, n_non, n_u): + h = {('compl', n, True, True, 'perm+quad', 'id'): n_id, ('compl', n, True, True, 'perm+quad', 'id+quad'): n_idq, + ('u', n, True, True, 'perm+quad', 'id+quad'): n_u} + if n_non: + h[('noncompl', n - 2, None, None, None, None)] = n_non # control w.u = 0: rank n - 2 + return h + + +ENDPOINT = {3: _hist(3, 1, 2, 0, 1), 4: _hist(4, 1, 2, 4, 1), 5: _hist(5, 1, 6, 8, 1), 6: _hist(6, 1, 14, 16, 1), + 9: _hist(9, 1, 40, 50, 2)} +PORT_PRICE = {n: n - 1 for n in (3, 4, 5, 6, 9)} # Y 0->w^perp, Y 0->u^perp, X ->FULL all cost n - 1 +INTERVAL_SUBSPACES = {3: 16, 4: 67, 5: 374} # number of subspaces of F2^n, all with zero violations +CORRECTOR = {3: dict(s=0b010, charged=4), 4: dict(s=0b0010, charged=6), 5: dict(s=0b00010, charged=8)} # charged = 2(n-1) + + +def par(x): + return bin(x).count('1') & 1 + + +def basis(vs, n): + b = [] + for v in vs: + if ce.rank(b + [v]) > len(b): + b.append(v) + return b + + +def perp(vs, n): + return [z for z in range(1, 1 << n) if all(par(z & v) == 0 for v in vs)] + + +def hyper(w, n): + """a basis of w^perp.""" + return basis(perp([w], n), n) + + +def T(n, U): + return ce.canonical_frame(n, tuple(U)) + + +def d(A, B): + a, b = len(A), len(B) + return a + b - 2 * (a + b - ce.rank(A + B)) + + +def opstep(n, A, B): + """the operator T_B T_A^{-1} (T_A^{-1} is applied first).""" + return (T(n, A).adjoint().then(T(n, B))) if A else T(n, B) + + +def rk(op): + return ce.lower_child(op)[0]['rank'] + + +def lower_ops(op): + """clifford_exact.lower_child, but also returning the monomial operators: + op == rmon.then(fourier(n, range(r))).then(lmon) (rmon acts first); returns (r, lmon, rmon, lrec, rrec).""" + n = op.n + Bcols = [x for x, z, p in op.tab[n:]] + r = ce.rank(Bcols) + G = ce.transpose(ce.basis_extend(Bcols, n), n) + A = ce.inv(G, n) + PA = ce.perm(n, A) + part = op.then(PA) + Bcols = [x for x, z, p in part.tab[n:]] + Dcols = [z for x, z, p in part.tab[n:]] + picks = [] + sel = [] + for j, x in enumerate(Bcols): + if ce.rank(sel + [x]) > len(sel): + picks.append(j) + sel.append(x) + Br = ce.transpose(sel, r) + Bi = ce.inv(Br, r) + Dr = ce.transpose([Dcols[j] & ((1 << r) - 1) for j in picks], r) + Qs = tuple(sum(ce.parity(row & col) << j for j, col in enumerate(ce.transpose(Bi, r))) for row in Dr) + DQ = ce.diag(n, Qs + (0,) * (n - r)) + V = part.then(DQ).then(ce.hadamard(n, range(r))) + Vmon, _ = ce.monomial(V) + S = ce.diag(n, tuple(1 << i if i < r else 0 for i in range(n))) + left = S.adjoint().then(DQ.adjoint()).then(PA.adjoint()) + right = Vmon.then(S.adjoint()).then(ce.xgate(n, (1 << r) - 1)) + lmon, lrec = ce.monomial(left) + rmon, rrec = ce.monomial(right) + comp = rmon.then(ce.fourier(n, range(r))).then(lmon) + assert comp.tab == op.tab and comp.zero_state() == op.zero_state() + return r, lmon, rmon, lrec, rrec + + +def cols_equal(A, B, n, cols): + return all(A.zero_state(c) == B.zero_state(c) for c in cols) + + +def endpoint(n, u, w, ncol, rng): + U = [u] + V = hyper(w, n) + R = opstep(n, U, V) + r, lmon, rmon, lrec, rrec = lower_ops(R) + assert r == rk(R) # agrees with lower_child + out = dict(rank=r) + if r == n: + fixed = rmon.adjoint().then(R).then(lmon.adjoint()) # Lmon^{-1} R Rmon^{-1} + F = ce.fourier(n) + cols = list(range(1 << n)) if ncol is None else rng.sample(range(1 << n), ncol) + out['tab_eq'] = fixed.tab == F.tab + out['cols_eq'] = cols_equal(fixed, F, n, cols) + + def cls(rec): # is the address map trivial? is there a quadratic (off-diagonal) phase part? + Gid = tuple(rec['matrix_rows']) == tuple(1 << i for i in range(n)) + Qoff = any((rec['quadratic_rows'][i] & ~(1 << i)) for i in range(n)) + return ('perm' if not Gid else 'id') + ('+quad' if Qoff else '') + out['Lclass'] = cls(lrec) + out['Rclass'] = cls(rrec) + return out + + +def all_subspace_bases(n): + """bases of all subspaces of F2^n (closure enumeration).""" + layer = {frozenset({0})} + seen = set(layer) + while layer: + nxt = set() + for S in layer: + for v in range(1, 1 << n): + if v not in S: + t = frozenset(S | {x ^ v for x in S}) + if t not in seen: + seen.add(t) + nxt.add(t) + layer = nxt + return [basis(sorted(S), n) for S in seen] + + +def interval(n, w, Gs): + """number of violations of: Y family 0 -> G -> w^perp has excess 0 iff G <= w^perp, else exactly 2.""" + V = hyper(w, n) + bad = 0 + n_inside = 0 + for G in Gs: + ex = d([], G) + d(G, V) - d([], V) + inside = all(par(g & w) == 0 for g in G) + n_inside += inside + if ex != (0 if inside else 2): + bad += 1 + return bad, n_inside + + +def network(n, u, w, s, rng): + """Roles x (source, label , ends FULL) and y (target, 0 -> -> w^perp); gate y += c x at frame . + Expected operator: x -> T_FULL l_x ; y -> T_V (l_y + c l_x) with l = T_start^{-1} h. Exact on every basis column + of x (and 3 sampled columns of y per column of x).""" + V = hyper(w, n) + N = 1 << n + c = Fr(1, 2) + + def mat(op): # exact matrix from the columns op.zero_state(b) + cols = [] + for bi in range(N): + vec, den = op.zero_state(bi) + cols.append([(Fr(a, 1 << den), Fr(b, 1 << den)) for a, b in vec]) + return [[cols[j][i] for j in range(N)] for i in range(N)] + + def cm(a, b): + return (a[0] * b[0] - a[1] * b[1], a[0] * b[1] + a[1] * b[0]) + + def mv(M, v): + out = [] + for i in range(N): + re = im = Fr(0) + for j in range(N): + pr = cm(M[i][j], v[j]) + re += pr[0] + im += pr[1] + out.append((re, im)) + return out + + def add(a, b, k=Fr(1)): + return [(x[0] + k * y[0], x[1] + k * y[1]) for x, y in zip(a, b)] + + S = [s] + FULL = [1 << i for i in range(n)] + steps = [('y', [], S), ('x', S, FULL), ('y', S, V)] + charged = 0 + ok_rank = True + for who, A, B in steps: + r = rk(opstep(n, A, B)) + dd = d(A, B) + charged += r + ok_rank &= (r == dd) + Ty_s = mat(T(n, S)) + Ty_V_from_S = mat(opstep(n, S, V)) + Tx_full_from_S = mat(opstep(n, S, FULL)) + TSinv = mat(T(n, S).adjoint()) + TV = mat(T(n, V)) + TF = mat(T(n, FULL)) + good = True + for bx in range(N): + for by in rng.sample(range(N), 3): + hx = [(Fr(int(i == bx)), Fr(0)) for i in range(N)] # physical x stored in frame + hy = [(Fr(int(i == by)), Fr(0)) for i in range(N)] # physical y at frame 0 + y1 = mv(Ty_s, hy) # y climbs 0 -> + y1 = add(y1, hx, c) # gate at the common frame + x1 = mv(Tx_full_from_S, hx) # x climbs -> FULL + y2 = mv(Ty_V_from_S, y1) # y climbs -> w^perp + lx = mv(TSinv, hx) # expected: logical content l_x = T_^{-1} h_x + ex_x = mv(TF, lx) + ex_y = mv(TV, add(hy, lx, c)) + good &= (x1 == ex_x) and (y2 == ex_y) + return charged, ok_rank, good + + +rng = random.Random(1) +for n in (3, 4, 5, 6, 9): + u = 0b111 if n < 9 else 0b000011111 # odd weight (3 / 5) + stats = {} + ws = list(range(1, 1 << n)) + if n == 9: + ws = rng.sample(ws, 160) + [u] + for w in ws: + if not par(w): + continue # even w: w^perp contains w, frame labels would be degenerate + kind = 'u' if w == u else ('compl' if par(w & u) else 'noncompl') + e = endpoint(n, u, w, None if n <= 6 else 6, rng) + key = (kind, e['rank'], e.get('tab_eq'), e.get('cols_eq'), e.get('Lclass'), e.get('Rclass')) + stats[key] = stats.get(key, 0) + 1 + + # --- endpoint claims + compl = {k: v for k, v in stats.items() if k[0] == 'compl'} + non = {k: v for k, v in stats.items() if k[0] == 'noncompl'} + ctl_u = {k: v for k, v in stats.items() if k[0] == 'u'} + n_compl = sum(compl.values()) + exp = ENDPOINT[n] + ok_c = (all(k[1] == n and k[2] is True and k[3] is True and k[4] == 'perm+quad' and k[5] in ('id', 'id+quad') + for k in compl) and n_compl > 0 + and {k: v for k, v in exp.items() if k[0] == 'compl'} == compl) + cols_txt = 'all %d basis columns' % (1 << n) if n <= 6 else '6 sampled columns each' + check('C3g.complement-n%d' % n, ok_c, + '%d complement w (odd, w.u=1)%s: route T_{w^perp} T_^-1 has Clifford rank %d; Lmon^-1 R Rmon^-1 == F on the ' + 'tableau and on %s; wrapper classes (Lmon perm+quad; Rmon id: %d, id+quad: %d)' + % (n_compl, '' if n <= 6 else ' (seeded sample)', n, cols_txt, + compl.get(('compl', n, True, True, 'perm+quad', 'id'), 0), + compl.get(('compl', n, True, True, 'perm+quad', 'id+quad'), 0))) + ok_u = (all(k[1] == n and k[2] is True and k[3] is True for k in ctl_u) + and {k: v for k, v in exp.items() if k[0] == 'u'} == ctl_u) + check('C3g.format-sink-n%d' % n, ok_u, + 'control w = u (sink u^perp, %d draw%s): rank %d, exact (tableau and columns)' + % (sum(ctl_u.values()), '' if sum(ctl_u.values()) == 1 else 's', n)) + if n >= 4: + ok_n = (non and all(k[1] == n - 2 for k in non) and {k: v for k, v in exp.items() if k[0] == 'noncompl'} == non) + check('C3g.noncomplement-n%d' % n, bool(ok_n), + 'control w.u=0 (%d odd w): Clifford rank n-2 = %d' % (sum(non.values()), n - 2)) + else: + check('C3g.noncomplement-n%d' % n, not non, 'no odd w with w.u=0 exists at n=3 (control vacuous)') + + # --- port price: first odd complement w != u + w = next(w for w in range(1, 1 << n) if par(w) and par(w & u) and w != u) + V = hyper(w, n) + Uperp = hyper(u, n) + FULL = [1 << i for i in range(n)] + rY, dY, rYu, rX = rk(T(n, V)), d([], V), rk(T(n, Uperp)), rk(opstep(n, [u], FULL)) + check('C3g.port-price-n%d' % n, (rY, dY, rYu, rX) == (PORT_PRICE[n],) * 4, + 'Y: 0 -> w^perp rank %d (d %d), 0 -> u^perp rank %d; X: -> FULL rank %d; all n-1 = %d' + % (rY, dY, rYu, rX, n - 1)) + + if n <= 5: + Gs = all_subspace_bases(n) + bad, n_inside = interval(n, w, Gs) + check('C3g.interval-n%d' % n, bad == 0 and len(Gs) == INTERVAL_SUBSPACES[n] and 0 < n_inside < len(Gs), + 'Y: 0 -> G -> w^perp excess 0 iff G <= w^perp (%d of %d subspaces) else exactly 2: violations %d' + % (n_inside, len(Gs), bad)) + s = next((s for s in range(1, 1 << n) if par(s) and par(s & w) == 0 and par(s & u) == 1), None) + ch, okr, good = network(n, u, w, s, rng) + exp_c = CORRECTOR[n] + check('C3g.corrector-n%d' % n, s == exp_c['s'] and ch == exp_c['charged'] == 2 * (n - 1) and okr and good, + 's=%s (s.u=1, s.w=0): charged %d = d-sum 2(n-1), child rank == d at every step %s, operator exact on ' + 'columns %s' % (format(s, '0%db' % n), ch, okr, good)) + +finish() diff --git a/research/format-limits/scripts/c3_complement_taint.py b/research/format-limits/scripts/c3_complement_taint.py new file mode 100644 index 0000000000..0547b0dbfc --- /dev/null +++ b/research/format-limits/scripts/c3_complement_taint.py @@ -0,0 +1,337 @@ +"""Rigidity of the complement sink (Lemma R): on the 112-target, 9-bit-port decoder every target has exactly one +admissible sink, the standard one. + +Setting (frames and the common-frame identity: upstream/build/sections/03-motifs.tex:154-186; the route operator +C_sink C_source^-1 of a complex interface: 03-motifs.tex:568-640; the recursive contract: 05-layers.tex:141-154). +A word is a scalar program on registers 0..n-1, n = 2V+R, V = 112 ports. Registers 0..V-1 are the sources s +(port vector u_s in F_2^9), V..2V-1 the targets T_t, 2V.. the helper and centre registers; its events are +['add', t, s, ...] (register t receives register s) in three phases A, cut, B. A target T_t must end at a sink +V_t = w_t^perp with w_t odd-weight and w_t . u_t = 1 (the standard sink is w_t = u_t, V_t = u_t^perp; every other +choice is a 'complement' sink). + +Two quantities are computed, both over GF(2) with 9-bit integers (bit 0 = least significant): + +* lower closure lo(r): the smallest frame register r can stand at in ANY frame assignment of the same scalar word + whose only drops are the centre drops at the cut. Sources start at ; targets, helpers and centres start at 0 + (an entrance is a choice, 0 is the most permissive); every 'add' puts both registers at one common frame, so both + get lo(t)+lo(s) (monotone from then on); at the cut every centre drops to 0 (the most permissive drop). The final + frame of T_t is at least lo(T_t), so any sink must satisfy lo(T_t) <= w_t^perp, i.e. w_t is orthogonal to lo(T_t); + u_t in lo(T_t) would make the word illegal. +* drop-free source taint of T_t: the set of sources whose content reaches T_t along 'add' events (centres reset at + the cut). A source s whose content reaches T_t drop-free must be lossless, i.e. w_t . u_s = 0. + +Lemma R: if the taint of T_t spans u_t^perp then w_t = u_t is the only complement sink of t. +Measured here: the taint of T_t is exactly the Gram-orthogonal neighbourhood {s != t : u_s . u_t = 0} (52 sources, +span of dimension 8 = u_t^perp), the most permissive closure has dimension 8 on all 112 targets, and w_t = u_t is the +only admissible sink on all 112; nothing reaches a target in phase A, no target carries its own source. + +Further checks on one word (#569 width7/eight): +* kmin: for a complement sink w != u_t (w odd, w . u_t = 1) the violated correctors are the taint sources s with + w . u_s = 1; 'newly allowed' are sources s with u_s . u_t = 1 (illegal under u_t^perp) and w . u_s = 0. + The minimum over w of the violated count is 20 on every target. +* positive control: the instrument does see freedom when it exists. For the target T_0 and the complement sink + w_0 (the first minimiser of the violated count) delete (i) the 3 events that write taint carrying a violated source + into T_0 -- this does NOT free T_0, because the gate closure is stickier than the content taint -- and + (ii) the 4 gates touching T_0 whose partner frame (at that point of the closure) is not inside w_0^perp -- now T_0 + has dim 7 and the two admissible sinks {u_0, w_0}, while the other 111 targets stay forced. + +Words: #569 width7-eight and fourcold-eight, #571 combined-eight-local (DominikScholz), #531 direct-delivery504 +(icekylinx, file of main). Run: python3 c3_complement_taint.py +""" +import gzip +import json +import time +from collections import Counter + +from report import check, finish, DATA, VENDOR, main_file + +V = 112 # ports (sources) and targets +NB = 9 # port bits + +# --------------------------------------------------------------------------------------------------------------- +# expected values (from the recorded measurements) +EXPECTED = { + 'dim': 8, # dim lo(T_t) = dim u_t^perp + 'n_taint': 52, # |{s != t : u_s . u_t = 0}| + 'kmin': 20, # min over complement sinks w of the number of violated correctors + # (violated, newly allowed) over all (t, w), w odd, w.u_t = 1, w != u_t: 127 sinks per target + 'kdist': {(20, 32): 336, (22, 30): 5376, (24, 28): 896, (24, 32): 448, (28, 28): 896, (28, 32): 448, + (30, 30): 5376, (32, 32): 336, (52, 0): 112}, + 'w0': 0b110000001, # first minimiser for target 0, printed as 110000001 + 'w0_violated': 20, + 'taint_filter_removed': 3, # events writing violated taint into T_0 + 'closure_filter_removed': 4, # gates touching T_0 whose partner frame is not inside w0^perp + 'closure_dims': {7: 1, 8: 111}, + 'closure_admissible': {1: 111, 2: 1}, +} + +WORDS = [ # (key, label, path, has recorded entrance-frame variant) + ('width7_eight', '#569 width7/eight', VENDOR / 'pr569' / 'width7-eight-FULL-WORD.json.gz', True), + ('fourcold_eight', '#569 fourcold/eight', VENDOR / 'pr569' / 'fourcold-eight-FULL-WORD.json.gz', True), + ('combined_eight_local', '#571 combined-eight-local', VENDOR / 'pr571' / 'combined-eight-local-FULL-WORD.json.gz', True), + ('direct504_local', '#531 direct-delivery504 local', + 'research/direct-delivery504-global/evidence/local/FULL-WORD.json.gz', False), +] + + +# --------------------------------------------------------------------------------------------------------------- +# GF(2) helpers on 9-bit integers +def par(x): + return bin(x).count('1') & 1 + + +def basis(vs): + """reduced row echelon basis (tuple, canonical order) of the span of the integers vs.""" + b = {} + for x in vs: + for p in sorted(b, reverse=True): + if x >> p & 1: + x ^= b[p] + if x: + p = x.bit_length() - 1 + for q in list(b): + if b[q] >> p & 1: + b[q] ^= x + b[p] = x + return tuple(b[p] for p in sorted(b, reverse=True)) + + +def in_span(x, B): + return len(basis(list(B) + [x])) == len(B) + + +def perp_vectors(B): + return [z for z in range(1, 1 << NB) if all(par(z & b) == 0 for b in B)] + + +def admissible_sinks(D, u): + """odd-weight w with w.u = 1 and w orthogonal to the frame D.""" + return [z for z in perp_vectors(D) if par(z & u) and par(z)] + + +# --------------------------------------------------------------------------------------------------------------- +def lower_closure(word, skip=None, entrances=False): + """lo(r) for every register. skip(phase, i, t, s, lo) -> True deletes the i-th event of the phase (an 'add' gate + of registers t, s); used by the positive control.""" + R = word['report']['R'] + n = 2 * V + R + P = word['ports'] + lo = {} + for r in range(n): + if r < V: + lo[r] = (P[r],) + elif entrances and r >= 2 * V and str(r) in word.get('start_extra', {}): + lo[r] = basis(word['start_extra'][str(r)]) + else: + lo[r] = () + removed = [] + + def run(phase, seq): + for i, e in enumerate(seq): + if e[0] != 'add': + continue + t, s = e[1], e[2] + if skip is not None and skip(phase, i, t, s, lo): + removed.append((phase, i, t, s)) + continue + F = basis(list(lo[t]) + list(lo[s])) + lo[t] = F + lo[s] = F + + run('A', word['A']) + for c in word['centers']: + lo[c] = () + run('cut', word['cut']) + run('B', word['B']) + return lo, removed + + +def closure_report(word, lo): + """per-target (dim lo, #admissible sinks, w==u forced) plus counters.""" + P = word['ports'] + dims, free = Counter(), Counter() + illegal = forced = 0 + sinks = {} + for t in range(V): + D, u = lo[V + t], P[t] + if in_span(u, D): + illegal += 1 + sinks[t] = (len(D), None) + continue + ws = admissible_sinks(D, u) + dims[len(D)] += 1 + free[len(ws)] += 1 + forced += (ws == [u]) + sinks[t] = (len(D), ws) + return dict(dims=dict(sorted(dims.items())), free=dict(sorted(free.items())), illegal=illegal, forced=forced, + sinks=sinks) + + +def source_taint(word, skip=None): + """taint[r] = set of sources whose content reaches register r drop-free (centres reset at the cut). + Returns (taint after A, final taint, removed events); skip(phase, i, t, s, taint) deletes an event.""" + n = 2 * V + word['report']['R'] + taint = {r: ({r} if r < V else set()) for r in range(n)} + removed = [] + + def run(phase, seq): + for i, e in enumerate(seq): + if e[0] == 'add': + if skip is not None and skip(phase, i, e[1], e[2], taint): + removed.append((phase, i, e[1], e[2])) + continue + taint[e[1]] |= taint[e[2]] + run('A', word['A']) + after_A = {t: set(taint[V + t]) for t in range(V)} + for c in word['centers']: + taint[c] = set() + run('cut', word['cut']) + run('B', word['B']) + return after_A, taint, removed + + +def kmin_stats(word, taint): + """(min violated per target, Counter over all (t, w != u_t) of (violated, newly allowed)).""" + P = word['ports'] + dist = Counter() + mins = {} + argmin0 = None + for t in range(V): + u, S = P[t], taint[V + t] + nonorth = [s for s in range(V) if s != t and par(P[s] & u)] + best = None + for z in range(1, 1 << NB): + if par(z) and par(z & u) and z != u: + viol = sum(1 for s in S if par(z & P[s])) + new = sum(1 for s in nonorth if not par(z & P[s])) + dist[(viol, new)] += 1 + if best is None or viol < best: + best = viol + if t == 0: + argmin0 = z # first z (increasing) attaining the minimum + mins[t] = best + return mins, dist, argmin0 + + +# --------------------------------------------------------------------------------------------------------------- +def load_word(path): + p = main_file(path) if isinstance(path, str) else path + return json.loads(gzip.decompress(p.read_bytes())) + + +def run_word(key, label, path, has_entrance_variant, words_out): + word = load_word(path) + words_out[key] = word + P = word['ports'] + assert len(P) == V and word['report']['R'] == 504 + tag = 'C3t.%s.' % key + t0 = time.time() + + lo, _ = lower_closure(word) + rep = closure_report(word, lo) + is_perp = all(all(par(b & P[t]) == 0 for b in lo[V + t]) for t in range(V)) # lo(T_t) lies in u_t^perp + check(tag + 'closure_dim8', rep['dims'] == {EXPECTED['dim']: V} and rep['illegal'] == 0 and is_perp, + '%s: dim lo(T_t) %s on %d targets (= u_t^perp: %s), u_t in lo(T_t): %d' % (label, rep['dims'], V, is_perp, rep['illegal'])) + only_u = all(s[1] == [P[t]] for t, s in rep['sinks'].items()) + check(tag + 'sink_forced', rep['free'] == {1: V} and rep['forced'] == V and only_u, + '#admissible sinks %s, w_t = u_t forced on %d/%d' % (rep['free'], rep['forced'], V)) + + after_A, taint, _ = source_taint(word) + eq = sum(1 for t in range(V) + if taint[V + t] == {s for s in range(V) if s != t and not par(P[s] & P[t])}) + nsrc = Counter(len(taint[V + t]) for t in range(V)) + span = Counter(len(basis([P[s] for s in taint[V + t]])) for t in range(V)) + check(tag + 'taint_is_orth_neighbourhood', + eq == V and dict(nsrc) == {EXPECTED['n_taint']: V} and dict(span) == {EXPECTED['dim']: V}, + 'taint == {s != t : u_s.u_t = 0} on %d/%d, #sources %s, span dim %s' % (eq, V, dict(nsrc), dict(span))) + spanA = Counter(len(basis([P[s] for s in after_A[t]])) for t in range(V)) + check(tag + 'nothing_reaches_targets_in_A', dict(spanA) == {0: V}, + 'span dim of the taint after phase A only: %s' % dict(spanA)) + own = sum(1 for t in range(V) if t in taint[V + t]) + check(tag + 'no_own_source', own == 0, 'targets carrying their own source drop-free: %d' % own) + + mins, dist, _ = kmin_stats(word, taint) + check(tag + 'kmin20', Counter(mins.values()) == Counter({EXPECTED['kmin']: V}), + 'min over complement sinks w != u_t of #violated correctors: %s' % dict(Counter(mins.values()))) + if key == 'width7_eight': + check(tag + 'kmin_distribution', dict(dist) == EXPECTED['kdist'], + '(violated, newly allowed) over %d (t, w) pairs: %s' % (sum(dist.values()), sorted(dist.items()))) + + if has_entrance_variant: + lo2, _ = lower_closure(word, entrances=True) + rep2 = closure_report(word, lo2) + check(tag + 'closure_with_word_entrances', rep2['dims'] == {EXPECTED['dim']: V} and rep2['free'] == {1: V} + and rep2['illegal'] == 0, + 'closure with the word\'s own entrance frames (start_extra): dims %s, sinks %s' % (rep2['dims'], rep2['free'])) + else: + print('NOTE %s: the word stores its helper entrance frames in a convention this closure does not model (frames ' + 'taken from the start would put u_t in the closure); the claims above use the most permissive ' + 'entrances, every helper at 0, which bound every frame assignment' % label, flush=True) + return time.time() - t0 + + +def positive_control(key, word, label): + """delete the gates/events that carry the lossless corrections of T_0 and watch the instrument see freedom.""" + P = word['ports'] + tag = 'C3t.posctl.%s.' % key + T0 = V + _, taint, _ = source_taint(word) + _, _, w0 = kmin_stats(word, taint) + u0 = P[0] + viol = {s for s in taint[T0] if par(w0 & P[s])} + check(tag + 'w0', w0 == EXPECTED['w0'] and len(viol) == EXPECTED['w0_violated'], + '%s: target 0, u_0 = %s, w_0 = %s, violated correctors %d' % ( + label, format(u0, '09b'), format(w0, '09b'), len(viol))) + + # (i) taint-filtered: delete the events writing violated taint into T_0 (from the content taint), then recompute + # the gate closure without those events + def skip_taint(phase, i, t, s, taint_now): + return t == T0 and bool(taint_now[s] & viol) + _, _, removed_t = source_taint(word, skip=skip_taint) + gone = {(ph, i) for ph, i, _, _ in removed_t} + lo_t, _ = lower_closure(word, skip=lambda ph, i, t, s, lo: (ph, i) in gone) + rep_t = closure_report(word, lo_t) + d0, ws0 = rep_t['sinks'][0] + check(tag + 'taint_filter_does_not_free', + len(removed_t) == EXPECTED['taint_filter_removed'] and rep_t['dims'] == {EXPECTED['dim']: V} + and rep_t['free'] == {1: V} and (d0, ws0) == (EXPECTED['dim'], [u0]) and w0 not in ws0, + 'removed %d events (partners %s); dims %s, #admissible %s, T_0 (dim, sinks) = (%d, %s), w_0 admissible: %s' % ( + len(removed_t), [s for _, _, _, s in removed_t], rep_t['dims'], rep_t['free'], d0, ws0, w0 in ws0)) + + # (ii) closure-filtered: delete the gates touching T_0 whose partner frame is not inside w0^perp + def skip_closure(phase, i, t, s, lo_now): + if T0 not in (t, s): + return False + partner = s if t == T0 else t + return any(par(w0 & b) for b in lo_now[partner]) + lo_c, rm_c = lower_closure(word, skip=skip_closure) + rep_c = closure_report(word, lo_c) + d0, ws0 = rep_c['sinks'][0] + check(tag + 'closure_filter_frees_T0', + len(rm_c) == EXPECTED['closure_filter_removed'] and rep_c['dims'] == EXPECTED['closure_dims'] + and rep_c['free'] == EXPECTED['closure_admissible'] and rep_c['illegal'] == 0 + and sorted(ws0) == sorted([u0, w0]) and rep_c['forced'] == V - 1, + 'removed gates %s (phase, event, t, s); dims %s, #admissible %s, T_0 (dim, sinks) = (%d, %s), others forced: %d/%d' % ( + rm_c, rep_c['dims'], rep_c['free'], d0, ws0, rep_c['forced'], V - 1)) + # (the gates removed are the correction gates read at T_0: each partner holds a violated source) + reads_target = sum(1 for e in word['B'] if e[0] == 'add' and V <= e[2] < 2 * V) + check(tag + 'every_target_read_once', reads_target == V, + 'B events whose source register is a target: %d' % reads_target) + + +def main(): + t_start = time.time() + words = {} + for key, label, path, flag in WORDS: + dt = run_word(key, label, path, flag, words) + print(' (%s: %.1f s)' % (key, dt), flush=True) + t0 = time.time() + for key in ('width7_eight', 'fourcold_eight', 'combined_eight_local'): + positive_control(key, words[key], dict((k, l) for k, l, _, _ in WORDS)[key]) + print(' (positive control: %.1f s)' % (time.time() - t0), flush=True) + print('total %.1f s' % (time.time() - t_start)) + finish() + + +if __name__ == '__main__': + main() diff --git a/research/format-limits/scripts/c4_quotient.py b/research/format-limits/scripts/c4_quotient.py new file mode 100644 index 0000000000..dec39d9b01 --- /dev/null +++ b/research/format-limits/scripts/c4_quotient.py @@ -0,0 +1,507 @@ +"""Lemma Q: a unit with degenerate labels is dominated by its quotient. + +Setting. A unit has ports with F_2 (complex) or Q (bit) labels spanning a space W of dimension d. For the complex +side the form is the standard dot product on F_2^n, rad = W cap W^perp has dimension rho, the Gram rank is +r = d - rho, and pi : W -> W/rad is the quotient map. A 'total' j is read by the targets from a frame f_j, the span +of the labels of its sources. Reading total j at a cut frame g costs the frame-lemma price + d(f_j, g) = dim f_j + dim g - 2 dim(f_j cap g) (upstream/build/sections/03-motifs.tex:154-186), +where all targets stand at one common frame g that lies in every target's sink; because f_j lies in W, f_j cap g lies +in rad, so only cuts g inside rad matter. Per total, for g inside rad, + d(f_j, g) >= dim f_j - dim(f_j cap rad) = dim pi(f_j). +Hence for every schedule of cuts (a chain 0 = g_0 < g_1 < ... of subspaces of rad, each total read at one of them) + cst_E2' >= cst_quotient = sum_j dim pi(f_j) >= cst_pair = sum_j rank pairing(sources_j, readers_j), +the last being the pairing-rank floor of a total, which only depends on the Gram. The quotient unit (labels mod rad, same Gram +and decoder) has window r = d - rho <= h - 2 rho for every realisation with window h = d + rho. Certified exponents X +are non-increasing in the window and in the copy cost, so X_deg(s) <= X(s, r/k, cst_quotient/v) for every s. + +This script checks, with exact ranks: +* the one degenerate paired cube (p = 3: 8 ports in F_2^6, 16 helper registers, six totals each of dimension 3; the + instance is data/toys/sol_p3_cone_R16.json): d 4, rho 2, copy cost 18 when read at 0, 16 for the best schedule of cuts + over all flags of rad, 12 for the quotient (= the pairing-rank bound); window 6 against 2 for the quotient, which has + only 2 distinct labels; +* the paired cubes p = 3..12 (ports chi_S: three index pairs, one of two bits each, form 9I - J on the bit side): only the + complex p = 3 is degenerate, the bit side never; +* E8 (120 root lines in doubled standard coordinates, nine F_2 label coordinates, e8units.standard_e8) decorated by one + isotropic direction e on the bit side (nine star totals) and by weight-2 isotropic directions on the complex side + (eight coordinate totals of 78 lines): the best schedule recovers exactly the quotient cost 72 at a larger window + (10 against 8; 11/13/15 against 9); a decoration aligned with two totals needs 73; +* 737 random instances (337 with extra-coordinate radicals, 400 with intrinsic radicals; Python's seeded Mersenne + Twister, seeds 1 and 7): no schedule beats the quotient; +* the certified exponents X (hi of skel.X at the best odd s in 3..13) of the quotient against the degenerate realisation, + with the references of the punctured units (bit 111/63, complex 112/64). +Run: python3 c4_quotient.py +""" +import itertools +import random +import time + +import numpy as np + +from report import check, finish, DATA, load_json +from e8units import (standard_e8, e8_labels, f2_rank, rank_q, row_basis_idx_q, gram_rank_q, dot2, span_basis, + rows_to_int) +from skel import X as skel_X +from fractions import Fraction as Fr + +# --------------------------------------------------------------------------------------------------------------- +# expected values (from the recorded runs) +EXPECTED = { + 'toy': dict(d=4, rho=2, r=2, n_totals=6, dim_f=3, cst0=18, cstE2=16, cstQ=12, window_deg=6, window_quot=2, + n_labels=2, rad=[0b110011, 0b001111, 0b111100]), + # paired cubes p = 3..12: number of ports and complex (d, rho); the bit side is nondegenerate + 'paired_v': {3: 8, 4: 32, 5: 80, 6: 160, 7: 280, 8: 448, 9: 672, 10: 960, 11: 1320, 12: 1760}, + # E8 rows: (d, rho, r, window of the degenerate realisation, cst0, cstE2, cstQ, cstC) + 'e8_bit_e': (9, 1, 8, 10, 81, 72, 72, 72), + 'e8_cx': {1: (10, 1, 9, 11, 80, 72, 72, 72), 2: (11, 2, 9, 13, 88, 72, 72, 72), 3: (12, 3, 9, 15, 96, 72, 72, 72)}, + 'e8_cx_aligned': (11, 2, 9, 13, 86, 73, 72, 72), + # random instances: 'tests', no violation of cst_E2' >= cst_quotient, and how often a cut schedule beats reading at 0 + # ('gain') / equals the quotient ('equal'). The recorded run (gain 257 of 337, gain 376 and equal 374 of 400) + # minimised only over the flags built from subsets of the radical basis ('coordinate flags'); the optimum over ALL + # flags of the radical (this script's best_e2) is slightly better: gain_all 275, 379, equal_all 391. + 'random_extra': dict(tests=337, violations=0, gain=257, gain_all=275), # extra-coordinate radicals + 'random_intrinsic': dict(tests=400, violations=0, gain=376, equal=374, gain_all=379, equal_all=391), + # certified X (hi, best s over 3,5,...,13) printed to 5 significant digits; None = deficit D <= 0 at every s + 'X': {'toy_deg': None, 'toy_quot': None, + 'bit_quot': '5.1598e-03', 'bit_e_deg': '4.0462e-03', + 'cx_quot': '4.5356e-03', 'cx_rho1': '3.6522e-03', 'cx_rho2': '3.0570e-03', 'cx_rho3': '2.6286e-03', + 'bit_punct': '6.0005e-03', 'cx_punct': '5.1863e-03', + 'bit_star_floor': '8.0093e-03', 'cx_star_floor': '7.0728e-03'}, +} + + +# --------------------------------------------------------------------------------------------------------------- +# F_2 helpers on integer bit vectors +def f2_rad(basis): + """basis (echelon, decreasing) of W cap W^perp for W = span(basis): solve A c = 0 with A_ij = b_i . b_j.""" + n = len(basis) + A = [[dot2(basis[i], basis[j]) for j in range(n)] for i in range(n)] + rows = [sum(A[i][j] << j for j in range(n)) for i in range(n)] + red = [] + for r in rows: + for (p, rr) in red: + if r >> p & 1: + r ^= rr + if r: + p = r.bit_length() - 1 + red = [(pp, (rr ^ r) if rr >> p & 1 else rr) for pp, rr in red] + red.append((p, r)) + pivs = {p for p, _ in red} + ker = [] + for fj in [j for j in range(n) if j not in pivs]: + c = 1 << fj + for p, rr in red: + if rr & c: + c |= 1 << p + x = 0 + for i in range(n): + if c >> i & 1: + x ^= basis[i] + assert all(dot2(x, b) == 0 for b in basis) + ker.append(x) + return span_basis(ker) + + +def f2_dim(vecs): + return len(span_basis(vecs)) + + +def in_span(x, basis): + for b in basis: + if x ^ b < x: + x ^= b + return x == 0 + + +def quot_dim(f, rad): + """dim pi(f) = dim (f + rad) - dim rad.""" + return f2_dim(list(f) + list(rad)) - len(rad) + + +def subspaces_of(rad, all_subspaces): + """subspaces of rad as echelon-basis tuples. all_subspaces=False: only spans of subsets of the given basis (the + coordinate subspaces); True: every subspace (spans of subsets of the nonzero vectors, deduplicated).""" + rho = len(rad) + pool = [x for x in _span_elems(rad) if x] if all_subspaces else list(rad) + subs = {} + for k in range(rho + 1): + for comb in itertools.combinations(pool, k): + sp = tuple(sorted(span_basis(list(comb)), reverse=True)) + subs[sp] = len(sp) + return list(subs) + + +def best_e2(fs, rad, all_subspaces=True): + """minimum over complete flags 0 < g_1 < ... < g_rho = rad of sum_j min_{g in flag} d(f_j, g), exactly.""" + rho = len(rad) + subs = subspaces_of(rad, all_subspaces) + + def dcut(f, g): + cap = f2_dim([x for x in _span_elems(g) if in_span(x, f)]) + return len(f) + len(g) - 2 * cap + + def inside(a, b): + return f2_dim(list(a) + list(b)) == len(b) + cache = {} + + def cost(fi, g): + key = (fi, g) + if key not in cache: + cache[key] = dcut(fs[fi], g) + return cache[key] + best = None + + def flags(cur, chain): + nonlocal best + if len(cur) == rho: + c = sum(min(cost(i, g) for g in chain) for i in range(len(fs))) + best = c if best is None else min(best, c) + return + for g in subs: + if len(g) == len(cur) + 1 and inside(cur, g): + flags(g, chain + [g]) + flags((), [()]) + return best + + +def _span_elems(g): + """all vectors of the span of the basis g.""" + out = [0] + for b in g: + out += [x ^ b for x in out] + return out + + +# --------------------------------------------------------------------------------------------------------------- +def toy_p3(): + t0 = time.time() + c = load_json(DATA / 'toys' / 'sol_p3_cone_R16.json') + ports, fr = c['ports'], c['frames'] + tot = [fr[f] for _, _, f in c['ret']] # the six total frames f_j (bit vectors in F_2^6) + W = span_basis(ports) + d = len(W) + rad = f2_rad(W) + rho = len(rad) + Ex = EXPECTED['toy'] + cst0 = sum(len(span_basis(f)) for f in tot) + cstE2 = best_e2([tuple(span_basis(f)) for f in tot], rad) + cstE2_coord = best_e2([tuple(span_basis(f)) for f in tot], rad, all_subspaces=False) + cstQ = sum(quot_dim(span_basis(f), rad) for f in tot) + # pairing rank between the span of a total's source labels and the readers' span (all ports) + cstC = sum(f2_rank(np.array([[dot2(a, b) for b in ports] for a in span_basis(f)])) for f in tot) + rad_vecs = sorted(x for x in _span_elems(rad) if x) + check('C4.toy_p3.degeneracy', (d, rho, d - rho) == (Ex['d'], Ex['rho'], Ex['r']) and rad_vecs == sorted(Ex['rad']), + 'port span d = %d, radical rho = %d (nonzero radical vectors %s), Gram rank %d' + % (d, rho, [format(x, '06b') for x in rad_vecs], d - rho)) + check('C4.toy_p3.costs', (len(tot), cst0, cstE2, cstE2_coord, cstQ, cstC) == (Ex['n_totals'], Ex['cst0'], Ex['cstE2'], Ex['cstE2'], + Ex['cstQ'], Ex['cstQ']) + and all(len(span_basis(f)) == Ex['dim_f'] for f in tot), + '%d totals of dim %d: copy cost at 0 = %d, best cut schedule over all flags of rad = %d (coordinate flags: %d), ' + 'quotient = %d = pairing-rank bound %d' % (len(tot), Ex['dim_f'], cst0, cstE2, cstE2_coord, cstQ, cstC)) + labels = {reduce_mod(p, rad) for p in ports} + check('C4.toy_p3.window_labels', (c['h'], d - rho, len(labels)) == (Ex['window_deg'], Ex['window_quot'], Ex['n_labels']), + 'window of the degenerate realisation %d, of the quotient %d; quotient has %d distinct labels (ports mod rad)' + % (c['h'], d - rho, len(labels))) + print(' (toy_p3: %.1f s)' % (time.time() - t0), flush=True) + return dict(d=d, rho=rho, cstE2=cstE2, cstQ=cstQ, window=c['h'], v=c['v']) + + +def reduce_mod(x, rad): + for b in rad: + if x ^ b < x: + x ^= b + return x + + +# --------------------------------------------------------------------------------------------------------------- +def paired_cube(p, tau=3): + ports = [] + for I in itertools.combinations(range(p), tau): + for bb in itertools.product((0, 1), repeat=tau): + x = [0] * (2 * p) + for i, b in zip(I, bb): + x[2 * i + b] = 1 + ports.append(x) + return ports + + +def paired_cubes(): + t0 = time.time() + degenerate_cx, degenerate_bit, vs, bit_dims = [], [], {}, {} + for p in range(3, 13): + P = paired_cube(p) + vs[p] = len(P) + ints = [rows_to_int(r) for r in P] + B = span_basis(ints) + rho = len(f2_rad(B)) + # bit side: Q labels with form 9 I - J; window = rank_Q of the Gram L Q L^T/9, d = rank_Q L + h = 2 * p + Q = [[(9 if i == j else 0) - 1 for j in range(h)] for i in range(h)] + dq = len(row_basis_idx_q(P)) + rq = gram_rank_q(P, Q, range(len(P))) + if rho: + degenerate_cx.append((p, len(B), rho)) + if dq != rq: + degenerate_bit.append((p, dq, rq)) + bit_dims[p] = (dq, rq) + check('C4.paired.complex', vs == EXPECTED['paired_v'] and degenerate_cx == [(3, 4, 2)], + 'ports %s; complex labels degenerate only for (p, d, rho) = %s' % (list(vs.values()), degenerate_cx)) + check('C4.paired.bit', not degenerate_bit and all(bit_dims[p] == ((4, 4) if p == 3 else (2 * p, 2 * p)) for p in bit_dims), + 'bit labels (form 9I - J): rank of the labels = rank of the Gram for every p = 3..12 (p: rank) %s; degenerate: %s' + % ({p: bit_dims[p][0] for p in bit_dims}, degenerate_bit)) + print(' (paired cubes: %.1f s)' % (time.time() - t0), flush=True) + + +# --------------------------------------------------------------------------------------------------------------- +def e8_rows(rng): + """the E8 decorations. The random draws are made in a fixed order (bit decorations, then complex ones) so that the + generator state after this function is deterministic; it is passed on to the random tests.""" + L, G = standard_e8() + v = 120 + U9 = e8_labels(G) + bit_tots = [np.nonzero(U9[:, j])[0] for j in range(9)] # 9 totals S_j = ports with label bit j set + cx_tots = [(np.nonzero(L[:, a])[0], np.nonzero(L[:, a])[0]) for a in range(8)] # coordinate a: readers = sources + rows = {} + + def bit_decorated(cvec, key): + P = np.hstack([L, np.array(cvec, dtype=np.int64).reshape(-1, 1), np.zeros((v, 1), dtype=np.int64)]) + e = np.zeros(10, dtype=np.int64) + e[8] = 1 + d, r = rank_q(P.tolist()), 8 + rho = d - r + c0 = cE2 = cQ = cC = 0 + for Sj in bit_tots: + F = P[Sj] + df = rank_q(F.tolist()) + e_in = rank_q(np.vstack([F, e]).tolist()) == df + c0 += df + cE2 += min(df, df + 1 - 2 * int(e_in)) if rho == 1 else df # cuts: 0 or the line + cQ += rank_q(L[Sj].tolist()) + cC += rank_q(G[np.ix_(Sj, Sj)].tolist()) + rows[key] = (d, rho, r, d + rho, c0, cE2, cQ, cC) + + bit_decorated([0] * v, 'bit_control') + bit_decorated([1] * v, 'bit_e_all') + bit_decorated([rng.randint(0, 1) for _ in range(v)], 'bit_e_random') + bit_decorated([rng.randint(-3, 3) for _ in range(v)], 'bit_e_lifts') + + u = [rows_to_int(U9[t]) for t in range(v)] + assert all(dot2(u[s], u[t]) == ((1 + G[s, t]) % 2) for s in range(v) for t in range(v)) + + def cx_decorated(cmat, rho_max, key): + E = [(1 << (9 + 2 * i)) | (1 << (10 + 2 * i)) for i in range(rho_max)] # weight-2 isotropic directions + q = [] + for t in range(v): + x = u[t] + for i in range(rho_max): + if cmat[t] >> i & 1: + x ^= E[i] + q.append(x) + assert all(dot2(q[s], q[t]) == dot2(u[s], u[t]) for s in range(v) for t in range(v)) # Gram unchanged + B = span_basis(q) + rad = f2_rad(B) + d, rho = len(B), len(rad) + r = d - rho + c0 = cQ = cC = 0 + fs = [] + for R, A in cx_tots: + f = span_basis([q[t] for t in A]) + fs.append(tuple(f)) + c0 += len(f) + cQ += quot_dim(f, rad) + cC += f2_rank(np.array([[dot2(q[a], q[b]) for b in R] for a in A])) + cE2 = best_e2(fs, rad) if rho >= 1 else c0 + cE2c = best_e2(fs, rad, all_subspaces=False) if rho >= 1 else c0 + rows[key] = (d, rho, r, d + rho, c0, cE2, cQ, cC) + rows[key + '_coordflags'] = cE2c + + cx_decorated([0] * v, 0, 'cx_control') + cx_decorated([1] * v, 1, 'cx_e_all') + for rho_max in (1, 2, 3): + cx_decorated([rng.randrange(1 << rho_max) for _ in range(v)], rho_max, 'cx_rho%d' % rho_max) + cx_decorated([(1 if t in set(cx_tots[0][1].tolist()) else 0) | (2 if t in set(cx_tots[1][1].tolist()) else 0) for t in range(v)], + 2, 'cx_aligned') + return rows + + +def check_e8(rows): + Ex = EXPECTED + names = ('d', 'rho', 'r', 'window', 'cst0', 'cstE2', 'cstQ', 'cstPair') + + def fmt(t): + return ', '.join('%s %d' % (n, x) for n, x in zip(names, t)) + check('C4.e8_bit_e.controls', rows['bit_control'] == (8, 0, 8, 8, 72, 72, 72, 72), + 'undecorated bit E8: ' + fmt(rows['bit_control'])) + ok = all(rows[k] == Ex['e8_bit_e'] for k in ('bit_e_all', 'bit_e_random', 'bit_e_lifts')) + check('C4.e8_bit_e', ok, 'E8 bit + isotropic e (every port / random ports / lifts n_T e): ' + fmt(rows['bit_e_all']) + + '; window 10 vs quotient 8') + check('C4.e8_cx.controls', rows['cx_control'] == (9, 0, 9, 9, 72, 72, 72, 72) and rows['cx_e_all'][1] == 0, + 'undecorated complex E8: ' + fmt(rows['cx_control'])) + for k in (1, 2, 3): + t = rows['cx_rho%d' % k] + check('C4.e8_cx.rho%d' % k, t == Ex['e8_cx'][k], 'E8 complex + weight-2 isotropic decoration rho=%d: %s ' + '(coordinate-flag optimum %d)' % (k, fmt(t), rows['cx_rho%d_coordflags' % k])) + t = rows['cx_aligned'] + check('C4.e8_cx.aligned', t == Ex['e8_cx_aligned'], + 'aligned decoration (e1 on total-0 sources, e2 on total-1 sources): %s (coordinate-flag optimum %d)' + % (fmt(t), rows['cx_aligned_coordflags'])) + return rows + + +# --------------------------------------------------------------------------------------------------------------- +def random_extra(rng): + """random instances with extra-coordinate radicals: odd-weight vectors in F_2^n decorated by weight-2 isotropic + directions in extra coordinates.""" + tests = viol = viol_c = gain = gain_c = 0 + for trial in range(400): + n = rng.randint(6, 9) + rho_t = rng.randint(1, 3) + E = [(1 << (n + 2 * i)) | (1 << (n + 1 + 2 * i)) for i in range(rho_t)] + nports = rng.randint(6, 14) + ports = [] + while len(ports) < nports: + x = rng.randrange(1, 1 << n) + if bin(x).count('1') % 2 == 1: + for i in range(rho_t): + if rng.random() < 0.5: + x ^= E[i] + ports.append(x) + B = span_basis(ports) + rad = f2_rad(B) + if not rad: + continue + ntot = rng.randint(2, 6) + fs = [tuple(span_basis(rng.sample(ports, rng.randint(2, len(ports))))) for _ in range(ntot)] + cE2 = best_e2(fs, rad) + cE2c = best_e2(fs, rad, all_subspaces=False) + cQ = sum(quot_dim(f, rad) for f in fs) + c0 = sum(len(f) for f in fs) + tests += 1 + viol += cE2 < cQ + viol_c += cE2c < cQ + gain += cE2 < c0 + gain_c += cE2c < c0 + return dict(tests=tests, violations=viol, violations_coord=viol_c, gain=gain_c, gain_all=gain) + + +def random_intrinsic(): + """W a random subspace of F_2^n (n 6..10) with a nonzero radical; ports = odd-norm vectors of W.""" + rng = random.Random(7) + tests = viol = viol_c = gain = gain_c = eq = eq_c = 0 + while tests < 400: + n = rng.randint(6, 10) + k = rng.randint(3, n - 1) + gens = [rng.randrange(1, 1 << n) for _ in range(k)] + B = span_basis(gens) + rad = f2_rad(B) + if not rad or len(rad) > 3: + continue + span = [0] + for b in B: + span += [x ^ b for x in span] + odd = [x for x in span if dot2(x, x) == 1] + if len(odd) < 6: + continue + ports = rng.sample(odd, min(len(odd), rng.randint(6, 16))) + Bp = span_basis(ports) + radp = f2_rad(Bp) + if not radp or len(radp) > 3: + continue + fs = [tuple(span_basis(rng.sample(ports, rng.randint(2, len(ports))))) for _ in range(rng.randint(2, 6))] + cE2 = best_e2(fs, radp) + cE2c = best_e2(fs, radp, all_subspaces=False) + cQ = sum(quot_dim(f, radp) for f in fs) + c0 = sum(len(f) for f in fs) + tests += 1 + viol += cE2 < cQ + viol_c += cE2c < cQ + gain += cE2 < c0 + gain_c += cE2c < c0 + eq += cE2 == cQ + eq_c += cE2c == cQ + return dict(tests=tests, violations=viol, violations_coord=viol_c, gain=gain_c, gain_all=gain, equal=eq_c, equal_all=eq) + + +# --------------------------------------------------------------------------------------------------------------- +def certified_X(h, k, cst, v): + """(best hi over s = 3,5,..,13, s) of the certified skeleton exponent, or (None, None) if D <= 0 at every s.""" + x = Fr(cst, v) + best = (None, None) + for s in (3, 5, 7, 9, 11, 13): + r = skel_X(s, h, k, x) + if r is not None: + hi = float(r['hi']) + if best[0] is None or hi > best[0]: + best = (hi, s) + return best + + +def check_X(toy, rows): + t0 = time.time() + cases = { # key: (h, cst, v) + 'toy_deg': (toy['window'], toy['cstE2'], toy['v']), + 'toy_quot': (toy['d'] - toy['rho'], toy['cstQ'], toy['v']), + 'bit_quot': (rows['bit_e_all'][2], rows['bit_e_all'][6], 120), + 'bit_e_deg': (rows['bit_e_all'][3], rows['bit_e_all'][5], 120), + 'cx_quot': (rows['cx_rho1'][2], rows['cx_rho1'][6], 120), + 'cx_rho1': (rows['cx_rho1'][3], rows['cx_rho1'][5], 120), + 'cx_rho2': (rows['cx_rho2'][3], rows['cx_rho2'][5], 120), + 'cx_rho3': (rows['cx_rho3'][3], rows['cx_rho3'][5], 120), + 'bit_punct': (8, 63, 111), # punctured references: 111 ports, copy cost 63 + 'cx_punct': (9, 64, 112), # 112 ports, copy cost 64 (the binding reference) + 'bit_star_floor': (8, 64, 120), # 64/120: unattained star-scope bounds for repeated labels + 'cx_star_floor': (9, 64, 120), + } + got = {} + for key, (h, cst, v) in cases.items(): + hi, s = certified_X(h, 1, cst, v) + got[key] = None if hi is None else '%.4e' % hi + print(' %-15s h=%2d cst/v=%d/%d X* = %s (s=%s)' % (key, h, cst, v, got[key] or 'D<=0 at every s', s), flush=True) + Ex = EXPECTED['X'] + check('C4.X.toy', got['toy_deg'] == Ex['toy_deg'] and got['toy_quot'] == Ex['toy_quot'], + 'toy_p3: deficit D <= 0 at every s for the degenerate (h=6, 16/8) and the quotient (h=2, 12/8) unit') + check('C4.X.bit', (got['bit_quot'], got['bit_e_deg']) == (Ex['bit_quot'], Ex['bit_e_deg']), + 'bit E8: quotient (h=8, 72/120) X* = %s versus +e realisation (h=10, 72/120) X* = %s' % (got['bit_quot'], got['bit_e_deg'])) + check('C4.X.cx', tuple(got[k] for k in ('cx_quot', 'cx_rho1', 'cx_rho2', 'cx_rho3')) + == tuple(Ex[k] for k in ('cx_quot', 'cx_rho1', 'cx_rho2', 'cx_rho3')), + 'complex E8: quotient (h=9) X* = %s versus rho=1/2/3 realisations (h=11/13/15) %s / %s / %s' + % (got['cx_quot'], got['cx_rho1'], got['cx_rho2'], got['cx_rho3'])) + check('C4.X.references', (got['bit_punct'], got['cx_punct']) == (Ex['bit_punct'], Ex['cx_punct']), + 'punctured references: bit 111/63 (h=8) X* = %s, complex 112/64 (h=9) X* = %s (binding)' % (got['bit_punct'], got['cx_punct'])) + check('C4.X.star_floor', (got['bit_star_floor'], got['cx_star_floor']) == (Ex['bit_star_floor'], Ex['cx_star_floor']), + 'star-scope floor cst/v = 64/120 (unattained bound for repeated labels): bit %s, complex %s' + % (got['bit_star_floor'], got['cx_star_floor'])) + print(' (certified X: %.1f s)' % (time.time() - t0), flush=True) + + +def main(): + t_start = time.time() + toy = toy_p3() + paired_cubes() + t0 = time.time() + rng = random.Random(1) + rows = e8_rows(rng) + check_e8(rows) + print(' (E8 decorations: %.1f s)' % (time.time() - t0), flush=True) + t0 = time.time() + re = random_extra(rng) + Ex = EXPECTED['random_extra'] + check('C4.random_extra', (re['tests'], re['violations'], re['violations_coord'], re['gain'], re['gain_all']) + == (Ex['tests'], 0, 0, Ex['gain'], Ex['gain_all']), + '%d instances with extra-coordinate radicals: violations of cst_E2\' >= cst_quotient: %d (coordinate flags: %d); ' + 'a cut schedule beats reading at 0 in %d (coordinate flags: %d)' + % (re['tests'], re['violations'], re['violations_coord'], re['gain_all'], re['gain'])) + ri = random_intrinsic() + Ex = EXPECTED['random_intrinsic'] + check('C4.random_intrinsic', (ri['tests'], ri['violations'], ri['violations_coord'], ri['gain'], ri['gain_all'], ri['equal'], ri['equal_all']) + == (Ex['tests'], 0, 0, Ex['gain'], Ex['gain_all'], Ex['equal'], Ex['equal_all']), + '%d instances with intrinsic radicals: violations %d (coordinate flags: %d); schedule beats reading at 0 in %d ' + '(coordinate flags: %d), equals the quotient in %d (coordinate flags: %d)' + % (ri['tests'], ri['violations'], ri['violations_coord'], ri['gain_all'], ri['gain'], ri['equal_all'], ri['equal'])) + print(' (random tests: %.1f s)' % (time.time() - t0), flush=True) + check_X(toy, rows) + print('total %.1f s' % (time.time() - t_start)) + finish() + + +if __name__ == '__main__': + main() diff --git a/research/format-limits/scripts/c5_lambda.py b/research/format-limits/scripts/c5_lambda.py new file mode 100644 index 0000000000..4eb6c0bd57 --- /dev/null +++ b/research/format-limits/scripts/c5_lambda.py @@ -0,0 +1,291 @@ +"""Lemma lambda: a phase-frame butterfly needs sqrt(-1); a different payload ring cannot remove the butterfly layer. + +The complex interface (upstream/build/sections/03-motifs.tex:568-640, 05-layers.tex:1-100) is built from the +butterfly kernel C = aI + bX on one address bit (X the bit swap), H0 = D1 C D2 with D1, D2 diagonal, and the +phase frames q_U = wt(P_U x) mod 4. The checks below are exact (Fractions, integers mod M, sympy), no floats. + +T1 length-8 synthetic (Nussbaumer) transform over R = Q[y]/(y^4+1), root y of order 8 + (upstream/build/sections/06-transforms.tex, synthetic DIF): three levels 'H0 on one address bit, then a + twiddle y^(-k)'. The product of the six factors equals B_8 F_8^- exactly. The three twiddle factors are signed + permutations (monomial, bit-legal controlled shifts); the three H0 factors are not monomial (row support 2). +T2 Fermat specialisation y -> 2, R -> Z/17: the same program is the bit-reversed length-8 NTT with root 2. +T3 Fourier mass: monomials preserve row support and a 2-point butterfly level at most doubles it; the target has + row support 8 = 2^3 blocks, so at least 3 butterfly levels are needed, the same as the complex DFT_8. +T4 Kernel lemma over Z/M (M odd): D1 (aI+bX) D2 = u [[1,1],[1,-1]] with D1, D2 invertible diagonal, u a unit, + aI+bX invertible, is solvable iff -1 is a square mod M, and in every solution + lambda = (a-b)/(a+b) satisfies lambda^2 = -1 (an order-4 Walsh phase). Brute force over the listed M. +T5 Directional-kernel lemma: for a 2x2 matrix K, conjugation of K (x) I by the address map x1 += x2 fixes K (x) I + iff K commutes with X, i.e. K = aI + bX. +T6 The complex identities hold verbatim in Z/17 with i = 4: C^2 = X and H0 = b S C S, lambda = +-i. +T7 A REAL butterfly D1 H D2 never lies in span(I, X) (a complex d1 is needed with e1 = +-i e2). +T8 In the phase calculus a residual vector v of weight 2 mod 4 gives H^m diag(i^(wt(v) [v.x])) H^m / 2^m a + permutation (a translation, rank 0); weights 3 and 1 do not. +real T7 and T8 together: real kernels have no subspace-labelled directional version, and only weight-2 mod 4 + directions are free translations. +Run: python3 c5_lambda.py +""" +import itertools +import time +from fractions import Fraction as Fr +from math import gcd + +import numpy as np +import sympy as sp + +from report import check, finish + +# --------------------------------------------------------------------------------------------------------------- +# expected values (from the recorded runs) +EXPECTED = { + 'T1_factors': (3, 3), # (monomial twiddle factors, non-monomial H0 factors) + 'T3_support': 8, # row support (ring blocks) of the length-8 transform; levels = 3 + 'T3_levels': 3, + # M -> number of solutions (a, b, e1, e2) of the kernel equation; nonzero iff -1 is a square mod M + 'T4': {3: 0, 5: 32, 7: 0, 9: 0, 11: 0, 13: 288, 15: 0, 17: 512, 21: 0, 25: 800, 29: 1568, 33: 0, 37: 2592, + 41: 3200, 45: 0, 65: 9216}, + 'T6_lambda': 4, # (a-b)/(a+b) in Z/17 with i = 4 + 'T8': {(1, 1, 0): True, (1, 1, 1): False, (1, 0, 0): False}, +} + +R = 4 # y^R = -1 : the ring Q[y]/(y^4+1) +T = 8 # transform length, root w = y of order 2R = 8 + + +# --------------------------------------------------------------------------------------------------------------- +def ymul_matrix(a): + """R x R matrix of multiplication by y^a on coefficient vectors (a signed permutation).""" + M = [[0] * R for _ in range(R)] + for k in range(R): + e = (k + a) % (2 * R) + sign = 1 + if e >= R: + e -= R + sign = -1 + M[e][k] = sign + return M + + +def zeros(n): + return [[Fr(0)] * n for _ in range(n)] + + +def matmul(A, B): + n, m, p = len(A), len(B), len(B[0]) + C = [[Fr(0)] * p for _ in range(n)] + for i in range(n): + Ai = A[i] + for k in range(m): + if Ai[k] != 0: + Bk, a = B[k], Ai[k] + for j in range(p): + if Bk[j] != 0: + C[i][j] += a * Bk[j] + return C + + +def put_block(i, j, M, big): + for r in range(R): + for c in range(R): + big[i * R + r][j * R + c] = Fr(M[r][c]) + + +def is_monomial(A): + return all(sum(1 for x in row if x != 0) == 1 for row in A) and all(sum(1 for x in col if x != 0) == 1 for col in zip(*A)) + + +def max_row_support_blocks(A): + """row support counted in ring blocks (an R x R block is nonzero iff some entry is).""" + n = len(A) // R + return max(sum(1 for j in range(n) if any(A[i * R + r][j * R + c] != 0 for r in range(R) for c in range(R))) + for i in range(n)) + + +def rev3(j): + return int(format(j, '03b')[::-1], 2) + + +def build_T1(): + target = zeros(T * R) # bit-reversed length-8 transform: (F^- z)_j = (1/8) sum_k w^(-jk) z_k at slot rev3(j) + for j in range(T): + for k in range(T): + put_block(rev3(j), k, [[Fr(x, T) for x in row] for row in ymul_matrix(-(j * k) % (2 * R))], target) + + def butterfly_level(bit): + A = zeros(T * R) + h = Fr(1, 2) + for s in range(T): + if (s >> bit) & 1: + continue + p = s | (1 << bit) + for (o, i, sg) in ((s, s, 1), (s, p, 1), (p, s, 1), (p, p, -1)): + put_block(o, i, [[h * sg * (1 if r == c else 0) for c in range(R)] for r in range(R)], A) + return A + + def twiddle_level(bit, t): + A = zeros(T * R) + wt_exp = (2 * R) // t # w_t = y^(2R/t) + for s in range(T): + b = (s >> bit) & 1 + k = s & ((1 << bit) - 1) + put_block(s, s, ymul_matrix((-(wt_exp * k * b)) % (2 * R)), A) + return A + + factors = [] # first element is applied first + for lev, bit in enumerate((2, 1, 0)): + t = T >> lev + factors.append(('H0 on bit %d' % bit, butterfly_level(bit))) + factors.append(('twiddle w_%d^-k on bit %d' % (t, bit), twiddle_level(bit, t))) + prog = None + for name, Fm in factors: + prog = Fm if prog is None else matmul(Fm, prog) + return target, factors, prog, rev3 + + +def reduce_mod_17(M): + """evaluate an R-block matrix at y = 2 (ring Q[y]/(y^4+1) -> Z/17).""" + P = 17 + n = len(M) // R + out = [[0] * n for _ in range(n)] + for i in range(n): + for j in range(n): + val = sum(M[i * R + r][j * R + 0] * (2 ** r) for r in range(R)) + out[i][j] = (val.numerator * pow(val.denominator, -1, P)) % P + return out + + +def kernel_lemma(M): + """number of solutions (a, b, e1, e2) of D1 (aI+bX) D2 = u H over Z/M and whether lambda^2 = -1 in all.""" + U = np.array([x for x in range(M) if gcd(x, M) == 1]) + isunit = np.zeros(M, dtype=bool) + isunit[U] = True + sols = 0 + lam_ok = True + A = np.arange(M) + for a in range(M): + for b in range(M): + if not isunit[(a * a - b * b) % M]: + continue + # row 1: (a e1, b e2) equal and a unit; row 2: (b e1, a e2) sums to 0 and first entry a unit + r10 = (a * U) % M + r11 = (b * U) % M + r20 = (b * U) % M + r21 = (a * U) % M + ok = (r10[:, None] == r11[None, :]) & isunit[r10][:, None] \ + & (((r20[:, None] + r21[None, :]) % M) == 0) & isunit[r20][:, None] + cnt = int(ok.sum()) + if cnt: + sols += cnt + s = (a + b) % M + if isunit[s]: + lam = ((a - b) * pow(s, -1, M)) % M + if (lam * lam) % M != M - 1: + lam_ok = False + else: + lam_ok = False + return sols, lam_ok + + +def main(): + t_all = time.time() + # ---- T1, T2, T3 + t0 = time.time() + target, factors, prog, _ = build_T1() + n_mono = sum(1 for _, F in factors if is_monomial(F)) + n_non = len(factors) - n_mono + pattern = [(name, is_monomial(F), max_row_support_blocks(F)) for name, F in factors] + ok_pat = all(m == name.startswith('twiddle') and s == (1 if m else 2) for name, m, s in pattern) + check('C5.T1', prog == target and (n_mono, n_non) == EXPECTED['T1_factors'] and ok_pat, + 'product of 6 factors == B_8 F_8^- exactly; monomial twiddles %d, non-monomial H0 factors %d (row supports %s)' + % (n_mono, n_non, [s for _, _, s in pattern])) + P = 17 + ntt = [[0] * T for _ in range(T)] + inv8 = pow(8, -1, P) + for j in range(T): + for k in range(T): + ntt[rev3(j)][k] = (pow(2, (-(j * k)) % 16, P) * inv8) % P + check('C5.T2', reduce_mod_17(prog) == ntt, 'program at y = 2 == bit-reversed length-8 NTT over Z/17 with root 2') + sup_target = max_row_support_blocks(target) + sup_ntt = max(sum(1 for x in row if x) for row in ntt) + dft = np.exp(-2j * np.pi * np.outer(range(T), range(T)) / T) / T # complex DFT_8: every entry has modulus 1/8 + sup_dft = int(max((np.abs(row) > 1e-12).sum() for row in dft)) + levels = (sup_target - 1).bit_length() + check('C5.T3', sup_target == sup_ntt == sup_dft == EXPECTED['T3_support'] and levels == EXPECTED['T3_levels'], + 'row support of F_8 over R: %d blocks, of the Z/17 NTT: %d, of the complex DFT_8: %d -> >= %d butterfly levels' + % (sup_target, sup_ntt, sup_dft, levels)) + print(' (T1-T3: %.1f s)' % (time.time() - t0), flush=True) + + # ---- T4 + t0 = time.time() + got, allok = {}, True + for M in EXPECTED['T4']: + sols, lam_ok = kernel_lemma(M) + sq = any((x * x) % M == M - 1 for x in range(M)) + got[M] = sols + good = ((sols > 0) == sq) and (sols == 0 or lam_ok) + allok &= good + print(' M=%3d: -1 square=%-5s solutions=%6d lambda^2=-1 in all=%s' % (M, sq, sols, lam_ok if sols else '-'), flush=True) + check('C5.T4', got == EXPECTED['T4'] and allok, + 'solutions exist iff -1 is a square mod M and lambda^2 = -1 in every solution, M in %s' % sorted(got)) + print(' (T4: %.1f s)' % (time.time() - t0), flush=True) + + # ---- T5 + a_, b_, c_, d_ = sp.symbols('a b c d') + K = sp.Matrix([[a_, b_], [c_, d_]]) + KI = sp.kronecker_product(K, sp.eye(2)) + Pn = sp.zeros(4, 4) + for x1 in (0, 1): + for x2 in (0, 1): + Pn[2 * (x1 ^ x2) + x2, 2 * x1 + x2] = 1 + cond = sp.simplify(Pn * KI * Pn.inv() - KI) + sol = sp.solve(list(cond), [c_, d_], dict=True) + check('C5.T5', sol == [{c_: b_, d_: a_}], 'conjugation by x1 += x2 fixes K (x) I <=> %s, i.e. K = aI + bX' % sol) + + # ---- T6: Z/17 with i = 4 + M, i = 17, 4 + assert (i * i) % M == M - 1 + h = pow(2, -1, M) + a = ((1 + i) * h) % M + b = ((1 - i) * h) % M + + def mm(A, B): + return [[sum(A[r][k] * B[k][c] for k in range(2)) % M for c in range(2)] for r in range(2)] + C = [[a, b], [b, a]] + X = [[0, 1], [1, 0]] + S = [[1, 0], [0, i]] + H0 = [[h, h], [h, (-h) % M]] + bSCS = [[(b * x) % M for x in row] for row in mm(mm(S, C), S)] + lam = ((a - b) * pow((a + b) % M, -1, M)) % M + check('C5.T6', mm(C, C) == X and bSCS == H0 and lam == EXPECTED['T6_lambda'] and lam in {i, M - i}, + 'Z/17, i=4: C^2 == X, H0 == b S C S, lambda = (a-b)/(a+b) = %d (i or -i: %s)' % (lam, sorted({i, M - i}))) + + # ---- T7, T8 (real kernels; weight of the residual vector) + d1, d2, e1, e2 = sp.symbols('d1 d2 e1 e2', real=True, nonzero=True) + H = sp.Matrix([[1, 1], [1, -1]]) + Kr = sp.diag(d1, d2) * H * sp.diag(e1, e2) + real_sol = sp.solve([sp.Eq(Kr[0, 0], Kr[1, 1]), sp.Eq(Kr[0, 1], Kr[1, 0])], [d1, e1], dict=True) + z1 = sp.symbols('z1') + Kc = sp.diag(z1, 1) * H * sp.diag(e1, e2) + cplx_sol = sp.solve([Kc[0, 0] - Kc[1, 1], Kc[0, 1] - Kc[1, 0]], [z1, e1], dict=True) + ok7 = (real_sol == [] and cplx_sol == []) + check('C5.T7', ok7, 'real solutions of D1 H D2 in span(I,X): %s; with complex d1 (needs e1 = +-i e2): %s' % (real_sol, cplx_sol)) + m = 3 + Hm = sp.Matrix([[1]]) + for _ in range(m): + Hm = sp.kronecker_product(Hm, H) + xs = list(itertools.product((0, 1), repeat=m)) + t8 = {} + for v in EXPECTED['T8']: + w = sum(v) + ph = sp.diag(*[sp.I ** ((w % 4) * (sum(p * q for p, q in zip(v, x)) % 2)) for x in xs]) + Op = (Hm * ph * Hm) / 2 ** m + t8[v] = all(sum(1 for t in Op.row(r) if t != 0) == 1 for r in range(2 ** m)) + check('C5.T8', t8 == EXPECTED['T8'], + 'H^m diag(i^(wt*[v.x])) H^m / 2^m is a permutation: ' + ', '.join('v=%s wt=%d: %s' % (v, sum(v), t8[v]) for v in t8)) + check('C5.real', ok7 and t8 == EXPECTED['T8'], + 'no real subspace-labelled butterfly (T7); only weight 2 mod 4 residuals are free translations (T8)') + print('total %.1f s' % (time.time() - t_all)) + finish() + + +if __name__ == '__main__': + main() diff --git a/research/format-limits/scripts/c6_asym.py b/research/format-limits/scripts/c6_asym.py new file mode 100644 index 0000000000..cf0dd58777 --- /dev/null +++ b/research/format-limits/scripts/c6_asym.py @@ -0,0 +1,311 @@ +"""Asymmetric pairing uniqueness: at the E8-linear decoder pattern the F_2 pairing is unique up to gauge at window <= 9. + +Setting. A cross-field unit on v ports has a decoder N over Q and an F_2 pairing B = W U^T, B_TS = , between +sink words w_T and source labels u_S in F_2^c. Lossless correction of the garbage N_TS x_S needs B_TS = 0, exactness +needs N o B = diag (N_TT != 0, B_TT = 1). The window is the F_2 rank of B and the copy cost of a total j is +rank B[readers_j, sources_j]. The pair (U, W) -> (U P, W P^-T) with P in GL(c, F_2) leaves B fixed, so 'W != U' is +meaningful only through B != B^T or B != B0 = (J + G) mod 2, the pairing of the symmetric unit. + +The E8-linear decoder pattern. Ports are root lines of E8 (e8units.hamming_e8: 8 coordinate lines and the 112 code +lines, G = L L^T / 2); the decoder is the sum of the 8 coordinate terms N = G/2, so N_TS != 0 exactly where +G_TS != 0. B must therefore vanish on every ordered pair with G_TS != 0 (T != S) and have unit diagonal. P120 is the +set of all 120 lines, P112 the 112 code lines. Gauge: K = a set of 8 pairwise non-orthogonal lines has B[K,K] = I +forced, which brings U_K = W_K to [I_8 | 0] (valid for every c >= 8). + +Checks (Cadical 1.5.3 through pysat; minrank_sat.py): +* c = 9 on P112: a non-symmetric B is UNSAT; B != B0 on some free pair is UNSAT; with U fixed to the E8 labels and W free, + a non-symmetric B is UNSAT; the unconstrained problem is SAT and every solution has B = B0 of rank 9. +* c = 9 on P120: non-symmetric B UNSAT; B != B0 UNSAT. +* c = 8 on the pattern of all 120 lines: UNSAT for symmetric and for non-symmetric words (and on P112). + c = 9 with non-symmetric words is SAT (calibration of the encoding). +* an exact asymmetric 2-target unit on P112: relaxing two targets (sinks w_t != u_t) with one shared extra total of 24 + sources and copy cost 1 gives B != B0 at copy cost 8*8 + 1 = 65 and window 9, N' o B = diag on all 112 x 112 entries + (rationals), the relaxed targets need 28 corrections instead of 52. +* an exact asymmetric toy: the directed 3-cycle with B non-symmetric of rank 2, decoded exactly on all 343 inputs. +Run: python3 c6_asym.py +""" +import itertools +import time +from fractions import Fraction as Fr + +import numpy as np + +from report import check, finish +from e8units import hamming_e8, e8_labels, f2_rank, first_clique, rank_q +from minrank_sat import solve_minrank, solve_asym + +# --------------------------------------------------------------------------------------------------------------- +# expected values (from the recorded runs) +EXPECTED = { + 'ncl': 8, # size of the gauge clique + 'sat': { # (set, c, mode) -> result + ('P112', 9, 'nonsym'): 'UNSAT', ('P112', 9, 'neB0'): 'UNSAT', ('P112', 9, 'fixU_nonsym'): 'UNSAT', + ('P120', 9, 'nonsym'): 'UNSAT', ('P120', 9, 'neB0'): 'UNSAT', + ('P112', 9, 'none'): 'SAT', ('P112', 9, 'fixU_none'): 'SAT', + }, + 'minrank': {('P120', 8, 'sym'): 'UNSAT', ('P120', 8, 'nonsym'): 'UNSAT', ('P120', 9, 'nonsym'): 'SAT'}, + 'rankB0': 9, + 'unit': { # d0 -> (relaxed lines, sinks, extra-total sources, corrections of a relaxed target) + 75: ([75, 76], [329, 438]), 76: ([75, 76], [329, 438]), 77: ([74, 77], [378, 389])}, + 'unit_common': dict(Qsize=24, beta_alpha=1, beta_coord=[8] * 8, rankB=9, corr_relaxed=28, corr_E8=52, copy_cost=65), + 'toy3': dict(betas=[2, 2], cst=4, rankB=2, rankN=2, inputs=343, D=(-6, -12)), +} + + +# --------------------------------------------------------------------------------------------------------------- +class Geometry: + def __init__(self): + self.L, self.G = hamming_e8() + self.U9 = e8_labels(self.G) # 120 x 9, U9 U9^T = (J + G) mod 2 + self.M0 = ((1 + self.G) % 2).astype(np.uint8) + + def port_set(self, name): + return list(range(8, 120)) if name == 'P112' else list(range(120)) + + def pattern(self, P): + """ordered pairs (i, j), i != j, of positions in P with G != 0.""" + return {(i, j) for i in range(len(P)) for j in range(len(P)) if i != j and self.G[P[i], P[j]] != 0} + + def clique(self, P, size=8): + adj = [[i != j and self.G[P[i], P[j]] != 0 for j in range(len(P))] for i in range(len(P))] + return first_clique(adj, size), first_clique(adj, size + 1) + + +def sat_checks(geo): + t_all = time.time() + got = {} + for name in ('P112', 'P120'): + P = geo.port_set(name) + pat = geo.pattern(P) + K, K9 = geo.clique(P, EXPECTED['ncl']) + assert K is not None and K9 is None, 'the largest set of pairwise non-orthogonal lines has 8 elements' + B0 = geo.M0[np.ix_(P, P)] + U = geo.U9[P] + runs = [(9, 'nonsym', None), (9, 'neB0', None)] + if name == 'P112': + runs += [(9, 'none', None), (9, 'nonsym', U), (9, 'none', U)] + for c, mode, Ufix in runs: + r = solve_asym(len(P), pat, B0, c, mode, K, U_fixed=Ufix) + key = (name, c, ('fixU_' + mode) if Ufix is not None else mode) + got[key] = r + extra = '' + if r['result'] == 'SAT': + Bm = r['B'] + extra = '; B == B0: %s, rank_F2 B = %d' % (bool((Bm == B0).all()), f2_rank(Bm.astype(np.uint8))) + print(' %s c=%d %-12s %s (%.1f s, %d vars, %d clauses)%s' % (name, c, key[2], r['result'], r['sec'], r['vars'], + r['clauses'], extra), flush=True) + ok_all = True + for key, want in EXPECTED['sat'].items(): + ok_all &= got[key]['result'] == want + names = {('P112', 9, 'nonsym'): 'C6.P112.c9.nonsym', ('P112', 9, 'neB0'): 'C6.P112.c9.neB0', + ('P112', 9, 'fixU_nonsym'): 'C6.P112.c9.fixU_nonsym', ('P120', 9, 'nonsym'): 'C6.P120.c9.nonsym', + ('P120', 9, 'neB0'): 'C6.P120.c9.neB0'} + text = {'nonsym': 'no non-symmetric pairing (B_TS != B_ST on some free pair)', + 'neB0': 'no pairing with B != B0 = (J+G) mod 2 on a free pair', + 'fixU_nonsym': 'U fixed to the E8 labels, W free: no non-symmetric pairing'} + for key, cid in names.items(): + r = got[key] + check(cid, r['result'] == EXPECTED['sat'][key], + '%s at window 9 under the E8-linear pattern: %s -> %s (%.1f s)' % (key[0], text[key[2]], r['result'], r['sec'])) + # calibration: unconstrained is SAT and forces B = B0 + P = geo.port_set('P112') + B0 = geo.M0[np.ix_(P, P)] + cal = {} + for key in (('P112', 9, 'none'), ('P112', 9, 'fixU_none')): + r = got[key] + okB = r['result'] == 'SAT' and bool((r['B'] == B0).all()) and f2_rank(r['B'].astype(np.uint8)) == EXPECTED['rankB0'] + cal[key] = okB + check('C6.P112.c9.calibration', all(cal.values()) and all(got[k]['result'] == 'SAT' for k in cal), + 'unconstrained c=9 (and with U fixed) is SAT; the solution has B = B0 = (J+G) mod 2 of F_2 rank %d' % EXPECTED['rankB0']) + print(' (window-9 SAT runs: %.1f s)' % (time.time() - t_all), flush=True) + return got + + +def window8_checks(geo): + t0 = time.time() + P = geo.port_set('P120') + off = sorted((i, j) for (i, j) in geo.pattern(P) if i < j) + K, _ = geo.clique(P, 8) + res = {} + for c, sym in ((8, True), (8, False), (9, False)): + r = solve_minrank(len(P), off, c, sym, K) + res[(c, sym)] = r + print(' pattern of 120 lines, c=%d %s: %s (%.1f s, %d vars, %d clauses)' % (c, 'sym' if sym else 'nonsym', r[0], r[1], r[2], r[3]), + flush=True) + check('C6.P120.c8.sym', res[(8, True)][0] == EXPECTED['minrank'][('P120', 8, 'sym')], + '120-line pattern (%d off-cap pairs), symmetric words at window 8: %s' % (len(off), res[(8, True)][0])) + check('C6.P120.c8.nonsym', res[(8, False)][0] == EXPECTED['minrank'][('P120', 8, 'nonsym')], + '120-line pattern, non-symmetric words at window 8: %s' % res[(8, False)][0]) + check('C6.P120.c9.minrank_calibration', res[(9, False)][0] == EXPECTED['minrank'][('P120', 9, 'nonsym')], + '120-line pattern, non-symmetric words at window 9 (the encoding finds solutions): %s (%.1f s)' + % (res[(9, False)][0], res[(9, False)][1])) + P112 = geo.port_set('P112') + off112 = sorted((i, j) for (i, j) in geo.pattern(P112) if i < j) + K112, _ = geo.clique(P112, 8) + r112 = solve_minrank(len(P112), off112, 8, False, K112) + print(' pattern of the 112 code lines, c=8 nonsym: %s (%.1f s)' % (r112[0], r112[1]), flush=True) + check('C6.P112.c8.nonsym', r112[0] == 'UNSAT', '112-line pattern, non-symmetric words at window 8: %s' % r112[0]) + print(' (window-8 runs: %.1f s)' % (time.time() - t0), flush=True) + + +# --------------------------------------------------------------------------------------------------------------- +def bits9(w): + return [(w >> (8 - j)) & 1 for j in range(9)] + + +def int9(row): + return int(''.join(str(int(x)) for x in row), 2) + + +def asym_unit(geo): + """exact 2-target asymmetric P112 unit. Relax two targets: sink w_t != u_t, decoder row n_t = L d + mu L e + alpha + where d, e are root vectors and alpha is the extra total with sources Q (coefficients -).""" + t0 = time.time() + L, G, U9 = geo.L, geo.G, geo.U9 + P = geo.port_set('P112') + v = len(P) + Lp = L[P].astype(np.int64) + u = np.array([[int(x) for x in U9[p]] for p in P], dtype=np.int64) + Wall = np.array([bits9(w) for w in range(512)], dtype=np.int64) + Zall = (Wall @ u.T) % 2 == 1 # Zall[w, t]: = 1 + uint = [int9(U9[p]) for p in P] + + def nodes_of(e, d0): + pe, pd = Lp @ e, Lp @ d0 + eperp = pe == 0 + V2 = eperp & (pd == 0) + out = [] + for t in range(v): + for w in range(1, 512): + if not Zall[w, t] or w == uint[t]: + continue + Z = Zall[w].copy() + Z[t] = False + o = np.nonzero(Z & ~eperp)[0] + mus = {Fr(-int(pd[S]), int(pe[S])) for S in o} + if len(mus) > 1: + continue + if mus: + mu = mus.pop() + else: + mu = next(Fr(k) for k in range(1, 50) if pd[t] + k * pe[t] != 0) if (pd[t] or pe[t]) else None + if mu is None or pd[t] + mu * pe[t] == 0: + continue + E = Z & eperp & ~V2 + if E[t]: + continue + out.append((t, w, mu, E)) + return out + + res = {} + for (ei, di) in [(0, 75), (0, 76), (0, 77)]: + e, d0 = L[ei], L[di] + ns = nodes_of(e, d0) + pair = None + for a in range(len(ns)): + for b in range(a + 1, len(ns)): + ta, wa, ma, Ea = ns[a] + tb, wb, mb, Eb = ns[b] + if ta != tb and not (Ea & ~Zall[wb]).any() and not (Eb & ~Zall[wa]).any() and not Ea[tb] and not Eb[ta]: + pair = (ns[a], ns[b]) + break + if pair: + break + (ta, wa, ma, Ea), (tb, wb, mb, Eb) = pair + Q = Ea | Eb + sinks = {t: uint[t] for t in range(v)} + sinks[ta], sinks[tb] = wa, wb + Wm = np.array([bits9(sinks[t]) for t in range(v)], dtype=np.int64) + B = (Wm @ u.T) % 2 + alpha = {S: -Fr(int(Lp[S] @ d0)) for S in np.nonzero(Q)[0]} + N = [[Fr(int(G[P[t], P[S]]), 2) for S in range(v)] for t in range(v)] + for t, mu in ((ta, ma), (tb, mb)): + vec = [Fr(int(d0[i])) + mu * Fr(int(e[i])) for i in range(8)] + N[t] = [sum(Fr(int(Lp[S][i])) * vec[i] for i in range(8)) + alpha.get(S, 0) for S in range(v)] + exact = all((t == S) or N[t][S] == 0 or B[t, S] == 0 for t in range(v) for S in range(v)) and \ + all(B[t, t] == 1 and N[t][t] != 0 for t in range(v)) + Qi = list(np.nonzero(Q)[0]) + beta_alpha = f2_rank(B[np.ix_([ta, tb], Qi)].astype(np.uint8)) + beta_coord = [f2_rank(B[np.ix_([t for t in range(v) if Lp[t, a] != 0 or t in (ta, tb)], + [S for S in range(v) if Lp[S, a] != 0])].astype(np.uint8)) for a in range(8)] + corr = {int(t): sum(1 for S in range(v) if S != t and N[t][S] != 0) for t in (ta, tb)} + B0 = geo.M0[np.ix_(P, P)] + res[di] = dict(relaxed=[int(P[ta]), int(P[tb])], sinks=[int(wa), int(wb)], mu=[str(ma), str(mb)], exact=bool(exact), + Qsize=len(Qi), beta_alpha=int(beta_alpha), beta_coord=[int(b) for b in beta_coord], + rankB=int(f2_rank(B.astype(np.uint8))), corr=corr, differs_from_B0=int((B != B0).sum()), + asym_pairs=int((B != B.T).sum() // 2), nodes=len(ns)) + print(' pencil e=line %d, d0=line %d: %s' % (ei, di, res[di]), flush=True) + Ex, Exc = EXPECTED['unit'], EXPECTED['unit_common'] + ok = True + for di, r in res.items(): + ok &= r['relaxed'] == Ex[di][0] and r['sinks'] == Ex[di][1] and r['exact'] and r['Qsize'] == Exc['Qsize'] \ + and r['beta_alpha'] == Exc['beta_alpha'] and r['beta_coord'] == Exc['beta_coord'] and r['rankB'] == Exc['rankB'] \ + and set(r['corr'].values()) == {Exc['corr_relaxed']} and r['differs_from_B0'] > 0 + r = res[75] + cost = sum(r['beta_coord']) + r['beta_alpha'] + check('C6.unit.exact', ok and cost == Exc['copy_cost'], + '2-target asymmetric P112 unit (3 pencils): N\' o B = diag on 112 x 112 rational entries; relaxed lines %s with sinks %s ' + '(w != u); extra total: %d sources, copy cost %d; 8 coordinate totals at 8 each; copy cost %d total, window rank B = %d' + % (r['relaxed'], r['sinks'], r['Qsize'], r['beta_alpha'], cost, r['rankB'])) + check('C6.unit.corrections', all(set(r['corr'].values()) == {Exc['corr_relaxed']} for r in res.values()), + 'relaxed targets need %s corrections instead of %d' % (sorted({c for r in res.values() for c in r['corr'].values()}), + Exc['corr_E8'])) + check('C6.unit.not_gauge', all(r['differs_from_B0'] > 0 and r['asym_pairs'] > 0 for r in res.values()), + 'B differs from B0 in %s entries and is non-symmetric on %s pairs (not a gauge of the symmetric unit)' + % ([r['differs_from_B0'] for r in res.values()], [r['asym_pairs'] for r in res.values()])) + print(' (2-target unit: %.1f s)' % (time.time() - t0), flush=True) + + +# --------------------------------------------------------------------------------------------------------------- +def toy3(): + """directed 3-cycle: U = (10,01,11), W = (10,11,01) in F_2^2, B = W U^T non-symmetric; decoder N of rank 2.""" + U = [(1, 0), (0, 1), (1, 1)] + W = [(1, 0), (1, 1), (0, 1)] + B = [[sum(a * b for a, b in zip(W[t], U[s])) % 2 for s in range(3)] for t in range(3)] + N = [[Fr(1), Fr(1), Fr(0)], [Fr(0), Fr(1), Fr(1)], [Fr(-1), Fr(0), Fr(1)]] + ok_pattern = all((N[t][s] == 0) or (t == s) or B[t][s] == 0 for t in range(3) for s in range(3)) and \ + all(B[t][t] == 1 and N[t][t] != 0 for t in range(3)) + # totals tau1 = x1 + x2 (read by ports 1, 3), tau2 = x2 + x3 (read by ports 2, 3) + terms = [({0, 2}, {0, 1}, {0: Fr(1), 2: Fr(-1)}, {0: Fr(1), 1: Fr(1)}), + ({1, 2}, {1, 2}, {1: Fr(1), 2: Fr(1)}, {1: Fr(1), 2: Fr(1)})] # (readers, sources, reader coeffs, source coeffs) + Nr = [[sum(rd.get(t, 0) * ad.get(s, 0) for _, _, rd, ad in terms) for s in range(3)] for t in range(3)] + n_inputs = 0 + exact = Nr == N + for x in itertools.product(range(-3, 4), repeat=3): + x = [Fr(a) for a in x] + tau = [sum(ad[s] * x[s] for s in ad) for _, _, _, ad in terms] + for t in range(3): + y = sum(rd.get(t, 0) * tau[j] for j, (_, _, rd, _) in enumerate(terms)) + for s in range(3): + if s != t and N[t][s] != 0: + if B[t][s] != 0: + exact = False # a lossless correction is only legal on pairs with B_TS = 0 + y -= N[t][s] * x[s] + exact &= (y == N[t][t] * x[t]) + n_inputs += 1 + betas = [f2_rank(np.array([[B[t][s] for s in sorted(A)] for t in sorted(R)], dtype=np.uint8)) for R, A, _, _ in terms] + Ex = EXPECTED['toy3'] + sym = B == [list(r) for r in zip(*B)] + rankB = f2_rank(np.array(B, dtype=np.uint8)) + rankN = rank_q([[int(x) for x in row] for row in N]) + D = (2 * 3 - 3 * sum(betas), 8 * 3 - 9 * sum(betas)) + check('C6.toy3', ok_pattern and exact and not sym and n_inputs == Ex['inputs'] and betas == Ex['betas'] + and sum(betas) == Ex['cst'] and rankB == Ex['rankB'] and rankN == Ex['rankN'] and D == Ex['D'], + 'directed 3-cycle: B = %s non-symmetric, rank_F2 B = %d, rank_Q N = %d; decoded exactly on all %d integer inputs ' + '(corrections only where B_TS = 0); betas %s, cst %d, D at s=3,9: %s (<0: formalism toy)' + % (B, rankB, rankN, n_inputs, betas, sum(betas), D)) + + +def main(): + t_start = time.time() + geo = Geometry() + sat_checks(geo) + window8_checks(geo) + asym_unit(geo) + toy3() + print('total %.1f s' % (time.time() - t_start)) + finish() + + +if __name__ == '__main__': + main() diff --git a/research/format-limits/scripts/c7_descent_price.py b/research/format-limits/scripts/c7_descent_price.py new file mode 100644 index 0000000000..419479f9ef --- /dev/null +++ b/research/format-limits/scripts/c7_descent_price.py @@ -0,0 +1,28 @@ +"""C. Per-call pricing of a paid descent on the frontier pipelines. + +c7_descent_toy.py shows exactly that a rank-1 descent of a register followed by its re-climb costs two extra rank-1 +children (2 units of data mass) in the local word. The local word runs in every call (#555: s T = 288 stage-replicas; +#568: 72 calls), so by the deficit identity m W - mass = D each descent per local word lowers D by 2 per call and adds +two rank-1 children per call. This script prices that on the published global profiles with the certified pressure +root, hosting held fixed, for one and two rank-1 descents per local word. +""" +from fractions import Fraction as Fr + +from cert import root_bracket +from report import VENDOR, check, finish, load_json, near + +EXPECTED = {('#555', 1): -5.630, ('#555', 2): -11.257, ('#568', 1): -5.646, ('#568', 2): -11.290} +e555 = load_json(VENDOR / 'pr555' / 'EXPECTED.json') +p568 = load_json(VENDOR / 'pr568' / 'PLAN.json.gz') +WORDS = {'#555': ({int(k): z for k, z in e555['nine']['profile'].items()}, 64, 10272, 288), + '#568': ({int(k): z for k, z in p568['profile'].items()}, 73, 2560, 72)} +for name, (P, m, D, calls) in WORDS.items(): + _, h0 = root_bracket(P, m, D, hi=Fr(1, 100)) + for n in (1, 2): + Q = dict(P) + Q[1] = Q.get(1, 0) + 2 * n * calls + _, h = root_bracket(Q, m, D - 2 * n * calls, hi=Fr(1, 100)) + pct = 100 * float(h / h0 - 1) + check('C7.price.%s.%d' % (name, n), near(pct, EXPECTED[name, n], 3), + '%d rank-1 descent(s) per local word, paid in all %d calls: %+.3f%% of the supplier value' % (n, calls, pct)) +finish() diff --git a/research/format-limits/scripts/c7_descent_toy.py b/research/format-limits/scripts/c7_descent_toy.py new file mode 100644 index 0000000000..5831b87179 --- /dev/null +++ b/research/format-limits/scripts/c7_descent_toy.py @@ -0,0 +1,429 @@ +"""Exact toy: one reader reads three terms at their point stations, paying for descents between the reads (n = 5). + +Setting. Labels live in F2^5 with the standard dot product. Three term anchors u_a, u_b, u_c are odd and pairwise +orthogonal; a "double" reader t has an odd label u_t orthogonal to all three anchors and reads all three terms; for each +term j a "single" reader r_j reads only term j. Term j has a source x_j stored at a 2-dimensional nondegenerate frame +f_j = containing u_j. The natural readers of term j are all odd vectors orthogonal to u_j; they span u_j^perp, +so the only frame orthogonal to all of them is : the only common read frame of term j is the point station +(checked by enumeration). The operator (identical in all networks) is + y_r -> T_{u_r^perp} ( l_y + sum_j q_rj l_{x_j} ), x_j -> T_FULL l_{x_j}, +with fixed dyadic Gaussian coefficients q_rj, on the 7 logical registers (x_a, x_b, x_c, y_t, y_a, y_b, y_c). +T_F is the canonical Clifford frame operator of a subspace F, d(A, B) = dim A + dim B - 2 dim(A cap B) the frame +distance; the charged rank of a step A -> B is the Clifford rank of T_B T_A^{-1} (clifford_exact.lower_child). + +Networks (copy C_j of x_j is dropped f_j -> at cost 1 each, except in STD where noted): + STD : nesting kept, only term a is read at a point station; C_b, C_c drop to 0 (cost 2 each); t and the single + readers r_b, r_c read b, c at 0 first, then t climbs 0 -> (reads a) -> u_t^perp. + CLONE : nesting kept by clones: t climbs 0 -> [a] -> [b, read from a clone of C_b raised + -> ] -> [c, from a clone raised -> ] -> u_t^perp. + DESC : t reads at the point stations in turn: 0 -> [a] -> (one NON-comparable step, rank 2) [b] -> + (rank 2) [c] -> u_t^perp. + DESC0 : as DESC but each descent goes through 0: -> 0 -> -> 0 -> . +Checks: the whole linear map is exactly equal to the intended operator (exact Gaussian-dyadic arithmetic) on all +7 * 32 = 224 basis columns, in every network; every transition has Clifford child rank == d(A, B); the charged mass +by role is compared with the closed forms (+2 per descent between two lines, 2(k-1) for k point stations, STD vs DESC). +""" +import itertools +import random +import sys + +import numpy as np + +from report import check, finish, main_file + +sys.path.insert(0, str(main_file('research/direct-delivery504-global/vendor/clifford/clifford_exact.py').parent)) +import clifford_exact as ce # noqa: E402 (the repository's exact Clifford compiler, unmodified) + +# ---------------------------------------------------------------------------------------------------------------- +# Expected values (from the exact run of the toy; every one is re-derived below and compared). +EXPECTED = { + 'instance': dict(anchors=[0b00111, 0b01011, 0b01110], u_t=0b01101, singles=[0b01000, 0b00100, 0b00001], + frames=[[0b00111, 0b01000], [0b01011, 0b00100], [0b01110, 0b00001]]), + 'readers_per_term': 8, # odd vectors orthogonal to u_j + 'common_frames': [[0, 7], [0, 11], [0, 14]], # {z : z.r = 0 for all natural readers r} = {0, u_j} + 'columns': 224, # 7 registers x 32 basis vectors + # transitions (role, dim A, dim B, child rank, distance d), source-register steps omitted (3 steps 2 -> 5, rank 3) + 'transitions': { + 'STD': [('copy-drop', 2, 1, 1, 1), ('copy-drop', 2, 0, 2, 2), ('copy-drop', 2, 0, 2, 2), ('t', 0, 1, 1, 1), + ('t', 1, 4, 3, 3), ('single', 0, 4, 4, 4), ('single', 0, 4, 4, 4), ('single', 0, 1, 1, 1), + ('single', 1, 4, 3, 3)], + 'CLONE': [('copy-drop', 2, 1, 1, 1), ('copy-drop', 2, 1, 1, 1), ('copy-drop', 2, 1, 1, 1), ('clone', 1, 2, 1, 1), + ('clone', 1, 3, 2, 2), ('t', 0, 1, 1, 1), ('t', 1, 2, 1, 1), ('t', 2, 3, 1, 1), ('t', 3, 4, 1, 1), + ('single', 0, 1, 1, 1), ('single', 1, 4, 3, 3), ('single', 0, 1, 1, 1), ('single', 1, 4, 3, 3), + ('single', 0, 1, 1, 1), ('single', 1, 4, 3, 3)], + 'DESC': [('copy-drop', 2, 1, 1, 1), ('copy-drop', 2, 1, 1, 1), ('copy-drop', 2, 1, 1, 1), ('t', 0, 1, 1, 1), + ('t-DESCENT', 1, 1, 2, 2), ('t-DESCENT', 1, 1, 2, 2), ('t', 1, 4, 3, 3), ('single', 0, 1, 1, 1), + ('single', 1, 4, 3, 3), ('single', 0, 1, 1, 1), ('single', 1, 4, 3, 3), ('single', 0, 1, 1, 1), + ('single', 1, 4, 3, 3)], + 'DESC0': [('copy-drop', 2, 1, 1, 1), ('copy-drop', 2, 1, 1, 1), ('copy-drop', 2, 1, 1, 1), ('t', 0, 1, 1, 1), + ('t-DESCENT', 1, 0, 1, 1), ('t-reclimb', 0, 1, 1, 1), ('t-DESCENT', 1, 0, 1, 1), + ('t-reclimb', 0, 1, 1, 1), ('t', 1, 4, 3, 3), ('single', 0, 1, 1, 1), ('single', 1, 4, 3, 3), + ('single', 0, 1, 1, 1), ('single', 1, 4, 3, 3), ('single', 0, 1, 1, 1), ('single', 1, 4, 3, 3)], + }, + # charged mass by role, and total + 'mass': { + 'STD': ({'copy-drop': 5, 't': 4, 'single': 12, 'source': 9}, 30), + 'CLONE': ({'copy-drop': 3, 'clone': 3, 't': 4, 'single': 12, 'source': 9}, 31), + 'DESC': ({'copy-drop': 3, 't': 4, 't-DESCENT': 4, 'single': 12, 'source': 9}, 32), + 'DESC0': ({'copy-drop': 3, 't': 4, 't-DESCENT': 2, 't-reclimb': 2, 'single': 12, 'source': 9}, 32), + }, + 'reader_mass': {'STD': 4, 'CLONE': 4, 'DESC': 8, 'DESC0': 8}, # all roles starting with 't' + 'nested_minimum': 4, # dim u_t^perp = n - 1: path 0 -> -> u_t^perp + 'descent_mass_each': 2, # one descent between two lines: direct or via 0 + 'k_stations_extra': {1: 0, 2: 2, 3: 4}, # reader at k point stations pays 2(k-1) + 'desc_vs_std': dict(cst=-2, reader=4, net=2), +} + +n = 5 +N = 1 << n + + +def par(x): + return bin(x).count('1') & 1 + + +def span(vs): + out = {0} + for v in vs: + out |= {o ^ v for o in out} + return out + + +def perp(vs): + return [z for z in range(N) if all(par(z & v) == 0 for v in vs)] + + +def basis(vs): + b = [] + for v in vs: + if ce.rank(b + [v]) > len(b): + b.append(v) + return b + + +def dim(A): + return len(basis(A)) + + +def meet(A, B): + sA = span(basis(A)) + return [z for z in span(basis(B)) if z in sA] + + +def dist(A, B): + """frame distance d(A,B) = dim A + dim B - 2 dim(A cap B).""" + return dim(A) + dim(B) - 2 * dim(meet(A, B)) + + +def nondeg(F): + b = basis(F) + G = [[par(x & y) for y in b] for x in b] + rows = [sum(G[i][j] << j for j in range(len(b))) for i in range(len(b))] + return ce.rank(rows) == len(b) + + +def T(F): + return ce.canonical_frame(n, tuple(basis(F))) + + +# ---- exact Gaussian-dyadic matrices: (Re int array, Im int array, exponent e), value = (Re + i Im) / 2^e +def mat(op): + E = 0 + raw = [] + for bidx in range(N): + vec, den = op.zero_state(bidx) + raw.append((vec, den)) + E = max(E, den) + R = np.zeros((N, N), dtype=object) + I = np.zeros((N, N), dtype=object) + for j, (vec, den) in enumerate(raw): + s = 1 << (E - den) + for i, (a, c) in enumerate(vec): + R[i, j] = a * s + I[i, j] = c * s + return (R, I, E) + + +def norm(M): + R, I, E = M + while E > 0 and all(int(v) % 2 == 0 for v in R.flat) and all(int(v) % 2 == 0 for v in I.flat): + R = R // 2 + I = I // 2 + E -= 1 + return (R, I, E) + + +def mm(A, B): + (a, b, e), (c, d, f) = A, B + return norm((a.dot(c) - b.dot(d), a.dot(d) + b.dot(c), e + f)) + + +def madd(A, B): + (a, b, e), (c, d, f) = A, B + E = max(e, f) + return norm((a * (1 << (E - e)) + c * (1 << (E - f)), b * (1 << (E - e)) + d * (1 << (E - f)), E)) + + +def scal(q, A): # q = (re, im, exp) is the dyadic Gaussian number (re + i im) / 2^exp + (qr, qi, qe) = q + (a, b, e) = A + return norm((qr * a - qi * b, qr * b + qi * a, e + qe)) + + +def eq(A, B): + A = norm(A) + B = norm(B) + return A[2] == B[2] and (A[0] == B[0]).all() and (A[1] == B[1]).all() + + +ZERO = (np.zeros((N, N), dtype=object), np.zeros((N, N), dtype=object), 0) +ID = (np.eye(N, dtype=object) * 1, np.zeros((N, N), dtype=object), 0) +cache = {} + + +def Tm(F): + k = tuple(sorted(span(basis(F)))) + if k not in cache: + cache[k] = (mat(T(F)), mat(T(F).adjoint())) + return cache[k] + + +# ---- instance search (deterministic, seeded): anchors odd and pairwise orthogonal, u_t odd orthogonal to all of them, +# one single reader per term, f_j = nondegenerate +odd = [v for v in range(1, N) if par(v)] +inst = None +rng = random.Random(24) +trip = list(itertools.combinations(odd, 3)) +rng.shuffle(trip) +for ua, ub, uc in trip: + if any(bin(u).count('1') == 1 for u in (ua, ub, uc)): + continue # avoid coordinate anchors + if par(ua & ub) or par(ua & uc) or par(ub & uc): + continue + ts = [t for t in odd if not par(t & ua) and not par(t & ub) and not par(t & uc)] + if not ts: + continue + ut = ts[0] + + def single(u, others): + c = [r for r in odd if not par(r & u) and all(par(r & o) for o in others)] + return c[0] if c else None + ra, rb, rc = single(ua, [ub, uc]), single(ub, [ua, uc]), single(uc, [ua, ub]) + if None in (ra, rb, rc): + continue + ok = True + for u in (ua, ub, uc): + R = [r for r in odd if not par(r & u)] # the full natural reader set of the term + if set(perp(R)) != {0, u}: + ok = False + if not ok: + continue + fs = [] + for u in (ua, ub, uc): + w = [w for w in range(1, N) if w not in span([ua, ub, uc]) and nondeg([u, w]) and dim([u, w]) == 2] + fs.append([u, w[0]]) + inst = (ua, ub, uc, ut, ra, rb, rc, fs) + break +assert inst, 'no instance found' +ua, ub, uc, ut, ra, rb, rc, fs = inst +U = [ua, ub, uc] +FULL = list(range(1, N)) + +# ---- C7.c0-station +common = [] +n_read = [] +for u in U: + R = [r for r in odd if not par(r & u)] + n_read.append(len(R)) + common.append(sorted(perp(R))) +inst_got = dict(anchors=U, u_t=ut, singles=[ra, rb, rc], frames=fs) +frames_ok = all(nondeg(F) for F in [[ua], [ub], [uc], [ua, ub], [ua, ub, uc], perp([ut])] + fs) +orth_ok = (all(par(u) == 1 for u in U + [ut]) and not par(ua & ub) and not par(ua & uc) and not par(ub & uc) + and all(not par(ut & u) for u in U)) +check('C7.c0-station', + common == EXPECTED['common_frames'] and n_read == [EXPECTED['readers_per_term']] * 3 and orth_ok and frames_ok + and inst_got == EXPECTED['instance'], + 'anchors %s, u_t %s; each term has %d natural readers whose common read frames are %s = {0, u_j}: only the point ' + 'station ' % ([format(u, '05b') for u in U], format(ut, '05b'), n_read[0], common)) + +# ---- the four networks +regs = ['x0', 'x1', 'x2', 'yt', 'ya', 'yb', 'yc'] +reads = {'yt': [0, 1, 2], 'ya': [0], 'yb': [1], 'yc': [2]} +ulab = {'yt': ut, 'ya': ra, 'yb': rb, 'yc': rc} +Q = {('yt', 0): (1, 0, 0), ('yt', 1): (-1, 0, 0), ('yt', 2): (1, 1, 1), ('ya', 0): (3, 0, 1), ('yb', 1): (0, 1, 0), + ('yc', 2): (-1, 2, 2)} # dyadic Gaussian q = (re + i im) / 2^e + + +def run(mode): + log = [] + # state: register -> {input register: matrix}; physical x_j = T_{f_j} l_{x_j}; targets start at frame 0 + S = {r: {} for r in regs} + for j in range(3): + S['x%d' % j] = {'x%d' % j: Tm(fs[j])[0]} + for y in ('yt', 'ya', 'yb', 'yc'): + S[y] = {y: ID} + + def step(reg, A, B, who): + if basis(A) == basis(B) and span(basis(A)) == span(basis(B)): + return + op = T(A).adjoint().then(T(B)) if basis(A) else T(B) + r = ce.lower_child(op)[0]['rank'] + dd = dist(A, B) + log.append((who, dim(A), dim(B), r, dd)) + M = mm(Tm(B)[0], Tm(A)[1]) + S[reg] = {k: mm(M, v) for k, v in S[reg].items()} + + def addto(dst, src, q): + for k, v in S[src].items(): + S[dst][k] = madd(S[dst].get(k, ZERO), scal(q, v)) + + def copy(new, src): + S[new] = {k: v for k, v in S[src].items()} + + for j in range(3): + copy('cp%d' % j, 'x%d' % j) + if mode == 'STD': + step('cp0', fs[0], [ua], 'copy-drop') # term a cheap + step('cp1', fs[1], [], 'copy-drop') + step('cp2', fs[2], [], 'copy-drop') + addto('yt', 'cp1', Q[('yt', 1)]) # reads of b, c at frame 0 + addto('yt', 'cp2', Q[('yt', 2)]) + addto('yb', 'cp1', Q[('yb', 1)]) + addto('yc', 'cp2', Q[('yc', 2)]) + step('yt', [], [ua], 't') + addto('yt', 'cp0', Q[('yt', 0)]) + step('yt', [ua], perp([ut]), 't') + step('yb', [], perp([rb]), 'single') + step('yc', [], perp([rc]), 'single') + else: + for j, u in enumerate(U): + step('cp%d' % j, fs[j], [u], 'copy-drop') + if mode in ('DESC', 'DESC0'): + step('yt', [], [ua], 't') + addto('yt', 'cp0', Q[('yt', 0)]) + if mode == 'DESC': + step('yt', [ua], [ub], 't-DESCENT') + else: + step('yt', [ua], [], 't-DESCENT') + step('yt', [], [ub], 't-reclimb') + addto('yt', 'cp1', Q[('yt', 1)]) + if mode == 'DESC': + step('yt', [ub], [uc], 't-DESCENT') + else: + step('yt', [ub], [], 't-DESCENT') + step('yt', [], [uc], 't-reclimb') + addto('yt', 'cp2', Q[('yt', 2)]) + step('yt', [uc], perp([ut]), 't') + elif mode == 'CLONE': + copy('K1', 'cp1') + copy('K2', 'cp2') # clones at the bottom frame (equal-frame copy, no drop) + step('K1', [ub], [ua, ub], 'clone') + step('K2', [uc], [ua, ub, uc], 'clone') + step('yt', [], [ua], 't') + addto('yt', 'cp0', Q[('yt', 0)]) + step('yt', [ua], [ua, ub], 't') + addto('yt', 'K1', Q[('yt', 1)]) + step('yt', [ua, ub], [ua, ub, uc], 't') + addto('yt', 'K2', Q[('yt', 2)]) + step('yt', [ua, ub, uc], perp([ut]), 't') + step('yb', [], [ub], 'single') + addto('yb', 'cp1', Q[('yb', 1)]) + step('yb', [ub], perp([rb]), 'single') + step('yc', [], [uc], 'single') + addto('yc', 'cp2', Q[('yc', 2)]) + step('yc', [uc], perp([rc]), 'single') + step('ya', [], [ua], 'single') + addto('ya', 'cp0', Q[('ya', 0)]) + step('ya', [ua], perp([ra]), 'single') + for j in range(3): + step('x%d' % j, fs[j], FULL, 'source') + return S, log + + +def expected(): + E = {} + for j in range(3): + E['x%d' % j] = {'x%d' % j: Tm(FULL)[0]} + for y, js in reads.items(): + P = Tm(perp([ulab[y]]))[0] + dct = {y: P} + for j in js: + dct['x%d' % j] = scal(Q[(y, j)], P) + E[y] = dct + return E + + +EXP = expected() +res = {} +for mode in ('STD', 'CLONE', 'DESC', 'DESC0'): + S, log = run(mode) + # column (input register k, basis vector) is exact iff every output register's block for k matches the intended + # operator (blocks absent from the intended operator must be zero) + ncols = 0 + for k in regs: + if all(eq(S[r].get(k, ZERO), EXP[r].get(k, ZERO)) for r in regs): + ncols += N + by = {} + for who, a, b, r, dd in log: + by[who] = by.get(who, 0) + r + res[mode] = dict(cols=ncols, log=log, by=by, total=sum(by.values()), + shown=[x for x in log if x[0] != 'source'], + reader=sum(v for k, v in by.items() if k.startswith('t'))) + check('C7.exact-%s' % mode.lower(), ncols == EXPECTED['columns'], + '%s: whole operator equals the intended one on %d/%d basis columns of the 7 logical registers' + % (mode, ncols, EXPECTED['columns'])) + +all_eq = all(r == dd for m in res.values() for _, _, _, r, dd in m['log']) +shown_ok = all(m['shown'] == EXPECTED['transitions'][mode] for mode, m in res.items()) +n_trans = sum(len(m['log']) for m in res.values()) +# the two descents of DESC are steps between two distinct lines -> -> : non-comparable, child rank 2 +noncomp = [x for x in res['DESC']['log'] if x[0] == 't-DESCENT'] +lines_meet_zero = all(len(meet([a], [b])) == 1 for a, b in ((ua, ub), (ub, uc))) +check('C7.child-eq-d', all_eq and shown_ok and len(noncomp) == 2 and lines_meet_zero + and all((a, b, r, dd) == (1, 1, 2, 2) for _, a, b, r, dd in noncomp), + 'lower_child rank == d(A,B) on all %d transitions of the four networks, including the %d non-comparable ' + 'line-to-line descents (dim 1 -> 1, meet 0) of rank 2' % (n_trans, len(noncomp))) + +# ---- descents: +2 per line-to-line descent, direct or through 0 +per_desc = {'DESC': sum(r for w_, a, b, r, dd in res['DESC']['log'] if w_ == 't-DESCENT') // 2, + 'DESC0': sum(r for w_, a, b, r, dd in res['DESC0']['log'] if w_ in ('t-DESCENT', 't-reclimb')) // 2} +check('C7.descent-mass', + per_desc == {'DESC': EXPECTED['descent_mass_each'], 'DESC0': EXPECTED['descent_mass_each']}, + '+%d data mass per rank-1 descent -> : direct %d (one rank-2 step), via 0 %d (two rank-1 steps), identical' + % (EXPECTED['descent_mass_each'], per_desc['DESC'], per_desc['DESC0'])) + + +# ---- a reader at k point stations pays 2(k-1) beyond the nested minimum +def path_mass(stations): + tot = 0 + for A, B in zip(stations, stations[1:]): + op = T(A).adjoint().then(T(B)) if basis(A) else T(B) + r = ce.lower_child(op)[0]['rank'] + assert r == dist(A, B) + tot += r + return tot + + +extra = {} +for k in (1, 2, 3): + path = [[]] + [[u] for u in U[:k]] + [perp([ut])] + extra[k] = path_mass(path) - EXPECTED['nested_minimum'] +check('C7.reader-stations', + extra == EXPECTED['k_stations_extra'] and res['DESC']['reader'] == EXPECTED['nested_minimum'] + extra[3] + and all(extra[k] == 2 * (k - 1) for k in extra), + 'reader path 0 -> -> ... -> -> u_t^perp costs %d + 2(k-1): extra %s for k = 1, 2, 3 (DESC: %d = %d + 4)' + % (EXPECTED['nested_minimum'], extra, res['DESC']['reader'], EXPECTED['nested_minimum'])) + +# ---- charged mass by role; DESC vs STD +mass_ok = all((m['by'], m['total']) == EXPECTED['mass'][mode] for mode, m in res.items()) +reader_ok = {mode: m['reader'] for mode, m in res.items()} == EXPECTED['reader_mass'] +cst = res['DESC']['by']['copy-drop'] - res['STD']['by']['copy-drop'] +rd = res['DESC']['reader'] - res['STD']['reader'] +check('C7.desc-vs-std', + mass_ok and reader_ok and (cst, rd, cst + rd) == tuple(EXPECTED['desc_vs_std'][k] for k in ('cst', 'reader', 'net')), + 'charged totals STD %d, CLONE %d, DESC %d, DESC0 %d; reader path mass %s; DESC vs STD: copy-drop mass %+d, reader ' + '%+d, net %+d (2 cheap terms earned, 2 descents paid)' + % (res['STD']['total'], res['CLONE']['total'], res['DESC']['total'], res['DESC0']['total'], + {m: v['reader'] for m, v in res.items()}, cst, rd, cst + rd)) + +finish() diff --git a/research/format-limits/scripts/cert.py b/research/format-limits/scripts/cert.py new file mode 100644 index 0000000000..351fbd107c --- /dev/null +++ b/research/format-limits/scripts/cert.py @@ -0,0 +1,133 @@ +"""Certified (rational interval) pressure-root tools. +g_q(r) = r*((m/r)^q - 1). Root of sum_i z_i g_q(r_i) = D (increasing in q). +All transcendental values are enclosed by rational intervals (Fraction endpoints, outward rounding).""" +from fractions import Fraction as Fr +import math + +DEN = 10**45 # outward rounding grid + + +def rd(x): # round down to grid + return Fr(math.floor(x * DEN), DEN) + + +def ru(x): + return Fr(math.ceil(x * DEN), DEN) + + +def ln_iv(x): + """enclosure of ln(x), x = Fraction > 0, via ln x = 2 atanh(z), z=(x-1)/(x+1); reduce by powers of 2.""" + x = Fr(x) + assert x > 0 + if x == 1: + return (Fr(0), Fr(0)) + # reduce: x = 2^e * y, y in [1/sqrt2, sqrt2] (use [2/3, 4/3]-ish via loop) + e = 0 + while x > Fr(4, 3): + x /= 2; e += 1 + while x < Fr(2, 3): + x *= 2; e -= 1 + lo2, hi2 = LN2 + lo, hi = _atanh2(x) + return (rd(lo + e * (lo2 if e >= 0 else hi2)), ru(hi + e * (hi2 if e >= 0 else lo2))) + + +def _atanh2(x): + z = (x - 1) / (x + 1) + az = abs(z) + s = Fr(0); t = z; k = 0 + N = 40 + for k in range(N): + s += t / (2 * k + 1) + t *= z * z + # tail bound: |sum_{k>=N} z^(2k+1)/(2k+1)| <= |z|^(2N+1)/((2N+1)(1-z^2)) + tail = az ** (2 * N + 1) / ((2 * N + 1) * (1 - z * z)) + s = 2 * s; tail = 2 * tail + return (rd(s - tail), ru(s + tail)) + + +def _ln2(): + # ln 2 = 2 atanh(1/3) + z = Fr(1, 3); s = Fr(0); t = z + N = 60 + for k in range(N): + s += t / (2 * k + 1); t *= z * z + tail = z ** (2 * N + 1) / ((2 * N + 1) * (1 - z * z)) + return (rd(2 * s - 2 * tail), ru(2 * s + 2 * tail)) + + +LN2 = _ln2() + + +def expm1_iv(lo, hi): + """enclosure of e^y - 1 for y in [lo,hi], 0 <= lo <= hi <= 1.""" + assert 0 <= lo <= hi <= 2 + N = 30 + + def ser(y): + s = Fr(0); t = Fr(1) + for i in range(1, N + 1): + t = t * y / i; s += t + return s + slo = ser(lo) # all terms >= 0 -> lower bound + shi = ser(hi) + 8 * hi ** (N + 1) / math.factorial(N + 1) # tail <= y^(N+1)/(N+1)! * e^y, e^y<=8 (y<=2) + return (rd(slo), ru(shi)) + + +def g_iv(r, m, q): + """enclosure of r*((m/r)^q - 1), q Fraction >= 0.""" + if r >= m: + return (Fr(0), Fr(0)) if r == m else None + l_lo, l_hi = ln_iv(Fr(m) / r) + lo, hi = expm1_iv(q * l_lo, q * l_hi) + return (r * lo, r * hi) + + +def F_iv(prof, m, q): + """prof: dict rank -> count (Fractions/ints allowed), returns enclosure of sum z g_q(r).""" + lo = Fr(0); hi = Fr(0) + for r, z in prof.items(): + if z == 0: + continue + a, b = g_iv(Fr(r), Fr(m), Fr(q)) + lo += z * a; hi += z * b + return (rd(lo), ru(hi)) + + +def root_bracket(prof, m, D, lo=Fr(0), hi=Fr(1, 10), iters=60): + """returns (qlo, qhi) with F(qlo) < D (certified via upper enclosure) and F(qhi) >= D (via lower enclosure): + the true root lies in [qlo, qhi]. qhi is a certified UPPER bound of the root.""" + D = Fr(D) + assert F_iv(prof, m, hi)[0] >= D, 'hi too small' + for _ in range(iters): + mid = rd((lo + hi) / 2) + flo, fhi = F_iv(prof, m, mid) + if flo >= D: + hi = mid + elif fhi < D: + lo = mid + else: + break + return lo, hi + + +def cost_iv(prof, m): + """enclosure of Cost = sum z r ln(m/r).""" + lo = Fr(0); hi = Fr(0) + for r, z in prof.items(): + if z == 0 or r >= m: + continue + a, b = ln_iv(Fr(m) / r) + lo += z * r * a; hi += z * r * b + return lo, hi + + +if __name__ == '__main__': + # self-test against floats + for x in (Fr(64, 7), Fr(73, 8), Fr(100, 3), Fr(3, 2), Fr(1, 5)): + lo, hi = ln_iv(x) + assert lo <= Fr(math.log(x)) + Fr(1, 10**12) and hi >= Fr(math.log(x)) - Fr(1, 10**12), x + assert hi - lo < Fr(1, 10**40), (x, float(hi - lo)) + print('ln ok', float(LN2[1] - LN2[0])) + lo, hi = expm1_iv(Fr(1, 100), Fr(1, 100)) + print('expm1(0.01)', float(lo), math.expm1(0.01), float(hi - lo)) diff --git a/research/format-limits/scripts/d1_cover_numbers.py b/research/format-limits/scripts/d1_cover_numbers.py new file mode 100644 index 0000000000..406a1012f8 --- /dev/null +++ b/research/format-limits/scripts/d1_cover_numbers.py @@ -0,0 +1,371 @@ +"""D1. Design-free cover numbers at the two ends of a register chain (complex P112 and bit E8), and the helper counts they force. + +Setting. A register carries a monotone chain of frames (subspaces) and a gate acts on registers that stand in a common +frame. In a lossless transfer x_s -> y_q between a source s and a terminal q with s orthogonal to q, the information crosses +every level d exactly once, inside one register's climb from a frame a (dim a < d) into a frame b (dim b >= d); such a +climb contributes a rank-one term with support (sources lying in a) x (terminals lying in b^perp). + +* Source end (level 2). A source s starts in the one-dimensional frame . A register standing at and climbing + into a frame b = serves the readers t of s (t perp s) with t . w = 0: a "hyperplane section" + {t perp s, t.w = 0} of the set T(s) of readers of s. Every reader of s is served by some crossing register, so the + sections of the crossing registers cover T(s); the cover number of s is the least number of proper sections covering T(s). +* Terminal end (level h-1 -> h). The same statement for the sources lying in q^perp, covered by hyperplane sections of q^perp. + +Each source (terminal) is served by its own register x_s (y_q) and by other registers, so with cover number c every source +needs c-1 foreign crossing registers. Data registers (x and y) can supply only a few of these; the rest are helpers. + +This script computes the cover numbers exactly on the two units + * complex P112 (PR #531): readers = the 52 ports orthogonal to a port; frames = F_2-subspaces of F_2^9; + * bit E8 (PR #555): readers of a source = the 63 lines of E7 orthogonal to it; frames = subspaces of Q^8; the sections are + the hyperplane flats of E7 (all lines of E7 inside a hyperplane of the 7-space), +and derives the lower bounds on the number of helper registers that follow from them. Upstream: PR #531 (complex word, +geometry), PR #555 (bit word). +""" +import sys + +sys.dont_write_bytecode = True + +from collections import Counter, defaultdict +from fractions import Fraction as Fr + +import numpy as np +from scipy.sparse import csr_matrix +from scipy.sparse.csgraph import connected_components + +import d_geometry as dg +from report import check, finish + +# --------------------------------------------------------------------------------------------------------------- +# Expected values (hard-coded; each is the exact outcome of the computation below) +# --------------------------------------------------------------------------------------------------------------- +EXPECTED = dict( + # complex P112 (F_2^9, 112 ports, 52 readers per port) + cx_readers=52, + cx_max_section=32, # largest section {t perp s, t.w = 0} over all sources and all w (any frame) + cx_closed_max_section=26, # same when the frame must be spanned by ports (w or u_s + w a port) + cx_cover2=112, # sources whose 52 readers are covered by two proper sections (any frames and closed frames) + # census of the word of PR #531 + c531_crossings_per_source={3: 112}, # every source has exactly 3 level-2 crossings + c531_class_mix={'h': 224, 'x': 112}, # = X_s plus two helpers per source (224 helper crossings) + c531_frame_dims={2: 336}, # all 336 post-crossing frames are 2-dimensional + c531_section=20, # each such frame serves 20 readers + c531_level8={'h': 266, 'y': 112, 'x': 14}, # entries into 8-dimensional frames by register class + c531_nonport_rank1_frames=7, # frames of dim >= 2 are all port-spanned; 7 rank-1 frames are not ports + # drop-free demand of the word of PR #531 + demand_nnz=5824, demand_minus_half=3920, demand_plus_half=1904, + # bit E8 (63 readers of a source) + bit_flats_sampled=2258, # 60000 random 6-subsets (seed 1) of E7: legacy sampled census + bit_flats_sampled_hist={10: 232, 13: 589, 16: 683, 21: 663, 30: 63, 36: 28}, + bit_flats=8821, # exhaustive census of the hyperplane flats of E7 + bit_flats_hist={10: 5040, 13: 2016, 16: 1008, 21: 666, 30: 63, 36: 28}, + bit_union2=52, # largest union of two hyperplane flats + bit_leftover=11, # 63 - 52 lines left uncovered by the best two sections + bit_cover_number=3, + bit_term_live_leftover_min=6, # worst live-source leftover after any two sections, over all 120 terminals + # shipped word of PR #555 + bit555_level2={'x': 111, 'y': 10, 'h': 285}, + bit555_per_source_min=3, + bit555_per_source_hist={3: 78, 4: 6, 5: 17, 6: 7, 7: 3}, + bit555_level7={'x': 108, 'y': 111, 'h': 252}, + bit555_R=439, + # forced helper counts + bit_sink=212, bit_strict=138, cx_sink=107, cx_sink_closed=108, cx_strict=0, +) +# The seven maximal parabolic types J of E7 (delete one node of the Dynkin diagram): the flat of rank 6 is the root subsystem of +# type J; its connected components (lines joined when not orthogonal) have the listed numbers of lines. There are +# |W(E7)| / (2 |W_J|) flats of type J (the number of parabolic subgroups conjugate to W_J is |W(E7)| / |N(W_J)|, and |N(W_J)| = 2 |W_J| for all seven types, as the +# census below confirms). +W_E7 = 2903040 # order of the Weyl group of E7 +TYPES = { # component sizes (in lines) -> (name, |W_J|) + (36,): ('E6', 51840), (30,): ('D6', 23040), (21,): ('A6', 5040), (20, 1): ('D5+A1', 1920 * 2), + (15, 1): ('A5+A1', 720 * 2), (10, 3): ('A4+A2', 120 * 6), (6, 3, 1): ('A3+A2+A1', 24 * 6 * 2), +} + + +# --------------------------------------------------------------------------------------------------------------- +# Complex P112: census of the word of PR #531 +# --------------------------------------------------------------------------------------------------------------- +def census531(): + """replay the frame assignments of the word of PR #531 (phases precondition, A, cut, B, cleanup). A register moved + from a one-dimensional frame into a frame F of dimension >= 2 is a level-2 crossing for the source s; its section is + the set of readers t of s with t perp F. Also records entries into 8-dimensional frames and the types of all frames.""" + d = dg.word531() + V = 112 + ports = d['ports'] + red, inspan, pd = dg.f2_reduce, dg.f2_inspan, dg.pdot + cls = lambda r: 'x' if r < V else 'y' if r < 2 * V else 'h' + cur = {int(k): red(v) for k, v in d['start_extra'].items()} + for s in range(V): + cur[s] = [ports[s]] + port_spanned = lambda B: len(red([p for p in ports if inspan(p, B)])) == len(B) + cnt = defaultdict(list) + c8 = Counter() + for ph in ['precondition', 'A', 'cut', 'B', 'cleanup']: + for e in d.get(ph, []): + regs = (e[1], e[2]) if e[0] == 'add' else (e[1],) + F = e[-1] + if F is None: + continue + Fb = red(F) + for r in regs: + c = cur.get(r, []) + if len(c) == 1 < len(Fb): + s = next((i for i in range(V) if inspan(ports[i], c)), None) + if s is not None: + sec = sum(1 for t in range(V) if not pd(ports[t], ports[s]) and all(not pd(ports[t], f) for f in Fb)) + cnt[s].append((cls(r), len(Fb), sec, port_spanned(Fb))) + if len(c) < 8 <= len(Fb) and len(Fb) == 8: + c8[cls(r)] += 1 + cur[r] = Fb + frames = set() + for ph in ['precondition', 'A', 'B', 'cleanup']: + for e in d.get(ph, []): + if e[-1] is not None: + frames.add(tuple(sorted(e[-1]))) + for v in d['start_extra'].values(): + frames.add(tuple(sorted(v))) + ftype = Counter() + for F in frames: + B = red(list(F)) + ftype[(len(B), port_spanned(B))] += 1 + return cnt, c8, ftype + + +def demand531(): + """the drop-free demand of the word of PR #531: replay the additions and scalings of the phases precondition, A, B, + cleanup over Q with the decoder copies (phase cut) removed, tracking for each register its coefficient vector on the + 112 sources. Returns the matrix L[t][s] = coefficient of x_s in y_t and the replay sanity flags.""" + d = dg.word531() + V = 112 + n = 2 * V + d['report']['R'] + ports = d['ports'] + val = [{} for _ in range(n)] + for s in range(V): + val[s] = {s: Fr(1)} + for ph in ['precondition', 'A', 'B', 'cleanup']: + for e in d.get(ph, []): + if e[0] == 'add': + _, a, b, num, den, _F = e + c = Fr(num, den) + for k, x in val[b].items(): + nv = val[a].get(k, 0) + c * x + if nv: + val[a][k] = nv + else: + val[a].pop(k, None) + elif e[0] == 'scale': + _, r, num, den, _F = e + c = Fr(num, den) + val[r] = {k: x * c for k, x in val[r].items()} + else: + raise ValueError(e) + L = {t: val[V + t] for t in range(V)} + restored = all(val[s] == {s: Fr(1)} for s in range(V)) + helpers_free = all(not val[r] for r in range(2 * V, n)) + return L, ports, restored, helpers_free + + +# --------------------------------------------------------------------------------------------------------------- +# Bit E8: hyperplane flats, covers, terminal side, shipped word +# --------------------------------------------------------------------------------------------------------------- +def sampled_flats(): + """the earlier sampled census: 60000 random 6-subsets of the 63 lines (numpy default_rng(1)); each independent + 6-subset together with s0 spans a hyperplane of R^8 whose E7 lines form a flat. Returns the set of line-id frozensets.""" + E = dg.e8() + s0 = E['srcid'][0] + LN = E['L'].astype(float) + P = np.array(dg.e7_of(s0)) + rng = np.random.default_rng(1) + secs = set() + for _ in range(60000): + S = rng.choice(P, 6, replace=False) + M = np.vstack([LN[S], LN[s0][None, :]]) + if np.linalg.matrix_rank(M) < 7: + continue + _, _, Vt = np.linalg.svd(M) + nv = Vt[-1] + secs.add(frozenset(int(x) for x in P[np.abs(LN[P] @ nv) < 1e-7])) + return secs + + +def terminal_side(hyp): + """for every one of the 120 lines q (111 targets and the 9 pseudo-targets at the punctured lines): the live sources + lying in q^perp (the live lines orthogonal to q) and the least number of them left uncovered by any two hyperplane + flats of E7(q). The flats of E7(q) are the images of the flats of E7(s0) under an E8 symmetry taking s0 to q.""" + E = dg.e8() + idx, _ = dg.e7_flats() + s0, g, perms = dg.e8_isometries() + F0 = np.zeros((len(hyp), 120), dtype=bool) + for fi, m in enumerate(hyp): + for k in range(63): + if m >> k & 1: + F0[fi, idx[k]] = True + isl = E['isl'] + G = E['G'] + worst, nlive_min = 10 ** 9, 10 ** 9 + for q in range(120): + Fq = np.zeros_like(F0) + Fq[:, perms[q]] = F0 + perp = G[q] == 0 + assert (Fq <= perp[None, :]).all() + nlive = int((perp & isl).sum()) + pad = np.zeros((len(hyp), 128), dtype=bool) + pad[:, :120] = Fq & isl[None, :] + words = np.packbits(pad, axis=1, bitorder='little').view(np.uint64) + left = nlive - dg.max_pair_union(words) + worst = min(worst, left) + nlive_min = min(nlive_min, nlive) + return worst, nlive_min + + +def bit555_crossings(): + """level-2 crossings (rank-1 frame -> rank >= 2) and level-7 crossings (rank < 7 -> rank-7 frame) of the registers of the + word of PR #555, by register class (x sources, y targets, h helpers), and the number of level-2 crossings per source.""" + w, dims, path = dg.bit_paths() + v = w['v'] + cls = lambda r: 'x' if r < v else 'y' if r < 2 * v else 'h' + c2, c7, per = Counter(), Counter(), Counter() + for r, p in enumerate(path): + for a, b in zip(p, p[1:]): + if dims[a] < 2 <= dims[b] and dims[a] == 1: + c2[cls(r)] += 1 + per[tuple(w['frames'][a])] += 1 + if dims[a] < 7 <= dims[b] and dims[b] == 7: + c7[cls(r)] += 1 + return dict(c2), dict(c7), per, w + + +def main(): + # ===== complex P112: covers of the readers of a source ====================================================== + cv = dg.cx_section_covers() + ok = (cv['readers'] == {EXPECTED['cx_readers']} and cv['cover2_all'] == EXPECTED['cx_cover2'] and cv['left_all'] == 0 + and cv['max_all'] == EXPECTED['cx_max_section'] and cv['improper_all'] == 0) + check('D1.cx-cover2', ok, + 'every source (%d/112): its %d readers are covered by two proper sections {t perp s, t.w = 0} (no single section covers them: ' + 'cover number 2); largest single section %d' % (cv['cover2_all'], EXPECTED['cx_readers'], cv['max_all'])) + ok = (cv['cover2_closed'] == EXPECTED['cx_cover2'] and cv['left_closed'] == 0 and cv['max_closed'] == EXPECTED['cx_closed_max_section'] + and cv['improper_closed'] == 0) + check('D1.cx-cover2-closed', ok, + 'frames spanned by ports only: largest section %d, two sections still cover %d/112 sources' + % (cv['max_closed'], cv['cover2_closed'])) + + # ===== complex P112: the word of PR #531 ==================================================================== + cnt, c8, ftype = census531() + per_src = Counter(len(v) for v in cnt.values()) + mix = Counter(c for v in cnt.values() for c, _, _, _ in v) + dims = Counter(dm for v in cnt.values() for _, dm, _, _ in v) + secs = Counter(sc for v in cnt.values() for _, _, sc, _ in v) + allclosed = all(ps for v in cnt.values() for _, _, _, ps in v) + ok = (len(cnt) == 112 and dict(per_src) == EXPECTED['c531_crossings_per_source'] and dict(mix) == EXPECTED['c531_class_mix'] + and dict(dims) == EXPECTED['c531_frame_dims'] and dict(secs) == {EXPECTED['c531_section']: 336} and allclosed) + check('D1.cx531-level2', ok, + 'every source has exactly 3 level-2 crossings (X_s + 2 helpers: %d helper crossings), all into 2-dim port-spanned frames ' + 'with section %d (3 x %d = %d >= 52 > 2 x %d)' % (mix['h'], EXPECTED['c531_section'], EXPECTED['c531_section'], + 3 * EXPECTED['c531_section'], EXPECTED['c531_section'])) + check('D1.cx531-level8', dict(c8) == EXPECTED['c531_level8'], + 'entries into 8-dimensional frames: helpers %d, targets %d, sources %d' % (c8['h'], c8['y'], c8['x'])) + nonport = ftype[(1, False)] + ok = all(ps for (dm, ps) in ftype if dm >= 2) and nonport == EXPECTED['c531_nonport_rank1_frames'] + check('D1.cx531-frame-types', ok, + 'every frame of dimension >= 2 used by the word is port-spanned (closed); %d rank-1 entrance frames are not ports' % nonport) + sec531 = EXPECTED['c531_section'] + ok = 2 * sec531 < EXPECTED['cx_readers'] <= 3 * sec531 and cv['cover2_all'] == 112 and cv['cover2_closed'] == 112 + check('D1.cx-224-is-section-type', ok, + "the 224 helper crossings (2 per source) are forced by #531's section type (2 x %d = %d < 52 <= %d), not by the format: " + 'sections of size up to %d (%d with closed frames) let two sections cover every source' + % (sec531, 2 * sec531, 3 * sec531, cv['max_all'], cv['max_closed'])) + + L, ports, restored, helpers_free = demand531() + nz = sum(len(r) for r in L.values()) + northo = sum(1 for t in range(112) for s in range(112) if not dg.pdot(ports[s], ports[t])) + bad = sum(1 for t in L for s in L[t] if dg.pdot(ports[s], ports[t])) + hist = Counter(str(x) for r in L.values() for x in r.values()) + ok = (restored and helpers_free and nz == northo == EXPECTED['demand_nnz'] and bad == 0 + and hist == Counter({'-1/2': EXPECTED['demand_minus_half'], '1/2': EXPECTED['demand_plus_half']})) + check('D1.cx-demand', ok, + 'drop-free demand: %d nonzeros = all %d orthogonal (source, target) pairs, values -1/2 x %d and +1/2 x %d, %d entries on non-orthogonal pairs' + % (nz, northo, hist['-1/2'], hist['1/2'], bad)) + + # ===== bit E8: hyperplane flats of E7 ======================================================================= + E = dg.e8() + idx, lattice = dg.e7_flats() + hyp = lattice[6] + pos = {l: i for i, l in enumerate(idx)} + sampled = sampled_flats() + hs = Counter(len(x) for x in sampled) + hyp_set = set(hyp) + sampled_masks = {sum(1 << pos[l] for l in x) for x in sampled} + ok = len(sampled) == EXPECTED['bit_flats_sampled'] and dict(hs) == EXPECTED['bit_flats_sampled_hist'] and sampled_masks <= hyp_set + check('D1.bit-flats-sampled', ok, + 'earlier census by sampling 60000 random 6-subsets (seed 1): %d flats %s, all genuine hyperplane flats of E7 but an ' + 'undercount of the small types' % (len(sampled), dict(sorted(hs.items())))) + hh = Counter(m.bit_count() for m in hyp) + certified = dg.certify_hyperplane_flats(hyp) + G7 = E['G'][np.ix_(idx, idx)] + by_type = Counter() + for m in hyp: + members = [i for i in range(63) if m >> i & 1] + sub = (G7[np.ix_(members, members)] != 0) & ~np.eye(len(members), dtype=bool) + _, lab = connected_components(csr_matrix(sub), directed=False) + by_type[tuple(sorted(Counter(lab.tolist()).values(), reverse=True))] += 1 + orb_ok = (set(by_type) == set(TYPES) + and all(by_type[k] == W_E7 // (2 * TYPES[k][1]) for k in TYPES)) + ok = len(hyp) == EXPECTED['bit_flats'] == certified and dict(hh) == EXPECTED['bit_flats_hist'] and orb_ok + check('D1.bit-flats', ok, + 'exhaustive census of the hyperplane flats of E7 (closure of flats, each certified in integers): %d flats, by size %s; by type %s ' + '(= |W(E7)| / (2 |W_J|) for each of the 7 maximal parabolic types)' + % (len(hyp), dict(sorted(hh.items())), {TYPES[k][0]: by_type[k] for k in sorted(TYPES, key=lambda k: -sum(k))})) + + words = dg.masks_to_words(hyp, 63) + full = dg.masks_to_words([(1 << 63) - 1], 63)[0] + u2 = dg.max_pair_union(words) + big = dg.masks_to_words([m for m in hyp if m.bit_count() >= 21], 63) # a witness may be searched among the large flats + triple = dg.find_triple_cover(big, full) + ok = u2 == EXPECTED['bit_union2'] and 63 - u2 == EXPECTED['bit_leftover'] and triple is not None + check('D1.bit-cover3', ok, + 'readers of a source (63 lines of E7): two hyperplane flats cover at most %d, leaving >= %d lines; three flats of size %s ' + 'cover all 63, so the cover number is %d' % (u2, 63 - u2, [int(dg.popcount(big[i]).sum()) for i in triple], EXPECTED['bit_cover_number'])) + + worst, nlive_min = terminal_side(hyp) + ok = worst == EXPECTED['bit_term_live_leftover_min'] and worst >= (63 - u2) - 9 + check('D1.bit-terminal-cover3', ok, + 'terminal side: for each of the 120 terminals q, the live sources in q^perp (at least %d) are not covered by two flats of E7(q): at ' + 'least %d live sources remain (>= 11 - 9 punctured lines = 2), so the cover number is 3' % (nlive_min, worst)) + + c2, c7, per, w = bit555_crossings() + ph = Counter(per.values()) + ok = c2 == EXPECTED['bit555_level2'] and len(per) == 111 and min(ph) == EXPECTED['bit555_per_source_min'] and dict(ph) == EXPECTED['bit555_per_source_hist'] + check('D1.bit555-level2', ok, + 'shipped #555 word: level-2 crossings from rank-1 frames x %d / y %d / h %d; every source has >= %d (histogram %s)' + % (c2['x'], c2['y'], c2['h'], min(ph), dict(sorted(ph.items())))) + check('D1.bit555-level7', c7 == EXPECTED['bit555_level7'], + 'shipped #555 word: level-7 crossings into rank-7 frames x %d / y %d / h %d' % (c7['x'], c7['y'], c7['h'])) + + # ===== derived helper counts ================================================================================ + nsrc = w['v'] + nterm = 120 + cmin_bit = EXPECTED['bit_cover_number'] + leftover_bit = 63 - u2 + sink_bit, strict_bit = dg.single_cut_bounds(nsrc, nterm, leftover_bit, cmin_bit) + ok = (sink_bit == EXPECTED['bit_sink'] and strict_bit == EXPECTED['bit_strict'] and w['R'] == EXPECTED['bit555_R'] + and triple is not None and u2 < 63) + check('D1.bit-bounds', ok, + 'bit (cover number %d, leftover %d): sink-only targets R >= 2 x %d - floor(%d/%d) = %d; strict R >= max(3 x %d - %d, 3 x %d - %d) = %d ' + '(shipped %d: %.1f%%)' % (cmin_bit, leftover_bit, nsrc, nsrc, leftover_bit, sink_bit, nsrc, 2 * nsrc, nterm, 2 * nsrc, strict_bit, + w['R'], 100.0 * strict_bit / w['R'])) + V = 112 + cmin_cx = 2 if cv['cover2_all'] == V else None + left_cx = EXPECTED['cx_readers'] - cv['max_all'] + left_cl = EXPECTED['cx_readers'] - cv['max_closed'] + sink_cx, strict_cx = dg.single_cut_bounds(V, V, left_cx, cmin_cx) + sink_cl, strict_cl = dg.single_cut_bounds(V, V, left_cl, cmin_cx) + R531 = dg.word531()['report']['R'] + ok = (sink_cx == EXPECTED['cx_sink'] and sink_cl == EXPECTED['cx_sink_closed'] and strict_cx == strict_cl == EXPECTED['cx_strict'] + and R531 == 504 and len(dg.word531()['centers']) == 8) + check('D1.cx-bounds', ok, + 'complex (cover number %d, symmetric ends): sink-only targets R >= 112 - floor(112/%d) = %d (%d with closed frames, section %d); ' + 'strict R >= 2 x 112 - 224 = %d (shipped %d helpers + 8 centres)' % (cmin_cx, left_cx, sink_cx, sink_cl, cv['max_closed'], strict_cx, R531 - 8)) + + +main() +finish() diff --git a/research/format-limits/scripts/d2_coupled_count.py b/research/format-limits/scripts/d2_coupled_count.py new file mode 100644 index 0000000000..29459e249b --- /dev/null +++ b/research/format-limits/scripts/d2_coupled_count.py @@ -0,0 +1,521 @@ +"""D2. The coupled (cross-level) cover relaxation with a helper-count objective, on the complex unit P112 and the bit unit E8. + +D1 bounds the number of helper registers by a cut at one level of the frame lattice (the source end or the terminal +end). Here the cuts at all levels are coupled through the register chains. + +Model. Let K be the top rank (K = 9 for P112 inside F_2^9, K = 8 for E8). A register has a class and a chain of frame ranks: + X (source) : starts at rank 1, ends at rank K, stops at any subset of {2, ..., K-1}; + Y (target) : starts at rank 0, ends at rank K-1 (the frame u_q^perp), stops at any subset of {1, ..., K-2}; + H (helper) : starts at a rank s0 (0 for the bit unit, 0..5 for the complex unit) and ends at rank K, stops at any subset of + {s0+1, ..., K-1}. +A hop from rank a to rank b > a carries one rank-one term of the transfer matrix, supported on (sources in a) x (terminals in +b^perp); it serves every level d with a < d <= b. Its area (number of orthogonal source/terminal pairs it can serve) is at +most ell_a * ell_{K-b}, where ell_i is the largest number of source points in a subspace of rank i, further capped by + * the exact unit rectangle cap M(d) of every level d spanned by the hop (largest area of a product (P cap a) x (P cap c) of + mutually orthogonal subspaces a, c with dim a = d-1, dim c = K-d), + * the largest section of a source's readers by a hyperplane (hops leaving rank 1) and of a terminal's sources (hops entering rank K-1), + * for sink-only targets (a target is only a destination, its hop serves one terminal column) ell_a x 1. +Variables x_t >= 0 (integer for the ILP): the number of registers of type t = (class, chain). Constraints: + (level) for every level d = 2..K-1: sum_t area_t(d) x_t >= P, where P is the number of orthogonal pairs; + (counts) exactly nX registers of class X, exactly nY of class Y; + (source) every source is served by a multiset of registers standing at its rank-1 frame whose first hops are sections of its + readers: at least cmin sections, any two cover at most u2 readers, together at least NT_src readers (patterns of + registers, linked to the first hops of the chains by >= ); + (terminal) the same for the sources of every terminal q at the rank-(K-1) end: the registers entering the frame q^perp + must cover the sources in q^perp by sections of q^perp (the target's own register contributes the section of + the hop that enters its final frame; pseudo-targets at the 9 punctured lines of the bit unit have no own register). +Objective: the number of helper registers. Scope: this is a relaxation under the assumptions above (frames are arbitrary +subspaces, the only drops are the decoder copies, the areas are exact maxima over the geometry); it is not a proof about every +conceivable design. The shipped words of PR #555 (bit) and PR #569 (complex) are feasible points of it. + +Claims. (a) the optimum of the coupled model equals the single-cut bounds of D1 (212, 138 for the bit unit; 107, 0 for the +complex unit): coupling adds nothing; (b) exact geometry inputs (ell_k and unit caps of P112); (c) the shipped words are +feasible; (d) with the data ladders of the shipped words fixed, the least number of helpers is 222 (bit) and 146 / 123 (complex). +Upstream: PR #555 (bit word), PR #531 (P112 and its word), PR #569 (complex word with width-7 gauges). +""" +import sys + +sys.dont_write_bytecode = True + +import itertools +from collections import Counter + +import numpy as np +from scipy.optimize import LinearConstraint, Bounds, milp +from scipy.sparse import lil_matrix, csr_matrix + +import d_geometry as dg +from report import VENDOR, check, finish, load_json + +# --------------------------------------------------------------------------------------------------------------- +# Expected values (hard-coded; each is the exact outcome of the computation below) +# --------------------------------------------------------------------------------------------------------------- +EXPECTED = dict( + cx_ell=[1, 2, 4, 8, 12, 20, 36, 64, 112], # ell_k, k = 1..9: most ports in a k-dimensional subspace of F_2^9 + cx_nsubspaces=8283458, # all subspaces of F_2^9 (sum of the Gaussian binomials) + cx_unitcaps={2: 32, 3: 32, 4: 32, 5: 36, 6: 32, 7: 32, 8: 32}, # exact rectangle cap per level d = 2..8 + bit_ell=[1, 3, 6, 12, 20, 36, 63], # ell_i, i = 1..7: lines in the largest rank-i flat (A1, A2, A3, D4, D5, E6, E7) + bit_sink=212, bit_strict=138, cx_sink=107, cx_strict=0, # integer optima of the coupled model (helpers) + lp=dict(bit_sink=2331 / 11, bit_strict=138.0, cx_sink=106.4, cx_strict=0.0), # their LP relaxations + ship_fixed_bit=222, ship_fixed_bit_strict=222, ship_fixed_cx_sink=146, ship_fixed_cx_strict=123, +) +TIME_LIMIT = 300 # seconds per ILP; every ILP below proves optimality in well under a second + + +# --------------------------------------------------------------------------------------------------------------- +# Exact geometry of P112: ell_k and the unit rectangle caps (exhaustive over all subspaces of F_2^9) +# --------------------------------------------------------------------------------------------------------------- +def cx_ell(orth_lo, orth_hi): + """ell_k = largest number of ports in a k-dimensional subspace u of F_2^9, k = 0..9: u = W^perp for the (9-k)-dimensional + subspace W spanned by the rows of an echelon basis; the ports in u are those orthogonal to every row. Returns (ell, + number of subspaces enumerated).""" + ell, total = {}, 0 + for m in range(0, 10): + best = 0 + for rows in dg.subspace_bases(m): + total += len(rows) + if m == 0: + best = len(dg.cx_ports()) + continue + lo = np.bitwise_and.reduce(orth_lo[rows], axis=1) + hi = np.bitwise_and.reduce(orth_hi[rows], axis=1) + best = max(best, int((dg.popcount(lo) + dg.popcount(hi)).max())) + ell[9 - m] = best + return [ell[k] for k in range(1, 10)], total + + +def cx_unit_caps(orth_lo, orth_hi): + """M(d) for d = 2..8: the largest |P cap a| * |P cap c| over orthogonal subspaces a, c of F_2^9 with dim a = d-1, + dim c = 9-d, c a hyperplane of a^perp. Enumerated exhaustively over a for dim a = 1..4 (d = 2..5); the pair (a, c) is + symmetric in its two members (a is a hyperplane of c^perp as well), so M(d) = M(10-d) gives d = 6, 7, 8.""" + ports = dg.cx_ports() + isport = np.zeros(512, dtype=bool) + isport[list(ports)] = True + lo1, hi1 = orth_lo[1:], orth_hi[1:] # for w = 1..511 + caps = {} + for p in (1, 2, 3, 4): + best = 0 + for rows in dg.subspace_bases(p, chunk=1 << 13): + n = len(rows) + vs = np.zeros((n, 1), dtype=np.int64) # all vectors of the span of each basis (column 0 is the zero vector) + for i in range(p): + vs = np.concatenate([vs, vs ^ rows[:, i:i + 1]], axis=1) + na = isport[vs[:, 1:]].sum(axis=1) # ports in a + olo = np.bitwise_and.reduce(orth_lo[rows], axis=1) + ohi = np.bitwise_and.reduce(orth_hi[rows], axis=1) # ports in a^perp + cc = dg.popcount(lo1[None, :] & olo[:, None]) + dg.popcount(hi1[None, :] & ohi[:, None]) # ports in a^perp cap w^perp + np.put_along_axis(cc, vs[:, 1:] - 1, 0, axis=1) # w in span(a) does not cut a hyperplane out of a^perp + best = max(best, int((na * cc.max(axis=1)).max())) + caps[p + 1] = best + for d in (6, 7, 8): + caps[d] = caps[10 - d] + return caps + + +# --------------------------------------------------------------------------------------------------------------- +# The coupled cover model +# --------------------------------------------------------------------------------------------------------------- +class Spec: + """parameters of one unit: K, ell[0..K], hstarts, capS(j), capT(i), ymode ('sink' or 'strict'), cmin, u2, NT_src, NT_top, + P, nX, nY, nsrc, nterm and optionally unitcap {level: cap}.""" + + +def feasible(caps, cmin, NT, u2): + """can sections with these caps serve NT readers: at least cmin of them, and (if u2 is given) any two cover at most u2.""" + caps = sorted(caps, reverse=True) + if len(caps) < cmin: + return False + top2 = sum(caps[:2]) + if u2 is not None: + top2 = min(top2, u2) + return top2 + sum(caps[2:]) >= NT + + +def minimal_patterns(fixed, itemcaps, cmin, NT, u2, maxextra=4): + """minimal multisets of optional items (key -> cap) that, together with the fixed items, can serve NT readers; minimal + means removing any optional item destroys feasibility. Returns the list of item tuples.""" + keys = [k for k in itemcaps if itemcaps[k] > 0] + base = [c for _, c in fixed] + out = [] + for r in range(0, maxextra + 1): + for combo in itertools.combinations_with_replacement(keys, r): + if not feasible(base + [itemcaps[k] for k in combo], cmin, NT, u2): + continue + if all(not feasible(base + [itemcaps[k] for t, k in enumerate(combo) if t != idx], cmin, NT, u2) for idx in range(len(combo))): + out.append(combo) + return out + + +class CoverModel: + def __init__(self, spec): + self.sp = sp = spec + K = sp.K + self.types = [] + for ch in self._chains(1, K, 2, K - 1): + self.types.append(('X', ch)) + for ch in self._chains(0, K - 1, 1, K - 2): + self.types.append(('Y', ch)) + for s0 in sp.hstarts: + for ch in self._chains(s0, K, s0 + 1, K - 1): + self.types.append(('H', ch)) + self.index = {t: i for i, t in enumerate(self.types)} + + @staticmethod + def _chains(start, end, lo, hi): + mids = list(range(lo, hi + 1)) + return [(start,) + T + (end,) for k in range(len(mids) + 1) for T in itertools.combinations(mids, k)] + + def area(self, cls, ch, d): + """largest number of orthogonal pairs the hop of the chain that spans level d can serve (0 if no hop spans d).""" + sp = self.sp + K = sp.K + for a, b in zip(ch, ch[1:]): + if a < d <= b: + if a == 0: + return 0.0 + if cls == 'Y' and sp.ymode == 'sink': + return float(min(sp.ell[a], sp.capT(a))) + ar = sp.ell[a] * sp.ell[K - b] + uc = getattr(sp, 'unitcap', None) + if uc: + ar = min(ar, min(uc.get(dd, 0) for dd in range(a + 1, b + 1))) + if a == 1: + ar = min(ar, sp.capS(b)) + if b == K - 1: + ar = min(ar, sp.capT(a)) + return float(ar) + return 0.0 + + @staticmethod + def first_hop(ch): + """target rank of the hop leaving rank 1 (None if the chain has no rank-1 stop).""" + return ch[ch.index(1) + 1] if 1 in ch[:-1] else None + + def last_hop(self, ch): + """source rank of the hop entering rank K-1 (None if the chain never enters rank K-1).""" + K = self.sp.K + return ch[ch.index(K - 1) - 1] if (K - 1) in ch[1:] else None + + def build(self, xfix=None): + sp = self.sp + K, T = sp.K, self.types + n = len(T) + j1 = [self.first_hop(ch) for _, ch in T] + i7 = [self.last_hop(ch) for _, ch in T] + srcpat = [] # (rank of X's hop, tuple of other (class, hop rank) items) + for jX in range(2, K + 1): + capX = sp.capS(jX) if jX < K else 0 + if sp.ymode == 'sink': + hk = [('H', j) for j in range(2, K)] + for r in range(0, 4): + for combo in itertools.combinations_with_replacement(hk, r): + caps = [capX] + [sp.capS(j) for _, j in combo] + for a in range(0, int(sp.NT_src) + 1): # a sink-only targets, one reader each + if not feasible(caps + [1] * a, sp.cmin, sp.NT_src, sp.u2): + continue + ok = not (a > 0 and feasible(caps + [1] * (a - 1), sp.cmin, sp.NT_src, sp.u2)) + for idx in range(len(combo)): + c2 = [capX] + [sp.capS(j) for t_, (_, j) in enumerate(combo) if t_ != idx] + [1] * a + if feasible(c2, sp.cmin, sp.NT_src, sp.u2): + ok = False + break + if ok: + srcpat.append((jX, tuple(combo) + tuple([('Y', 2)] * a))) + break + else: + optional = {} + for j in range(2, K + 1): + optional[('H', j)] = sp.capS(j) if j < K else 0 + optional[('Y', j)] = sp.capS(j) if j < K else 0 + for combo in minimal_patterns([(('X', jX), capX)], optional, sp.cmin, sp.NT_src, sp.u2): + srcpat.append((jX, combo)) + toppat = [] # (has own target section, its rank, tuple of other (class, hop rank) items) + for hasY in (True, False): + for iY in (range(0, K - 1) if hasY else [None]): + fixed = [(('Y', iY), sp.capT(iY))] if hasY else [] + optional = {} + for i in range(1, K - 1): + optional[('H', i)] = sp.capT(i) + optional[('X', i)] = sp.capT(i) + for combo in minimal_patterns(fixed, optional, sp.cmin, sp.NT_top, sp.u2): + toppat.append((hasY, iY, combo)) + ns, nt = len(srcpat), len(toppat) + N = n + ns + nt + c = np.zeros(N) + for t, (cls, ch) in enumerate(T): + c[t] = 1.0 if cls == 'H' else 0.0 + rows, lo, hi = [], [], [] + + def addrow(coefs, l, h): + rows.append(coefs) + lo.append(l) + hi.append(h) + + for d in range(2, K): # level covers + addrow({t: self.area(cls, ch, d) for t, (cls, ch) in enumerate(T) if self.area(cls, ch, d) > 0}, sp.P, np.inf) + addrow({t: 1.0 for t, (cls, _) in enumerate(T) if cls == 'X'}, sp.nX, sp.nX) + addrow({t: 1.0 for t, (cls, _) in enumerate(T) if cls == 'Y'}, sp.nY, sp.nY) + addrow({n + k: 1.0 for k in range(ns)}, sp.nsrc, sp.nsrc) # source patterns + for cls in ('X', 'H', 'Y'): + for j in range(2, K + 1): + co = {t: 1.0 for t, (cl, _) in enumerate(T) if cl == cls and j1[t] == j} + for k, (jX, combo) in enumerate(srcpat): + m = (1 if (cls == 'X' and jX == j) else 0) + sum(1 for it in combo if it == (cls, j)) + if m: + co[n + k] = co.get(n + k, 0) - m + addrow(co, 0, np.inf) + addrow({n + ns + k: 1.0 for k in range(nt) if toppat[k][0]}, sp.nY, sp.nY) # terminal patterns + addrow({n + ns + k: 1.0 for k in range(nt) if not toppat[k][0]}, sp.nterm - sp.nY, sp.nterm - sp.nY) + for cls in ('X', 'H', 'Y'): + for i in range(0, K - 1): + co = {t: 1.0 for t, (cl, _) in enumerate(T) if cl == cls and i7[t] == i} + for k, (hasY, iY, combo) in enumerate(toppat): + m = (1 if (cls == 'Y' and hasY and iY == i) else 0) + sum(1 for it in combo if it == (cls, i)) + if m: + co[n + ns + k] = co.get(n + ns + k, 0) - m + if co: + addrow(co, 0, np.inf) + if xfix: + for t, v in xfix.items(): + addrow({t: 1.0}, v, v) + A = lil_matrix((len(rows), N)) + for r, co in enumerate(rows): + for k, v in co.items(): + A[r, k] = v + self.c, self.A, self.lo, self.hi, self.N = c, csr_matrix(A), np.array(lo, float), np.array(hi, float), N + self.npat = (ns, nt) + + def solve(self, integer, xfix=None): + """minimise the number of helpers; returns scipy's result. Integer solves use mip_rel_gap = 0.""" + self.build(xfix) + cons = LinearConstraint(self.A, lb=self.lo, ub=self.hi) + integ = np.ones(self.N) if integer else np.zeros(self.N) + return milp(self.c, constraints=[cons], integrality=integ, bounds=Bounds(0, np.inf), + options=dict(time_limit=TIME_LIMIT, disp=False, mip_rel_gap=0.0)) + + +def optimum(model, integer, xfix=None): + """(value, proved) where proved says: solver status 'optimal', and for an ILP the dual bound equals the objective.""" + res = model.solve(integer, xfix) + if res.status != 0 or res.x is None: + return None, False + proved = True + if integer: + proved = abs(res.fun - round(res.fun)) < 1e-6 and (res.mip_dual_bound is None or res.mip_dual_bound >= res.fun - 1e-6) + return float(res.fun), proved + + +# --------------------------------------------------------------------------------------------------------------- +# Unit specifications +# --------------------------------------------------------------------------------------------------------------- +def e8_geometry(): + """cover parameters of the bit unit from the exact E7 flat lattice: ell_i = lines in the largest rank-i flat of E7 (for + i <= 7 the largest rank-i flats of E8 have the same sizes: the largest root subsystems of rank i are A1, A2, A3, D4, D5, E6, E7 + by the classification of parabolic subsystems; only the E7 part is enumerated here), u2 = largest union of two hyperplane + flats, cmin = cover number.""" + idx, lattice = dg.e7_flats() + ell = [max(m.bit_count() for m in lattice[k]) for k in range(1, 7)] + [63] + hyp = lattice[6] + words = dg.masks_to_words(hyp, 63) + full = dg.masks_to_words([(1 << 63) - 1], 63)[0] + u2 = dg.max_pair_union(words) + big = dg.masks_to_words([m for m in hyp if m.bit_count() >= 21], 63) + cmin = 2 if u2 == 63 else (3 if dg.find_triple_cover(big, full) is not None else None) + return ell, u2, cmin + + +def bit_spec(ymode, ell, u2, cmin): + E = dg.e8() + K = 8 + G, isl = E['G'], E['isl'] + nlive_perp = [int(((G[q] == 0) & isl).sum()) for q in range(120)] + sp = Spec() + sp.K, sp.ell = K, [0] + list(ell) + [120] + sp.hstarts = [0] + sp.capS = lambda j: sp.ell[K - j] + sp.capT = lambda i: sp.ell[i] + sp.ymode, sp.cmin, sp.u2 = ymode, cmin, u2 + sp.NT_src, sp.NT_top = 63, min(nlive_perp) + sp.P = sum(int((G[E['srcid'][i]] == 0).sum()) for i in range(111)) + sp.nX = sp.nY = sp.nsrc = 111 + sp.nterm = 120 + return sp + + +def cx_spec(ymode, ell, unitcap, sec, cmin): + K = 9 + sp = Spec() + sp.K, sp.ell = K, [0] + list(ell) + sp.hstarts = [0, 1, 2, 3, 4, 5] + sp.capS = lambda j: min(sp.ell[K - j], sec) if j < K else 0 + sp.capT = lambda i: min(sp.ell[i], sec) + sp.unitcap = unitcap + sp.ymode, sp.cmin, sp.u2 = ymode, cmin, None + sp.NT_src = sp.NT_top = 52 + sp.P = 112 * 52 + sp.nX = sp.nY = sp.nsrc = sp.nterm = 112 + return sp + + +# --------------------------------------------------------------------------------------------------------------- +# Chains of the shipped words +# --------------------------------------------------------------------------------------------------------------- +def bit_ship_counts(): + """(class, chain of frame ranks) -> number of registers, for the 661 registers of the word of PR #555.""" + w, dims, path = dg.bit_paths() + v = w['v'] + cnt = Counter() + for r, p in enumerate(path): + cnt[('X' if r < v else 'Y' if r < 2 * v else 'H', tuple(dims[f] for f in p))] += 1 + return cnt, w['R'] + + +def cx_ship_counts(): + """the same for the word of PR #569 with width-7 gauges, without its 8 rank-8 centres (which are not helpers of the + model). The chain of a register is the sequence of ranks of the frames it occupies during the phases A and B and at the + end (sources and helpers end in the full frame, targets in the perp of their port).""" + g = dg.gk() + word = load_json(VENDOR / 'pr569' / 'width7-eight-FULL-WORD.json.gz') + V = 112 + R = word['report']['R'] + n = 2 * V + R + P = word['ports'] + start_extra = word.get('start_extra', {}) + cur = {} + for r in range(n): + if r < V: + cur[r] = (P[r],) + elif r >= 2 * V: + cur[r] = g.basis(start_extra[str(r)]) if str(r) in start_extra else () + else: + cur[r] = () + chain = {r: [len(cur[r])] for r in range(n)} + + def climb(r, F): + F = g.basis(F) + if cur[r] != F: + chain[r].append(len(F)) + cur[r] = F + + for seq in (word['A'], word['B']): + for e in seq: + for r in [e[1]] + ([e[2]] if e[0] == 'add' else []): + climb(r, e[-1]) + for r in range(n): + climb(r, g.FULL if (r < V or r >= 2 * V) else g.perp(P[r - V])) + ctr = set(word['centers']) + cnt = Counter() + for r in range(n): + if r in ctr: + continue + cnt[('X' if r < V else 'Y' if r < 2 * V else 'H', tuple(chain[r]))] += 1 + return cnt, R, len(ctr) + + +def fix_all(model, cnt): + """x fixed to the counts cnt for every type (missing types are fixed to 0); returns (xfix, types of cnt not in the model).""" + missing = [k for k in cnt if k not in model.index] + return {i: cnt.get(t, 0) for i, t in enumerate(model.types)}, missing + + +def fix_data(model, cnt): + """x fixed to the shipped counts for the data classes X and Y only.""" + missing = [k for k in cnt if k[0] in 'XY' and k not in model.index] + return {i: cnt.get(t, 0) for i, t in enumerate(model.types) if t[0] in 'XY'}, missing + + +def main(): + ports = dg.cx_ports() + _, olo, ohi = dg.orth_tables(ports) + + # ===== exact geometry of P112 ============================================================================== + ell, nsub = cx_ell(olo, ohi) + check('D2.cx-ell', ell == EXPECTED['cx_ell'] and nsub == EXPECTED['cx_nsubspaces'], + 'largest number of ports in a k-dimensional subspace of F_2^9, k = 1..9: %s (all %d subspaces enumerated)' % (ell, nsub)) + caps = cx_unit_caps(olo, ohi) + check('D2.cx-unitcaps', caps == EXPECTED['cx_unitcaps'], + 'exact rectangle cap per level d = 2..8: %s (the product ell_(d-1) x ell_(9-d) = 8 x 8 = 64 at d = 5 is not attained)' + % [caps[d] for d in range(2, 9)]) + cv = dg.cx_section_covers() + sec, cmin_cx = cv['max_all'], (2 if cv['cover2_all'] == 112 else None) + assert sec == caps[2] == 32 and cmin_cx == 2 + + ell_bit, u2, cmin_bit = e8_geometry() + check('D2.bit-ell', ell_bit == EXPECTED['bit_ell'], + 'largest flat of rank i = 1..7 of E7 (exhaustive census of the flats): %s lines = A1, A2, A3, D4, D5, E6, E7; E8 itself has 120 lines; ' + 'two hyperplane flats cover at most %d of 63 lines, cover number %d' % (ell_bit, u2, cmin_bit)) + + # ===== the coupled model: count-minimal helpers ============================================================= + results = {} + for name, mk in (('bit', lambda y: bit_spec(y, ell_bit, u2, cmin_bit)), ('cx', lambda y: cx_spec(y, ell, caps, sec, cmin_cx))): + for ymode in ('sink', 'strict'): + m = CoverModel(mk(ymode)) + lp, _ = optimum(m, False) + ip, proved = optimum(m, True) + results[(name, ymode)] = (lp, ip, proved, m) + leftover_bit, leftover_cx = 63 - u2, 52 - sec + sc = {('bit', 'sink'): None, ('bit', 'strict'): None, ('cx', 'sink'): None, ('cx', 'strict'): None} + s, t = dg.single_cut_bounds(111, 120, leftover_bit, cmin_bit) + sc[('bit', 'sink')], sc[('bit', 'strict')] = s, t + s, t = dg.single_cut_bounds(112, 112, leftover_cx, cmin_cx) + sc[('cx', 'sink')], sc[('cx', 'strict')] = s, t + labels = {('bit', 'sink'): ('D2.bit-sink', 'bit_sink', 'bit unit, sink-only targets'), + ('bit', 'strict'): ('D2.bit-strict', 'bit_strict', 'bit unit, strict targets'), + ('cx', 'sink'): ('D2.cx-sink', 'cx_sink', 'complex unit, sink-only targets'), + ('cx', 'strict'): ('D2.cx-strict', 'cx_strict', 'complex unit, strict targets')} + for key, (cid, exp, text) in labels.items(): + lp, ip, proved, m = results[key] + ok = (proved and round(ip) == EXPECTED[exp] == sc[key] and abs(lp - EXPECTED['lp'][exp]) < 1e-6 + and int(np.ceil(lp - 1e-9)) == round(ip)) + check(cid, ok, '%s: coupled optimum %d helpers (ILP %s, LP relaxation %.4f, %d types, %d+%d patterns) = single-cut bound %d: ' + 'coupling adds %d' % (text, round(ip), 'proved optimal' if proved else 'NOT proved optimal', lp, len(m.types), m.npat[0], + m.npat[1], sc[key], round(ip) - sc[key])) + + # ===== the shipped words are feasible points ================================================================ + bit_cnt, bit_R = bit_ship_counts() + stat = [] + for ymode in ('sink', 'strict'): + m = results[('bit', ymode)][3] + xf, missing = fix_all(m, bit_cnt) + val, proved = optimum(m, False, xf) + stat.append((ymode, val, missing)) + ok = all(v is not None and not mi for _, v, mi in stat) and sum(bit_cnt.values()) == 661 and bit_R == 439 + check('D2.bit-ship-feasible', ok, 'the word of PR #555 (111 x + 111 y + %d helpers) is feasible in the model, sink-only and strict' % bit_R) + cx_cnt, cx_R, ncent = cx_ship_counts() + stat = [] + for ymode in ('sink', 'strict'): + m = results[('cx', ymode)][3] + xf, missing = fix_all(m, cx_cnt) + val, proved = optimum(m, False, xf) + stat.append((ymode, val, missing)) + ok = all(v is not None and not mi for _, v, mi in stat) and sum(cx_cnt.values()) == 112 + 112 + 496 and ncent == 8 + check('D2.cx-ship-feasible', ok, 'the word of PR #569 (width 7) without its %d centres (112 x + 112 y + %d helpers) is feasible in the model, ' + 'sink-only and strict' % (ncent, cx_R - ncent)) + + # ===== data ladders fixed to the shipped words ================================================================ + fixed_bit = {} + for ymode in ('sink', 'strict'): + m = results[('bit', ymode)][3] + xf, missing = fix_data(m, bit_cnt) + fixed_bit[ymode] = optimum(m, True, xf) + (missing,) + ok = (all(p and not mi for _, p, mi in fixed_bit.values()) and round(fixed_bit['sink'][0]) == EXPECTED['ship_fixed_bit'] + and round(fixed_bit['strict'][0]) == EXPECTED['ship_fixed_bit_strict']) + check('D2.bit-fixed-data', ok, + 'bit unit, data ladders fixed to the shipped word (X: 1,2,4,6,7,8 ...; Y: 0,2,7 ...): at least %d helpers sink-only, %d strict ' + '(= the 222 carriers, 2 per source; the free optima are 212 and 138)' + % (round(fixed_bit['sink'][0]), round(fixed_bit['strict'][0]))) + vals = {} + for ymode in ('sink', 'strict'): + m = results[('cx', ymode)][3] + xf, missing = fix_data(m, cx_cnt) + vals[ymode] = optimum(m, True, xf) + (missing,) + ok = (all(p and not mi for _, p, mi in vals.values()) and round(vals['sink'][0]) == EXPECTED['ship_fixed_cx_sink'] + and round(vals['strict'][0]) == EXPECTED['ship_fixed_cx_strict']) + check('D2.cx-fixed-data', ok, + 'complex unit, data ladders fixed to the shipped word: at least %d helpers sink-only, %d strict (free optima 107 and 0; the shipped X ladders ' + 'have no hop across ranks 5-8, so helpers must supply the large rectangles there; shipped 496)' + % (round(vals['sink'][0]), round(vals['strict'][0]))) + + +main() +finish() diff --git a/research/format-limits/scripts/d3_carrier_ledger.py b/research/format-limits/scripts/d3_carrier_ledger.py new file mode 100644 index 0000000000..0493cbbf6a --- /dev/null +++ b/research/format-limits/scripts/d3_carrier_ledger.py @@ -0,0 +1,297 @@ +"""D3. The register ledger of PR #531's 504 helpers, rebuilt from tile objects on the geometry P112, and the carrier-neutrality identity. + +Geometry (PR #531). The 112 sources are the root lines 8..119 of the file inputs/hamming/PROTOTYPE.json; two sources are +adjacent (a reader t "reads" a source s) when their root lines have inner product +-2; Gm[t, s] = (root_t . root_s)/2 in {0, +-1} +is the signed adjacency; every reader reads 52 sources. The sources fall into 14 blocks of 8 (the support of the root +line), each block into 2 tetrads of 4 (parity of the number of minus signs). The F_2 label of a source is its port in F_2^9. + +Tile objects. A "face" is a set B of 4 sources of one block together with a sign pattern; its reach is the number of readers +t that read all four sources with that pattern (Gm[t, B] proportional to the pattern). A "key" is a pair of faces of two +different blocks, disjoint in sources, that have at least 3 readers in common with a consistent relative sign. For a key with +reader set T and source set S (8 sources) two readers are mates if their common neighbourhood with consistent sign has at least +|S| + 8 sources; mu is the size of a maximum matching of mates among T. + +Ledger. The helper registers needed by a hierarchy of faces and keys are counted by births = sum over object instances of +(uses - 1): + carriers 2 N2 - 112 + waste (N2 faces, each built from two edge objects, "waste" = edges used with only one sign variant), + face copies 2 K - N2 (K keys, each face used by two keys), + M copies R - K (R = key hosts = sum over keys of (|T| - mu), minus the 56 slots borrowed from the output pairs), +so that B = N2 + K + R - 112 + waste. For PR #531 the objects are the 168 block-local planes (faces of reach 8 whose four ports +add to 0), their 168 tetrad edges, and 168 keys; the ledger gives 224 + 168 + 112 = 504 = the helper count R of the word. +A butterfly (an edge object with both sign variants) is register-neutral, so the ledger depends on the edge cover only through +`waste`: rebuilt from edges joining the two tetrads of a block the same planes cost 168 more registers (12 wasted single-variant +butterflies per block), while the tetrad edges waste nothing. Upstream: PR #531 (word and geometry). +""" +import sys + +sys.dont_write_bytecode = True + +import itertools +from collections import Counter, defaultdict + +from ortools.sat.python import cp_model + +import d_geometry as dg +from report import check, finish + +# --------------------------------------------------------------------------------------------------------------- +# Expected values (hard-coded; each is the exact outcome of the computation below) +# --------------------------------------------------------------------------------------------------------------- +EXPECTED = dict( + faces=168, faces_per_block=12, face_reach=8, face_rank=3, # block-local planes + edges=168, edge_degree=3, carriers=224, # tetrad edges, each source in 3, births of the sources + keys=168, key_readers={4: 168}, face_uses={2: 168}, key_rank={5: 168}, + nested_width={2: 168}, face_copies=168, # consumer frames of the two keys of a face are never nested + mate_matching={2: 168}, borrowed=56, hosts=280, m_copies=112, + total=504, classes=(224, 168, 112), + cross_block_best=(28, 12, 12, 16, 12), # per block: (births, wasted butterflies, edges, births_0, births_1) + cross_total=392, cross_extra=168, cross_waste=12, + waste_min=0, candidate_edges=392, +) + + +# --------------------------------------------------------------------------------------------------------------- +# Faces, keys +# --------------------------------------------------------------------------------------------------------------- +def block_local_faces(P): + """all faces of reach 8 inside one block: for each 4-subset B of a block (sources in increasing order) and each sign + pattern (signs of Gm[t, B] normalised so that the first is +1) count the readers t with that pattern. Returns the list of + faces (B, pattern, {reader: sign at B[0]}), sorted, and the census {(reach): number of (B, pattern)}.""" + Gm, ADJ, blk = P['Gm'], P['ADJ'], P['blk'] + faces, census = [], Counter() + for b in range(P['nblocks']): + srcs = [s for s in range(P['n']) if blk[s] == b] + for B in itertools.combinations(srcs, 4): + readers = [t for t in range(P['n']) if all(ADJ[t, s] for s in B)] + groups = defaultdict(dict) + for t in readers: + v = [int(Gm[t, s]) for s in B] + groups[tuple(x * v[0] for x in v)][t] = v[0] + for pat, rd in groups.items(): + census[len(rd)] += 1 + if len(rd) == EXPECTED['face_reach']: + faces.append((B, pat, rd)) + return sorted(faces, key=lambda f: (f[0], f[1])), census + + +def keys_of(faces, P): + """keys = pairs of faces of different blocks without common source, with relative sign rho = +-1 on at least 3 common + readers. Returns [(i, j, rho, sorted tuple of the common readers with that relative sign)].""" + blk = P['blk'] + out = [] + for i, j in itertools.combinations(range(len(faces)), 2): + Bi, _, Ri = faces[i] + Bj, _, Rj = faces[j] + if blk[Bi[0]] == blk[Bj[0]] or set(Bi) & set(Bj): + continue + common = set(Ri) & set(Rj) + for rho in (1, -1): + rd = [t for t in common if Ri[t] * Rj[t] == rho] + if len(rd) >= 3: + out.append((i, j, rho, tuple(sorted(rd)))) + return out + + +def f2_rank(vs): + return len(dg.f2_reduce(vs)) + + +def mate_matching(P, S8, T): + """size (0, 1 or 2) of a maximum matching of mates among the (four) readers T of a key with source set S8.""" + Gm, ADJ, n = P['Gm'], P['ADJ'], P['n'] + + def mate(t1, t2): + r = Gm[t1, S8[0]] * Gm[t2, S8[0]] + a = [s for s in range(n) if ADJ[t1, s] and ADJ[t2, s] and Gm[t1, s] * Gm[t2, s] == r] + return len(a) >= len(S8) + 8 + + G = [(a, b) for a, b in itertools.combinations(T, 2) if mate(a, b)] + if any(len(set(p) | set(q)) == 4 for p, q in itertools.combinations(G, 2)): + return 2 + return 1 if G else 0 + + +# --------------------------------------------------------------------------------------------------------------- +# Edge covers and waste +# --------------------------------------------------------------------------------------------------------------- +def block_births(options): + """options[f] = list of candidate splits of face f into two edge-variants; a split is [(edge, variant), (edge, variant)]. + For every choice of one split per face (exhaustively) compute: waste = number of edges used with exactly one sign variant, + births_0 = sum over sources of (number of distinct edges at the source - 1), births_1 = sum over used edge variants of + (number of faces using it - 1). Returns the list of (births, waste, edges, births_0, births_1) over all choices.""" + res = [] + for ch in itertools.product(*[range(len(o)) for o in options]): + used = defaultdict(set) + cnt = Counter() + for o, c in zip(options, ch): + for e, v in o[c]: + used[e].add(v) + cnt[(e, v)] += 1 + deg = Counter(x for e in used for x in e) + b0 = sum(d - 1 for d in deg.values()) + b1 = sum(u - 1 for u in cnt.values()) + res.append((b0 + b1, sum(1 for v in used.values() if len(v) == 1), len(used), b0, b1)) + return res + + +def face_splits(P, faces, kind): + """per block: for each face of the block, its splits into two edge-variants, where an edge is a pair of sources and its + variant the product of the face signs at its two ends. kind 'tetrad': the one split into two pairs inside the two + tetrads of the face; kind 'cross': the two splits whose pairs join the two tetrads.""" + tet = P['tet'] + byblk = defaultdict(list) + for B, pat, rd in faces: + s = dict(zip(B, pat)) + a = [x for x in B if tet[x] == tet[B[0]]] + c = [x for x in B if tet[x] != tet[B[0]]] + assert len(a) == 2 and len(c) == 2 + if kind == 'tetrad': + splits = [[(a[0], a[1]), (c[0], c[1])]] + else: + splits = [[(a[0], c[0]), (a[1], c[1])], [(a[0], c[1]), (a[1], c[0])]] + byblk[int(P['blk'][B[0]])].append([[(tuple(sorted(e)), s[e[0]] * s[e[1]]) for e in sp] for sp in splits]) + return byblk + + +def waste_min_all_splits(faces, tl=120): + """CP-SAT: choose one of the 3 splits of every face into two pairs (the tetrad split and the two cross splits) so that the + number of edges used with exactly one sign variant is minimal. Returns (optimum, status name, number of candidate edges).""" + m = cp_model.CpModel() + var = {0: {}, 1: {}} # variant +1 -> 0, -1 -> 1 : edge -> Bool "variant used" + + def v(variant, e): + d = var[0 if variant == 1 else 1] + if e not in d: + d[e] = m.NewBoolVar('') + return d[e] + + for B, pat, rd in faces: + s = dict(zip(B, pat)) + opts = [] + for part in ((0, 1), (0, 2), (0, 3)): + e1 = tuple(sorted((B[part[0]], B[part[1]]))) + rest = [i for i in range(4) if i not in part] + e2 = tuple(sorted((B[rest[0]], B[rest[1]]))) + z = m.NewBoolVar('') + opts.append(z) + for e in (e1, e2): + m.AddImplication(z, v(s[e[0]] * s[e[1]], e)) + m.AddExactlyOne(opts) + edges = set(var[0]) | set(var[1]) + obj = [] + for e in edges: + a, b = v(1, e), v(-1, e) + both = m.NewBoolVar('') + m.Add(both <= a) + m.Add(both <= b) + obj.append(a + b - 2 * both) + m.Minimize(sum(obj)) + solver = cp_model.CpSolver() + solver.parameters.max_time_in_seconds = tl + solver.parameters.num_workers = 4 + solver.parameters.random_seed = 1 + status = solver.Solve(m) + return int(round(solver.ObjectiveValue())), solver.StatusName(status), len(edges) + + +def main(): + P = dg.p112() + n, ports, Gm, ADJ, blk, tet = P['n'], P['ports'], P['Gm'], P['ADJ'], P['blk'], P['tet'] + word = dg.word531() + ok = (all(int(ADJ[t].sum()) == 52 for t in range(n)) and Counter(blk.tolist()) == Counter({b: 8 for b in range(14)}) + and Counter(tet.tolist()) == Counter({x: 4 for x in range(28)}) + and all((bin(ports[s] & ports[t]).count('1') % 2 == 0) == bool(ADJ[t, s]) for s in range(n) for t in range(n) if s != t)) + check('D3.geometry', ok, '112 sources in 14 blocks of 8 (28 tetrads of 4), 52 readers each; two sources are adjacent iff their ports are orthogonal in F_2^9') + + # ===== faces: the block-local planes ======================================================================== + faces, census = block_local_faces(P) + per_block = Counter(int(blk[f[0][0]]) for f in faces) + ranks = Counter(f2_rank([ports[s] for s in f[0]]) for f in faces) + tet_shape = Counter(tuple(sorted(Counter(int(tet[s]) for s in f[0]).values())) for f in faces) + plane = all(ports[f[0][0]] ^ ports[f[0][1]] ^ ports[f[0][2]] ^ ports[f[0][3]] == 0 for f in faces) + ok = (len(faces) == EXPECTED['faces'] and per_block == Counter({b: EXPECTED['faces_per_block'] for b in range(14)}) + and ranks == Counter({EXPECTED['face_rank']: 168}) and tet_shape == Counter({(2, 2): 168}) and plane + and max(census) == EXPECTED['face_reach']) + check('D3.faces', ok, + '%d block-local faces of reach %d (%d per block; no block-local 4-set has a larger reach), four ports adding to 0 (rank %d), each made ' + 'of 2 sources in each tetrad of its block' % (len(faces), EXPECTED['face_reach'], EXPECTED['faces_per_block'], EXPECTED['face_rank'])) + + edges = {tuple(sorted(s for s in f[0] if tet[s] == t)) for f in faces for t in {int(tet[s]) for s in f[0]}} + deg = Counter(s for e in edges for s in e) + births0 = sum(d - 1 for d in deg.values()) + ok = (len(edges) == EXPECTED['edges'] and set(deg.values()) == {EXPECTED['edge_degree']} and len(deg) == 112 and births0 == EXPECTED['carriers']) + check('D3.edges', ok, '%d tetrad edges, every source in %d of them: births of the sources %d = 2 x %d - 112' + % (len(edges), EXPECTED['edge_degree'], births0, len(edges))) + + # ===== keys ================================================================================================ + kl = keys_of(faces, P) + keys = [(tuple(sorted(faces[i][0] + faces[j][0])), i, j, rho, T) for i, j, rho, T in kl] + uses = Counter() + for _, i, j, _, _ in keys: + uses[i] += 1 + uses[j] += 1 + kr = Counter(len(T) for *_, T in keys) + krank = Counter(f2_rank([ports[s] for s in S8]) for S8, *_ in keys) + ok = len(keys) == EXPECTED['keys'] and dict(kr) == EXPECTED['key_readers'] and Counter(uses.values()) == Counter(EXPECTED['face_uses']) \ + and len(uses) == 168 and dict(krank) == EXPECTED['key_rank'] + check('D3.keys', ok, '%d keys = pairs of planes of two blocks with 4 common readers (the only plane pairs with >= 3 common readers); ' + 'every plane lies in exactly 2 keys; key frames have rank 5' % len(keys)) + + def contains(Fa, Fb): + return f2_rank(Fb + Fa) == f2_rank(Fb) + + cons = defaultdict(list) + for S8, i, j, rho, T in keys: + fr8 = [ports[s] for s in S8] + cons[i].append(fr8) + cons[j].append(fr8) + width = Counter() + for i, (a, b) in ((i, l[:2]) for i, l in cons.items()): + width[2 if not (contains(a, b) or contains(b, a)) else 1] += 1 + copies = sum(w - 1 for w, c in width.items() for _ in range(c)) + ok = dict(width) == EXPECTED['nested_width'] and copies == EXPECTED['face_copies'] + check('D3.face-copies', ok, 'the frames of the two keys using a plane are not nested for %d/168 planes: %d face copies (= 2K - N2 = 2 x %d - %d)' + % (width[2], copies, len(keys), len(faces))) + + mu = Counter(mate_matching(P, S8, list(T)) for S8, i, j, rho, T in keys) + hosts = sum(len(T) - mate_matching(P, S8, list(T)) for S8, i, j, rho, T in keys) - word['report']['borrowed_output_pairs'] + ok = dict(mu) == EXPECTED['mate_matching'] and word['report']['borrowed_output_pairs'] == EXPECTED['borrowed'] and hosts == EXPECTED['hosts'] + check('D3.hosts', ok, 'the mates of the 4 readers of a key form a matching of size 2 for %d/168 keys: hosts R = sum(|T| - mu) - %d = %d' + % (mu[2], EXPECTED['borrowed'], hosts)) + + # ===== the ledger ========================================================================================== + N2, K, R, waste = len(faces), len(keys), hosts, 0 + scratch, face, mcop = 2 * N2 - 112 + waste, 2 * K - N2, R - K + B = N2 + K + R - 112 + waste + ok = ((scratch, face, mcop) == EXPECTED['classes'] and B == scratch + face + mcop == EXPECTED['total'] == word['report']['R'] + and scratch == births0 and face == copies and len(edges) * 2 - 112 == scratch) + check('D3.ledger', ok, 'B = N2 + K + R - 112 + waste = %d + %d + %d - 112 + %d = %d = helper count of the word of PR #531; classes: %d scratch ' + '(carriers), %d face copies, %d M copies; the identity agrees with the direct counts %d (source births) and %d (face copies)' + % (N2, K, R, waste, B, scratch, face, mcop, births0, copies)) + + # ===== carriers are register-neutral ========================================================================== + tet_b = face_splits(P, faces, 'tetrad') + cross_b = face_splits(P, faces, 'cross') + base = [block_births(tet_b[b]) for b in range(14)] + best_tet = [min(r) for r in base] + cross = [block_births(cross_b[b]) for b in range(14)] + best = [min(r) for r in cross] + identity = all(r[0] == 2 * 12 - 8 + r[1] for blk_res in (base + cross) for r in blk_res) # births = 2 N2 - 8 + waste, per block + total_tet = sum(x[0] for x in best_tet) + total_cross = sum(x[0] for x in best) + ok = (tuple(best[0]) == EXPECTED['cross_block_best'] and len(set(best)) == 1 and total_tet == EXPECTED['carriers'] + and total_cross == EXPECTED['cross_total'] and total_cross - total_tet == EXPECTED['cross_extra'] + and all(x[1] == 0 for x in best_tet) and sum(x[1] for x in best) == 14 * EXPECTED['cross_waste'] and identity) + check('D3.carriers-neutral', ok, + 'the same 168 planes rebuilt from edges joining the two tetrads of a block cost %d registers instead of %d: +%d (%d wasted single-variant ' + 'butterflies per block, optimal over all 2^12 choices of split); for every choice births = 2 N2 - 112 + waste, tetrad edges waste 0' + % (total_cross, total_tet, total_cross - total_tet, best[0][1])) + + opt, status, nedges = waste_min_all_splits(faces) + check('D3.waste-min', (opt, status, nedges) == (EXPECTED['waste_min'], 'OPTIMAL', EXPECTED['candidate_edges']), + 'CP-SAT over all 3 splits of every plane (%d candidate edges): minimum waste %d, status %s (the tetrad splits attain it)' + % (nedges, opt, status)) + + +main() +finish() diff --git a/research/format-limits/scripts/d_geometry.py b/research/format-limits/scripts/d_geometry.py new file mode 100644 index 0000000000..8dd30ebc39 --- /dev/null +++ b/research/format-limits/scripts/d_geometry.py @@ -0,0 +1,452 @@ +"""Geometry shared by the design-free lower-bound checks d1_cover_numbers.py, d2_coupled_count.py, d3_carrier_ledger.py. + +Two incidence geometries are used. + +* E8 (bit side, PR #555). The 240 roots of E8 are scaled to norm 4 and live in {-2..2}^8 with even pairwise inner + products; a "line" is a pair {r, -r}, so there are 120 lines. The word of PR #555 uses 111 of them as sources; the other 9 + are punctured. Two lines are orthogonal iff their inner product is 0. For a line s the 63 lines orthogonal to s form an + E7 line system of rank 7; its flats of rank 6 are the "hyperplane flats". +* P112 (complex side, PR #531). The 112 ports are vectors of F_2^9 (odd weight), two ports are orthogonal iff their + F_2 dot product is 0. The root lines of PR #531's geometry file give a second description of the same 112 points, used + by d3 (blocks, tetrads, signed adjacency). + +All arithmetic is exact (integers); floating point is used only to group vectors by direction and every grouping result is +re-verified with integer arithmetic where it matters. +""" +import functools +import itertools +import sys + +sys.dont_write_bytecode = True # never write __pycache__ next to files of main + +import numpy as np + +from report import VENDOR, load_json, main_file + +# --------------------------------------------------------------------------------------------------------------- +# F_2 helpers +# --------------------------------------------------------------------------------------------------------------- + + +def pdot(a, b): + """F_2 dot product of two bit vectors stored as ints.""" + return (a & b).bit_count() & 1 + + +def f2_reduce(vs): + """a basis (list of ints) of the F_2 span of vs, built by xor-min reduction.""" + b = [] + for v in vs: + for x in b: + v = min(v, v ^ x) + if v: + b.append(v) + return b + + +def f2_inspan(v, basis): + for x in basis: + v = min(v, v ^ x) + return v == 0 + + +if hasattr(np, 'bitwise_count'): # numpy >= 2.0 + def popcount(x): + """number of set bits of every element of an unsigned integer array.""" + return np.bitwise_count(x).astype(np.int64) +else: + def popcount(x): + x = np.ascontiguousarray(x) + return np.unpackbits(x.view(np.uint8)).reshape(x.shape + (8 * x.dtype.itemsize,)).sum(axis=-1).astype(np.int64) + + +def orth_tables(ports, nbits=9): + """ORTH[w] (w in 0..2^nbits-1) = bit mask over the ports i with ports[i] . w = 0, plus the two 64-bit halves as + uint64 arrays (the 112 ports need 112 bits).""" + orth = [sum(1 << i for i, p in enumerate(ports) if not pdot(p, w)) for w in range(1 << nbits)] + m64 = (1 << 64) - 1 + lo = np.array([o & m64 for o in orth], dtype=np.uint64) + hi = np.array([o >> 64 for o in orth], dtype=np.uint64) + return orth, lo, hi + + +def subspace_bases(m, nbits=9, chunk=1 << 14): + """yield int64 arrays of shape (n, m); each row of an array is the reduced-row-echelon basis of one m-dimensional + subspace of F_2^nbits, and every subspace occurs exactly once (the number of subspaces is the Gaussian binomial).""" + if m == 0: + yield np.zeros((1, 0), dtype=np.int64) + return + for piv in itertools.combinations(range(nbits), m): # leading-bit positions of the m rows + pivset = set(piv) + free = [[b for b in range(p) if b not in pivset] for p in piv] + tot = sum(len(f) for f in free) + for start in range(0, 1 << tot, chunk): + bits = np.arange(start, min(start + chunk, 1 << tot), dtype=np.int64) + rows = np.empty((len(bits), m), dtype=np.int64) + sh = 0 + for i in range(m): + v = np.full(len(bits), 1 << piv[i], dtype=np.int64) + for k, b in enumerate(free[i]): + v |= ((bits >> (sh + k)) & 1) << b + sh += len(free[i]) + rows[:, i] = v + yield rows + + +# --------------------------------------------------------------------------------------------------------------- +# P112 (PR #531) +# --------------------------------------------------------------------------------------------------------------- +WORD531 = 'research/direct-delivery504-global/evidence/local/FULL-WORD.json.gz' +PROTO531 = 'research/direct-delivery504-global/inputs/hamming/PROTOTYPE.json' +GK_WORD = 'research/direct-delivery504-global/vendor/gk/gk_word.py' +GK_COMMON = 'research/direct-delivery504-global/vendor/gk/gk_common.py' + + +@functools.lru_cache(None) +def word531(): + """the complex word of PR #531 (a file of main).""" + return load_json(main_file(WORD531)) + + +@functools.lru_cache(None) +def cx_ports(): + """the 112 ports of P112 as 9-bit integers (orthogonality = even F_2 dot product).""" + return tuple(word531()['ports']) + + +@functools.lru_cache(None) +def p112(): + """P112 with its root-line description (PR #531's geometry file, lines 8..119): returns a dict with + ports, root lines RL, the signed adjacency Gm[t,s] = (RL_t . RL_s)/2, ADJ = (Gm != 0), the 14 blocks (supports of + the root lines), the parity par (number of minus signs mod 2) and the tetrad id tet = 2*block + par (28 tetrads).""" + D = load_json(main_file(PROTO531)) + ports = [D['binary_ports'][i] for i in range(8, 120)] + RL = [D['root_lines'][i] for i in range(8, 120)] + assert tuple(ports) == cx_ports() and RL == word531()['root_lines'] + n = 112 + Gm = np.array([[sum(x * y for x, y in zip(RL[t], RL[s])) // 2 for s in range(n)] for t in range(n)], dtype=np.int8) + np.fill_diagonal(Gm, 0) + ADJ = Gm != 0 + assert (ADJ == ADJ.T).all() + supp = [tuple(i for i in range(8) if RL[s][i]) for s in range(n)] + blocks = sorted(set(supp)) + blk = np.array([blocks.index(supp[s]) for s in range(n)]) + par = np.array([sum(RL[s][i] < 0 for i in supp[s]) % 2 for s in range(n)]) + tet = blk * 2 + par + return dict(n=n, ports=ports, RL=RL, Gm=Gm, ADJ=ADJ, blk=blk, par=par, tet=tet, nblocks=len(blocks)) + + +@functools.lru_cache(None) +def gk(): + """PR #531's word helpers (gk_word.py / gk_common.py of main): basis(), perp(), FULL.""" + p = main_file(GK_WORD) + main_file(GK_COMMON) # imported by gk_word.py from the same directory + sys.path.insert(0, str(p.parent)) + import gk_word + return gk_word + + +def cx_section_covers(): + """covers of the readers of a source by sections, for every source s of P112. The readers are T(s) = the ports orthogonal + to u_s (52 of them); a section is T(s) & {t : t.w = 0} for a vector w outside (a frame of dimension 2); it + is proper if it is not all of T(s). "all" uses every w in F_2^9, "closed" only those w for which w or u_s + w is a port + (frames spanned by ports). For each family returns the largest section size over all sources, the number of sources + whose readers are covered by two proper sections, the largest leftover (uncovered readers) after the best two, and the + number of improper sections (w outside whose section is all of T(s); zero means the readers of s span u_s^perp, so no + single frame serves them all and the cover number is exactly 2). The orthogonality relation of P112 is symmetric, so the + same numbers hold for the sources lying in the perp of a terminal.""" + ports = cx_ports() + orth, _, _ = orth_tables(ports) + out = dict(readers=set(), max_all=0, max_closed=0, cover2_all=0, cover2_closed=0, left_all=0, left_closed=0, + improper_all=0, improper_closed=0) + m64 = (1 << 64) - 1 + + def words(masks): + return np.array([[m & m64, m >> 64] for m in masks], dtype=np.uint64) + + for s, us in enumerate(ports): + T = orth[us] + out['readers'].add(T.bit_count()) + secs = {T & orth[w] for w in range(1, 512) if w != us} + closed = {T & orth[w] for w in ({p for p in ports if p != us} | {p ^ us for p in ports if p != us})} + for key, fam in (('all', secs), ('closed', closed)): + out['improper_' + key] += int(T in fam) + fam = sorted(fam - {T}) # proper sections only + out['max_' + key] = max(out['max_' + key], max(x.bit_count() for x in fam)) + best = max_pair_union(words(fam)) + out['left_' + key] = max(out['left_' + key], T.bit_count() - best) + out['cover2_' + key] += (best == T.bit_count()) + return out + + +# --------------------------------------------------------------------------------------------------------------- +# E8 (PR #555) +# --------------------------------------------------------------------------------------------------------------- +BIT_WORD = VENDOR / 'pr555' / 'bitE8mut-p111.json.gz' + + +@functools.lru_cache(None) +def bit_word(): + return load_json(BIT_WORD) + + +@functools.lru_cache(None) +def e8(): + """the 120 lines of E8 (integer vectors of norm 4, one representative per +-pair, sorted), the 111 live source lines of + PR #555's word (srcid[i] = line index of the i-th source) and the inner-product matrix G. + + The lines are the norm-4 vectors with entries in {-2..2} that have even inner product with every live line; the + candidates are the vectors (+-2, 0, ..., 0) and (+-1, +-1, +-1, +-1, 0, 0, 0, 0).""" + live = np.array(bit_word()['lines'], dtype=np.int64) + cands = [] + for i in range(8): + for s in (2, -2): + v = [0] * 8 + v[i] = s + cands.append(v) + for pos in itertools.combinations(range(8), 4): + for sg in itertools.product((1, -1), repeat=4): + v = [0] * 8 + for p, s in zip(pos, sg): + v[p] = s + cands.append(v) + C = np.array(cands, dtype=np.int64) + roots = C[((C @ live.T) % 2 == 0).all(axis=1)] + canon = lambda a: max(tuple(a), tuple(-x for x in a)) + L = np.array(sorted({canon(r) for r in roots.tolist()}), dtype=np.int64) + assert len(roots) == 240 and len(L) == 120 + index = {tuple(l): i for i, l in enumerate(L.tolist())} + srcid = [index[canon(a)] for a in live.tolist()] + assert len(set(srcid)) == 111 + isl = np.zeros(120, dtype=bool) + isl[srcid] = True + G = L @ L.T + return dict(L=L, srcid=srcid, isl=isl, G=G, index=index, canon=canon) + + +def e8_line_index(v): + E = e8() + return E['index'][E['canon'](tuple(int(x) for x in v))] + + +def e7_of(q): + """indices of the 63 lines orthogonal to line q.""" + G = e8()['G'] + return [j for j in range(120) if G[q, j] == 0] + + +@functools.lru_cache(None) +def e8_isometries(): + """for every line q a matrix g_q (8x8, float with exact binary entries) of the E8 symmetry group generated by the + reflections in the roots, with g_q(line s0) = +-(line q), where s0 = line of the first live source; and the induced + permutation perm_q of the 120 lines (line i is sent to line perm_q[i]).""" + E = e8() + L = E['L'].astype(float) + s0 = E['srcid'][0] + refl = [np.eye(8) - np.outer(L[i], L[i]) / 2.0 for i in range(120)] + g = {s0: np.eye(8)} + todo = [s0] + while todo: + a = todo.pop() + for r in range(120): + m = refl[r] @ g[a] + b = e8_line_index(np.rint(m @ L[s0]).astype(int)) + if b not in g: + g[b] = m + todo.append(b) + assert len(g) == 120 + perms = {} + for q, m in g.items(): + img = np.rint(L @ m.T).astype(int) + perms[q] = np.array([e8_line_index(v) for v in img]) + assert sorted(perms[q]) == list(range(120)) + return s0, g, perms + + +# --- flats of a vector configuration -------------------------------------------------------------------------- + + +def flat_lattice(V, top_rank): + """all flats of the matroid of the rows of V (float array, rows are vectors) of rank 1..top_rank, as int bit masks. + A flat of rank k+1 is the closure of a flat F of rank k together with one more vector, so level k+1 is found by + grouping the vectors outside F by the direction of their component orthogonal to span(F). + returns {rank: sorted list of masks}.""" + n = len(V) + levels = {} + level = {0} + for k in range(1, top_rank + 1): + nxt = set() + for mask in level: + idx = [i for i in range(n) if mask >> i & 1] + if idx: + U, S, _ = np.linalg.svd(V[idx].T, full_matrices=False) + Q = U[:, S > 1e-9] + Rr = V - (V @ Q) @ Q.T + else: + Rr = V.copy() + nrm = np.linalg.norm(Rr, axis=1) + out = [i for i in range(n) if nrm[i] > 1e-9] + Rn = Rr[out] / nrm[out][:, None] + same = np.abs(Rn @ Rn.T) > 1 - 1e-9 + seen = set() + for a in range(len(out)): + if a in seen: + continue + grp = np.nonzero(same[a])[0] + seen.update(grp.tolist()) + m = mask + for g_ in grp: + m |= 1 << out[g_] + nxt.add(m) + level = nxt + levels[k] = sorted(level) + return levels + + +@functools.lru_cache(None) +def e7_flats(): + """flats of ranks 1..6 of the E7 line system E7(s0) (the 63 lines orthogonal to the line s0 of the first live source). + returns (E7 line indices, {rank: masks over the 63 positions}); the rank-6 flats are the hyperplane flats.""" + E = e8() + s0 = E['srcid'][0] + idx = e7_of(s0) + assert len(idx) == 63 + V = E['L'][idx].astype(float) + assert np.linalg.matrix_rank(V) == 7 + return idx, flat_lattice(V, 6) + + +def rank_mod_p(rows, p=1000003, want=None): + """rank of an integer matrix modulo the prime p (stops early once the rank reaches want). For the 8-column matrices of + norm-4 vectors used here every nonzero 6x6 minor is at most 2^6 < p in absolute value, so the rank mod p equals the + rank over the rationals as long as the rank is at most 6.""" + rows = [[x % p for x in r] for r in rows] + rk = 0 + ncol = len(rows[0]) + for c in range(ncol): + piv = next((i for i in range(rk, len(rows)) if rows[i][c]), None) + if piv is None: + continue + rows[rk], rows[piv] = rows[piv], rows[rk] + inv = pow(rows[rk][c], -1, p) + rows[rk] = [(x * inv) % p for x in rows[rk]] + for i in range(len(rows)): + if i != rk and rows[i][c]: + f = rows[i][c] + rows[i] = [(x - f * y) % p for x, y in zip(rows[i], rows[rk])] + rk += 1 + if want is not None and rk >= want: + break + return rk + + +def certify_hyperplane_flats(masks): + """exact (integer) certificate that every mask is a hyperplane flat of E7(s0). For a mask with member lines l_1..l_k the + vector s0 and the members span a hyperplane n^perp of R^8; n is found numerically, scaled to an integer vector and then + checked EXACTLY: (i) the lines of E7(s0) with n . l = 0 are precisely the members (so the mask is closed under taking + the span), and (ii) the members have rank 6 (computed modulo a prime larger than every nonzero 6x6 minor).""" + E = e8() + idx, _ = e7_flats() + E7 = E['L'][idx] + sv = E['L'][E['srcid'][0]] + for m in masks: + members = [i for i in range(63) if m >> i & 1] + A = np.vstack([E7[members], sv[None, :]]).astype(float) + _, S, Vt = np.linalg.svd(A) + assert S[6] > 1e-6 and S[7] < 1e-9 + nv = Vt[7] + nz = np.abs(nv) > 1e-9 + nn = nv / np.abs(nv[nz]).min() + for t in range(1, 49): + if np.abs(t * nn - np.rint(t * nn)).max() < 1e-7: + break + else: + raise AssertionError('normal vector is not rational with small denominator') + n = np.rint(t * nn).astype(np.int64) + assert (E7 @ n == 0).tolist() == [bool(m >> i & 1) for i in range(63)], 'flat is not closed' + assert int(sv @ n) == 0 + assert rank_mod_p(E7[members].tolist(), want=6) == 6 + return len(masks) + + +def max_pair_union(words): + """maximum, over unordered pairs (a, b) of rows (a = b allowed), of the number of set bits in the union of two rows; + words: (n, k) uint64 array (the bit sets). Exact; pairs are pruned with |a|+|b| <= current best.""" + sizes = popcount(words).sum(axis=1) + order = np.argsort(-sizes, kind='stable') + W, S = words[order], sizes[order] + best = 0 + neg = -S + for i in range(len(W)): + if 2 * S[i] <= best: + break + cnt = int(np.searchsorted(neg, -(best - S[i]), side='left')) # rows j with S[j] > best - S[i] + cnt = max(cnt, i + 1) + u = popcount(W[i][None, :] | W[i:cnt]).sum(axis=1) + best = max(best, int(u.max())) + return best + + +def masks_to_words(masks, nbits): + """list of int bit masks -> (n, ceil(nbits/64)) uint64 array.""" + k = (nbits + 63) // 64 + m64 = (1 << 64) - 1 + return np.array([[(m >> (64 * j)) & m64 for j in range(k)] for m in masks], dtype=np.uint64) + + +def find_triple_cover(words, universe): + """indices (i, j, k) of three rows of words (an (n, w) uint64 array) whose union is the universe (a (w,) uint64 row), or + None. For every pair (i, j) the rows containing the leftover are searched.""" + n = len(words) + for i in range(n): + for j in range(i, n): + left = universe & ~(words[i] | words[j]) + ok = np.nonzero(((words & left) == left).all(axis=1))[0] + if len(ok): + return i, j, int(ok[0]) + return None + + +def single_cut_bounds(nsrc, nterm, leftover, cmin): + """lower bounds on the number of helper registers from the cover numbers at the two ends of the chains. + nsrc sources (and nsrc targets, so 2 nsrc data registers), nterm terminals; cmin = cover number (every source and every + terminal needs cmin crossing registers at its end); leftover = number of readers that the best (cmin-1) sections leave + uncovered (the readers a further register must serve). + * strict (every data register may serve as a crossing register, each crossing a level at most once): the cmin x nsrc + crossings needed at the source end and cmin x nterm at the terminal end are supplied by at most 2 nsrc data registers, + so R >= max(cmin nsrc - 2 nsrc, cmin nterm - 2 nsrc, 0). + * sink-only (a target register is only a destination, so it can serve a single reader of a source): a source can do + with one helper fewer only if `leftover` targets serve its leftover readers one by one; nsrc targets allow that for at + most floor(nsrc / leftover) sources, so R >= (cmin - 1) nsrc - floor(nsrc / leftover). + returns (sink-only bound, strict bound).""" + data = 2 * nsrc + sink = (cmin - 1) * nsrc - nsrc // leftover + strict = max(cmin * nsrc - data, cmin * nterm - data, 0) + return sink, strict + + +# --- paths of the registers of the word of PR #555 -------------------------------------------------------------- + + +@functools.lru_cache(None) +def bit_paths(): + """replay the frame changes of PR #555's word. Each register r (0..110 sources x, 111..221 targets y, then 439 + helpers) starts in frame w['start'][r]; every gate (phases D, A, B, C in this order) [f, dst, srcs] moves dst and the + srcs into frame f; finally every register is moved to its final frame. Returns (word, dims, path) where + dims[f] = rank of frame f (span of its lines) and path[r] = list of frame indices visited by r.""" + w = bit_word() + lines = np.array(w['lines'], dtype=float) + dims = [int(np.linalg.matrix_rank(lines[F])) if F else 0 for F in w['frames']] + cur = list(w['start']) + path = [[f] for f in cur] + for ph in 'DABC': + for f, dst, srcs in w[ph]: + for r in [dst] + list(srcs): + if cur[r] != f: + cur[r] = f + path[r].append(f) + for r in range(len(cur)): + if cur[r] != w['final'][r]: + path[r].append(w['final'][r]) + cur[r] = w['final'][r] + return w, dims, path diff --git a/research/format-limits/scripts/e1_run_census.py b/research/format-limits/scripts/e1_run_census.py new file mode 100644 index 0000000000..bab27fb79b --- /dev/null +++ b/research/format-limits/scripts/e1_run_census.py @@ -0,0 +1,234 @@ +"""E. Moment-cost census by register class on the frontier words #555 (bit) and #569 (complex). + +Each register's chain of frame dimensions is replayed from the published word. A run is one paid child (one change +of frame); its moment cost at the word's own root q is phi(r) = r((m/r)^q - 1), and the published global profile has +sum phi = D at q. For each class the script prints the number of registers, runs, mean run rank, interior stops per +register, its share of sum phi (F-share), and the 'all-single-run ceiling': the supplier value if every register of the +class climbed in one child (one run of rank = its total climb), with hosting held proportional (the idle remainder +absorbs the change of hosted helper mass), i.e. the most any re-scheduling of that class's stops could give. +#555: s = 9, T = 32 (288 stage-replicas), m = 64, D = 10272; #569: 72 calls, m = 73, D = 2560, with the width-7 +provider word used for all 72 calls in the class shares (the 9 four-cold calls differ in a handful of runs). +""" +from collections import Counter, defaultdict +import sys + +import numpy as np + +from report import DATA, VENDOR, check, finish, load_json, main_file, near_all + + +def root(P, m, D, hi=0.05): + f = lambda q: sum(z * r * ((m / r) ** q - 1) for r, z in P.items() if z) - D + lo = 0.0 + for _ in range(100): + mid = (lo + hi) / 2 + if f(mid) < 0: + lo = mid + else: + hi = mid + return hi + + +def runs_of(ch): + return [abs(b - a) for a, b in zip(ch, ch[1:])] + + +def hist_of(pats): + h = Counter() + for ch, z in pats.items(): + for r in runs_of(ch): + h[r] += z + return h + + +def proportional(m, D, base, rem, hel_new, hmass_new, hmass0): + """root of base + hel_new + rem rescaled so the total hosted-plus-remainder mass stays fixed""" + remmass = sum(r * z for r, z in rem.items()) + scale = (remmass + hmass0 - hmass_new) / remmass + P = Counter() + for h in (base, hel_new): + for r, z in h.items(): + P[r] += z + for r, z in rem.items(): + P[r] += z * scale + return root(P, m, D) + + +# ------------------------------------------------------------------ #555 (bit) +EXP555 = { # class: (n, runs, mean run, stops per register, F-share %, all-single-run ceiling %) + 'A line-born carriers (0,1,2,..)': (205, 1120, 1.46, 4.46, 29.5, 14.75), + 'B cell-born (0,2,..)': (153, 686, 1.78, 3.48, 21.2, 9.60), + 'C line -> quad/D6 keepers and totals (0,1,4|6,..)': (80, 349, 1.83, 3.36, 10.7, 4.35), + 'D quad-born (0,4,..)': (1, 4, 2.00, 3.00, 0.1, 0.05), +} +EXP555_DATA = {'x': (539, 1.44, 14.1), 'y': (213, 3.65, 10.4), 'copies': 0.7, 'remainder': 13.4} +w = load_json(VENDOR / 'pr555' / 'bitE8mut-p111.json.gz') +e555 = load_json(VENDOR / 'pr555' / 'EXPECTED.json') +lines = np.array(w['lines'], float) +dims = [int(np.linalg.matrix_rank(lines[F])) if F else 0 for F in w['frames']] +cur = list(w['start']) +chain = {r: [dims[cur[r]]] for r in range(len(cur))} +for ph in 'DABC': + for f, dst, srcs in w[ph]: + for r in [dst] + list(srcs): + if cur[r] != f: + chain[r].append(dims[f]) + cur[r] = f +for r in range(len(cur)): + if cur[r] != w['final'][r]: + chain[r].append(dims[w['final'][r]]) +v, R, S, m, D = 111, w['R'], 288, 64, 10272 +real = {int(r): z for r, z in e555['nine']['profile'].items()} +pats = Counter(tuple(chain[r]) for r in range(2 * v, 2 * v + R)) +hel0 = hist_of(pats) +dat = hist_of(Counter(tuple(chain[r]) for r in range(2 * v))) +rem = Counter(real) +for h in (dat, hel0, {7: 9}): + for r, z in h.items(): + rem[r] -= z * S +rem = {r: z for r, z in rem.items() if z} +base = Counter({r: z * S for r, z in dat.items()}) +base[7] += 9 * S +c0 = root(real, m, D) +phi = lambda r: r * ((m / r) ** c0 - 1) +F = lambda h, k=S: sum(z * k * phi(r) for r, z in h.items()) +hmass0 = S * sum(r * z for r, z in hel0.items()) +check('E1.#555.root', abs(c0 / 1.733052825e-3 - 1) < 1e-8 and abs(F(real, 1) - D) < 1e-6 * D, + 'root of the published profile %.9e; sum phi = D' % c0) +classes = { + 'A line-born carriers (0,1,2,..)': lambda p: p[1] == 1 and p[2] == 2, + 'B cell-born (0,2,..)': lambda p: p[1] == 2, + 'C line -> quad/D6 keepers and totals (0,1,4|6,..)': lambda p: p[1] == 1 and p[2] != 2, + 'D quad-born (0,4,..)': lambda p: p[1] == 4, +} +for name, fn in classes.items(): + sub = Counter({p: z for p, z in pats.items() if fn(p)}) + h = hist_of(sub) + n, nr, mass = sum(sub.values()), sum(h.values()), sum(r * z for r, z in h.items()) + hel = Counter(hel0) + for r, z in h.items(): + hel[r] -= z + hel[8] += n + c1 = proportional(m, D, base, rem, {r: z * S for r, z in hel.items()}, S * sum(r * z for r, z in hel.items()), hmass0) + got = (n, nr, mass / nr, (nr - n) / n, 100 * F(h) / D, 100 * (c1 / c0 - 1)) + check('E1.#555.' + name.split()[0], near_all(got, EXP555[name], (None, None, 2, 2, 1, 2)), + '%s: n %d, runs %d, mean run %.2f, stops/register %.2f, F-share %.1f%%, all-single-run ceiling %+.2f%% c' + % ((name,) + got)) +for k, rng in (('x', range(v)), ('y', range(v, 2 * v))): + h = hist_of(Counter(tuple(chain[r]) for r in rng)) + nr, mass = sum(h.values()), sum(r * z for r, z in h.items()) + got = (nr, mass / nr, 100 * F(h) / D) + check('E1.#555.data-' + k, near_all(got, EXP555_DATA[k], (None, 2, 1)), 'data %s: runs %d, mean run %.2f, F-share %.1f%%' % ((k,) + got)) +got = (100 * F({7: 9}) / D, 100 * F(rem, 1) / D) +check('E1.#555.copies-remainder', near_all(got, (EXP555_DATA['copies'], EXP555_DATA['remainder']), (1, 1)), + 'copies %.1f%%, idle remainder %.1f%% of sum phi' % got) + +# ------------------------------------------------------------------ #569 (complex) +EXP569 = {'factory': (216, 1304, 1.49, 5.04, 32.5, 16.4), 'face': (168, 696, 1.98, 3.14, 21.9, 9.1), + 'M': (112, 504, 1.43, 3.50, 12.4, 4.9)} +EXP569_OTHER = {'data': 28.3, 'centres': 1.8, 'remainder': 3.0} +sys.path.insert(0, str(main_file('research/direct-delivery504-global/vendor/gk/gk_word.py').parent)) +import gk_common as co # noqa: E402 +import gk_word as g # noqa: E402 +g.V = co.V = 112 +co.DATA = g.DATA = 7168 +V = 112 + + +def chains_gk(word): + """frame-dimension chain per register and the paid runs per register (gk_word.profile semantics: a centre's copy + descents to its served levels are paid at the cut and its later climbs start again from the centre frame).""" + R = word['report']['R'] + n = 2 * V + R + P = word['ports'] + cur = {} + for r in range(n): + if r < V: + cur[r] = (P[r],) + elif r >= 2 * V and str(r) in word.get('start_extra', {}): + cur[r] = g.basis(word['start_extra'][str(r)]) + else: + cur[r] = () + ch = {r: [len(cur[r])] for r in range(n)} + paid = {r: [] for r in range(n)} + + def climb(r, F): + F = g.basis(F) + o = cur[r] + assert g.basis(list(o) + list(F)) == F, 'frame violation' + if o != F: + ch[r].append(len(F)) + paid[r].append(len(F) - len(o)) + cur[r] = F + lev = {int(t): g.basis(E) for t, E in word.get('target_levels', {}).items()} + for seq, part in ((word['A'], 'A'), (word['B'], 'B')): + if part == 'B': + for r, f in zip(word['centers'], word['center_frames']): + o = g.basis(f) + assert cur[r] == o, 'centre frame' + served = sorted({lev.get(e[1] - V, ()) for e in word['cut'] if e[2] == r}, key=lambda E: -len(E)) + for Lv in served: + if Lv != o: + paid[r].append(len(o) - len(Lv)) + o = Lv + for e in seq: + for r in [e[1]] + ([e[2]] if e[0] == 'add' else []): + climb(r, e[-1]) + for r in range(n): + climb(r, g.FULL if (r < V or r >= 2 * V) else g.perp(P[r - V])) + return ch, paid, R, set(word['centers']) + + +ch7, paid7, R, ctr = chains_gk(load_json(VENDOR / 'pr569' / 'width7-eight-FULL-WORD.json.gz')) +chF, paidF, RF, ctrF = chains_gk(load_json(VENDOR / 'pr569' / 'fourcold-eight-FULL-WORD.json.gz')) +runs = lambda paid, regs: Counter(x for r in regs for x in paid[r]) +m, D, CALLS = 73, 2560, 72 +dat = hist_of(Counter(tuple(ch7[r]) for r in range(2 * V))) +cen = runs(paid7, ctr) +hel = hist_of(Counter(tuple(ch7[r]) for r in range(2 * V, 2 * V + R) if r not in ctr)) +locF = runs(paidF, range(2 * V + RF)) +loc7 = runs(paid7, range(2 * V + R)) +calls = load_json(DATA / 'prices' / 'pr569-provider-calls.json')['calls'] # #569's per-call dispatch +n7 = sum(1 for _, prov in calls if prov == 'width7_eight') +assert len(calls) == CALLS and n7 == 63 +rem = {3: 1200, 7: 48, 48: 1808} # #569's idle remainder (its hosting control is recomputed in e2_helper_prices.py) +P = Counter() +for r, z in loc7.items(): + P[r] += z * n7 +for r, z in locF.items(): + P[r] += z * (CALLS - n7) +for r, z in rem.items(): + P[r] += z +PUB = {1: 169056, 2: 41184, 3: 25968, 4: 13824, 5: 4032, 6: 4032, 7: 48, 8: 576, 48: 1808} +check('E1.#569.profile', dict(P) == PUB and 73 * 7168 - sum(r * z for r, z in PUB.items()) == D, + '63 width-7 calls + 9 four-cold calls + idle remainder = the published global profile; D = %d' % D) +b0 = root(PUB, m, D) +phi = lambda r: r * ((m / r) ** b0 - 1) +F = lambda h, k=CALLS: sum(z * k * phi(r) for r, z in h.items()) +helall = Counter({r: z * CALLS for r, z in hel.items()}) +hmass0 = sum(r * z for r, z in helall.items()) +datg = Counter({r: z * CALLS for r, z in dat.items()}) +ceng = Counter({r: z * CALLS for r, z in cen.items()}) +base_b = proportional(m, D, datg + ceng, rem, helall, hmass0, hmass0) +cls = lambda h: 'factory' if h < 224 else ('face' if h < 392 else 'M') +for k in ('factory', 'face', 'M'): + sub = Counter(tuple(ch7[r]) for r in range(2 * V, 2 * V + R) if r not in ctr and cls(r - 2 * V) == k) + h = hist_of(sub) + n, nr, mass = sum(sub.values()), sum(h.values()), sum(r * z for r, z in h.items()) + single = Counter() + for p, z in sub.items(): + single[p[-1] - p[0]] += z + hel2 = Counter(helall) + for r, z in h.items(): + hel2[r] -= z * CALLS + for r, z in single.items(): + hel2[r] += z * CALLS + b2 = proportional(m, D, datg + ceng, rem, hel2, hmass0, hmass0) + got = (n, nr, mass / nr, (nr - n) / n, 100 * F(h) / D, 100 * (b2 / base_b - 1)) + check('E1.#569.' + k, near_all(got, EXP569[k], (None, None, 2, 2, 1, 1)), + '%s: n %d, runs %d, mean run %.2f, stops/register %.2f, F-share %.1f%%, all-single-run ceiling %+.1f%% b' + % ((k,) + got)) +got = (100 * F(dat) / D, 100 * F(cen) / D, 100 * F(rem, 1) / D) +check('E1.#569.data-centres-remainder', near_all(got, tuple(EXP569_OTHER.values()), (1, 1, 1)), + 'data %.1f%%, centres %.1f%%, idle remainder %.1f%% of sum phi' % got) +finish() diff --git a/research/format-limits/scripts/e2_helper_prices.py b/research/format-limits/scripts/e2_helper_prices.py new file mode 100644 index 0000000000..6608d37354 --- /dev/null +++ b/research/format-limits/scripts/e2_helper_prices.py @@ -0,0 +1,362 @@ +"""E2. What a complex helper costs, by class, on the word of PR #569 (DominikScholz). + +Question: by how many percent does the pressure root b of PR #569's global word (published conservative +b = 1.60263181098e-3) improve when ONE helper register of a given class is deleted, in all 72 calls, and the hosting is +re-optimised? The answer is the price of a helper of that class; the published word has 504 helpers per call. + +Data (all derived here; nothing is copied from the original measurement except the checked constants of EXPECTED): + * the two local words of PR #569 (data/vendor/pr569: width7_eight, fourcold_eight; PR #433's FULL-WORD format with the + start_extra / target_levels extension keys that gk_word.py reads) and PR #569's per-call dispatch + (data/prices/pr569-provider-calls.json: 63 calls use width7_eight, 9 use fourcold_eight); + * the word helpers gk_word.py / gk_common.py and PR #523's ASYNC112 hosting windows, files of main. +Per local word, replaying the frame chains register by register gives (i) the paid climbs of every register, hence the +per-call local profile LOC, and (ii) the width of every helper, 9 minus the dimension of its entrance frame, hence the +per-call demand DEM of helper widths to be hosted. For every non-centre helper the local mass (sum of its paid climbs) +equals its width, so a deleted helper takes its width out of the demand together with the same mass out of the local +profile and the total paid mass stays 520704 (D = 73 * 7168 - 520704 = 2560). + +Model of a deletion (hypothetical removal, no dependent registers): helper h leaves every call (in a call of word type +nm its climbs leave LOC[nm] and its width leaves DEM[nm]); the hosting linear programme (e_hosting.py: the relaxation of +the whole-owner hosting model of PR #523's 112-port unit) is re-solved at q = the published b; the new paid profile is the +72 local profiles plus the LP's idle remainders and its b is the moment root b_float (W = 7168). Price = percent change +of b per deleted helper. + +Cells are (role, width in the width7_eight word); the role is told by index range (h < 224 factory scratch registers, +h < 392 face copies, else M copies: 14 blocks of 16 / 12 / 8). k = 1 deletes the single helper of the cell whose local +fee is closest to the cell mean. The recorded values are reproduced to the last printed digit (HiGHS through scipy +1.17; the dual simplex and the interior-point method returned the same idle remainders and b on the cells F9, P8, P7, +M5, M4 when tried once). + +Claims: E2.inputs, E2.cells, E2.control (zero deletion), E2.k1. for the seven cells, E2.width-law, E2.table. +The eight LPs (control and seven cells) run in parallel in at most 6 processes. +""" +import multiprocessing as mp +import os +import sys +import time +from collections import Counter + +os.environ.setdefault('PYTHONDONTWRITEBYTECODE', '1') +sys.dont_write_bytecode = True + +from report import DATA, VENDOR, check, finish, load_json, main_file # noqa: E402 +import e_hosting as hosting # noqa: E402 + +V = 112 # data registers per side; helpers are registers 2 V + h +N_HELPERS = 504 # helpers per local word (h = 0..503) +N_FACTORY, N_FACE = 224, 392 # h < 224 factory scratch, h < 392 face copies, else M copies (14 blocks of 16 / 12 / 8) +M = hosting.M +CALLS = hosting.CALLS +Q_PICK = 1.6026e-3 # q at which the representative helper of a cell is chosen +PROVIDER_FILES = {'width7_eight': 'width7-eight-FULL-WORD.json.gz', 'fourcold_eight': 'fourcold-eight-FULL-WORD.json.gz'} +GK_DIR = 'research/direct-delivery504-global/vendor/gk/gk_word.py' +CELL_ORDER = ['F9', 'P9', 'P8', 'P7', 'M8', 'M5', 'M4'] + +# ---- expected values --------------------------------------------------------------------------------------------- +EXPECTED = { + # per-call local profile (rank: number of paid climbs) of each local word, from the register-by-register replay + 'LOC': {'width7_eight': {1: 2352, 2: 592, 3: 328, 4: 192, 5: 56, 6: 56, 8: 8}, + 'fourcold_eight': {1: 2320, 2: 432, 3: 456, 4: 192, 5: 56, 6: 56, 8: 8}}, + # per-call demand of helper widths (width: number of helpers) + 'DEM': {'width7_eight': {4: 8, 5: 48, 7: 32, 8: 128, 9: 288}, 'fourcold_eight': {4: 8, 5: 48, 8: 160, 9: 288}}, + 'DISPATCH': {'width7_eight': 63, 'fourcold_eight': 9}, + # PR #569's published global profile, W = 7168, and its idle remainder (rank: count) + 'PUB': {1: 169056, 2: 41184, 3: 25968, 4: 13824, 5: 4032, 6: 4032, 7: 48, 8: 576, 48: 1808}, + 'REM': {3: 1200, 7: 48, 48: 1808}, + 'MASS': 520704, 'D': 2560, + 'B_PUBLISHED': 1.602631810982070e-3, # conservative certified b of the published profile (PR #569) + # zero-deletion LP: objective (to 1e-4), idle remainder, b_float printed 1.602631811e-3 + 'CONTROL': {'obj': 78.05857, 'b': 1.602631811e-3}, + # cells: size (non-centre helpers), recorded k = 1 LP objective, b_float, and the price in percent b per helper + # (3 decimals) ; 'share' = LP objective increase / local fee saved, in percent (1 decimal) + 'CELLS': { + 'F9': dict(size=216, obj=78.30161, b=0.0016048723869705752, pct=0.140, share=6.3), + 'P9': dict(size=64, obj=78.30161, b=0.0016047716270276408, pct=0.134, share=6.6), + 'P8': dict(size=72, obj=78.64326, b=0.0016043095787383996, pct=0.105, share=17.9), + 'P7': dict(size=32, obj=78.94317, b=0.001603832889308516, pct=0.075, share=31.5), + 'M8': dict(size=56, obj=78.64326, b=0.0016044102805557185, pct=0.111, share=17.0), + 'M5': dict(size=48, obj=79.39080, b=0.0016032504527875107, pct=0.039, share=57.4), + 'M4': dict(size=8, obj=78.96089, b=0.0016033092416224345, pct=0.042, share=45.4), + }, + # offset share bands in percent by width (k = 1): w9 about 6, w8 about 18, w7 31-55, w5 57-65, w4 about 45 + 'SHARE_BANDS': {9: (5.0, 7.5), 8: (16.0, 19.0), 7: (31.0, 55.0), 5: (57.0, 65.0), 4: (43.0, 47.0)}, +} +TOL_OBJ = 1e-4 # LP objective +TOL_B_REL = 1e-9 # b against the recorded value (LP solutions agree to ~1e-14 across scipy 1.17-1.18) +TOL_TABLE_OBJ = 1e-6 # recorded table against recomputation +TOL_MASS = 1e-6 # rank mass of an LP-derived profile (floating sum of fractional remainders) +TOL_PRINTED = 6e-4 # a value printed with 3 decimals: half a unit of the last digit plus slack +TOL_SHARE = 0.06 # a share printed with 1 decimal +SHARE_ORDER = [9, 8, 7, 5] # offset share increases as the width falls through 9, 8, 7, 5 (width 4 sits between 7 and 5) + + +# ---- word replay -------------------------------------------------------------------------------------------------- +def load_gk(): + """import gk_word / gk_common of main and set them to the 112-port unit (V = 112, DATA = 7168)""" + d = main_file(GK_DIR).parent + sys.path.insert(0, str(d)) + import gk_word as g + import gk_common as co + g.V = co.V = V + g.DATA = co.DATA = hosting.W_DATA + return g + + +def per_register_climbs(word, g): + """paid climbs of every register of a gk word: {register: [climb sizes in order]}. A climb is a change of the + register's frame; its size is the rank of the paid child. This is gk_word.profile with per-register attribution + (the centre registers also pay the descents through the served target levels).""" + R = word['report']['R'] + n = 2 * V + R + P = word['ports'] + cur = {} + for r in range(n): + if r < V: + cur[r] = (P[r],) + elif r >= 2 * V: + cur[r] = g.basis(word['start_extra'][str(r)]) if str(r) in word.get('start_extra', {}) else () + else: + cur[r] = () + paid = {r: [] for r in range(n)} + + def climb(r, F): + F = g.basis(F) + o = cur[r] + assert g.basis(list(o) + list(F)) == F, ('frame violation', r, o, F) + if o != F: + paid[r].append(len(F) - len(o)) + cur[r] = F + lev = {int(t): g.basis(E) for t, E in word.get('target_levels', {}).items()} + for seq, part in ((word['A'], 'A'), (word['B'], 'B')): + if part == 'B': + for r, f in zip(word['centers'], word['center_frames']): + assert cur[r] == g.basis(f), 'centre frame' + served = sorted({lev.get(e[1] - V, ()) for e in word['cut'] if e[2] == r}, key=lambda E: -len(E)) + o = g.basis(f) + for Lv in served: + if Lv != o: + paid[r].append(len(o) - len(Lv)) + o = Lv + for e in seq: + for r in [e[1]] + ([e[2]] if e[0] == 'add' else []): + climb(r, e[-1]) + for r in range(n): + climb(r, g.FULL if (r < V or r >= 2 * V) else g.perp(P[r - V])) + return paid + + +def replay(name, g): + """paid climbs, local profile, helper widths and centres of one provider word""" + word = load_json(VENDOR / 'pr569' / PROVIDER_FILES[name]) + assert word['report']['R'] == N_HELPERS + paid = per_register_climbs(word, g) + loc = Counter() + for r, l in paid.items(): + for c in l: + loc[c] += 1 + se = word.get('start_extra', {}) + width = [9 - len(se[str(2 * V + h)]) if str(2 * V + h) in se else 9 for h in range(N_HELPERS)] + centres = {c - 2 * V for c in word['centers']} + dem = dict(sorted(Counter(width).items())) + return dict(paid=paid, loc=dict(sorted(loc.items())), width=width, dem=dem, centres=centres, + profile_g=dict(sorted(g.profile(word).items())), widths_g=g.widths_of(word)) + + +def role(h, centres): + if h in centres: + return 'C' + return 'F' if h < N_FACTORY else ('P' if h < N_FACE else 'M') + + +def fee(climbs, q): + """pressure fee of a list of paid climbs: sum r ((m / r)^q - 1)""" + return sum(c * ((M / c) ** q - 1) for c in climbs) + + +def pick_representative(cell_helpers, w7): + """the helper of the cell whose local fee (width7_eight word, q = Q_PICK) is closest to the cell mean""" + fees = {h: fee(w7['paid'][2 * V + h], Q_PICK) for h in cell_helpers} + mean = sum(fees.values()) / len(fees) + return min(cell_helpers, key=lambda h: abs(fees[h] - mean)) + + +# ---- scenarios ---------------------------------------------------------------------------------------------------- +def deleted_models(words, prov, dele): + """per-call local profiles and demands when helpers `dele` are deleted in all 72 calls (word type per call)""" + out_l, out_d = [], [] + for t in range(CALLS): + w = words[prov[t]] + l = dict(w['loc']) + d = dict(w['dem']) + for h in dele: + for c in w['paid'][2 * V + h]: + l[c] -= 1 + d[w['width'][h]] -= 1 + assert all(z >= 0 for z in l.values()) and all(z >= 0 for z in d.values()) + out_l.append({r: z for r, z in l.items() if z}) + out_d.append({x: z for x, z in d.items() if z}) + return out_l, out_d + + +def local_fee_saved(words, prov, dele, q): + tot = 0 + for t in range(CALLS): + for h in dele: + tot += fee(words[prov[t]]['paid'][2 * V + h], q) + return tot + + +def rel(a, b): + return abs(a / b - 1) + + +def main(): + t_start = time.time() + ex = EXPECTED + g = load_gk() + + # ---- E2.inputs -------------------------------------------------------------------------------------------- + pc = load_json(DATA / 'prices' / 'pr569-provider-calls.json') + calls = pc['calls'] + assert [c[0] for c in calls] == list(range(CALLS)) + prov = [c[1] for c in calls] + words = {nm: replay(nm, g) for nm in PROVIDER_FILES} + disp = dict(Counter(prov)) + loc_ok = all(words[nm]['loc'] == ex['LOC'][nm] and words[nm]['profile_g'] == ex['LOC'][nm] for nm in words) + dem = {nm: words[nm]['dem'] for nm in words} + dem_ok = all(dem[nm] == ex['DEM'][nm] and words[nm]['widths_g'] == words[nm]['width'] for nm in words) + ident_ok = all(sum(words[nm]['paid'][2 * V + h]) == words[nm]['width'][h] + for nm in words for h in range(N_HELPERS) if h not in words[nm]['centres']) + comp = Counter() + for nm in words: + for r, z in words[nm]['loc'].items(): + comp[r] += z * disp[nm] + for r, z in ex['REM'].items(): + comp[r] += z + comp = dict(sorted(comp.items())) + mass_pub = hosting.mass(comp) + check('E2.inputs', + disp == ex['DISPATCH'] and loc_ok and dem_ok and ident_ok and comp == ex['PUB'] + and mass_pub == ex['MASS'] and hosting.M * hosting.W_DATA - mass_pub == ex['D'], + 'dispatch %s; local profile width7_eight %s, fourcold_eight %s (replay = gk_word.profile); demand %s / %s; ' + 'local mass = width for the 496 non-centre helpers of each word; 63 x width7_eight + 9 x fourcold_eight local ' + 'profiles + idle remainder %s = published profile %s; mass %d, D %d' + % (disp, words['width7_eight']['loc'], words['fourcold_eight']['loc'], dem['width7_eight'], + dem['fourcold_eight'], ex['REM'], comp, mass_pub, hosting.M * hosting.W_DATA - mass_pub)) + + # ---- E2.cells --------------------------------------------------------------------------------------------- + w7 = words['width7_eight'] + cells = {} + for h in range(N_HELPERS): + cells.setdefault((role(h, w7['centres']), w7['width'][h]), []).append(h) + specs = load_json(DATA / 'prices' / 'k1-specs.json')['cells'] + dele, sizes_ok, pick_ok = {}, True, True + for c in CELL_ORDER: + key = (specs[c]['role'], specs[c]['width']) + members = cells[key] + dele[c] = specs[c]['deleted_helpers'] + sizes_ok &= len(members) == ex['CELLS'][c]['size'] and len(dele[c]) == 1 and dele[c][0] in members + pick_ok &= pick_representative(members, w7) == dele[c][0] + check('E2.cells', sizes_ok and pick_ok and len(cells[('F', 9)]) == 216 and len(w7['centres']) == 8, + 'cell sizes %s (+ 8 centre accumulators, not priced); k = 1 helper per cell %s is the helper with the local ' + 'fee closest to the cell mean' + % ({c: ex['CELLS'][c]['size'] for c in CELL_ORDER}, {c: dele[c][0] for c in CELL_ORDER})) + + # ---- the eight LPs in parallel ------------------------------------------------------------------------- + jobs = [] + for name, dl in [('ctl', [])] + [(c, dele[c]) for c in CELL_ORDER]: + out_l, out_d = deleted_models(words, prov, dl) + jobs.append((name, out_l, out_d, ex['B_PUBLISHED'])) + nproc = min(6, len(jobs)) + t_lp = time.time() + with mp.get_context('spawn').Pool(nproc) as pool: + res = {r['name']: r for r in pool.imap_unordered(hosting.run_job, jobs)} + wall_lp = time.time() - t_lp + bad = [n for n, r in res.items() if r['status'] != 0] + if bad: + check('E2.control', False, 'LP failed for %s: %s' % (bad, [res[n]['status'] for n in bad])) + finish() + return + + # ---- E2.control --------------------------------------------------------------------------------------------- + c0 = res['ctl'] + b0, obj0 = c0['b'], c0['obj'] + rem_ok = set(c0['rem']) == set(ex['REM']) and all(abs(c0['rem'][r] - z) < 1e-6 for r, z in ex['REM'].items()) + p_pub = {r: float(z) for r, z in ex['PUB'].items()} + b_pub_profile = hosting.b_float(p_pub, hosting.W_DATA) + ctl_ok = (abs(obj0 - ex['CONTROL']['obj']) < TOL_OBJ and rem_ok and rel(b0, ex['CONTROL']['b']) < 1e-9 + and rel(b0, ex['B_PUBLISHED']) < 1e-12 and rel(b_pub_profile, b0) < 1e-12 and abs(c0['mass'] - ex['MASS']) < TOL_MASS) + check('E2.control', ctl_ok, + 'zero-deletion LP objective %.5f, idle remainder %s, b_float %.9e = published conservative b %.12e ' + '(relative difference %.1e); b_float of the published profile %.9e; (%.0f s)' + % (obj0, {r: round(z, 6) for r, z in c0['rem'].items()}, b0, ex['B_PUBLISHED'], rel(b0, ex['B_PUBLISHED']), + b_pub_profile, c0['secs'])) + + # ---- E2.k1. ------------------------------------------------------------------------------------------- + shares, lfs = {}, {} + for c in CELL_ORDER: + r, e = res[c], ex['CELLS'][c] + pct = 100 * (r['b'] / b0 - 1) + lf = local_fee_saved(words, prov, dele[c], b0) + lfs[c] = lf + shares[c] = 100 * (r['obj'] - obj0) / lf + ok = (abs(r['obj'] - e['obj']) < TOL_OBJ and rel(r['b'], e['b']) < TOL_B_REL and abs(pct - e['pct']) < TOL_PRINTED + and abs(r['mass'] - ex['MASS']) < TOL_MASS) + check('E2.k1.' + c, ok, + 'delete helper %d (cell of %d): %.4f%% b per helper (printed %.3f); LP objective %.5f (+%.5f); b %.12e ' + '(recorded %.12e, relative difference %.1e); (%.0f s)' + % (dele[c][0], e['size'], pct, e['pct'], r['obj'], r['obj'] - obj0, r['b'], e['b'], rel(r['b'], e['b']), + r['secs'])) + + # ---- E2.width-law ------------------------------------------------------------------------------------------- + width_of = {c: specs[c]['width'] for c in CELL_ORDER} + dobj = {c: res[c]['obj'] - obj0 for c in CELL_ORDER} + same = all(abs(dobj[a] - dobj[b]) < 1e-9 for a in CELL_ORDER for b in CELL_ORDER if width_of[a] == width_of[b]) + bands = all(ex['SHARE_BANDS'][width_of[c]][0] <= shares[c] <= ex['SHARE_BANDS'][width_of[c]][1] + for c in CELL_ORDER) + printed = all(abs(shares[c] - ex['CELLS'][c]['share']) < TOL_SHARE for c in CELL_ORDER) + by_w = {} + for c in CELL_ORDER: + by_w.setdefault(width_of[c], []).append(shares[c]) + mono = all(max(by_w[SHARE_ORDER[i]]) < min(by_w[SHARE_ORDER[i + 1]]) for i in range(len(SHARE_ORDER) - 1)) + # price in fee units per percent of b: (local fee saved - LP objective increase) / (percent b) + conv = {c: (lfs[c] - dobj[c]) / (100 * (res[c]['b'] / b0 - 1)) for c in CELL_ORDER} + conv_ok = max(conv.values()) / min(conv.values()) < 1.02 + check('E2.width-law', same and bands and printed and mono and conv_ok, + 'hosting offset = LP objective increase / local fee saved at k = 1 (percent): ' + + ', '.join('%s (w%d) %.1f' % (c, width_of[c], shares[c]) for c in CELL_ORDER) + + '; equal widths give an identical LP objective increase (%s); the share rises as the width falls through ' + '9, 8, 7, 5 with width 4 (45) between 7 and 5; fee saved less offset per percent b (one conversion constant ' + 'for all cells, within 2%%): %.2f..%.2f' + % (', '.join('w%d %.5f' % (w, dobj[next(c for c in CELL_ORDER if width_of[c] == w)]) for w in (9, 8)), + min(conv.values()), max(conv.values()))) + + # ---- E2.table ----------------------------------------------------------------------------------------------- + tab = load_json(DATA / 'prices' / 'helper-price-table.json') + rows = {r['name']: r for r in tab['rows']} + rc = tab['control'] + tab_ok = (abs(rc['lp_objective'] - obj0) < TOL_TABLE_OBJ and rel(rc['b'], b0) < TOL_B_REL + and all(abs(rc['idle_remainder'][str(r)] - z) < 1e-6 for r, z in c0['rem'].items())) + for c in CELL_ORDER: + rw, r = rows[c + '_k1'], res[c] + tab_ok &= (rw['status'] == tab['status_recomputed'] and rw['deleted_helpers'] == dele[c] + and abs(rw['lp_objective'] - r['obj']) < TOL_TABLE_OBJ and rel(rw['b'], r['b']) < TOL_B_REL + and abs(rw['mass'] - r['mass']) < TOL_MASS and set(map(int, rw['idle_remainder'])) == set(r['rem']) + and all(abs(rw['idle_remainder'][str(k)] - z) < 1e-6 for k, z in r['rem'].items())) + tab_ok &= all(rw['status'] == (tab['status_recomputed'] if rw['name'] in {c + '_k1' for c in CELL_ORDER} + else tab['status_recorded']) for rw in tab['rows']) + tab_ok &= all(rel(100 * (rw['b'] / rc['b'] - 1) / rw['k'], rw['pct_b_per_helper']) < 1e-9 if rw['k'] else True + for rw in tab['rows']) + check('E2.table', tab_ok, + '%d recorded rows in data/prices/helper-price-table.json (all cells at k = 1, 8, 14, whole cell; mixed classes; ' + 'sub-classes): the control and the seven k = 1 rows equal the recomputation, the other rows are marked ' + '"%s", every row\'s percent per helper is consistent with its b' + % (len(tab['rows']), tab['status_recorded'])) + + print('total %.1f s (hosting LPs %.1f s wall in %d processes; machine load %s)' + % (time.time() - t_start, wall_lp, nproc, ' '.join('%.1f' % x for x in os.getloadavg()))) + finish() + + +if __name__ == '__main__': + main() diff --git a/research/format-limits/scripts/e8units.py b/research/format-limits/scripts/e8units.py new file mode 100644 index 0000000000..c4c1053bd1 --- /dev/null +++ b/research/format-limits/scripts/e8units.py @@ -0,0 +1,275 @@ +"""Geometry shared by the E8 / paired-cube checks of research/format-limits: exact linear algebra over F_2 and Q, +the 120 root lines of E8, and the 9-bit labels of a complex or bit unit. Everything is generated here; nothing is +read from a file. + +Conventions. A 'unit' on v ports has an integer Gram matrix G (diagonal 2 for E8) and F_2 labels u_T in F_2^c with +U U^T = (J + G) mod 2, i.e. = 1 + G_ST (mod 2). Vectors of F_2^n are Python integers (bit j = coordinate j) +or 0/1 numpy rows; both representations are used below and the function names say which. +Two coordinate systems of the same 120 E8 root lines are provided. standard_e8(): doubled standard coordinates +(roots +-2e_i +-2e_j and the half-integer (+-1)^8 with an even number of minus signs, G = L L^T/4); the totals +'coordinate a' used for the complex decoder are the 78 lines with a nonzero a-th coordinate. hamming_e8(): lines +numbered as in the Hamming-code construction: + lines 0..7 : the coordinate lines 2 e_a, + lines 8..119 : the 112 'code lines', for each of the 14 weight-4 words of the extended Hamming code [8,4,4] + (support i0 integer with bit j = row[j].""" + return sum(int(x) << j for j, x in enumerate(row)) + + +# --------------------------------------------------------------------------------------------------------------- +# exact rank over Q +def _reduce_int(r, pc, rr): + """r - (r[pc]/rr[pc]) rr, scaled to stay integral and divided by the content.""" + f, g = r[pc], rr[pc] + r = [g * x - f * y for x, y in zip(r, rr)] + c = math.gcd(*r) + return [x // c for x in r] if c > 1 else r + + +def rank_q(rows): + """exact rank over Q of a list of integer rows (fraction-free elimination).""" + red = [] # (pivot column, row) + for r in rows: + r = [int(x) for x in r] + for pc, rr in red: + if r[pc] != 0: + r = _reduce_int(r, pc, rr) + pc = next((j for j, x in enumerate(r) if x != 0), None) + if pc is not None: + red.append((pc, r)) + return len(red) + + +def row_basis_idx_q(rows): + """indices of a maximal independent set of rows over Q (greedy, in order).""" + chosen, red = [], [] + for i, r in enumerate(rows): + r = [int(x) for x in r] + for pc, rr in red: + if r[pc] != 0: + r = _reduce_int(r, pc, rr) + pc = next((j for j, x in enumerate(r) if x != 0), None) + if pc is not None: + red.append((pc, r)) + chosen.append(i) + return chosen + + +def gram_rank_q(L, Q, S): + """rank over Q of the Gram block L_S Q L_S^T (L integer v x h, Q integer h x h, S index list), computed on a + row basis B of L_S: rank(L_S Q L_S^T) = rank(B Q B^T) because L_S = C B with C of full column rank.""" + LS = [[int(x) for x in L[s]] for s in S] + idx = row_basis_idx_q(LS) + if not idx: + return 0 + B = [LS[i] for i in idx] + Qm = [[int(x) for x in row] for row in Q] + BQ = [[sum(b[k] * Qm[k][j] for k in range(len(b))) for j in range(len(Qm[0]))] for b in B] + BQBt = [[sum(x * y for x, y in zip(bq, b2)) for b2 in B] for bq in BQ] + return rank_q(BQBt) + + +# --------------------------------------------------------------------------------------------------------------- +# E8 +def hamming_e8(): + """(L, G): L = 120 x 8 integer root lines (norm 4), G = L L^T / 2 (diagonal 2, off-diagonal 0, +-1).""" + gen = np.array([[1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 1, 1, 1, 1], + [0, 1, 0, 1, 0, 1, 0, 1]]) + code = {tuple((np.array(c) @ gen) % 2) for c in itertools.product([0, 1], repeat=4)} + w4 = sorted(c for c in code if sum(c) == 4) + assert len(w4) == 14 + L = [tuple(2 * (np.arange(8) == a).astype(int)) for a in range(8)] + for c in w4: + idx = [i for i in range(8) if c[i]] + for sg in itertools.product([1, -1], repeat=3): + x = np.zeros(8, dtype=int) + x[idx[0]] = 1 + for k in range(3): + x[idx[k + 1]] = sg[k] + L.append(tuple(x)) + L = np.array(L, dtype=np.int64) + G = L @ L.T + assert (G % 2 == 0).all() + G = G // 2 + assert len(L) == 120 and set(np.diag(G)) == {2} and set(G[~np.eye(120, dtype=bool)].tolist()) == {-1, 0, 1} + return L, G + + +def standard_e8(): + """(L, G): the 120 root lines of E8 in doubled standard coordinates (norm 8), G = L L^T / 4. Lines 0..55 are + +-2e_i +-2e_j (i column + nvar = 0 + ylist = [] # (g, pattern, total width, cost, column) + for gi, (orp, i, r, ts) in enumerate(G): + ws, pats = patterns(r, widths, len(ts)) + for p in pats: + size = sum(c * w for c, w in zip(p, ws)) + ylist.append((gi, p, size, f_cost(r - size, q), nvar)) + nvar += 1 + for gi, (orp, i, r, ts) in enumerate(G): + for t in ts: + for w in widths: + xvars[gi, t, w] = nvar + nvar += 1 + c = np.zeros(nvar) + for gi, p, size, co, col in ylist: + c[col] = co + rows, cs, vs, beq = [], [], [], [] + nr = 0 + ybyg = defaultdict(list) + for gi, p, size, co, col in ylist: + ybyg[gi].append((p, col)) + for gi in range(len(G)): # sum_pattern y = P + for p, col in ybyg[gi]: + rows.append(nr); cs.append(col); vs.append(1.0) + beq.append(float(PORTS)); nr += 1 + for gi, (orp, i, r, ts) in enumerate(G): # hosted helpers of width w = helpers the patterns provide + for w in widths: + for t in ts: + rows.append(nr); cs.append(xvars[gi, t, w]); vs.append(1.0) + for p, col in ybyg[gi]: + n = p[widx[w]] + if n: + rows.append(nr); cs.append(col); vs.append(-float(n)) + beq.append(0.0); nr += 1 + gt = defaultdict(list) + for gi, (orp, i, r, ts) in enumerate(G): + for t in ts: + gt[t].append(gi) + for t in range(CALLS): # demand + for w in widths: + for gi in gt[t]: + rows.append(nr); cs.append(xvars[gi, t, w]); vs.append(1.0) + beq.append(float(dem_t[t].get(w, 0))); nr += 1 + Aeq = sp.csr_matrix((vs, (rows, cs)), shape=(nr, nvar)) + rows, cs, vs, bub = [], [], [], [] + nu = 0 + for gi, (orp, i, r, ts) in enumerate(G): # one helper per port family and call + for t in ts: + for w in widths: + rows.append(nu); cs.append(xvars[gi, t, w]); vs.append(1.0) + bub.append(float(PORTS)); nu += 1 + Aub = sp.csr_matrix((vs, (rows, cs)), shape=(nu, nvar)) + t0 = time.time() + res = linprog(c, A_ub=Aub, b_ub=bub, A_eq=Aeq, b_eq=beq, bounds=(0, None), method='highs', + options=dict(time_limit=time_limit)) + out = dict(status=int(res.status), obj=res.fun, secs=time.time() - t0) + if res.status == 0: + rem = defaultdict(float) + for gi, p, size, co, col in ylist: + v = res.x[col] + if v > 1e-9 and G[gi][2] - size > 0: + rem[G[gi][2] - size] += v + out['rem'] = dict(sorted(rem.items())) + return out + + +def mass(p): + return sum(r * z for r, z in p.items()) + + +def b_float(p, W): + lo, hi = 0., .01 + for _ in range(100): + q = (lo + hi) / 2 + mom = (sum(r * z / (M * W) * (M / r) ** q for r, z in p.items()) + + 32 * M * sum(p.values()) / (10 ** 16 * W) * M ** q) + if mom < 1: + lo = q + else: + hi = q + return (lo + hi) / 2 + + +def profile_with_remainder(local_profiles, rem): + """paid profile = sum of the per-call local profiles + the LP's idle remainders (rank -> count)""" + p = defaultdict(float) + for l in local_profiles: + for r, z in l.items(): + p[r] += z + for r, z in rem.items(): + p[int(r)] += float(z) + return {r: z for r, z in p.items() if z > 1e-12} + + +def run_job(job): + """worker for a process pool: job = (name, local profiles per call, demands per call, q); solves the hosting LP, + builds the paid profile and its b""" + name, out_l, out_d, q = job + o = solve_lp(out_d, q) + if o['status'] != 0: + return dict(name=name, status=o['status'], secs=o['secs']) + p = profile_with_remainder(out_l, o['rem']) + return dict(name=name, status=0, obj=o['obj'], rem={int(k): float(v) for k, v in o['rem'].items()}, + b=b_float(p, W_DATA), mass=mass(p), secs=o['secs']) diff --git a/research/format-limits/scripts/minrank_sat.py b/research/format-limits/scripts/minrank_sat.py new file mode 100644 index 0000000000..99a4a8c833 --- /dev/null +++ b/research/format-limits/scripts/minrank_sat.py @@ -0,0 +1,133 @@ +"""SAT encodings for the F_2 pairing of a decoder pattern. + +A pattern is a set of unordered 'off-cap' pairs {S, T} of ports and the question is whether there are words +u_T (and, in the asymmetric case, v_T) in F_2^c with + = 1 (unit diagonal) + = = 0 for every off-cap pair {S, T} +(symmetric case v = u). Such words exist iff the pairing matrix B = V U^T (B_TS = ) has unit diagonal, +vanishes on the pattern, and has F_2 rank at most c; the smallest c is the F_2 'minrank' of the pattern. + +Symmetry breaking. A set K of pairwise off-cap ports has B[K,K] = I forced, so U_K and V_K are invertible; the action +(U, V) -> (U P, V P^-T) of GL(c, F_2) leaves B fixed and can bring U_K to [I_|K| | 0] and V_K to [I_|K| | 0] +(for |K| = c this is U_K = V_K = I; for |K| < c the last columns of V_K are cleared with the remaining freedom of P). +In the symmetric case O(c, F_2) is transitive on orthonormal bases, so U_K = V_K = [I | 0] as well. + +solve_minrank() is the plain minrank question (gauge only when |K| = c). solve_asym() adds the gauge for any +|K| <= c and the extra constraints 'B is not symmetric' (some free pair has B_TS != B_ST) or 'B differs from B0 = +(J + G) mod 2' (some free pair), and optionally fixes U to given labels. The solver is Cadical 1.5.3 through pysat. +""" +import time + +import numpy as np +from pysat.solvers import Cadical153 + + +class CNF: + def __init__(self): + self.n = 0 + self.cl = [] + + def new(self): + self.n += 1 + return self.n + + def AND(self, a, b): + z = self.new() + self.cl += [[-z, a], [-z, b], [z, -a, -b]] + return z + + def XOR(self, a, b): + z = self.new() + self.cl += [[-z, a, b], [-z, -a, -b], [z, -a, b], [z, a, -b]] + return z + + def xorlist(self, lits): + acc = lits[0] + for l in lits[1:]: + acc = self.XOR(acc, l) + return acc + + def parity(self, lits, val): + """add the constraint xor(lits) = val.""" + if not lits: + if val: + self.cl.append([]) + return + acc = self.xorlist(lits) + self.cl.append([acc] if val else [-acc]) + + +def build(v, offpairs, c, sym, clique): + f = CNF() + U = [[f.new() for _ in range(c)] for _ in range(v)] + V = U if sym else [[f.new() for _ in range(c)] for _ in range(v)] + for T in range(v): + f.parity([f.AND(U[T][j], V[T][j]) for j in range(c)], 1) + for (S, T) in offpairs: + f.parity([f.AND(U[S][j], V[T][j]) for j in range(c)], 0) + if not sym: + f.parity([f.AND(U[T][j], V[S][j]) for j in range(c)], 0) + if clique and len(clique) == c: # U_K V_K^T = I => WLOG U_K = V_K = I + for i, T in enumerate(clique): + for j in range(c): + f.cl.append([U[T][j]] if j == i else [-U[T][j]]) + if not sym: + f.cl.append([V[T][j]] if j == i else [-V[T][j]]) + return f + + +def solve_minrank(v, offpairs, c, sym, clique): + """('SAT'|'UNSAT', seconds, variables, clauses) for words in F_2^c on the pattern.""" + f = build(v, offpairs, c, sym, clique) + s = Cadical153(bootstrap_with=f.cl) + t = time.time() + r = s.solve() + return ('SAT' if r else 'UNSAT'), round(time.time() - t, 1), f.n, len(f.cl) + + +def solve_asym(v, pattern, B0, c, mode, K, U_fixed=None): + """Existence of source labels U and sink labels W (v x c over F_2), B = W U^T, with B_TT = 1, B_TS = 0 on the + ordered pairs of `pattern`, gauge U_K = W_K = [I | 0] on the pairwise off-cap set K, and + mode 'none' : no further condition, + mode 'nonsym' : B_TS != B_ST for some free pair (T, S), + mode 'neB0' : B_TS != B0_TS for some free pair. + U_fixed (v x c 0/1 array) additionally fixes U (then K's gauge is dropped). Returns a dict with the result and, + when satisfiable, the pairing B = W U^T and its F_2 rank.""" + f = CNF() + U = [[f.new() for _ in range(c)] for _ in range(v)] + W = [[f.new() for _ in range(c)] for _ in range(v)] + Bvar = {} + + def B(T, S): + if (T, S) not in Bvar: + Bvar[(T, S)] = f.xorlist([f.AND(W[T][j], U[S][j]) for j in range(c)]) + return Bvar[(T, S)] + for T in range(v): + f.cl.append([B(T, T)]) + for (T, S) in pattern: + f.cl.append([-B(T, S)]) + if U_fixed is not None: + for T in range(v): + for j in range(c): + f.cl.append([U[T][j]] if U_fixed[T][j] else [-U[T][j]]) + else: + for i, T in enumerate(K): + for j in range(c): + f.cl.append([U[T][j]] if j == i else [-U[T][j]]) + f.cl.append([W[T][j]] if j == i else [-W[T][j]]) + free = [(T, S) for T in range(v) for S in range(v) if T != S and (T, S) not in pattern] + if mode == 'nonsym': + f.cl.append([f.XOR(B(T, S), B(S, T)) for (T, S) in free if T < S]) + elif mode == 'neB0': + f.cl.append([B(T, S) if B0[T][S] == 0 else -B(T, S) for (T, S) in free]) + s = Cadical153(bootstrap_with=f.cl) + t = time.time() + r = s.solve() + out = dict(c=c, mode=mode, result='SAT' if r else 'UNSAT', sec=round(time.time() - t, 1), vars=f.n, clauses=len(f.cl)) + if r: + m = set(x for x in s.get_model() if x > 0) + Uv = np.array([[1 if U[T][j] in m else 0 for j in range(c)] for T in range(v)], dtype=np.int64) + Wv = np.array([[1 if W[T][j] in m else 0 for j in range(c)] for T in range(v)], dtype=np.int64) + out['B'] = (Wv @ Uv.T) % 2 + out['U'], out['W'] = Uv, Wv + return out diff --git a/research/format-limits/scripts/provenance.py b/research/format-limits/scripts/provenance.py new file mode 100644 index 0000000000..8a43afd4dc --- /dev/null +++ b/research/format-limits/scripts/provenance.py @@ -0,0 +1,62 @@ +"""Step 0 of verify.sh: the package's files, its vendored inputs and the files of main it reads. + +MANIFEST.sha256 every file of the package (except MANIFEST.sha256 itself) with its sha256; a mismatch, a missing file + or an unlisted file fails. +SOURCES.json every file under data/vendor/ with the PR, author, commit and path it was copied from and the git blob + id of the original file (for a .gz copy: of the decompressed content); the blob id is recomputed here, + so anyone can compare it with `git rev-parse :`. +DEPENDS.json the files of main the checks read, by sha256. +""" +import gzip +import hashlib +import json +import os +import sys + +from report import PKG, REPO, check, finish + + +def sha256(p): + return hashlib.sha256(p.read_bytes()).hexdigest() + + +def blob_id(data): + return hashlib.sha1(b'blob %d\0' % len(data) + data).hexdigest() + + +listed, bad = set(), [] +for line in (PKG / 'MANIFEST.sha256').read_text().splitlines(): + h, rel = line.split(' ', 1) + listed.add(rel) + p = PKG / rel + if not p.is_file() or sha256(p) != h: + bad.append(rel) +present = set() +for root, dirs, files in os.walk(PKG): + dirs[:] = [d for d in dirs if d != '__pycache__'] + for f in files: + rel = os.path.relpath(os.path.join(root, f), PKG) + if rel != 'MANIFEST.sha256': + present.add(rel) +unlisted = sorted(present - listed) +check('0.manifest', not bad and not unlisted, + '%d files match MANIFEST.sha256' % len(listed) if not bad and not unlisted + else 'mismatch or missing: %s; unlisted: %s' % (bad, unlisted)) + +src = json.loads((PKG / 'SOURCES.json').read_text()) +vend = sorted(os.path.relpath(os.path.join(r, f), PKG) for r, _, fs in os.walk(PKG / 'data' / 'vendor') for f in fs) +bad = [] +for e in src['files']: + data = (PKG / e['file']).read_bytes() + if e['file'].endswith('.gz') and not e['source_path'].endswith('.gz'): + data = gzip.decompress(data) + if blob_id(data) != e['blob']: + bad.append(e['file']) +check('0.sources', not bad and sorted(e['file'] for e in src['files']) == vend, + '%d vendored files match the git blob ids of their PR commits' % len(vend) if not bad else 'blob mismatch: %s' % bad) + +dep = json.loads((PKG / 'DEPENDS.json').read_text()) +bad = [d['path'] for d in dep['files'] if not (REPO / d['path']).is_file() or sha256(REPO / d['path']) != d['sha256']] +check('0.depends', not bad, '%d files of main match DEPENDS.json (repository root %s)' % (len(dep['files']), REPO) + if not bad else 'missing or changed: %s' % bad) +finish() diff --git a/research/format-limits/scripts/report.py b/research/format-limits/scripts/report.py new file mode 100644 index 0000000000..5593062527 --- /dev/null +++ b/research/format-limits/scripts/report.py @@ -0,0 +1,60 @@ +"""Shared paths and PASS/FAIL reporting for the checks of research/format-limits. + +Every check prints one line per claim: 'PASS ' or 'FAIL ', and finish() exits +with status 1 if any claim failed. Paths: PKG is this package, DATA its data/ directory, REPO the repository root +(the package lives at REPO/research/format-limits; files of main are read from REPO and pinned in DEPENDS.json). +""" +import gzip +import json +import os +import pathlib +import sys + +HERE = pathlib.Path(__file__).resolve().parent +PKG = HERE.parent +DATA = PKG / 'data' +VENDOR = DATA / 'vendor' +REPO = pathlib.Path(os.environ.get('FORMAT_LIMITS_REPO', PKG.parent.parent)).resolve() + +_failed = [] + + +def check(cid, ok, detail=''): + print(('PASS ' if ok else 'FAIL ') + cid + (' ' + str(detail) if detail != '' else ''), flush=True) + if not ok: + _failed.append(cid) + return ok + + +def near(x, expected, places): + """x agrees with a value printed to `places` decimals: |x - expected| <= 0.6 * 10^-places (half a unit of the last + printed digit plus slack, so a float computed with a different library build cannot flip a rounding boundary).""" + return abs(float(x) - float(expected)) <= 0.6 * 10.0 ** (-places) + + +def near_all(xs, expected, places): + xs, expected = list(xs), list(expected) + return len(xs) == len(expected) and all( + (x == e) if isinstance(e, int) and not isinstance(e, bool) and p is None else near(x, e, p) + for x, e, p in zip(xs, expected, places)) + + +def finish(): + if _failed: + print('FAILED CLAIMS: ' + ' '.join(_failed), flush=True) + sys.exit(1) + + +def load_json(path): + path = pathlib.Path(path) + if path.suffix == '.gz': + return json.loads(gzip.decompress(path.read_bytes())) + return json.loads(path.read_text()) + + +def main_file(rel): + """a file of the repository's main branch (pinned by sha256 in DEPENDS.json).""" + p = REPO / rel + if not p.exists(): + sys.exit('missing file of main: %s (run from a checkout of the whole repository)' % rel) + return p diff --git a/research/format-limits/scripts/run_all.py b/research/format-limits/scripts/run_all.py new file mode 100644 index 0000000000..9482f0749b --- /dev/null +++ b/research/format-limits/scripts/run_all.py @@ -0,0 +1,78 @@ +"""Run every check of research/format-limits, a few at a time, and print PASS/FAIL per claim in a fixed order. + +usage: run_all.py OUTPUT_DIR [JOBS] +Each check script runs in its own process with its output in OUTPUT_DIR/logs/