From 6ef2168ac90d42926bceb7ac9b2e029463800c76 Mon Sep 17 00:00:00 2001 From: Chafik Boukhalfa Date: Tue, 13 Oct 2026 20:52:17 +0400 Subject: [PATCH] Prove averaged cyclotomic heights and quadratic-log precision --- .../workflows/averaged-cyclotomic-height.yml | 43 +++ .../LINUX314-MATH.json.gz | Bin 0 -> 53705 bytes .../LINUX314-PACKAGE.json | 66 +++++ .../LINUX314-PLATFORM.json | 11 + .../LINUX314-TERMINAL.json | 6 + .../LINUX314.log.txt | 40 +++ .../MACOS311-MATH.json.gz | Bin 0 -> 53705 bytes .../MACOS311-PACKAGE.json | 66 +++++ .../MACOS311-PLATFORM.json | 11 + .../MACOS311-TERMINAL.json | 6 + .../MACOS311.log.txt | 40 +++ .../README.md | 38 +++ .../REPOSITORY-CHECKS.log.txt | 12 + .../SOURCE-GIT-CHECK.json | 89 ++++++ .../VALIDATION.json | 29 ++ .../EXPECTED.json.gz | Bin 0 -> 53705 bytes .../averaged-cyclotomic-height/MANIFEST.json | 27 ++ research/averaged-cyclotomic-height/NOTICE.md | 48 ++++ research/averaged-cyclotomic-height/PROOF.md | 251 ++++++++++++++++ research/averaged-cyclotomic-height/README.md | 56 ++++ .../SOURCE-PINS.json | 90 ++++++ .../averaged-cyclotomic-height/budgets.py | 64 +++++ .../interval_check.py | 203 +++++++++++++ .../requirements.txt | 2 + .../averaged-cyclotomic-height/resultants.py | 80 ++++++ .../test_package.py | 127 +++++++++ .../vendor/pr621/NOTICE.md | 21 ++ .../vendor/pr621/PROOF.md | 212 ++++++++++++++ .../vendor/pr621/independent_verify.py | 141 +++++++++ .../vendor/pr621/verify.py | 229 +++++++++++++++ .../vendor/pr628/NOTICE.md | 24 ++ .../vendor/pr628/PROOF.md | 269 ++++++++++++++++++ .../vendor/pr628/interval_kernel.py | 61 ++++ .../vendor/pr862/NOTICE.md | 31 ++ .../vendor/pr862/PROOF.md | 259 +++++++++++++++++ .../vendor/pr977/NOTICE.md | 40 +++ .../vendor/pr977/PROOF.md | 238 ++++++++++++++++ .../vendor/pr977/cubic.py | 62 ++++ research/averaged-cyclotomic-height/verify.py | 114 ++++++++ 39 files changed, 3106 insertions(+) create mode 100644 .github/workflows/averaged-cyclotomic-height.yml create mode 100644 research/averaged-cyclotomic-height-validation/LINUX314-MATH.json.gz create mode 100644 research/averaged-cyclotomic-height-validation/LINUX314-PACKAGE.json create mode 100644 research/averaged-cyclotomic-height-validation/LINUX314-PLATFORM.json create mode 100644 research/averaged-cyclotomic-height-validation/LINUX314-TERMINAL.json create mode 100644 research/averaged-cyclotomic-height-validation/LINUX314.log.txt create mode 100644 research/averaged-cyclotomic-height-validation/MACOS311-MATH.json.gz create mode 100644 research/averaged-cyclotomic-height-validation/MACOS311-PACKAGE.json create mode 100644 research/averaged-cyclotomic-height-validation/MACOS311-PLATFORM.json create mode 100644 research/averaged-cyclotomic-height-validation/MACOS311-TERMINAL.json create mode 100644 research/averaged-cyclotomic-height-validation/MACOS311.log.txt create mode 100644 research/averaged-cyclotomic-height-validation/README.md create mode 100644 research/averaged-cyclotomic-height-validation/REPOSITORY-CHECKS.log.txt create mode 100644 research/averaged-cyclotomic-height-validation/SOURCE-GIT-CHECK.json create mode 100644 research/averaged-cyclotomic-height-validation/VALIDATION.json create mode 100644 research/averaged-cyclotomic-height/EXPECTED.json.gz create mode 100644 research/averaged-cyclotomic-height/MANIFEST.json create mode 100644 research/averaged-cyclotomic-height/NOTICE.md create mode 100644 research/averaged-cyclotomic-height/PROOF.md create mode 100644 research/averaged-cyclotomic-height/README.md create mode 100644 research/averaged-cyclotomic-height/SOURCE-PINS.json create mode 100644 research/averaged-cyclotomic-height/budgets.py create mode 100644 research/averaged-cyclotomic-height/interval_check.py create mode 100644 research/averaged-cyclotomic-height/requirements.txt create mode 100644 research/averaged-cyclotomic-height/resultants.py create mode 100644 research/averaged-cyclotomic-height/test_package.py create mode 100644 research/averaged-cyclotomic-height/vendor/pr621/NOTICE.md create mode 100644 research/averaged-cyclotomic-height/vendor/pr621/PROOF.md create mode 100644 research/averaged-cyclotomic-height/vendor/pr621/independent_verify.py create mode 100644 research/averaged-cyclotomic-height/vendor/pr621/verify.py create mode 100644 research/averaged-cyclotomic-height/vendor/pr628/NOTICE.md create mode 100644 research/averaged-cyclotomic-height/vendor/pr628/PROOF.md create mode 100644 research/averaged-cyclotomic-height/vendor/pr628/interval_kernel.py create mode 100644 research/averaged-cyclotomic-height/vendor/pr862/NOTICE.md create mode 100644 research/averaged-cyclotomic-height/vendor/pr862/PROOF.md create mode 100644 research/averaged-cyclotomic-height/vendor/pr977/NOTICE.md create mode 100644 research/averaged-cyclotomic-height/vendor/pr977/PROOF.md create mode 100644 research/averaged-cyclotomic-height/vendor/pr977/cubic.py create mode 100644 research/averaged-cyclotomic-height/verify.py diff --git a/.github/workflows/averaged-cyclotomic-height.yml b/.github/workflows/averaged-cyclotomic-height.yml new file mode 100644 index 0000000000..c34148c6e2 --- /dev/null +++ b/.github/workflows/averaged-cyclotomic-height.yml @@ -0,0 +1,43 @@ +name: Averaged cyclotomic height + +on: + workflow_dispatch: + pull_request: + paths: + - 'research/averaged-cyclotomic-height/**' + - '.github/workflows/averaged-cyclotomic-height.yml' + push: + branches: ['codex/averaged-cyclotomic-height-20261013'] + paths: + - 'research/averaged-cyclotomic-height/**' + - '.github/workflows/averaged-cyclotomic-height.yml' + +permissions: + contents: read + +jobs: + verify: + runs-on: ubuntu-latest + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + python: ['3.11', '3.14'] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + - name: Install exact-algebra dependency + run: python -m pip install -r research/averaged-cyclotomic-height/requirements.txt + - name: Rational intervals, exact resultants and integer budgets + run: python -I -O -B research/averaged-cyclotomic-height/verify.py --out /tmp/averaged-height-math.json + - name: Package rejection controls and full read-only relocation + run: python -I -O -B research/averaged-cyclotomic-height/test_package.py --out /tmp/averaged-height-package.json + - uses: actions/upload-artifact@v4 + if: always() + with: + name: averaged-height-python-${{ matrix.python }} + path: | + /tmp/averaged-height-math.json + /tmp/averaged-height-package.json diff --git a/research/averaged-cyclotomic-height-validation/LINUX314-MATH.json.gz b/research/averaged-cyclotomic-height-validation/LINUX314-MATH.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..35906824df9b700c19434057e80a2f948638bbea GIT binary patch literal 53705 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 O@&5yJFu(+fkp=)gWRJlB literal 0 HcmV?d00001 diff --git a/research/averaged-cyclotomic-height-validation/LINUX314-PACKAGE.json b/research/averaged-cyclotomic-height-validation/LINUX314-PACKAGE.json new file mode 100644 index 0000000000..838a0a043a --- /dev/null +++ b/research/averaged-cyclotomic-height-validation/LINUX314-PACKAGE.json @@ -0,0 +1,66 @@ +{ + "controls": [ + { + "name": "missing manifest", + "rejected": true, + "terminal": "ValueError: missing package manifest" + }, + { + "name": "altered implementation", + "rejected": true, + "terminal": "ValueError: package hash: budgets.py" + }, + { + "name": "extra file", + "rejected": true, + "terminal": "ValueError: package file coverage" + }, + { + "name": "missing source", + "rejected": true, + "terminal": "ValueError: package file coverage" + }, + { + "name": "source hash independent of manifest", + "rejected": true, + "terminal": "ValueError: source SHA256: vendor/pr621/PROOF.md" + }, + { + "name": "source Git object independent of manifest", + "rejected": true, + "terminal": "ValueError: source Git blob: vendor/pr621/PROOF.md" + }, + { + "name": "duplicate manifest key", + "rejected": true, + "terminal": "ValueError: duplicate JSON key: files" + }, + { + "name": "symlink injection", + "rejected": true, + "terminal": "ValueError: package symlink" + }, + { + "name": "preloaded module substitution", + "rejected": true, + "terminal": "ValueError: local module binding: budgets" + }, + { + "name": "false receipt boolean integer confusion", + "rejected": true, + "terminal": "ValueError: mathematical receipt mismatch" + }, + { + "name": "existing output preserved", + "rejected": true + }, + { + "name": "full read-only isolated optimized relocation", + "passed": true, + "receipt_sha256": "b25ae109654d2e3ac16e6348c982b86d8c07fca80d8cff600205511b9d2617bf" + } + ], + "full_readonly_replay": true, + "rejected": 11, + "status": "PASS_AVERAGED_HEIGHT_PACKAGE" +} diff --git a/research/averaged-cyclotomic-height-validation/LINUX314-PLATFORM.json b/research/averaged-cyclotomic-height-validation/LINUX314-PLATFORM.json new file mode 100644 index 0000000000..163297a4b0 --- /dev/null +++ b/research/averaged-cyclotomic-height-validation/LINUX314-PLATFORM.json @@ -0,0 +1,11 @@ +{ + "bytecode_disabled": true, + "isolated": true, + "machine": "aarch64", + "manifest_sha256": "7844dd0039723d9a955a2d0961ff1cb0f710f21277c0b2905577ad7b2b5c2f2a", + "mpmath": "1.3.0", + "optimized": true, + "platform": "Linux-6.17.0-1032-nvidia-aarch64-with-glibc2.39", + "python": "3.14.8", + "sympy": "1.14.0" +} diff --git a/research/averaged-cyclotomic-height-validation/LINUX314-TERMINAL.json b/research/averaged-cyclotomic-height-validation/LINUX314-TERMINAL.json new file mode 100644 index 0000000000..a2c152e250 --- /dev/null +++ b/research/averaged-cyclotomic-height-validation/LINUX314-TERMINAL.json @@ -0,0 +1,6 @@ +{ + "full_package_controls": true, + "manifest_sha256": "7844dd0039723d9a955a2d0961ff1cb0f710f21277c0b2905577ad7b2b5c2f2a", + "math_sha256": "b25ae109654d2e3ac16e6348c982b86d8c07fca80d8cff600205511b9d2617bf", + "status": "PASS_FROZEN_AVERAGED_HEIGHT_PACKAGE" +} diff --git a/research/averaged-cyclotomic-height-validation/LINUX314.log.txt b/research/averaged-cyclotomic-height-validation/LINUX314.log.txt new file mode 100644 index 0000000000..875d8b38ae --- /dev/null +++ b/research/averaged-cyclotomic-height-validation/LINUX314.log.txt @@ -0,0 +1,40 @@ +PASS 752 integer budgets, exact logarithm enclosure and dyadic polynomial +3 PASS rational interval enclosures +4 PASS rational interval enclosures +5 PASS rational interval enclosures +7 PASS rational interval enclosures +8 PASS rational interval enclosures +9 PASS rational interval enclosures +11 PASS rational interval enclosures +13 PASS rational interval enclosures +16 PASS rational interval enclosures +17 PASS rational interval enclosures +19 PASS rational interval enclosures +23 PASS rational interval enclosures +25 PASS rational interval enclosures +27 PASS rational interval enclosures +29 PASS rational interval enclosures +31 PASS rational interval enclosures +32 PASS rational interval enclosures +3 PASS independent exact resultant +4 PASS independent exact resultant +5 PASS independent exact resultant +7 PASS independent exact resultant +8 PASS independent exact resultant +9 PASS independent exact resultant +PASS_AVERAGED_CYCLOTOMIC_HEIGHT interval_radices=17 exact_resultants=6 budgets=752 kappa=unchanged +PASS package control missing manifest +PASS package control altered implementation +PASS package control extra file +PASS package control missing source +PASS package control source hash independent of manifest +PASS package control source Git object independent of manifest +PASS package control duplicate manifest key +PASS package control symlink injection +PASS package control preloaded module substitution +PASS package control false receipt boolean integer confusion +PASS package control existing output preserved +PASS full read-only isolated optimized relocation +PASS_AVERAGED_HEIGHT_PACKAGE rejected=11 full_readonly_replay=True +PASS_AVERAGED_HEIGHT_BINDINGS sources=12 +PASS_FROZEN_AVERAGED_HEIGHT_PACKAGE diff --git a/research/averaged-cyclotomic-height-validation/MACOS311-MATH.json.gz b/research/averaged-cyclotomic-height-validation/MACOS311-MATH.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..35906824df9b700c19434057e80a2f948638bbea GIT binary patch literal 53705 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 O@&5yJFu(+fkp=)gWRJlB literal 0 HcmV?d00001 diff --git a/research/averaged-cyclotomic-height-validation/MACOS311-PACKAGE.json b/research/averaged-cyclotomic-height-validation/MACOS311-PACKAGE.json new file mode 100644 index 0000000000..838a0a043a --- /dev/null +++ b/research/averaged-cyclotomic-height-validation/MACOS311-PACKAGE.json @@ -0,0 +1,66 @@ +{ + "controls": [ + { + "name": "missing manifest", + "rejected": true, + "terminal": "ValueError: missing package manifest" + }, + { + "name": "altered implementation", + "rejected": true, + "terminal": "ValueError: package hash: budgets.py" + }, + { + "name": "extra file", + "rejected": true, + "terminal": "ValueError: package file coverage" + }, + { + "name": "missing source", + "rejected": true, + "terminal": "ValueError: package file coverage" + }, + { + "name": "source hash independent of manifest", + "rejected": true, + "terminal": "ValueError: source SHA256: vendor/pr621/PROOF.md" + }, + { + "name": "source Git object independent of manifest", + "rejected": true, + "terminal": "ValueError: source Git blob: vendor/pr621/PROOF.md" + }, + { + "name": "duplicate manifest key", + "rejected": true, + "terminal": "ValueError: duplicate JSON key: files" + }, + { + "name": "symlink injection", + "rejected": true, + "terminal": "ValueError: package symlink" + }, + { + "name": "preloaded module substitution", + "rejected": true, + "terminal": "ValueError: local module binding: budgets" + }, + { + "name": "false receipt boolean integer confusion", + "rejected": true, + "terminal": "ValueError: mathematical receipt mismatch" + }, + { + "name": "existing output preserved", + "rejected": true + }, + { + "name": "full read-only isolated optimized relocation", + "passed": true, + "receipt_sha256": "b25ae109654d2e3ac16e6348c982b86d8c07fca80d8cff600205511b9d2617bf" + } + ], + "full_readonly_replay": true, + "rejected": 11, + "status": "PASS_AVERAGED_HEIGHT_PACKAGE" +} diff --git a/research/averaged-cyclotomic-height-validation/MACOS311-PLATFORM.json b/research/averaged-cyclotomic-height-validation/MACOS311-PLATFORM.json new file mode 100644 index 0000000000..8839b7ab18 --- /dev/null +++ b/research/averaged-cyclotomic-height-validation/MACOS311-PLATFORM.json @@ -0,0 +1,11 @@ +{ + "bytecode_disabled": true, + "isolated": true, + "machine": "arm64", + "manifest_sha256": "7844dd0039723d9a955a2d0961ff1cb0f710f21277c0b2905577ad7b2b5c2f2a", + "mpmath": "1.3.0", + "optimized": true, + "platform": "macOS-27.0.1-arm64-arm-64bit", + "python": "3.11.15", + "sympy": "1.14.0" +} diff --git a/research/averaged-cyclotomic-height-validation/MACOS311-TERMINAL.json b/research/averaged-cyclotomic-height-validation/MACOS311-TERMINAL.json new file mode 100644 index 0000000000..a2c152e250 --- /dev/null +++ b/research/averaged-cyclotomic-height-validation/MACOS311-TERMINAL.json @@ -0,0 +1,6 @@ +{ + "full_package_controls": true, + "manifest_sha256": "7844dd0039723d9a955a2d0961ff1cb0f710f21277c0b2905577ad7b2b5c2f2a", + "math_sha256": "b25ae109654d2e3ac16e6348c982b86d8c07fca80d8cff600205511b9d2617bf", + "status": "PASS_FROZEN_AVERAGED_HEIGHT_PACKAGE" +} diff --git a/research/averaged-cyclotomic-height-validation/MACOS311.log.txt b/research/averaged-cyclotomic-height-validation/MACOS311.log.txt new file mode 100644 index 0000000000..875d8b38ae --- /dev/null +++ b/research/averaged-cyclotomic-height-validation/MACOS311.log.txt @@ -0,0 +1,40 @@ +PASS 752 integer budgets, exact logarithm enclosure and dyadic polynomial +3 PASS rational interval enclosures +4 PASS rational interval enclosures +5 PASS rational interval enclosures +7 PASS rational interval enclosures +8 PASS rational interval enclosures +9 PASS rational interval enclosures +11 PASS rational interval enclosures +13 PASS rational interval enclosures +16 PASS rational interval enclosures +17 PASS rational interval enclosures +19 PASS rational interval enclosures +23 PASS rational interval enclosures +25 PASS rational interval enclosures +27 PASS rational interval enclosures +29 PASS rational interval enclosures +31 PASS rational interval enclosures +32 PASS rational interval enclosures +3 PASS independent exact resultant +4 PASS independent exact resultant +5 PASS independent exact resultant +7 PASS independent exact resultant +8 PASS independent exact resultant +9 PASS independent exact resultant +PASS_AVERAGED_CYCLOTOMIC_HEIGHT interval_radices=17 exact_resultants=6 budgets=752 kappa=unchanged +PASS package control missing manifest +PASS package control altered implementation +PASS package control extra file +PASS package control missing source +PASS package control source hash independent of manifest +PASS package control source Git object independent of manifest +PASS package control duplicate manifest key +PASS package control symlink injection +PASS package control preloaded module substitution +PASS package control false receipt boolean integer confusion +PASS package control existing output preserved +PASS full read-only isolated optimized relocation +PASS_AVERAGED_HEIGHT_PACKAGE rejected=11 full_readonly_replay=True +PASS_AVERAGED_HEIGHT_BINDINGS sources=12 +PASS_FROZEN_AVERAGED_HEIGHT_PACKAGE diff --git a/research/averaged-cyclotomic-height-validation/README.md b/research/averaged-cyclotomic-height-validation/README.md new file mode 100644 index 0000000000..148464e78b --- /dev/null +++ b/research/averaged-cyclotomic-height-validation/README.md @@ -0,0 +1,38 @@ +# Frozen averaged-height validation + +The complete package in `../averaged-cyclotomic-height` passed on macOS +arm64 / Python 3.11.15 and Linux aarch64 / Python 3.14.8, both with +SymPy 1.14.0 and mpmath 1.3.0. Each replay used `-I -O -B`. + +Each platform ran all 17 rational interval cases, six exact resultants and +752 integer budgets three times: the ordinary verifier, the deliberately +altered-receipt rejection, and the full read-only relocation. Each package +harness rejected eleven faults. The full mathematical receipts are byte +identical after decompression, including all rational endpoints and integer +budget rows. The Linux source tree was read-only and outside Git; its +supervisor recorded exit code zero. + +- Mathematical receipt SHA256: + `b25ae109654d2e3ac16e6348c982b86d8c07fca80d8cff600205511b9d2617bf`. +- Source manifest SHA256: + `7844dd0039723d9a955a2d0961ff1cb0f710f21277c0b2905577ad7b2b5c2f2a`. +- `SOURCE-GIT-CHECK.json` records the twelve retained files checked against + immutable original Git objects before replay. +- `MACOS311-*` and `LINUX314-*` contain the complete math, package-control, + platform and terminal receipts. The logs record successful completion. +- `REPOSITORY-CHECKS.log.txt` records the selected-record check and all + 25 selected-record/inventory/proof-binding tests at the publication base. + +The preparation base recorded in the frozen source pins is +`8bddbee377e2f3ce1f1247196c4b290d55767d20`. The isolated publication branch +was subsequently advanced to main +`2921874911956718fcaaaf9396fe8267b3cfa9f0` without changing any frozen +package byte. Main still selects PR942 at +`1661960547713947/10^18`. This contribution does not change that selection. + +The all-size claim comes from the written proof. The large-radix rows test +exact exponent arithmetic; no inverse at those enormous word sizes was +executed. The full repository suite, selected construction's cold replay +and full multiplication theorem were not verified here. No independent +human/delegated-agent review or practical speedup is claimed. Hosted CI is +separate from these retained local platform results. diff --git a/research/averaged-cyclotomic-height-validation/REPOSITORY-CHECKS.log.txt b/research/averaged-cyclotomic-height-validation/REPOSITORY-CHECKS.log.txt new file mode 100644 index 0000000000..94d20716c3 --- /dev/null +++ b/research/averaged-cyclotomic-height-validation/REPOSITORY-CHECKS.log.txt @@ -0,0 +1,12 @@ +Publication base: 2921874911956718fcaaaf9396fe8267b3cfa9f0 +COMMAND ['make', 'selected-record-check'] +python3 -B scripts/verify_selected_result.py +PASS selected record, exact kappa, original source inventory and proof supplement: 1661960547713947/1000000000000000000 +EXIT 0 +COMMAND ['python3', '-B', '-m', 'unittest', 'discover', '-s', 'tests', '-p', 'test_selected*.py'] +......................... +---------------------------------------------------------------------- +Ran 25 tests in 0.327s + +OK +EXIT 0 diff --git a/research/averaged-cyclotomic-height-validation/SOURCE-GIT-CHECK.json b/research/averaged-cyclotomic-height-validation/SOURCE-GIT-CHECK.json new file mode 100644 index 0000000000..4f324551c4 --- /dev/null +++ b/research/averaged-cyclotomic-height-validation/SOURCE-GIT-CHECK.json @@ -0,0 +1,89 @@ +{ + "status": "PASS_SOURCE_GIT_OBJECTS", + "sources": [ + { + "path": "vendor/pr621/PROOF.md", + "head": "520774462b19b29af41554b74def31f9d01e997e", + "source_path": "research/prime-power-cyclic-inverse/PROOF.md", + "sha256": "2b8056c88e66f692f407450fff0414d41bcd09db8597be22e274a6c3dc20eb9e", + "git_blob": "0c757c37c70fdeb261d73f111ceedd3b233287bf" + }, + { + "path": "vendor/pr621/NOTICE.md", + "head": "520774462b19b29af41554b74def31f9d01e997e", + "source_path": "research/prime-power-cyclic-inverse/NOTICE.md", + "sha256": "96111c95cfec3c03a6f69c8e02c5d0bceff957d187e638d0534c676d6e3ffd77", + "git_blob": "a78e84066711e2f4776152d69d480e9629c26961" + }, + { + "path": "vendor/pr621/verify.py", + "head": "520774462b19b29af41554b74def31f9d01e997e", + "source_path": "research/prime-power-cyclic-inverse/verify.py", + "sha256": "40e5e18cbd98d39ba6d0bb036778ccacc077dff009099a54b9c8f441af5d6a56", + "git_blob": "20a069f42ac2e7102d8b1ddac4f568b83e077074" + }, + { + "path": "vendor/pr621/independent_verify.py", + "head": "520774462b19b29af41554b74def31f9d01e997e", + "source_path": "research/prime-power-cyclic-inverse/independent_verify.py", + "sha256": "515d60fbbb28c025251b5a2929231b4b6124dabe357b8526fdb93c1456c847ce", + "git_blob": "813ffd0304c98c6ea4fea89f021a4247f26f9971" + }, + { + "path": "vendor/pr628/PROOF.md", + "head": "0768f97d06c623b8211e651543c66135796b62bf", + "source_path": "research/prime-power-cyclic-scan/PROOF.md", + "sha256": "595893609764c64a90d9b21b9cbd6d9e61980703f3deb43361105cf8c3d1d093", + "git_blob": "fb8fe7cb3bd036c69047ae7b4f4009a51b11825b" + }, + { + "path": "vendor/pr628/NOTICE.md", + "head": "0768f97d06c623b8211e651543c66135796b62bf", + "source_path": "research/prime-power-cyclic-scan/NOTICE.md", + "sha256": "abeacf1ad1491d5797cfcf1f3832799bbf3b24b99597229d7bc884059a51ec68", + "git_blob": "22fbeb8ef0a28dd6b3feea718492091319ceb96e" + }, + { + "path": "vendor/pr628/interval_kernel.py", + "head": "0768f97d06c623b8211e651543c66135796b62bf", + "source_path": "research/prime-power-cyclic-scan/interval_kernel.py", + "sha256": "9b7bb24640a9a7d3f83c7951dfef483ec933db4c50de6c0130b85f450eeddfbe", + "git_blob": "1182175a55cb871481de0f56ea9ae56e474705fe" + }, + { + "path": "vendor/pr862/PROOF.md", + "head": "57e0659150d323b784580110b36aa64a2dca2a33", + "source_path": "research/cubic-cyclic-inverse/PROOF.md", + "sha256": "bdb0518892c631f8b6ac149535ac5a92270def19fe7778ca737641cd56b7da0b", + "git_blob": "0196499f010857b58ea297611f44721a4b7a0ec6" + }, + { + "path": "vendor/pr862/NOTICE.md", + "head": "57e0659150d323b784580110b36aa64a2dca2a33", + "source_path": "research/cubic-cyclic-inverse/NOTICE.md", + "sha256": "08c25cd6248e8c4dc7008e14e9ea7690f9084e94f927bb602363773637a89921", + "git_blob": "737060bd4d9666a925dfd1e17fc6eaa53c289b8d" + }, + { + "path": "vendor/pr977/PROOF.md", + "head": "2846af720af190cb75b45ebddbb0357dec1121ec", + "source_path": "research/cyclic-stride-effective-depth/PROOF.md", + "sha256": "30c296d4f1947cbcaaeb0fe575c36e3c2308f1583dde6029efb4a162fb7a4b27", + "git_blob": "6019f4d03f2a429c07aae18deba0525d9af36d71" + }, + { + "path": "vendor/pr977/NOTICE.md", + "head": "2846af720af190cb75b45ebddbb0357dec1121ec", + "source_path": "research/cyclic-stride-effective-depth/NOTICE.md", + "sha256": "b6e1bab630faf7eb4ad0952173dd789a7f5d6333bf938b275bcf087474f4f189", + "git_blob": "57939c758daebf9b7c952ce849ccb169d10c35c6" + }, + { + "path": "vendor/pr977/cubic.py", + "head": "2846af720af190cb75b45ebddbb0357dec1121ec", + "source_path": "research/cyclic-stride-effective-depth/cubic.py", + "sha256": "7c6cbeedeb77dee4a167fb32b4e14b33f8bd00d69a560d0d2232ecfca7ee59f8", + "git_blob": "61c213dd255e084805cb3ab22fc9ec5d2e947b66" + } + ] +} diff --git a/research/averaged-cyclotomic-height-validation/VALIDATION.json b/research/averaged-cyclotomic-height-validation/VALIDATION.json new file mode 100644 index 0000000000..0fa37dfe43 --- /dev/null +++ b/research/averaged-cyclotomic-height-validation/VALIDATION.json @@ -0,0 +1,29 @@ +{ + "files": { + "LINUX314-MATH.json.gz": "3050ab8713b13e0b95510f6d2601b254ec4b6a9ce81db8ca3467fc93f24d49f5", + "LINUX314-PACKAGE.json": "2a5c27c854fdcf76ecea15a07f5beccc45ea198728c806882ff36133555dc4ae", + "LINUX314-PLATFORM.json": "b2689b8e145d0fee0df73a85501f012b3ca2a695ee0b2edd4e7584f73fdc24e1", + "LINUX314-TERMINAL.json": "7c8b4ad5ac38c7776a0116039b80084f509dfaa28d645c7215f0270bcc1d0aaa", + "LINUX314.log.txt": "4ea474f1fd25336c73f335dbec30d714e8f6eaa74516196ade64f133c599588d", + "MACOS311-MATH.json.gz": "3050ab8713b13e0b95510f6d2601b254ec4b6a9ce81db8ca3467fc93f24d49f5", + "MACOS311-PACKAGE.json": "2a5c27c854fdcf76ecea15a07f5beccc45ea198728c806882ff36133555dc4ae", + "MACOS311-PLATFORM.json": "7cc8655afa33fa6f9e077cfaad12b6153500e92c2079a80fa4bac2d31087e62b", + "MACOS311-TERMINAL.json": "7c8b4ad5ac38c7776a0116039b80084f509dfaa28d645c7215f0270bcc1d0aaa", + "MACOS311.log.txt": "4ea474f1fd25336c73f335dbec30d714e8f6eaa74516196ade64f133c599588d", + "README.md": "278d3666ac88c5f33d283cfddf9558507c3f5d09f2d3b96210dfd6940c1feff9", + "REPOSITORY-CHECKS.log.txt": "cc79f9351bd035294a41bdc84e4870a2a18c3680df1422679a5e553359f6d398", + "SOURCE-GIT-CHECK.json": "8434f0830f30adad6902cf63d75d6056f85268d00999d7e8cfea24358a79d61e" + }, + "full_decompressed_receipts_byte_equal": true, + "linux_source_read_only": true, + "linux_supervisor_exit": 0, + "manifest_sha256": "7844dd0039723d9a955a2d0961ff1cb0f710f21277c0b2905577ad7b2b5c2f2a", + "math_sha256": "b25ae109654d2e3ac16e6348c982b86d8c07fca80d8cff600205511b9d2617bf", + "package_rejections_per_platform": 11, + "publication_base": "2921874911956718fcaaaf9396fe8267b3cfa9f0", + "read_only_full_replay_per_platform": true, + "selected_kappa": "1661960547713947/1000000000000000000", + "selected_record_checks": true, + "selected_related_tests": 25, + "status": "PASS_TWO_COMPLETE_FROZEN_PLATFORM_REPLAYS" +} diff --git a/research/averaged-cyclotomic-height/EXPECTED.json.gz b/research/averaged-cyclotomic-height/EXPECTED.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..35906824df9b700c19434057e80a2f948638bbea GIT binary patch literal 53705 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 O@&5yJFu(+fkp=)gWRJlB literal 0 HcmV?d00001 diff --git a/research/averaged-cyclotomic-height/MANIFEST.json b/research/averaged-cyclotomic-height/MANIFEST.json new file mode 100644 index 0000000000..51a3173dbe --- /dev/null +++ b/research/averaged-cyclotomic-height/MANIFEST.json @@ -0,0 +1,27 @@ +{ + "files": { + "EXPECTED.json.gz": "3050ab8713b13e0b95510f6d2601b254ec4b6a9ce81db8ca3467fc93f24d49f5", + "NOTICE.md": "4a0c8a8c8568ccea7dc4b0d9b455408b806da42d18521732ccc923a8275be2ce", + "PROOF.md": "5f8ec1431faecb7a2503f8c2dd7e398e5a749176d36cd54ae57763b4a4f0d4c4", + "README.md": "b2ca4494c2d057fb61a0cb703c6cac2c36f1b28216a5846024af750a5667e3a0", + "SOURCE-PINS.json": "66c2898770feb2bc8d0691d75efae711023e0c4d1e0006bd9d5257af3f1e55f6", + "budgets.py": "2b2a5ddb2669432c2a7199dc3d7d4ab1ece83166af4b70649e361902db1e551d", + "interval_check.py": "ad6786e9f2db9000a438097f8c4d41f645b54a8df8e70315cc617c19c8a979b1", + "requirements.txt": "47fd19021144e071cc43b6e265aafada0056abe89724ad95bd6e3a8e37995b94", + "resultants.py": "486c4ec2f6723026c50452c67c36c4dfa4ca4e8c90e1249fc77fff73964ff5df", + "test_package.py": "64148d9084b4477b9dcc995afa2a66427716167706910c745c9575c892558c59", + "vendor/pr621/NOTICE.md": "96111c95cfec3c03a6f69c8e02c5d0bceff957d187e638d0534c676d6e3ffd77", + "vendor/pr621/PROOF.md": "2b8056c88e66f692f407450fff0414d41bcd09db8597be22e274a6c3dc20eb9e", + "vendor/pr621/independent_verify.py": "515d60fbbb28c025251b5a2929231b4b6124dabe357b8526fdb93c1456c847ce", + "vendor/pr621/verify.py": "40e5e18cbd98d39ba6d0bb036778ccacc077dff009099a54b9c8f441af5d6a56", + "vendor/pr628/NOTICE.md": "abeacf1ad1491d5797cfcf1f3832799bbf3b24b99597229d7bc884059a51ec68", + "vendor/pr628/PROOF.md": "595893609764c64a90d9b21b9cbd6d9e61980703f3deb43361105cf8c3d1d093", + "vendor/pr628/interval_kernel.py": "9b7bb24640a9a7d3f83c7951dfef483ec933db4c50de6c0130b85f450eeddfbe", + "vendor/pr862/NOTICE.md": "08c25cd6248e8c4dc7008e14e9ea7690f9084e94f927bb602363773637a89921", + "vendor/pr862/PROOF.md": "bdb0518892c631f8b6ac149535ac5a92270def19fe7778ca737641cd56b7da0b", + "vendor/pr977/NOTICE.md": "b6e1bab630faf7eb4ad0952173dd789a7f5d6333bf938b275bcf087474f4f189", + "vendor/pr977/PROOF.md": "30c296d4f1947cbcaaeb0fe575c36e3c2308f1583dde6029efb4a162fb7a4b27", + "vendor/pr977/cubic.py": "7c6cbeedeb77dee4a167fb32b4e14b33f8bd00d69a560d0d2232ecfca7ee59f8", + "verify.py": "8fc79b50d08c55db72ca9a673250b26a5dcb43b749ec8e99383d82b0adbe07ed" + } +} diff --git a/research/averaged-cyclotomic-height/NOTICE.md b/research/averaged-cyclotomic-height/NOTICE.md new file mode 100644 index 0000000000..8ded624012 --- /dev/null +++ b/research/averaged-cyclotomic-height/NOTICE.md @@ -0,0 +1,48 @@ +# Attribution and scope + +The averaged-height estimate and its integration with the explicit +precision budget were prepared by Chafik Boukhalfa (@chafreaky), with +substantial OpenAI Codex assistance. Apache-2.0, as in the repository. +No literature-priority, independent human review, delegated-agent review +or full formal-verification claim is made. + +- Ali Romman (@aliromman), PR621, head + `520774462b19b29af41554b74def31f9d01e997e`: the prime-power ideal + argument, nonzero resultant, cofactor/circle estimate, Fourier inverse + bound and rational field checker. Its proof, notice and two checkers + are retained byte for byte. The new `resultants.py` adapts the independent + SymPy checker's field and Sylvester constructions, and compares a + polynomial resultant with the retained rational-field computation. +- Chafik Boukhalfa, PR628, head + `0768f97d06c623b8211e651543c66135796b62bf`: coefficient preparation, + root-margin framework and rational interval kernel. Its proof, notice + and interval implementation are retained. The new interval checker sets + its documented module precision to 192 bits, and adds outward rational + logarithm and square-root bounds. +- Chafik Boukhalfa, PR862, head + `57e0659150d323b784580110b36aa64a2dca2a33`: the common-operator + complementary-factor bound and explicit cubic precision budgets. + Its proof and notice are retained. +- Chafik Boukhalfa, PR977, head + `2846af720af190cb75b45ebddbb0357dec1121ec`: effective nonzero depth + for the original PR846 stride solver and its cubic-budget integration. + Its proof, notice and budget code are retained. `budgets.py` adapts those + formulas to the new circle exponent. `verify.py` and `test_package.py` + adapt that package's source binding, receipt comparison and relocation + harness. Rohan Guliani's PR846 arbitrary-stride Euclidean solver and + Charles Bethin's PR764 shared-suffix estimate remain credited through + the retained notice; no new solver execution is claimed here. + +The kernel comes from the pinned OpenAI exact-DFT manuscript, with its +classical Newton/q-Pochhammer factorization provenance retained in PR621's +notice. The logarithm Fourier series, geometric sums, Hadamard inequality, +algebraic norm, Mahler-measure argument, approximate factorization and fast +arithmetic remain classical ingredients. The new proof is self-contained +for its averaged-height estimate and does not infer a finite rational-unit +bound from an irrational Sudler-product theorem. + +All retained files have immutable Git-blob and SHA256 pins in +`SOURCE-PINS.json`. Existing notices and licenses are unchanged. This +contribution improves a sufficient precision theorem; it does not resolve +the full-transform, common-label, Clifford, physical hosting or complete +multiplication obligations, and it makes no new kappa claim. diff --git a/research/averaged-cyclotomic-height/PROOF.md b/research/averaged-cyclotomic-height/PROOF.md new file mode 100644 index 0000000000..3215a58a40 --- /dev/null +++ b/research/averaged-cyclotomic-height/PROOF.md @@ -0,0 +1,251 @@ +# Averaged coefficient heights for the prime-power cyclic inverse + +Theorem and proof, 2026-10-13. This is a new derivation on top of +PR621's nonzero resultant and Bezout argument. It is not a new kappa, +a full transform, or a common-label implementation. The finite scripts +check examples and arithmetic; the argument below supplies the universal +claim. No independent human review or formal verification is claimed. + +Let r>=3 be a prime power, n=r-1, D=phi(r), zeta=exp(2 pi i/r), and + + f_k(z) = sum_(j=0)^n a_(k,j) z^j, + a_(k,j) = product_(s=j+1)^n (1-zeta^(ks)), + H_k = sum_j |a_(k,j)|, + +where k ranges over the units modulo r. Thus f_k=r P_k, as in PR621. +All logarithms in the analytic argument are natural. Write t=log r. +We prove + + sum_(k unit mod r) log H_k <= D (4t^2+8t+2). (1) + +The existing proof used H_k<=2^r-1 separately at every embedding. +Using (1) in exactly the same determinant and cofactor argument gives + + |P_k(z)| >= exp[-n D (4t^2+8t+2)] / (2rn), |z|=1. (2) + +Consequently, with ell=ceil(log2 r), + + d = 1+2ell+n D min(r,8ell^2) + +is a valid integer exponent for |P_k(z)|>=2^-d. The minimum retains +PR621's cubic bound at small radices. The new exponent is +O(r phi(r) log^2 r), uniformly in the primitive embedding and circle +point. No average-over-embeddings assumption is imposed on the output. +The original uniform bound and its proof are retained in +[`vendor/pr621/PROOF.md`](vendor/pr621/PROOF.md). + +## The discrete logarithm has small Fourier mass + +Define L(0)=0 and L(s)=log|1-zeta^s| for 1<=s=1) rho^m cos(2 pi m s/r)/m. + +Aliasing into r residues and the triangle inequality show that the +sum of the moduli of its discrete Fourier coefficients is at most +sum_(m>=1) rho^m/m=-log(1-rho)=log r. + +For s!=0, set a_s=|1-zeta^s|. We have + + |1-rho zeta^s|^2/a_s^2 = rho(1+delta^2/(rho a_s^2)). + +By the triangle inequality, -log(1-delta)<=delta/rho, and +log(1+x)<=x for x>=0, this gives + + |L(s)-Lrho(s)| <= delta/(2rho)+delta^2/(2rho a_s^2). + +The difference can have either sign. Pair s with r-s. Concavity of +sine gives a_s>=4 min(s,r-s)/r, so comparison of the reciprocal-square +tail with its integral yields + + sum_(s=1)^(r-1) a_s^-2 + <= (r^2/8) sum_(j>=1) j^-2 <= r^2/4. + +Consequently, since rho>=2/3, + + sum_(s=1)^(r-1) |L(s)-Lrho(s)| + <= (r-1)delta/(2rho)+delta^2 r^2/(8rho) + = 1/2+1/(8rho) <=11/16<1. + +At s=0 the difference is log r. For any sampled function E, normalization gives +sum_h |Ehat(h)|<=sum_s |E(s)|. Applying this to L-Lrho gives + + sum_h |Lhat(h)| <= 2log r+11/16 <=2log r+1. (4) + +The value at zero is essential: silently omitting its correction would +undercharge the Fourier mass. We never evaluate L(0) in a coefficient +product; it is only a convenient finite Fourier extension. + +## Average a geometric-sum bound over units + +Fix h!=0 modulo r and put d0=r/gcd(h,r). For any interval I of +consecutive integers, and any unit k modulo r, + + |sum_(s in I) zeta^(hks)| <= 2/|1-zeta^(hk)|. + +As k ranges over the units modulo r, zeta^(hk) ranges uniformly over +the primitive d0-th roots. This follows from the surjection of the +unit groups for prime-power moduli, followed by multiplication by +h/gcd(h,r), a unit modulo d0. The fibers have equal size. In particular +d0 is a prime power and d0/phi(d0)<=2, including d0=2. + +Pairing j with d0-j and using sin(pi j/d0)>=2j/d0 for +1<=j<=floor(d0/2) gives + + sum_(j=1)^(d0-1) 1/sin(pi j/d0) + <= d0 H_floor(d0/2) <= d0 (1+log d0). + +The middle term is overcounted when d0 is even, which is harmless. +Hence the average over primitive k of the geometric-sum bound is +at most 2(1+log r). This bound holds simultaneously for every I; +the right-hand side for each k does not depend on I. + +Let M_k be the maximum of zero and all logarithms log|a_(k,j)|. +Fourier inversion, (3), and the triangle inequality give the pointwise +upper bound + + M_k <= log r + sum_(h=1)^(r-1) |Lhat(h)| 2/|1-zeta^(hk)|. + +Average this inequality and apply (4). Because H_k<=r exp(M_k), + + average_k log H_k + <= 2log r+2(2log r+1)(1+log r) + = 4t^2+8t+2, + +which is (1). This averages an upper bound on the maximum; it does +not exchange an average and a maximum. + +## Resultant and cofactor cancellation + +Use PR621's Sylvester matrix for f and its conjugate reciprocal f*. +Let R be its determinant in Q(zeta). The prime-power ideal argument +from that proof establishes R!=0. For each embedding k, every +column has Euclidean norm at most H_k, so |R_k|<=H_k^(2n). +The chosen embedding and its complex conjugate have the same H and +the same |R|; they are distinct since r>=3. The nonzero algebraic +integer norm therefore gives + + |R| >= product_(k excluding chosen pair) H_k^(-n). + +The coefficients of the two Bezout polynomials are cofactors. Each +cofactor at the chosen embedding has modulus at most H^(2n-1). +For |z|=1, |f*(z)|=|f(z)|, so + + |P(z)| >= |R|/[2rn H^(2n-1)] + >= H/[2rn product_(all k) H_k^n] + >= 1/[2rn product_(all k) H_k^n]. (5) + +Here H>=1 because f is monic. The local cofactor powers cancel the +two removed embeddings exactly, leaving a favorable numerator H. +Equation (1) now proves (2). No rationality or Galois invariance of R +is assumed; such invariance is false already at r=5. + +## Dyadic exponent and inherited precision budgets + +Since 2/3=2 the second difference is +5ell^2-8ell-3=1+12(ell-2)+5(ell-2)^2>=0. Also +2rn<=2^(1+2ell). These inequalities prove the displayed d. + +PR862's perturbation and partial-inverse estimates, and PR977's +effective-depth stride theorem, use the circle theorem only through +d. Set T=n D min(r,8ell^2) and use their unchanged definitions: + + d=1+2ell+T, a0=2d+r+2, g=d+ell+2r+2, h=a0+2r, + c=ceil(log2(r-1)), + e=max(d+1,a0+1,p+2a0+m+3), b=max((r-1)ell,e+r+3), + J=c+2h+3g+ell+m+5, W=p+J+2, G=m+ell+h+g+8. + +In particular, PR621's Fourier inverse estimate with the unchanged +coefficient bound H=2^r-1 gives ||P(U)^-1||<=2^a0. The bound applies +to every isometry with ||U^j||=1 for all integer j, by the absolutely +convergent Laurent series argument retained in PR862. This includes +arbitrary-stride cyclic unit shifts. The inherited proofs are retained +as [`vendor/pr862/PROOF.md`](vendor/pr862/PROOF.md) and +[`vendor/pr977/PROOF.md`](vendor/pr977/PROOF.md). + +Here p,m>=0, input infinity norm is <=2^m, and target error is +2^-p. Direct substitution gives + + W=p+m+7T+12r+18ell+c+24, + G=m+3T+5r+8ell+15, + b=p+m+4T+3r+8ell+14. + +The last equality follows because p+2a0+m+3 dominates the other e +terms, and its resulting b term exceeds (r-1)ell. For the latter, +d>=n D min(r,8ell^2)>=n ell: D>=1, r>=ell and +8ell^2>=ell. With N=r^2 ell^2, T<=8N and r>=3, ell>=2, +ell<=r, N>=12r, these give convenient universal bounds + + W<=p+m+60N, G<=m+26N, b<=p+m+34N. + +For example, the non-T W terms are <=31r+24<=39r<4N; +the G terms are <=13r+15<=18r<2N; the b terms are +<=11r+14<=16r<2N. All previous cubic bounds remain valid because +d did not increase. The admission W>=2g+8 and the common-error +contraction exponents remain unchanged algebraically. Thus the +existing clean-scratch arbitrary-stride solver has the same 40L +record bound per first-order inverse and an O(r^2 log^2 r) precision +overhead. This statement inherits all phase-oracle, coefficient +preparation, word-size, and clean-workspace charges from PR977; +it is not a new bit-reversible or dirty-array circuit. + +## Evidence and attribution + +`interval_check.py` uses 192-bit outward-rounded rational enclosures +to check 17 prime-power radices through 32. It checks regularization, +Fourier mass, primitive-character fiber multiplicities, geometric +averages, each pointwise maximum bound before averaging, total averaged +height, and dyadic conversion. A separate exact enclosure at r=4096 +proves that the average bound is false if assigned to every embedding +individually. That negative control uses sin(x)<=x and AM-GM, not a +floating-point sample of a large polynomial. + +`resultants.py` independently compares SymPy polynomial resultants and +Sylvester determinants with PR621's rational field arithmetic for +r=3,4,5,7,8,9. It checks all Galois conjugates and norms, and rejects +the rational-resultant shortcut explicitly at r=5. The retained unit-root +and missing-conjugation controls are replayed in all six cases. + +`budgets.py` checks 752 exact integer budgets, including dyadic orders +through 2^128, the dyadic-conversion polynomial identity and a +rational enclosure of log 2. Those large orders test exponent arithmetic; +no enormous polynomial, array or working word is allocated. No actual +inverse execution at the reduced large-radix precision is claimed. + +The full package additionally rejects eleven packaging/receipt faults +and replays from a read-only relocated copy. The finite checks support +specific identities and failure modes. They do not prove the analytic +theorem for all radices; that is the role of the argument above. + +The kernel is from the pinned OpenAI exact-DFT preprint, with its +classical Newton and q-Pochhammer provenance retained in PR621's +NOTICE. The ideal/resultant/cofactor proof is retained from Ali +Romman's PR621. The partial-inverse precision framework is retained +from Chafik's PR862; the arbitrary-stride solver is Rohan Guliani's +PR846, with the effective-depth argument in Chafik's PR977. Classical +ingredients here are the logarithm Fourier series, finite Fourier +inversion, geometric sums, cyclotomic embeddings, Hadamard's +inequality, and the algebraic norm. A search found related Sudler +product literature, including [Bence Borda, arXiv:2104.06716](https://arxiv.org/abs/2104.06716), but the +finite rational-unit average above is derived in full and does not +rely on an irrational-rotation theorem. No priority claim is made. + +The immutable source objects and notices are retained in `vendor/` and +bound by `SOURCE-PINS.json`. Common-label and bit-reversible compilation, +full-transform normalization and traffic, supplier hosting, and the +multiplication reduction remain open. The new averaged-height estimate +does not discharge those obligations. diff --git a/research/averaged-cyclotomic-height/README.md b/research/averaged-cyclotomic-height/README.md new file mode 100644 index 0000000000..79ea64928a --- /dev/null +++ b/research/averaged-cyclotomic-height/README.md @@ -0,0 +1,56 @@ +# Averaged cyclotomic heights + +For every prime-power radix r>=3, average the coefficient heights across +the cyclotomic embeddings before using the algebraic norm. This improves +the uniform circle-separation exponent from O(r^3) to O(r^2 log^2 r). +The same substitution improves the inherited cyclic-inverse precision +budget. No new kappa is claimed. + +Let ell=ceil(log2 r), n=r-1, D=phi(r). The explicit bound is + + |P(z)| >= 2^-d, |z|=1, + d = 1+2ell+n D min(r,8ell^2). + +It holds at every primitive embedding and every point of the unit circle. +The minimum preserves the prior bound at small radices. For example, +at r=4096 the circle exponent decreases from 34,351,349,785 to +9,661,317,145. These are conservative analytic precision bounds, not +executed word sizes or timing measurements. + +With N=r^2 ell^2, input norm <=2^m and target error 2^-p, the retained +PR977 clean-scratch arbitrary-stride construction has fractional working +precision W<=p+m+60N, integer guard G<=m+26N, and factor-preparation +precision b<=p+m+34N. Its inherited record count is unchanged. The theorem +does not supply a new solver, dirty-array circuit, common-label compiler, +complete transform or multiplication exponent. + +## Replay + +Python 3.11 or later and the pinned SymPy dependency are sufficient: + +```sh +python -m pip install -r research/averaged-cyclotomic-height/requirements.txt +python -I -O -B research/averaged-cyclotomic-height/verify.py +python -I -O -B research/averaged-cyclotomic-height/test_package.py +``` + +The verifier checks the source/manifest binding, 17 rational interval +cases, six independent exact resultants and 752 integer budget rows. +Two explicit mathematical controls reject a rational-resultant shortcut +and misuse of the averaged height as a pointwise estimate. The inherited +unit-root and missing-conjugation controls are also replayed. The package +harness rejects eleven packaging faults and runs a complete read-only +relocation, including the mathematical checks. + +`--out /outside/package/result.json` writes a fresh external receipt after +comparison with `EXPECTED.json.gz`. Existing output files are preserved. +`--write` is an explicit authoring mode that skips the expected-receipt +comparison; it is not a verification result and is not used by CI. +No network or private workspace file is needed after installing the +declared dependency. Compressed receipt equality is defined by the full +decompressed canonical payload. + +[PROOF.md](PROOF.md) contains the complete new derivation and the precise +inherited claims. [NOTICE.md](NOTICE.md) identifies contributors and +classical sources. Finite checks are supporting evidence, not a formal +verification of the full multiplication theorem. diff --git a/research/averaged-cyclotomic-height/SOURCE-PINS.json b/research/averaged-cyclotomic-height/SOURCE-PINS.json new file mode 100644 index 0000000000..e775030c9c --- /dev/null +++ b/research/averaged-cyclotomic-height/SOURCE-PINS.json @@ -0,0 +1,90 @@ +{ + "base_commit": "8bddbee377e2f3ce1f1247196c4b290d55767d20", + "repository": "https://github.com/CrocSwap/integer-mult-bounds", + "sources": [ + { + "git_blob": "0c757c37c70fdeb261d73f111ceedd3b233287bf", + "head": "520774462b19b29af41554b74def31f9d01e997e", + "path": "vendor/pr621/PROOF.md", + "sha256": "2b8056c88e66f692f407450fff0414d41bcd09db8597be22e274a6c3dc20eb9e", + "source_path": "research/prime-power-cyclic-inverse/PROOF.md" + }, + { + "git_blob": "a78e84066711e2f4776152d69d480e9629c26961", + "head": "520774462b19b29af41554b74def31f9d01e997e", + "path": "vendor/pr621/NOTICE.md", + "sha256": "96111c95cfec3c03a6f69c8e02c5d0bceff957d187e638d0534c676d6e3ffd77", + "source_path": "research/prime-power-cyclic-inverse/NOTICE.md" + }, + { + "git_blob": "20a069f42ac2e7102d8b1ddac4f568b83e077074", + "head": "520774462b19b29af41554b74def31f9d01e997e", + "path": "vendor/pr621/verify.py", + "sha256": "40e5e18cbd98d39ba6d0bb036778ccacc077dff009099a54b9c8f441af5d6a56", + "source_path": "research/prime-power-cyclic-inverse/verify.py" + }, + { + "git_blob": "813ffd0304c98c6ea4fea89f021a4247f26f9971", + "head": "520774462b19b29af41554b74def31f9d01e997e", + "path": "vendor/pr621/independent_verify.py", + "sha256": "515d60fbbb28c025251b5a2929231b4b6124dabe357b8526fdb93c1456c847ce", + "source_path": "research/prime-power-cyclic-inverse/independent_verify.py" + }, + { + "git_blob": "fb8fe7cb3bd036c69047ae7b4f4009a51b11825b", + "head": "0768f97d06c623b8211e651543c66135796b62bf", + "path": "vendor/pr628/PROOF.md", + "sha256": "595893609764c64a90d9b21b9cbd6d9e61980703f3deb43361105cf8c3d1d093", + "source_path": "research/prime-power-cyclic-scan/PROOF.md" + }, + { + "git_blob": "22fbeb8ef0a28dd6b3feea718492091319ceb96e", + "head": "0768f97d06c623b8211e651543c66135796b62bf", + "path": "vendor/pr628/NOTICE.md", + "sha256": "abeacf1ad1491d5797cfcf1f3832799bbf3b24b99597229d7bc884059a51ec68", + "source_path": "research/prime-power-cyclic-scan/NOTICE.md" + }, + { + "git_blob": "1182175a55cb871481de0f56ea9ae56e474705fe", + "head": "0768f97d06c623b8211e651543c66135796b62bf", + "path": "vendor/pr628/interval_kernel.py", + "sha256": "9b7bb24640a9a7d3f83c7951dfef483ec933db4c50de6c0130b85f450eeddfbe", + "source_path": "research/prime-power-cyclic-scan/interval_kernel.py" + }, + { + "git_blob": "0196499f010857b58ea297611f44721a4b7a0ec6", + "head": "57e0659150d323b784580110b36aa64a2dca2a33", + "path": "vendor/pr862/PROOF.md", + "sha256": "bdb0518892c631f8b6ac149535ac5a92270def19fe7778ca737641cd56b7da0b", + "source_path": "research/cubic-cyclic-inverse/PROOF.md" + }, + { + "git_blob": "737060bd4d9666a925dfd1e17fc6eaa53c289b8d", + "head": "57e0659150d323b784580110b36aa64a2dca2a33", + "path": "vendor/pr862/NOTICE.md", + "sha256": "08c25cd6248e8c4dc7008e14e9ea7690f9084e94f927bb602363773637a89921", + "source_path": "research/cubic-cyclic-inverse/NOTICE.md" + }, + { + "git_blob": "6019f4d03f2a429c07aae18deba0525d9af36d71", + "head": "2846af720af190cb75b45ebddbb0357dec1121ec", + "path": "vendor/pr977/PROOF.md", + "sha256": "30c296d4f1947cbcaaeb0fe575c36e3c2308f1583dde6029efb4a162fb7a4b27", + "source_path": "research/cyclic-stride-effective-depth/PROOF.md" + }, + { + "git_blob": "57939c758daebf9b7c952ce849ccb169d10c35c6", + "head": "2846af720af190cb75b45ebddbb0357dec1121ec", + "path": "vendor/pr977/NOTICE.md", + "sha256": "b6e1bab630faf7eb4ad0952173dd789a7f5d6333bf938b275bcf087474f4f189", + "source_path": "research/cyclic-stride-effective-depth/NOTICE.md" + }, + { + "git_blob": "61c213dd255e084805cb3ab22fc9ec5d2e947b66", + "head": "2846af720af190cb75b45ebddbb0357dec1121ec", + "path": "vendor/pr977/cubic.py", + "sha256": "7c6cbeedeb77dee4a167fb32b4e14b33f8bd00d69a560d0d2232ecfca7ee59f8", + "source_path": "research/cyclic-stride-effective-depth/cubic.py" + } + ] +} diff --git a/research/averaged-cyclotomic-height/budgets.py b/research/averaged-cyclotomic-height/budgets.py new file mode 100644 index 0000000000..f3976e25d6 --- /dev/null +++ b/research/averaged-cyclotomic-height/budgets.py @@ -0,0 +1,64 @@ +"""Exact integer budget checks for the averaged-height bound.""" +from fractions import Fraction as F +import json +from pathlib import Path + + +def need(ok,label): + if not ok: + raise ValueError(label) + + +def plan(r,phi,p,m): + need(all(type(x) is int for x in (r,phi,p,m)) and r>=3 and 1<=phi<=r and p>=0 and m>=0, + 'budget inputs') + ell,c=(r-1).bit_length(),(r-2).bit_length() + T=(r-1)*phi*min(r,8*ell**2) + d=1+2*ell+T + a0=2*d+r+2 + g=d+ell+2*r+2 + h=a0+2*r + e=max(d+1,a0+1,p+2*a0+m+3) + b=max((r-1)*ell,e+r+3) + J=c+2*h+3*g+ell+m+5 + W=p+J+2 + G=m+ell+h+g+8 + depth=2*g+(W-1).bit_length()+4 + need(W==p+m+7*T+12*r+18*ell+c+24,'width identity') + need(G==m+3*T+5*r+8*ell+15,'guard identity') + need(b==p+m+4*T+3*r+8*ell+14,'preparation identity') + need(W>=2*g+8 and (4*(depth+1)-1).bit_length()<=W-g,'effective-depth admission') + t_exp=c+h+3+3*g-W + need(t_exp<=-1 and 1+t_exp+ell+h+m+1==-p-2,'common-error contraction') + N=r*r*ell*ell + need(W<=p+m+60*N and G<=m+26*N and b<=p+m+34*N,'quasiquadratic bounds') + need(W<=p+m+9*r**3 and G<=m+6*r**3 and b<=p+m+6*r**3,'retained cubic bounds') + old_T=r*(r-1)*phi + old_W=p+m+7*old_T+12*r+18*ell+c+24 + need(W<=old_W,'budget monotonicity') + return dict(r=r,phi=phi,p=p,m=m,ell=ell,d=d,W=W,G=G,b=b, + previous_W=old_W,saved_bits=old_W-W,effective_depth=depth) + + +def main(): + # 2*atanh(1/3) with a positive geometric tail encloses log 2. + lo=2*sum((F(1,3)**(2*j+1)/(2*j+1) for j in range(20)),F(0)) + hi=lo+2*F(1,3)**41/(41*(1-F(1,9))) + need(F(2,3)=0,'nonnegative square root') + s=i.SCALE + n=isqrt(x.numerator*s*s//x.denominator) + lo=F(n,s) + return lo,lo if lo*lo==x else F(n+1,s) + + +def square(a): + low=0 if a[0]<=0<=a[1] else min(a[0]*a[0],a[1]*a[1]) + return i.hull(low,max(a[0]*a[0],a[1]*a[1])) + + +def modulus(a): + squared=i.add(square(a[0]),square(a[1])) + return sqrt_point(squared[0])[0],sqrt_point(squared[1])[1] + + +def atanh_sum(z): + need(0<=z<=F(1,3),'log series argument') + count=80 + lo=2*sum((z**(2*j+1)/(2*j+1) for j in range(count)),F(0)) + hi=lo+2*z**(2*count+1)/((2*count+1)*(1-z*z)) + return i.hull(lo,hi) + + +LOG2=atanh_sum(F(1,3)) + + +@lru_cache(maxsize=None) +def log_point(x): + x=F(x) + need(x>0,'positive logarithm') + k=x.numerator.bit_length()-x.denominator.bit_length() + y=x/F(2)**k + while y<1: + k-=1 + y*=2 + while y>=2: + k+=1 + y/=2 + lo,hi=atanh_sum((y-1)/(y+1)) + return i.add((lo,hi),i.scale(LOG2,k)) + + +def logarithm(a): + return log_point(a[0])[0],log_point(a[1])[1] + + +def cscale(a,b): + return i.mul(a[0],b),i.mul(a[1],b) + + +def total(values): + out=i.point(0) + for value in values: + out=i.add(out,value) + return out + + +def upper_lt_lower(left,right,label): + need(left[1]averaged[1],'reject treating average as pointwise height') + return dict(r=r,j=j,primitive_power=1,log_height_lower=encoded(lower), + average_height_upper=encoded(averaged),pointwise_average_rejected=True) + + +def main(): + rows=[] + for r in [3,4,5,7,8,9,11,13,16,17,19,23,25,27,29,31,32]: + rows.append(case(r)) + print(r,'PASS rational interval enclosures',flush=True) + result={'status':'PASS_RATIONAL_INTERVAL_CASES','bits':i.BITS, + 'source_sha256':hashlib.sha256(SOURCE.read_bytes()).hexdigest(), + 'scope':__doc__,'cases':rows,'pointwise_negative_control':reject_pointwise_average()} + return result + + +if __name__=='__main__': + main() diff --git a/research/averaged-cyclotomic-height/requirements.txt b/research/averaged-cyclotomic-height/requirements.txt new file mode 100644 index 0000000000..de9542d36e --- /dev/null +++ b/research/averaged-cyclotomic-height/requirements.txt @@ -0,0 +1,2 @@ +sympy==1.14.0 +mpmath==1.3.0 diff --git a/research/averaged-cyclotomic-height/resultants.py b/research/averaged-cyclotomic-height/resultants.py new file mode 100644 index 0000000000..39baa6d1d2 --- /dev/null +++ b/research/averaged-cyclotomic-height/resultants.py @@ -0,0 +1,80 @@ +"""Independent SymPy resultant identities and nonrationality counterexample.""" +import importlib.util +import json +from math import gcd +from pathlib import Path +from sympy import Poly, QQ, Symbol, cyclotomic_poly +from sympy.polys.matrices import DomainMatrix + +HERE=Path(__file__).resolve().parent +SOURCE=HERE/'vendor/pr621/verify.py' +spec=importlib.util.spec_from_file_location('retained_pr621',SOURCE) +original=importlib.util.module_from_spec(spec) +spec.loader.exec_module(original) + + +def need(ok,label): + if not ok: + raise ValueError(label) + + +def case(r): + x,z=Symbol('x'),Symbol('z') + field=QQ.alg_field_from_poly(Poly(cyclotomic_poly(r,x),x),alias='u') + u=field([1,0]) + n=r-1 + def embed(a,k): + result=field.zero + for coefficient in a.to_list(): + result=result*u**(k%r)+field(coefficient) + return result + f=[field.one]*r + for j in range(n-1,-1,-1): + f[j]=f[j+1]*(field.one-u**(j+1)) + need(f[0]==field(r),'kernel constant coefficient') + star=[embed(a,-1) for a in reversed(f)] + fp=Poly.from_list(list(reversed(f)),z,domain=field) + gp=Poly.from_list(list(reversed(star)),z,domain=field) + R=field((-1)**n)*fp.rep.resultant(gp.rep) + matrix=[[field.zero]*(2*n) for _ in range(2*n)] + for poly,start in [(f,0),(star,n)]: + for offset in range(n): + for degree,a in enumerate(poly): + matrix[degree+offset][start+offset]=a + need(DomainMatrix(matrix,(2*n,2*n),field).det()==R,'determinant/resultant sign') + need(R!=field.zero and embed(R,-1)==R,'nonzero real resultant') + norm=field.one + embeddings=[] + for k in range(1,r): + if gcd(k,r)!=1: + continue + value=embed(R,k) + norm*=value + embeddings.append([str(c) for c in value.to_list()]) + need(len(norm.to_list())==1 and norm.to_list()[0].denominator==1,'integer norm') + retained=original.case(r,1) + encoded=[str(c) for c in reversed(R.to_list())] + encoded+=['0']*(field.mod.degree()-len(encoded)) + need(encoded==retained['resultant'],'independent exact field agreement') + need(str(norm.to_list()[0])==retained['resultant_norm'],'independent norm agreement') + if r==5: + need(R!=embed(R,2) and len(R.to_list())>1,'reject rational-resultant shortcut') + need(encoded==['98873','0','17859','17859'],'radix-five counterexample') + return dict(r=r,resultant_ascending=encoded,norm=str(norm.to_list()[0]), + embeddings_descending=embeddings,independent_field_agreement=True, + rational_resultant=(len(R.to_list())==1), + inherited_unit_root_control=retained['unit_root_negative_control'], + inherited_missing_conjugation_control=retained['missing_conjugation_negative_control']) + + +def main(): + rows=[] + for r in [3,4,5,7,8,9]: + rows.append(case(r)) + print(r,'PASS independent exact resultant',flush=True) + result={'status':'PASS_INDEPENDENT_EXACT_RESULTANTS','scope':__doc__,'cases':rows} + return result + + +if __name__=='__main__': + main() diff --git a/research/averaged-cyclotomic-height/test_package.py b/research/averaged-cyclotomic-height/test_package.py new file mode 100644 index 0000000000..5ec69c834a --- /dev/null +++ b/research/averaged-cyclotomic-height/test_package.py @@ -0,0 +1,127 @@ +"""Fail-closed package controls and a full read-only optimized relocation.""" +import argparse +import gzip +import hashlib +import json +from pathlib import Path +import shutil +import subprocess +import sys +import tempfile + +P = Path(__file__).resolve().parent +sys.dont_write_bytecode = True +sys.set_int_max_str_digits(100000) + + +def require(value, message): + if not value: + raise ValueError(message) + + +def run(root, *args, code=None): + command = [sys.executable, '-I', '-O', '-B'] + command += ['-c', code] if code is not None else [str(root/'verify.py'), *map(str, args)] + return subprocess.run(command, cwd=root.parent, text=True, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, timeout=2400) + + +def rebind(root, name): + path = root/'MANIFEST.json' + record = json.loads(path.read_text()) + record['files'][name] = hashlib.sha256((root/name).read_bytes()).hexdigest() + path.write_text(json.dumps(record, indent=2, sort_keys=True)+'\n') + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--out', type=Path) + args = parser.parse_args() + if args.out: + require(not args.out.exists() and not args.out.resolve().is_relative_to(P), 'fresh external report') + results = [] + with tempfile.TemporaryDirectory(prefix='averaged height package controls ') as temporary: + base = Path(temporary) + def copy(name): + root = Path(shutil.copytree(P, base/name)) + # The supplied package may itself be read-only. Only these + # disposable test fixtures must permit deliberate corruption. + root.chmod(0o755) + for path in root.rglob('*'): + path.chmod(0o755 if path.is_dir() else 0o644) + return root + def rejection(name, mutate, *, full=False, code=None): + root = copy(name) + mutate(root) + output = base/(name+' output.json') + result = run(root, '--out', output, code=code(root) if code else None) if full or code else run(root, '--bindings-only') + require(result.returncode != 0, 'mutation accepted: '+name) + require(not output.exists(), 'failed verification wrote a receipt: '+name) + results.append(dict(name=name, rejected=True, terminal=result.stdout.strip().splitlines()[-1])) + print('PASS package control', name, flush=True) + + rejection('missing manifest', lambda root: (root/'MANIFEST.json').unlink()) + rejection('altered implementation', lambda root: (root/'budgets.py').write_text((root/'budgets.py').read_text()+'\n# altered\n')) + rejection('extra file', lambda root: (root/'undeclared.txt').write_text('unbound\n')) + rejection('missing source', lambda root: (root/'vendor/pr621/PROOF.md').unlink()) + def wrong_source(root): + file = root/'vendor/pr621/PROOF.md' + file.write_text(file.read_text()+'\nchanged\n') + rebind(root, 'vendor/pr621/PROOF.md') + rejection('source hash independent of manifest', wrong_source) + def wrong_blob(root): + file = root/'SOURCE-PINS.json' + value = json.loads(file.read_text()) + value['sources'][0]['git_blob'] = '0'*40 + file.write_text(json.dumps(value)+'\n') + rebind(root, 'SOURCE-PINS.json') + rejection('source Git object independent of manifest', wrong_blob) + rejection('duplicate manifest key', lambda root: (root/'MANIFEST.json').write_text('{"files":{},"files":{}}\n')) + rejection('symlink injection', lambda root: (root/'linked.txt').symlink_to(root/'README.md')) + rejection('preloaded module substitution', lambda root: None, code=lambda root: + "import sys,types,runpy; m=types.ModuleType('budgets'); m.__file__='/not/the/package.py'; " + "sys.modules['budgets']=m; sys.argv=["+repr(str(root/'verify.py'))+"] ; runpy.run_path(sys.argv[0],run_name='__main__')") + def wrong_receipt(root): + file = root/'EXPECTED.json.gz' + value = json.loads(gzip.decompress(file.read_bytes())) + require(value['budgets']['rows'][0]['p'] == 0, 'known zero budget field') + value['budgets']['rows'][0]['p'] = False + file.write_bytes(gzip.compress((json.dumps(value, indent=2, sort_keys=True)+'\n').encode(), mtime=0)) + rebind(root, 'EXPECTED.json.gz') + rejection('false receipt boolean integer confusion', wrong_receipt, full=True) + + root = copy('existing output') + existing = base/'existing.json' + existing.write_bytes(b'preserve this exact output\n') + result = run(root, '--out', existing) + require(result.returncode != 0 and existing.read_bytes() == b'preserve this exact output\n', 'existing output preservation') + results.append(dict(name='existing output preserved', rejected=True)) + print('PASS package control existing output preserved', flush=True) + + root = copy('read only isolated relocation') + for file in root.rglob('*'): + file.chmod(0o555 if file.is_dir() else 0o444) + root.chmod(0o555) + output = base/'relocated receipt.json' + try: + result = run(root, '--out', output) + require(result.returncode == 0, 'full relocated replay failed: '+result.stdout[-2000:]) + require(output.read_bytes() == gzip.decompress((P/'EXPECTED.json.gz').read_bytes()), 'relocated receipt byte equality') + require(run(root, '--bindings-only').returncode == 0, 'read-only package unchanged after replay') + finally: + root.chmod(0o755) + for directory in root.rglob('*'): + if directory.is_dir(): + directory.chmod(0o755) + results.append(dict(name='full read-only isolated optimized relocation', passed=True, + receipt_sha256=hashlib.sha256(output.read_bytes()).hexdigest())) + print('PASS full read-only isolated optimized relocation', flush=True) + report = dict(status='PASS_AVERAGED_HEIGHT_PACKAGE', controls=results, rejected=11, full_readonly_replay=True) + if args.out: + with args.out.open('x') as handle: + handle.write(json.dumps(report, indent=2, sort_keys=True)+'\n') + print('PASS_AVERAGED_HEIGHT_PACKAGE rejected=11 full_readonly_replay=True') + + +if __name__ == '__main__': + main() diff --git a/research/averaged-cyclotomic-height/vendor/pr621/NOTICE.md b/research/averaged-cyclotomic-height/vendor/pr621/NOTICE.md new file mode 100644 index 0000000000..a78e840667 --- /dev/null +++ b/research/averaged-cyclotomic-height/vendor/pr621/NOTICE.md @@ -0,0 +1,21 @@ +# Attribution and assistance + +The kernel definition comes from the OpenAI exact-DFT preprint at +`adc7f1241b42e322a6451854ab7e4b4c146bf78a`, at `loc:newton` and +`loc:fourier-factorization`. Its source has the Apache-2.0 license. +The Newton and q-Pochhammer Fourier factorization is classical; see +Alexey Kuznetsov, [Using q-calculus to study LDLT factorization of a +certain Vandermonde matrix](https://arxiv.org/abs/1507.02959v2). +This source is not presented as a proof of the cyclic conditioning result. + +The proof extends prior unpublished local cyclic inverse and stability +notes from research directed by Ali Romman. The rational field routines +use that work's exact-arithmetic scaffold. The full proof is included +here; no private file is needed for replay. No literature priority is claimed. + +The proof, verifier, and package were prepared with substantial OpenAI +Codex assistance. Separate Codex agents reviewed the proof and checked +it with independent SymPy arithmetic. These are AI-assisted reviews, +not maintainer acceptance or a full Lean multiplication proof. + +This contribution uses the repository's Apache-2.0 license. diff --git a/research/averaged-cyclotomic-height/vendor/pr621/PROOF.md b/research/averaged-cyclotomic-height/vendor/pr621/PROOF.md new file mode 100644 index 0000000000..0c757c37c7 --- /dev/null +++ b/research/averaged-cyclotomic-height/vendor/pr621/PROOF.md @@ -0,0 +1,212 @@ +# Uniform bounds for the prime-power cyclic inverse + +## Result and scope + +Let r=ell^a>=3, where ell is prime and a>=1. Let u be a primitive +r-th root of unity, and put n=r-1 and D=phi(r). Define + + h_j = 1 / product_(s=1)^j (1-u^s), + P(z) = sum_(j=0)^n h_j z^j, + f(z) = r P(z). + +For every such r and u, P has no zero on the complex unit circle. +Put H=2^r-1 and delta_r=1/(2rn H^(nD-1)). For every complex +z with |z|=1, + + |P(z)| >= delta_r. + +This bound does not depend on the order of z. In particular, it holds +at all eigenvalues of a cyclic shift of any length. The old bound from +the algebraic norm of P at a root of unity depends on that root's order. +The new bound removes that dependence. + +There is also an operator bound that does not require root +classification. For any complex scalar tau with |tau|=1, +any cyclic shift Z_L with L>=1, and any integer w, put U=tau Z_L^w. Then + + ||P(U)^-1||_infinity <= delta_r^-1 + 2nH/(r delta_r^2). + +The bound has logarithm O(r^2 phi(r)), hence O(r^3). It is uniform +in L, w, and tau. The induced infinity norm is the maximum absolute +row sum. This bound does not supply a complete O(p polylog p) guard +for growing radix families. Efficient coefficient preparation, rounded +execution, scratch restoration, and a fast fixed-tape circuit remain open. No integer +kappa, complex b, or BIT c changes in this result. + +For an odd prime q, D=n=q-1, so the circle bound becomes + + delta_q = 1/(2q(q-1) (2^q-1)^((q-1)^2-1)). + +The result includes dyadic r>=4. For r=2, P(z)=1+z/2; the geometric +series gives ||P(U)^-1||_infinity<=2. No result for other composite +radices is claimed. The ideal argument below requires a prime power. + +## Integral polynomial and unit roots + +The identity product_(s=1)^(r-1)(1-u^s)=r gives + + f(z) = sum_(j=0)^n a_j z^j, + a_j = product_(s=j+1)^n (1-u^s). + +All a_j are algebraic integers in K=Q(u), and a_n=1. Thus f is +monic. Every root of f is an algebraic integer. + +Take any root alpha and a number field E that contains K and alpha. +The algebraic integer 1-u is not a unit in E, since + + |Norm_(E/Q)(1-u)| = ell^[E:K] > 1. + +Here Norm_(K/Q)(1-u)=Phi_r(1)=ell. The prime-power cyclotomic +polynomial is Phi_r(x)=sum_(j=0)^(ell-1) x^(j r/ell). + +There is a maximal ideal m in the ring of integers of E that contains +1-u. Modulo m, all a_j with j=3, the two embeddings are distinct. Bound the other +D-2 factors by H^(2n). This gives + + 1 <= |Norm_(K/Q)(R)| <= |R|^2 H^(2n(D-2)), + |R| >= H^(-n(D-2)). + +The equation S adj(S) e_0 = R e_0 gives polynomials A and C of +degree below n with + + A(z) f(z) + C(z) f*(z) = R. + +Each coefficient of A and C is a cofactor of S. A cofactor is a +determinant of size 2n-1. Deleting a row and a column cannot +increase the Euclidean norm of any retained column. Therefore each +cofactor has modulus at most H^(2n-1). For |z|=1, + + |A(z)| + |C(z)| <= 2n H^(2n-1), + |f*(z)| = |f(z)|. + +The Bezout identity gives + + |f(z)| >= H^(-n(D-2)) / (2n H^(2n-1)) + = 1 / (2n H^(nD-1)). + +Divide by r to obtain the stated bound for P. Neither this proof +nor its constants use the degree of a root of unity at which P is +evaluated. + +## An inverse bound from Fourier coefficients + +Let g(t)=1/P(exp(it)). The circle bound gives |g(t)|<=delta_r^-1. +The coefficient bound gives + + |P'(exp(it))| <= nH/r, + |g'(t)| <= nH/(r delta_r^2). + +Let c_k be the Fourier coefficients of g, with the average integral +on [0,2 pi] as the normalization. Parseval's identity for g' gives + + sum_k k^2 |c_k|^2 <= (nH/(r delta_r^2))^2. + +The estimate sum_(k!=0) k^-2 <= 4 follows from comparison of the +positive tail with the integral of x^-2 on [1,infinity). By the +Cauchy-Schwarz inequality and |c_0|<=delta_r^-1, + + sum_k |c_k| <= delta_r^-1 + 2nH/(r delta_r^2). + +Thus the Fourier series is absolutely convergent. Its product with +the finite polynomial P(exp(it)) has Fourier coefficients equal to +those of the constant one. For U=tau Z_L^w, every integer power U^k +has infinity norm one. The absolutely convergent matrix series + + sum_(k in Z) c_k U^k + +therefore has norm at most sum_k |c_k|. Multiplication by P(U) gives +the identity matrix, by the same coefficient identities. This proves +the stated inverse bound for all L, w, and unit tau. + +This is a bound for the exact operator. It is not a paid +coefficient-preparation or rounded-program theorem. The infinite +series is used to prove the norm bound, not as a declared algorithm. + +## Products and unit gauges + +For a finite family of such kernels with r_i>=3 on the same cyclic array, put + + C = product_i P_i(tau_i Z_L^(w_i)). + +Each factor is invertible. Submultiplicativity gives + + ||C^-1||_infinity <= product_i [delta_i^-1 + 2n_i H_i/(r_i delta_i^2)]. + +A diagonal conjugation with entries of modulus one preserves this +norm. Thus this bound also applies to a unit-gauged product. Its +logarithm is O(sum_i r_i^2 phi(r_i)). The bound concerns arbitrary +input vectors. It does not give operation counts or a tape schedule. + +## Value, sources, and remaining work + +This result permits inner roots and proves a uniform circle bound for +every primitive root choice. It supplies an explicit all-length inverse +bound for each growing prime-power radix. For an odd prime q and a root of unity xi, a direct algebraic norm +argument in E=Q(u,xi) gives + + |P_q(xi)| >= q^-1 (2^q-1)^(-([E:Q]-1)). + +The degree of E can grow with the order of xi. The new bound uses +Q(u) only and controls every point on the unit circle. The logarithm +of its inverse upper bound still grows polynomially with r. It does +not establish the required combined precision guard or change the +full-array traffic of the literal filter chain. A sharper lower bound +and a paid implementation remain useful next questions. + +The polynomial is from the pinned OpenAI exact-DFT preprint: + +https://github.com/openai/math/blob/adc7f1241b42e322a6451854ab7e4b4c146bf78a/preprints/An-explicit-power-saving-for-the-exact-discrete-Fourier-transform-September-25-2026/build/sections/local.tex + +The unit-ideal argument extends the prior unpublished local note +"Cyclic polynomial stability, norm growth, and rescaling". The prior +local note "Full-output cyclic quotient: exact structure and cost" +supplies the cyclic inverse context. The field arithmetic in the +finite verifier uses the prior local exact-arithmetic scaffold. +The resultant and cofactor estimates use standard algebraic and +linear-algebra facts. Repository and literature novelty checks are +separate from this proof. No priority claim is made here. + +Prepared with OpenAI Codex assistance. Apache-2.0. diff --git a/research/averaged-cyclotomic-height/vendor/pr621/independent_verify.py b/research/averaged-cyclotomic-height/vendor/pr621/independent_verify.py new file mode 100644 index 0000000000..813ffd0304 --- /dev/null +++ b/research/averaged-cyclotomic-height/vendor/pr621/independent_verify.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +"""Check the cyclotomic identities with independent SymPy arithmetic.""" + +import argparse +import json +from math import gcd +from pathlib import Path +from sympy import Poly, QQ, Symbol, cyclotomic_poly +from sympy.polys.matrices import DomainMatrix + + +def require(condition): + if not condition: + raise ValueError('Exact identity check failed') + + +def check(q, power): + x, z = (Symbol('x'), Symbol('z')) + field = QQ.alg_field_from_poly(Poly(cyclotomic_poly(q, x), x), alias='u') + u = field([1, 0]) + n = q - 1 + residue_prime = int(cyclotomic_poly(q, x).subs(x, 1)) + require(residue_prime >= 2) + + def embed(value, exponent): + result = field.zero + root = u ** (exponent % q) + for coefficient in value.to_list(): + result = result * root + field(coefficient) + return result + + def encode(value): + return [str(coefficient) for coefficient in value.to_list()] + + prefix = field.one + f = [] + for j in range(q): + if j: + prefix *= field.one - u ** (power * j % q) + f.append(field(q) / prefix) + require(f[0] == field(q) and f[-1] == field.one) + for j in range(q): + product = field.one + for s in range(j + 1, q): + product *= field.one - u ** (power * s % q) + require(f[j] == product) + coefficients = f[j].to_list() + require(all((coefficient.denominator == 1 for coefficient in coefficients))) + require(int(sum(coefficients)) % residue_prime == (1 if j == n else 0)) + star = [embed(value, -1) for value in reversed(f)] + matrix = [[field.zero] * (2 * n) for _ in range(2 * n)] + for polynomial, start in ((f, 0), (star, n)): + for offset in range(n): + for degree, coefficient in enumerate(polynomial): + matrix[degree + offset][start + offset] = coefficient + dm = DomainMatrix(matrix, (2 * n, 2 * n), field) + determinant = dm.det() + require(determinant != field.zero) + require(embed(determinant, -1) == determinant) + require(all(coefficient.denominator == 1 + for coefficient in determinant.to_list())) + require(int(sum(determinant.to_list())) % residue_prime + == (-1) ** n % residue_prime) + inverse = dm.inv().to_list() + cofactor_column = [row[0] * determinant for row in inverse] + require(all(coefficient.denominator == 1 + for value in cofactor_column for coefficient in value.to_list())) + for row, values in enumerate(matrix): + actual = sum((value * cofactor for value, cofactor in + zip(values, cofactor_column)), field.zero) + require(actual == (determinant if row == 0 else field.zero)) + real_norm = field.one + for exponent in range(1, q // 2 + 1): + if gcd(exponent, q) == 1: + real_norm *= embed(determinant, exponent) + require(len(real_norm.to_list()) == 1) + require(real_norm.to_list()[0].denominator == 1) + require(real_norm != field.zero) + full_norm = field.one + for exponent in range(1, q): + if gcd(exponent, q) == 1: + full_norm *= embed(determinant, exponent) + require(full_norm == real_norm * real_norm) + fp = Poly.from_list(list(reversed(f)), z, domain=field) + gp = Poly.from_list(list(reversed(star)), z, domain=field) + require(fp.gcd(gp).degree() == 0) + require(fp.rep.resultant(gp.rep) == field((-1) ** n) * determinant) + inverse_checks = [] + pp = fp.quo_ground(q) + for length in (1, 2, 4, 8): + modulus = Poly(z ** length - 1, z, domain=field) + reciprocal = pp.invert(modulus) + require((pp * reciprocal).rem(modulus) == Poly(1, z, domain=field)) + inverse_checks.append(length) + unit = Poly(z ** n - 1, z, domain=field) + unit_star = -unit + require(unit.resultant(unit_star) == 0) + missing_conjugation = Poly.from_list(f, z, domain=field) + bad = False + for exponent in range(q): + point = u ** exponent + v = fp.rep.eval(point) + r = missing_conjugation.rep.eval(point) + if v * embed(v, -1) != r * embed(r, -1): + bad = True + break + require(bad) + return { + 'order': q, + 'residue_prime': residue_prime, + 'field_degree': int(field.mod.degree()), + 'primitive_power': power, + 'coefficient_order': 'descending powers of u', + 'resultant': encode(determinant), + 'real_subfield_norm': encode(real_norm)[0], + 'full_field_norm': encode(full_norm)[0], + 'cofactor_identity': True, + 'primitive_ideal_reduction': 'f=z^(order-1), determinant=(-1)^(order-1)', + 'exact_cyclic_inverse_lengths': inverse_checks, + 'unit_root_negative_control': 'zero resultant', + 'missing_conjugation_negative_control': 'different exact squared modulus', + } + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--output', type=Path) + args = parser.parse_args() + cases = [check(radix, power) for radix, power in + ((3, 1), (4, 1), (5, 2), (7, 1), (8, 1), (8, 3), + (9, 1), (11, 1), (11, 4))] + result = { + 'status': 'PASS', + 'scope': 'Exact finite identities. The written proof supplies the uniform theorem.', + 'cases': cases, + } + payload = json.dumps(result, indent=2) + '\n' + if args.output is None: + print(payload, end='') + else: + args.output.write_text(payload) diff --git a/research/averaged-cyclotomic-height/vendor/pr621/verify.py b/research/averaged-cyclotomic-height/vendor/pr621/verify.py new file mode 100644 index 0000000000..20a069f42a --- /dev/null +++ b/research/averaged-cyclotomic-height/vendor/pr621/verify.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python3 +"""Check exact polynomial and resultant identities for prime-power inputs.""" + +from fractions import Fraction as F +from pathlib import Path +import argparse +import json +from math import gcd + + +def require(condition): + if not condition: + raise ValueError("Exact identity check failed") + + +def trim(a): + while len(a) > 1 and a[-1] == 0: + a.pop() + return a + + +def subtract(a, b): + c = [F(0)] * max(len(a), len(b)) + for j, x in enumerate(a): + c[j] += x + for j, x in enumerate(b): + c[j] -= x + return trim(c) + + +def multiply(a, b): + c = [F(0)] * (len(a) + len(b) - 1) + for i, x in enumerate(a): + for j, y in enumerate(b): + c[i + j] += x * y + return trim(c) + + +def divide(a, b): + a = trim(list(a)) + c = [F(0)] * max(1, len(a) - len(b) + 1) + while a != [0] and len(a) >= len(b): + k, x = len(a) - len(b), a[-1] / b[-1] + c[k] += x + for j, y in enumerate(b): + a[k + j] -= x * y + trim(a) + return trim(c), a + + +class Field: + def __init__(self, r): + p = next(j for j in range(2, r + 1) if r % j == 0) + remainder = r + while remainder % p == 0: + remainder //= p + require(r >= 3 and remainder == 1) + step = r // p + self.q, self.n, self.prime = r, (p - 1) * step, p + self.modulus = [F(0)] * (self.n + 1) + for j in range(p): + self.modulus[j * step] = F(1) + self.zero = (F(0),) * self.n + self.one = (F(1),) + (F(0),) * (self.n - 1) + + def reduce(self, a): + a = divide(a, self.modulus)[1] + return tuple(a + [F(0)] * (self.n - len(a))) + + def root(self, j): + return self.reduce([F(0)] * (j % self.q) + [F(1)]) + + def add(self, a, b): + return tuple(x + y for x, y in zip(a, b)) + + def sub(self, a, b): + return tuple(x - y for x, y in zip(a, b)) + + def scale(self, a, x): + return tuple(y * x for y in a) + + def mul(self, a, b): + return self.reduce(multiply(a, b)) + + def inv(self, a): + require(a != self.zero) + r0, r1, s0, s1 = self.modulus, trim(list(a)), [F(0)], [F(1)] + while r1 != [0]: + c, r = divide(r0, r1) + r0, r1 = r1, r + s0, s1 = s1, subtract(s0, multiply(c, s1)) + require(len(r0) == 1 and r0[0] != 0) + return self.reduce([x / r0[0] for x in s0]) + + def embed(self, a, power): + out = self.zero + for j, x in enumerate(a): + out = self.add(out, self.scale(self.root(power * j), x)) + return out + + def conjugate(self, a): + return self.embed(a, -1) + + +def poly_product(k, a, b): + out = [k.zero] * (len(a) + len(b) - 1) + for i, x in enumerate(a): + for j, y in enumerate(b): + out[i + j] = k.add(out[i + j], k.mul(x, y)) + return out + + +def evaluate(k, a, z): + out = k.zero + for x in reversed(a): + out = k.add(k.mul(out, z), x) + return out + + +def sylvester(k, a, b): + n = len(a) - 1 + require(len(b) == n + 1) + out = [[k.zero for _ in range(2 * n)] for _ in range(2 * n)] + for offset, polynomial in ((0, a), (n, b)): + for j in range(n): + for i, x in enumerate(polynomial): + out[i + j][j + offset] = x + return out + + +def eliminate(k, matrix, boundary=None): + a = [list(row) for row in matrix] + b = list(boundary) if boundary is not None else None + determinant = k.one + for col in range(len(a)): + pivot = next((j for j in range(col, len(a)) if a[j][col] != k.zero), None) + if pivot is None: + return k.zero, None + if pivot != col: + a[col], a[pivot] = a[pivot], a[col] + if b is not None: + b[col], b[pivot] = b[pivot], b[col] + determinant = k.scale(determinant, -1) + value = a[col][col] + determinant = k.mul(determinant, value) + reciprocal = k.inv(value) + for j in range(col, len(a)): + a[col][j] = k.mul(a[col][j], reciprocal) + if b is not None: + b[col] = k.mul(b[col], reciprocal) + for row in range(len(a)): + if row == col: + continue + value = a[row][col] + for j in range(col, len(a)): + a[row][j] = k.sub(a[row][j], k.mul(value, a[col][j])) + if b is not None: + b[row] = k.sub(b[row], k.mul(value, b[col])) + return determinant, b + + +def case(r, power): + k, n = Field(r), r - 1 + require(gcd(r, power) == 1) + tail = [k.zero] * r + tail[-1] = k.one + for j in range(n - 1, -1, -1): + tail[j] = k.mul(tail[j + 1], k.sub(k.one, k.root(power * (j + 1)))) + require(tail[0] == k.scale(k.one, r)) + kernel = [k.one] + for j in range(1, r): + kernel.append(k.mul(kernel[-1], k.inv(k.sub(k.one, k.root(power * j))))) + require(tail == [k.scale(x, r) for x in kernel]) + for j in range(r): + require(all(x.denominator == 1 for x in tail[j])) + require(sum(tail[j]) % k.prime == (1 if j == n else 0)) + star = [k.conjugate(x) for x in reversed(tail)] + require([k.conjugate(x) for x in reversed(star)] == tail) + for j in range(r): + require(sum(star[j]) % k.prime == (1 if j == 0 else 0)) + matrix = sylvester(k, tail, star) + boundary = [k.one] + [k.zero] * (2 * n - 1) + resultant, solution = eliminate(k, matrix, boundary) + require(resultant != k.zero) + require(all(x.denominator == 1 for x in resultant)) + residue = (-1) ** n % k.prime + require(sum(resultant) % k.prime == residue) + a, b = solution[:n], solution[n:] + af, bs = poly_product(k, a, tail), poly_product(k, b, star) + require([k.add(x, y) for x, y in zip(af, bs)] == boundary) + norm = k.one + for embedding in range(1, r): + if gcd(embedding, r) == 1: + norm = k.mul(norm, k.embed(resultant, embedding)) + require(all(x == 0 for x in norm[1:]) and norm[0].denominator == 1 and norm[0] != 0) + for j in range(r): + value, reverse = evaluate(k, tail, k.root(j)), evaluate(k, star, k.root(j)) + require(k.mul(value, k.conjugate(value)) == k.mul(reverse, k.conjugate(reverse))) + unit = [k.scale(k.one, -1)] + [k.zero] * (n - 1) + [k.one] + unit_star = [k.conjugate(x) for x in reversed(unit)] + require(eliminate(k, sylvester(k, unit, unit_star))[0] == k.zero) + bad_star = list(reversed(tail)) + require(any(k.mul(evaluate(k, tail, k.root(j)), k.conjugate(evaluate(k, tail, k.root(j)))) != + k.mul(evaluate(k, bad_star, k.root(j)), k.conjugate(evaluate(k, bad_star, k.root(j)))) + for j in range(r))) + return {"radix": r, "prime": k.prime, "field_degree": k.n, + "polynomial_degree": n, "primitive_power": power, + "resultant": [str(x) for x in resultant], "resultant_norm": str(norm[0]), + "bezout_identity": True, "mod_ideal_resultant": residue, + "unit_root_negative_control": "singular", + "missing_conjugation_negative_control": "rejected", + "circle_bound_base": 2 ** r - 1, + "circle_bound_exponent": n * k.n - 1, + "circle_bound_denominator": 2 * r * n} + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--output", type=Path) + args = parser.parse_args() + cases = [case(r, power) for r, power in + ((3, 1), (4, 1), (5, 2), (7, 1), (8, 1), (9, 1), (11, 1), (11, 4))] + result = {"status": "PASS", "cases": cases, + "scope": "Exact finite identities. The written proof supplies the uniform theorem."} + payload = json.dumps(result, indent=2) + "\n" + if args.output is None: + print(payload, end="") + else: + args.output.write_text(payload) diff --git a/research/averaged-cyclotomic-height/vendor/pr628/NOTICE.md b/research/averaged-cyclotomic-height/vendor/pr628/NOTICE.md new file mode 100644 index 0000000000..22fbeb8ef0 --- /dev/null +++ b/research/averaged-cyclotomic-height/vendor/pr628/NOTICE.md @@ -0,0 +1,24 @@ +# Attribution and scope + +Ali Romman's PR621, exact head 520774462b19b29af41554b74def31f9d01e997e, +supplies the prime-power kernel circle bound. Its kernel attribution is +OpenAI's exact-DFT preprint at adc7f1241b42e322a6451854ab7e4b4c146bf78a +(`loc:newton`, `loc:fourier-factorization`) and classical q-Pochhammer/Newton +factorization, including Alexey Kuznetsov's cited q-calculus work. This +package does not claim to originate those constructions. + +Pan's approximate-factorization theorem is used in the form stated by +Mehlhorn, Sagraloff and Wang; Brent's work supplies fast elementary-function +evaluation. Causal/anticausal recursive filtering is standard, as illustrated +by the Briand-Davy source listed in SOURCE.json. Sources are cited for these +specific tools, not as proofs of this package's complete claim. + +The scan rounding analysis, explicit budget composition, interval and +factor certificates, routed reference execution, and packaging were +prepared with substantial OpenAI Codex assistance for chafreaky. The dense +matrix solver and algebraic coefficient crosschecks provide independent +computational paths, not human peer review or formal Lean verification. + +No new multiplication exponent, literature priority, maintainer acceptance, +physical tape execution, or production performance result is claimed. +The code and documents use the repository's Apache-2.0 license. diff --git a/research/averaged-cyclotomic-height/vendor/pr628/PROOF.md b/research/averaged-cyclotomic-height/vendor/pr628/PROOF.md new file mode 100644 index 0000000000..fb8fe7cb3b --- /dev/null +++ b/research/averaged-cyclotomic-height/vendor/pr628/PROOF.md @@ -0,0 +1,269 @@ +# Uniform preparation and rounded inversion of a neighboring cyclic kernel + +This note combines PR621's circle lower bound, standard approximate +factorization, and the local two-scan rounding lemma. It concerns a +neighboring cyclic shift with gauge 1 and clean input/output work arrays. +It is not a complete multiplication algorithm, reversible word, arbitrary +stride tape schedule, or new kappa result. The proof uses the cited +factorization theorem; the accompanying numerical nomination program does +not implement that theorem's worst-case algorithm. + +## Statement and model + +Let r>=3 be a prime power, k coprime to r, zeta=exp(2 pi i k/r), and + + P(z)=sum_(j=0)^(r-1) h_j z^j, + h_j=1/product_(s=1)^j(1-zeta^s). + +Let S be either neighboring cyclic shift on L>=1 entries. Given p>=1 +and an exactly supplied dyadic complex vector x with ||x||infinity<=1, +there is an algorithm producing y with + + ||y-P(S)^-1 x||infinity <= 2^-p. + +Coefficient preparation is independent of L. Both the required coefficient +bit lengths and the execution precision are O(p+r^4), including magnitude +bits. The array execution uses O(rL) rounded scalar operations and O(r) +sequential full-array passes. With ordinary near-linear integer arithmetic, +including a conservative exact coefficient-product verification in setup, +the bit-operation bound is + + soft-O((Lr+r^3)(p+r^4)). + +Here soft-O suppresses logarithms in the displayed parameters. Input +fractional precision is assumed at most the execution budget below; +longer exact inputs require their reading/rounding cost and a separately +charged input-error budget. Clean arrays and standard arithmetic scratch +are allowed. The scan layout is sequential for S=Z or Z^-1; this statement +does not assert that an arbitrary modular-stride permutation is free. +The setup bound uses the bit-complexity model of the cited factorization +result. A concrete fixed-tape implementation of its setup is not supplied. + +## Explicit budgets + +Put n=r-1, D=phi(r), ell=ceil(log2 r), and + + d=1+2 ell+r n D, + g=d+ell+2r+2, beta=2^-g, + a=ell+n g, Abar=2^a, + e=max(d+1, a+1, p+2a+3), epsilon=2^-e, + b=max(n ell, e+r+3), + w=max(2g+ceil(log2(14n)), + p+(n+2)g+ceil(log2(28n(r+1)))), u=2^-w. + +All these are computable integer budgets. Their sizes satisfy +d,g=O(r^3) and a,e,b,w=O(p+r^4). No array length occurs in them. +The executable budget checker verifies the integer inequalities used below +for a range of radices and precisions; the algebra proves them generally. + +## Approximate factorization and preparation + +Define f=rP. Its leading coefficient is 1 and its coefficients are + + f_j=product_(s=j+1)^(r-1)(1-zeta^s). + +Thus ||f||_1<=H=2^r-1, and Cauchy's bound places all roots inside +|z|<=1+H<2^(r+1). Its logarithmic root bound is O(r). + +Pan's approximate-factorization theorem, in Theorem 2 and Corollary 1 of +Mehlhorn, Sagraloff and Wang [1], provides dyadics rho_1,...,rho_n with +||f-product_j(z-rho_j)||_1<=2^-b ||f||_1. Its factorization cost is +soft-O(n b+n^2 Gamma), with coefficient-oracle precision O(b+n Gamma), +where Gamma bounds the logarithmic root magnitudes. Repeated roots do not +require a distinct-root count for this factorization step. + +Let Q=(1/r) product_j(z-rho_j). Our choice b>=e+r+3 gives + + ||P-Q||_1 < epsilon/8. + +Only this coefficient error is needed. We do not isolate the true roots, +match approximate roots to true roots, or require simple roots. + +The coefficient oracle is also charged. Compute zeta to the requested +precision, its first r powers, and the backward products defining f_j. +There are O(r) complex operations. Products have magnitude at most 2^r; +guarding by O(r+log r) bits bounds coefficient errors. Fast elementary +function evaluation [2] supplies the required pi, sine and cosine values +with near-linear precision cost up to logarithms. Hence the oracle fits +soft-O(r(p+r^4)). This is an algorithmic preparation argument, not a +complexity claim about the Fraction/Decimal reference scripts. + +An independent certificate can expand the dyadic-root product exactly and +compare it with rigorous coefficient enclosures of total componentwise +error at most epsilon/8. Replacing complex moduli by the sum of absolute +real and imaginary parts costs at most a factor of 2, so the resulting +upper bound is still below epsilon. Exact expansion +of n B-bit roots has O(nB)-bit coefficients; a simple iterative expansion +costs soft-O(n^3 B) bit operations, B=O(p+r^4). This conservative setup +cost is included in the theorem. Faster expansion is unnecessary here. + +## Stability without individual root certification + +PR621 gives |P(z)|>=delta on |z|=1, where + + delta=1/[2rn H^(nD-1)] >= 2^-d. + +The coefficient certificate and e>=d+1 imply |Q(z)|>=delta/2 on the +unit circle. Also ||Q||_1<=H/r+epsilon<=H/r+1<=2^r. + +For any root rho of Q at radial distance t=||rho|-1|<1/2, integrate Q' +along the radial segment to the unit circle. On that segment |z|<2, so + + delta/2 <= t n 2^r 2^(n-1). + +Roots farther than 1/2 already have a fixed gap. Therefore every root of +Q lies at radial distance at least + + eta=min(1/2, delta/[2n 2^r 2^(n-1)]). + +Our g ensures beta<=eta/2. If |rho|>1, b_rho=1/rho has modulus at most +1-beta. If |rho|<1, b_rho=rho has modulus at most 1-beta. These comparisons +can be made exactly on the dyadic rho. Inverting an outer rho produces +an exact rational complex coefficient with O(p+r^4) numerator and +denominator bits; it need not be rounded to a dyadic. + +For each factor, + + (S-rho I)^-1 = -rho^-1 (I-rho^-1 S)^-1 if |rho|>1, + (S-rho I)^-1 = (I-rho S^-1)^-1 S^-1 if |rho|<1. + +Each stable inverse has norm at most beta^-1. Outer scalar factors have +modulus less than 1, while the inner shift has norm 1. Apply the scalar r +to the input first. Exact stage-j values have norm at most r beta^-j. +In particular, ||Q(S)^-1||<=r beta^-n<=Abar, uniformly in L. + +Since epsilon Abar<=1/2, a Neumann perturbation bound gives + + ||P(S)^-1-Q(S)^-1|| + <= Abar^2 epsilon/(1-Abar epsilon) + <= 2 Abar^2 epsilon <= 2^(-p-2). + +This is an operator bound for arbitrary input vectors, not just samples +or a particular Fourier mode. + +## Rounded execution + +Use the two-scan periodic first-order procedure proved in +SCAN-PROOF.md, with grid u and exact rational coefficients. +An inner factor scans in the opposite direction and includes the unit +cyclic shift. An outer factor includes a final rounded multiplication by +-rho^-1. The per-factor error is bounded by + + 7(B+1)u/beta^3 + +for input norm B. The constant 7 includes the outer scalar multiplication; +the original scan constant is 6. Copying and shifting dyadic entries is +exact. Multiplying the original dyadic input by integer r is exact. + +If E_j is the error after j factors, then E_0=0 and + + E_j <= E_(j-1)/beta + +7(r beta^(-(j-1))+E_(j-1)+1)u/beta^3. + +Set T_j=beta^j E_j. Since beta<=1 and j>=1, + + T_j <= (1+7u/beta^2)T_(j-1)+7(r+1)u/beta^2. + +The budget u<=beta^2/(14n) implies +(1+7u/beta^2)^n<=exp(1/2)<2. Consequently + + E_n <= 14n(r+1)u beta^(-(n+2)) <= 2^(-p-1). + +Adding the factorization perturbation yields at most 3*2^(-p-2)<2^-p. +All scan intermediates have O(p+r^4) bits including integer magnitude. +In particular, b_rho^L is accumulated with rounding at every step, so its +representation does not grow with L. The closure denominator stays at +least beta/2, by the single-factor proof. + +Exact rational multiply/add followed by dyadic rounding and the one +closure division use integers of O(p+r^4) bits. Standard fast integer +multiplication and division give the stated scalar bit cost. A bounded +number of sequential passes suffices per factor, including rewinds and +the unit cyclic rotation. Two alternating clean data arrays suffice for +the streaming values. A conservative space allowance is +soft-O((L+r^2)(p+r^4)) bits, including setup and arithmetic scratch. + +## Paid unit phases + +The same factor certificate works for U=tau S when tau is an exactly +supplied rational complex number of modulus 1. In an outer factor, the +scan coefficient becomes tau/rho and the final scalar remains -1/rho. +In an inner factor, it becomes rho/tau; after the backward scan and unit +shift, multiply by tau^-1. Both new coefficients retain the same margin +beta. The inner scalar has modulus 1, so the same constant 7 covers its +rounded multiplication. If tau has T representation bits, scalar +arithmetic costs use O(p+r^4+T)-bit operands; T is not silently free. + +More generally suppose a unit tau has a charged approximation oracle. +Choose a rational unit sigma with |tau-sigma|<=nu, where + + nu <= epsilon/(n 2^r). + +Then ||P(tau S)-Q(sigma S)||<=epsilon+n||Q||_1 nu<=2 epsilon. +Because e>=p+2a+3, we still have 2 epsilon Abar<=1/2 and + + ||P(tau S)^-1-Q(sigma S)^-1|| + <=4 Abar^2 epsilon<=2^(-p-1). + +The same rounded execution budget contributes at most 2^(-p-1), giving +the original target 2^-p. The phase needs O(p+r^4) approximation bits, +in addition to reading whatever representation defines it. + +Here is a constructive way to obtain sigma with exact unit modulus. +Choose C in {1,-1,i,-i} so v=C^-1 tau has Re(v)>=1/2. A coarse enclosure +suffices to choose such a chart: one coordinate of a unit vector has +absolute value at least 1/sqrt(2). Put t=Im(v)/(1+Re(v)). Its denominator +is at least 3/2. Approximate t by a dyadic t0 with |t-t0|<=nu/2 and set + + sigma=C (1-t0^2+2i t0)/(1+t0^2). + +This is exactly rational and unit. The stereographic map's derivative +has modulus 2/(1+t^2)<=2, proving |tau-sigma|<=nu. Obtaining t0 costs +the oracle request plus scalar arithmetic at the stated precision. +For a phase exp(2 pi i h/m), [2] supplies that oracle after the cost of +reading/reducing the integer phase description; a very long h or m is +an extra input cost and is not covered by a bound that omits its length. + +This section treats a single constant unit phase. WEIGHTED-PROOF.md +extends the same bounds to a unit-weighted neighboring shift with an +independent phase at each position. The full transform's collection of +phases still needs its composition and preparation accounting. + +## Scope and finite evidence + +For r bounded by a fixed power of log p, the cost is quasi-linear in p +up to polylogarithmic factors and polynomial dependence on that radix. +There is no extra factor proportional to p in the number of full-array +passes. This removes the repeated-Neumann-pass obstruction for this +neighboring, clean-array inverse primitive. + +The mixed-factor reference certificate at CERTIFICATE-PROOF.md checks +ten kernel/embedding cases through radix 16, including inner roots, exact +rational unit phases, and a certified rational approximation of +exp(2 pi i/7). It uses exact coefficient enclosures, exact factor products, +and an explicit rounding budget. These finite certificates do not implement Pan's +worst-case factorizer or prove its complexity. The uniform argument above +depends on [1], [2], PR621, and the proved scan lemma. + +Remaining work for a multiplication application includes the complete +collection of phase gauges and their paid preparation, the actual strides/layout of every kernel, +composition across the complete transform and recursion, its total +precision guard, input/output normalization, and restoration of dirty +scratch where required. None is inferred from this standalone theorem. + +## Sources and attribution + +[1] K. Mehlhorn, M. Sagraloff, P. Wang, *From Approximate Factorization to +Root Isolation with Application to Cylindrical Algebraic Decomposition*, +Theorem 2 and Corollary 1 (crediting V. Pan), +https://arxiv.org/pdf/1301.4870, PDF page 8. + +[2] R. P. Brent, *Fast multiple-precision evaluation of elementary +functions*, J. ACM 23 (1976), 242-251, +https://maths-people.anu.edu.au/~brent/pub/pub034.html. + +PR621 by aliromman, head 520774462b19b29af41554b74def31f9d01e997e, +supplies the kernel and circle bound. Causal/anticausal filtering and +approximate factorization are standard methods. The explicit budget +composition and reference certificates here were prepared with OpenAI +Codex for chafreaky. No literature-priority claim is made. diff --git a/research/averaged-cyclotomic-height/vendor/pr628/interval_kernel.py b/research/averaged-cyclotomic-height/vendor/pr628/interval_kernel.py new file mode 100644 index 0000000000..1182175a55 --- /dev/null +++ b/research/averaged-cyclotomic-height/vendor/pr628/interval_kernel.py @@ -0,0 +1,61 @@ +"""Outward-rounded rational enclosures for prime-power cyclic kernels.""" +from fractions import Fraction as F +import math +from functools import lru_cache + +BITS=1536 +SCALE=1<4:raise ValueError('angle bound') + itheta=(point(0),theta) + total=term=ONE + # Taylor remainder for complex exp: <=exp(4)*4^(N+1)/(N+1)! <128*... + n=0 + while True: + n+=1;term=cmul(term,itheta);term=(scale(term[0],F(1,n)),scale(term[1],F(1,n)));total=cadd(total,term) + remainder=F(128*4**(n+1),math.factorial(n+1)) + if remainder=3, the PR628 neighboring +cyclic scan needs working precision + + max(p,w) + O(r^3 + log(D+1)), + +including integer magnitude bits, to approximate the inverse to absolute +error 2^-p on a source of norm <=D initially on the 2^-w grid. The same +precision suffices for coarse-grid in-place source recovery. The previous +uniform scan composition charged O(r^4) because it propagated every local +error through a product of individual reciprocal margins. Here every +partial inverse is bounded by the full inverse and complementary factors. + +Array execution still costs O(rL) rounded scalar operations. With the same +charged approximate-factorization and coefficient-verification algorithms, +the bit cost for a neighboring cyclic layout is + + soft-O((Lr+r^3)(max(p,w)+r^3+log(D+1))). + +This is a standard-arithmetic, supplied-layout theorem. The worst-case +factorization and fast arithmetic are inherited algorithms, not implemented +by the Fraction reference. The restored-source version needs owned widened +source words whose low working bits are initially zero; those bits are +charged. No arbitrary dirty-bit, Clifford, common-label, complete-transform +or multiplication-exponent claim follows. +Phase-oracle costs and the cost of reading a longer phase description are +additional to the displayed bit bound. + +## Full inverse controls every partial inverse + +Let U be an invertible isometry in the maximum norm: ||U^k||=1 for every +integer k. A unit-weighted permutation, including a weighted cyclic shift, +has this property. Let + + f(z)=product_(j=1)^n (z-rho_j) = s Q(z), + M >= sum_j |Q_j|, ||Q(U)^-1|| <= A. + +Assume Q(U) is invertible. All factors are polynomials in the **same U**. +The assertion below does not apply to different noncommuting shifts. + +For a monic polynomial f define its Mahler measure + + M(f)=product_j max(1,|rho_j|). + +For completeness, the elementary circle identity +mean_t log|exp(it)-rho| = log max(1,|rho|) follows by integrating the +power series of log(1-z) when |z|<1 and factoring out rho when |rho|>1. +There are no unit-circle roots in this application. Summing the identities, +then applying concavity of log and Parseval, gives + + log M(f) = mean log|f(exp(it))| + <= (1/2) log(mean |f(exp(it))|^2) + = (1/2) log(sum_j |f_j|^2). + +Thus M(f)<=||f||_2<=||f||_1<=sM. For any subset J of the root occurrences +(multiplicities included), the complementary factor has coefficient norm + + ||product_(j notin J)(z-rho_j)||_1 + <= product_(j notin J)(1+|rho_j|) + <= 2^n M(f) <= 2^n sM. + +As the factors commute, + + product_(j in J)(U-rho_j I)^-1 + = product_(j notin J)(U-rho_j I) Q(U)^-1 / s. + +Every such inverse, including every prefix and every contiguous suffix, +therefore has norm <= B=max(1,2^n M A). Importantly, log B depends on the +full inverse bound, not n times the worst individual reciprocal margin. + +For later source restoration, let K_j=1+|Re rho_j|+|Im rho_j|. Then +K_j<=3 max(1,|rho_j|), so every forward subproduct has norm bounded by +its product of K_j, which is <=F=3^n sM. This also bounds amplification of +the rounding errors introduced during forward restoration. + +## Rounded execution without repeated reciprocal-margin multiplication + +Suppose every factor is implemented by PR628's stable scan with margin +beta, and u=2^-W<=beta^2/2. Including the final outer scalar or inner unit +shift, its local error for an input of norm <=X is at most + + a (X+1)u, a=7 beta^-3. + +Begin with s x and apply all n inverse factors. The exact prefix norm is +<=sBD. Let E_j be the computed prefix error, E=max_(0<=j<=n) E_j, and +delta_j the local error at stage j. Then + + |delta_j| <= a(sBD+E+1)u. + +The error at any prefix is the sum of earlier delta_j propagated through +contiguous inverse subproducts. Each propagation has norm <=B, hence + + E <= nBa(sBD+E+1)u. + +For t=nBa u<1 this implies + + E <= t(sBD+1)/(1-t). (1) + +This rearrangement is not an inductive assumption that the error is small: +all finite computed prefixes exist by the stable closure condition, and +their maximum obeys the displayed inequality. The strict contraction +condition then bounds it. The verifier compares every prefix with an +independent exact dense oracle in its small-cycle cases. + +## Recovering a coarse-grid source + +The cyclic inverse's first pass computes the boundary seed read-only. Its +second pass reads each original source entry before overwriting that slot. +An inner factor's unit shift is performed in place with one saved boundary +entry; an outer factor needs a scalar pass. Thus no full-length intermediate +array is required for evaluation on a neighboring cyclic layout. + +After adding the computed inverse to a distinct working-grid target, +apply the forward factors in reverse order. Each forward pass saves the +original cyclic predecessor before overwriting the current entry. It has +error at most u per output entry. Divide by s and round at W bits. Relative +to the original source, the resulting error is at most + + R <= F E/s + nF u/s + u. (2) + +Alternatively, the finite checker uses the sharper exact recurrence +R=E, then R=K_j R+u for j=n,...,1, then R=R/s+u. If R<2^(-w-1), rounding +each component to the original grid recovers the source exactly. The target +increment is independent of its initial value. The low W-w source bits +are explicit reserved zeros; their capacity is 2L(W-w) bits. Integer guards, +target widening and arithmetic workspace are also charged. + +For a fixed coarse-grid external shear, round the computed increment to +the original grid before its exact addition to the target. The resulting +function f(x) approximates Q(U)^-1 x, depends only on x, and gives the exact +grid bijection (x,y)->(x,y+f(x)). Subtracting the identical f(x) is its inverse. +All arrays then stay on the same coarse grid between calls. The separate +composition proof gives a fixed (w,W) budget for an entire prescribed word; +it does not require new low bits at every stage. + +## Explicit prime-power budgets + +Let r>=3 be a prime power, n=r-1, Dfield=phi(r), H=2^r-1 and +ell=ceil(log2 r), c=ceil(log2 n). To avoid overloading D, write the source +bound as D<=2^m with m>=0. PR621 supplies + + delta = 1/(2rn H^(n Dfield-1)), + |P(z)|>=delta on |z|=1, + ||P(U)^-1|| <= delta^-1 + 2nH/(r delta^2). + +Its absolutely summable Laurent-series argument applies to the isometry U +above, including varying unit phases. No phase table is constructed for +this norm argument. Put + + d=1+2ell+r n Dfield, delta>=2^-d, + a0=2d+r+2, ||P(U)^-1||<=2^a0, + g=d+ell+2r+2, beta=2^-g, + h=a0+2r, + e=max(d+1,a0+1,p+2a0+m+3), epsilon=2^-e, + b=max(n ell,e+r+3). + +As in PR628, approximate-factorization and exact coefficient verification +produce dyadic roots for Q=(1/r)product(z-rho_j) with ||P-Q||_1<=epsilon. +The first two e constraints imply |Q|>=delta/2 on the circle and +||Q(U)^-1||<=2^(a0+1). The last one gives + + D ||P(U)^-1-Q(U)^-1|| <= 2^(-p-2). + +Also ||Q||_1<=H/r+epsilon<=2^r. PR628's radial derivative argument applied +to Q supplies the stated stable margin beta for its inner or reciprocal +outer roots. Consequently the complementary-factor bound gives B<=2^h. +The forward product bound gives F<=2^v for v=3r+ell. + +Define + + J=c+2h+3g+ell+m+5, + W=J+max(p+2,w+v+3). (3) + +This W satisfies u<=beta^2/2 and t<=1/2. Since rBD+1<=2^(ell+h+m+1), +equation (1) yields E<=2^(J-W)<=2^(-p-2). Combining with coefficient +perturbation gives total inverse error <=2^(-p-1), leaving extra slack. +Since 2^J>=n+1, equation (2) gives + + R <= 2^(v+J+1-W) <= 2^(-w-2) < 2^(-w-1), + +which proves exact source recovery after coarse rounding. + +These are explicit integer exponent inequalities, not numerical fits. +Using Dfield<=r, ell<=r, c<=r and r>=3 gives the convenient bounds + + W <= max(p,w)+12r^3+m, + b <= p+6r^3+m. + +For example, J+v+3 <= 7r^3+35r+25+m <=12r^3+m. Likewise +e+r+3<=p+4r^3+11r+14+m<=p+6r^3+m, and n ell<=r^2. +Intermediate magnitude bits also have order O(r^3+m): exact prefixes are +bounded by rBD, scan closure state adds at most O(g) magnitude bits, and +forward subproducts add O(r) bits. A target additionally needs the bits +for its own initial magnitude. Bounds (3) concern fractional precision; +the complete word width includes these integer bits. + +## Preparation, phases, and scope + +The monic exact polynomial rP has coefficient norm <=H and logarithmic +root bound O(r). Pan's approximate-factorization bound, as stated in +Mehlhorn–Sagraloff–Wang, Theorem 2 and Corollary 1, applies at b>=n log n +with cost soft-O(nb+n^2 Gamma) and O(b+n Gamma) coefficient precision. +Here Gamma=O(r) and b=O(p+r^3+m). The same coefficient oracle and +conservative exact product verification from PR628 cost +soft-O(r^3(p+r^3+m)); the latter forms exact O(rb)-bit coefficients. +Repeated roots need not be individually isolated. This inherits the cited +algorithms; the finite fixture checker does not implement their worst-case +runtime. [Approximate-factorization source](https://arxiv.org/pdf/1301.4870), +PDF page 8. + +A supplied exact rational unit phase uses its actual numerator/denominator +length in scalar costs. For an approximate phase oracle, bound the induced +polynomial coefficient perturbation separately and allocate additional +slack by replacing p with p+O(1). Its required precision is O(p+r^3+m) +under the same bounded description assumptions as PR628. An arbitrarily +long phase description remains an extra input cost. + +The proof applies to any implementation of each factor with the stated +local error bound. The concrete in-place and restored-source schedule here +covers neighboring cyclic layouts only. PR846's clean-tape arbitrary-stride +solver has a compatible local bound and an additional depth admission +condition; extending the present tape claim would require retaining that +condition and its clean-scratch model. That solver is not part of this +package or its certified source-restoration claim. + +The cubic improvement comes from bounding intermediate inverse products, +not from improving PR621's circle lower bound. The full multiplication +assembly, common-label and Clifford interfaces, arbitrary dirty storage, +transform-level phase and normalization accounting remain separate. +No new kappa, practical timing improvement, or literature-priority claim +is made. + +## Executable evidence and attribution + +The exact verifier checks 5,220 integer budgets over all 116 prime-power +radices from 3 through 512, five target precisions, three source precisions +and three magnitude bounds. These support implementation of (3); the +inequalities above are the all-size proof. + +There are 120 kernel executions on ten pinned PR628 fixtures, with both +directions, varying exact rational unit phases and lengths 1,2,3,8,17,64. +Sixty executions compare every prefix to independent dense solves. All +120 check the expanded polynomial residual, pre-round recovery error, +exact coarse-grid restoration and total true-kernel error <=2^-128. +The finite tests use PR628's existing, conservative supplied inverse-norm +certificates; they do not claim that those finite certificates are tighter +than every previous finite execution budget. Six controls reject omitted +complement growth, insufficient target/recovery/coefficient precision, +nonshared shifts and lost prefix contraction. + +Credit Ali Romman for PR621, Chafik Boukhalfa for PR628, and the standard +Mahler-measure, cyclic-filtering and approximate-factorization methods. +This extension was prepared by Chafik Boukhalfa with substantial OpenAI +Codex assistance. The independent dense checker is a separate implementation, +not an independent human or delegated-agent review. Source pins are in +`SOURCE.json`. diff --git a/research/averaged-cyclotomic-height/vendor/pr977/NOTICE.md b/research/averaged-cyclotomic-height/vendor/pr977/NOTICE.md new file mode 100644 index 0000000000..57939c758d --- /dev/null +++ b/research/averaged-cyclotomic-height/vendor/pr977/NOTICE.md @@ -0,0 +1,40 @@ +# Attribution and scope + +New effective-depth argument, cubic-stride integration and checks by Chafik +Boukhalfa (@chafreaky), with substantial OpenAI Codex assistance, under the +repository's Apache-2.0 license. No independent human/delegated-agent review +or literature-priority claim is made. + +- Rohan Guliani (@Rohansguliani), PR846, head + `4bdb3e755ea7118170a7a34764df955880dec282`: arbitrary-stride Euclidean + chain/closure solver, fixed-tape FIFO accounting, uniform error argument + and kernel integration. Its solver, checker, proof, source record and + notice are retained unchanged. `early.py` is an explicitly attributed + adaptation of its `solve` function, adding a charged exact-zero base case. +- Charles Bethin (@cbethin), PR764, head + `983d66f0f2e48ee500ec7eee2da9244c001c5064`: shared-suffix scan identity and + inverse-square error analysis, used through the retained PR846 proof. +- Chafik Boukhalfa, PR628, head + `0768f97d06c623b8211e651543c66135796b62bf`: root-factor certificates, + preparation/phase budgets and exact arithmetic. The five files retained + by PR846 remain byte-identical and independently hash-bound here. +- Chafik Boukhalfa, PR862, head + `57e0659150d323b784580110b36aa64a2dca2a33`: common-operator complement + bound and cubic preparation/execution precision. Its proof and notice + are retained unchanged. +- Ali Romman (@aliromman), PR621, head + `520774462b19b29af41554b74def31f9d01e997e`: prime-power kernel and its + uniform inverse bound, retained through the cited preparation lineage. + +Original notices retain the OpenAI exact-DFT manuscript, classical +Mahler/Wiener arguments, Pan factorization, fast elementary arithmetic, +and the standard queue-from-two-stacks attribution. Their credits and +licenses remain unchanged. Nearest-grid extinction and pointwise-zero +substitution are elementary; no priority claim is made for those ideas. + +The new result removes the stride solver's length-dependent precision +admission and combines its unchanged local error with PR862's cubic bound. +It does not replace the inherited preparation theorem with the finite root +fixtures or claim that the Python reference implements its asymptotic cost. +Clean scratch, phase access and all remaining transform/physical obligations +stay explicit. No new multiplication exponent is claimed. diff --git a/research/averaged-cyclotomic-height/vendor/pr977/PROOF.md b/research/averaged-cyclotomic-height/vendor/pr977/PROOF.md new file mode 100644 index 0000000000..6019f4d03f --- /dev/null +++ b/research/averaged-cyclotomic-height/vendor/pr977/PROOF.md @@ -0,0 +1,238 @@ +# An effective depth bound for the rounded stride solver + +This research argument extends PR846 at head +4bdb3e755ea7118170a7a34764df955880dec282. The original source is retained +unchanged in vendor/pr846/stride.py. Its clean scratch and sequential-tape model +remain unchanged. No borrowed-array, bit-reversible or kappa claim. + +Let beta=2^-g, g>=1, and let u=2^-W with W>=2g+8. Assume every input +coefficient has modulus at most 1-beta. Add one exact zero test at each +recursion level: when every coefficient is zero, return the data rounded +once. This solves that level exactly up to one rounding. Count the test as +one full coefficient scan and head return; traffic is at most 44L records instead of +the original conservative 40L. + +For the early-terminated solver, the number K of non-base levels is bounded independently of L by + + D(g,W)=2g+ceil(log2 W)+4. + +Consequently 4(K+1)u<=beta follows from W>=2g+8. This removes the original +p>=log2(log2 L+2) admission condition, after imposing this sufficient local +working-precision condition instead. + +## Decay of the rounded closure coefficients + +Write rho for the maximum coefficient modulus at a level. Every chain has +at least two coefficients. Its product is initialized with the first exact +coefficient and then rounded after each multiplication. For chain length +ell>=2, its magnitude is bounded by + + rho^ell+u*(1+rho+...+rho^(ell-2)) <= rho^2+u/(1-rho). + +Thus a scalar majorant for the next maximum is rho^2+u/(1-rho). + +First suppose beta<=m=1-rho<=1/2. Since u<=beta^2/16<=m^2/16, + + 1-rho_next >= m(2-m)-u/m >= (23/16)m > sqrt(2)m. + +Within at most 2g levels, the margin therefore reaches 1/2, unless recursion +has already terminated. While rho<=1/2, the majorant is rho^2+2u. +This stays below 1/2, and two further levels give rho<=1/4 (W>=10 is more +than sufficient for these elementary inequalities). + +While rho>2sqrt(u), the same majorant satisfies rho_next<=3rho^2/2. +For t=2rho, this implies t_next<=t^2, starting from t<=1/2. After at most +ceil(log2 W) additional levels, rho<=2sqrt(u): otherwise repeated squaring +would give rho<=2^(-2^j-1)<=u/2, a contradiction. + +One more level gives rho<=6u. At the following level the first multiplication +in every chain has modulus at most 36u^2=2g+8, ceil(log2 W)<=W-1 and 2g<=W-8, hence + + 4(D+1)<=8W-16. + +Also W-g>=ceil(W/2)+4 and 2^ceil(W/2)>=W for W>=4, so + + 2^(W-g)>=16W>4(D+1). + +This proves 4(K+1)u<=beta, and u<=beta/3 is automatic. PR846's margin, +weighted-data and shared-suffix error arguments now apply through at most +D levels. The new terminal system has exact solution x; rounding it once +has error at most u, matching the old terminal bound. Therefore the stated all-length error bound holds for both implementations, +with K equal to the truncated depth, or conservatively min(D,1/beta) in its +geometric error factor. The original structural depth is not used for admission. + +The algebraic source/input restoration properties are unchanged: this is +still a clean-tape solver with the input unmodified. The optional early-exit check adds at most 2 sum L_k<=4L coefficient records +to the original 40L traffic bound. Executing the unchanged implementation +needs no extra scan and retains 40L. +Any full-kernel composition must use a working precision satisfying both +its existing error target and W>=2g+8. That added local condition is O(g) +and preserves the previous polynomial-in-r precision order. + +## Cubic precision for the full kernel at arbitrary strides + +This section combines the local result above with PR862's retained +common-operator argument. The target is the same prime-power kernel +P(U), with U=tau Z_L^w and |tau|=1, as in PR846. All inverse factors use +this one operator. Different noncommuting shifts are outside the argument. + +A stride solve on input norm at most X has error at most + + (u/beta^2)(5+4X/beta)+u. + +After the outer scalar or inner unit rotation and its rounding, its error +is at most 7(X+1)u/beta^3 for beta<=1/2. This is exactly the local bound +required by PR862. Its proof only needs stable factors and that bound; +it does not require the neighboring-stride implementation. + +Let n=r-1, let Q=(1/r) product(z-rho_j), and suppose + + ||Q||_1<=M, ||Q(U)^-1||<=H, + B=max(1,2^n M H). + +The complementary-factor/Mahler argument in the retained PR862 proof +bounds every inverse prefix and contiguous inverse subproduct by B. +Starting with r x, ||x||<=D, the maximum prefix execution error E obeys + + E <= t(r B D+E+1), t=7nB beta^-3 u. + +For t<1 this yields E<=t(rBD+1)/(1-t). This does not repeatedly multiply +the worst reciprocal root margin at every factor. + +For prime-power r>=3 and p,m>=0, retain the source preparation hypotheses +and put + + ell=ceil(log2 r), c=ceil(log2(r-1)), phi=EulerPhi(r), + d=1+2ell+r(r-1)phi, a0=2d+r+2, + g=d+ell+2r+2, beta=2^-g, h=a0+2r, + e=max(d+1,a0+1,p+2a0+m+3), + b=max((r-1)ell,e+r+3). + +PR628/862's charged approximate factorization and coefficient verification +supply prepared roots with stable margin beta, ||Q||_1<=2^r, +||Q(U)^-1||<=2^(a0+1), and source-scaled kernel perturbation at most +2^(-p-2) for D<=2^m. Thus B<=2^h. These are certified premises, not +conclusions drawn merely from a numerical root list. + +Choose + + J=c+2h+3g+ell+m+5, W=p+J+2. + +This W exceeds 2g+8, so the stride admission holds for every L and every +stride. Moreover n<=2^c and 7<=2^3 imply + + t <= 2^(c+h+3+3g-W) <= 1/2, + rBD+1 <= 2^(ell+h+m+1), + E <= 2t(rBD+1) <= 2^(J-W)=2^(-p-2). + +Adding the independently charged kernel preparation perturbation gives +error at most 2^(-p-1), within the target 2^-p. Approximate phase oracles +still need their separately charged perturbation and access budget. + +A sufficient integer guard for data/state magnitudes is + + G=m+ell+h+g+8. + +Indeed each factor input is bounded by rBD+E. PR846's weighted-data +invariant bounds recursive data and closure values by O(rBD/beta); +its corresponding recursive rounding error is at most one under the +chosen W (h>=g). Chain values, products, scalar application and division +fit this guard. Exact arithmetic accumulators and numerator/denominator +products may use a constant-factor wider representation, as usual. + +Using phi<=r, ell<=r and c<=r gives the explicit cubic bounds + + W <= p+m+9r^3, G <= m+6r^3, b <= p+m+6r^3. + +The exact nonnegative remainders in t=r-3 are + +| Bound | Remainder after removing p and m as appropriate | +| --- | --- | +| 9r^3 minus the working overhead | 65t+25t^2+2t^3 | +| 6r^3 minus the integer guard overhead | 51+85t+30t^2+3t^3 | +| 6r^3 minus the factor-precision overhead | 43+67t+22t^2+2t^3 | + +For the final row, the alternative (r-1)ell<=r^2 also fits the cap. +`cubic.py` checks these coefficient identities and exact exponent +inequalities; it does not infer an all-size bound from sampled radices. + +If the incoming data have fractional width w, define the word scale +A=max(p,w)+2m+16r^3. With a supplied exact rational phase of representation +size B_tau, the one-kernel bill is + + soft-O(r^3(p+m+r^3)) + + O(rL) M(A+B_tau) + + O(rL(A+B_tau)). + +The terms are factor preparation/coefficient verification, rounded +execution, and sequential tape traffic. Here M is the cost of the charged +integer arithmetic; the Python reference is not a measured implementation +of asymptotically fast multiplication or factorization. Longer initial +coefficient/phase descriptions retain their actual input-reading cost. +Execution uses the inherited clean scratch tapes and O(L) data records; +there is no borrowed-array or bit-reversible realization claim. + +The original solver retains its 40L traffic bound per stable factor. +Exact inner rotations and scalar applications add their inherited O(L) +work. The optional zero-truncated solver has at most 44L per factor. +Neither bound has a sorting factor or a precision admission depending +on L. Transform-level layout, phase collection, normalization, common +labels and the multiplication reduction remain separate. + +## Evidence and attribution + +The checks compare 423 array cases exactly between the unchanged and +truncated solver, with independent geometric oracles for the short cases. +They include non-dyadic margins and four deeper arrays through L=5741. +Ninety scalar coefficient paths test exact extinction for gaps through +2^-256; they are not huge-array executions. + +All 300 original PR846 kernel cases pass using the uniform effective-depth +admission, with exact output equivalence and their original residual/dense +checks. An additional 64 executions at the actual cubic W cover radices +3/4/5/7, every stride at lengths 1/2/5, two unit phases, and arbitrary odd +lowest working bits. Roots are rounded to no more than the stated +preparation budget. Every common-operator hypothesis and the independent +kernel perturbation are checked before using the cubic budget. + +The source lineage is PR846 (Rohan Guliani), PR764 (Charles Bethin), PR628 +and PR862 (Chafik Boukhalfa), and PR621 (Ali Romman), together with their +retained classical references. This argument and its exact integration +checks do not claim independent human peer review or formal verification. +No new kappa is claimed. diff --git a/research/averaged-cyclotomic-height/vendor/pr977/cubic.py b/research/averaged-cyclotomic-height/vendor/pr977/cubic.py new file mode 100644 index 0000000000..61c213dd25 --- /dev/null +++ b/research/averaged-cyclotomic-height/vendor/pr977/cubic.py @@ -0,0 +1,62 @@ +"""Exact cubic budgets combining the retained partial-inverse and stride bounds.""" +from fractions import Fraction as F +from math import gcd +from common import need +from uniform import ceil_log2 + + +def plan(r,phi,p,m): + need(all(type(v) is int for v in (r,phi,p,m)) and r>=3 and 1<=phi<=r and p>=0 and m>=0, + 'integer cubic budget inputs') + ell,c=ceil_log2(r),ceil_log2(r-1) + d=1+2*ell+r*(r-1)*phi + a0=2*d+r+2 + g=d+ell+2*r+2 + h=a0+2*r + e=max(d+1,a0+1,p+2*a0+m+3) + factor_bits=max((r-1)*ell,e+r+3) + J=c+2*h+3*g+ell+m+5 + W=p+J+2 + guard=m+ell+h+g+8 + depth=2*g+(W-1).bit_length()+4 + need(W>=2*g+8 and ceil_log2(4*(depth+1))<=W-g,'uniform stride admission') + # n<=2^c, 7<=2^3 and r*2^(h+m)+1<=2^(ell+h+m+1). + # These exact exponent bounds avoid constructing enormous fractions. + t_exponent=c+h+3+3*g-W + need(r-1<=1<=0 for v in width+guard+factor),'all-size nonnegative remainders') + print('PASS cubic budget rows',len(rows),'identities 3',flush=True) + return dict(rows=rows,working_width_remainder=width,integer_guard_remainder=guard, + factor_preparation_remainder=factor) diff --git a/research/averaged-cyclotomic-height/verify.py b/research/averaged-cyclotomic-height/verify.py new file mode 100644 index 0000000000..e147345331 --- /dev/null +++ b/research/averaged-cyclotomic-height/verify.py @@ -0,0 +1,114 @@ +"""Source-bound averaged-height replay, Python 3.11+ with SymPy 1.14.0.""" +import argparse +import gzip +import hashlib +import importlib +import json +from pathlib import Path +import re +import sys + +P = Path(__file__).resolve().parent +sys.dont_write_bytecode = True +sys.set_int_max_str_digits(100000) + + +def require(value, message): + if not value: + raise ValueError(message) + + +def unique_object(pairs): + out = {} + for key, value in pairs: + require(key not in out, 'duplicate JSON key: '+key) + out[key] = value + return out + + +def read_json(path): + data = gzip.decompress(path.read_bytes()) if path.suffix == '.gz' else path.read_bytes() + return json.loads(data, object_pairs_hook=unique_object) + + +def canonical(value): + return json.dumps(value, sort_keys=True, separators=(',', ':'), default=str) + + +def bindings(authoring=False): + manifest = P/'MANIFEST.json' + require(manifest.exists() or authoring, 'missing package manifest') + require(not any(path.is_symlink() for path in P.rglob('*')), 'package symlink') + if manifest.exists(): + record = read_json(manifest) + require(set(record) == {'files'} and type(record['files']) is dict, 'manifest schema') + files = record['files'] + actual = {str(path.relative_to(P)) for path in P.rglob('*') if path.is_file() and path != manifest} + require(set(files) == actual, 'package file coverage') + for name, sha in files.items(): + require(not Path(name).is_absolute() and '..' not in Path(name).parts, 'relative package path') + require(type(sha) is str and re.fullmatch('[0-9a-f]{64}', sha), 'manifest hash type') + require(hashlib.sha256((P/name).read_bytes()).hexdigest() == sha, 'package hash: '+name) + pins = read_json(P/'SOURCE-PINS.json') + require(len(pins['sources']) == 12, 'source inventory') + require(len({row['path'] for row in pins['sources']}) == 12, 'unique source inventory') + for row in pins['sources']: + name = row['path'] + require(not Path(name).is_absolute() and '..' not in Path(name).parts, 'relative source path') + raw = (P/name).read_bytes() + require(hashlib.sha256(raw).hexdigest() == row['sha256'], 'source SHA256: '+name) + require(hashlib.sha1(b'blob '+str(len(raw)).encode()+b'\0'+raw).hexdigest() == row['git_blob'], + 'source Git blob: '+name) + return dict(files=12, source_pins_sha256=hashlib.sha256((P/'SOURCE-PINS.json').read_bytes()).hexdigest()) + + +def modules(): + sys.path.insert(0, str(P)) + names = ['budgets', 'interval_check', 'resultants'] + loaded = {} + for name in names: + loaded[name] = importlib.import_module(name) + require(Path(loaded[name].__file__).resolve() == P/(name+'.py'), 'local module binding: '+name) + return loaded + + +def calculate(): + loaded = modules() + result = dict(status='PASS_AVERAGED_CYCLOTOMIC_HEIGHT', kappa='unchanged') + for name in ['budgets', 'interval_check', 'resultants']: + result[name] = loaded[name].main() + result['scope'] = ('The written proof supplies an all-prime-power averaged-height circle bound. ' + 'Finite rational enclosures, independent exact resultants and integer budgets ' + 'support its identities and failure modes. The inherited clean-scratch stride ' + 'budget becomes O(r^2 log^2 r); no new solver execution, dirty-array, ' + 'bit-reversible, common-label, full-transform or kappa claim.') + return result + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--write', type=Path, help='authoring: write a fresh external receipt') + parser.add_argument('--out', type=Path, help='verify expected mathematics and write a fresh external copy') + parser.add_argument('--bindings-only', action='store_true') + args = parser.parse_args() + require(sum(bool(v) for v in (args.write, args.out, args.bindings_only)) <= 1, 'choose one mode') + destination = args.write or args.out + if destination: + require(not destination.exists(), 'output already exists') + require(not destination.resolve().is_relative_to(P), 'output must be outside package') + pins = bindings(authoring=args.write is not None) + if args.bindings_only: + print('PASS_AVERAGED_HEIGHT_BINDINGS sources=12') + return + result = calculate() + result['sources'] = pins + if not args.write: + require(canonical(result) == canonical(read_json(P/'EXPECTED.json.gz')), 'mathematical receipt mismatch') + if destination: + with destination.open('x') as handle: + handle.write(json.dumps(result, indent=2, sort_keys=True, default=str)+'\n') + print('PASS_AVERAGED_CYCLOTOMIC_HEIGHT interval_radices=17 exact_resultants=6 budgets=752 kappa=unchanged') + + +if __name__ == '__main__': + main()