diff --git a/research/char2-jets/LICENSE b/research/char2-jets/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/research/char2-jets/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/char2-jets/MANIFEST.sha256 b/research/char2-jets/MANIFEST.sha256 new file mode 100644 index 0000000000..9c9779c698 --- /dev/null +++ b/research/char2-jets/MANIFEST.sha256 @@ -0,0 +1,83 @@ +c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4 LICENSE +2eeab89221c6ebc3e228d55aa279992b028ce19bfa7732ff808a601f81dd146a NOTICE.md +c1f20a1e7afb7eded3ff0ab765975f62466c5464ccaec143656319cdd4091945 README.md +55d864202535c22952e1a9080ad834f1908d18ff857c8dc26211e25a847d1fc8 c/enumall.c +a4e75f24543b3ae10f7ea4b03182e67e6b7998111ef8313dc95f20135652d264 checks/a_tprime.py +38fe007a75c5b942e1fc93fcc1ec2413c5f2213d1ea25a9180dcb0ae5ddeb56e checks/b_cr2.py +e4364436856f5b42fc8b2b662bdc03e161dd2f01938c0f0124f92155f90ef9b9 checks/c_jets.py +bd5530b6c6fca7fc794292e1b2beb9d13331df676dc8492f7e18a3fb5846c3d2 checks/common.py +2191412eb19afacb9f71dac4cc77fb8a25c86f7330238cbc0742c42ea39ac136 checks/d_lemmaA_B2.py +a8b13901e3b124888fd2bc397b6060d78559c4d7d11a37fe5c9927dcdb6b6ee6 checks/e_jetfail.py +4b3193ee81d7ac39d6c2e4b2d7597c5f485b17ca8b60d30c10b3d58bcadad468 checks/provenance.py +4c48f91787e8ee0407c218e3253ab38327cad0536128f73533edf864c9040891 data/aff14.json +89907be2205b217f5dfa79f6e12b19f05e52f158be301752a0ccfd3759151122 data/cech_v8.json +6ef2af941ccad9f8a1c38f3a26020425022b5b09e15183b52dc0a3651261cde8 data/cex_joint_v7.json +86064701dde94b4f35427bc3e19275eaf1e40e9e90d4fea28e7857f3564d4dd7 data/cex_min_1.json +9e92b7b5f1221c180af3637ff70940aca5255b92f7b641efe3c615433e54761a data/cex_wholeTS_v9.json +2ce114152529d375215f1f64a45072c9b78d1719d156e76bc692eff1fa955666 data/cr2_realisations.json +ea72716f98af4a99141d28f828db3c5c99c2cc8ad7d15ed6a8329de37ee36790 data/gad.json +cd8a8c2436e0a025348af0b52ccb48a4f64535b0ff8df32cbe13da73673266b7 data/jf0.json +b615b5c0916bf839e859fae3599c7ecb85881371a0cf1d55c1565e8e45afcd5a data/jf1.json +4baab4d953b56b20a138fb32650eca99fff1279f0cfaa0e4d674bc3fa3d219df data/jf2.json +7e5e5fa66dbaf0ac1fa7382fec28bbebe10d477e80022d648fb4c0093f23c64c data/nojoint_21_1.json +c56efcac1b354fca4efe5ce203c0df2c723e28b5acaf6600c53d65510f2aad5e data/nojoint_21_10.json +8315bda5e6e175c322c1db4767635c30c58a8095ff939b8555984da737fcd258 data/nojoint_21_11.json +a4ac2c9bfb72c2256032c5cde87860e0a82e78b4b788d0dae39d96e56dec7a58 data/nojoint_21_12.json +2d4ab6b67d6b17d8c231d6ddfaf58f1c73e34e1c8d622b69b133ac83b0a62b0b data/nojoint_21_13.json +b6ef1c334c38c805bfb8c33459db73f805da80a3e3bc64944a5542d75dafc4dd data/nojoint_21_14.json +6020caec4ce319e9ee122948b3e09ac987cba8f504ece906e550f3996e3d46a5 data/nojoint_21_2.json +d9531dccba8cad1ed6bce75e21ee1336d512969e73a53faff98718b3889b1ec3 data/nojoint_21_3.json +ba139ce8e3e65f429346a60015042ff2bffd25b91c7487a68d06f12457aba6b5 data/nojoint_21_4.json +e7cd06311ce71bd6460b3c6cf237eb9c19721ddc4c8cedd39ea736c1dfe1692f data/nojoint_21_5.json +9c7c2d30b33de6a34821ad853f455bbe9a8ca3c42707010c247dbef00575bca8 data/nojoint_21_6.json +d477bd3bafb872c2ba638183e34762d402f2c3687953360b137cc7222afa3f98 data/nojoint_21_7.json +99fd2dcbc1b52b1a7255cabe92e88508bccf936900d87f42108609bbc58952e4 data/nojoint_21_8.json +4b44af0cf900012124e1844f223abf1423c46d2561dce60a380d3957495d0e8e data/nojoint_21_9.json +2781dda2b8bc4d3ee75a2465cb7350973b514a9c737f9181e3bcff3f358ce839 data/supmin_fail_v8.json +670ed90924b601ade22f0d4adaff46d1667e5449326a0f7ba7b88dd8f5906f93 data/tied_min.json +f6d31a1f6e84a23ec615acd8828ea85acbdee885a832791b0514be6c424db5bb data/tied_min_B.json +b5aa8ca01a87a898ae27160d5274af7ff08127cf0b27cf372f73a5725cd216a5 data/tm_noncr2.json +f4e3f08ecd59aa64877bafc655d7cd58aea57418ce5d264107c6a5d4900585c7 evidence/PROOF-working-notes.md +560b3830c3f6d4764a156cde9f1447bfcacbfd3e4ce778a3b8c274a0a1482b5d lean/DecoderDuality.lean +ad4b7e6f8c06fbcc7d01d4e85828a4aa5de7280afd53c436ca7c8c938354b8df lean/README.md +9b4c0a346edd9d1362903bd0a32262fe0fb8e4f1f0ea3cbc2a66d700a7d4b3cb lean/lake-manifest.json +4b85c0ff74598a2970ff4a0a974971813a473361960bd5bedf09c14525186c4d lean/lakefile.toml +62c2d9c0fc1ec4c67e151c11eff41ca004ef38e179cf9476c230406e6defedef lean/lean-toolchain +b9f4881da1cbad7c394a0a70614d62e4596b52bfde9967f8cd9aaa1279eaddde lib/col.py +ff3c1bbd072c4d1f47158f903aa3ff4fcd8db5bbc4709c3d15b21a1815eef3bd lib/cr2.py +4936fe52a5b996f91142c7fa0d8a1ca74f7c0e76ba9c3346748291c92e0940fa lib/gen.py +92fea2aca7b5298b30fb5ee176539a3887c0953728173c0fc1e26d55887b0f11 lib/gr.py +b7dc11f282395f40fb028249960e230598774680d0d73bfafd2166fe913f70ba lib/jet2.py +c707f5270b2eaef2da1dc0c1bf95c3ebf55d3fb667161c6c03a2126fad0422ec lib/kit.py +234e3a5f030bcc7356f582a85b8e02c6a02c18749d26ac222cc042b6ce198a08 lib/phi.py +cfbddbee3112f115c2ef606f7603481b4ef18cf80341041513a203417cc789e9 lib/satlib.py +afaae711d85b5508ee38efa8f23fa16774ec2c5c00f75c4687a9236841724772 lib/tangent.py +54424173c83403b81c7520f90197ba69dd32b17c02c54b3e0c927768e938453f requirements.txt +92281cc7387ca652203670976198add4131bb4df14a7e8f3c73fe87ec9e4153f scripts/make_data.py +b91c043adabcaf22c9cbe1729549c73406d49f87bb9062423f2678d57976cda3 scripts/t1.py +2bc5e670f02dba2cf177adef620fc63eade431c7b552bd3fd9ea0bbb24553987 scripts/t10.py +5106b0c310b3152e061df4c031b3774bf1e0aaac2831c8030ebc34f50755e607 scripts/t11.py +3e647cda0774ce7befb50110f1b02083859f730cf68f75f3064deab83f74c453 scripts/t12.py +f796de97a406d5069844f820f09d2fdb56afc43978fbf6d7957bd786d9cf29cb scripts/t13.py +5ba35faa15f53bdaa9bf99f35c67bcb131272d9627b8e4036fd6e01bfde56216 scripts/t14.py +f729950e9121c836c51e706dc04e44dfedb33f5464595c9604ca3f6c50d40bc7 scripts/t15.py +a23084d0b8d6a36356ddc3b57b1edab25b1d91e10d5f4380429c48ffc817aa47 scripts/t16.py +9aba9c011f3011fce22d5f5b6931c4613d5bf8a1340ffc091655f34e8ed5cd96 scripts/t17.py +aed231e657c62d4f347ffbf3ba93ae22a0ea3567f35ad3cc611cda90ccf8bf0b scripts/t18.py +83ac8a6dad9058f35ff12e61c9932688480be5b1cc2852004a5a28562d90cceb scripts/t19.py +c6c279f38df554c3cc7871019260935b99fe782a94f369d5ba808d5d78396698 scripts/t2.py +8c7bdfc55562ce2851102b872f127c01af06a45fdecd465bc2cf8b127b364b37 scripts/t20.py +8f7ef0cd3c0a6e74f2e11d1c82998b6947bcc03e7b2967433a126cfd7a1c3da5 scripts/t21.py +a590027e626d40f46e9eeb72077cda6872a998768bba8c07d17dbc3d709240df scripts/t22.py +60a7bee1d34be85fd6dc79b960f606be3541bd4cb39d36b6ab92ef7cfddb3afd scripts/t23.py +2e484e45e19dfd91fbeead52313b2dfffa011c796e96f5237d966c4309962453 scripts/t24.py +c9233cc4a134bd23dccaab3a982901a4fe503482e41537a68e196b4daaef3b2e scripts/t3.py +ba9ee091236742423eb698d0ef997c2190f7f4f8dd6cc03a05f533a9b3309e8f scripts/t4.py +fba0e1fc5364d94da884fd3c6b6c650bf8f337f0a8b60fb25cde1f1fabfa275d scripts/t5.py +a4904277d51abd4c9c5063cd282bb1f27915c96e7abaf73ee14420d6561c8f29 scripts/t6.py +69521b91da0ca0f07e1489895bb01bcb79fb9ba88bfaa8f40569f23486364050 scripts/t7.py +b3a4b48d5843e5b992b4ade587c4f1bae6f6bd4b5408d6134ac7e145c16c0a2e scripts/t8.py +785138735f8c27df1f4ea3af1083d321f063bb09ee0a975e0641713f58e51ad4 scripts/t9.py +cf9a793e3d6bdb5d033aa1b9c055feb87d093c60b4a08ebea9e8ec6558d067b6 scripts/tied_min_jet_cert.py +dbfb48fffcf2420aea8dad5e7c8b012fbfe2b19a3862d5dff8059cf31929e70b scripts/verify_cr2.py +31c4c9ca13073ae0723b90610cc0112554795456e49dde5611269332984d86d2 verify.sh diff --git a/research/char2-jets/NOTICE.md b/research/char2-jets/NOTICE.md new file mode 100644 index 0000000000..6991d8ac18 --- /dev/null +++ b/research/char2-jets/NOTICE.md @@ -0,0 +1,23 @@ +# Notice + +Prepared by DreamingOfClouds with Claude Opus 5.5 (Anthropic), via Claude Code; Apache-2.0 (`LICENSE`, copied from the repository root). + +## Credits (prior work this package stands on) + +- **#446** (Theorem C; closed, not merged): the cost formula and exactness model, carried by the merged **#595** (FL C.6): the pairing model and the window table. +- **#717**: the provenance / manifest pattern (`checks/provenance.py` follows it) and the complex E8 decoders. +- **#1590** (`research/root-unit-decoder-lemmas`, merged): Lemma A (T ≤ 2), the lift identity Lemma B, ERR1. The Lean file formalises the rank argument behind Lemma B; the step-0 manifest check and the PASS/FAIL style of `verify.sh` follow that package. +- **#2111** (pending): the three-total model and lemmas, the sharp example `tied_min`, the configurations in `data/` (copies), `lib/kit.py`, `lib/satlib.py`, `c/enumall.c`. This package asks and answers a different question about the same objects and is self-contained; it does not depend on #2111 being merged. +- **#2031** (pending): the DRAT certificate of the D5 CNF of #1590, cited as context, not duplicated. +- **#2125** (pending): the T² threshold for root-unit decoders, the context for why characteristic 2 matters. +- Our own swarm working cards of 2026-10-14 (the `KPR4-T3` struct card: tracks on CR2, the map φ, jets, the jetfail search, and the Lean project), shipped verbatim in `evidence/PROOF-working-notes.md`. + +## New in this package + +`README.md`, `verify.sh`, `requirements.txt`, `MANIFEST.sha256`, `checks/*.py` (written for this package; they re-implement the checks of the working scripts in exact arithmetic with fixed seeds), `data/tied_min_B.json`, `data/cr2_realisations.json`, `scripts/make_data.py`, and `lean/`. + +## Adapted from our earlier work + +- `lib/kit.py`, `lib/satlib.py`, `c/enumall.c`, `data/*.json` (configurations): unchanged copies from #2111 (themselves from the working cards). +- `lib/cr2.py`, `gr.py`, `phi.py`, `gen.py`, `tangent.py`, `jet2.py`, `col.py` and `scripts/t*.py`, `tied_min_jet_cert.py`, `verify_cr2.py`: the working scripts of the struct card; only the import / data paths were changed (and `t4.py`, `t18.py`, `t22.py` write their output to the current directory). +- `data/jf0..2.json`, `data/tm_noncr2.json`: outputs of those scripts. diff --git a/research/char2-jets/README.md b/research/char2-jets/README.md new file mode 100644 index 0000000000..38c80ad34f --- /dev/null +++ b/research/char2-jets/README.md @@ -0,0 +1,136 @@ +# Characteristic-2 shadows of rank-3 decoders: the anti-Fano bound by first-order jets, with a Lean-checked core (no κ claim) + +> **What is claimed, and what is not.** This package studies the three-total (T = 3) pairing-cost problem of #2111 through *characteristic 2*: a realisation of the incidence pattern over a field of characteristic 2 (Lemma CR2), its multiplicative version (Theorem B2), and a valued version, the *first-order jet* (Lemma VCR2, Corollary J, Theorem T′). +> **Claimed.** +> (1) PROVEN (statements and proofs below; the core lemma, Lemma B and Lemma CR2 are also machine-checked in Lean, §7): Lemma CR2 with its tropical / 2-adic corollary; Theorem B2 (the map φ; cost ≥ v − |H| − |F| + MAS(W[F])); Lemma VCR2 and Corollary J (a B-independent jet test); **Theorem T′: the 12-line configuration `tied_min` of #2111 (the anti-Fano configuration) has cost ≥ 12 for every admissible B, by a first-order jet, with no SAT call and no enumeration**; Lemma F (the first-order obstruction is a binary flow); Lemma A (T ≤ 2) as a one-line corollary of CR2. +> (2) PROVEN, with one quoted step: the generic-rank / split bound (Lemma GR, Lemma Split). That the split bound is *complete* (equivalent to (A)) uses a standard min-max that is quoted, not proved here, and is checked on instances. +> (3) CHECKED: the data of §4 (exact, by `verify.sh`, or recorded with the script named). +> (4) Three counterexamples to "the first-order jet always works" (jf0, jf1, jf2) in which the jet fails at order 1 and order 2, but (A) still holds (exact costs 12, 14, ≥ 16 against v = 9, 9, 11). +> +> **Not claimed.** No κ gain, no word, no new window. **(A) at T = 3 — cost ≥ v for every exact three-total decoder over Q — is neither proved nor refuted here.** The "2-adic shadow" conjecture (§6) is a conjecture. T′ is a bound for one configuration (and for the 4095 sub-configurations of it, by the same test), not for all configurations. + +## 0. Reading this package + +Every result has one of three statuses: + +- **PROVEN**: a proof is in this README (short ones in full; the longer ones in `evidence/PROOF-working-notes.md`, a verbatim snapshot of our working card, section numbers cited as "WN §k"). The scripts only sanity-check proofs on instances. +- **CHECKED**: recomputed by `verify.sh` in exact arithmetic (integers, F2, GF(2^k), exhaustive enumeration), the check group named; or **CHECKED (recorded)**: a result of our own working scripts that `verify.sh` does **not** repeat. The script is in `scripts/` and the count is stated. +- **OPEN**: a precisely stated question, or an argument that is not a proof. + +```sh +python3 -m pip install -r research/char2-jets/requirements.txt # python-sat and numpy; a C compiler (cc) is also needed +bash research/char2-jets/verify.sh /fresh/output/dir # from a checkout or `git archive` of the whole repository; no Lean needed +LEAN=1 bash research/char2-jets/verify.sh /fresh/output/dir # optional extra step: `lake build` of lean/ (needs Mathlib at the pinned revision) +``` + +Step 0 checks every file against `MANIFEST.sha256` and stops with exit 1 on any mismatch; then `c/enumall.c` is compiled and five check groups run one after the other, one PASS/FAIL line per assertion (about one minute). `scripts/` holds the exploratory scripts of the working card with their paths fixed; `verify.sh` does not run them. `scripts/make_data.py` regenerates `data/tied_min_B.json` and `data/cr2_realisations.json`. + +## 1. Model (as in #595, #446 Theorem C, #1590, #2111) + +A configuration is a list of lines t = 1…v, each with a point p(t) ∈ Q³ and a line q(t) ∈ Q³ with p(t)·q(t) ≠ 0. A **pairing** B is a 0/1 matrix over F2 with unit diagonal and B_ts = 1 (s ≠ t) only where p(t)·q(s) = 0 (*admissible*). An exact decoder with T = 3 totals is M = Σ_{j≤3} p_j q_jᵀ over Q with M_tt ≠ 0 and M_ts = 0 wherever B_ts = 1. Write R_j = supp p_j, A_j = supp q_j, π(t) = {j : p_j(t) ≠ 0}, σ(t) = {j : q_j(t) ≠ 0}, D(t) = π(t) ∩ σ(t) ≠ ∅, and + +**cost(B) := Σ_j rank_F2 B[R_j, A_j]** + +(the floor w of Theorem C is dropped, so a lower bound on this sum is the stronger statement). Let E = {(t, s) : t ≠ s, B_ts = 1}. An incidence (t, s) matters only if it lies inside some block, i.e. π(t) ∩ σ(s) ≠ ∅; `free` in the code is the list of these incidences for the full pattern. + +**Target (A).** cost(B) ≥ v for every exact decoder and every admissible B. Known: T ≤ 2 (Lemma A of #1590); fails for T ≥ 7 (#1590 ERR1). Open at T = 3 (#2111). **Lemma B** (#1590): for every rational B′ with supp B′ ⊆ supp B and B′_tt ≠ 0, v ≤ Σ_j rank_Q B′[R_j, A_j]. `tied_min` is the 12-line configuration of #2111 §4 (all entries ±1 or 0; cost exactly 12 = v, 217 optima); `cex_min_1`, `gad`, `aff14`, `cex_joint_v7`, … are the other configurations of #2111, copied to `data/`. (The package is self-contained: it reads nothing outside `research/char2-jets/`; #2111 and #2125 are cited for context.) + +The statements below use **Lemma GR** (§3): for any field K ⊇ F2 and support-compatible vectors P~(t), Q~(s) ∈ K³ (supp P~(t) ⊆ π(t), supp Q~(s) ⊆ σ(s); nothing else assumed), cost(B) ≥ rank_K (B ∘ P~Q~ᵀ). *Proof.* B ∘ P~Q~ᵀ = Σ_j D(p~_j) B D(q~_j) (p~_j the j-th coordinate over the lines), and rank_K D(p~_j) B D(q~_j) ≤ rank_K B[R_j, A_j] ≤ rank_F2 B[R_j, A_j] since p~_j vanishes off R_j and q~_j off A_j. ∎ This is the same one-field-extension argument as Lemma B, and its diagonal case (B ∘ P~Q~ᵀ diagonal with nonzero diagonal) is the core lemma formalised in Lean (§7); Lean does not prove the general bound rank N ≤ cost. + +## 2. PROVEN + +### 2.1 Lemma CR2 (characteristic-2 realisation) and its corollaries + +**Lemma CR2.** Suppose a field K of characteristic 2 and vectors P~(t), Q~(s) ∈ K³ satisfy (i) supp P~(t) ⊆ π(t), supp Q~(s) ⊆ σ(s); (ii) P~(t)·Q~(s) = 0 for every (t, s) ∈ E; (iii) P~(t)·Q~(t) ≠ 0 for every t. Then **cost(B) ≥ v**. +*Proof.* N := B ∘ P~Q~ᵀ has N_ts = B_ts P~(t)·Q~(s), so N = diag(P~(t)·Q~(t)) has rank v; by Lemma GR, cost(B) ≥ rank N = v. ∎ +CR2 depends only on E and is down-closed (a realisation of E realises every E′ ⊆ E; extra incidences, coinciding points and zero coordinates are allowed). So **if the full pattern `free` of a configuration is CR2, (A) holds for it for every B at once.** + +**Lemma A (T ≤ 2) as a corollary.** For T = 2 the objects live in P¹: p(t)·q(s) = 0 iff p(t) = perp q(s). Map the finitely many used points of P¹(Q) (the p(t) and the perp q(s)) injectively into P¹(F̄2), fixing [1:0] and [0:1]; the image vectors realise the full pattern (incidence = equality, preserved; diagonal = inequality, preserved by injectivity; supports preserved by fixing the two coordinate points). By CR2, cost ≥ v. CHECKED: group d (60 random T = 2 configurations, explicit injection into GF(2⁶)). + +**Corollary (2-adic / tropical reduction).** Let ν be a valuation on K ⊇ Q extending v₂, and suppose a ∈ ((1/n)Z)³ satisfies, for every t, ν(p(t)·q(t)) = min_{j∈π(t)}(ν p_j(t) + a_j) + min_{j∈σ(t)}(ν q_j(t) − a_j). Then the full pattern is CR2. *Proof.* Replace p_j ← ϖ^{a_j} p_j, q_j ← ϖ^{−a_j} q_j: all products p(t)·q(s), hence incidences and supports, are unchanged. Scale each vector to minimum valuation 0 and reduce to the residue field (characteristic 2): incidences reduce to incidences, supports can only shrink, and the hypothesis says the diagonal product has valuation exactly 0, so it reduces to a nonzero element. ∎ (a = 0: if every primitive integer p(t)·q(t) is odd, (A) holds for every B.) For `tied_min`, p·q = ±1 ± 1 = ±2 on every line and no a works. + +### 2.2 Theorem B2 (the multiplicative map φ) + +Call an incidence (t, s) *binomial* if |π(t) ∩ σ(s)| = 2 and *wild* if |π(t) ∩ σ(s)| = 3. Call a line t *harmonic* if |D(t)| = 2 and the two terms of p(t)·q(t) are equal (p(t)·q(t) = 2 p_i(t) q_i(t)). H = harmonic lines, W = wild incidences, F = lines with p(t) and q(t) both of full support (F ∩ H = ∅). Let K = F2(z_p : p prime) and φ : Q* → K* the homomorphism with φ(−1) = 1, φ(p) = z_p (φ(0) = 0). Apply φ entrywise: P~ = φ(p), Q~ = φ(q); supports are preserved. + +- A binomial incidence x_i y_i + x_j y_j = 0 means x_i y_i = −x_j y_j, so φ(x_i)φ(y_i) = φ(x_j)φ(y_j) and P~(t)·Q~(s) = 0 in characteristic 2: every binomial incidence is preserved. +- P~(t)·Q~(t) = Σ_{j∈D(t)} φ(p_j q_j) is a sum of |D(t)| monomials, zero iff they cancel in pairs: never for |D| ∈ {1, 3}; for |D| = 2 iff |p_i q_i| = |p_j q_j|, i.e. iff t is harmonic. **The diagonal vanishes exactly on H.** + +**Theorem B2.** Let X ⊆ [v] \ H contain no directed cycle of wild incidences. Then cost(B) ≥ |X| for every admissible B. Consequently: (i) no wild incidence and no harmonic line ⇒ the full pattern is CR2 ⇒ (A) for every B; (ii) no wild incidence ⇒ cost ≥ v − |H|; (iii) in general cost ≥ v − |H| − |F| + MAS(W[F]) (a wild edge joins a full point to a full line, so a wild cycle lies inside F; MAS(W[F]) = the maximum size of an induced acyclic vertex set, i.e. of a set Y ⊆ F of lines whose induced wild subgraph W[Y] has no directed cycle; it is applied with X = ([v] \ (H ∪ F)) ∪ Y. It is not the maximum acyclic edge set: that reading is false, see #2334 and #2340). +*Proof.* N := B ∘ P~Q~ᵀ has rank ≤ cost (Lemma GR). Off the diagonal, N_ts ≠ 0 only if B_ts = 1 and the incidence is not preserved, i.e. wild; N[X, X] is triangular in a topological order of W[X] with nonzero diagonal. ∎ +`tied_min` is no-wild with all 12 lines harmonic; the anti-Fano obstruction *is* the harmonic-conjugate configuration ("1 + 1 = 0" is "harmonic conjugate = itself"). + +### 2.3 Lemma VCR2, Corollary J, Theorem T′ + +**Lemma VCR2 (valuative CR2).** Let K be a field of characteristic 2 with a valuation ν (e.g. F((ε))), P~, Q~ support-compatible, w_ts := ν(P~(t)·Q~(s)). If every directed cycle C of E satisfies Σ_{(t,s)∈C} w_ts > Σ_{t∈C} w_tt and all w_tt < ∞ (a separate hypothesis), then cost(B) ≥ v for every B with off-diagonal support in E. +*Proof.* N = B ∘ P~Q~ᵀ has rank ≤ cost (Lemma GR). det N = Σ_σ Π_t N_{tσ(t)}; a permutation σ ≠ id splits into fixed points and cycles of E, so its term has valuation > Σ_t w_tt, the valuation of the identity term. No cancellation: det N ≠ 0. ∎ (CR2 is the case w = ∞ on E.) + +**Corollary J (first-order jets; B-independent).** Let the configuration be no-wild, φ as above, and suppose support-compatible X, Y over K satisfy + (J1) φp(t)·Y(s) + X(t)·φq(s) = 0 for every incidence (t, s) of the full pattern; + (J2) δ′_t := φp(t)·Y(t) + X(t)·φq(t) ≠ 0 for every harmonic t. +Then with P~ = φP + εX, Q~ = φQ + εY over K((ε)) the valuations are w = ∞ or ≥ 2 on incidences, w_tt = 0 on non-harmonic and 1 on harmonic lines, so every cycle has Σ_edges ≥ 2|C| > |C| ≥ Σ_vertices, and (A) holds for the configuration for every B (Lemma VCR2). +(J1) is a homogeneous linear system; (J2) asks the v functionals δ′_t to be nonzero *simultaneously* on its solution space. Over an infinite field it suffices that **each** δ′_t is not identically zero on the solution space (a vector space is not a finite union of proper subspaces); the solution space is defined over the field of the data, and the test is run over GF(2¹⁶) and extended to its algebraic closure. So Corollary J is a B-independent linear-algebra certificate. The proof uses only a homomorphism φ : Q* → K* with φ(−1) = 1 whose diagonal vanishes exactly on H (K need not be F2(z_p)); the checks take z_p ↦ random elements of GF(2¹⁶)* and verify these order-0 conditions exactly for each configuration. T′ is unaffected (φ ≡ 1 over F2). + +**Theorem T′ (cost(`tied_min`) ≥ 12 for every admissible B).** `tied_min` has four points (1, ±1, ±1) forming a complete quadrangle with diagonal points e₁, e₂, e₃, and 12 lines (u, k): the point u together with the line of class k (q_k = 0, so it passes through e_k) that is a side of the quadrangle *not* containing u. For each k the four points split into two pairs, M_k, the two sides of class k. Here φ(`tied_min`) is the Fano collapse: all entries are ±1, so every point becomes the Fano centre c = (1,1,1) and every class-k line becomes the Fano line ℓ_k through c and e_k (ℓ₀ = (0,1,1), ℓ₁ = (1,0,1), ℓ₂ = (1,1,0)). Write f_k(t) = X(t)·ℓ_k and g(s) = c·Y(s). Since ℓ₀ + ℓ₁ + ℓ₂ = 0 in characteristic 2, f₀ + f₁ + f₂ = 0 at each point t, and (X(t) of full support) any such triple occurs; g(s) is arbitrary (Y(s) has two free entries). (J1) for an incidence t → s, s of class k, reads f_k(t) = g(s). The class-k lines carrying a side {x, y} of M_k are the two lines (u, k), u in the other pair; so every line t whose point lies on a side S of M_k needs f_k(t) = G_k(S), the common g-value of the lines carrying S. (J2) for line (u, k): f_k = G_k(side ∋ u) ≠ g(u, k) = G_k(side ∌ u), i.e. h_k := G_k(S) + G_k(S′) ≠ 0 for the two sides S, S′ of M_k. The constraint f₀ + f₁ + f₂ = 0 at the four quadrangle points reads: at a, Σ_k G_k(side_k(a)) = 0; at the vertex b paired with a in M₀ the same sum plus h₁ + h₂ = 0, so h₁ = h₂; likewise h₀ = h₂ and h₀ = h₁. **Solution: h₀ = h₁ = h₂ = h ≠ 0**, any G with Σ_k G_k(side_k(a)) = 0. So (J1) and (J2) are solvable already over F2, Corollary J applies, and cost(B) ≥ 12 for every admissible B; with an optimum of #2111, = 12. ∎ (`checks/a_tprime.py` builds the jet from this hand formula.) +CHECKED (group a, exact over F2): the explicit jet (h = 1) satisfies (J1) on all 72 incidences and (J2) on all 12 lines; order 0 holds on all incidences and diagonals; and N = B ∘ P~Q~ᵀ at a fixed ε ∈ GF(2¹⁶) has rank 12 for the 217 optima, the full B and 300 random admissible B (518/518 stored matrices, `data/tied_min_B.json`; for the optima the exact cost Σ rank is also recomputed and equals 12; for the full B it is 24). + +*Reading.* `tied_min` = anti-Fano is not realisable in characteristic 2 (§4), but it is realisable to first order around its Fano collapse: the equal-characteristic shadow of its 2-adic picture (diagonal products of valuation ν(2) = 1 ↔ diagonal of ε-order 1; incidences of valuation ∞ ↔ ε-order ≥ 2). The tightness of `tied_min` (cost = v) is the statement that the jet has order exactly 1 on every line. + +### 2.4 Lemma F (the first-order obstruction is a binary flow) + +Write X(t) = φp(t) ∘ ξ(t), Y(s) = φq(s) ∘ η(s) (every support-compatible tangent has this form). On a binomial incidence over the pair {i, j}, (J1) becomes Δ_ij ξ(t) = Δ_ij η(s), with Δ_ij ξ = ξ_i + ξ_j; for harmonic t with D(t) = {i, j}, (J2) is Δ_ij ξ(t) ≠ Δ_ij η(t). Hence **the jet test fails at t iff the harmonic equation at t is an F2-combination of incidence equations**: a set Z of incidence edges plus the harmonic edge, with, at each object whose support has size 2, an even number of Z-edges, and at each object of full support, equal parities of Z-edges over the three pairs {01}, {02}, {12}. Any such Z has an *even* number of incidence edges (evaluate at the sign labels ξ_j(t) = [p_j(t) < 0], η_j(s) = [q_j(s) < 0], which give 1 on every incidence and 0 on every harmonic diagonal). On objects with two-element supports only (a cycle in P¹) Z would be a cycle with an odd number of incidences, so **no obstruction exists there**: the Q-geometry (−1 ≠ 1) enters exactly through this parity. With full-support objects the parity condition is "Fano-like" (Δ₀₁ + Δ₀₂ + Δ₁₂ = 0) and flows of even incidence count can exist (jf0, jf1, jf2, §5). + +## 3. The generic-rank / split bound + +By Lemma GR the best bound of this kind is GR(B) := rank over F2(X, Y) of B ∘ XYᵀ (X_tj, j ∈ π(t), Y_sj, j ∈ σ(s), indeterminates). **PROVEN (Lemma Split).** Mod 2, det(B ∘ XYᵀ) = Σ_σ Π_t B_{tσ(t)} x(t)·y(σ(t)); the coefficient of the monomial Π_t x_{a(t)}(t) Π_s y_{b(s)}(s) is per(B ∘ K_ab) = det_F2(B ∘ K_ab), with K_ab[t, s] = [a(t) = b(s)], and after permuting B ∘ K_ab = ⊕_c B[R′_c, A′_c] with R′_c = a⁻¹(c) ⊆ R_c, A′_c = b⁻¹(c) ⊆ A_c. The same argument on minors gives + **GR(B) = SPL(B) := max over row-partitions {R′_c ⊆ R_c} and column-partitions {A′_c ⊆ A_c} of Σ_c rank B[R′_c, A′_c]**, +and GR(B) = v iff a *perfect split* exists (three square nonsingular submatrices, one inside each block, whose row sets partition the lines and whose column sets partition the lines); a perfect split gives cost(B) ≥ v directly. +**Quoted, not proved here:** the independent-matching (Rado–Edmonds type) min-max SPL(B) = min_{S,T ⊆ [v]} (v − |S|) + (v − |T|) + Σ_c rank_F2 B[S ∩ R_c, T ∩ A_c]. "≤" is elementary; equality is cited from the matroid-union / linking-system literature from memory. CHECKED (recorded, `scripts/t9.py`): 300 random instances, v = 3–6, 92 of them with SPL < v, 0 mismatches. **Conditional corollary:** if (A) holds for every sub-configuration, then Σ_c rank B[S ∩ R_c, T ∩ A_c] ≥ |S ∩ T| ≥ |S| + |T| − v, so SPL(B) = v; hence, *given the min-max*, (A) at T = 3 ⟺ every admissible B on every configuration has a perfect split. The anti-Fano obstruction of §4 is an obstruction to the *diagonal* (CR2) form only, never to the generic form (GR = v for 100 random B at each of four densities on `tied_min`, `cex_min_1`, `gad`, `aff14`, `cex_joint_v7`: recorded, `scripts/t7.py`). + +## 4. CHECKED + +| Statement | Status | Where | +|---|---|---| +| T′: jet exact over F2 for `tied_min` ((J1) on 72 incidences, (J2) on 12 lines); 518 stored matrices have rank N = 12; the 217 optima have exact cost 12 | CHECKED (verify.sh) | group a | +| The 217 optima themselves (SAT enumeration of all B with block ranks ≤ (4,4,4)) | CHECKED (recorded); the stored list is what group a uses | `scripts/make_data.py`, `lib/satlib.py` | +| Lemma CR2 on 21 stored configurations: stored realisation vectors (not re-searched) are verified exactly (supports, all incidences, all diagonals, 40 random B each: N diagonal and cost ≥ v). All realise over GF(2) except `cex_min_1` (v = 19, 114 incidences) over GF(4) (none over GF(2)). So (A) holds on all of them for every B, by CR2 alone; in particular cost(`cex_min_1`) ≥ 19 for every B, where every order/label certificate of #2111 stops at 18 | CHECKED (verify.sh) | group b | +| `tied_min` full 72-incidence pattern is **not** CR2 over GF(2), GF(4), GF(8), GF(16) (exhaustive DFS) | CHECKED (verify.sh) | group b | +| 44 minimal non-CR2 sub-configurations of `tied_min` (32 of 6 lines, 12 of 7 lines; non-realisable over GF(2), GF(4), GF(8); every one-line deletion is realisable); the 32 six-line ones are tight (exhaustive minimum cost 6 = v) | CHECKED (verify.sh); minimum cost 8 for the seven-line ones is recorded (2²⁶ matrices each), `scripts/t4.py`, `scripts/t5.py` | group b | +| All 217 optima of `tied_min` are CR2 over GF(2) (off-diagonal supports of size 12, 14, 16, 18, 24); all minimisers and cost-(min+1) matrices of `cex_joint_v7`, `cech_v8`, `supmin_fail_v8`, `cex_wholeTS_v9`, `nojoint_21_1..4` are CR2 over GF(2) | CHECKED (recorded) | `scripts/t1.py`, `scripts/t2.py` | +| Corollary J holds on **all 4095** sub-configurations of `tied_min` and on **1500/1500** random all-harmonic configurations (v = 4–14, entries ±r^a, r ∈ {2,3,5}); exact order-0 conditions are re-checked for each | CHECKED (verify.sh) | group c | +| Corollary J holds on 1889 of 1892 random no-wild configurations with harmonic lines (mixed supports), failing on exactly the three jf0..2 | CHECKED (recorded) | `scripts/t16.py`, `scripts/t17.py` | +| Theorem B2: on random no-wild configurations φ preserves every block incidence and its zero diagonals are exactly H (80/80 re-run; 400/400 recorded); exhaustive minimum cost ≥ v − \|H\| (79 re-run, 379 recorded) | CHECKED | group d; `scripts/t11.py` | +| Lemma A, T = 2: explicit injection realisation, 60 random configurations | CHECKED (verify.sh) | group d | +| 300 random configurations containing a directed cycle of wild incidences (v = 6–12, entries ≤ 3): full pattern CR2 for all (293 over GF(2), 7 over GF(4)), so (A) holds on each by CR2 | CHECKED (recorded) | `scripts/t24.py` | +| Split min-max on 300 instances; GR = v on the stored configurations | CHECKED (recorded) | `scripts/t9.py`, `scripts/t7.py` | +| End-to-end CR2 (N = Σ_j D(p~_j) B D(q~_j) diagonal, nonzero diagonal, for 200 random B on each of four configurations) | CHECKED (recorded; group b repeats it with 40 B on all 21) | `scripts/verify_cr2.py` | + +## 5. The three jet failures jf0, jf1, jf2 + +The random run of §4 (1892 no-wild configurations with harmonic lines) produced three configurations, stored in `data/jf0.json`, `jf1.json`, `jf2.json` (v = 11, 9, 9; 41, 27, 20 free incidences), in which a harmonic line is *immovable* at first order: δ′_t vanishes on the whole tangent space of (J1) (immovable lines: jf0: line 0; jf1: line 7; jf2: lines 0 and 2). The first-order jet does not exist, and this is independent of z_p (the full collapse φ₀ with all nonzero entries ↦ 1 fails at the same lines). None of the three is CR2 (GF(2), GF(4), GF(8)). They are not counterexamples to (A): + +- **Order 2 fails structurally.** With P~ = φ₀P + εX₁ + ε²X₂ (same for Q~), the order-2 diagonal of an immovable line is the constant Q_t = X₁(t)·Y₁(t) + Σ c_e b_e (δ′_t = Σ c_e A_e a combination of the incidence functionals A_e, b_e = X₁(t_e)·Y₁(s_e)), independent of (X₂, Y₂). **CHECKED (verify.sh, group e; exact): Q_t is identically zero as a polynomial on the first-order tangent space V** for all four immovable lines, so the order-2 diagonal vanishes for every jet over every characteristic-2 field. (The Lemma F flow kills the quadratic term too.) Order ≥ 3 was not tested. +- **(A) holds, with slack.** jf1: v = 9, exact minimum cost **12** (exhaustive over 2²⁷ admissible B; 192 minimisers). jf2: v = 9, exact minimum cost **14** (2²⁰; 12 928 minimisers). jf0: v = 11, 41 free incidences (too many to enumerate): the CNF "cost ≤ K" (CaDiCaL, `lib/satlib.py`) is UNSAT for K ≤ 15 — group e re-runs K = 15 — so **cost(jf0) ≥ 16 > 11**; the exact value is unknown. +- **The B-dependent test works on the optima.** jf1: 186 of the 192 minimisers pass the first-order jet test on E = supp B (group e re-runs this) and are CR2 (recorded: `scripts/t23.py`); the other 6 pass neither test, but cost ≥ v holds there anyway. jf2: every one of the 12 928 minimisers passes the jet test on E = supp B and is CR2 (recorded: `scripts/t23.py`). + +## 6. OPEN + +1. **(A) at T = 3.** Nothing here proves it for all configurations. +2. **The "2-adic shadow" conjecture.** Every configuration over Q admits a characteristic-2 valued realisation (over F̄2((ε))) whose diagonal is strictly dominant on every directed cycle of incidences (Lemma VCR2); this would prove (A). It cannot hold at T ≥ 7 (E7/E8; (A) fails there), which is a consistency check only. The B-independent form is likely false (jf0..2 admit no jet certificate of order 1 or 2, and whether any order works is item 3); the B-dependent form (for every B, or for some minimiser, a cycle-dominant realisation of supp B) is open. +3. **Does the Lemma F flow obstruct at every order** on jf0..2 (orders ≥ 3 untested)? +4. **Wild cycles** (three-term incidences x_i y_i + x_j y_j + x_k y_k = 0), which φ breaks: no theorem here. All 300 recorded random wild-cycle configurations are CR2 (§4). +5. Completeness of the split min-max (§3): standard, quoted, not proved here. + +## 7. Formal verification (Lean 4 + Mathlib) + +`lean/DecoderDuality.lean` (about 230 lines; `lean/README.md` has the statements) formalises: + +- **`hadamard_diag_rank_sum`** (the core lemma): over a field F, if the Hadamard product B_ts · Σ_j p_j(t) q_j(s) is diagonal with nonzero diagonal and supp p_j ⊆ S_j, supp q_j ⊆ U_j, then |ι| ≤ Σ_j rank B[S_j, U_j]; +- **`lemmaB`**: Lemma B of #1590 in the form "B over K, B_tt ≠ 0, B_ts ≠ 0 ∧ t ≠ s ⇒ M_ts = 0, M_tt ≠ 0 ⇒ v ≤ Σ_j rank_K B[R_j, A_j]"; +- **`lemmaCR2`**: Lemma CR2 above (B over F2 = ZMod 2, P~, Q~ over a field L of characteristic 2). + +No `sorry`; the three `#print axioms` lines show only `propext`, `Classical.choice`, `Quot.sound`. Auxiliary results proved there: subadditivity of rank, `rank_diag_mul_mul_diag_le`, and `rank_map_le` for a ring hom of fields. The Lean file does **not** formalise Theorem B2, Lemma VCR2 (valuations), Corollary J, Theorem T′, Lemma F or the split bound; those rest on the proofs in §2 and the exact checks of §4. Build: `cd lean && LEAN_NUM_THREADS=4 lake build` (toolchain `leanprover/lean4:v4.33.0-rc1`; Mathlib at the revision pinned in `lean/lake-manifest.json`; `lake exe cache get` first on a fresh checkout). `verify.sh` does not need Lean; `LEAN=1 bash verify.sh` runs the build on a copy as an optional step. A successful build confirms the proof terms; it does not check that the statements match the prose above, which is for the reader to compare with `lean/README.md`. + +## 8. Layout + +`README.md`, `NOTICE.md`, `LICENSE`, `MANIFEST.sha256`, `requirements.txt`, `verify.sh`; `checks/` (`a_tprime.py` … `e_jetfail.py`, `provenance.py`, `common.py`); `lib/` (`kit.py`, `satlib.py`, `gr.py`, `cr2.py`, `phi.py`, `gen.py`, `tangent.py`, `jet2.py`, `col.py`); `c/enumall.c`; `data/` (configurations, `jf0..2.json`, `tm_noncr2.json`, `tied_min_B.json`, `cr2_realisations.json`); `scripts/` (exploratory scripts `t1`–`t24`, `tied_min_jet_cert.py`, `verify_cr2.py`, `make_data.py`, paths fixed); `lean/`; `evidence/PROOF-working-notes.md` (verbatim snapshot of the working notes, cited as "WN §k"; its §7 is the status list this README follows). diff --git a/research/char2-jets/c/enumall.c b/research/char2-jets/c/enumall.c new file mode 100644 index 0000000000..f05b16c846 --- /dev/null +++ b/research/char2-jets/c/enumall.c @@ -0,0 +1,28 @@ +// exhaustive: input v f; f lines "t s"; for j: nR R.., nA A..; optional slack k: output all B with cost<=min+k (we output cost too) +#include +#include +#include +int v,f,ft[64],fs[64],nR[3],nA[3],R[3][32],A[3][32]; +uint32_t row[32]; +static inline int rk(int j){uint32_t rows[32];int n=0; + for(int a=0;a>s&1)x|=1u<0 && (31-__builtin_clz(rows[k]))>(31-__builtin_clz(rows[k-1]));k--){uint32_t tmp=rows[k];rows[k]=rows[k-1];rows[k-1]=tmp;} + }} + return r;} +int main(int argc,char**argv){int slack=argc>1?atoi(argv[1]):0; + if(scanf("%d %d",&v,&f)!=2)return 1;for(int i=0;i= 12 for every admissible B, by a first-order jet over F2((eps)) around the Fano collapse (Corollary J / Lemma VCR2). +Exact steps (integer / F2 arithmetic): (1) tied_min is no-wild with 12 harmonic lines; (2) the hand-formula jet X, Y (h = 1) satisfies (J1) on all incidences and (J2) on all lines, +and the eps-expansion of every product P~(t).Q~(s) = c0 + c1 eps + c2 eps^2 gives valuation >= 2 on incidences, 0/1 on diagonals (Lemma VCR2 hypothesis for every directed cycle); +(3) for the 518 stored matrices B: admissible, and rank N = rank (B o P~Q~^T) = 12 at a fixed eps in GF(2^16) (a specialisation: rank can only drop) -- a direct certificate cost(B) >= 12. +For the 217 optima the exact cost (sum of F2 block ranks) is also computed and must equal 12.""" +import json, random +from common import * +from kit import *; from gr import mul, rank, Q as FQ; from phi import classify +P, Q = load_cfg('tied_min.json'); v = 12; R, A, free = setup(P, Q) +w, H = classify(P, Q) +report('T1 tied_min is no-wild, v=12, 72 incidences, all 12 lines harmonic', (w, len(H), len(free)) == (0, 12, 72), 'wild=%d |H|=%d f=%d' % (w, len(H), len(free))) +cls = [next(j for j in range(3) if q[j] == 0) for q in Q] +a0 = P[0] +def side(k, x): + i, j = [y for y in range(3) if y != k]; q = [0, 0, 0]; q[i] = x[j]; q[j] = -x[i]; return q +def same(q1, q2): return all(q1[i] * q2[j] == q1[j] * q2[i] for i in range(3) for j in range(3)) +G = lambda k, q: 0 if same(q, side(k, a0)) else 1 +f = [[G(k, side(k, P[t])) for k in range(3)] for t in range(v)] +report('T2 f_0+f_1+f_2 = 0 at every point (sum-zero constraint)', all((f[t][0] ^ f[t][1] ^ f[t][2]) == 0 for t in range(v))) +X = [[f[t][1], f[t][0], 0] for t in range(v)] +g = [G(cls[s], Q[s]) for s in range(v)] +Y = [] +for s in range(v): + y = [0, 0, 0]; y[next(j for j in range(3) if j != cls[s])] = g[s]; Y.append(y) +phP = [[1 if x else 0 for x in p] for p in P]; phQ = [[1 if x else 0 for x in q] for q in Q] +d2 = lambda a, b: (a[0] & b[0]) ^ (a[1] & b[1]) ^ (a[2] & b[2]) +report('T3 jet is support-compatible', all(all(X[t][j] == 0 for j in range(3) if P[t][j] == 0) and all(Y[t][j] == 0 for j in range(3) if Q[t][j] == 0) for t in range(v))) +c0 = lambda t, s: d2(phP[t], phQ[s]); c1 = lambda t, s: d2(phP[t], Y[s]) ^ d2(X[t], phQ[s]) +report('T4 order 0: phi(p).phi(q) = 0 on all 72 incidences and on all 12 diagonals', all(c0(t, s) == 0 for (t, s) in free) and all(c0(t, t) == 0 for t in range(v))) +report('T5 (J1): order-1 coefficient 0 on all 72 incidences => w_ts >= 2', all(c1(t, s) == 0 for (t, s) in free)) +report('T6 (J2): order-1 coefficient 1 on all 12 diagonals => w_tt = 1', all(c1(t, t) == 1 for t in range(v))) +vl = lambda t, s: 0 if c0(t, s) else (1 if c1(t, s) else 2) # valuation (capped at 2) of P~(t).Q~(s) = c0 + c1 eps + c2 eps^2 +emin = min(vl(t, s) for (t, s) in free); dmax = max(vl(t, t) for t in range(v)) +report('T7 VCR2 hypothesis: min incidence valuation (%d) > max diagonal valuation (%d), so every directed cycle C has sum_edges w >= 2|C| > |C| >= sum_vertices w and all w_tt < inf' % (emin, dmax), emin >= 2 and dmax == 1 and all(vl(t, t) == 1 for t in range(v))) +d = json.load(open(PKG + '/data/tied_min_B.json')) +assert d['f'] == len(free) +random.seed(1); e = random.randrange(2, FQ) +Pt = [[phP[t][j] ^ mul(e, X[t][j]) for j in range(3)] for t in range(v)]; Qt = [[phQ[s][j] ^ mul(e, Y[s][j]) for j in range(3)] for s in range(v)] +dd = lambda a, b: mul(a[0], b[0]) ^ mul(a[1], b[1]) ^ mul(a[2], b[2]) +M = [[dd(Pt[t], Qt[s]) for s in range(v)] for t in range(v)] +def check(gs, tag, exact_cost=None): + ok = 0; adm = 0; ex = 0 + for gg in gs: + B = tomat(gg, free, v) + adm += all(B[t][t] == 1 for t in range(v)); + ok += rank([[M[t][s] if B[t][s] else 0 for s in range(v)] for t in range(v)]) == 12 + if exact_cost is not None: ex += sum(blockranks(B, R, A)) == exact_cost + return ok, adm, ex +n = len(d['optima']) +ok, adm, ex = check(d['optima'], 'opt', 12) +report('T8 217 optima: admissible, exact cost = 12 (sum of F2 block ranks), rank N = 12', n == 217 and ok == n and adm == n and ex == n, '%d matrices, rank-12 %d, cost-12 %d' % (n, ok, ex)) +ok, adm, ex = check([d['full']], 'full', None) +cf = sum(blockranks(tomat(d['full'], free, v), R, A)) +report('T9 full B (all 72 incidences): rank N = 12 (exact cost of full B = %d >= 12)' % cf, ok == 1 and cf >= 12) +ok, adm, ex = check(d['random'], 'rnd', None) +cm = min(sum(blockranks(tomat(g_, free, v), R, A)) for g_ in d['random']) +report('T10 300 random admissible B: rank N = 12 for all (min exact cost among them = %d)' % cm, ok == 300 and cm >= 12, 'rank-12 %d/300' % ok) +done() diff --git a/research/char2-jets/checks/b_cr2.py b/research/char2-jets/checks/b_cr2.py new file mode 100644 index 0000000000..276dbb95e4 --- /dev/null +++ b/research/char2-jets/checks/b_cr2.py @@ -0,0 +1,54 @@ +"""Lemma CR2: stored char-2 realisations of the full incidence pattern are verified exactly (not re-searched), and the anti-Fano non-realisability of tied_min and the atoms are re-run (exhaustive DFS).""" +import json, random, itertools +from common import * +from kit import *; from cr2 import realise, cfg_data, IRR +def gfmul(a, b, k): + r = 0; m = IRR[k] + while b: + if b & 1: r ^= a + b >>= 1; a <<= 1 + if a >> k & 1: a ^= m + return r +def dot(a, b, k): return gfmul(a[0], b[0], k) ^ gfmul(a[1], b[1], k) ^ gfmul(a[2], b[2], k) +D = json.load(open(PKG + '/data/cr2_realisations.json')); random.seed(7) +nb = 0 +for nm, r in D.items(): + k = r['k']; Pc, Qc = load_cfg(nm + '.json'); v = len(Pc); R, A, free = setup(Pc, Qc); pi, sig = cfg_data(Pc, Qc) + Pt, Qt = r['P'], r['Q'] + s_ok = all(all(Pt[t][j] == 0 for j in range(3) if j not in pi[t]) and all(Qt[t][j] == 0 for j in range(3) if j not in sig[t]) and all(0 <= x < (1 << k) for x in Pt[t] + Qt[t]) for t in range(v)) + inc_ok = all(dot(Pt[t], Qt[s], k) == 0 for (t, s) in free) + dg_ok = all(dot(Pt[t], Qt[t], k) != 0 for t in range(v)) + nt = 40; good = 0 + for _ in range(nt): + B = tomat(random.getrandbits(len(free)), free, v) + N = [[(dot(Pt[t], Qt[s], k) if B[t][s] else 0) for s in range(v)] for t in range(v)] + good += all((N[t][s] == 0) == (t != s) for t in range(v) for s in range(v)) and sum(blockranks(B, R, A)) >= v + report('C %-15s v=%2d f=%3d GF(2^%d): supports, %d incidences, %d diagonals, %d random B (N diagonal, cost>=v)' % (nm, v, len(free), k, len(free), v, nt), s_ok and inc_ok and dg_ok and good == nt) +report('C all 21 stored configurations except tied_min: full pattern CR2 (cex_min_1 over GF(4), others GF(2))', len(D) == 21 and D['cex_min_1']['k'] == 2 and all(r['k'] == 1 for n_, r in D.items() if n_ != 'cex_min_1')) +Pt_, Qt_ = load_cfg('tied_min.json'); R, A, free = setup(Pt_, Qt_); pi, sig = cfg_data(Pt_, Qt_) +res = [realise(pi, sig, set(free), k=k) for k in (1, 2, 3, 4)] +report('C tied_min: full 72-incidence pattern has NO realisation over GF(2), GF(4), GF(8), GF(16) (exhaustive DFS)', all(r is None for r in res), str(['none' if r is None else 'FOUND' for r in res])) +# minimal non-CR2 atoms: the minimal elements of the stored family; each is non-realisable over GF(2),GF(4),GF(8) and every one-line deletion is realisable +fam = [tuple(x) for x in json.load(open(PKG + '/data/tm_noncr2.json'))]; fs = set(fam) +minimal = [S for S in fam if not any(tuple(x for x in S if x != y) in fs for y in S)] +Pm, Qm = Pt_, Qt_ +def sub(S): return [Pm[i] for i in S], [Qm[i] for i in S] +def cr2(S, ks): + P_, Q_ = sub(S); R_, A_, fr = setup(P_, Q_); pi_, sig_ = cfg_data(P_, Q_) + for k in ks: + r = realise(pi_, sig_, set(fr), k=k, limit=10 ** 6) + if isinstance(r, dict): return True + return False +from collections import Counter +cnt = Counter(len(S) for S in minimal) +report('C minimal non-CR2 sub-configurations of tied_min (from stored family): %s lines' % dict(sorted(cnt.items())), sum(cnt.values()) == 44 and cnt[6] == 32 and cnt[7] == 12, 'total %d' % len(minimal)) +bad_non = [S for S in minimal if cr2(S, (1, 2, 3))] +bad_min = [S for S in minimal for y in S if not cr2(tuple(x for x in S if x != y), (1, 2, 3))] +report('C each of the 44 atoms is not realisable over GF(2),GF(4),GF(8) (exhaustive)', not bad_non, '%d violations' % len(bad_non)) +report('C every one-line deletion of every atom IS realisable (so the atoms are minimal)', not bad_min, '%d violations' % len(bad_min)) +tight = 0 +for S in minimal: + if len(S) == 6: + P_, Q_ = sub(S); R_, A_, fr = setup(P_, Q_); tight += kit.enum_raw(6, R_, A_, fr, 0)[0] == 6 +report('C all 32 six-line atoms are tight: exhaustive minimum cost = 6 = v (the 12 seven-line atoms have minimum cost 8: RECORDED, 2^26 each)', tight == 32, '%d/32' % tight) +done() diff --git a/research/char2-jets/checks/c_jets.py b/research/char2-jets/checks/c_jets.py new file mode 100644 index 0000000000..60f2bd087f --- /dev/null +++ b/research/char2-jets/checks/c_jets.py @@ -0,0 +1,35 @@ +"""Corollary J (B-independent first-order jet test, no-wild class) on: all 4095 sub-configurations of tied_min; a seeded sample of random all-harmonic configurations +(same generator as scripts/t16.py). For each configuration: classify (no wild incidence), phi with random z_p over GF(2^16) (preserving binomial incidences), exact order-0 checks +(incidences 0, harmonic diagonals 0, other diagonals != 0), then (J1) solved as a nullspace over GF(2^16) and every (J2) functional tested for being non-zero on it +(over the algebraic closure this gives one jet satisfying all of (J2), see README). A pass is a certificate that (A) holds for the configuration for every B.""" +import itertools, random, collections, sys +from common import * +from kit import *; from phi import *; from tangent import tangent_cr2; from gen import prim +def jtest(P, Q): + v = len(P); R, A, free = setup(P, Q) + pi = [{j for j in range(3) if P[t][j]} for t in range(v)]; sig = [{j for j in range(3) if Q[t][j]} for t in range(v)] + w, H = classify(P, Q) + if w: return 'wild' + phi = make_phi(random.Random(12345)); Pt = [[phi(x) for x in p] for p in P]; Qt = [[phi(x) for x in q] for q in Q] + if not all(dot2(Pt[t], Qt[s]) == 0 for (t, s) in free): return 'order0-incidence' + dz = [t for t in range(v) if dot2(Pt[t], Qt[t]) == 0] + if dz != H: return 'order0-diagonal' + res, dim = tangent_cr2(Pt, Qt, pi, sig, free, H) + return 'ok' if all(res.values()) else 'fail' +P0, Q0 = load_cfg('tied_min.json'); st = collections.Counter() +for m in range(1, 13): + for S in itertools.combinations(range(12), m): + st[jtest([P0[i] for i in S], [Q0[i] for i in S])] += 1 +report('J all 4095 sub-configurations of tied_min pass the jet test (hence cost >= |W| for every B on each)', dict(st) == {'ok': 4095}, str(dict(st))) +def harm(p, k): + i, j = [x for x in range(3) if x != k]; q = [0, 0, 0]; q[i] = p[j]; q[j] = p[i]; return prim(q) +random.seed(11); st = collections.Counter(); N = int(sys.argv[1]) if len(sys.argv) > 1 else 1500 +for it in range(N): + r = random.choice([2, 3, 5]); E = random.choice([1, 2, 3]) + pool = list({tuple(prim([random.choice([1, -1]) * r ** random.randint(0, E), random.choice([1, -1]) * r ** random.randint(0, E), random.choice([1, -1]) * r ** random.randint(0, E)])) for _ in range(random.randint(3, 8))}) + v = random.randint(4, 14); P = []; Q = [] + for _ in range(v): + p = list(random.choice(pool)); k = random.randrange(3); P.append(p); Q.append(harm(p, k)) + st[jtest(P, Q)] += 1 +report('J %d random all-harmonic configurations (v = 4..14, entries +-r^a) pass the jet test (the 1500 of the working notes)' % N, dict(st) == {'ok': N}, str(dict(st))) +done() diff --git a/research/char2-jets/checks/common.py b/research/char2-jets/checks/common.py new file mode 100644 index 0000000000..40145063b8 --- /dev/null +++ b/research/char2-jets/checks/common.py @@ -0,0 +1,13 @@ +"""Shared helpers of the checks: path bootstrap and PASS/FAIL reporting (one line per assertion; exit status 1 on any FAIL).""" +import os, sys, time +PKG = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG + '/lib') +import kit +kit.BIN = os.environ.get('TTD_BIN') or PKG + '/c/bin' +BAD = [0]; T0 = [time.time()] +def report(name, ok, msg=''): + print('%s %s %s' % ('PASS' if ok else 'FAIL', name, msg), flush=True) + if not ok: BAD[0] += 1 +def done(): + print(' (%.1fs)' % (time.time() - T0[0]), flush=True) + sys.exit(1 if BAD[0] else 0) diff --git a/research/char2-jets/checks/d_lemmaA_B2.py b/research/char2-jets/checks/d_lemmaA_B2.py new file mode 100644 index 0000000000..5e97b4f5fe --- /dev/null +++ b/research/char2-jets/checks/d_lemmaA_B2.py @@ -0,0 +1,67 @@ +"""Lemma A (T = 2) as a corollary of CR2, and spot checks of Theorem B2. +Lemma A: a configuration in P^1 (p(t), q(s) in Z^2, p(t).q(t) != 0). The finitely many points p(t) and perp(q(s)) = (q2, -q1) of P^1(Q) are mapped injectively into P^1(GF(2^k)) fixing +[1:0] and [0:1]; the image vectors are a CR2 realisation (incidence <=> equality of points, preserved by injectivity; diagonal <=> inequality, preserved too). Verified exactly for random +configurations (and for random admissible B: N = sum_j D(p~_j) B D(q~_j) is diagonal with non-zero diagonal). +B2: for random no-wild configurations, phi (phi(-1) = 1, phi(prime) = random element of GF(2^16)*) preserves every incidence of the blocks, its diagonal vanishes exactly on the harmonic +lines H, and the exhaustive minimum cost (C program enumall, f <= 20) is >= v - |H|.""" +import random, collections, sys +from fractions import Fraction +from common import * +from kit import *; from phi import *; from gen import randcfg +from gr import mul +def gfmul(a, b, k, m): + r = 0 + while b: + if b & 1: r ^= a + b >>= 1; a <<= 1 + if a >> k & 1: a ^= m + return r +IR = {4: 0b10011, 6: 0b1000011} +random.seed(3); okA = 0; nA = 60 +for it in range(nA): + v = random.randint(3, 9); pts = [(1, 0), (0, 1)] + [(random.choice([1, 2, 3, -1, -2]), random.choice([1, 2, 3, -1, -2, 5])) for _ in range(5)] + P = [list(random.choice(pts)) + [0] for _ in range(v)]; Q = [] + for t in range(v): + while True: + q = [random.randint(-3, 3), random.randint(-3, 3), 0] + if (q[0] or q[1]) and P[t][0] * q[0] + P[t][1] * q[1] != 0: Q.append(q); break + norm = lambda x, y: Fraction(y, x) if x else None # P^1(Q) point [x:y] -> y/x, infinity -> None + perp = lambda q: (q[1], -q[0]) # p.q = 0 iff p ~ perp(q) + used = {norm(*p[:2]) if p[0] else 'inf' for p in P} | {norm(*perp(q)) if perp(q)[0] else 'inf' for q in Q} + k = 6; vals = [z for z in used if z not in ('inf', 0)]; assert len(vals) < (1 << k) - 1 + img = {'inf': None, 0: 0}; nxt = iter(range(1, 1 << k)) + for z in vals: img[z] = next(nxt) + def vec(p): # image of point p of P^1(Q) as a vector of GF(2^k)^2 + if p[0] == 0: return [0, 1] + z = Fraction(p[1], p[0]); return [1, img[z]] # z = 0 -> [1:0] + Pt = [vec(p) + [0] for p in P] + # line vector q~ = perp of the image point; in char 2 perp(x, y) = (y, x) + Qt = [[vec(perp(q))[1], vec(perp(q))[0], 0] for q in Q] + R, A, free = setup(P, Q); pi = [{j for j in range(3) if P[t][j]} for t in range(v)]; sig = [{j for j in range(3) if Q[t][j]} for t in range(v)] + dotk = lambda a, b: gfmul(a[0], b[0], k, IR[k]) ^ gfmul(a[1], b[1], k, IR[k]) + s_ok = all(Pt[t][j] == 0 for t in range(v) for j in range(3) if j not in pi[t]) and all(Qt[t][j] == 0 for t in range(v) for j in range(3) if j not in sig[t]) + good = s_ok and all(dotk(Pt[t], Qt[s]) == 0 for (t, s) in free) and all(dotk(Pt[t], Qt[t]) != 0 for t in range(v)) + for _ in range(5): + B = tomat(random.getrandbits(len(free)), free, v) + N = [[(dotk(Pt[t], Qt[s]) if B[t][s] else 0) for s in range(v)] for t in range(v)] + good = good and all((N[t][s] == 0) == (t != s) for t in range(v) for s in range(v)) and sum(blockranks(B, R, A)) >= v + okA += good +report('A Lemma A (T=2): explicit injection P^1(Q) -> P^1(GF(2^6)) realises the full pattern; N diagonal; cost >= v', okA == nA, '%d/%d random T=2 configurations' % (okA, nA)) +random.seed(5); st = collections.Counter(); nB = int(sys.argv[1]) if len(sys.argv) > 1 else 80 +def nowild_cfg(v, R): + while True: + P, Q = randcfg(v, R=R) + w, H = classify(P, Q) + if w == 0: return P, Q +for it in range(nB): + v = random.randint(5, 9); P, Q = nowild_cfg(v, random.choice([1, 2, 3])) + w, H = classify(P, Q); R, A, free = setup(P, Q) + phi = make_phi(random.Random(it)); Pt = [[phi(x) for x in p] for p in P]; Qt = [[phi(x) for x in q] for q in Q] + st['inc'] += all(dot2(Pt[t], Qt[s]) == 0 for (t, s) in free) + st['diag0==H'] += [t for t in range(v) if dot2(Pt[t], Qt[t]) == 0] == H + if len(free) <= 20: + best, ms = enum_raw(v, R, A, free, 0); st['n_exh'] += 1; st['cost>=v-|H|'] += best >= v - len(H) + st['H>0'] += len(H) > 0 +report('B2 phi preserves all incidences, zero diagonals = H exactly, on %d random no-wild configurations' % nB, st['inc'] == nB and st['diag0==H'] == nB, str(dict(st))) +report('B2 exhaustive min cost >= v - |H| on the %d of them with f <= 20 (%d with |H| > 0)' % (st['n_exh'], st['H>0']), st['n_exh'] > 0 and st['cost>=v-|H|'] == st['n_exh']) +done() diff --git a/research/char2-jets/checks/e_jetfail.py b/research/char2-jets/checks/e_jetfail.py new file mode 100644 index 0000000000..7911f9e624 --- /dev/null +++ b/research/char2-jets/checks/e_jetfail.py @@ -0,0 +1,48 @@ +"""jetfail jf0, jf1, jf2: no-wild configurations with a harmonic line that the first-order jet cannot move, but for which (A) still holds. +Checks (exact): no-wild; first-order tangent test fails (random phi, and the full collapse phi0 over F2: immovable lines 0 / 7 / 0,2); order-2 diagonal Q_t is identically zero as a polynomial on the +first-order tangent space V (the order-2 jet fails structurally); full pattern not CR2 over GF(2), GF(4), GF(8); exact minimum cost by exhaustive enumeration (C program enumall) = 12 (v = 9, 192 +minimisers) for jf1 and 14 (v = 9, 12928 minimisers) for jf2; jf0 (v = 11, f = 41 too large to enumerate): the CNF 'cost <= K' is UNSAT for K <= 15 (CaDiCaL, python-sat) so cost >= 16 > v; +B-dependent jet test on the jf1 minimisers (the CR2 status of these 192 is recorded, not re-run).""" +import json, collections, random +import numpy as np +from common import * +from kit import *; from phi import *; from tangent import tangent_cr2; from cr2 import realise, cfg_data; from jet2 import * +exp = {0: dict(v=11, f=41, imm=[0]), 1: dict(v=9, f=27, imm=[7], cost=12, nmin=192), 2: dict(v=9, f=20, imm=[0, 2], cost=14, nmin=12928)} +def polyvec(M): + d = M.shape[0]; out = [] + for i in range(d): + for j in range(i, d): out.append(int(M[i, i]) if i == j else int(M[i, j] ^ M[j, i])) + return int(''.join(map(str, out)), 2) if out else 0 +for i in range(3): + P, Q = json.load(open(PKG + '/data/jf%d.json' % i)); v = len(P); R, A, free = setup(P, Q); pi, sig = cfg_data(P, Q); e = exp[i] + w, H = classify(P, Q) + report('F jf%d: v=%d, f=%d, no-wild, harmonic lines %s' % (i, v, len(free), H), (v, len(free), w) == (e['v'], e['f'], 0) and len(H) > 0) + phi = make_phi(random.Random(1)); Pt = [[phi(x) for x in p] for p in P]; Qt = [[phi(x) for x in q] for q in Q] + res, dim = tangent_cr2(Pt, Qt, pi, sig, free, H) + bad = sorted(t for t in H if not res[t]) + an = analyse(P, Q, free, H) + report('F jf%d: first-order jet test FAILS (phi random z_p: harmonic lines immovable %s; full collapse phi0: %s)' % (i, bad, sorted(an['imm'])), bool(bad) and sorted(an['imm']) == e['imm']) + E = an['E'] + deps = [polyvec(quad_matrix(an, [E[k] for k in range(len(E)) if z >> k & 1])) for z in an['deps']] + ok2 = all(polyvec(quad_matrix(an, [(t, t)] + [E[k] for k in range(len(E)) if c >> k & 1])) == 0 for t, c in an['imm'].items()) + report('F jf%d: order-2 diagonal Q_t is identically 0 on the first-order tangent space V (dim V = %d) for every immovable line' % (i, len(an['basis'])), ok2) + nc = [realise(pi, sig, set(free), k=k, limit=10 ** 6) for k in (1, 2, 3)] + report('F jf%d: full pattern not CR2 over GF(2), GF(4), GF(8) (exhaustive)' % i, all(r is None for r in nc)) + if i in (1, 2): + best, ms = enum_raw(v, R, A, free, 0) + report('F jf%d: exact minimum cost (exhaustive over 2^%d admissible B) = %d, %d minimisers; v = %d, so (A) holds' % (i, len(free), best, len(ms), v), best == e['cost'] and len(ms) == e['nmin'] and best >= v) + if i == 1: + cj = 0 + for c_, g in ms: + ent = [free[k] for k in range(len(free)) if g >> k & 1] + r_, d_ = tangent_cr2(Pt, Qt, pi, sig, ent, H); cj += all(r_.values()) + report('F jf1: B-dependent: of the 192 minimisers, %d pass the first-order jet test on E = supp B (the other %d do not)' % (cj, 192 - cj), cj == 186, 'RECORDED, not re-run here: exactly these 186 are also CR2 (scripts/ + README)') + else: + try: + from satlib import cost_leq + import time + t0 = time.time(); un = all(cost_leq(P, Q, K) is None for K in (15,)) + report('F jf0: CNF "cost <= 15" is UNSAT (and hence <= K for K < 15), so cost(jf0) >= 16 > v = 11', un, '%.0fs' % (time.time() - t0)) + except ImportError: + print('SKIP F jf0 cost >= 16 (python-sat not installed); RECORDED in the README') +done() diff --git a/research/char2-jets/checks/provenance.py b/research/char2-jets/checks/provenance.py new file mode 100644 index 0000000000..4d94441a9b --- /dev/null +++ b/research/char2-jets/checks/provenance.py @@ -0,0 +1,34 @@ +"""Step 0 of verify.sh (standard library only): every file of the package matches MANIFEST.sha256 (sha256), none is missing and none is extra. +Prints PASS/FAIL and exits 1 on any mismatch. usage: python3 provenance.py [--write-manifest] (the flag is for the authors) +Ignored: __pycache__, *.pyc, .DS_Store, a bin/ directory of compiled programs, and lean/.lake, lean/build (Lean build products).""" +import hashlib, os, sys +PKG = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +def sha(b): return hashlib.sha256(b).hexdigest() +def listing(): + out = [] + for d, ds, fs in os.walk(PKG): + ds[:] = sorted(x for x in ds if x not in ('__pycache__', 'bin', '.lake', 'build')) + for f in fs: + if f.endswith('.pyc') or f == '.DS_Store': continue + p = os.path.relpath(os.path.join(d, f), PKG) + if p != 'MANIFEST.sha256': out.append(p) + return sorted(out) +if '--write-manifest' in sys.argv: + with open(os.path.join(PKG, 'MANIFEST.sha256'), 'w') as h: + for p in listing(): h.write('%s %s\n' % (sha(open(os.path.join(PKG, p), 'rb').read()), p)) + print('wrote MANIFEST.sha256 (%d files)' % len(listing())); sys.exit(0) +bad = 0; want = {} +try: + for l in open(os.path.join(PKG, 'MANIFEST.sha256'), encoding='utf-8'): + h, p = l.rstrip('\n').split(' ', 1); want[p] = h +except OSError: + print('FAIL 0.manifest MANIFEST.sha256 missing'); sys.exit(1) +have = listing(); n = 0 +for p in sorted(set(want) | set(have)): + f = os.path.join(PKG, p) + if p not in want: print('FAIL 0.manifest extra file not in MANIFEST: ' + p); bad += 1 + elif not os.path.isfile(f): print('FAIL 0.manifest missing file: ' + p); bad += 1 + elif sha(open(f, 'rb').read()) != want[p]: print('FAIL 0.manifest hash differs: ' + p); bad += 1 + else: n += 1 +print('%s 0.manifest %d files match MANIFEST.sha256' % ('PASS' if not bad else 'FAIL', n), flush=True) +sys.exit(1 if bad else 0) diff --git a/research/char2-jets/data/aff14.json b/research/char2-jets/data/aff14.json new file mode 100644 index 0000000000..5e44c9fe09 --- /dev/null +++ b/research/char2-jets/data/aff14.json @@ -0,0 +1 @@ +[[[0, 3, 2], [3, 0, -1], [1, -3, -3], [1, 3, 1], [3, 1, 3], [1, -3, 3], [2, -3, -2], [2, 3, 3], [1, -2, -2], [2, 1, -1], [2, -1, -1], [1, -1, 2], [3, -3, -1], [0, 1, 2]], [[2, -3, 4], [0, 1, -1], [0, 1, -3], [6, 4, -1], [2, 2, -1], [1, 0, 3], [3, -4, 2], [3, -4, 9], [3, -2, 3], [1, -12, 3], [0, 2, -3], [15, 2, -3], [0, 0, 1], [6, -3, -5]], [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1], [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0], [1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1]]] \ No newline at end of file diff --git a/research/char2-jets/data/cech_v8.json b/research/char2-jets/data/cech_v8.json new file mode 100644 index 0000000000..731b545d93 --- /dev/null +++ b/research/char2-jets/data/cech_v8.json @@ -0,0 +1 @@ +[[[-1, 2, 1], [-1, 2, -1], [-2, -2, -1], [-2, 2, 0], [2, -1, -2], [1, -3, 4], [0, -2, 2], [0, -4, 2]], [[1, -1, -1], [2, 0, 0], [-2, 2, 2], [4, 2, 0], [-4, 1, 6], [4, 0, -8], [-4, 1, 6], [0, 2, -2]]] \ No newline at end of file diff --git a/research/char2-jets/data/cex_joint_v7.json b/research/char2-jets/data/cex_joint_v7.json new file mode 100644 index 0000000000..cf7a3db872 --- /dev/null +++ b/research/char2-jets/data/cex_joint_v7.json @@ -0,0 +1 @@ +[[[2, 0, -2], [-32, -32, -48], [-4, -4, -4], [0, 1, 1], [-2, 0, -1], [0, -1, 1], [-2, -2, 0]], [[2, -12, -4], [1, -2, 0], [-2, 2, -1], [-1, 2, -1], [-2, 0, 2], [-4, 4, 0], [32, 64, -64]]] \ No newline at end of file diff --git a/research/char2-jets/data/cex_min_1.json b/research/char2-jets/data/cex_min_1.json new file mode 100644 index 0000000000..4629aa02b1 --- /dev/null +++ b/research/char2-jets/data/cex_min_1.json @@ -0,0 +1 @@ +[[[1, -1, 0], [1, 0, -1]], [[1, -1, 1], [0, 1, -1]], [[1, -1, 1], [1, -1, 0]], [[1, -1, 1], [1, 0, 1]], [[1, 0, -1], [0, 1, -1]], [[1, 0, -1], [0, 1, 1]], [[1, 0, -1], [1, -1, 0]], [[1, 0, -1], [1, 1, -1]], [[1, 0, 1], [1, 1, 0]], [[1, 0, 1], [1, 1, 1]], [[1, 1, -1], [0, 1, -1]], [[1, 1, -1], [1, -1, 1]], [[1, 1, -1], [1, 0, -1]], [[1, 1, -1], [1, 1, 0]], [[1, 1, 0], [0, 1, 1]], [[1, 1, 0], [1, 0, 1]], [[1, 1, 1], [0, 1, 1]], [[1, 1, 1], [1, 0, 1]], [[1, 1, 1], [1, 1, 0]]] \ No newline at end of file diff --git a/research/char2-jets/data/cex_wholeTS_v9.json b/research/char2-jets/data/cex_wholeTS_v9.json new file mode 100644 index 0000000000..a843cce049 --- /dev/null +++ b/research/char2-jets/data/cex_wholeTS_v9.json @@ -0,0 +1 @@ +[[[2, -1, -2], [1, 0, -1], [2, 2, -1], [0, -6, 3], [-3, -2, 1], [3, 2, -1], [-2, 0, -2], [1, 3, 1], [-2, 2, 0]], [[-2, 2, 2], [1, 1, 2], [1, 1, 2], [0, 6, -3], [4, 0, 8], [3, -1, -3], [4, 0, 8], [1, 0, 1], [-1, 0, -1]]] \ No newline at end of file diff --git a/research/char2-jets/data/cr2_realisations.json b/research/char2-jets/data/cr2_realisations.json new file mode 100644 index 0000000000..9b5e66750b --- /dev/null +++ b/research/char2-jets/data/cr2_realisations.json @@ -0,0 +1 @@ +{"aff14": {"k": 1, "P": [[0, 0, 1], [0, 0, 1], [0, 1, 0], [0, 0, 1], [0, 0, 1], [1, 0, 0], [1, 0, 0], [0, 1, 0], [1, 0, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 0, 1], [0, 1, 0]], "Q": [[0, 0, 1], [0, 0, 1], [0, 1, 0], [0, 0, 1], [0, 0, 1], [1, 0, 0], [1, 0, 0], [0, 1, 0], [1, 0, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 0, 1], [0, 1, 0]]}, "cech_v8": {"k": 1, "P": [[0, 0, 1], [1, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]], "Q": [[0, 0, 1], [1, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]]}, "cex_joint_v7": {"k": 1, "P": [[0, 0, 1], [1, 0, 1], [0, 0, 1], [0, 1, 0], [1, 0, 1], [0, 1, 0], [1, 0, 0]], "Q": [[1, 0, 1], [1, 0, 0], [0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 0], [1, 0, 1]]}, "cex_wholeTS_v9": {"k": 1, "P": [[0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 0, 1], [1, 0, 0], [1, 0, 0], [1, 0, 0]], "Q": [[0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 0, 1], [1, 0, 0], [1, 0, 0], [1, 0, 0]]}, "gad": {"k": 1, "P": [[1, 0, 1], [0, 0, 1], [0, 0, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]], "Q": [[0, 1, 1], [1, 0, 1], [0, 1, 1], [0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]}, "supmin_fail_v8": {"k": 1, "P": [[1, 0, 0], [0, 1, 0], [1, 0, 0], [0, 0, 1], [0, 0, 1], [0, 1, 0], [0, 0, 1], [0, 0, 1]], "Q": [[1, 0, 0], [0, 1, 0], [1, 0, 0], [0, 0, 1], [0, 0, 1], [0, 1, 0], [0, 0, 1], [0, 0, 1]]}, "nojoint_21_1": {"k": 1, "P": [[1, 0, 0], [1, 0, 0], [0, 0, 1], [1, 0, 0], [0, 1, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [0, 1, 0], [0, 1, 1]], "Q": [[1, 0, 0], [1, 0, 0], [0, 0, 1], [1, 0, 0], [0, 0, 1], [0, 1, 1], [0, 1, 0], [1, 0, 0], [0, 1, 1], [0, 0, 1]]}, "nojoint_21_2": {"k": 1, "P": [[0, 1, 0], [1, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 1], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0]], "Q": [[0, 1, 0], [1, 0, 0], [0, 0, 1], [0, 1, 1], [0, 0, 1], [0, 0, 1], [0, 1, 0], [0, 1, 0], [1, 0, 0]]}, "nojoint_21_3": {"k": 1, "P": [[0, 0, 1], [1, 1, 1], [0, 1, 0], [1, 0, 0], [0, 0, 1], [1, 1, 0], [1, 0, 0], [0, 1, 0]], "Q": [[0, 0, 1], [0, 0, 1], [0, 1, 0], [1, 0, 1], [0, 1, 1], [1, 0, 0], [1, 1, 0], [0, 1, 0]]}, "nojoint_21_4": {"k": 1, "P": [[0, 0, 1], [0, 0, 1], [0, 0, 1], [1, 0, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]], "Q": [[0, 0, 1], [0, 0, 1], [0, 0, 1], [1, 0, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]}, "nojoint_21_5": {"k": 1, "P": [[0, 1, 0], [1, 0, 0], [0, 0, 1], [0, 1, 0], [1, 1, 0], [1, 1, 0], [0, 0, 1], [1, 0, 0], [1, 0, 0]], "Q": [[0, 1, 0], [1, 1, 0], [0, 0, 1], [0, 1, 0], [0, 1, 0], [1, 0, 0], [0, 0, 1], [1, 0, 0], [1, 1, 0]]}, "nojoint_21_6": {"k": 1, "P": [[1, 0, 1], [0, 0, 1], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [0, 1, 1], [1, 0, 0]], "Q": [[0, 0, 1], [1, 0, 1], [0, 0, 1], [0, 1, 1], [0, 1, 0], [1, 0, 0], [0, 1, 0], [1, 0, 0]]}, "nojoint_21_7": {"k": 1, "P": [[0, 1, 0], [1, 1, 1], [0, 0, 1], [0, 0, 1], [1, 0, 0], [0, 1, 1], [1, 0, 0], [0, 1, 0]], "Q": [[0, 1, 0], [0, 0, 1], [0, 1, 1], [0, 1, 1], [1, 0, 0], [0, 0, 1], [1, 0, 0], [1, 1, 0]]}, "nojoint_21_8": {"k": 1, "P": [[1, 0, 1], [0, 1, 0], [0, 1, 0], [1, 0, 0], [0, 0, 1], [1, 0, 0], [0, 1, 1], [1, 1, 1], [0, 0, 1]], "Q": [[1, 1, 0], [1, 1, 1], [0, 1, 1], [1, 0, 0], [0, 0, 1], [1, 0, 0], [1, 0, 1], [0, 0, 1], [0, 0, 1]]}, "nojoint_21_9": {"k": 1, "P": [[1, 0, 0], [0, 0, 1], [0, 0, 1], [1, 1, 0], [0, 0, 1], [1, 1, 1], [0, 0, 1], [1, 0, 0], [0, 1, 0]], "Q": [[1, 0, 0], [0, 0, 1], [0, 0, 1], [0, 1, 1], [0, 0, 1], [0, 1, 0], [0, 0, 1], [1, 1, 0], [1, 1, 0]]}, "nojoint_21_10": {"k": 1, "P": [[0, 1, 0], [0, 1, 0], [1, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [0, 1, 0], [1, 0, 1]], "Q": [[0, 1, 0], [0, 1, 0], [1, 0, 0], [0, 0, 1], [0, 1, 1], [0, 1, 0], [1, 0, 1], [0, 1, 0], [1, 0, 0]]}, "nojoint_21_11": {"k": 1, "P": [[0, 0, 1], [1, 0, 0], [0, 1, 0], [1, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 1], [1, 1, 0]], "Q": [[0, 0, 1], [1, 0, 0], [1, 1, 0], [1, 1, 0], [0, 0, 1], [0, 1, 0], [0, 0, 1], [0, 1, 0]]}, "nojoint_21_12": {"k": 1, "P": [[0, 0, 1], [0, 0, 1], [1, 0, 1], [0, 1, 1], [0, 1, 0], [0, 1, 0], [1, 0, 0], [0, 1, 1]], "Q": [[1, 1, 1], [0, 1, 1], [0, 1, 1], [0, 1, 0], [0, 1, 0], [0, 1, 1], [1, 0, 0], [0, 0, 1]]}, "nojoint_21_13": {"k": 1, "P": [[0, 0, 1], [1, 1, 0], [0, 1, 0], [0, 1, 0], [1, 0, 0], [0, 0, 1], [1, 0, 0]], "Q": [[0, 0, 1], [0, 1, 0], [1, 1, 0], [0, 1, 0], [1, 0, 0], [0, 0, 1], [1, 1, 0]]}, "nojoint_21_14": {"k": 1, "P": [[0, 1, 0], [0, 0, 1], [0, 0, 1], [0, 0, 1], [1, 0, 0], [1, 0, 0], [1, 0, 1], [0, 0, 1]], "Q": [[0, 1, 0], [0, 0, 1], [1, 0, 1], [0, 0, 1], [1, 0, 0], [1, 0, 0], [0, 0, 1], [1, 0, 1]]}, "cex_min_1": {"k": 2, "P": [[1, 1, 0], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 0, 2], [1, 0, 2], [1, 0, 2], [1, 0, 2], [1, 0, 1], [1, 0, 1], [1, 2, 2], [1, 2, 2], [1, 2, 2], [1, 2, 2], [1, 2, 0], [1, 2, 0], [1, 2, 1], [1, 2, 1], [1, 2, 1]], "Q": [[1, 0, 1], [0, 1, 2], [1, 3, 0], [1, 0, 3], [0, 1, 2], [0, 1, 1], [1, 3, 0], [1, 1, 1], [1, 1, 0], [1, 1, 3], [0, 1, 2], [1, 3, 3], [1, 0, 1], [1, 1, 0], [0, 1, 1], [1, 0, 3], [0, 1, 1], [1, 0, 3], [1, 1, 0]]}} \ No newline at end of file diff --git a/research/char2-jets/data/gad.json b/research/char2-jets/data/gad.json new file mode 100644 index 0000000000..9cd95fad4d --- /dev/null +++ b/research/char2-jets/data/gad.json @@ -0,0 +1 @@ +[[[1, 0, 1], [0, 2, 1], [3, 3, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]], [[0, 4, -4], [-4, 0, 4], [-1, -4, 5], [1, 0, 1], [0, 1, 1], [1, 1, 3], [-2, -1, 2], [-3, 2, 3], [-1, 3, -6], [6, 4, -30]], [[1, 0, 0, 0, 0, 0, 1, 1, 0, 0], [0, 1, 0, 0, 0, 0, 1, 0, 1, 0], [0, 0, 1, 0, 0, 0, 0, 1, 1, 1], [1, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 1, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 1, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0, 1, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0, 1, 0], [1, 1, 1, 0, 0, 0, 0, 0, 0, 1]]] \ No newline at end of file diff --git a/research/char2-jets/data/jf0.json b/research/char2-jets/data/jf0.json new file mode 100644 index 0000000000..100b78f665 --- /dev/null +++ b/research/char2-jets/data/jf0.json @@ -0,0 +1 @@ +[[[1, 1, 1], [0, 1, 1], [1, 0, -1], [1, 1, 0], [1, 1, 1], [0, 1, 1], [1, 1, 0], [1, 1, 1], [1, 1, 1], [1, 0, -1], [1, 1, 1]], [[1, 0, 1], [0, 1, 1], [1, -1, 0], [0, 1, -1], [1, -1, -2], [1, 0, 1], [1, 1, 0], [1, -1, -2], [1, -1, 1], [1, -1, 0], [1, -1, 1]]] \ No newline at end of file diff --git a/research/char2-jets/data/jf1.json b/research/char2-jets/data/jf1.json new file mode 100644 index 0000000000..dd841a25fc --- /dev/null +++ b/research/char2-jets/data/jf1.json @@ -0,0 +1 @@ +[[[1, 1, -1], [1, -1, 0], [1, -1, 0], [1, -1, 1], [1, -1, 0], [1, -1, 0], [1, 1, -1], [0, 1, -1], [1, 0, 1]], [[1, 0, -1], [0, 1, 1], [0, 1, -1], [1, -1, -1], [1, 0, -1], [1, -1, 0], [1, 1, 0], [1, 1, -1], [1, 1, 0]]] \ No newline at end of file diff --git a/research/char2-jets/data/jf2.json b/research/char2-jets/data/jf2.json new file mode 100644 index 0000000000..9c5379c4c7 --- /dev/null +++ b/research/char2-jets/data/jf2.json @@ -0,0 +1 @@ +[[[1, 1, 1], [1, 1, 0], [1, 1, 1], [0, 1, 1], [1, 0, 1], [0, 1, -1], [1, 1, 0], [1, 1, 1], [0, 1, 1]], [[0, 1, 1], [1, 0, -1], [0, 1, 1], [1, 0, 1], [1, 0, 1], [1, -1, 0], [1, 0, -1], [1, -1, -1], [0, 1, 1]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_1.json b/research/char2-jets/data/nojoint_21_1.json new file mode 100644 index 0000000000..154d2ffb50 --- /dev/null +++ b/research/char2-jets/data/nojoint_21_1.json @@ -0,0 +1 @@ +[[[-2, 1, -2], [-96, 0, 0], [-4, 0, 4], [2, 0, 1], [192, -192, 384], [-2, -1, -2], [16, -16, 32], [-10, -2, -2], [0, -8, 0], [2, 2, -2]], [[-1, 0, -1], [4, 4, 0], [0, -8, 8], [-2, 2, -2], [-4, 0, 4], [-2, 6, 4], [0, -12, 0], [16, 0, -8], [0, -192, -96], [0, -2, 1]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_10.json b/research/char2-jets/data/nojoint_21_10.json new file mode 100644 index 0000000000..be9e238216 --- /dev/null +++ b/research/char2-jets/data/nojoint_21_10.json @@ -0,0 +1 @@ +[[[1, 1, 0], [-1, -1, -1], [12, -44, 14], [-2, -2, -1], [-12, 12, -14], [11, -1, -6], [-2, 1, 0], [-1, -1, -2], [2, 2, 2]], [[1, 2, -6], [-6, 2, 8], [-2, 2, 2], [-14, 0, 12], [-2, -4, -3], [-1, -2, 6], [-48, -16, 64], [2, -1, -2], [1, 1, 0]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_11.json b/research/char2-jets/data/nojoint_21_11.json new file mode 100644 index 0000000000..e684f066b3 --- /dev/null +++ b/research/char2-jets/data/nojoint_21_11.json @@ -0,0 +1 @@ +[[[0, 2, -2], [2, 2, 2], [18, 6, -24], [6, 8, 5], [0, -1, -1], [4, 2, -3], [-6, -2, -2], [-66, -42, 18]], [[-6, 2, 4], [-60, 180, 0], [48, -132, -132], [-1, 2, 1], [-3, 1, 2], [6, -2, -4], [30, -42, 12], [0, 2, -2]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_12.json b/research/char2-jets/data/nojoint_21_12.json new file mode 100644 index 0000000000..4a5df3368c --- /dev/null +++ b/research/char2-jets/data/nojoint_21_12.json @@ -0,0 +1 @@ +[[[-1, -2, -2], [-2, 0, -1], [-2, 2, 1], [-6, 5, -2], [0, -1, -2], [2, -2, 0], [-6, 0, 0], [0, 36, -36]], [[-108, -72, -72], [-1, -2, -2], [0, -216, -216], [3, 5, -4], [3, 6, -6], [-18, -36, -36], [-2, -3, 4], [0, -12, 6]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_13.json b/research/char2-jets/data/nojoint_21_13.json new file mode 100644 index 0000000000..7d152dd0e2 --- /dev/null +++ b/research/char2-jets/data/nojoint_21_13.json @@ -0,0 +1 @@ +[[[1, -2, 2], [12, -4, -20], [-60, 36, 132], [40, -52, -144], [-2, 1, 2], [-3, 3, 3], [2, -3, -4]], [[4, -8, 4], [-6, -6, -3], [2, 1, 1], [1, 2, -1], [-12, -9, -3], [-40, -208, 64], [48, 44, 20]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_14.json b/research/char2-jets/data/nojoint_21_14.json new file mode 100644 index 0000000000..c8a6e78ee3 --- /dev/null +++ b/research/char2-jets/data/nojoint_21_14.json @@ -0,0 +1 @@ +[[[0, -12, -12], [1, 1, -2], [-1, 1, -2], [0, 0, 1], [18, 0, 0], [-12, -4, -12], [4, 8, -2], [1, 0, 2]], [[8, -12, -4], [-2, 0, 2], [2, -2, -4], [4, 6, -6], [2, -1, 2], [1, 1, 0], [0, 6, -6], [-1, 0, -2]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_2.json b/research/char2-jets/data/nojoint_21_2.json new file mode 100644 index 0000000000..68b8427982 --- /dev/null +++ b/research/char2-jets/data/nojoint_21_2.json @@ -0,0 +1 @@ +[[[-2, 1, -1], [2, 0, 1], [1, -1, 2], [-2, -4, -1], [-2, -1, 2], [0, 2, 2], [2, 2, 2], [0, 2, -1], [-8, -6, -4]], [[3, -9, -6], [4, 8, 4], [-2, 4, -2], [2, 1, 2], [-1, 0, 2], [-1, 0, 2], [-2, -4, 4], [-6, -2, 2], [1, -1, 2]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_3.json b/research/char2-jets/data/nojoint_21_3.json new file mode 100644 index 0000000000..b176c2557b --- /dev/null +++ b/research/char2-jets/data/nojoint_21_3.json @@ -0,0 +1 @@ +[[[1, 0, 1], [2, 2, 2], [2, 1, -2], [-2, 8, 2], [-8, -2, -6], [-16, -16, 24], [-28, -8, -20], [8, -4, 0]], [[-2, 0, -2], [-1, -2, -2], [-1, 1, 1], [6, -8, 2], [-12, -8, 20], [4, 8, -8], [-8, 8, 0], [2, 1, -2]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_4.json b/research/char2-jets/data/nojoint_21_4.json new file mode 100644 index 0000000000..fbd7a7ded2 --- /dev/null +++ b/research/char2-jets/data/nojoint_21_4.json @@ -0,0 +1 @@ +[[[-2, 0, -2], [-1, -1, 2], [-10, 20, 10], [1, 1, -1], [2, -4, -1], [3, -1, 1], [-4, -2, 2]], [[1, 1, -2], [-2, 1, -1], [-10, 0, -20], [-16, -16, 16], [1, -1, 0], [0, -2, 4], [2, -1, -2]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_5.json b/research/char2-jets/data/nojoint_21_5.json new file mode 100644 index 0000000000..1117ca7270 --- /dev/null +++ b/research/char2-jets/data/nojoint_21_5.json @@ -0,0 +1 @@ +[[[-1, 2, 2], [6, 36, 6], [-2, 0, 1], [-1, -1, 0], [-6, 3, 6], [2, -3, -4], [0, 14, -7], [-1, 0, 2], [-2, 0, 4]], [[8, -2, 4], [-3, 6, -6], [-2, 0, -1], [-144, 36, -72], [-2, -2, 2], [-6, 1, -4], [-198, 72, -234], [2, 1, 2], [11, 2, 4]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_6.json b/research/char2-jets/data/nojoint_21_6.json new file mode 100644 index 0000000000..e0dda71fe4 --- /dev/null +++ b/research/char2-jets/data/nojoint_21_6.json @@ -0,0 +1 @@ +[[[288, -288, 288], [-2, 1, 1], [-18, -2, 2], [72, 96, 48], [16, -12, -4], [-2, -2, -1], [8, -15, -11], [2, 2, 1]], [[0, 24, -48], [-288, 48, 336], [-9, 18, -18], [1, 2, -2], [0, -1, -1], [-4, -4, -4], [-2, 2, 0], [-2, 7, -11]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_7.json b/research/char2-jets/data/nojoint_21_7.json new file mode 100644 index 0000000000..e0caf1819a --- /dev/null +++ b/research/char2-jets/data/nojoint_21_7.json @@ -0,0 +1 @@ +[[[1, -2, 0], [-2, -9, -7], [-2, 1, -1], [2, -1, 2], [2, 0, -2], [0, -6, -6], [1, 1, -2], [0, 6, 12]], [[1, 2, 0], [4, 2, 4], [-1, 1, -1], [2, -1, 1], [4, 4, -2], [-1, 2, -1], [4, 2, -2], [-4, -3, 5]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_8.json b/research/char2-jets/data/nojoint_21_8.json new file mode 100644 index 0000000000..f2b1cf2b19 --- /dev/null +++ b/research/char2-jets/data/nojoint_21_8.json @@ -0,0 +1 @@ +[[[1, 0, 1], [1, -2, 1], [12, 8, -4], [1, -1, 2], [2, 0, -2], [-4, 0, 0], [-2, 2, 2], [-1, -1, -1], [1, -2, -1]], [[-1, 2, -1], [-2, -4, 2], [0, 4, -4], [4, 0, 4], [0, -2, -4], [-16, 0, -16], [-2, 0, 2], [3, 1, -1], [0, 2, -1]]] \ No newline at end of file diff --git a/research/char2-jets/data/nojoint_21_9.json b/research/char2-jets/data/nojoint_21_9.json new file mode 100644 index 0000000000..f8691b0ad2 --- /dev/null +++ b/research/char2-jets/data/nojoint_21_9.json @@ -0,0 +1 @@ +[[[-28, -28, 112], [2, 0, 2], [4, 4, 4], [-4, -8, 24], [0, 0, -2], [-1, -2, 8], [4, 4, -2], [2, 2, -1], [-4, 6, -4]], [[2, 0, -2], [28, 28, 14], [-2, -2, 1], [0, -4, -1], [2, 1, 2], [2, -2, 0], [1, -1, -2], [4, -14, -4], [2, -1, 0]]] \ No newline at end of file diff --git a/research/char2-jets/data/supmin_fail_v8.json b/research/char2-jets/data/supmin_fail_v8.json new file mode 100644 index 0000000000..384dc6d2c8 --- /dev/null +++ b/research/char2-jets/data/supmin_fail_v8.json @@ -0,0 +1 @@ +[[[2, -1, 0], [1, -1, 2], [-2, -1, -1], [2, 0, -2], [4, 4, 4], [0, -2, 0], [2, -3, -2], [-2, 0, 2]], [[1, 0, 1], [-2, 2, -2], [-2, 0, 2], [1, 2, -4], [2, 4, 1], [2, 1, 0], [2, -2, -2], [0, 0, -2]]] diff --git a/research/char2-jets/data/tied_min.json b/research/char2-jets/data/tied_min.json new file mode 100644 index 0000000000..ae11f01fab --- /dev/null +++ b/research/char2-jets/data/tied_min.json @@ -0,0 +1 @@ +[[[1, -1, -1], [0, 1, 1]], [[1, -1, -1], [1, -1, 0]], [[1, -1, -1], [1, 0, -1]], [[1, -1, 1], [0, 1, -1]], [[1, -1, 1], [1, -1, 0]], [[1, -1, 1], [1, 0, 1]], [[1, 1, -1], [0, 1, -1]], [[1, 1, -1], [1, 0, -1]], [[1, 1, -1], [1, 1, 0]], [[1, 1, 1], [0, 1, 1]], [[1, 1, 1], [1, 0, 1]], [[1, 1, 1], [1, 1, 0]]] \ No newline at end of file diff --git a/research/char2-jets/data/tied_min_B.json b/research/char2-jets/data/tied_min_B.json new file mode 100644 index 0000000000..2e5b7c48ed --- /dev/null +++ b/research/char2-jets/data/tied_min_B.json @@ -0,0 +1 @@ +{"config": "tied_min.json", "f": 72, "optima": [463044722869916013834, 666678162966765177345, 592675436169256831493, 110969962557597820929, 110970525508088113153, 703571651109893450245, 627478233671914496513, 627263185758919338500, 627263186858430966277, 110970525508092307461, 701265209966891115013, 703643568037305854465, 113347757678600202241, 113059527302452422661, 76166039155033311237, 666461989153863174660, 703355477296987253252, 701049037257791578629, 113276403701673895937, 113276403701678090245, 110969962561892853761, 111042582071338084356, 113348460264923867140, 627551416135071312388, 627550290235164467716, 627479359571821341185, 76454268431673657348, 627550291334671901185, 627550291338966934017, 76382352608063719429, 113275840751187798021, 629785237765411318277, 110754351695186110468, 701337829479553444356, 666461849513738963461, 701049600202913098245, 701049600207208131077, 76382211868423686145, 76382352608059525121, 76454269531181090817, 592963666545404611073, 76454410270816929793, 703643566937798420996, 113347756579092768772, 629857294328657095172, 629569063952505121284, 113275700015846991877, 703643003988381868548, 110754352794697738245, 592674309169838359044, 629784111865500279297, 113060090252942714885, 113276262966337284101, 592674449909474198020, 701337830579060877825, 701337830583355910657, 111042020224650258433, 703355478396498881029, 703571651109889255937, 629785097030070512133, 629785097030066317825, 592891608882647206401, 629567798416769098245, 629568924316675942917, 111042020220355225601, 592962540645497766401, 113060229888771893252, 627262060958524121605, 110753789844207446021, 627479359576120568325, 627551416139366345220, 627262060962819154437, 629567797317257470468, 629783971130163667461, 629856027693409444356, 627263186862725999109, 701265209971181953537, 701337267633939358209, 703354914347570700804, 629567938052598276612, 629785237765407123969, 627551417238873778689, 666461990253374802437, 113276262966333089793, 76382774818913978369, 666750079889886743041, 701265772916303473153, 592674451008985825797, 113347897314433574916, 592963806185533016580, 666677459277716980229, 666678022227133532677, 703354915447082328581, 629567939152109904389, 76382774818918172677, 76382211868427880453, 110970525512383145985, 110754351699481143300, 76382915558549817345, 113059668037793228805, 701265209966886920705, 701337267629644325377, 113275700015842797569, 110970525512387340293, 701337829483848477188, 629569065052016749061, 592963807285040450049, 76166179894669150213, 627478233676209529345, 629856169528257683969, 629856168428750250500, 703643144723722674692, 113348319529583060996, 666461285464810783236, 666677600017348624897, 113059666938281601028, 110969962561897048069, 701049599107696503300, 627263185763214371332, 627479359576116374017, 592675576908892670469, 111042019120847792132, 592890623722376200705, 592891749622283045377, 703355336561646447108, 113059526202940794884, 76166038055521683460, 76166601006011975684, 113060089153431087108, 703643707673139227140, 111042582075633117188, 76454972121799788548, 592675435069745203716, 592675575809381042692, 111042019125142824964, 111042583170845517825, 113348461364431300609, 703643145823230108161, 666749657680106029569, 666678022227129338369, 666677459277712785921, 113347898413941008385, 703643708772646660609, 629857154692823722497, 629568923217164315140, 701337266530136891908, 666678162966769371653, 666461848414227335684, 76166741745647814660, 666461426204446622212, 76166178795157522436, 76454832481671383041, 76382915558554011653, 703354774711741522437, 703355337661158074885, 666750219530015148548, 666750220629522582017, 703643005087889302017, 703571088160476897797, 629784111865504473605, 592890482982744556037, 592891608882651400709, 592891749622287239685, 592890623722380395013, 627479359571825535493, 110753788744695818244, 666749516940470190593, 110753788748990851076, 701337266534431924740, 666749656580598596100, 701049036158279950852, 110969962557602015237, 701265209971186147845, 627478233676213723653, 592890482982740361729, 592962680285626171908, 666677600017352819205, 629857153593316289028, 111042583175140550657, 76166742845159442437, 666461427303958249989, 703571088160472703489, 627551417234578745857, 110753789848502478853, 76454409171309496324, 627550290239459500548, 627262059863307526660, 627262059859012493828, 76454831382163949572, 592963665445897177604, 592962539545990332932, 592962681385133605377, 666461286564322411013, 666749515840962757124, 701265772920598505985, 592674310269349986821, 703571510374548449793, 627478233671918690821, 113060230988283521029, 629857295428164528641, 701265772916307667461, 113348320629090494465, 666750078790379309572, 629783971130159473153, 113275840751183603713, 701049036153984918020, 701049037253496545797, 629856028792916877825, 76454973221307222017, 703570947425136091653, 703571510374552644101, 76166602105523603461, 110754352798992771077, 703354773612229894660, 701049599103401470468, 701265772920602700293, 703570947425131897345], "full": 4722366482869645213695, "random": [3797214928400492746826, 1200202480225027013572, 3587807514568258743177, 3070870903300732082339, 992226813777225348758, 138126575408620449420, 1841644808302563978470, 3608320347623064720006, 3283559294880903885145, 3399113841165950313773, 2789678273274862403125, 4244636895189548221090, 92798006075341345171, 2557632693548276227769, 4167841660759336239423, 1027234316102042819023, 3420434330069907999810, 1042750712990154045319, 4435296177937618954383, 1098556359474483662100, 3195545460800344806016, 2172306064841361197225, 4377223872670482189047, 3955280396591885736309, 4363696371781388511472, 868841650982912616275, 3430956847914691675546, 558869759988731311293, 4230441535792975109130, 3375260756685454783400, 4573620066040660912310, 3920075473790637651033, 897808670793647907676, 2772253426172134264605, 2359015361592610266216, 2396986775621838333151, 4032255381972312052412, 1152556756725585588055, 1914724151720715559372, 823919092903414102901, 4160640966828624696273, 3187151659263000738471, 412740420400160944208, 2410320899892903397910, 770676238707918463509, 1860168778549535979588, 3458574392851347182296, 211571613370879719814, 4015918573374473488598, 2796799611025602261179, 3050973404770605422093, 2364293257284999184718, 73456348729819304135, 2549331109543172702525, 2598413715646081321166, 2423984349045767267591, 4002066642029219477794, 2164785814739557702734, 3104020333948419028065, 4530685347328059604072, 1807886234028084951167, 3889624176627285860635, 4443565705595040543543, 3827929978382499029431, 3680469996222025203087, 2014485638006636357164, 2269984813221838638423, 2681506083181304544332, 4430904964237547617430, 2295022149987617561683, 1961936484936661323263, 2527233171536897150984, 3719296909116919029438, 2164377464504926711630, 3782098582382905924612, 841824011321338193196, 859331627545519873233, 3764825538703494157227, 4017647318680185355987, 1216211361713126246933, 4461192773130785865174, 388681262751682734849, 2121683456294727081397, 3574133131191831376859, 1258982152156282126698, 2947739670188824949326, 1371412541881180134629, 740959044937993405064, 4492287261049590503407, 1284938515597304237074, 1396632322891590966883, 1525594167769897063290, 543695110819200775518, 1813536394314760645219, 3752453626027772824268, 502829112954875762700, 3447693119238225175050, 995695076981148677610, 2040314093608658480056, 110229504858350256868, 1863450693724930186389, 3394852560121802687572, 2105884501792085741960, 3200626483013716347084, 3939204469051354639171, 4611261303410380061083, 3279790713690874594112, 1059781035117263183271, 141090040537616876268, 2724121133978807175485, 3104978943611610246211, 284564996694024244366, 595804117966376245992, 4135983811579190215412, 337693228976050604547, 1458702964558049810864, 1419279363012769353998, 1958273283058744193001, 613397739847683142807, 4142414081321803170592, 2786157791666050440599, 4541912875351207649158, 2168788876414328483369, 4110449486412634426182, 3688865053165845799014, 2409568365175027457103, 947756242155498411022, 961057387394410509940, 4236740320969253008765, 914800035862431519167, 4429144864490233967341, 1390701152542574522699, 83006657552496537136, 4124915703557835577928, 1344761708148971978886, 943679446467769122276, 3824521772141130516269, 3699740613360068020826, 2016950314659881729457, 3177756691860248141547, 1804787032444011151678, 1633415404766508603013, 3963880513339704019754, 2297252914688652899318, 2526936612181588341446, 3413852645959578772809, 628751373151166246709, 4301163721369653941059, 1258307166813817408589, 2828480469266674839605, 1214554515104549955661, 1611117442869868909420, 1112176618371042338184, 2858212219686088554919, 3393358030824000187461, 636205934679704194644, 3644175883226693767384, 190383790387153191983, 1790684355411639197190, 3726080587182397797775, 605579048025811537946, 2898254464822572027493, 4386301921012681301397, 2694638607884769244308, 2660457942866041163381, 1271944439518624292937, 1399937577241446812811, 4363287589501452392041, 4232748745221858382335, 3709782839205417022247, 1398775432903086465704, 3165713577722879111976, 1938599382871709412753, 4184203384539858819964, 886182019457560704360, 4663069647761957231787, 764082836991418830550, 783081047012710627483, 742323181237352451915, 495203193417052402760, 4554699680171631502906, 4589669596305382885222, 3872141710374725298547, 1190741186866474983715, 1484538809069117121166, 3065989329936879587420, 111411328510006014598, 4644647766621579937784, 3418099586182623288523, 2127283161747015916191, 1887346907435686835580, 4299275502150708262379, 2840241740620754702758, 524917929762114278752, 3693318429856766369280, 4626036102673965029217, 4105192165116473658527, 3126149797583103276292, 853329520480642103864, 1442679951982166700597, 1701645385661478326333, 1324844736033330599246, 3559914960683972944768, 3063828733295657072804, 1598289844402058232455, 1830422936817138661980, 190126612130039003370, 1497632358843208308715, 2745745001118402902192, 1437395228415120666242, 467335964728100906804, 2741396310012460161871, 435268682216363573690, 96294871239439072830, 1886064460937678182667, 2605935819071418535585, 3432402573760549889863, 2988769404630341498050, 3547139572872472292102, 2330915664677682585288, 4055750016983533717488, 2363045153579852124284, 1545744615222586006289, 4491953183777984694414, 833299236238402627618, 4651338455786540343750, 4091885365538340984968, 503699837026888932700, 3938644722736728261074, 1394608765281926576633, 975717631699939831647, 4308153938187469008591, 3671487938179375181643, 4276343208342834503801, 3187668511701459763408, 3976250131010280962737, 4662344188167612501343, 833893074647533571930, 2535184700609269231714, 3358203173142165974825, 1174463220186684228856, 309495349883490107581, 2120700157178282804579, 2590479432245404345597, 2076021991292625905645, 2149747765968230043874, 3954902801071678694939, 1220649050280694056308, 3745139304355453487165, 1972559032836798874654, 84312755571639948622, 1672966642540089724773, 2788009246805135950147, 1220039905363221836951, 1306563225540124482836, 1891973186219710745454, 417125984445381450777, 27411800865532057963, 1503939095670484746845, 3078633110532947375366, 4398410610152948476371, 3461330655979967042320, 1480136762588459006641, 2263174756059381042693, 3361459084124938553765, 2644100060534194894440, 3447824478606897006986, 1303325330118651335067, 1044941923412188343604, 349041977386199329069, 3053151818123871040439, 744670895320938241370, 3740373022754549157242, 1461053044222983989834, 1414727970764789172139, 1762629152818683411307, 3314903570960160990960, 2812478746651668112862, 587644591561953562069, 4530632964946342173985, 1781424814467803401989, 1183465240141712354010, 4449679677940486352204, 3573495840244572611462, 2325251441513954722202, 3383014937649899092497, 1814200045126305228873, 790359327641091879525, 4698937202106390687981, 4639802065491933782636, 1213942296166447485535, 1256242574806657138757, 404220973733380487291, 663618313930609117319, 2910449014994624273536, 3116887337865591703500, 381855124366096264815, 4369129234409253199482, 4020859080662863415848, 3798922421068013627405]} \ No newline at end of file diff --git a/research/char2-jets/data/tm_noncr2.json b/research/char2-jets/data/tm_noncr2.json new file mode 100644 index 0000000000..a2a029123a --- /dev/null +++ b/research/char2-jets/data/tm_noncr2.json @@ -0,0 +1 @@ +[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11], [0, 1, 2, 3, 4, 5, 6, 7, 8, 10], [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11], [0, 1, 2, 3, 4, 5, 6, 7, 8, 11], [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11], [0, 1, 2, 3, 4, 5, 6, 7, 9, 11], [0, 1, 2, 3, 4, 5, 6, 7, 10, 11], [0, 1, 2, 3, 4, 5, 6, 7, 11], [0, 1, 2, 3, 4, 5, 6, 8, 9], [0, 1, 2, 3, 4, 5, 6, 8, 9, 10], [0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11], [0, 1, 2, 3, 4, 5, 6, 8, 9, 11], [0, 1, 2, 3, 4, 5, 6, 8, 10], [0, 1, 2, 3, 4, 5, 6, 8, 10, 11], [0, 1, 2, 3, 4, 5, 6, 8, 11], [0, 1, 2, 3, 4, 5, 6, 9, 10, 11], [0, 1, 2, 3, 4, 5, 6, 9, 11], [0, 1, 2, 3, 4, 5, 6, 10, 11], [0, 1, 2, 3, 4, 5, 6, 11], [0, 1, 2, 3, 4, 5, 7, 8, 9], [0, 1, 2, 3, 4, 5, 7, 8, 9, 10], [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11], [0, 1, 2, 3, 4, 5, 7, 8, 9, 11], [0, 1, 2, 3, 4, 5, 7, 8, 10], [0, 1, 2, 3, 4, 5, 7, 8, 10, 11], [0, 1, 2, 3, 4, 5, 7, 8, 11], [0, 1, 2, 3, 4, 5, 7, 9, 10, 11], [0, 1, 2, 3, 4, 5, 7, 9, 11], [0, 1, 2, 3, 4, 5, 7, 10, 11], [0, 1, 2, 3, 4, 5, 7, 11], [0, 1, 2, 3, 4, 5, 8, 9], [0, 1, 2, 3, 4, 5, 8, 9, 10], [0, 1, 2, 3, 4, 5, 8, 9, 10, 11], [0, 1, 2, 3, 4, 5, 8, 9, 11], [0, 1, 2, 3, 4, 5, 8, 10], [0, 1, 2, 3, 4, 5, 8, 10, 11], [0, 1, 2, 3, 4, 5, 8, 11], [0, 1, 2, 3, 4, 6, 7, 8, 9, 10], [0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11], [0, 1, 2, 3, 4, 6, 7, 8, 10], [0, 1, 2, 3, 4, 6, 7, 8, 10, 11], [0, 1, 2, 3, 4, 6, 7, 9, 10, 11], [0, 1, 2, 3, 4, 6, 7, 10, 11], [0, 1, 2, 3, 4, 6, 8, 9, 10], [0, 1, 2, 3, 4, 6, 8, 9, 10, 11], [0, 1, 2, 3, 4, 6, 8, 10], [0, 1, 2, 3, 4, 6, 8, 10, 11], [0, 1, 2, 3, 4, 6, 9, 10, 11], [0, 1, 2, 3, 4, 6, 10, 11], [0, 1, 2, 3, 4, 7, 8, 9, 10], [0, 1, 2, 3, 4, 7, 8, 9, 10, 11], [0, 1, 2, 3, 4, 7, 8, 10], [0, 1, 2, 3, 4, 7, 8, 10, 11], [0, 1, 2, 3, 4, 7, 9, 10, 11], [0, 1, 2, 3, 4, 7, 10, 11], [0, 1, 2, 3, 4, 8, 9, 10], [0, 1, 2, 3, 4, 8, 9, 10, 11], [0, 1, 2, 3, 4, 8, 10], [0, 1, 2, 3, 4, 8, 10, 11], [0, 1, 2, 3, 5, 6, 7, 8, 9], [0, 1, 2, 3, 5, 6, 7, 8, 9, 10], [0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11], [0, 1, 2, 3, 5, 6, 7, 8, 9, 11], [0, 1, 2, 3, 5, 6, 7, 8, 10], [0, 1, 2, 3, 5, 6, 7, 8, 10, 11], [0, 1, 2, 3, 5, 6, 7, 8, 11], [0, 1, 2, 3, 5, 6, 7, 9, 10, 11], [0, 1, 2, 3, 5, 6, 7, 9, 11], [0, 1, 2, 3, 5, 6, 7, 10, 11], [0, 1, 2, 3, 5, 6, 7, 11], [0, 1, 2, 3, 5, 6, 8, 9], [0, 1, 2, 3, 5, 6, 8, 9, 10], [0, 1, 2, 3, 5, 6, 8, 9, 10, 11], [0, 1, 2, 3, 5, 6, 8, 9, 11], [0, 1, 2, 3, 5, 6, 8, 10], [0, 1, 2, 3, 5, 6, 8, 10, 11], [0, 1, 2, 3, 5, 6, 8, 11], [0, 1, 2, 3, 5, 6, 9, 10, 11], [0, 1, 2, 3, 5, 6, 9, 11], [0, 1, 2, 3, 5, 6, 10, 11], [0, 1, 2, 3, 5, 6, 11], [0, 1, 2, 3, 5, 7, 8, 9], [0, 1, 2, 3, 5, 7, 8, 9, 10], [0, 1, 2, 3, 5, 7, 8, 9, 10, 11], [0, 1, 2, 3, 5, 7, 8, 9, 11], [0, 1, 2, 3, 5, 7, 8, 10], [0, 1, 2, 3, 5, 7, 8, 10, 11], [0, 1, 2, 3, 5, 7, 8, 11], [0, 1, 2, 3, 5, 7, 9, 10, 11], [0, 1, 2, 3, 5, 7, 9, 11], [0, 1, 2, 3, 5, 7, 10, 11], [0, 1, 2, 3, 5, 7, 11], [0, 1, 2, 3, 5, 8, 9], [0, 1, 2, 3, 5, 8, 9, 10], [0, 1, 2, 3, 5, 8, 9, 10, 11], [0, 1, 2, 3, 5, 8, 9, 11], [0, 1, 2, 3, 5, 8, 10], [0, 1, 2, 3, 5, 8, 10, 11], [0, 1, 2, 3, 5, 8, 11], [0, 1, 2, 3, 6, 7, 8, 9, 10], [0, 1, 2, 3, 6, 7, 8, 9, 10, 11], [0, 1, 2, 3, 6, 7, 8, 10], [0, 1, 2, 3, 6, 7, 8, 10, 11], [0, 1, 2, 3, 6, 7, 9, 10, 11], [0, 1, 2, 3, 6, 7, 10, 11], [0, 1, 2, 3, 6, 8, 9, 10], [0, 1, 2, 3, 6, 8, 9, 10, 11], [0, 1, 2, 3, 6, 8, 10], [0, 1, 2, 3, 6, 8, 10, 11], [0, 1, 2, 3, 6, 9, 10, 11], [0, 1, 2, 3, 6, 10, 11], [0, 1, 2, 3, 7, 8, 9, 10], [0, 1, 2, 3, 7, 8, 9, 10, 11], [0, 1, 2, 3, 7, 8, 10], [0, 1, 2, 3, 7, 8, 10, 11], [0, 1, 2, 3, 7, 9, 10, 11], [0, 1, 2, 3, 7, 10, 11], [0, 1, 2, 3, 8, 9, 10], [0, 1, 2, 3, 8, 9, 10, 11], [0, 1, 2, 3, 8, 10], [0, 1, 2, 3, 8, 10, 11], [0, 1, 2, 4, 5, 6, 7, 8, 9], [0, 1, 2, 4, 5, 6, 7, 8, 9, 10], [0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11], [0, 1, 2, 4, 5, 6, 7, 8, 9, 11], [0, 1, 2, 4, 5, 6, 7, 8, 10], [0, 1, 2, 4, 5, 6, 7, 8, 10, 11], [0, 1, 2, 4, 5, 6, 7, 8, 11], [0, 1, 2, 4, 5, 6, 7, 9, 10, 11], [0, 1, 2, 4, 5, 6, 7, 9, 11], [0, 1, 2, 4, 5, 6, 7, 10, 11], [0, 1, 2, 4, 5, 6, 7, 11], [0, 1, 2, 4, 5, 6, 8, 9], [0, 1, 2, 4, 5, 6, 8, 9, 10], [0, 1, 2, 4, 5, 6, 8, 9, 10, 11], [0, 1, 2, 4, 5, 6, 8, 9, 11], [0, 1, 2, 4, 5, 6, 8, 10], [0, 1, 2, 4, 5, 6, 8, 10, 11], [0, 1, 2, 4, 5, 6, 8, 11], [0, 1, 2, 4, 5, 6, 9, 10, 11], [0, 1, 2, 4, 5, 6, 9, 11], [0, 1, 2, 4, 5, 6, 10, 11], [0, 1, 2, 4, 5, 6, 11], [0, 1, 2, 4, 6, 7, 8, 9, 10], [0, 1, 2, 4, 6, 7, 8, 9, 10, 11], [0, 1, 2, 4, 6, 7, 8, 10], [0, 1, 2, 4, 6, 7, 8, 10, 11], [0, 1, 2, 4, 6, 7, 9, 10, 11], [0, 1, 2, 4, 6, 7, 10, 11], [0, 1, 2, 4, 6, 8, 9, 10], [0, 1, 2, 4, 6, 8, 9, 10, 11], [0, 1, 2, 4, 6, 8, 10], [0, 1, 2, 4, 6, 8, 10, 11], [0, 1, 2, 4, 6, 9, 10, 11], [0, 1, 2, 4, 6, 10, 11], [0, 1, 2, 5, 6, 7, 8, 9], [0, 1, 2, 5, 6, 7, 8, 9, 10], [0, 1, 2, 5, 6, 7, 8, 9, 10, 11], [0, 1, 2, 5, 6, 7, 8, 9, 11], [0, 1, 2, 5, 6, 7, 8, 10], [0, 1, 2, 5, 6, 7, 8, 10, 11], [0, 1, 2, 5, 6, 7, 8, 11], [0, 1, 2, 5, 6, 7, 9, 10, 11], [0, 1, 2, 5, 6, 7, 9, 11], [0, 1, 2, 5, 6, 7, 10, 11], [0, 1, 2, 5, 6, 7, 11], [0, 1, 2, 5, 6, 8, 9], [0, 1, 2, 5, 6, 8, 9, 10], [0, 1, 2, 5, 6, 8, 9, 10, 11], [0, 1, 2, 5, 6, 8, 9, 11], [0, 1, 2, 5, 6, 8, 10], [0, 1, 2, 5, 6, 8, 10, 11], [0, 1, 2, 5, 6, 8, 11], [0, 1, 2, 5, 6, 9, 10, 11], [0, 1, 2, 5, 6, 9, 11], [0, 1, 2, 5, 6, 10, 11], [0, 1, 2, 5, 6, 11], [0, 1, 3, 4, 5, 6, 7, 8, 9], [0, 1, 3, 4, 5, 6, 7, 8, 9, 10], [0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11], [0, 1, 3, 4, 5, 6, 7, 8, 9, 11], [0, 1, 3, 4, 5, 6, 7, 8, 10], [0, 1, 3, 4, 5, 6, 7, 8, 10, 11], [0, 1, 3, 4, 5, 6, 7, 8, 11], [0, 1, 3, 4, 5, 6, 7, 9, 10, 11], [0, 1, 3, 4, 5, 6, 7, 9, 11], [0, 1, 3, 4, 5, 6, 7, 10, 11], [0, 1, 3, 4, 5, 6, 7, 11], [0, 1, 3, 4, 5, 7, 8, 9], [0, 1, 3, 4, 5, 7, 8, 9, 10], [0, 1, 3, 4, 5, 7, 8, 9, 10, 11], [0, 1, 3, 4, 5, 7, 8, 9, 11], [0, 1, 3, 4, 5, 7, 8, 10], [0, 1, 3, 4, 5, 7, 8, 10, 11], [0, 1, 3, 4, 5, 7, 8, 11], [0, 1, 3, 4, 5, 7, 9, 10, 11], [0, 1, 3, 4, 5, 7, 9, 11], [0, 1, 3, 4, 5, 7, 10, 11], [0, 1, 3, 4, 5, 7, 11], [0, 1, 3, 4, 6, 7, 8, 9, 10], [0, 1, 3, 4, 6, 7, 8, 9, 10, 11], [0, 1, 3, 4, 6, 7, 8, 10], [0, 1, 3, 4, 6, 7, 8, 10, 11], [0, 1, 3, 4, 6, 7, 9, 10, 11], [0, 1, 3, 4, 6, 7, 10, 11], [0, 1, 3, 4, 7, 8, 9, 10], [0, 1, 3, 4, 7, 8, 9, 10, 11], [0, 1, 3, 4, 7, 8, 10], [0, 1, 3, 4, 7, 8, 10, 11], [0, 1, 3, 4, 7, 9, 10, 11], [0, 1, 3, 4, 7, 10, 11], [0, 1, 3, 5, 6, 7, 8, 9], [0, 1, 3, 5, 6, 7, 8, 9, 10], [0, 1, 3, 5, 6, 7, 8, 9, 10, 11], [0, 1, 3, 5, 6, 7, 8, 9, 11], [0, 1, 3, 5, 6, 7, 8, 10], [0, 1, 3, 5, 6, 7, 8, 10, 11], [0, 1, 3, 5, 6, 7, 8, 11], [0, 1, 3, 5, 6, 7, 9, 10, 11], [0, 1, 3, 5, 6, 7, 9, 11], [0, 1, 3, 5, 6, 7, 10, 11], [0, 1, 3, 5, 6, 7, 11], [0, 1, 3, 5, 7, 8, 9], [0, 1, 3, 5, 7, 8, 9, 10], [0, 1, 3, 5, 7, 8, 9, 10, 11], [0, 1, 3, 5, 7, 8, 9, 11], [0, 1, 3, 5, 7, 8, 10], [0, 1, 3, 5, 7, 8, 10, 11], [0, 1, 3, 5, 7, 8, 11], [0, 1, 3, 5, 7, 9, 10, 11], [0, 1, 3, 5, 7, 9, 11], [0, 1, 3, 5, 7, 10, 11], [0, 1, 3, 5, 7, 11], [0, 1, 3, 6, 7, 8, 9, 10], [0, 1, 3, 6, 7, 8, 9, 10, 11], [0, 1, 3, 6, 7, 8, 10], [0, 1, 3, 6, 7, 8, 10, 11], [0, 1, 3, 6, 7, 9, 10, 11], [0, 1, 3, 6, 7, 10, 11], [0, 1, 3, 7, 8, 9, 10], [0, 1, 3, 7, 8, 9, 10, 11], [0, 1, 3, 7, 8, 10], [0, 1, 3, 7, 8, 10, 11], [0, 1, 3, 7, 9, 10, 11], [0, 1, 3, 7, 10, 11], [0, 1, 4, 5, 6, 7, 8, 9], [0, 1, 4, 5, 6, 7, 8, 9, 10], [0, 1, 4, 5, 6, 7, 8, 9, 10, 11], [0, 1, 4, 5, 6, 7, 8, 9, 11], [0, 1, 4, 5, 6, 7, 8, 10], [0, 1, 4, 5, 6, 7, 8, 10, 11], [0, 1, 4, 5, 6, 7, 8, 11], [0, 1, 4, 5, 6, 7, 9, 10, 11], [0, 1, 4, 5, 6, 7, 9, 11], [0, 1, 4, 5, 6, 7, 10, 11], [0, 1, 4, 5, 6, 7, 11], [0, 1, 4, 6, 7, 8, 9, 10], [0, 1, 4, 6, 7, 8, 9, 10, 11], [0, 1, 4, 6, 7, 8, 10], [0, 1, 4, 6, 7, 8, 10, 11], [0, 1, 4, 6, 7, 9, 10, 11], [0, 1, 4, 6, 7, 10, 11], [0, 1, 5, 6, 7, 8, 9], [0, 1, 5, 6, 7, 8, 9, 10], [0, 1, 5, 6, 7, 8, 9, 10, 11], [0, 1, 5, 6, 7, 8, 9, 11], [0, 1, 5, 6, 7, 8, 10], [0, 1, 5, 6, 7, 8, 10, 11], [0, 1, 5, 6, 7, 8, 11], [0, 1, 5, 6, 7, 9, 10, 11], [0, 1, 5, 6, 7, 9, 11], [0, 1, 5, 6, 7, 10, 11], [0, 1, 5, 6, 7, 11], [0, 2, 3, 4, 5, 6, 7, 8, 9], [0, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [0, 2, 3, 4, 5, 6, 7, 8, 9, 11], [0, 2, 3, 4, 5, 6, 7, 8, 10], [0, 2, 3, 4, 5, 6, 7, 8, 10, 11], [0, 2, 3, 4, 5, 6, 7, 8, 11], [0, 2, 3, 4, 5, 6, 7, 9, 10, 11], [0, 2, 3, 4, 5, 6, 7, 9, 11], [0, 2, 3, 4, 5, 6, 7, 10, 11], [0, 2, 3, 4, 5, 6, 7, 11], [0, 2, 3, 4, 5, 6, 8, 9], [0, 2, 3, 4, 5, 6, 8, 9, 10], [0, 2, 3, 4, 5, 6, 8, 9, 10, 11], [0, 2, 3, 4, 5, 6, 8, 9, 11], [0, 2, 3, 4, 5, 6, 8, 10], [0, 2, 3, 4, 5, 6, 8, 10, 11], [0, 2, 3, 4, 5, 6, 8, 11], [0, 2, 3, 4, 5, 6, 9, 10, 11], [0, 2, 3, 4, 5, 6, 9, 11], [0, 2, 3, 4, 5, 6, 10, 11], [0, 2, 3, 4, 5, 6, 11], [0, 2, 3, 4, 5, 7, 8, 9], [0, 2, 3, 4, 5, 7, 8, 9, 10], [0, 2, 3, 4, 5, 7, 8, 9, 10, 11], [0, 2, 3, 4, 5, 7, 8, 9, 11], [0, 2, 3, 4, 5, 7, 8, 10], [0, 2, 3, 4, 5, 7, 8, 10, 11], [0, 2, 3, 4, 5, 7, 8, 11], [0, 2, 3, 4, 5, 7, 9, 10, 11], [0, 2, 3, 4, 5, 7, 9, 11], [0, 2, 3, 4, 5, 7, 10, 11], [0, 2, 3, 4, 5, 7, 11], [0, 2, 3, 4, 5, 8, 9], [0, 2, 3, 4, 5, 8, 9, 10], [0, 2, 3, 4, 5, 8, 9, 10, 11], [0, 2, 3, 4, 5, 8, 9, 11], [0, 2, 3, 4, 5, 8, 10], [0, 2, 3, 4, 5, 8, 10, 11], [0, 2, 3, 4, 5, 8, 11], [0, 2, 3, 4, 6, 7, 8, 9, 10], [0, 2, 3, 4, 6, 7, 8, 9, 10, 11], [0, 2, 3, 4, 6, 7, 8, 10], [0, 2, 3, 4, 6, 7, 8, 10, 11], [0, 2, 3, 4, 6, 7, 9, 10, 11], [0, 2, 3, 4, 6, 7, 10, 11], [0, 2, 3, 4, 6, 8, 9, 10], [0, 2, 3, 4, 6, 8, 9, 10, 11], [0, 2, 3, 4, 6, 8, 10], [0, 2, 3, 4, 6, 8, 10, 11], [0, 2, 3, 4, 6, 9, 10, 11], [0, 2, 3, 4, 6, 10, 11], [0, 2, 3, 4, 7, 8, 9, 10], [0, 2, 3, 4, 7, 8, 9, 10, 11], [0, 2, 3, 4, 7, 8, 10], [0, 2, 3, 4, 7, 8, 10, 11], [0, 2, 3, 4, 7, 9, 10, 11], [0, 2, 3, 4, 7, 10, 11], [0, 2, 3, 4, 8, 9, 10], [0, 2, 3, 4, 8, 9, 10, 11], [0, 2, 3, 4, 8, 10], [0, 2, 3, 4, 8, 10, 11], [0, 2, 4, 5, 6, 7, 8, 9], [0, 2, 4, 5, 6, 7, 8, 9, 10], [0, 2, 4, 5, 6, 7, 8, 9, 10, 11], [0, 2, 4, 5, 6, 7, 8, 9, 11], [0, 2, 4, 5, 6, 7, 8, 10], [0, 2, 4, 5, 6, 7, 8, 10, 11], [0, 2, 4, 5, 6, 7, 8, 11], [0, 2, 4, 5, 6, 7, 9, 10, 11], [0, 2, 4, 5, 6, 7, 9, 11], [0, 2, 4, 5, 6, 7, 10, 11], [0, 2, 4, 5, 6, 7, 11], [0, 2, 4, 5, 6, 8, 9], [0, 2, 4, 5, 6, 8, 9, 10], [0, 2, 4, 5, 6, 8, 9, 10, 11], [0, 2, 4, 5, 6, 8, 9, 11], [0, 2, 4, 5, 6, 8, 10], [0, 2, 4, 5, 6, 8, 10, 11], [0, 2, 4, 5, 6, 8, 11], [0, 2, 4, 5, 6, 9, 10, 11], [0, 2, 4, 5, 6, 9, 11], [0, 2, 4, 5, 6, 10, 11], [0, 2, 4, 5, 6, 11], [0, 2, 4, 6, 7, 8, 9, 10], [0, 2, 4, 6, 7, 8, 9, 10, 11], [0, 2, 4, 6, 7, 8, 10], [0, 2, 4, 6, 7, 8, 10, 11], [0, 2, 4, 6, 7, 9, 10, 11], [0, 2, 4, 6, 7, 10, 11], [0, 2, 4, 6, 8, 9, 10], [0, 2, 4, 6, 8, 9, 10, 11], [0, 2, 4, 6, 8, 10], [0, 2, 4, 6, 8, 10, 11], [0, 2, 4, 6, 9, 10, 11], [0, 2, 4, 6, 10, 11], [0, 3, 4, 5, 6, 7, 8, 9], [0, 3, 4, 5, 6, 7, 8, 9, 10], [0, 3, 4, 5, 6, 7, 8, 9, 10, 11], [0, 3, 4, 5, 6, 7, 8, 9, 11], [0, 3, 4, 5, 6, 7, 8, 10], [0, 3, 4, 5, 6, 7, 8, 10, 11], [0, 3, 4, 5, 6, 7, 8, 11], [0, 3, 4, 5, 6, 7, 9, 10, 11], [0, 3, 4, 5, 6, 7, 9, 11], [0, 3, 4, 5, 6, 7, 10, 11], [0, 3, 4, 5, 6, 7, 11], [0, 3, 4, 5, 7, 8, 9], [0, 3, 4, 5, 7, 8, 9, 10], [0, 3, 4, 5, 7, 8, 9, 10, 11], [0, 3, 4, 5, 7, 8, 9, 11], [0, 3, 4, 5, 7, 8, 10], [0, 3, 4, 5, 7, 8, 10, 11], [0, 3, 4, 5, 7, 8, 11], [0, 3, 4, 5, 7, 9, 10, 11], [0, 3, 4, 5, 7, 9, 11], [0, 3, 4, 5, 7, 10, 11], [0, 3, 4, 5, 7, 11], [0, 3, 4, 6, 7, 8, 9, 10], [0, 3, 4, 6, 7, 8, 9, 10, 11], [0, 3, 4, 6, 7, 8, 10], [0, 3, 4, 6, 7, 8, 10, 11], [0, 3, 4, 6, 7, 9, 10, 11], [0, 3, 4, 6, 7, 10, 11], [0, 3, 4, 7, 8, 9, 10], [0, 3, 4, 7, 8, 9, 10, 11], [0, 3, 4, 7, 8, 10], [0, 3, 4, 7, 8, 10, 11], [0, 3, 4, 7, 9, 10, 11], [0, 3, 4, 7, 10, 11], [0, 4, 5, 6, 7, 8, 9], [0, 4, 5, 6, 7, 8, 9, 10], [0, 4, 5, 6, 7, 8, 9, 10, 11], [0, 4, 5, 6, 7, 8, 9, 11], [0, 4, 5, 6, 7, 8, 10], [0, 4, 5, 6, 7, 8, 10, 11], [0, 4, 5, 6, 7, 8, 11], [0, 4, 5, 6, 7, 9, 10, 11], [0, 4, 5, 6, 7, 9, 11], [0, 4, 5, 6, 7, 10, 11], [0, 4, 5, 6, 7, 11], [0, 4, 6, 7, 8, 9, 10], [0, 4, 6, 7, 8, 9, 10, 11], [0, 4, 6, 7, 8, 10], [0, 4, 6, 7, 8, 10, 11], [0, 4, 6, 7, 9, 10, 11], [0, 4, 6, 7, 10, 11], [1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [1, 2, 3, 4, 5, 6, 7, 8, 9, 11], [1, 2, 3, 4, 5, 6, 7, 9, 10, 11], [1, 2, 3, 4, 5, 6, 7, 9, 11], [1, 2, 3, 4, 5, 6, 8, 9], [1, 2, 3, 4, 5, 6, 8, 9, 10], [1, 2, 3, 4, 5, 6, 8, 9, 10, 11], [1, 2, 3, 4, 5, 6, 8, 9, 11], [1, 2, 3, 4, 5, 6, 9, 10, 11], [1, 2, 3, 4, 5, 6, 9, 11], [1, 2, 3, 4, 5, 7, 8, 9], [1, 2, 3, 4, 5, 7, 8, 9, 10], [1, 2, 3, 4, 5, 7, 8, 9, 10, 11], [1, 2, 3, 4, 5, 7, 8, 9, 11], [1, 2, 3, 4, 5, 7, 9, 10, 11], [1, 2, 3, 4, 5, 7, 9, 11], [1, 2, 3, 4, 5, 8, 9], [1, 2, 3, 4, 5, 8, 9, 10], [1, 2, 3, 4, 5, 8, 9, 10, 11], [1, 2, 3, 4, 5, 8, 9, 11], [1, 2, 3, 4, 6, 7, 8, 9, 10], [1, 2, 3, 4, 6, 7, 8, 9, 10, 11], [1, 2, 3, 4, 6, 7, 9, 10, 11], [1, 2, 3, 4, 6, 8, 9, 10], [1, 2, 3, 4, 6, 8, 9, 10, 11], [1, 2, 3, 4, 6, 9, 10, 11], [1, 2, 3, 4, 7, 8, 9, 10], [1, 2, 3, 4, 7, 8, 9, 10, 11], [1, 2, 3, 4, 7, 9, 10, 11], [1, 2, 3, 4, 8, 9, 10], [1, 2, 3, 4, 8, 9, 10, 11], [1, 2, 3, 5, 6, 7, 8, 9], [1, 2, 3, 5, 6, 7, 8, 9, 10], [1, 2, 3, 5, 6, 7, 8, 9, 10, 11], [1, 2, 3, 5, 6, 7, 8, 9, 11], [1, 2, 3, 5, 6, 7, 9, 10, 11], [1, 2, 3, 5, 6, 7, 9, 11], [1, 2, 3, 5, 6, 8, 9], [1, 2, 3, 5, 6, 8, 9, 10], [1, 2, 3, 5, 6, 8, 9, 10, 11], [1, 2, 3, 5, 6, 8, 9, 11], [1, 2, 3, 5, 6, 9, 10, 11], [1, 2, 3, 5, 6, 9, 11], [1, 2, 3, 5, 7, 8, 9], [1, 2, 3, 5, 7, 8, 9, 10], [1, 2, 3, 5, 7, 8, 9, 10, 11], [1, 2, 3, 5, 7, 8, 9, 11], [1, 2, 3, 5, 7, 9, 10, 11], [1, 2, 3, 5, 7, 9, 11], [1, 2, 3, 5, 8, 9], [1, 2, 3, 5, 8, 9, 10], [1, 2, 3, 5, 8, 9, 10, 11], [1, 2, 3, 5, 8, 9, 11], [1, 2, 3, 6, 7, 8, 9, 10], [1, 2, 3, 6, 7, 8, 9, 10, 11], [1, 2, 3, 6, 7, 9, 10, 11], [1, 2, 3, 6, 8, 9, 10], [1, 2, 3, 6, 8, 9, 10, 11], [1, 2, 3, 6, 9, 10, 11], [1, 2, 3, 7, 8, 9, 10], [1, 2, 3, 7, 8, 9, 10, 11], [1, 2, 3, 7, 9, 10, 11], [1, 2, 3, 8, 9, 10], [1, 2, 3, 8, 9, 10, 11], [1, 2, 4, 5, 6, 7, 8, 9], [1, 2, 4, 5, 6, 7, 8, 9, 10], [1, 2, 4, 5, 6, 7, 8, 9, 10, 11], [1, 2, 4, 5, 6, 7, 8, 9, 11], [1, 2, 4, 5, 6, 7, 9, 10, 11], [1, 2, 4, 5, 6, 7, 9, 11], [1, 2, 4, 5, 6, 8, 9], [1, 2, 4, 5, 6, 8, 9, 10], [1, 2, 4, 5, 6, 8, 9, 10, 11], [1, 2, 4, 5, 6, 8, 9, 11], [1, 2, 4, 5, 6, 9, 10, 11], [1, 2, 4, 5, 6, 9, 11], [1, 2, 4, 6, 7, 8, 9, 10], [1, 2, 4, 6, 7, 8, 9, 10, 11], [1, 2, 4, 6, 7, 9, 10, 11], [1, 2, 4, 6, 8, 9, 10], [1, 2, 4, 6, 8, 9, 10, 11], [1, 2, 4, 6, 9, 10, 11], [1, 2, 5, 6, 7, 8, 9], [1, 2, 5, 6, 7, 8, 9, 10], [1, 2, 5, 6, 7, 8, 9, 10, 11], [1, 2, 5, 6, 7, 8, 9, 11], [1, 2, 5, 6, 7, 9, 10, 11], [1, 2, 5, 6, 7, 9, 11], [1, 2, 5, 6, 8, 9], [1, 2, 5, 6, 8, 9, 10], [1, 2, 5, 6, 8, 9, 10, 11], [1, 2, 5, 6, 8, 9, 11], [1, 2, 5, 6, 9, 10, 11], [1, 2, 5, 6, 9, 11], [1, 3, 4, 5, 6, 7, 8, 9], [1, 3, 4, 5, 6, 7, 8, 9, 10], [1, 3, 4, 5, 6, 7, 8, 9, 10, 11], [1, 3, 4, 5, 6, 7, 8, 9, 11], [1, 3, 4, 5, 6, 7, 9, 10, 11], [1, 3, 4, 5, 6, 7, 9, 11], [1, 3, 4, 5, 7, 8, 9], [1, 3, 4, 5, 7, 8, 9, 10], [1, 3, 4, 5, 7, 8, 9, 10, 11], [1, 3, 4, 5, 7, 8, 9, 11], [1, 3, 4, 5, 7, 9, 10, 11], [1, 3, 4, 5, 7, 9, 11], [1, 3, 4, 6, 7, 8, 9, 10], [1, 3, 4, 6, 7, 8, 9, 10, 11], [1, 3, 4, 6, 7, 9, 10, 11], [1, 3, 4, 7, 8, 9, 10], [1, 3, 4, 7, 8, 9, 10, 11], [1, 3, 4, 7, 9, 10, 11], [1, 3, 5, 6, 7, 8, 9], [1, 3, 5, 6, 7, 8, 9, 10], [1, 3, 5, 6, 7, 8, 9, 10, 11], [1, 3, 5, 6, 7, 8, 9, 11], [1, 3, 5, 6, 7, 9, 10, 11], [1, 3, 5, 6, 7, 9, 11], [1, 3, 5, 7, 8, 9], [1, 3, 5, 7, 8, 9, 10], [1, 3, 5, 7, 8, 9, 10, 11], [1, 3, 5, 7, 8, 9, 11], [1, 3, 5, 7, 9, 10, 11], [1, 3, 5, 7, 9, 11], [1, 3, 6, 7, 8, 9, 10], [1, 3, 6, 7, 8, 9, 10, 11], [1, 3, 6, 7, 9, 10, 11], [1, 3, 7, 8, 9, 10], [1, 3, 7, 8, 9, 10, 11], [1, 3, 7, 9, 10, 11], [1, 4, 5, 6, 7, 8, 9], [1, 4, 5, 6, 7, 8, 9, 10], [1, 4, 5, 6, 7, 8, 9, 10, 11], [1, 4, 5, 6, 7, 8, 9, 11], [1, 4, 5, 6, 7, 9, 10, 11], [1, 4, 5, 6, 7, 9, 11], [1, 4, 6, 7, 8, 9, 10], [1, 4, 6, 7, 8, 9, 10, 11], [1, 4, 6, 7, 9, 10, 11], [1, 5, 6, 7, 8, 9], [1, 5, 6, 7, 8, 9, 10], [1, 5, 6, 7, 8, 9, 10, 11], [1, 5, 6, 7, 8, 9, 11], [1, 5, 6, 7, 9, 10, 11], [1, 5, 6, 7, 9, 11], [2, 3, 4, 5, 6, 7, 8, 9], [2, 3, 4, 5, 6, 7, 8, 9, 10], [2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [2, 3, 4, 5, 6, 7, 8, 9, 11], [2, 3, 4, 5, 6, 7, 9, 10, 11], [2, 3, 4, 5, 6, 7, 9, 11], [2, 3, 4, 5, 6, 8, 9], [2, 3, 4, 5, 6, 8, 9, 10], [2, 3, 4, 5, 6, 8, 9, 10, 11], [2, 3, 4, 5, 6, 8, 9, 11], [2, 3, 4, 5, 6, 9, 10, 11], [2, 3, 4, 5, 6, 9, 11], [2, 3, 4, 5, 7, 8, 9], [2, 3, 4, 5, 7, 8, 9, 10], [2, 3, 4, 5, 7, 8, 9, 10, 11], [2, 3, 4, 5, 7, 8, 9, 11], [2, 3, 4, 5, 7, 9, 10, 11], [2, 3, 4, 5, 7, 9, 11], [2, 3, 4, 5, 8, 9], [2, 3, 4, 5, 8, 9, 10], [2, 3, 4, 5, 8, 9, 10, 11], [2, 3, 4, 5, 8, 9, 11], [2, 3, 4, 6, 7, 8, 9, 10], [2, 3, 4, 6, 7, 8, 9, 10, 11], [2, 3, 4, 6, 7, 9, 10, 11], [2, 3, 4, 6, 8, 9, 10], [2, 3, 4, 6, 8, 9, 10, 11], [2, 3, 4, 6, 9, 10, 11], [2, 3, 4, 7, 8, 9, 10], [2, 3, 4, 7, 8, 9, 10, 11], [2, 3, 4, 7, 9, 10, 11], [2, 3, 4, 8, 9, 10], [2, 3, 4, 8, 9, 10, 11], [2, 4, 5, 6, 7, 8, 9], [2, 4, 5, 6, 7, 8, 9, 10], [2, 4, 5, 6, 7, 8, 9, 10, 11], [2, 4, 5, 6, 7, 8, 9, 11], [2, 4, 5, 6, 7, 9, 10, 11], [2, 4, 5, 6, 7, 9, 11], [2, 4, 5, 6, 8, 9], [2, 4, 5, 6, 8, 9, 10], [2, 4, 5, 6, 8, 9, 10, 11], [2, 4, 5, 6, 8, 9, 11], [2, 4, 5, 6, 9, 10, 11], [2, 4, 5, 6, 9, 11], [2, 4, 6, 7, 8, 9, 10], [2, 4, 6, 7, 8, 9, 10, 11], [2, 4, 6, 7, 9, 10, 11], [2, 4, 6, 8, 9, 10], [2, 4, 6, 8, 9, 10, 11], [2, 4, 6, 9, 10, 11]] \ No newline at end of file diff --git a/research/char2-jets/evidence/PROOF-working-notes.md b/research/char2-jets/evidence/PROOF-working-notes.md new file mode 100644 index 0000000000..33a4e39451 --- /dev/null +++ b/research/char2-jets/evidence/PROOF-working-notes.md @@ -0,0 +1,277 @@ +# struct: principled route to (A) at T = 3 — the characteristic-2 shadow + +Status keys: PROVEN / CHECKED (exact, script named) / OPEN. + +## 1. Lemma CR2 (characteristic-2 realisation) — PROVEN + +Let E = {(t,s) : t ≠ s, B_ts = 1} be the off-diagonal support of an admissible B. Suppose there are a field K of +characteristic 2 and vectors P~(t), Q~(s) ∈ K³ with + (i) supp P~(t) ⊆ π(t), supp Q~(s) ⊆ σ(s); + (ii) P~(t)·Q~(s) = 0 for every (t,s) ∈ E; + (iii) P~(t)·Q~(t) ≠ 0 for every t. +Then cost(B) ≥ v. + +*Proof.* B has entries in F2 ⊆ K. N := Σ_j D(p~_j) B D(q~_j) has N_ts = B_ts P~(t)·Q~(s), so N = diag(P~(t)·Q~(t)), +rank v. And rank_K D(p~_j) B D(q~_j) ≤ rank_K B[supp p~_j, supp q~_j] ≤ rank_F2 B[R_j, A_j] by (i). ∎ + +This is Lemma B with the roles swapped: Lemma B moves B to the field of the geometry (Q), and CR2 moves the geometry to +the field of B (char 2). CR2 depends only on E and is **down-closed**: a realisation of E realises every E′ ⊆ E. So +**if the full incidence pattern E_full = `free` is CR2, (A) holds for the configuration for every admissible B at once.** +Degenerate realisations are allowed: points may coincide, lines may coincide, extra incidences and extra zero +coordinates are allowed; the only non-incidences demanded are the v diagonal ones. + +*T = 2 (Lemma A) is a one-line corollary:* in P¹ an incidence is an equality p(t) = q(s)^⊥, so any injection of the +finitely many used points of P¹(Q) into P¹(F̄2) fixing [1:0] and [0:1] and sending full-support points to full-support +points realises the whole pattern. + +## 2. Data — CHECKED (cr2.py exhaustive DFS over GF(2^k); t1.py, t2.py, t3.py) + +- **Full pattern CR2 for every stored configuration except tied_min** (t3.py): aff14, cech_v8, cex_joint_v7, + cex_wholeTS_v9, gad, nojoint_21_1..14, supmin_fail_v8 realise over GF(2); cex_min_1 (v = 19, 114 incidences) over + GF(4) (none over GF(2)). So (A) holds on all of them for every B, by Lemma CR2 alone (no SAT, no certificate). + In particular cost(cex_min_1) ≥ 19 for every B, where every order/label certificate stopped at 18. +- **tied_min: full pattern NOT realisable** over GF(2), GF(4), GF(8), GF(16) (exhaustive). Reason: tied_min is the + complete quadrangle a₁..a₄ whose diagonal points are the coordinate vertices e₁, e₂, e₃ (the supports force each + side through its e_k). In characteristic 2 the diagonal points of a quadrangle are collinear (Fano), but e₁e₂e₃ is a + frame: tied_min is the **anti-Fano (non-Fano) configuration**, the canonical "1 + 1 ≠ 0" gadget. +- **All 217 optima of tied_min are CR2 over GF(2) itself** (t1.py; off-diagonal ones 12, 14, 16, 18, 24). Every optimum + drops exactly enough of the anti-Fano incidences to become Fano-compatible. +- All minimisers and all cost-(min+1) matrices of cex_joint_v7, cech_v8, supmin_fail_v8, cex_wholeTS_v9, + nojoint_21_1..4 are CR2 over GF(2) (t2.py). +- verify_cr2.py: end-to-end — for the realisations of cex_min_1 (GF(4)), cex_joint_v7, gad, aff14 (GF(2)): supports + inside π, σ; for 200 random admissible B each, N = Σ_j D(p~_j) B D(q~_j) over GF(2^k) is diagonal with nonzero + diagonal, and cost(B) ≥ v. CHECKED. + +## 1b. Corollary (2-adic tropical reduction) — PROVEN + +Let ν be a valuation on a field K ⊇ Q extending v₂ (e.g. Q₂(2^{1/n})), ϖ a uniformiser-power with ν(ϖ^{a}) = a for +a ∈ (1/n)Z. If some a ∈ ((1/n)Z)³ satisfies, for every t, + ν(p(t)·q(t)) = min_{j∈π(t)} (ν p_j(t) + a_j) + min_{j∈σ(t)} (ν q_j(t) − a_j), +then the full pattern is CR2, so (A) holds for every B. *Proof.* Replace p_j ← ϖ^{a_j} p_j, q_j ← ϖ^{−a_j} q_j: all +products p(t)·q(s), hence all incidences and supports, are unchanged. Scale each vector to minimum valuation 0 and +reduce to the residue field (char 2): incidences reduce to incidences, supports can only shrink, and the hypothesis +says the diagonal product has valuation exactly 0, so it reduces to a nonzero element. ∎ +*Special case a = 0:* **if every primitive integer p(t), q(t) has p(t)·q(t) odd, (A) holds for every B.** The ultrametric +inequality always gives "≥"; equality fails exactly when the leading terms cancel — the two-odd-terms cancellation of +tied unit lines. tied_min: p·q = ±1 ± 1 = ±2 on every line, and min_j a_j − max_{j≠k} a_j ≤ 0 < 1 for every a, so no +tropical scaling works — consistent with its being anti-Fano. + +## 1c. The per-B alternative and direct sums — PROVEN (remark) + +Write Qmin(E) := min Σ_j rank_Q B′[R_j,A_j] over rational B′ with supp B′ ⊆ E ∪ diag, B′_tt ≠ 0. Lemma B: Qmin ≥ v. +Witnesses for cost(B) ≥ v: **(L)** Qmin(supp B) ≤ cost(B); **(C)** supp B is CR2. +On a direct sum X ⊕ Y (no incidences between), Qmin, cost and CR2 behave additively / conjunctively, so (L) can borrow +slack between components: e.g. tied_min's full B has cost 24 but Qmin = 12 (a lifted optimum is a sub-support), so +B_X ⊕ B_full satisfies (L) even for a non-liftable B_X with excess < 12. The alternative "(L) or (C)" fails on +B_X ⊕ B_Y as soon as B_X has Qmin(supp B_X) > cost(B_X) and B_Y is a **non-CR2 B with Qmin(supp B_Y) = cost(B_Y)**, +e.g. a non-CR2 minimiser of a tight configuration Y. None is known: every optimum of tied_min is CR2. So the +alternative, per B, is equivalent on direct sums to "no tight non-CR2 minimiser coexists with a non-liftable B"; +the robust form is per strong component (Lemma SCC), and inside a component it is the selection question of §3. + +## 2. The char-2 side is complete: generic realisation = split certificate — PROVEN (completeness conditional on a standard min-max, CHECKED on instances) + +**Lemma GR.** For any field K ⊇ F2 and any support-compatible P~, Q~ ∈ K^{v×3} (supp p~_j ⊆ R_j, supp q~_j ⊆ A_j; +**no incidence or diagonal condition**), cost(B) ≥ rank_K (B ∘ P~Q~ᵀ), since B ∘ P~Q~ᵀ = Σ_j D(p~_j) B D(q~_j). +The best such bound is the generic rank GR(B) := rank_{F2(X,Y)} (B ∘ XYᵀ) (X_tj, j ∈ π(t), Y_sj, j ∈ σ(s), indeterminates). +CR2 is the special case where B ∘ P~Q~ᵀ is diagonal. Hybrid: it suffices that the *violated* incidences +{(t,s) ∈ E : p~(t)·q~(s) ≠ 0} form an acyclic digraph (then B∘P~Q~ᵀ is triangular after reordering). + +**Lemma Split (expansion of GR).** mod 2, det(B ∘ XYᵀ) = Σ_σ Π_t B_{tσ(t)} x(t)·y(σ(t)); the coefficient of the monomial +Π_t x_{a(t)}(t) Π_s y_{b(s)}(s) is per(B ∘ K_ab) = det_F2(B ∘ K_ab), K_ab[t,s] = [a(t) = b(s)]. After permuting, +B ∘ K_ab = ⊕_c B[R′_c, A′_c] with R′_c = a⁻¹(c) ⊆ R_c, A′_c = b⁻¹(c) ⊆ A_c. Hence + **GR(B) = SPL(B) := max over row-partitions {R′_c ⊆ R_c} and column-partitions {A′_c ⊆ A_c} of Σ_c rank B[R′_c, A′_c]** +(same argument on minors), and GR(B) = v iff a **perfect split** exists: three square F2-nonsingular submatrices, one +inside each block, whose row sets partition the lines and whose column sets partition the lines. A perfect split +gives cost(B) ≥ v directly (rank of a block ≥ rank of a submatrix): an elementary certificate. + +**Min-max (standard independent-matching / linking-system duality, Rado–Edmonds type; cited from memory, not re-proved here).** + SPL(B) = min_{S,T ⊆ [v]} (v − |S|) + (v − |T|) + Σ_c rank_F2 B[S ∩ R_c, T ∩ A_c]. +"≤" is elementary; equality: CHECKED on 300 random (not necessarily admissible) instances, v = 3–6, including 92 with +SPL < v (t9.py: GR by evaluation over GF(2^16) vs exhaustive min over S, T; 0 mismatches). + +**Corollary (completeness; conditional on the min-max).** If (A) holds for every sub-configuration W (cost_W(B|_W) ≥ |W|), then for all S, T: +Σ_c rank B[S∩R_c, T∩A_c] ≥ cost_{S∩T}(B|_{S∩T}) ≥ |S∩T| ≥ |S| + |T| − v, so SPL(B) = v. Since (A) is hereditary: + **(A) at T = 3 ⟺ every admissible B on every configuration has a perfect split.** +So the char-2 Hadamard certificate is *complete* (unlike the char-0 one, whose completeness is (Q ≤ F2)), and the +anti-Fano obstruction of §1 is an obstruction only to the *diagonal* (CR2) form, never to the generic form. +Data: GR(B) = v for 100 random B at each of four densities on tied_min (incl. the full non-CR2 B), cex_min_1, gad, +aff14, cex_joint_v7 (t7.py) — consistent with (A), as it must be. + +**Principal split (COL), stronger and FALSE in general.** a = b = c(t) ∈ D(t): cost(B) ≥ Σ_c rank B[L_c, L_c] +(L_c = c⁻¹(c) ⊆ D_c). It holds for all 217 optima, the full B and 200 random B of tied_min (t10.py), but fails on the +private digon (two lines with D = {j}, B = J₂: L_j = both lines, singular), where the perfect split uses a ≠ b. +COL generalises MAS-sum (acyclic L_c) from unit-triangular to nonsingular principal minors. + +## 3. The multiplicative realisation: (A) without wild incidences and harmonic lines — PROVEN + +Call an incidence (t,s) (in some block) **binomial** if |π(t) ∩ σ(s)| = 2 and **wild** if |π(t) ∩ σ(s)| = 3 (a +full-support point on a full-support line; M1's obstacle). Call a line t **harmonic** if |D(t)| = 2 and the two terms +of p(t)·q(t) are equal: p(t)·q(t) = 2 p_i(t) q_i(t). Geometrically (when q(t) passes through the vertex e_k): q(t) is +the **harmonic conjugate** of the line e_k p(t) with respect to the two frame sides through e_k. Let H = harmonic lines, +W = the wild incidences, F = lines with both p(t) and q(t) of full support (|D| = 3; F ∩ H = ∅). + +**Map φ.** Let K = F2(z_p : p prime) and φ : Q* → K* the homomorphism with φ(−1) = 1, φ(p) = z_p; φ(0) = 0. +Set P~(t) = φ(p(t)), Q~(s) = φ(q(s)) entrywise. Supports are preserved exactly. +- A binomial incidence x_i y_i + x_j y_j = 0 means x_i y_i = (−1)·x_j y_j, so φ(x_i)φ(y_i) = φ(x_j)φ(y_j), i.e. + P~(t)·Q~(s) = 0 in characteristic 2. **Every binomial incidence is preserved.** +- Diagonal: P~(t)·Q~(t) = Σ_{j∈D(t)} φ(p_j q_j) is a sum of |D(t)| Laurent monomials (φ(±n) = monomial of |n|), + zero iff they cancel in pairs: never for |D| ∈ {1, 3}; for |D| = 2 iff |p_i q_i| = |p_j q_j|, i.e. (as p·q ≠ 0) + iff t is harmonic. **The diagonal vanishes exactly on H.** + +**Theorem B2.** Let X ⊆ [v] \ H be a set of non-harmonic lines containing no directed cycle of wild incidences. Then +**cost(B) ≥ |X| for every admissible B.** In particular: + (i) **no wild incidence and no harmonic line ⇒ the full pattern is CR2 ⇒ (A) holds for every B**; + (ii) no wild incidence ⇒ cost ≥ v − |H|; + (iii) in general cost ≥ v − |H| − |F| + MAS(W[F]) (wild edges join a full point to a full line, so a wild cycle + lies inside F). +*Proof.* N := B ∘ P~Q~ᵀ has rank ≤ cost (Lemma GR). Off the diagonal N_ts ≠ 0 only if B_ts = 1 and the incidence +is not preserved, i.e. wild. N[X,X] is triangular in a topological order of W[X] with nonzero diagonal. ∎ +By duality (P ↔ Q, B ↔ Bᵀ) nothing changes (both notions are symmetric). Compare Theorem M1 (no full-support point: +cost ≥ v/2): in that class W = F = ∅, so B2 gives **cost ≥ v − |H|**, and (A) unless a harmonic line exists. +CHECKED (t11.py, phi.py): 400 random no-wild configurations (v = 5–9, entries up to 3): φ over GF(2^16) (random z_p) +preserves every block incidence (assert), the zero diagonals are exactly H (400/400); exhaustive minimum cost ≥ v − |H| +on all 379 with f ≤ 20. + +**Where this leaves (A).** A counterexample needs harmonic lines or wild cycles. tied_min is no-wild with **all 12 +lines harmonic** (p·q = ±1 ± 1): the anti-Fano of §1 *is* the harmonic-conjugate configuration, and "1 + 1 = 0" +is exactly "harmonic conjugate = itself". The two residual mechanisms are thus the two classical char-2 phenomena: +harmonic conjugation (multiplicative, −1 ↦ 1) and the additive trinomial 1 + xy + x′y′ = 0 (wild). + +## 4. Jets: the "higher-order construction" — valuative CR2, and a SAT-free proof of cost(tied_min) = 12 + +**Lemma VCR2 (valuative CR2) — PROVEN.** Let K be a field of characteristic 2 with a valuation ν (e.g. F((ε))), and +P~, Q~ support-compatible over K; put w_ts = ν(P~(t)·Q~(s)). If every directed cycle C of E (incidences in blocks) +satisfies Σ_{(t,s)∈C} w_ts > Σ_{t∈C} w_tt (in particular all w_tt < ∞), then cost(B) ≥ v for every B with +off-diagonal support in E. *Proof.* N = B ∘ P~Q~ᵀ has rank ≤ cost (Lemma GR). det N = Σ_σ Π_t N_{tσ(t)}; a cycle cover +σ ≠ id splits into fixed points and cycles of E, so its term has valuation > Σ_t w_tt, the valuation of the identity +term. No cancellation: det N ≠ 0. ∎ +Special cases: CR2 (w = ∞ on E); the acyclic hybrid (every cycle has an edge with w = ∞); B2 (§3). + +**Corollary J (first-order jets, no-wild class) — PROVEN.** Let C be no-wild, φ as in §3, and suppose there are +support-compatible X, Y over K with + (J1) φp(t)·Y(s) + X(t)·φq(s) = 0 for every incidence (t,s) of E (incidences preserved to first order), + (J2) δ′_t := φp(t)·Y(t) + X(t)·φq(t) ≠ 0 for every harmonic t (harmonic points leave their lines at order 1). +Then with P~ = φP + εX, Q~ = φQ + εY over K((ε)): w = ∞ or ≥ 2 on E, w_tt = 0 on non-harmonic lines and = 1 on +harmonic lines, so every cycle has Σ_edges ≥ 2|C| > |C| ≥ Σ_vertices, and **(A) holds for every B**. +(J1) is a homogeneous linear system and (J2) asks v linear functionals to be nonzero on its solution space; over an +infinite field it suffices that **each** δ′_t is not identically zero on the solution space (a vector space is not a +finite union of proper subspaces). So Corollary J is a B-independent **linear-algebra certificate**. + +**Theorem T′ (cost(tied_min) ≥ 12, by hand).** φ(tied_min): all entries are ±1, so every point becomes the Fano +centre c = (1,1,1) and every class-k line becomes the Fano line ℓ_k through c and e_k (ℓ₀ = (0,1,1), ℓ₁ = (1,0,1), +ℓ₂ = (1,1,0)) — the Fano collapse of the anti-Fano. Write f_k(t) = X(t)·ℓ_k and g(s) = c·Y(s). Since ℓ₀+ℓ₁+ℓ₂ = 0 in +char 2, f₀+f₁+f₂ = 0 for each t, and (X(t) of full support) any such triple occurs; g(s) is arbitrary (Y(s) has two +free entries). (J1) for an incidence t → s, s of class k: f_k(t) = g(s). The class-k lines on the side {x,y} of M_k +are the two lines (u,k), u in the other pair; so all lines t whose point lies on a side S of M_k need f_k(t) = G_k(S), +the common g-value of the lines carrying S. (J2) for line (u,k): f_k = G_k(side ∋ u) ≠ g(u,k) = G_k(side ∌ u), i.e. +h_k := G_k(S) + G_k(S′) ≠ 0 for the two sides S, S′ of M_k. The constraint f₀+f₁+f₂ = 0 at the four points reads: +at a, Σ_k G_k(side_k(a)) = 0; at the vertex b paired with a in M₀: the same sum + h₁ + h₂ = 0, so h₁ = h₂; likewise +h₀ = h₂, h₀ = h₁. **Solution: h₀ = h₁ = h₂ = h ≠ 0**, any G with Σ_k G_k(side_k(a)) = 0. So (J1)+(J2) are solvable, +and cost(tied_min) ≥ 12 for every B; with an optimum, = 12. No SAT, no enumeration. ∎ +CHECKED from the hand formula (tied_min_jet_cert.py, exact over F2, so K = F2((ε)) suffices): h = 1 gives (J1) on all +72 incidences and (J2) on all 12 lines; N = B∘P~Q~ᵀ at a random ε ∈ GF(2^16) has rank 12 for the 217 optima, the full B +and 300 random B (518/518). Also (tangent.py, t15.py): the (J1) solution space of the full 72-incidence pattern has dimension 27 over GF(2^16) +and every one of the 12 functionals δ′_t is nonzero on it. + +**Reading.** tied_min = anti-Fano is *not* realisable in characteristic 2 (§1), but it is realisable **to first order +around its Fano collapse**: exactly the equal-characteristic shadow of its 2-adic picture (diagonal products of +valuation ν(2) = 1, incidences of valuation ∞ ↔ diagonal of ε-order 1, incidences of ε-order ≥ 2). This is the +"higher-order construction": the obstruction to char-2 realisation (harmonic conjugation, 1 + 1 = 0) is removed by a +jet of order 1, and the tightness of tied_min is the statement that the jet has order exactly 1 on every line. + +## 5. How far the first-order jet reaches — CHECKED; the obstruction — PROVEN + +**Data (t16.py, t17.py; exact linear algebra over GF(2^16), random z_p).** Corollary J's hypothesis holds on +**all 4095 sub-configurations of tied_min** and on **1500 random all-harmonic F2S configurations** (v = 4–14, entries +±r^a, r ∈ {2,3,5}): (A) holds on each for every B by a linear-algebra certificate. On 1892 random no-wild +configurations with harmonic lines (mixed supports), it holds on 1889 and **fails on 3** (stored jetfail/jf0..2.json; +v = 11, 9, 9): one or two harmonic lines whose δ′ vanishes on the whole first-order tangent space. Those three are +also not CR2 (GF(2), GF(4), GF(8)), but they are far from tight (exhaustive min cost 12 for v = 9, 14 for v = 9), so +they need either a jet of order ≥ 2, a degenerate base point other than φ, or a B-dependent argument. + +**Lemma F (the obstruction is a binary flow) — PROVEN.** Write X(t) = φp(t) ∘ ξ(t), Y(s) = φq(s) ∘ η(s) (every +support-compatible tangent has this form). On a binomial incidence over the pair {i,j}, (J1) becomes +Δ_ij ξ(t) = Δ_ij η(s) with Δ_ij ξ = ξ_i + ξ_j; for harmonic t with D(t) = {i,j}, (J2) is Δ_ij ξ(t) ≠ Δ_ij η(t). +So J fails at t iff the harmonic equation is an F2-combination of incidence equations: a set Z of incidence edges +plus the harmonic edge h with, at each object whose support has size 2, an even number of Z-edges, and at each object +of full support, equal parities of Z-edges over the three pairs {01}, {02}, {12}. Any such Z has |Z ∩ incidences| even +(evaluate at the sign labels ξ_j(t) = [p_j(t) < 0], η_j(s) = [q_j(s) < 0], which give 1 on every incidence and 0 on +every harmonic diagonal). On objects with two-element supports only (a cycle in P¹), Z would be a cycle with an odd +number of incidences, so **no obstruction exists there** — the Q-geometry (−1 ≠ 1) enters exactly through this parity. +With full-support objects the parity condition is "Fano-like" (Δ₀₁ + Δ₀₂ + Δ₁₂ = 0) and flows of even incidence +count can exist (jf0..2). + +Full collapse (every z_p := 1, t19.py) does not rescue jf0..2: the same harmonic lines stay immovable at order 1. + +## 6. Summary and conjecture + +- Duality answered: the char-2 Hadamard witness in generic form (GR = perfect split) is complete given (A), so a per-B + "(L) or (C)" alternative carries no independent content. The real hierarchy is in the char-2 *realisation order*: + order 0 (φ / CR2: everything without harmonic lines or wild cycles), order 1 (jets: tied_min, all its 4095 + sub-configurations, all 1500 random harmonic F2S configurations), higher / unknown (jf0..2, harmonic lines immovable + at order 1, all with slack ≥ 3). +- Decomposition (track 1): tied_min = anti-Fano = harmonic-conjugate configuration; its 44 minimal non-CR2 + sub-configurations (32 of 6 lines: four quadrangle vertices + six sides, each point paired with a side missing it; + 12 of 7 lines) are the atoms of the char-2 obstruction; the six-line ones are tight. Tightness of tied_min = the jet + has order exactly 1 on every line (diagonal ε-order 1 = ν₂(p·q)). +- **Conjecture (2-adic shadow).** Every configuration over Q admits a char-2 valued realisation (over F̄2((ε))) whose + diagonal is strictly dominant on every directed cycle of incidences (Lemma VCR2); this would prove (A). It must fail + for T ≥ 7 (E7/E8), which is a consistency check only. +- Open: harmonic lines immovable at first order (jf0..2), and wild cycles (three-term incidences), which φ breaks. + +## 5b. Order-2 jets on jf0..2 — CHECKED (jet2.py, t20–t23) + +**Order-2 scheme.** P~ = φ₀P + εX₁ + ε²X₂, Q~ likewise (φ₀ = full collapse, all nonzero entries ↦ 1, defined over F2). +Target: every incidence of ε-order ≥ 3, every diagonal of order ≤ 2 (non-harmonic: 0); VCR2 then applies. With +(X₁,Y₁) ∈ V = ker A (A = the first-order incidence functionals), the order-2 equations A(X₂,Y₂) = b, b_e = X₁(t_e)·Y₁(s_e), +are solvable iff every left-kernel vector z of A gives q_z(X₁,Y₁) = Σ z_e b_e = 0. For an immovable line t +(δ′_t = Σ c_e A_e), the order-2 diagonal is the constant **Q_t = X₁(t)·Y₁(t) + Σ c_e b_e**, independent of (X₂,Y₂). +**Result: for all four immovable lines (jf0: line 0; jf1: line 7; jf2: lines 0, 2), Q_t is identically zero as a +polynomial on V** (t21.py), so the order-2 diagonal vanishes for every jet over every char-2 field. Over F2 the search +finds no point with all q_z = 0 and Q_t = 1 for jf1, jf2 (dim V = 22, 24; exhaustive); the identity explains why. +So the immovability persists to order 2 for a structural reason: the Lemma F flow Z_t also kills the quadratic term. +Order ≥ 3 was not tested. Conjecture: the flow is an exact char-2 obstruction, so **no B-independent valuative +certificate exists for jf0..2**. + +**These are not counterexamples, and the B-dependent test works on the optima.** +- jf1: v = 9, exact minimum cost 12 (192 minimisers); 186 pass the first-order jet test on E = supp B (and are CR2). + The other 6 pass neither test, but cost ≥ v holds there anyway. +- jf2: v = 9, exact minimum cost 14 (12 928 minimisers); every one passes the jet test on E = supp B and is CR2. +- jf0: v = 11, f = 41; small CNF "cost ≤ K" (satlib) is UNSAT for K ≤ 15, so **cost(jf0) ≥ 16 > v**. + +**Three-term (wild) cycles (t24.py).** All 300 random configurations that contain a directed cycle of wild incidences +(v = 6–12, entries ≤ 3) are realisable in char 2 with the full pattern (293 over GF(2), 7 over GF(4)), so (A) holds on +each by Lemma CR2. φ breaks wild incidences, so this is not covered by any theorem here: **OPEN** in theory, never an +obstruction in the data. + +## 7. Final statement for packaging + +**PROVEN.** +- Lemma CR2 (§1): a char-2 realisation of supp B (supports ⊆, diagonal ≠ 0) gives cost(B) ≥ v. Corollaries: Lemma A + (T = 2) in one line; 2-adic/tropical reduction (§1b): primitive diagonals all odd (after some rescaling) ⇒ (A). +- Lemma GR / Split (§2): cost ≥ rank_K(B ∘ P~Q~ᵀ) for any support-compatible P~, Q~ in char 2; the generic rank equals + the best split Σ_c rank B[R′_c, A′_c]. (That this split is complete given (A) relies on a standard min-max, which is + CHECKED on instances, not re-proved.) +- Theorem B2 (§3): with φ(−1) = 1: cost ≥ v − |H| − |F| + MAS(W[F]). No wild incidences and no harmonic lines ⇒ (A) + for every B; no wild incidences ⇒ cost ≥ v − |H|. +- Lemma VCR2 (§4): a char-2 valued realisation whose diagonal is strictly dominant on every directed cycle gives + cost ≥ v. +- Corollary J (§4): the first-order jet test, linear algebra, independent of B. +- Theorem T′ (§4): cost(tied_min) = 12 by hand (Fano collapse, h₀ = h₁ = h₂ ≠ 0). +- Lemma F (§5): the only first-order obstruction is a binary flow through the harmonic edge, with an even number of + incidences; there is none when every object has a two-element support. +**CHECKED (exact).** +- CR2: the full pattern of every stored configuration except tied_min; all 217 tied_min optima. +- B2/φ: 400 random no-wild configurations (incidences kept; zero diagonals = H; cost ≥ v − |H|). +- Corollary J: all 4095 sub-configurations of tied_min; 1500/1500 random all-harmonic F2S; 1889/1892 random + no-wild configurations with harmonic lines. +- T′: tied_min_jet_cert.py (exact over F2; 518/518 matrices B of rank 12). +- jf0..2 (§5b): immovable at order 1 and order 2 (Q_t ≡ 0); (A) holds there: costs 12, 14 and ≥ 16 against + v = 9, 9, 11. +- Wild cycles: 300/300 fully CR2. +**OPEN.** (A) at T = 3. +- Conjecture (2-adic shadow), B-dependent form: for every B, or at least for some minimiser, supp B has a char-2 + valued realisation with a cycle-dominant diagonal. The B-independent form is likely false (jf0..2). +- Harmonic lines immovable at orders 1–2: does the flow obstruct at every order? +- A structural theorem for wild cycles. +- Completeness of the split min-max (standard, not re-proved here). diff --git a/research/char2-jets/lean/DecoderDuality.lean b/research/char2-jets/lean/DecoderDuality.lean new file mode 100644 index 0000000000..c02c32f6dc --- /dev/null +++ b/research/char2-jets/lean/DecoderDuality.lean @@ -0,0 +1,232 @@ +import Mathlib + +/-! +# Decoder duality certificates + +Two rank lower bounds ("duality certificates") behind the decoder lower bounds, +both obtained from one abstract lemma (`hadamard_diag_rank_sum`): + +* `lemmaB` : the lift identity, `B` over the same field `K` as the decomposition `P, Q`. +* `lemmaCR2` : the char-2 realisation, `B` over `𝔽₂`, realised by vectors `P~, Q~` + over a field of characteristic 2 supported inside the supports of `P, Q`. +-/ + +open Matrix + +namespace DecoderDuality + +/-! ## Generic linear-algebra helpers -/ + +section Helpers + +variable {F : Type*} [Field F] + +/-- Rank is subadditive. -/ +theorem rank_add_le {m n : Type*} [Fintype m] [Fintype n] (A B : Matrix m n F) : + (A + B).rank ≤ A.rank + B.rank := by + unfold Matrix.rank + rw [Matrix.mulVecLin_add] + calc Module.finrank F (LinearMap.range (A.mulVecLin + B.mulVecLin)) + ≤ Module.finrank F ↥(LinearMap.range A.mulVecLin ⊔ LinearMap.range B.mulVecLin) := + Submodule.finrank_mono (LinearMap.range_add_le _ _) + _ ≤ _ := Submodule.finrank_add_le_finrank_add_finrank _ _ + +/-- Rank of a finite sum is at most the sum of the ranks. -/ +theorem rank_sum_le {m n ι : Type*} [Fintype m] [Fintype n] (s : Finset ι) + (f : ι → Matrix m n F) : (∑ i ∈ s, f i).rank ≤ ∑ i ∈ s, (f i).rank := by + classical + induction s using Finset.induction_on with + | empty => simp + | insert a s ha ih => + rw [Finset.sum_insert ha, Finset.sum_insert ha] + exact (rank_add_le _ _).trans (Nat.add_le_add_left ih _) + +/-- **Support restriction.** If `p` vanishes off `S` and `q` vanishes off `U`, then +`rank (diag p * B * diag q) ≤ rank (B restricted to S × U)`. -/ +theorem rank_diag_mul_mul_diag_le {m n : Type*} [Fintype m] [Fintype n] + [DecidableEq m] [DecidableEq n] (B : Matrix m n F) (p : m → F) (q : n → F) + (S : Finset m) (U : Finset n) (hp : ∀ t, p t ≠ 0 → t ∈ S) (hq : ∀ s, q s ≠ 0 → s ∈ U) : + (diagonal p * B * diagonal q).rank ≤ + (B.submatrix ((↑) : S → m) ((↑) : U → n)).rank := by + let X : Matrix m S F := fun t i => if (i : m) = t then p t else 0 + let Y : Matrix U n F := fun k s => if (k : n) = s then q s else 0 + have key : diagonal p * B * diagonal q = X * B.submatrix ((↑) : S → m) ((↑) : U → n) * Y := by + ext t s + rw [mul_diagonal, diagonal_mul, mul_apply] + by_cases hs : s ∈ U + · rw [Fintype.sum_eq_single ⟨s, hs⟩] + · simp only [Y, if_pos rfl, mul_apply, submatrix_apply] + by_cases ht : t ∈ S + · rw [Fintype.sum_eq_single ⟨t, ht⟩] + · simp only [X, if_pos rfl] + · intro i hi + have : (i : m) ≠ t := fun h => hi (Subtype.ext h) + simp only [X, if_neg this, zero_mul] + · have hpt : p t = 0 := by + by_contra h; exact ht (hp t h) + rw [hpt] + simp only [zero_mul] + symm + rw [Finset.sum_mul] + apply Finset.sum_eq_zero + intro i _ + have : (i : m) ≠ t := fun h => ht (h ▸ i.2) + simp only [X, if_neg this, zero_mul] + · intro k hk + have : (k : n) ≠ s := fun h => hk (Subtype.ext h) + simp only [Y, if_neg this, mul_zero] + · have hqs : q s = 0 := by + by_contra h; exact hs (hq s h) + rw [hqs, mul_zero] + symm + apply Finset.sum_eq_zero + intro k _ + have : (k : n) ≠ s := fun h => hs (h ▸ k.2) + simp only [Y, if_neg this, mul_zero] + rw [key] + exact (rank_mul_le_left _ _).trans (rank_mul_le_right _ _) + +/-- Rank cannot increase under a ring homomorphism of fields (extension of scalars). +Only this direction is needed. -/ +theorem rank_map_le {K : Type*} [Field K] (f : F →+* K) {m n : Type*} [Fintype m] [Fintype n] + (A : Matrix m n F) : (A.map f).rank ≤ A.rank := by + rw [rank_eq_finrank_span_cols, rank_eq_finrank_span_cols] + set W := Submodule.span F (Set.range A.col) with hW + let b := Module.finBasis F W + let g : Fin (Module.finrank F W) → (m → K) := fun i => fun t => f ((b i : m → F) t) + have hsub : Submodule.span K (Set.range (A.map f).col) ≤ Submodule.span K (Set.range g) := by + rw [Submodule.span_le] + rintro _ ⟨s, rfl⟩ + have hmem : A.col s ∈ W := Submodule.subset_span ⟨s, rfl⟩ + have hrep := b.sum_repr ⟨A.col s, hmem⟩ + have hcol : (A.map f).col s = ∑ i, f (b.repr ⟨A.col s, hmem⟩ i) • g i := by + ext t + have h2 := congrArg (fun w : W => f ((w : m → F) t)) hrep + simp only [Submodule.coe_sum, Submodule.coe_smul, Finset.sum_apply, Pi.smul_apply, + smul_eq_mul, map_sum, map_mul] at h2 + simp only [col_apply, map_apply, Finset.sum_apply, Pi.smul_apply, smul_eq_mul, g] + exact h2.symm + rw [SetLike.mem_coe, hcol] + exact Submodule.sum_mem _ fun i _ => + Submodule.smul_mem _ _ (Submodule.subset_span ⟨i, rfl⟩) + calc Module.finrank K (Submodule.span K (Set.range (A.map f).col)) + ≤ Module.finrank K (Submodule.span K (Set.range g)) := Submodule.finrank_mono hsub + _ ≤ Fintype.card (Fin (Module.finrank F W)) := finrank_range_le_card g + _ = Module.finrank F W := Fintype.card_fin _ + +end Helpers + +/-! ## The core lemma: Hadamard-diagonal identity ⇒ rank-sum bound -/ + +/-- **Core lemma.** Let `B : ι × ι` over a field `F`, and vectors `p j, q j : ι → F` +(`j : T`). If the Hadamard product `N t s = B t s * ∑ⱼ p j t * q j s` is diagonal with +nonzero diagonal, then for any sets `S j ⊇ supp (p j)`, `U j ⊇ supp (q j)`, +`|ι| ≤ ∑ⱼ rank (B restricted to S j × U j)`. -/ +theorem hadamard_diag_rank_sum {F : Type*} [Field F] {ι T : Type*} [Fintype ι] + [DecidableEq ι] [Fintype T] (B : Matrix ι ι F) (p q : T → ι → F) + (S U : T → Finset ι) + (hpS : ∀ j t, p j t ≠ 0 → t ∈ S j) (hqU : ∀ j s, q j s ≠ 0 → s ∈ U j) + (hoff : ∀ t s, t ≠ s → B t s * ∑ j, p j t * q j s = 0) + (hdiag : ∀ t, B t t * ∑ j, p j t * q j t ≠ 0) : + Fintype.card ι ≤ ∑ j, (B.submatrix ((↑) : S j → ι) ((↑) : U j → ι)).rank := by + classical + let w : ι → F := fun t => B t t * ∑ j, p j t * q j t + have hN : ∑ j, diagonal (p j) * B * diagonal (q j) = diagonal w := by + ext t s + rw [Matrix.sum_apply] + simp only [mul_diagonal, diagonal_mul] + have : ∑ j, p j t * B t s * q j s = B t s * ∑ j, p j t * q j s := by + rw [Finset.mul_sum]; exact Finset.sum_congr rfl fun j _ => by ring + rw [this] + by_cases hts : t = s + · subst hts; simp [w] + · rw [diagonal_apply_ne _ hts]; exact hoff t s hts + have hrank : (diagonal w).rank = Fintype.card ι := by + rw [rank_diagonal] + exact Fintype.card_congr (Equiv.subtypeUnivEquiv fun t => hdiag t) + calc Fintype.card ι = (∑ j, diagonal (p j) * B * diagonal (q j)).rank := by rw [hN, hrank] + _ ≤ ∑ j, (diagonal (p j) * B * diagonal (q j)).rank := rank_sum_le _ _ + _ ≤ _ := Finset.sum_le_sum fun j _ => + rank_diag_mul_mul_diag_le B (p j) (q j) (S j) (U j) (hpS j) (hqU j) + +/-! ## Setup -/ + +section Setup + +variable {K : Type*} [Field K] {v T : ℕ} + +/-- `M t s = ∑ⱼ P t j * Q s j`. -/ +def M (P Q : Fin v → Fin T → K) : Matrix (Fin v) (Fin v) K := + Matrix.of fun t s => ∑ j, P t j * Q s j + +open Classical in +/-- Row support `R_j = {t | P t j ≠ 0}`. -/ +noncomputable def R (P : Fin v → Fin T → K) (j : Fin T) : Finset (Fin v) := + Finset.univ.filter fun t => P t j ≠ 0 + +open Classical in +/-- Column support `A_j = {s | Q s j ≠ 0}`. -/ +noncomputable def A (Q : Fin v → Fin T → K) (j : Fin T) : Finset (Fin v) := + Finset.univ.filter fun s => Q s j ≠ 0 + +end Setup + +/-! ## Lemma B (lift identity) -/ + +/-- **Lemma B.** `B` over the same field `K` as `P, Q`, with nonzero diagonal, such that +`B t s ≠ 0, t ≠ s ⇒ M t s = 0`, and `M t t ≠ 0`. Then `v ≤ ∑ⱼ rank (B[R_j, A_j])`. -/ +theorem lemmaB {K : Type*} [Field K] {v T : ℕ} (P Q : Fin v → Fin T → K) + (B : Matrix (Fin v) (Fin v) K) + (hBdiag : ∀ t, B t t ≠ 0) + (hBM : ∀ t s, B t s ≠ 0 → t ≠ s → M P Q t s = 0) + (hMdiag : ∀ t, M P Q t t ≠ 0) : + v ≤ ∑ j, (B.submatrix ((↑) : R P j → Fin v) ((↑) : A Q j → Fin v)).rank := by + have h := hadamard_diag_rank_sum B (fun j t => P t j) (fun j s => Q s j) (R P) (A Q) + (fun j t ht => by simp [R, ht]) (fun j s hs => by simp [A, hs]) + (fun t s hts => by + by_cases hB : B t s = 0 + · rw [hB, zero_mul] + · have := hBM t s hB hts + simp only [M, of_apply] at this + rw [this, mul_zero]) + (fun t => mul_ne_zero (hBdiag t) (by simpa [M] using hMdiag t)) + simpa using h + +/-! ## Lemma CR2 (char-2 realisation) -/ + +/-- **Lemma CR2.** `B` over `𝔽₂` with `B t t ≠ 0`. `P, Q` over any field `K` (giving the +supports `R_j, A_j`), and `P~, Q~` over a field `L` of characteristic 2 with +`supp P~ t ⊆ supp P t`, `supp Q~ s ⊆ supp Q s`, `P~ t · Q~ s = 0` whenever `B t s = 1`, +`t ≠ s`, and `P~ t · Q~ t ≠ 0`. Then `v ≤ ∑ⱼ rank_𝔽₂ (B[R_j, A_j])`. -/ +theorem lemmaCR2 {K L : Type*} [Field K] [Field L] [CharP L 2] {v T : ℕ} + (P Q : Fin v → Fin T → K) (B : Matrix (Fin v) (Fin v) (ZMod 2)) + (Pt Qt : Fin v → Fin T → L) + (hBdiag : ∀ t, B t t ≠ 0) + (hPsupp : ∀ t j, Pt t j ≠ 0 → P t j ≠ 0) + (hQsupp : ∀ s j, Qt s j ≠ 0 → Q s j ≠ 0) + (hoff : ∀ t s, B t s = 1 → t ≠ s → ∑ j, Pt t j * Qt s j = 0) + (hdiag : ∀ t, ∑ j, Pt t j * Qt t j ≠ 0) : + v ≤ ∑ j, (B.submatrix ((↑) : R P j → Fin v) ((↑) : A Q j → Fin v)).rank := by + let f : ZMod 2 →+* L := ZMod.castHom (dvd_refl 2) L + have h01 : ∀ x : ZMod 2, x = 0 ∨ x = 1 := by decide + have h := hadamard_diag_rank_sum (B.map f) (fun j t => Pt t j) (fun j s => Qt s j) + (R P) (A Q) + (fun j t ht => by simpa [R] using hPsupp t j ht) + (fun j s hs => by simpa [A] using hQsupp s j hs) + (fun t s hts => by + rcases h01 (B t s) with hB | hB + · simp [hB] + · simp only [map_apply]; rw [hoff t s hB hts, mul_zero]) + (fun t => by + have h1 : B t t = 1 := (h01 (B t t)).resolve_left (hBdiag t) + simp only [map_apply, h1, map_one, one_mul] + exact hdiag t) + rw [Fintype.card_fin] at h + refine h.trans (Finset.sum_le_sum fun j _ => ?_) + exact rank_map_le f (B.submatrix _ _) + +end DecoderDuality + +#print axioms DecoderDuality.hadamard_diag_rank_sum +#print axioms DecoderDuality.lemmaB +#print axioms DecoderDuality.lemmaCR2 diff --git a/research/char2-jets/lean/README.md b/research/char2-jets/lean/README.md new file mode 100644 index 0000000000..0705690377 --- /dev/null +++ b/research/char2-jets/lean/README.md @@ -0,0 +1,72 @@ +# decoder-duality + +Lean 4 + Mathlib formalization of the two duality certificates behind the decoder lower bounds. +Everything is in `DecoderDuality.lean`. It has no `sorry`, and every theorem depends only on +`propext`, `Classical.choice` and `Quot.sound`. + +## Build + +``` +export PATH=~/.elan/bin:$PATH +cd research/char2-jets/lean +LEAN_NUM_THREADS=4 lake exe cache get # fetches the prebuilt Mathlib at the revision pinned in lake-manifest.json +LEAN_NUM_THREADS=4 nice lake build +``` + +Toolchain `leanprover/lean4:v4.33.0-rc1`. The Mathlib revision is pinned in `lake-manifest.json`. With a built Mathlib already in +`.lake/packages` only `DecoderDuality.lean` is compiled (about 20 s). `verify.sh` does not need Lean; `LEAN=1 bash verify.sh` runs this build as an optional extra step if `lake` is on `PATH`. +The three `#print axioms` lines at the end of the file print `propext`, `Classical.choice`, `Quot.sound` for `hadamard_diag_rank_sum`, `lemmaB`, `lemmaCR2`. + +## Statements + +Setup: `t, s ∈ Fin v`, `j ∈ Fin T`, and `P, Q : Fin v → Fin T → K` over a field `K`. Define + +- `M t s = Σ_j P t j · Q s j` +- `R_j = {t | P t j ≠ 0}` +- `A_j = {s | Q s j ≠ 0}` + +**Core lemma** (`hadamard_diag_rank_sum`). The setting is: + +- a field `F` and a finite index type `ι`; +- a matrix `B : ι × ι → F`; +- vectors `p_j, q_j : ι → F`; +- sets `S_j ⊇ supp p_j` and `U_j ⊇ supp q_j`. + +Suppose the Hadamard product `B t s · Σ_j p_j(t) q_j(s)` is diagonal with nonzero diagonal. Then + + `|ι| ≤ Σ_j rank_F B[S_j, U_j]`. + +Proof: `N = Σ_j diag(p_j) B diag(q_j)` is that diagonal matrix, so `rank N = |ι|`. Rank is +subadditive (`rank_add_le`, `rank_sum_le`). Finally, `rank(diag p · B · diag q) ≤ rank B[S, U]` +when p vanishes off S and q vanishes off U (`rank_diag_mul_mul_diag_le`), because the product +factors as `X · B[S,U] · Y`. + +**Lemma B** (`lemmaB`, the lift identity). Let `B` be over `K` with: + +- `B t t ≠ 0`; +- `B t s ≠ 0 ∧ t ≠ s ⇒ M t s = 0`; +- `M t t ≠ 0`. + +Then `v ≤ Σ_j rank_K B[R_j, A_j]`. This is the core lemma with `F = K`, `p_j = P·j`, `q_j = Q·j`, +`S_j = R_j` and `U_j = A_j`. + +**Lemma CR2** (`lemmaCR2`, the char-2 realisation). The setting is: + +- `B` over `𝔽₂ = ZMod 2` with `B t t ≠ 0`; +- `P, Q` over any field `K`, which define `R_j` and `A_j`; +- `P~, Q~ : Fin v → Fin T → L` with `L` a field of characteristic 2. + +Assume: + +- `supp P~ t ⊆ supp P t` and `supp Q~ s ⊆ supp Q s`; +- `B t s = 1 ∧ t ≠ s ⇒ P~ t · Q~ s = 0`; +- `P~ t · Q~ t ≠ 0`. + +Then `v ≤ Σ_j rank_𝔽₂ B[R_j, A_j]`. + +Proof: apply the core lemma over `F = L` to the image of `B` in `L` (via `ZMod.castHom`) with +vectors `P~, Q~` and sets `R_j, A_j`. The support inclusions are exactly the `S_j ⊇ supp` +hypotheses. Then use `rank_L(map B') ≤ rank_𝔽₂(B')` (`rank_map_le`, proved here for any ring +hom of fields because Mathlib does not have it), applied to each submatrix. + +So the duality is one lemma used in two fields. diff --git a/research/char2-jets/lean/lake-manifest.json b/research/char2-jets/lean/lake-manifest.json new file mode 100644 index 0000000000..30118b5629 --- /dev/null +++ b/research/char2-jets/lean/lake-manifest.json @@ -0,0 +1,96 @@ +{"version": "1.2.0", + "packagesDir": ".lake/packages", + "packages": + [{"url": "https://github.com/leanprover-community/mathlib4.git", + "type": "git", + "subDir": null, + "scope": "", + "rev": "55b7917b472489c7c56a0fa6393af05cfd536599", + "name": "mathlib", + "manifestFile": "lake-manifest.json", + "inputRev": null, + "inherited": false, + "configFile": "lakefile.lean"}, + {"url": "https://github.com/leanprover-community/plausible", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "b1c4a69a7e247ab7df20460212001673d74f08c0", + "name": "plausible", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/LeanSearchClient", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "0498c7c070c143a3bf7379f4d99a2c63bb9d9715", + "name": "LeanSearchClient", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/import-graph", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "18a90119a5d316358fde6c86e0ca24e59212e32c", + "name": "importGraph", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/ProofWidgets4", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "b1436dc749e722c9920036b52cdc43b3451d0b69", + "name": "proofwidgets", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": true, + "configFile": "lakefile.lean"}, + {"url": "https://github.com/leanprover-community/aesop", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "57d3325be72a842920813bcb40f96a6f7393c185", + "name": "aesop", + "manifestFile": "lake-manifest.json", + "inputRev": "master", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/quote4", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "ee41917ae11d38479fb8fb24745f7ca4bf0a784d", + "name": "Qq", + "manifestFile": "lake-manifest.json", + "inputRev": "master", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/batteries", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "2c810760f0a0c4536b397dbe30ca9b2f2f467366", + "name": "batteries", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover/lean4-cli", + "type": "git", + "subDir": null, + "scope": "leanprover", + "rev": "da07ca808b6718cb2aed14dba154e5a08b8f8ecf", + "name": "Cli", + "manifestFile": "lake-manifest.json", + "inputRev": "v4.33.0-rc1", + "inherited": true, + "configFile": "lakefile.toml"}], + "name": "DecoderDuality", + "lakeDir": ".lake", + "fixedToolchain": false} diff --git a/research/char2-jets/lean/lakefile.toml b/research/char2-jets/lean/lakefile.toml new file mode 100644 index 0000000000..111a7afac0 --- /dev/null +++ b/research/char2-jets/lean/lakefile.toml @@ -0,0 +1,9 @@ +name = "DecoderDuality" +defaultTargets = ["DecoderDuality"] + +[[require]] +name = "mathlib" +git = "https://github.com/leanprover-community/mathlib4.git" + +[[lean_lib]] +name = "DecoderDuality" diff --git a/research/char2-jets/lean/lean-toolchain b/research/char2-jets/lean/lean-toolchain new file mode 100644 index 0000000000..fd85b262bf --- /dev/null +++ b/research/char2-jets/lean/lean-toolchain @@ -0,0 +1 @@ +leanprover/lean4:v4.33.0-rc1 diff --git a/research/char2-jets/lib/col.py b/research/char2-jets/lib/col.py new file mode 100644 index 0000000000..68d7fb38b2 --- /dev/null +++ b/research/char2-jets/lib/col.py @@ -0,0 +1,17 @@ +import itertools +def rk(rows): + piv=[] + for x in rows: + for p in piv: x=min(x,x^p) + if x: piv.append(x); piv.sort(reverse=True) + return len(piv) +def col_split(B, D): + """principal split: colouring c(t) in D(t) with every B[L_c,L_c] nonsingular over F2. Returns colouring or None.""" + v=len(B) + for ch in itertools.product(*[sorted(D[t]) for t in range(v)]): + ok=True + for c in range(3): + L=[t for t in range(v) if ch[t]==c] + if rk([sum(B[t][s]<= v (Hadamard argument of Lemma B, in char 2). +Exhaustive DFS over GF(2^k).""" +import itertools, sys +IRR = {1: 0b11, 2: 0b111, 3: 0b1011, 4: 0b10011, 5: 0b100101, 6: 0b1000011, 8: 0b100011011} +class GF: + def __init__(s, k): + s.k = k; s.q = 1 << k; m = IRR[k] + s.mul = [[0] * s.q for _ in range(s.q)] + for a in range(s.q): + for b in range(s.q): + r = 0; x = a; y = b + while y: + if y & 1: r ^= x + y >>= 1; x <<= 1 + if x & s.q: x ^= m + s.mul[a][b] = r + s.inv = [0] * s.q + for a in range(1, s.q): + for b in range(1, s.q): + if s.mul[a][b] == 1: s.inv[a] = b + def dot(s, a, b): + return s.mul[a[0]][b[0]] ^ s.mul[a[1]][b[1]] ^ s.mul[a[2]][b[2]] + +def proj_points(F, supp): + """normalised projective points with support inside supp (first nonzero = 1).""" + out = [] + for v in itertools.product(range(F.q), repeat=3): + if not any(v): continue + if any(v[j] and j not in supp for j in range(3)): continue + f = next(x for x in v if x) + if f != 1: continue + out.append(v) + return out + +def realise(pi, sig, E, k=2, limit=10**6, want_all=False): + """pi[t], sig[s]: allowed supports; E: set of (t,s) incidences required. Returns a realisation or None (exhaustive over GF(2^k)).""" + F = GF(k); v = len(pi) + cand = {('p', t): proj_points(F, pi[t]) for t in range(v)} + cand.update({('l', s): proj_points(F, sig[s]) for s in range(v)}) + nb = {x: [] for x in cand} + for (t, s) in E: + nb[('p', t)].append(('l', s)); nb[('l', s)].append(('p', t)) + other = {('p', t): ('l', t) for t in range(v)}; other.update({('l', t): ('p', t) for t in range(v)}) + asg = {}; nodes = [0] + def ok(x, val): + for y in nb[x]: + if y in asg and F.dot(val, asg[y]) != 0: return False + y = other[x] + if y in asg and F.dot(val, asg[y]) == 0: return False + return True + def pick(): + best = None; bc = None + for x in cand: + if x in asg: continue + c = [val for val in cand[x] if ok(x, val)] + if bc is None or len(c) < len(bc): + best, bc = x, c + if len(c) <= 1: break + return best, bc + sols = [] + def dfs(): + nodes[0] += 1 + if nodes[0] > limit: raise TimeoutError + if len(asg) == len(cand): + sols.append(dict(asg)); return not want_all + x, c = pick() + for val in c: + asg[x] = val + if dfs(): return True + del asg[x] + return False + try: + dfs() + except TimeoutError: + return 'timeout' + return sols if want_all else (sols[0] if sols else None) + +def cfg_data(P, Q): + v = len(P) + pi = [{j for j in range(3) if P[t][j]} for t in range(v)] + sig = [{j for j in range(3) if Q[t][j]} for t in range(v)] + return pi, sig diff --git a/research/char2-jets/lib/gen.py b/research/char2-jets/lib/gen.py new file mode 100644 index 0000000000..fe418ca818 --- /dev/null +++ b/research/char2-jets/lib/gen.py @@ -0,0 +1,29 @@ +import random +from math import gcd +def prim(v): + g=0 + for x in v: g=gcd(g,abs(x)) + if g==0: return None + v=[x//g for x in v] + for x in v: + if x: return v if x>0 else [-y for y in v] +def cross(a,b): return [a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]] +def dot(a,b): return sum(x*y for x,y in zip(a,b)) +def randcfg(v, R=1, rng=random, npts=None, pfix=0.3): + """points from a small pool in {-R..R}^3; lines through two pool points (or coordinate-ish random); p.q != 0.""" + npts = npts or max(3, v//2+1) + pool=[] + while len(pool)= rank_K(B o P~Q~^T) for every support-compatible P~,Q~ over any K of char 2 (Hadamard argument), hence >= GR(B). +A random evaluation over GF(2^16) of full rank v PROVES GR(B) = v (it is an explicit certificate); a deficient evaluation +is only probabilistic evidence (Schwartz-Zippel, error <= v/2^16 per trial).""" +import random +POLY = 0x1100B; Q = 1 << 16 +EXP = [0] * (2 * Q); LOG = [0] * Q +x = 1 +for i in range(Q - 1): + EXP[i] = x; LOG[x] = i + x <<= 1 + if x & Q: x ^= POLY +for i in range(Q - 1, 2 * Q): EXP[i] = EXP[i - (Q - 1)] +def mul(a, b): + return 0 if a == 0 or b == 0 else EXP[LOG[a] + LOG[b]] +def inv(a): return EXP[(Q - 1) - LOG[a]] +def rank(M): + M = [r[:] for r in M]; n = len(M); m = len(M[0]) if M else 0; r = 0 + for c in range(m): + p = next((i for i in range(r, n) if M[i][c]), None) + if p is None: continue + M[r], M[p] = M[p], M[r]; iv = inv(M[r][c]) + M[r] = [mul(iv, e) for e in M[r]] + for i in range(n): + if i != r and M[i][c]: + f = M[i][c]; M[i] = [e ^ mul(f, g) for e, g in zip(M[i], M[r])] + r += 1 + return r +def gr(B, pi, sig, trials=3, rng=random): + v = len(B); best = 0 + for _ in range(trials): + X = [[rng.randrange(1, Q) if j in pi[t] else 0 for j in range(3)] for t in range(v)] + Y = [[rng.randrange(1, Q) if j in sig[s] else 0 for j in range(3)] for s in range(v)] + N = [[(mul(X[t][0], Y[s][0]) ^ mul(X[t][1], Y[s][1]) ^ mul(X[t][2], Y[s][2])) if B[t][s] else 0 for s in range(v)] for t in range(v)] + best = max(best, rank(N)) + if best == v: break + return best diff --git a/research/char2-jets/lib/jet2.py b/research/char2-jets/lib/jet2.py new file mode 100644 index 0000000000..4094964931 --- /dev/null +++ b/research/char2-jets/lib/jet2.py @@ -0,0 +1,78 @@ +"""Order-2 jets over the full-collapse base phi0 (support indicators, defined over F2). +P~ = phi0 P + eps X1 + eps^2 X2, Q~ likewise. Target: every incidence has eps-order >= 3, every harmonic diagonal order <= 2, +non-harmonic diagonal order 0 => cycles dominated (Lemma VCR2) => cost >= v for every B. +Reduction: (X1,Y1) in V = ker A (A = first-order incidence functionals, over F2). Order-2 incidence eqs: A(X2,Y2) = b(X1,Y1), +b_e = X1(t_e).Y1(s_e); solvable iff q_z(X1,Y1) = sum_e z_e b_e = 0 for every left-kernel vector z of A. For a line t whose +first-order functional d_t lies in rowspace A (d_t = c.A, 'immovable'), the order-2 diagonal is the constant +Q_t = X1(t).Y1(t) + sum_e c_e b_e (independent of X2,Y2); other lines are generic at order <= 2.""" +import itertools, numpy as np +def f2_rref(rows, n): + """rows: list of int bitmasks (n bits). returns (pivot rows list with pivots, transform) -- simple elimination.""" + piv=[] # (col, row, combo) + for idx,r in enumerate(rows): + comb=1<>c&1: r^=pr; comb^=pc + if r: + c=r.bit_length()-1 + # reduce others + newpiv=[] + for c2,pr,pc in piv: + if pr>>c&1: pr^=r; pc^=comb + newpiv.append((c2,pr,pc)) + piv=newpiv+[(c,r,comb)] + else: + yield ('dep', comb) + yield ('piv', piv) +def analyse(P,Q,free,H): + v=len(P); pi=[[j for j in range(3) if P[t][j]] for t in range(v)]; sig=[[j for j in range(3) if Q[t][j]] for t in range(v)] + idx={} + for t in range(v): + for j in pi[t]: idx[('X',t,j)]=len(idx) + for s in range(v): + for j in sig[s]: idx[('Y',s,j)]=len(idx) + n=len(idx) + def lin(t,s): # phi0 p(t).Y(s) + X(t).phi0 q(s) + r=0 + for j in set(pi[t])&set(sig[s]): r^=(1<>fcol&1: vec|=1<>c&1: r^=pr; comb^=pc + if r==0: imm[t]=comb # d_t = sum_{e in comb} row_e + return dict(idx=idx,n=n,E=E,deps=deps,basis=basis,imm=imm,pi=pi,sig=sig) +def quad_matrix(an, pairs): + """quadratic form u -> sum over (t,s) in pairs of X1(t).Y1(s), on basis coords: returns d x d F2 matrix M (q(u) = u^T M u).""" + idx=an['idx']; B=an['basis']; d=len(B) + M=np.zeros((d,d),dtype=np.uint8) + bits=lambda vec,k: (vec>>k)&1 + for (t,s) in pairs: + for j in set(an['pi'][t])&set(an['sig'][s]): + kx=idx[('X',t,j)]; ky=idx[('Y',s,j)] + ax=np.array([bits(b,kx) for b in B],dtype=np.uint8); ay=np.array([bits(b,ky) for b in B],dtype=np.uint8) + M^=np.outer(ax,ay) + return M +def eval_quads(Ms, d, chunk=1<<18): + """yield (u_int, values array) over all u in F2^d.""" + for start in range(0,1<>np.arange(d))&1).astype(np.uint8) + vals=[ (np.einsum('ni,ij,nj->n',U,M,U,dtype=np.int64)&1) for M in Ms] + yield us, vals diff --git a/research/char2-jets/lib/kit.py b/research/char2-jets/lib/kit.py new file mode 100644 index 0000000000..cf4d156d58 --- /dev/null +++ b/research/char2-jets/lib/kit.py @@ -0,0 +1,203 @@ +"""Shared helpers of research/three-total-decoders (standard library; python-sat only where a SAT call is made). + +Model (see README section 1): a configuration is a list of lines t = (p(t), q(t)) with p, q in Z^3 and p(t).q(t) != 0. +R_j = {t : p_j(t) != 0}, A_j = {t : q_j(t) != 0}. An admissible B over F2 has unit diagonal and B_ts = 1 (t != s) only where +p(t).q(s) = 0. Only entries that fall inside some block R_j x A_j matter for the cost, so 'free' lists exactly those incidences. +cost(B) = sum_j rank_F2 B[R_j, A_j]. +""" +import json, os, subprocess, itertools +from fractions import Fraction + +PKG = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +DATA = os.path.join(PKG, 'data') +BIN = os.environ.get('TTD_BIN') or os.path.join(PKG, 'c', 'bin') + + +def dot(a, b): + return sum(x * y for x, y in zip(a, b)) + + +def load_cfg(name): + """Return (P, Q) from data/; accepts [[p,q],...] and [P,Q] (and [P,Q,B]).""" + d = json.load(open(os.path.join(DATA, name))) + if len(d) in (2, 3) and isinstance(d[0][0], list) and isinstance(d[0][0][0], int) and len(d[0]) == len(d[1]): + return d[0], d[1] + return [l[0] for l in d], [l[1] for l in d] + + +def setup(P, Q): + v = len(P) + R = [[t for t in range(v) if P[t][j]] for j in range(3)] + A = [[s for s in range(v) if Q[s][j]] for j in range(3)] + free = [(t, s) for t in range(v) for s in range(v) + if t != s and dot(P[t], Q[s]) == 0 and any(t in R[j] and s in A[j] for j in range(3))] + return R, A, free + + +def _run(binary, text, *args): + return subprocess.run([os.path.join(BIN, binary), *args], input=text, capture_output=True, text=True, check=True).stdout + + +def blocks_text(R, A): + return "".join("%d %s\n%d %s\n" % (len(R[j]), " ".join(map(str, R[j])), len(A[j]), " ".join(map(str, A[j]))) for j in range(3)) + + +def enum_raw(v, R, A, free, slack=0): + """Exhaustive over all 2^f admissible B (C program enumall, f <= 30). Returns (best, [(cost, g)]); g bit i = free[i].""" + inp = "%d %d\n" % (v, len(free)) + "".join("%d %d\n" % e for e in free) + blocks_text(R, A) + out = _run('enumall', inp, str(slack)).split() + best, nm = int(out[0]), int(out[1]); xs = list(map(int, out[2:])) + return best, [(xs[2 * i], xs[2 * i + 1]) for i in range(nm)] + + +def enum(P, Q, slack=0): + """enum_raw for an integer configuration. Returns (best, [(cost, g)], R, A, free).""" + v = len(P); R, A, free = setup(P, Q) + best, ms = enum_raw(v, R, A, free, slack) + return best, ms, R, A, free + + +def tomat(g, free, v): + B = [[int(t == s) for s in range(v)] for t in range(v)] + for i, (t, s) in enumerate(free): + if g >> i & 1: + B[t][s] = 1 + return B + + +def rank2(rows): + """F2 rank of a list of int bitmasks.""" + piv = [] + for x in rows: + for p in piv: + x = min(x, x ^ p) + if x: + piv.append(x); piv.sort(reverse=True) + return len(piv) + + +def blk_rows(B, rows, cols): + return [sum(B[t][s] << i for i, s in enumerate(cols)) for t in rows] + + +def blockranks(B, R, A): + return [rank2(blk_rows(B, R[j], A[j])) for j in range(3)] + + +def qrank(M): + M = [[Fraction(x) for x in r] for r in M] + if not M or not M[0]: + return 0 + rk = 0 + for c in range(len(M[0])): + p = next((i for i in range(rk, len(M)) if M[i][c] != 0), None) + if p is None: + continue + M[rk], M[p] = M[p], M[rk] + for i in range(len(M)): + if i != rk and M[i][c] != 0: + f = M[i][c] / M[rk][c]; M[i] = [a - f * b for a, b in zip(M[i], M[rk])] + rk += 1 + return rk + + +def tus(B, rows, cols): + """Camion test (C program tusign): is the submatrix B[rows, cols] TU-signable?""" + rows = list(rows); cols = list(cols) + inp = "%d %d\n" % (len(rows), len(cols)) + "\n".join(str(x) for x in blk_rows(B, rows, cols)) + r = _run('tusign', inp).strip() + assert r in ('0', '1'), r + return r == '1' + + +def jsign_batch(Bs, R, A, want_sign=False): + """C program jsign: per B the tuple (J, b0, b1, b2); with want_sign also the joint signing (list of +-1 per one, row-major) or None.""" + inp = [] + for B in Bs: + v = len(B); inp.append(str(v)); inp += [str(sum(B[t][s] << s for s in range(v))) for t in range(v)] + inp.append(blocks_text(R, A).strip()) + out = _run('jsign', "\n".join(inp) + "\n", *(['s'] if want_sign else [])).split('\n') + res = []; i = 0; out = [l for l in out if l.strip()] + while i < len(out): + fl = tuple(x == '1' for x in out[i].split()); i += 1 + sgn = None + if want_sign and fl[0]: + bits = out[i].split()[1]; i += 1 + sgn = [-1 if b == '1' else 1 for b in bits] + res.append((fl, sgn) if want_sign else fl) + assert len(res) == len(Bs), (len(res), len(Bs)) + return res + + +def brute_batch(Bs, R, A): + """C program brutetu: exhaustive signings + exhaustive minors; per B (J, b0, b1, b2) or None if out of range.""" + inp = [] + for B in Bs: + v = len(B); inp.append(str(v)); inp += [str(sum(B[t][s] << s for s in range(v))) for t in range(v)] + inp.append(blocks_text(R, A).strip()) + out = [l for l in _run('brutetu', "\n".join(inp) + "\n").split('\n') if l.strip()] + return [None if l.strip() == '-1' else tuple(x == '1' for x in l.split()) for l in out] + + +def signed_matrix(B, sgn): + v = len(B); S = [[0] * v for _ in range(v)]; k = 0 + for t in range(v): + for s in range(v): + if B[t][s]: + S[t][s] = sgn[k]; k += 1 + return S + + +def block_q(S, R, A): + return [qrank([[S[t][s] for s in A[j]] for t in R[j]]) for j in range(3)] + + +# ---- independent pure-Python Camion solver (same linear system as jsign.c, different code) ------------------------------- +def camion_eqs(B, rows, cols, vid): + eqs = [] + for k in range(1, len(rows) + 1): + for S in itertools.combinations(rows, k): + par = [sum(B[t][s] for t in S) % 2 for s in cols] + Z = [s for s, p in zip(cols, par) if p == 0] + for T in itertools.combinations(Z, k): + if all(sum(B[t][s] for s in T) % 2 == 0 for t in S): + e = 0; cnt = 0 + for t in S: + for s in T: + if B[t][s]: + e |= 1 << vid[(t, s)]; cnt += 1 + if cnt: + eqs.append((e, (cnt // 2) & 1)) + return eqs + + +def solve_f2(eqs): + piv = {} + for e, r in eqs: + while e: + b = e.bit_length() - 1 + if b in piv: + pe, pr = piv[b]; e ^= pe; r ^= pr + else: + piv[b] = (e, r); break + if not e and r: + return None + x = 0 + for b in sorted(piv): + e, r = piv[b] + if r ^ (bin(e & x & ~(1 << b)).count('1') & 1): + x |= 1 << b + return x + + +def py_flags(B, R, A, which=(0, 1, 2)): + """(J, b0, b1, b2) by the Python Camion system.""" + v = len(B); ents = [(t, s) for t in range(v) for s in range(v) if B[t][s]]; vid = {e: i for i, e in enumerate(ents)} + eq = [camion_eqs(B, R[j], A[j], vid) for j in range(3)] + bo = [solve_f2(eq[j]) is not None for j in range(3)] + J = solve_f2(eq[0] + eq[1] + eq[2]) is not None + return (J, *bo) + + +def pretty_flags(f): + return "J=%d b=%d%d%d" % (f[0], f[1], f[2], f[3]) diff --git a/research/char2-jets/lib/phi.py b/research/char2-jets/lib/phi.py new file mode 100644 index 0000000000..ac388273c1 --- /dev/null +++ b/research/char2-jets/lib/phi.py @@ -0,0 +1,35 @@ +"""Multiplicative char-2 realisation phi: Q* -> GF(2^16)*, -1 -> 1, prime p -> z_p (random), applied entrywise. +Preserves every BINOMIAL incidence (|pi(t) & sigma(s)| = 2): x_i y_i = -x_j y_j -> phi(x_i)phi(y_i) = phi(x_j)phi(y_j).""" +import random +from gr import mul, inv, EXP, LOG, Q as FQ +def factor(n): + n=abs(n); f={}; d=2 + while d*d<=n: + while n%d==0: f[d]=f.get(d,0)+1; n//=d + d+=1 + if n>1: f[n]=f.get(n,0)+1 + return f +def make_phi(rng=random): + z={} + def phi(x): + from fractions import Fraction + x=Fraction(x) + if x==0: return 0 + r=1 + for n,sgn in ((x.numerator,1),(x.denominator,-1)): + for p,e in factor(n).items(): + if p not in z: z[p]=rng.randrange(2,FQ) + for _ in range(e): + r = mul(r, z[p]) if sgn>0 else mul(r, inv(z[p])) + return r + return phi +def dot2(a,b): return mul(a[0],b[0])^mul(a[1],b[1])^mul(a[2],b[2]) +def classify(P,Q): + v=len(P); wild=0; H=[] + for t in range(v): + for s in range(v): + if t!=s and sum(P[t][j]*Q[s][j] for j in range(3))==0: + if all(P[t][j] and Q[s][j] for j in range(3)): wild+=1 + terms=[P[t][j]*Q[t][j] for j in range(3) if P[t][j]*Q[t][j]] + if len(terms)==2 and abs(terms[0])==abs(terms[1]): H.append(t) + return wild, H diff --git a/research/char2-jets/lib/satlib.py b/research/char2-jets/lib/satlib.py new file mode 100644 index 0000000000..deda2e3d6d --- /dev/null +++ b/research/char2-jets/lib/satlib.py @@ -0,0 +1,75 @@ +"""Small exact SAT encodings (python-sat, CaDiCaL): rank factorisations over F2 of the three blocks of an admissible B. +build_ranks: all B with rank B[R_j,A_j] <= rs[j] (used to enumerate the optima of tied_min). +cost_leq: one CNF 'cost <= K' (per block a factorisation with c_j active columns, total active <= K); returns a B or None. +Adapted from fprime/enumB.py and fprime/costsat2.py of the working cards (see NOTICE.md).""" +from pysat.solvers import Cadical153 +from pysat.formula import IDPool +from pysat.card import CardEnc, EncType + + +def _inc(P, Q): + return lambda t, s: t != s and sum(a * b for a, b in zip(P[t], Q[s])) == 0 + + +def _factor(cl, pool, P, Q, j, c, R, A, Bv, tag=''): + for t in R: + for s in A: + target = Bv(t, s) + ands = [] + for k in range(c): + x = pool.id(('X', j, t, k)); y = pool.id(('Y', j, k, s)); z = pool.id(('Z', j, t, s, k)) + cl += [[-z, x], [-z, y], [z, -x, -y]]; ands.append(z) + if not ands: + if target is True: cl.append([]) + elif target is not False: cl.append([-target]) + continue + acc = ands[0] + for z in ands[1:]: + n = pool.id(('C', j, t, s, z)); cl += [[-n, acc, z], [-n, -acc, -z], [n, -acc, z], [n, acc, -z]]; acc = n + if target is True: cl.append([acc]) + elif target is False: cl.append([-acc]) + else: cl += [[-acc, target], [acc, -target]] + + +def build_ranks(P, Q, rs): + v = len(P); pool = IDPool(); cl = []; inc = _inc(P, Q) + def Bv(t, s): + if t == s: return True + if inc(t, s): return pool.id(('B', t, s)) + return False + for j, r in enumerate(rs): + R = [t for t in range(v) if P[t][j]]; A = [s for s in range(v) if Q[s][j]] + _factor(cl, pool, P, Q, j, r, R, A, Bv) + bvars = {(t, s): pool.id(('B', t, s)) for t in range(v) for s in range(v) if inc(t, s)} + return cl, bvars + + +def enumerate_B(P, Q, rs, limit=10 ** 6): + """All distinct B (as set of (t,s) off-diagonal ones) with block ranks <= rs, by blocking clauses on the B variables.""" + cl, bv = build_ranks(P, Q, rs); s = Cadical153(bootstrap_with=cl); out = [] + while len(out) < limit and s.solve(): + m = set(l for l in s.get_model() if l > 0) + out.append(sorted(k for k, x in bv.items() if x in m)) + s.add_clause([-x if x in m else x for x in bv.values()]) + return out + + +def cost_leq(P, Q, K): + v = len(P); pool = IDPool(); cl = []; inc = _inc(P, Q); act = [] + def Bv(t, s): + if t == s: return True + if inc(t, s): return pool.id(('B', t, s)) + return False + for j in range(3): + R = [t for t in range(v) if P[t][j]]; A = [s for s in range(v) if Q[s][j]] + c = min(len(R), len(A), K) + e = [pool.id(('e', j, k)) for k in range(c)]; act += e + for k in range(c - 1): cl.append([-e[k + 1], e[k]]) + for t in R: + for k in range(c): cl.append([-pool.id(('X', j, t, k)), e[k]]) + _factor(cl, pool, P, Q, j, c, R, A, Bv) + card = CardEnc.atmost(lits=act, bound=K, top_id=pool.top, encoding=EncType.seqcounter) + s = Cadical153(bootstrap_with=cl + card.clauses) + if not s.solve(): return None + m = set(l for l in s.get_model() if l > 0) + return [[1 if t == u else (1 if inc(t, u) and pool.id(('B', t, u)) in m else 0) for u in range(v)] for t in range(v)] diff --git a/research/char2-jets/lib/tangent.py b/research/char2-jets/lib/tangent.py new file mode 100644 index 0000000000..d6deda9337 --- /dev/null +++ b/research/char2-jets/lib/tangent.py @@ -0,0 +1,49 @@ +"""Tangent-CR2: is there a first-order deformation (X,Y) of the char-2 configuration phi(C) (support-compatible) with + phi p(t).Y(s) + X(t).phi q(s) = 0 for every incidence (t,s) in E, and phi p(t).Y(t) + X(t).phi q(t) != 0 for all t in H? +If yes (and C is no-wild), N(eps) = B o (phiP+eps X)(phiQ+eps Y)^T has rank v for every B with supp in E: cost >= v.""" +import random +from gr import mul, inv, Q as FQ +def nullspace(rows, n): + """rows: list of dict col->val over GF(2^16). returns basis of nullspace as list of lists.""" + M=[dict(r) for r in rows]; piv={} # pivot col -> row + R=[] + for r in M: + for c,pr in piv.items(): + if c in r and r[c]: + f=r[c] + for cc,vv in pr.items(): r[cc]=r.get(cc,0)^mul(f,vv) + r={c:x for c,x in r.items() if x} + if not r: continue + c=min(r); iv=inv(r[c]); r={cc:mul(iv,x) for cc,x in r.items()} + for c2,pr in piv.items(): + if c in pr and pr[c]: + f=pr[c] + for cc,vv in r.items(): pr[cc]=pr.get(cc,0)^mul(f,vv) + piv[c2]={cc:x for cc,x in pr.items() if x} + piv[c]=r + free=[c for c in range(n) if c not in piv] + basis=[] + for f in free: + vec=[0]*n; vec[f]=1 + for c,pr in piv.items(): vec[c]=pr.get(f,0) # char 2: -x = x + basis.append(vec) + return basis +def tangent_cr2(Pt,Qt,pi,sig,E,H): + v=len(Pt); idx={} + for t in range(v): + for j in sorted(pi[t]): idx[('X',t,j)]=len(idx) + for s in range(v): + for j in sorted(sig[s]): idx[('Y',s,j)]=len(idx) + def lin(t,s): + r={} + for j in sig[s]: + if Pt[t][j]: r[idx[('Y',s,j)]]=r.get(idx[('Y',s,j)],0)^Pt[t][j] + for j in pi[t]: + if Qt[s][j]: r[idx[('X',t,j)]]=r.get(idx[('X',t,j)],0)^Qt[s][j] + return {c:x for c,x in r.items() if x} + basis=nullspace([lin(t,s) for (t,s) in E], len(idx)) + res={} + for t in H: + f=lin(t,t) + res[t]=any(sum(1 for _ in [0]) and (lambda b: (lambda acc: acc)( __import__('functools').reduce(lambda a,cx: a^mul(cx[1],b[cx[0]]), f.items(), 0)))(b) for b in basis) + return res, len(basis) diff --git a/research/char2-jets/requirements.txt b/research/char2-jets/requirements.txt new file mode 100644 index 0000000000..0e3bb2d786 --- /dev/null +++ b/research/char2-jets/requirements.txt @@ -0,0 +1,4 @@ +# Tested set (development environment: Python 3.14.7, Apple clang 16, python-sat 1.9.dev15, numpy 2.5.4). Lean is NOT needed by verify.sh. +# python >= 3.11, a C compiler (cc, C99, 128-bit integers) for c/enumall.c, numpy (checks/e_jetfail.py, lib/jet2.py), python-sat (jf0 lower bound; scripts/make_data.py). +python-sat==1.9.dev15 +numpy diff --git a/research/char2-jets/scripts/make_data.py b/research/char2-jets/scripts/make_data.py new file mode 100644 index 0000000000..c5b734ecaa --- /dev/null +++ b/research/char2-jets/scripts/make_data.py @@ -0,0 +1,27 @@ +"""Authors only (not run by verify.sh): writes data/tied_min_B.json (the 518 test matrices of Theorem T') and +data/cr2_realisations.json (stored char-2 realisations of the full incidence pattern, found by lib/cr2.py:realise). +Needs python-sat for the first file. usage: python3 scripts/make_data.py [outdir] (default: current directory)""" +import sys, os, json, random +PKG = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG + '/lib') +from kit import *; from cr2 import realise, cfg_data +out = sys.argv[1] if len(sys.argv) > 1 else '.' +# --- T' matrices: B is stored as the bitmask g over `free` (bit i = free[i]), as in kit.tomat +from satlib import enumerate_B +P, Q = load_cfg('tied_min.json'); v = 12; R, A, free = setup(P, Q); idx = {e: i for i, e in enumerate(free)} +opt = [sum(1 << idx[e] for e in ent) for ent in enumerate_B(P, Q, (4, 4, 4))] +random.seed(1); random.randrange(2, 1 << 16) # same stream as tied_min_jet_cert.py (epsilon draw first) +full = (1 << len(free)) - 1; rnd = [random.getrandbits(len(free)) for _ in range(300)] +json.dump({'config': 'tied_min.json', 'f': len(free), 'optima': opt, 'full': full, 'random': rnd}, open(out + '/tied_min_B.json', 'w')) +print('tied_min_B.json: %d optima, full, %d random' % (len(opt), len(rnd))) +# --- CR2 realisations +names = ['aff14', 'cech_v8', 'cex_joint_v7', 'cex_wholeTS_v9', 'gad', 'supmin_fail_v8'] + ['nojoint_21_%d' % i for i in range(1, 15)] + ['cex_min_1'] +res = {} +for nm in names: + P, Q = load_cfg(nm + '.json'); v = len(P); R, A, free = setup(P, Q); pi, sig = cfg_data(P, Q) + for k in (1, 2, 3, 4): + r = realise(pi, sig, set(free), k=k) + if isinstance(r, dict): + res[nm] = {'k': k, 'P': [r[('p', t)] for t in range(v)], 'Q': [r[('l', s)] for s in range(v)]}; break + print(nm, v, len(free), 'GF(2^%d)' % res[nm]['k'] if nm in res else 'NONE') +json.dump(res, open(out + '/cr2_realisations.json', 'w')) diff --git a/research/char2-jets/scripts/t1.py b/research/char2-jets/scripts/t1.py new file mode 100644 index 0000000000..b76d2b6212 --- /dev/null +++ b/research/char2-jets/scripts/t1.py @@ -0,0 +1,19 @@ +import sys, time +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from satlib import enumerate_B +from cr2 import * +P,Q = load_cfg('tied_min.json'); R,A,free = setup(P,Q); pi,sig = cfg_data(P,Q) +print('free', len(free)) +for k in (1,2,3,4): + t=time.time(); r = realise(pi,sig,set(free),k=k); print('full pattern GF(2^%d):'%k, 'REAL' if isinstance(r,dict) else r, round(time.time()-t,1)) +opt = enumerate_B(P,Q,(4,4,4)); print(len(opt)) +res={} +for ent in opt: + r = None + for k in (1,2,3): + r = realise(pi,sig,set(ent),k=k) + if isinstance(r,dict): break + res.setdefault((len(ent), 'REAL k=%d'%k if isinstance(r,dict) else str(r)),0) + res[(len(ent), 'REAL k=%d'%k if isinstance(r,dict) else str(r))]+=1 +print(res) diff --git a/research/char2-jets/scripts/t10.py b/research/char2-jets/scripts/t10.py new file mode 100644 index 0000000000..d2bff1ad24 --- /dev/null +++ b/research/char2-jets/scripts/t10.py @@ -0,0 +1,15 @@ +import sys, random, collections +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from satlib import enumerate_B; from cr2 import cfg_data; from col import col_split +P,Q=load_cfg('tied_min.json'); R,A,free=setup(P,Q); pi,sig=cfg_data(P,Q); D=[pi[t]&sig[t] for t in range(12)] +c=collections.Counter() +for ent in enumerate_B(P,Q,(4,4,4)): + B=[[int(t==s) for s in range(12)] for t in range(12)] + for t,s in ent: B[t][s]=1 + ch=col_split(B,D); c[('opt', ch is not None, len(ent))]+=1 +random.seed(2) +for _ in range(200): + g=random.getrandbits(72); B=tomat(g,free,12); c[('rand', col_split(B,D) is not None)]+=1 +B=tomat((1<<72)-1,free,12); c[('full', col_split(B,D) is not None)]+=1 +print(sorted(c.items(), key=str)) diff --git a/research/char2-jets/scripts/t11.py b/research/char2-jets/scripts/t11.py new file mode 100644 index 0000000000..60793ce6fa --- /dev/null +++ b/research/char2-jets/scripts/t11.py @@ -0,0 +1,26 @@ +# Theorem B2 check: on no-wild configurations, phi preserves all block incidences; diagonal is 0 exactly on harmonic lines +import sys, random, collections +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +import kit; kit.BIN=os.environ.get('TTD_BIN') or PKG+'/c/bin' +from kit import *; from phi import *; from gen import randcfg, prim +random.seed(int(sys.argv[1])); st=collections.Counter() +def nowild_cfg(v,R): + while True: + P,Q=randcfg(v,R=R) + # kill wild: give every line a zero coordinate with prob, or every point + if random.random()<0.5: + Q=[prim([0 if j==random.randrange(3) and False else x for j,x in enumerate(q)]) for q in Q] + w,H=classify(P,Q) + if w==0: return P,Q +for it in range(int(sys.argv[2])): + v=random.randint(5,9); P,Q=nowild_cfg(v,random.choice([1,2,3])) + w,H=classify(P,Q); R,A,free=setup(P,Q) + phi=make_phi(); Pt=[[phi(x) for x in p] for p in P]; Qt=[[phi(x) for x in q] for q in Q] + assert all(dot2(Pt[t],Qt[s])==0 for (t,s) in free), 'incidence broken' + dz=[t for t in range(v) if dot2(Pt[t],Qt[t])==0] + st[('diag0==H', dz==H)]+=1 + if len(free)<=20: + best,ms=enum_raw(v,R,A,free,0) + st[('cost>=v-|H|', best>=v-len(H))]+=1; st[('H', len(H)>0, 'cost-v', best-v)]+=1 +print(sorted(st.items(), key=str)) diff --git a/research/char2-jets/scripts/t12.py b/research/char2-jets/scripts/t12.py new file mode 100644 index 0000000000..9c0fd68ffa --- /dev/null +++ b/research/char2-jets/scripts/t12.py @@ -0,0 +1,29 @@ +# first-order char-2 deformation of the phi-realisation on harmonic lines: rank of N1_HH = B o (phiP Y'^T + X' phiQ^T) on H +import sys, random, collections +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from satlib import enumerate_B; from phi import *; from gr import rank, mul, Q as FQ +def n1rank(B,Pt,Qt,H,pi,sig,trials=3,modes=('XY',)): + best=0 + for _ in range(trials): + X={t:[random.randrange(1,FQ) if j in pi[t] else 0 for j in range(3)] for t in H} + Y={t:[random.randrange(1,FQ) if j in sig[t] else 0 for j in range(3)] for t in H} + M=[[ (dot2(Pt[t],Y[s])^dot2(X[t],Qt[s])) if B[t][s] else 0 for s in H] for t in H] + best=max(best,rank(M)) + return best +if __name__=="__main__": + P,Q=load_cfg('tied_min.json'); v=12; R,A,free=setup(P,Q) + pi=[{j for j in range(3) if P[t][j]} for t in range(v)]; sig=[{j for j in range(3) if Q[t][j]} for t in range(v)] + w,H=classify(P,Q); print('wild',w,'H',H) + phi=make_phi(); Pt=[[phi(x) for x in p] for p in P]; Qt=[[phi(x) for x in q] for q in Q] + c=collections.Counter() + for ent in enumerate_B(P,Q,(4,4,4)): + B=[[int(t==s) for s in range(v)] for t in range(v)] + for t,s in ent: B[t][s]=1 + c[('opt',n1rank(B,Pt,Qt,H,pi,sig))]+=1 + random.seed(3) + for _ in range(300): + B=tomat(random.getrandbits(72),free,v); c[('rand',n1rank(B,Pt,Qt,H,pi,sig))]+=1 + c[('full',n1rank(tomat((1<<72)-1,free,v),Pt,Qt,H,pi,sig))]+=1 + print(sorted(c.items(),key=str)) + \ No newline at end of file diff --git a/research/char2-jets/scripts/t13.py b/research/char2-jets/scripts/t13.py new file mode 100644 index 0000000000..07fb4b7768 --- /dev/null +++ b/research/char2-jets/scripts/t13.py @@ -0,0 +1,29 @@ +# all-harmonic F2S configurations: q(t) = harmonic conjugate (w.r.t. the two sides through e_k) of the line e_k p(t). +# Test DEF: N1 = B o (phiP Y^T + X phiQ^T) nonsingular, on minimisers (exhaustive) and random B. +import sys, random, collections +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +import kit; kit.BIN=os.environ.get('TTD_BIN') or PKG+'/c/bin' +from kit import *; from phi import *; from gen import prim; from t12 import n1rank +def harm(p,k): + i,j=[x for x in range(3) if x!=k]; q=[0,0,0]; q[i]=p[j]; q[j]=p[i]; return prim(q) +seed=int(sys.argv[1]); random.seed(seed); st=collections.Counter(); bad=[] +for it in range(int(sys.argv[2])): + r=random.choice([2,3]); E=random.choice([1,2]) + pool=list({tuple(prim([1, random.choice([1,-1])*r**random.randint(0,E), random.choice([1,-1])*r**random.randint(0,E)])) for _ in range(random.randint(3,6))}) + v=random.randint(5,9); P=[];Q=[] + for _ in range(v): + p=list(random.choice(pool)); k=random.randrange(3); P.append(p); Q.append(harm(p,k)) + R,A,free=setup(P,Q) + if len(free)>24: continue + w,H=classify(P,Q); assert w==0 and len(H)==v + pi=[{j for j in range(3) if P[t][j]} for t in range(v)]; sig=[{j for j in range(3) if Q[t][j]} for t in range(v)] + phi=make_phi(); Pt=[[phi(x) for x in p] for p in P]; Qt=[[phi(x) for x in q] for q in Q] + best,ms=enum_raw(v,R,A,free,0) + st[('cost-v',best-v)]+=1 + ok=all(n1rank(tomat(g,free,v),Pt,Qt,list(range(v)),pi,sig,trials=4)==v for c,g in ms) + st[('DEF on minimisers',ok)]+=1 + rb=[n1rank(tomat(random.getrandbits(len(free)),free,v),Pt,Qt,list(range(v)),pi,sig,trials=4)==v for _ in range(30)] + st[('DEF on random B',all(rb))]+=1 + if not ok or not all(rb): bad.append((P,Q)) +print(seed, sorted(st.items(),key=str)); print('bad',bad[:3]) diff --git a/research/char2-jets/scripts/t14.py b/research/char2-jets/scripts/t14.py new file mode 100644 index 0000000000..cc25df5ad1 --- /dev/null +++ b/research/char2-jets/scripts/t14.py @@ -0,0 +1,24 @@ +# DEF on all sub-configurations of tied_min with f<=26: every minimiser (exhaustive) + 20 random B +import sys, random, collections, itertools +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +import kit; kit.BIN=os.environ.get('TTD_BIN') or PKG+'/c/bin' +from kit import *; from phi import *; from t12 import n1rank +random.seed(7) +P0,Q0=load_cfg('tied_min.json'); st=collections.Counter(); bad=[] +phi=make_phi() +for m in range(2,13): + for S in itertools.combinations(range(12),m): + P=[P0[i] for i in S]; Q=[Q0[i] for i in S]; v=m; R,A,free=setup(P,Q) + pi=[{j for j in range(3) if P[t][j]} for t in range(v)]; sig=[{j for j in range(3) if Q[t][j]} for t in range(v)] + Pt=[[phi(x) for x in p] for p in P]; Qt=[[phi(x) for x in q] for q in Q] + if len(free)<=24: + best,ms=enum_raw(v,R,A,free,0) + ok=all(n1rank(tomat(g,free,v),Pt,Qt,list(range(v)),pi,sig,trials=3)==v for c,g in ms) + st[(m,'tight' if best==v else 'slack','minimisers DEF',ok)]+=1 + if not ok: bad.append(S) + else: + ok=all(n1rank(tomat(random.getrandbits(len(free)),free,v),Pt,Qt,list(range(v)),pi,sig,trials=3)==v for _ in range(5)) + st[(m,'random-B DEF',ok)]+=1 + if not ok: bad.append(S) +print(sorted(st.items(),key=str)); print('bad',bad[:5]) diff --git a/research/char2-jets/scripts/t15.py b/research/char2-jets/scripts/t15.py new file mode 100644 index 0000000000..90c13afa68 --- /dev/null +++ b/research/char2-jets/scripts/t15.py @@ -0,0 +1,10 @@ +import sys +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from phi import *; from tangent import tangent_cr2 +for nm in sys.argv[1:]: + P,Q=load_cfg(nm); v=len(P); R,A,free=setup(P,Q) + pi=[{j for j in range(3) if P[t][j]} for t in range(v)]; sig=[{j for j in range(3) if Q[t][j]} for t in range(v)] + w,H=classify(P,Q); phi=make_phi(); Pt=[[phi(x) for x in p] for p in P]; Qt=[[phi(x) for x in q] for q in Q] + res,dim=tangent_cr2(Pt,Qt,pi,sig,free,H) + print(nm,'v',v,'wild',w,'|H|',len(H),'tangent dim',dim,'harmonic lines movable:',sum(res.values()),'/',len(H)) diff --git a/research/char2-jets/scripts/t16.py b/research/char2-jets/scripts/t16.py new file mode 100644 index 0000000000..cbcfe4d449 --- /dev/null +++ b/research/char2-jets/scripts/t16.py @@ -0,0 +1,27 @@ +import sys, itertools, collections, random +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from phi import *; from tangent import tangent_cr2; from gen import prim +def tcheck(P,Q): + v=len(P); R,A,free=setup(P,Q) + pi=[{j for j in range(3) if P[t][j]} for t in range(v)]; sig=[{j for j in range(3) if Q[t][j]} for t in range(v)] + w,H=classify(P,Q); phi=make_phi(); Pt=[[phi(x) for x in p] for p in P]; Qt=[[phi(x) for x in q] for q in Q] + res,dim=tangent_cr2(Pt,Qt,pi,sig,free,H); return w, len(H), all(res.values()) +st=collections.Counter() +P0,Q0=load_cfg('tied_min.json') +for m in range(1,13): + for S in itertools.combinations(range(12),m): + w,h,ok=tcheck([P0[i] for i in S],[Q0[i] for i in S]); st[('tied_min sub',ok)]+=1 +print(sorted(st.items(),key=str), flush=True) +def harm(p,k): + i,j=[x for x in range(3) if x!=k]; q=[0,0,0]; q[i]=p[j]; q[j]=p[i]; return prim(q) +random.seed(11); st=collections.Counter(); bad=[] +for it in range(1500): + r=random.choice([2,3,5]); E=random.choice([1,2,3]) + pool=list({tuple(prim([random.choice([1,-1])*r**random.randint(0,E), random.choice([1,-1])*r**random.randint(0,E), random.choice([1,-1])*r**random.randint(0,E)])) for _ in range(random.randint(3,8))}) + v=random.randint(4,14); P=[];Q=[] + for _ in range(v): + p=list(random.choice(pool)); k=random.randrange(3); P.append(p); Q.append(harm(p,k)) + w,h,ok=tcheck(P,Q); st[('harmonic F2S', ok)]+=1 + if not ok: bad.append((P,Q)) +print(sorted(st.items(),key=str)); print(bad[:2]) diff --git a/research/char2-jets/scripts/t17.py b/research/char2-jets/scripts/t17.py new file mode 100644 index 0000000000..094b9ebff1 --- /dev/null +++ b/research/char2-jets/scripts/t17.py @@ -0,0 +1,38 @@ +# adversarial-ish random search for no-wild configurations where a harmonic line cannot be moved at first order +import sys, random, collections +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from phi import *; from tangent import tangent_cr2; from gen import prim, dot +seed=int(sys.argv[1]); random.seed(seed); st=collections.Counter(); bad=[] +def rv(r,E,supp): + return prim([random.choice([1,-1])*r**random.randint(0,E) if j in supp else 0 for j in range(3)]) +for it in range(int(sys.argv[2])): + r=random.choice([2,3]); E=random.choice([0,1,2]) + pts=[rv(r,E,random.choice([{0,1,2},{0,1,2},{0,1},{0,2},{1,2}])) for _ in range(random.randint(3,7))] + # candidate lines: through two pool points, harmonic partners, and random two-support lines + from gen import cross + lines=[] + for _ in range(12): + a,b=random.sample(pts,2); q=prim(cross(a,b)) + if q: lines.append(q) + for p in pts: + for k in range(3): + i,j=[x for x in range(3) if x!=k] + if p[i] and p[j]: q=[0,0,0]; q[i]=p[j]; q[j]=p[i]; lines.append(prim(q)) + lines=[q for q in lines if sum(1 for x in q if x)<=2 or random.random()<0.3] + v=random.randint(5,12); P=[];Q=[] + for _ in range(200): + if len(P)>=v: break + p=random.choice(pts); q=random.choice(lines) + if dot(p,q)!=0: P.append(p); Q.append(q) + if len(P)<4: continue + w,H=classify(P,Q) + if w or not H: st['skip']+=1; continue + v=len(P); R,A,free=setup(P,Q) + pi=[{j for j in range(3) if P[t][j]} for t in range(v)]; sig=[{j for j in range(3) if Q[t][j]} for t in range(v)] + phi=make_phi(); Pt=[[phi(x) for x in p] for p in P]; Qt=[[phi(x) for x in q] for q in Q] + res,dim=tangent_cr2(Pt,Qt,pi,sig,free,H); ok=all(res.values()) + st[('nowild with H', ok)]+=1 + if not ok: bad.append((P,Q,[t for t in H if not res[t]])) +print(seed, sorted(st.items(),key=str)); +for b in bad[:3]: print(b) diff --git a/research/char2-jets/scripts/t18.py b/research/char2-jets/scripts/t18.py new file mode 100644 index 0000000000..e1269118e5 --- /dev/null +++ b/research/char2-jets/scripts/t18.py @@ -0,0 +1,17 @@ +import sys, json +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +import kit; kit.BIN=os.environ.get('TTD_BIN') or PKG+'/c/bin' +from kit import *; from cr2 import realise +bads=[([[1, 1, 1], [0, 1, 1], [1, 0, -1], [1, 1, 0], [1, 1, 1], [0, 1, 1], [1, 1, 0], [1, 1, 1], [1, 1, 1], [1, 0, -1], [1, 1, 1]], [[1, 0, 1], [0, 1, 1], [1, -1, 0], [0, 1, -1], [1, -1, -2], [1, 0, 1], [1, 1, 0], [1, -1, -2], [1, -1, 1], [1, -1, 0], [1, -1, 1]]), +([[1, 1, -1], [1, -1, 0], [1, -1, 0], [1, -1, 1], [1, -1, 0], [1, -1, 0], [1, 1, -1], [0, 1, -1], [1, 0, 1]], [[1, 0, -1], [0, 1, 1], [0, 1, -1], [1, -1, -1], [1, 0, -1], [1, -1, 0], [1, 1, 0], [1, 1, -1], [1, 1, 0]]), +([[1, 1, 1], [1, 1, 0], [1, 1, 1], [0, 1, 1], [1, 0, 1], [0, 1, -1], [1, 1, 0], [1, 1, 1], [0, 1, 1]], [[0, 1, 1], [1, 0, -1], [0, 1, 1], [1, 0, 1], [1, 0, 1], [1, -1, 0], [1, 0, -1], [1, -1, -1], [0, 1, 1]])] +for i,(P,Q) in enumerate(bads): + json.dump([P,Q], open('jf%d.json'%i,'w')) + v=len(P); R,A,free=setup(P,Q); pi=[{j for j in range(3) if P[t][j]} for t in range(v)]; sig=[{j for j in range(3) if Q[t][j]} for t in range(v)] + cr=None + for k in (1,2,3): + r=realise(pi,sig,set(free),k=k,limit=10**6) + if isinstance(r,dict): cr=k; break + best=enum_raw(v,R,A,free,0)[0] if len(free)<=28 else None + print(i,'v',v,'f',len(free),'fullCR2 over GF(2^%s)'%cr,'min cost',best) diff --git a/research/char2-jets/scripts/t19.py b/research/char2-jets/scripts/t19.py new file mode 100644 index 0000000000..e2967f55e1 --- /dev/null +++ b/research/char2-jets/scripts/t19.py @@ -0,0 +1,13 @@ +import sys, json +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from phi import *; from tangent import tangent_cr2 +for i in range(3): + P,Q=json.load(open(PKG+'/data/jf%d.json'%i)); v=len(P); R,A,free=setup(P,Q) + pi=[{j for j in range(3) if P[t][j]} for t in range(v)]; sig=[{j for j in range(3) if Q[t][j]} for t in range(v)] + Pt=[[1 if x else 0 for x in p] for p in P]; Qt=[[1 if x else 0 for x in q] for q in Q] + assert all(dot2(Pt[t],Qt[s])==0 for (t,s) in free) + H2=[t for t in range(v) if dot2(Pt[t],Qt[t])==0] + res,dim=tangent_cr2(Pt,Qt,pi,sig,free,H2) + w,H=classify(P,Q) + print('jf%d'%i,'harmonic',H,'zero diag under full collapse',H2,'movable',[t for t in H2 if res[t]],'tangent dim',dim) diff --git a/research/char2-jets/scripts/t2.py b/research/char2-jets/scripts/t2.py new file mode 100644 index 0000000000..1f24797913 --- /dev/null +++ b/research/char2-jets/scripts/t2.py @@ -0,0 +1,22 @@ +import sys, time, os, subprocess +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +import kit +kit.BIN = os.environ.get('TTD_BIN') or PKG+'/c/bin' +from kit import * +from cr2 import * +def cr2(pi,sig,ent): + for k in (1,2,3): + r = realise(pi,sig,set(ent),k=k,limit=2*10**5) + if isinstance(r,dict): return k + return 0 if r is None else -1 +names = sys.argv[1:] +for nm in names: + P,Q = load_cfg(nm); v=len(P) + best, ms, R, A, free = enum(P,Q,1) + pi,sig = cfg_data(P,Q) + out={} + for c,g in ms: + ent=[free[i] for i in range(len(free)) if g>>i&1] + key=(c, cr2(pi,sig,ent)); out[key]=out.get(key,0)+1 + print(nm, 'v',v,'f',len(free),'best',best, {k:out[k] for k in sorted(out)}) diff --git a/research/char2-jets/scripts/t20.py b/research/char2-jets/scripts/t20.py new file mode 100644 index 0000000000..9181601d72 --- /dev/null +++ b/research/char2-jets/scripts/t20.py @@ -0,0 +1,20 @@ +import sys, json, numpy as np +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from phi import classify; from jet2 import * +for i in range(3): + P,Q=json.load(open(PKG+'/data/jf%d.json'%i)); v=len(P); R,A,free=setup(P,Q); w,H=classify(P,Q) + an=analyse(P,Q,free,H); d=len(an['basis']) + E=an['E'] + depM=[quad_matrix(an,[E[k] for k in range(len(E)) if z>>k&1]) for z in an['deps']] + immM={t:quad_matrix(an,[(t,t)]+[E[k] for k in range(len(E)) if c>>k&1]) for t,c in an['imm'].items()} + print('jf%d v %d |E| %d dimV %d #deps %d immovable %s'%(i,v,len(E),d,len(an['deps']),list(an['imm'])), flush=True) + if d>26: print(' too big for F2 enumeration'); continue + found=None; cnt=0 + for us,vals in eval_quads(depM+list(immM.values()),d): + nd=len(depM); ok=np.ones(len(us),dtype=bool) + for k in range(nd): ok&=(vals[k]==0) + for k in range(nd,len(vals)): ok&=(vals[k]==1) + cnt+=int(ok.sum()) + if found is None and ok.any(): found=int(us[np.argmax(ok)]) + print(' F2 points with all solvability quadrics 0 and all immovable Q_t = 1:',cnt,'example u',found, flush=True) diff --git a/research/char2-jets/scripts/t21.py b/research/char2-jets/scripts/t21.py new file mode 100644 index 0000000000..c072606109 --- /dev/null +++ b/research/char2-jets/scripts/t21.py @@ -0,0 +1,25 @@ +# Is the order-2 diagonal Q_t of an immovable line in the F2-span of the solvability quadrics (as polynomials)? +import sys, json, numpy as np +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from phi import classify; from jet2 import * +def polyvec(M): + d=M.shape[0]; out=[] + for i in range(d): + for j in range(i,d): + out.append(int(M[i,i]) if i==j else int(M[i,j]^M[j,i])) + return int(''.join(map(str,out)),2) if out else 0 +def inspan(x, vecs): + piv=[] + for r in vecs: + for p in piv: r=min(r,r^p) + if r: piv.append(r); piv.sort(reverse=True) + for p in piv: x=min(x,x^p) + return x==0 +for i in range(3): + P,Q=json.load(open(PKG+'/data/jf%d.json'%i)); v=len(P); R,A,free=setup(P,Q); w,H=classify(P,Q) + an=analyse(P,Q,free,H); E=an['E'] + deps=[polyvec(quad_matrix(an,[E[k] for k in range(len(E)) if z>>k&1])) for z in an['deps']] + for t,c in an['imm'].items(): + q=polyvec(quad_matrix(an,[(t,t)]+[E[k] for k in range(len(E)) if c>>k&1])) + print('jf%d line %d: Q_t identically 0: %s; Q_t in span of solvability quadrics: %s'%(i,t,q==0,inspan(q,deps))) diff --git a/research/char2-jets/scripts/t22.py b/research/char2-jets/scripts/t22.py new file mode 100644 index 0000000000..0ff696a9dd --- /dev/null +++ b/research/char2-jets/scripts/t22.py @@ -0,0 +1,9 @@ +import sys, json, time +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from satlib import cost_leq +P,Q=json.load(open(PKG+'/data/jf0.json')); v=len(P); R,A,free=setup(P,Q) +for K in range(10, 20): + t=time.time(); B=cost_leq(P,Q,K) + print('jf0 cost<=%d: %s (%.0fs)'%(K,'SAT ranks %s'%blockranks(B,R,A) if B else 'UNSAT',time.time()-t), flush=True) + if B: json.dump(B,open('jf0_min.json','w')); break diff --git a/research/char2-jets/scripts/t23.py b/research/char2-jets/scripts/t23.py new file mode 100644 index 0000000000..e61898926e --- /dev/null +++ b/research/char2-jets/scripts/t23.py @@ -0,0 +1,16 @@ +# B-dependent first-order jet test (E = supp B) on all minimisers of jf1, jf2 +import sys, json, collections +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +import kit; kit.BIN=os.environ.get('TTD_BIN') or PKG+'/c/bin' +from kit import *; from phi import *; from tangent import tangent_cr2; from cr2 import realise +for i in (1,2): + P,Q=json.load(open(PKG+'/data/jf%d.json'%i)); v=len(P); R,A,free=setup(P,Q); w,H=classify(P,Q) + pi=[{j for j in range(3) if P[t][j]} for t in range(v)]; sig=[{j for j in range(3) if Q[t][j]} for t in range(v)] + Pt=[[1 if x else 0 for x in p] for p in P]; Qt=[[1 if x else 0 for x in q] for q in Q] + best,ms=enum_raw(v,R,A,free,0); c=collections.Counter() + for _,g in ms: + E=[free[k] for k in range(len(free)) if g>>k&1] + res,_=tangent_cr2(Pt,Qt,pi,sig,E,H); cr=isinstance(realise(pi,sig,set(E),k=1),dict) or isinstance(realise(pi,sig,set(E),k=2),dict) + c[('jet1',all(res.values()),'CR2',cr)]+=1 + print('jf%d min cost %d, %d minimisers:'%(i,best,len(ms)), dict(c)) diff --git a/research/char2-jets/scripts/t24.py b/research/char2-jets/scripts/t24.py new file mode 100644 index 0000000000..08ce84f01a --- /dev/null +++ b/research/char2-jets/scripts/t24.py @@ -0,0 +1,26 @@ +# configurations with a directed cycle of wild incidences: is the full pattern CR2 (order 0, any base)? +import sys, random, collections +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from cr2 import realise, cfg_data; from gen import randcfg +random.seed(4); st=collections.Counter() +def wildcyc(P,Q): + v=len(P); adj={t:[s for s in range(v) if s!=t and all(P[t][j] and Q[s][j] for j in range(3)) and sum(P[t][j]*Q[s][j] for j in range(3))==0] for t in range(v)} + col={} + def dfs(u): + col[u]=1 + for w in adj[u]: + if col.get(w)==1 or (w not in col and dfs(w)): return True + col[u]=2; return False + return any(t not in col and dfs(t) for t in range(v)) +n=0 +while n<300: + v=random.randint(6,12); P,Q=randcfg(v,R=random.choice([1,2,3]),pfix=0.0) + if not wildcyc(P,Q): continue + n+=1; R_,A_,free=setup(P,Q); pi,sig=cfg_data(P,Q); k=0 + for kk in (1,2,3): + r=realise(pi,sig,set(free),k=kk,limit=2*10**5) + if isinstance(r,dict): k=kk; break + if r=='timeout': k=-1; break + st[k]+=1 +print('wild-cycle configs: CR2 field GF(2^k) ->', dict(st)) diff --git a/research/char2-jets/scripts/t3.py b/research/char2-jets/scripts/t3.py new file mode 100644 index 0000000000..99e5ca7e33 --- /dev/null +++ b/research/char2-jets/scripts/t3.py @@ -0,0 +1,15 @@ +import sys, os +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from cr2 import * +for nm in sorted(os.listdir(PKG+'/data')): + try: P,Q = load_cfg(nm) + except Exception as e: continue + if not (isinstance(P[0],list) and isinstance(P[0][0], int)): continue + R,A,free = setup(P,Q); pi,sig = cfg_data(P,Q) + res=[] + for k in (1,2,3,4): + r = realise(pi,sig,set(free),k=k,limit=3*10**5) + res.append('R' if isinstance(r,dict) else ('-' if r is None else 'T')) + if res[-1]=='R': break + print(nm, len(P), len(free), res) diff --git a/research/char2-jets/scripts/t4.py b/research/char2-jets/scripts/t4.py new file mode 100644 index 0000000000..1700683075 --- /dev/null +++ b/research/char2-jets/scripts/t4.py @@ -0,0 +1,26 @@ +# tied_min sub-configurations: full-pattern CR2 status; for non-CR2 ones with f<=28, is some minimiser CR2? +import sys, itertools, collections +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +import kit; kit.BIN=os.environ.get('TTD_BIN') or PKG+'/c/bin' +from kit import *; from cr2 import * +P0,Q0 = load_cfg('tied_min.json'); v0=len(P0) +def iscr2(pi,sig,E,ks=(1,2,3)): + for k in ks: + r = realise(pi,sig,set(E),k=k,limit=2*10**5) + if isinstance(r,dict): return k + return 0 +stat=collections.Counter(); minimal=[]; nonlist=[] +noncr2=set() +for m in range(1,v0+1): + for S in itertools.combinations(range(v0),m): + if any(set(T)<=set(S) for T in minimal): + noncr2.add(S); stat[(m,'non(sup)')]+=1; continue + P=[P0[i] for i in S]; Q=[Q0[i] for i in S]; R,A,free=setup(P,Q); pi,sig=cfg_data(P,Q) + k=iscr2(pi,sig,free) + if k: stat[(m,'cr2')]+=1 + else: + stat[(m,'non')]+=1; minimal.append(S); noncr2.add(S) +print(sorted(stat.items())) +print('minimal non-CR2 subsets:', minimal) +import json; json.dump(sorted(noncr2), open('tm_noncr2.json','w')) diff --git a/research/char2-jets/scripts/t5.py b/research/char2-jets/scripts/t5.py new file mode 100644 index 0000000000..679b744d26 --- /dev/null +++ b/research/char2-jets/scripts/t5.py @@ -0,0 +1,19 @@ +import sys, json, collections +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +import kit; kit.BIN=os.environ.get('TTD_BIN') or PKG+'/c/bin' +from kit import *; from cr2 import * +P0,Q0 = load_cfg('tied_min.json') +non = json.load(open(PKG+'/data/tm_noncr2.json')) +stat=collections.Counter(); bad=[] +for S in non: + P=[P0[i] for i in S]; Q=[Q0[i] for i in S]; R,A,free=setup(P,Q) + if len(free)>26: stat[(len(S),'skip f=%d'%len(free))]+=1; continue + pi,sig=cfg_data(P,Q); best,ms=enum_raw(len(S),R,A,free,0) + ncr=0 + for c,g in ms: + E=[free[i] for i in range(len(free)) if g>>i&1] + if isinstance(realise(pi,sig,set(E),k=1),dict) or isinstance(realise(pi,sig,set(E),k=2),dict): ncr+=1 + stat[(len(S), best-len(S), 'someCR2' if ncr else 'NONE', ncr==len(ms))]+=1 + if not ncr: bad.append(S) +print(sorted(stat.items(), key=str)); print('bad', bad[:10]) diff --git a/research/char2-jets/scripts/t6.py b/research/char2-jets/scripts/t6.py new file mode 100644 index 0000000000..f64c615968 --- /dev/null +++ b/research/char2-jets/scripts/t6.py @@ -0,0 +1,22 @@ +# tied_min: all B with cost <= 13 (rank caps), classify CR2 (GF2/GF4) +import sys, json, collections, itertools +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from satlib import enumerate_B; from cr2 import * +P,Q=load_cfg('tied_min.json'); R,A,free=setup(P,Q); pi,sig=cfg_data(P,Q) +seen={} +for caps in set(itertools.permutations((4,4,5)))|set(itertools.permutations((3,5,5)))|set(itertools.permutations((3,4,6))): + for ent in enumerate_B(P,Q,caps): + seen[tuple(ent)]=1 +print('B with cost<=13 (via caps):', len(seen)) +stat=collections.Counter(); non=[] +for ent in seen: + B=[[int(t==s) for s in range(12)] for t in range(12)] + for t,s in ent: B[t][s]=1 + c=sum(blockranks(B,R,A)) + k=0 + for kk in (1,2,3): + if isinstance(realise(pi,sig,set(ent),k=kk,limit=10**5),dict): k=kk; break + stat[(c,k)]+=1 + if not k: non.append(ent) +print(sorted(stat.items())); json.dump(non, open('tm_c13_noncr2.json','w')) diff --git a/research/char2-jets/scripts/t7.py b/research/char2-jets/scripts/t7.py new file mode 100644 index 0000000000..43bd21d75f --- /dev/null +++ b/research/char2-jets/scripts/t7.py @@ -0,0 +1,13 @@ +import sys, random, collections +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from cr2 import cfg_data; from gr import gr +random.seed(1) +for nm in ['tied_min.json','cex_min_1.json','gad.json','aff14.json','cex_joint_v7.json']: + P,Q=load_cfg(nm); v=len(P); R,A,free=setup(P,Q); pi,sig=cfg_data(P,Q) + c=collections.Counter() + for dens in (0.1,0.3,0.6,1.0): + for _ in range(100): + g=sum(1<22 or len(free)<4: continue + pi,sig=cfg_data(P,Q) + best,ms=enum_raw(v,R_,A_,free,2) + fullcr2 = isinstance(realise(pi,sig,set(free),k=1,limit=10**5),dict) or isinstance(realise(pi,sig,set(free),k=2,limit=10**5),dict) + stat[('cfg', best-v, 'fullCR2' if fullcr2 else 'NONCR2')]+=1 + for c,g in ms: + B=tomat(g,free,v); r=gr(B,pi,sig,trials=4) + if r>s&1 and c in sig[s]) for t in range(v) if S>>t&1 and c in pi[t]] + val+=rk(rows) + best=min(best,val) + return best +random.seed(5); bad=0; dist={} +for it in range(300): + v=random.randint(3,6) + pi=[set(random.sample(range(3),random.randint(1,3))) for _ in range(v)] + sig=[set(random.sample(range(3),random.randint(1,3))) for _ in range(v)] + B=[[int(t==s or random.random()<0.5) for s in range(v)] for t in range(v)] + g=gr(B,pi,sig,trials=6); m=minmax(B,pi,sig) + dist[(g-v,m-v)]=dist.get((g-v,m-v),0)+1 + if g!=m: bad+=1 +print('mismatch',bad, sorted(dist.items())) diff --git a/research/char2-jets/scripts/tied_min_jet_cert.py b/research/char2-jets/scripts/tied_min_jet_cert.py new file mode 100644 index 0000000000..301341c86f --- /dev/null +++ b/research/char2-jets/scripts/tied_min_jet_cert.py @@ -0,0 +1,44 @@ +"""Theorem T' certificate, built from the hand formula (no nullspace, no random z): cost(tied_min) >= 12 for every B. +phi(tied_min) = Fano collapse over F2 (all entries +-1 -> 1). Choose h = 1: G_k(side of M_k through point a0) = 0, other side = 1. +f_k(t) = G_k(side_k(p(t))); X(t) = (f1, f0, 0) so X.l0 = f0, X.l1 = f1, X.l2 = f0+f1 = f2; g(s) = G_k(side carried by q(s)), Y(s) = g in one +coordinate of sigma(s). Checks (J1) on all 72 incidences and (J2) on all 12 lines exactly over F2; then N = B o (P~ Q~^T) with +P~ = phiP + eps X, Q~ = phiQ + eps Y at a random eps in GF(2^16) (a specialisation, so rank can only drop) has rank 12 for the 217 +optima, the full B and 300 random B.""" +import sys, random +import os; PKG=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PKG+'/lib'); sys.path.insert(0, PKG+'/scripts') +from kit import *; from satlib import enumerate_B; from gr import mul, rank, Q as FQ +P,Q=load_cfg('tied_min.json'); v=12; R,A,free=setup(P,Q) +cls=[next(j for j in range(3) if q[j]==0) for q in Q] +a0=P[0] +def side(k,x): # the class-k line (as a primitive vector, up to sign) through e_k and x + i,j=[y for y in range(3) if y!=k]; q=[0,0,0]; q[i]=x[j]; q[j]=-x[i]; return q +def same(q1,q2): return all(q1[i]*q2[j]==q1[j]*q2[i] for i in range(3) for j in range(3)) +G=lambda k,q: 0 if same(q, side(k,a0)) else 1 +f=[[G(k,side(k,P[t])) for k in range(3)] for t in range(v)] +assert all((f[t][0]^f[t][1]^f[t][2])==0 for t in range(v)), 'sum-zero fails' +X=[[f[t][1],f[t][0],0] for t in range(v)] +g=[G(cls[s],Q[s]) for s in range(v)] +Y=[] +for s in range(v): + y=[0,0,0]; y[next(j for j in range(3) if j!=cls[s])]=g[s]; Y.append(y) +phP=[[1 if x else 0 for x in p] for p in P]; phQ=[[1 if x else 0 for x in q] for q in Q] +d2=lambda a,b: (a[0]&b[0])^(a[1]&b[1])^(a[2]&b[2]) +assert all(d2(phP[t],phQ[s])==0 for (t,s) in free), 'order-0 incidence' +assert all(d2(phP[t],phQ[t])==0 for t in range(v)), 'all harmonic' +assert all((d2(phP[t],Y[s])^d2(X[t],phQ[s]))==0 for (t,s) in free), '(J1) fails' +assert all((d2(phP[t],Y[t])^d2(X[t],phQ[t]))==1 for t in range(v)), '(J2) fails' +assert all(all(X[t][j]==0 for j in range(3) if P[t][j]==0) and all(Y[t][j]==0 for j in range(3) if Q[t][j]==0) for t in range(v)) +print('(J1) on all %d incidences and (J2) on all 12 lines hold exactly over F2' % len(free)) +random.seed(1); e=random.randrange(2,FQ) +Pt=[[phP[t][j]^mul(e,X[t][j]) for j in range(3)] for t in range(v)]; Qt=[[phQ[s][j]^mul(e,Y[s][j]) for j in range(3)] for s in range(v)] +dd=lambda a,b: mul(a[0],b[0])^mul(a[1],b[1])^mul(a[2],b[2]) +M=[[dd(Pt[t],Qt[s]) for s in range(v)] for t in range(v)] +Bs=[] +for ent in enumerate_B(P,Q,(4,4,4)): + B=[[int(t==s) for s in range(v)] for t in range(v)] + for t,s in ent: B[t][s]=1 + Bs.append(B) +Bs.append(tomat((1<=v + print(nm,'OK: N diagonal nonzero for 200 random B; cost>=v on each') diff --git a/research/char2-jets/verify.sh b/research/char2-jets/verify.sh new file mode 100755 index 0000000000..5a348a10f6 --- /dev/null +++ b/research/char2-jets/verify.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# One-command verification of research/char2-jets (no kappa claim). Step 0 checks the package against MANIFEST.sha256 and stops hard on any mismatch. +# Then five check groups run one after the other in a single process chain (python3 with numpy and python-sat, and a C compiler for one small enumerator): +# a Theorem T': the first-order jet for tied_min (exact over F2) and the 518 stored matrices B b Lemma CR2: stored realisations of 21 configurations; tied_min and the 44 atoms +# c Corollary J on all 4095 sub-configurations of tied_min and 1500 all-harmonic configurations d Lemma A (T = 2) and spot checks of Theorem B2 +# e jetfail jf0/jf1/jf2: first-order and order-2 failure, exact costs +# One PASS/FAIL line per assertion; exit status 0 only if every assertion passes. The Lean project (lean/) is NOT needed; with LEAN=1 and `lake` on PATH the Lean build is run as an extra last step. +# usage: bash verify.sh [/fresh/output/dir] (inside a checkout or `git archive` of the repository; nothing outside the package is read) +# env: PYTHON (default python3), CC (default cc), LEAN=1 (optional Lean build; needs Mathlib at the revision pinned in lean/lake-manifest.json) +# Not re-run here (RECORDED in the README, scripts included): the 217 SAT-enumerated optima of tied_min, the 1889/1892 random run, the min-max of the split bound, the 300 wild-cycle +# configurations, the CR2 status of the 192 jf1 minimisers, the minimum cost 8 of the seven-line atoms. +set -uo pipefail +HERE=$(cd "$(dirname "$0")" && pwd) +OUT=${1:-$(mktemp -d "${TMPDIR:-/tmp}/char2-jets.XXXXXX")} +mkdir -p "$OUT"; OUT=$(cd "$OUT" && pwd) +case "$OUT/" in "$HERE"/*) echo "output dir must be outside the package"; exit 2;; esac +PY="${PYTHON:-python3}"; CC="${CC:-cc}"; export PYTHONDONTWRITEBYTECODE=1 +T0=$SECONDS; FAILED=0 +echo "== 0. manifest" +if ! "$PY" -B "$HERE/checks/provenance.py" | tee "$OUT/provenance.log" | sed 's/^/ /' || grep -q '^FAIL' "$OUT/provenance.log" \ + || [ "$(grep -c '^PASS' "$OUT/provenance.log")" != 1 ]; then + echo "step 0 FAILED"; exit 1 +fi +R="$OUT/tree"; mkdir -p "$R/bin" "$OUT/logs" +cp -R "$HERE/checks" "$HERE/lib" "$HERE/data" "$HERE/c" "$R/" +export TTD_BIN="$R/bin" +echo "== compile c/enumall.c" +if ! $CC -O2 -o "$R/bin/enumall" "$R/c/enumall.c" 2> "$OUT/logs/cc.log"; then echo "FAIL compile enumall"; cat "$OUT/logs/cc.log"; exit 1; fi +run() { # name, script + echo "== $1" + ( cd "$OUT" && "$PY" -B "$R/checks/$2" ) 2>&1 | tee "$OUT/logs/$2.log" | sed 's/^/ /' + rc=${PIPESTATUS[0]} + if [ "$rc" != 0 ] || grep -q '^FAIL' "$OUT/logs/$2.log"; then FAILED=$((FAILED+1)); fi +} +run "a. Theorem T' (cost(tied_min) >= 12 by a first-order jet)" a_tprime.py +run "b. Lemma CR2: stored realisations, tied_min, atoms" b_cr2.py +run "c. Corollary J (first-order jet test)" c_jets.py +run "d. Lemma A (T = 2) and Theorem B2 spot checks" d_lemmaA_B2.py +run "e. jetfail jf0..2" e_jetfail.py +if [ "${LEAN:-0}" = 1 ]; then + echo "== f. Lean build (optional)" + if command -v lake >/dev/null 2>&1; then + L="$OUT/lean"; rm -rf "$L"; cp -R "$HERE/lean" "$L" + if ( cd "$L" && LEAN_NUM_THREADS=4 lake build ) > "$OUT/logs/lean.log" 2>&1; then echo " PASS lake build (DecoderDuality)"; else echo " FAIL lake build, see $OUT/logs/lean.log"; FAILED=$((FAILED+1)); fi + else echo " SKIP: LEAN=1 but lake not found"; fi +fi +PASSN=$(cat "$OUT"/logs/*.py.log | grep -c '^PASS'); FAILN=$(cat "$OUT"/logs/*.py.log | grep -c '^FAIL') +echo "== summary: $PASSN PASS, $FAILN FAIL line(s), $((SECONDS-T0))s" +if [ "$FAILED" = 0 ]; then echo "ALL CHECKS PASSED"; exit 0; else echo "SOME CHECKS FAILED"; exit 1; fi