From 968c7cbf16dc74459dbe836401f7469b61474b52 Mon Sep 17 00:00:00 2001 From: Nick Petalas Date: Mon, 2 Nov 2026 22:17:47 +0000 Subject: [PATCH] perf(research): accelerate exact relative-tariff replay --- .../BENCHMARK.json | 194 ++ .../relative-tariff-integer-exp/ORIGINS.json | 105 + .../relative-tariff-integer-exp/PROFILE.json | 22 + research/relative-tariff-integer-exp/PROOF.md | 100 + .../relative-tariff-integer-exp/README.md | 161 + .../relative-tariff-integer-exp/SOURCES.json | 18 + .../relative-tariff-integer-exp/TASK.json | 75 + .../relative-tariff-integer-exp/VERIFY.json | 34 + .../relative-tariff-integer-exp/benchmark.py | 73 + .../relative-tariff-integer-exp/exp_series.py | 26 + .../relative-tariff-integer-exp/replay.py | 72 + .../source/ORACLE-PROFILES.json | 652 ++++ .../source/PROFILE-PROOF.md | 275 ++ .../source/PROFILES.json | 465 +++ .../source/RELATIVE-RESULT.json | 172 + .../source/SOURCE-PINS.json | 71 + .../source/oracle_profiles.py | 385 +++ .../source/sources/CONTROLLER.json | 3039 +++++++++++++++++ .../source/sources/LIFTS.json | 83 + .../source/sources/NEW-WORD.json.gz | Bin 0 -> 85485 bytes .../source/sources/NOTICE | 309 ++ .../source/sources/OLD-WORD.json.gz | Bin 0 -> 85365 bytes .../source/sources/constructor-source.py | 195 ++ .../source/sources/controller-source.py | 212 ++ .../source/sources/upstream-PROOF.md | 79 + .../source/verify_profiles.py | 414 +++ .../source/verify_tariff.py | 358 ++ .../relative-tariff-integer-exp/verify.py | 160 + 28 files changed, 7749 insertions(+) create mode 100644 research/relative-tariff-integer-exp/BENCHMARK.json create mode 100644 research/relative-tariff-integer-exp/ORIGINS.json create mode 100644 research/relative-tariff-integer-exp/PROFILE.json create mode 100644 research/relative-tariff-integer-exp/PROOF.md create mode 100644 research/relative-tariff-integer-exp/README.md create mode 100644 research/relative-tariff-integer-exp/SOURCES.json create mode 100644 research/relative-tariff-integer-exp/TASK.json create mode 100644 research/relative-tariff-integer-exp/VERIFY.json create mode 100644 research/relative-tariff-integer-exp/benchmark.py create mode 100644 research/relative-tariff-integer-exp/exp_series.py create mode 100644 research/relative-tariff-integer-exp/replay.py create mode 100644 research/relative-tariff-integer-exp/source/ORACLE-PROFILES.json create mode 100644 research/relative-tariff-integer-exp/source/PROFILE-PROOF.md create mode 100644 research/relative-tariff-integer-exp/source/PROFILES.json create mode 100644 research/relative-tariff-integer-exp/source/RELATIVE-RESULT.json create mode 100644 research/relative-tariff-integer-exp/source/SOURCE-PINS.json create mode 100644 research/relative-tariff-integer-exp/source/oracle_profiles.py create mode 100644 research/relative-tariff-integer-exp/source/sources/CONTROLLER.json create mode 100644 research/relative-tariff-integer-exp/source/sources/LIFTS.json create mode 100644 research/relative-tariff-integer-exp/source/sources/NEW-WORD.json.gz create mode 100644 research/relative-tariff-integer-exp/source/sources/NOTICE create mode 100644 research/relative-tariff-integer-exp/source/sources/OLD-WORD.json.gz create mode 100644 research/relative-tariff-integer-exp/source/sources/constructor-source.py create mode 100644 research/relative-tariff-integer-exp/source/sources/controller-source.py create mode 100644 research/relative-tariff-integer-exp/source/sources/upstream-PROOF.md create mode 100644 research/relative-tariff-integer-exp/source/verify_profiles.py create mode 100644 research/relative-tariff-integer-exp/source/verify_tariff.py create mode 100644 research/relative-tariff-integer-exp/verify.py diff --git a/research/relative-tariff-integer-exp/BENCHMARK.json b/research/relative-tariff-integer-exp/BENCHMARK.json new file mode 100644 index 0000000000..3cbac19350 --- /dev/null +++ b/research/relative-tariff-integer-exp/BENCHMARK.json @@ -0,0 +1,194 @@ +{ + "command": "{python} -I -W error -B {package}/replay.py --arm {arm}", + "cpu_count": 18, + "executable": "/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12", + "failures": 0, + "inputs": { + "ORIGINS.json": "29931ccabb96aa7fe7798baca1baecdaa05665344be10cfa23cf7e2c288ddd25", + "benchmark.py": "dd3412bb95b6a8bc904550bd066573b69a4e2ebf3d63fcc4a25cd82ce1858828", + "exp_series.py": "91670ca0bcda02228dca95068e3690083a1f71e211a098721a96d0f5519706cc", + "replay.py": "cfa65ee8c1d850f6a5295c07b35a27c375c48209b0b2dd6c66f4aef6d68c0d10", + "source/ORACLE-PROFILES.json": "dd9abee4eed9bdf52cd731c2fb61d2ec17022ab136ab255e4325181652ba06e4", + "source/PROFILE-PROOF.md": "b95cbfc30cfcf85016406801005a8284b0eca61cb8c1cc5661376e242b0a153e", + "source/PROFILES.json": "985500c0ebda3ba82570cf844d3acaed78d4aec7923956ea889b575e43c4e6d1", + "source/RELATIVE-RESULT.json": "abae56ad096f0361e9b3698ac37b12021bd0432ac52968e60e3b40551aeddb24", + "source/SOURCE-PINS.json": "5eb5b9458165046dad7170d5801a12f84f92891ac16ef2fd8bcbacf357046237", + "source/oracle_profiles.py": "4840369f3311369c09762fccaadcbc2a9fecffc53bcf3dd925abf2b059014cb0", + "source/sources/CONTROLLER.json": "6fd67eaabe659956d6694471d3fd7d2824c0a4a79cf3b8f22922f7189b11b91f", + "source/sources/LIFTS.json": "38960b70a074888a2aeaf3b543629a7ae747c0c5d4f5c853371a6e7c483766c5", + "source/sources/NEW-WORD.json.gz": "9e31463a785c18a70f6ae6ef3d04a6560dbb965517109390fe820f9fac3371b3", + "source/sources/NOTICE": "91f24d68004688bc0a56303a48edcb5ddabd66bfc2326950603bf98dec245bbe", + "source/sources/OLD-WORD.json.gz": "e3b6f1c25d672b8c85433be97ebad77ae6a6972352ce2ff63507d30835fcb491", + "source/sources/constructor-source.py": "fe7dc1d9aa55da393465388ee90faaa687b1e5be48dfa816a421069fa3d2de08", + "source/sources/controller-source.py": "8067ade84815b54d539cbaef9885db9fa4d7a23fdde2e683451d317038a8477c", + "source/sources/upstream-PROOF.md": "769e0f87e6b85c557b48135d2d898bb485cf77ce9925540e0a3740e6283f41af", + "source/verify_profiles.py": "e7d2bf27b3ce2cca939d3fc8239876aa82dcdfcd816bd78df4c9171f37e09319", + "source/verify_tariff.py": "2f3306ed5c52a71bf7f16b5c76e253d49ce20c37a0af3f047e2b2a24809ad478" + }, + "load_average": [ + 5.62890625, + 2.92431640625, + 2.32275390625 + ], + "pairs": 9, + "platform": "macOS-27.0.1-arm64-arm-64bit", + "python": "3.12.15 (main, Oct 14 2026, 00:55:37) [Clang 23.1.3 ]", + "reduction_fraction": 0.2941931186957315, + "samples": [ + { + "arm": "original", + "exit_code": 0, + "nanoseconds": 52462125, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "integer", + "exit_code": 0, + "nanoseconds": 35457750, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "original", + "exit_code": 0, + "nanoseconds": 48862209, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "integer", + "exit_code": 0, + "nanoseconds": 34386625, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "original", + "exit_code": 0, + "nanoseconds": 48701375, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "integer", + "exit_code": 0, + "nanoseconds": 34706458, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "original", + "exit_code": 0, + "nanoseconds": 49178584, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "integer", + "exit_code": 0, + "nanoseconds": 34265209, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "original", + "exit_code": 0, + "nanoseconds": 48438583, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "integer", + "exit_code": 0, + "nanoseconds": 34710583, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "original", + "exit_code": 0, + "nanoseconds": 48920834, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "integer", + "exit_code": 0, + "nanoseconds": 34038625, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "original", + "exit_code": 0, + "nanoseconds": 50717583, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "integer", + "exit_code": 0, + "nanoseconds": 35261625, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "original", + "exit_code": 0, + "nanoseconds": 49847833, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "integer", + "exit_code": 0, + "nanoseconds": 36006292, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "original", + "exit_code": 0, + "nanoseconds": 49427792, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "integer", + "exit_code": 0, + "nanoseconds": 34945958, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + } + ], + "schema_version": 1, + "summary": { + "integer": { + "max_ns": 36006292, + "median_ns": 34710583, + "min_ns": 34038625 + }, + "original": { + "max_ns": 52462125, + "median_ns": 49178584, + "min_ns": 48438583 + } + }, + "warmups": [ + { + "arm": "original", + "exit_code": 0, + "nanoseconds": 50551458, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + }, + { + "arm": "integer", + "exit_code": 0, + "nanoseconds": 35503916, + "stderr_bytes": 0, + "stdout_sha256": "d2a83fa154e29c300827d8422a07f2466b2937c6a208218b773b50b1d4ede913" + } + ] +} diff --git a/research/relative-tariff-integer-exp/ORIGINS.json b/research/relative-tariff-integer-exp/ORIGINS.json new file mode 100644 index 0000000000..3592ebb8ce --- /dev/null +++ b/research/relative-tariff-integer-exp/ORIGINS.json @@ -0,0 +1,105 @@ +{ + "commit": "4cfe905d84f3720c23a7f155f615222401953f95", + "files": [ + { + "bytes": 10800, + "git_blob": "b62e36883e5c9323f215ae6b5282a503bc233296", + "path": "ORACLE-PROFILES.json", + "sha256": "dd9abee4eed9bdf52cd731c2fb61d2ec17022ab136ab255e4325181652ba06e4" + }, + { + "bytes": 12550, + "git_blob": "14fb494b3312eb6a41602ba68baeaf6c16f6ba92", + "path": "PROFILE-PROOF.md", + "sha256": "b95cbfc30cfcf85016406801005a8284b0eca61cb8c1cc5661376e242b0a153e" + }, + { + "bytes": 9032, + "git_blob": "d6f1eb6afe028d209dc2c9573a8685f75ced961e", + "path": "PROFILES.json", + "sha256": "985500c0ebda3ba82570cf844d3acaed78d4aec7923956ea889b575e43c4e6d1" + }, + { + "bytes": 5805, + "git_blob": "35f5f0898a62c167e65913858a1664a4a149b0d0", + "path": "RELATIVE-RESULT.json", + "sha256": "abae56ad096f0361e9b3698ac37b12021bd0432ac52968e60e3b40551aeddb24" + }, + { + "bytes": 2944, + "git_blob": "49ddf9c85fb2f07828654a6278e7458b2349cb8e", + "path": "SOURCE-PINS.json", + "sha256": "5eb5b9458165046dad7170d5801a12f84f92891ac16ef2fd8bcbacf357046237" + }, + { + "bytes": 21090, + "git_blob": "724e0a79f0d3f9dfe64f77b1e3e25ade6d4f1e8e", + "path": "oracle_profiles.py", + "sha256": "4840369f3311369c09762fccaadcbc2a9fecffc53bcf3dd925abf2b059014cb0" + }, + { + "bytes": 27959, + "git_blob": "1f2e375b24aba5fb25580dfea7fab7a2049f3eb8", + "path": "sources/CONTROLLER.json", + "sha256": "6fd67eaabe659956d6694471d3fd7d2824c0a4a79cf3b8f22922f7189b11b91f" + }, + { + "bytes": 1091, + "git_blob": "2ee8cb78fd149f9aca8dd953c650b92495a56266", + "path": "sources/LIFTS.json", + "sha256": "38960b70a074888a2aeaf3b543629a7ae747c0c5d4f5c853371a6e7c483766c5" + }, + { + "bytes": 85485, + "git_blob": "b1cfd03abe9128cf5a3908fbd82652e5e8a2e292", + "path": "sources/NEW-WORD.json.gz", + "sha256": "9e31463a785c18a70f6ae6ef3d04a6560dbb965517109390fe820f9fac3371b3" + }, + { + "bytes": 17583, + "git_blob": "638a187d1417bda8976e945a2aeaed116a090e37", + "path": "sources/NOTICE", + "sha256": "91f24d68004688bc0a56303a48edcb5ddabd66bfc2326950603bf98dec245bbe" + }, + { + "bytes": 85365, + "git_blob": "0af79e58172f85c302c35b193205c0b185b09393", + "path": "sources/OLD-WORD.json.gz", + "sha256": "e3b6f1c25d672b8c85433be97ebad77ae6a6972352ce2ff63507d30835fcb491" + }, + { + "bytes": 7874, + "git_blob": "c099995bef0e224cbb0ec61c06ed3d0b4d478b33", + "path": "sources/constructor-source.py", + "sha256": "fe7dc1d9aa55da393465388ee90faaa687b1e5be48dfa816a421069fa3d2de08" + }, + { + "bytes": 7474, + "git_blob": "3b4bf82eba05d57ef4bb1fd934e8ca65780425c1", + "path": "sources/controller-source.py", + "sha256": "8067ade84815b54d539cbaef9885db9fa4d7a23fdde2e683451d317038a8477c" + }, + { + "bytes": 3940, + "git_blob": "bd20fcaf2078691d914d6afbc5cb06a75f47770d", + "path": "sources/upstream-PROOF.md", + "sha256": "769e0f87e6b85c557b48135d2d898bb485cf77ce9925540e0a3740e6283f41af" + }, + { + "bytes": 22209, + "git_blob": "b1d52ab008099d8ac8ae8bc16af838f834931367", + "path": "verify_profiles.py", + "sha256": "e7d2bf27b3ce2cca939d3fc8239876aa82dcdfcd816bd78df4c9171f37e09319" + }, + { + "bytes": 17249, + "git_blob": "9c3327468fe1256403a7610835791c04c4bc9176", + "path": "verify_tariff.py", + "sha256": "2f3306ed5c52a71bf7f16b5c76e253d49ce20c37a0af3f047e2b2a24809ad478" + } + ], + "pull_request": 6378, + "repository": "CrocSwap/integer-mult-bounds", + "upstream_directory": "research/p104-6375-relative-tariff-audit", + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6378" +} diff --git a/research/relative-tariff-integer-exp/PROFILE.json b/research/relative-tariff-integer-exp/PROFILE.json new file mode 100644 index 0000000000..2a88c02102 --- /dev/null +++ b/research/relative-tariff-integer-exp/PROFILE.json @@ -0,0 +1,22 @@ +{ + "benchmark_samples_include_profiling": false, + "command": "{python} -I -W error -B -m cProfile -o OUTPUT source/verify_tariff.py", + "functions": { + "exp_positive": { + "calls": 72, + "cumulative_seconds": 0.025430217, + "primitive_calls": 72, + "self_seconds": 0.000529736 + }, + "run": { + "calls": 1, + "cumulative_seconds": 0.033980958000000006, + "primitive_calls": 1, + "self_seconds": 2.8792e-05 + } + }, + "profiled_source_sha256": "2f3306ed5c52a71bf7f16b5c76e253d49ce20c37a0af3f047e2b2a24809ad478", + "schema_version": 1, + "total_calls": 113185, + "total_seconds": 0.04363541899999999 +} diff --git a/research/relative-tariff-integer-exp/PROOF.md b/research/relative-tariff-integer-exp/PROOF.md new file mode 100644 index 0000000000..db059bcb0a --- /dev/null +++ b/research/relative-tariff-integer-exp/PROOF.md @@ -0,0 +1,100 @@ +# Exact finite exponential evaluation + +This contribution is produced by Nick Petalas. Independent human and formal +proof-kernel review are unclaimed. Apache-2.0. + +## Statement + +For every rational x=a/b with b>0 and 0<=x<=1/4, and every integer n>=1, +let + + S_n(x) = sum_(j=0)^n x^j/j! + E_n(x) = (x^(n+1)/(n+1)!) / (1-x/(n+2)). + +The following integer recurrence returns exactly the interval +`(S_n(x), S_n(x)+E_n(x))` used by ToikY's frozen PR6378 primary verifier. +There is no extra rounding, changed degree or shortened series. + + A = D = 1 + for k = n,n-1,...,1: + D = b*k*D + A = D+a*A + lower = A/D + tail = a^(n+1)*(n+2) / (D*(n+1)*(b*(n+2)-a)) + return lower, lower+tail + +The old A appears on the right of the second assignment; D is its updated +value. The executable accepts Fraction inputs with components of at most +4096 bits and degrees 1..64. The written identity has no component-size or +degree-64 restriction. The bound on x is the source's declared interval. + +## Algebraic proof + +Before the first iteration, A/D=1. At iteration k, the recurrence replaces +the previous ratio T by `1+(x/k)T`. Downward induction therefore gives, +after iteration k, + + A/D = sum_(j=0)^(n-k+1) ((k-1)!/(k+j-1)!) x^j. + +For j=0, the factorial ratio is one. At k=1 this is exactly S_n(x). +The denominator starts at one and is multiplied once by every bk, so its +final value is D=b^n n!. Substitution gives + + (x^(n+1)/(n+1)!) / (1-x/(n+2)) + = a^(n+1)*(n+2) / (D*(n+1)*(b*(n+2)-a)). + +The denominator is positive because a<=b/4 and n>=1. This also handles a=0, +where the tail is zero and the lower endpoint is one. Fraction construction +reduces exact integers; it introduces no rounding. Both returned endpoints +are consequently identical rational numbers to the predecessor's outputs. +The classical Taylor and geometric-tail argument, including its use as an +exponential enclosure, belongs to the predecessor and standard analysis. +This contribution proves preservation of that particular enclosure. + +## Complete caller preservation + +`ORIGINS.json` records sixteen byte-exact retained files from PR6378 at +`4cfe905d84f3720c23a7f155f615222401953f95`. The primary script, its fourteen +frozen inputs and its complete retained result are included. Its original +NOTICE and proof files remain unchanged. No foreign Git object or network +access is needed for replay. + +`replay.py` checks the manifest hash, every retained byte count/hash and the +primary script's fixed hash before loading it. It compiles the authenticated +script with a private name, so the script defines its original functions but +does not enter its final CLI block. The integer arm changes only the private +`exp_positive` binding. The source degree is checked to be 24. The adapter +then executes the unchanged final CLI block with its original argument list +and main name. Argument restoration occurs in a finally block. + +The sixteen fixed source files authenticate the exact CLI boundary and all +its code. The complete original source/profile/coefficient/kernel identities, +endpoint signs, examples and three counterfactual controls still execute. +The original typed JSON and exact-byte retained-result comparisons still +execute. The baseline arm takes the same path with the original binding. +Neither arm executes the predecessor profile producers or independent tariff +oracle. Their source and receipt authentication is retained exactly where the +primary originally performs it. This is one complete primary command, not +a replay or acceleration of all eight predecessor registered commands. + +By the interval identity, each reached replacement result equals its original +result. Induction through the remaining unchanged computations preserves all +values, branches, failures and the final result. The bounded conformance run +also records and compares the complete ordered list of 72 Fraction arguments. +Their largest denominator has 171 bits, inside the explicit backend limit. +The source's degree-24 loop thus has exactly 1728 iterations in this caller. +Those per-term Fraction operations become integer operations. The final +rational interval and every later outward rounding remain unchanged. + +## Verification boundary + +The verifier compares against a direct power/factorial sum on 1449 finite +cases, separately checks all 72 reached arguments, compares the complete +result bytes, and executes both complete CLIs. Fourteen negative controls +exercise domain/degree/size limits, omitted tails, premature rounding, +manifest/source mutation, read limits and invalid arm selection. Both normal +and optimized Python execute these predicates with explicit exceptions. + +This is a written scoped preservation proof with finite corroboration and +measured implementation evidence. It supplies no new root, kappa, scientific +audit of PR6378, native operator, supplier admission or multiplication theorem. diff --git a/research/relative-tariff-integer-exp/README.md b/research/relative-tariff-integer-exp/README.md new file mode 100644 index 0000000000..eb92f9f4ac --- /dev/null +++ b/research/relative-tariff-integer-exp/README.md @@ -0,0 +1,161 @@ +# Faster exact relative-tariff replay + +This contribution is produced by Nick Petalas. Independent human and formal +proof-kernel review are unclaimed. Apache-2.0. + +An exact integer Horner kernel reduces the complete frozen PR6378 primary +relative-tariff replay's median wall time by **29.42%**, from **49.18 ms to +34.71 ms**, on the recorded CPython 3.12.15/macOS arm64 host. The median uses +nine alternating fresh-process pairs. Original times range from 48.44 to +52.46 ms; integer times range from 34.04 to 36.01 ms. Every process succeeds. +[BENCHMARK.json](BENCHMARK.json) is the generated source-bound timing receipt. +This is a scoped exact-arithmetic preservation proof and measured verifier +improvement, with no new kappa. + +## Result and evidence + +[ToikY's PR6378](https://github.com/CrocSwap/integer-mult-bounds/pull/6378) +supplies the complete primary relative-tariff verifier, its theorem, frozen +profiles, independent oracle and rejection checks. This package changes its +private positive-exponential binding in an isolated opt-in replay. The +predecessor theorem is a cited premise, not an audit deliverable. + +For x=a/b, the replacement evaluates the same degree-n Taylor polynomial +using integer updates `D=b*k*D; A=D+a*A`, in descending k. It constructs the +same geometric tail by one rational expression. [PROOF.md](PROOF.md) proves +both endpoints equal the original rational endpoints for every rational +0<=x<=1/4 and n>=1. No precision or series term is removed. + +The complete caller reaches 72 exponential evaluations at degree 24. The +1728 per-term Fraction divisions, multiplications and additions become integer +arithmetic. All later outward rounding and the original CLI's full checks +remain. The complete 5805-byte result has unchanged SHA256 +`abae56ad096f0361e9b3698ac37b12021bd0432ac52968e60e3b40551aeddb24`. + +The deterministic verifier checks 1449 exact direct-power/factorial cases, +every reached exponential argument, complete result equality, both original +CLIs, fourteen negative controls and the benchmark's source binding. Its +finite evidence corroborates the written identity. The three inherited +controls still reject missing carrier fees, missing productive debits and +reversed endpoint signs. + +## Measurement contract + +Both timed arms use the same adapter, source authentication, interpreter +flags and fresh-process setup. The baseline arm retains the original kernel; +the integer arm binds the new kernel. The whole command, including its +original retained-result comparison, executes inside the timed region. No +persistent cache, network access or warm interpreter is used. Two checked +warmups precede the eighteen measured processes. + +The separate cProfile run identifies the exponential kernel as the limiter: +its 72 calls consume 25.4 ms of a 43.6 ms instrumented complete source run. +These profiling times are excluded from the benchmark. Fraction gcd work +dominates that kernel. [PROFILE.json](PROFILE.json) retains the generated +profile summary and source hash. The measured end-to-end gain is smaller +than the kernel's removable share. + +This is the predecessor's exact published arithmetic configuration, including +its existing logarithm cache, degree and work grids. Both arms use identical +settings. The host has eighteen logical CPUs and other work was present; +the recorded load averages are in the receipt. Alternation exposes both arms +to that load. The measured ranges do not overlap. The gain is for this command +and host, not a universal runtime guarantee or an aggregate speedup of every +PR6378 verification command. + +## Reproduction + +From the repository root, with CPython 3.12 and the standard library: + +```sh +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -I -W error -B research/relative-tariff-integer-exp/verify.py +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -I -W error -O -B research/relative-tariff-integer-exp/verify.py +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -B scripts/research_package.py --package research/relative-tariff-integer-exp +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -B scripts/check_research_commit.py --package research/relative-tariff-integer-exp --check-source-history +``` + +Expected markers are `PASS_RELATIVE_TARIFF_INTEGER_EXP`, +`PASS_REGISTERED_RESEARCH_PACKAGE` and `PASS_RESEARCH_COMMIT_BYTES`. +Another CPython 3.12 path can replace the displayed local interpreter. +Normal verification writes nothing and needs no Git or predecessor checkout. + +Run the measured complete command with `replay.py --arm original` or +`replay.py --arm integer`, under the same interpreter flags. To generate a +fresh timing receipt, use an unoccupied output path outside the checkout: + +```sh +/Users/nick/git/integer-mult-bounds/.venv/bin/python3.12 -I -W error -B research/relative-tariff-integer-exp/benchmark.py --pairs 9 --output /tmp/relative-tariff-timings.json +``` + +CI checks exact conformance and the committed timing receipt's bindings. +It does not certify the local speed percentage on a different host. + +## Scope, provenance and constraints + +Canonical base is `7c49fe32c55de02c2c873655c804b16e4c3fef0a`, priority +revision 8. [TASK.json](TASK.json) retains the refined replay-runtime card +and [SOURCES.json](SOURCES.json) its historical provenance. The selected +source-binding positive control passes; no selected scientific replay ran. +[ORIGINS.json](ORIGINS.json) binds the retained pending predecessor's public +commit, paths, Git blob IDs and byte hashes. The local source subset is +338450 bytes. The sixteen files include the original NOTICE unchanged. +There is no runtime reliance on that pending commit's presence in Git history. + +The new kernel accepts Fraction components of at most 4096 bits and degrees +1..64; the actual caller uses degree 24 and denominators of at most 171 bits. +No arbitrary public Python-number compatibility is claimed. Source changes +fail closed. The adapter modifies only its private namespace and restores +its temporary argument list even on failure. No original source, selected +frontier, shared tool or public verifier API changes. + +The new functions are below sixty physical lines. The kernel has at most +64 iterations, the finite polynomial fixture has 41 denominator choices and +six degrees, and source-call traces are capped at eighty. Benchmarks accept +five to fifteen pairs and give each process thirty seconds. Source reads +are bounded and authenticated. Warning-strict normal/optimized replay and +syntax parsing supply the available Python diagnostics. + +Power of Ten rule 3 deviation: Python and Fraction allocate managed objects. +The bounded kernel's raw and transient fraction arithmetic has a conservative 534000-bit bound; each +replay loads sixteen fixed retained files, whose total is 338450 bytes. +There is no new cache or queue; the fixed source logarithm cache has six rank keys. Rule 8/9 deviation: fixed local source +loading and one explicit function binding are necessary to run an unchanged +predecessor CLI. The adapter authenticates the source bytes before execution; +the callable targets are the original kernel and the new integer kernel. +Conformance covers both targets, while source mutation controls reject drift. +A shared or fixed-allocation integration needs its own resource contract. + +No complete scientific audit, independent human/kernel acceptance, native +phase/endpoint, caller ownership/restoration, compiler, precision/tape, +analytic recovery or supplier admission follows. The five selected framework +assumptions remain. Lean, Docker, selected cold replay, predecessor profile +producer/oracle replays and physical integration are unrun and unclaimed. + +## Open next questions + +- Can the same exact integer kernel improve a different actual caller? + Profile its complete command and bind its exact interval contract first. + No additional caller or timing evidence is supplied here. +- Should a future primary relative-tariff verifier adopt this backend? + Start with that exact new source head and preserve its full receipt and + rejection checks. Shared adoption and changed-head applicability remain + separate decisions. + +Structured relevance, first steps and blockers are in [TASK.json](TASK.json). + +## Credit and coordination + +ToikY retains PR6378's scientific proof, complete verifier and independent +oracle. DreamingOfClouds retains PR6375's shared-carrier construction; +Ali Romman retains the PR6372/6353/6349/6348 P104/query lineage. Cinna Davis, +Jacob Alan Sussman, zxv, Cao Yifan and all authors in the retained NOTICE +keep their native, caller, interval and construction credit. Horner evaluation, +Taylor polynomials and rational arithmetic are classical. The new result is +this interval-preserving backend and its measured complete-command gain. + +[Advance CLAIM](https://github.com/CrocSwap/integer-mult-bounds/discussions/1166#discussioncomment-19361553). +Live open/account PRs, handoff claims, local reservations, active Discussions, +merged object/formula searches and main README searches were checked. The +cached replay-runtime search has incomplete sparse local coverage; absence +of a match is not a novelty certificate. Unpublished work remains outside +that coverage. The first verified improvement is the stopping point. diff --git a/research/relative-tariff-integer-exp/SOURCES.json b/research/relative-tariff-integer-exp/SOURCES.json new file mode 100644 index 0000000000..594089b9c7 --- /dev/null +++ b/research/relative-tariff-integer-exp/SOURCES.json @@ -0,0 +1,18 @@ +{ + "schema_version": 1, + "base_commit": "7c49fe32c55de02c2c873655c804b16e4c3fef0a", + "files": [ + { + "path": "certificates/selected-result.json", + "usage": "provenance", + "git_blob": "d59b5035e7b4cbaa9d688a1d32dd0d6eb79c466a", + "sha256": "9b8d0eea95b3bf0dfcb7938a732a6439b87a2685dec2a5ab9e525b3b34debbfa" + }, + { + "path": "docs/research/agent-task-catalog.json", + "usage": "provenance", + "git_blob": "3404fbdd5e7529a0674eef26114b5071e4586cec", + "sha256": "ead6cdc9d0af6d58e8a49744d8ec8c7c15e13d2ba93c276c434bcf9b51b93a81" + } + ] +} diff --git a/research/relative-tariff-integer-exp/TASK.json b/research/relative-tariff-integer-exp/TASK.json new file mode 100644 index 0000000000..9af109ae9d --- /dev/null +++ b/research/relative-tariff-integer-exp/TASK.json @@ -0,0 +1,75 @@ +{ + "schema_version": 1, + "task_id": "replay-runtime", + "priority_revision": 8, + "base_commit": "7c49fe32c55de02c2c873655c804b16e4c3fef0a", + "original_card": { + "id": "replay-runtime", + "question": "Can one measured replay bottleneck be sped up without dropping coverage?", + "starting_points": [ + "scripts/run_isolated_tests.py", + "scripts/verify_replay_coverage.py", + "certificates/selected-result.json" + ], + "methods": [ + "Profile one isolated replay and optimize the measured bottleneck.", + "Design source-bound reuse with explicit dependency invalidation and negative controls." + ], + "acceptance_gate": "Report before/after wall time on the same fixture, retained checks and invalidation behavior.", + "first_step": { + "command": [ + "python3", + "-B", + "scripts/research_selected_baseline.py" + ], + "expected": "PASS_RESEARCH_BASELINE_BINDINGS_ONLY", + "inspect": "Resolve the current selected review, separate complex/ordinary BIT/admitted BIT/outer budgets, and compare the card against live handoffs before starting. Historical ceilings require exact source/model equivalence.", + "scope": "Source-binding orientation only; not a scientific replay or all-size proof. Materialize selected inputs if this checkout is sparse." + }, + "first_experiment": "Measure one unchanged fixture, preserve check coverage, and test one optimization with invalidation controls.", + "bottleneck_link": "Faster trustworthy replays increase review throughput and let mechanism candidates be checked sooner.", + "allowed_variations": [ + "Profile one stage or design one source-bound cache boundary." + ], + "scope_change_triggers": [ + "Skipping coverage or comparing different fixtures to claim speedup." + ], + "overlap_terms": [ + "replay runtime", + "cache invalidation", + "isolated tests" + ] + }, + "scope_status": "refined", + "actual_scope": "Accelerate the complete frozen PR6378 primary relative-tariff CLI through exact integer Horner evaluation of its positive exponential interval.", + "scope_change_reason": "The replay-runtime card is specialized to one authenticated complete caller. The predecessor mathematical result is a cited premise, not an audit deliverable.", + "bottleneck_link": "Exact interval replay throughput supports checking complete signed invoices without changing their mathematical or native/caller assumptions.", + "budget_minutes": 60, + "stop_rule": "Stop after the first verified complete-command improvement; leave other kernels and the independent oracle unchanged.", + "outcome": "completed", + "evidence": "exp_series.py, replay.py, verify.py, PROOF.md and generated BENCHMARK.json", + "author": "Nick Petalas", + "ai_assistance": "Independent human and formal proof-kernel review are unclaimed.", + "open_questions": [ + { + "question": "Can the same exact integer kernel improve another actual source-bound caller?", + "why_it_matters": "The written interval identity is general, while this measured gain concerns one frozen primary CLI.", + "first_step": "Profile a distinct complete caller and compare its exact interval contract before any integration.", + "blocked_by": "No other source-bound application or timing evidence is supplied." + }, + { + "question": "Should this opt-in backend be integrated into a future primary relative-tariff verifier?", + "why_it_matters": "This package preserves the predecessor files and exposes an isolated adapter.", + "first_step": "Bind the new verifier head and retain its complete receipt and rejection checks.", + "blocked_by": "Shared adoption and changed-head applicability remain separate decisions." + } + ], + "claim_type": "Scoped exact-arithmetic preservation proof and measured verifier-engineering improvement.", + "source_question": "replay-runtime card, applied to the complete primary CLI of ToikY PR6378", + "claim_url": "https://github.com/CrocSwap/integer-mult-bounds/discussions/1166#discussioncomment-19361553", + "environment": { + "python": "3.12.15", + "platform": "macOS-27.0.1-arm64-arm-64bit", + "dependencies": "standard library only" + } +} diff --git a/research/relative-tariff-integer-exp/VERIFY.json b/research/relative-tariff-integer-exp/VERIFY.json new file mode 100644 index 0000000000..8f36a646d7 --- /dev/null +++ b/research/relative-tariff-integer-exp/VERIFY.json @@ -0,0 +1,34 @@ +{ + "schema_version": 1, + "status": "ready", + "python": "3.12", + "requirements": [], + "inputs": [], + "commands": [ + { + "argv": [ + "{python}", + "-I", + "-W", + "error", + "-B", + "{package}/verify.py" + ], + "timeout_seconds": 120, + "checks": "Exact finite Taylor/tail identity, complete primary result and CLI equality, all reached exponential arguments, source/domain/semantic controls and benchmark source binding." + }, + { + "argv": [ + "{python}", + "-I", + "-W", + "error", + "-O", + "-B", + "{package}/verify.py" + ], + "timeout_seconds": 120, + "checks": "The same complete conformance and rejection predicates with Python optimization enabled." + } + ] +} diff --git a/research/relative-tariff-integer-exp/benchmark.py b/research/relative-tariff-integer-exp/benchmark.py new file mode 100644 index 0000000000..e611c27dab --- /dev/null +++ b/research/relative-tariff-integer-exp/benchmark.py @@ -0,0 +1,73 @@ +"""Alternate complete fresh-process replays and emit a source-bound receipt.""" + +import argparse +from hashlib import sha256 +import json +import os +from pathlib import Path +import platform +import statistics +import subprocess +import sys +import time + + +HERE = Path(__file__).resolve().parent +EXPECTED = b"PASS exact relative tariff threshold and retained receipt\n" + + +def inputs() -> dict[str, str]: + origin = json.loads((HERE / "ORIGINS.json").read_bytes()) + names = ["benchmark.py", "exp_series.py", "replay.py", "ORIGINS.json"] + names.extend("source/" + row["path"] for row in origin["files"]) + return {name: sha256((HERE / name).read_bytes()).hexdigest() for name in names} + + +def sample(arm: str) -> dict: + command = [sys.executable, "-I", "-W", "error", "-B", + str(HERE / "replay.py"), "--arm", arm] + start = time.perf_counter_ns() + result = subprocess.run(command, capture_output=True, timeout=30, check=False) + elapsed = time.perf_counter_ns() - start + if result.returncode != 0 or result.stderr or result.stdout != EXPECTED: + raise RuntimeError("complete replay failed: " + repr(result)) + return {"arm": arm, "nanoseconds": elapsed, "exit_code": result.returncode, + "stdout_sha256": sha256(result.stdout).hexdigest(), "stderr_bytes": 0} + + +def benchmark(pairs: int) -> dict: + if type(pairs) is not int or not 5 <= pairs <= 15: + raise ValueError("benchmark requires 5..15 alternating pairs") + before = inputs() + warmups = [sample(arm) for arm in ("original", "integer")] + observations = [sample(arm) for _ in range(pairs) + for arm in ("original", "integer")] + if inputs() != before: + raise RuntimeError("benchmark inputs changed during measurement") + summaries = {} + for arm in ("original", "integer"): + times = [row["nanoseconds"] for row in observations if row["arm"] == arm] + summaries[arm] = {"median_ns": statistics.median(times), + "min_ns": min(times), "max_ns": max(times)} + return {"schema_version": 1, "python": sys.version, "executable": sys.executable, + "platform": platform.platform(), "cpu_count": os.cpu_count(), + "load_average": list(os.getloadavg()), "pairs": pairs, + "command": "{python} -I -W error -B {package}/replay.py --arm {arm}", + "inputs": before, "warmups": warmups, "samples": observations, + "summary": summaries, "failures": 0, + "reduction_fraction": 1 - summaries["integer"]["median_ns"] / + summaries["original"]["median_ns"]} + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--pairs", type=int, default=9) + parser.add_argument("--output", type=Path, required=True) + args = parser.parse_args() + if args.output.exists(): + raise ValueError("benchmark receipt path already exists") + report = benchmark(args.pairs) + with args.output.open("x", encoding="utf-8") as stream: + stream.write(json.dumps(report, indent=2, sort_keys=True) + "\n") + print(json.dumps({"summary": report["summary"], + "reduction_fraction": report["reduction_fraction"]})) diff --git a/research/relative-tariff-integer-exp/exp_series.py b/research/relative-tariff-integer-exp/exp_series.py new file mode 100644 index 0000000000..394cbfe45e --- /dev/null +++ b/research/relative-tariff-integer-exp/exp_series.py @@ -0,0 +1,26 @@ +"""Exact rational Taylor interval, evaluated with integer Horner arithmetic.""" + +from fractions import Fraction + + +def exp_interval(value: Fraction, degree: int = 24) -> tuple[Fraction, Fraction]: + """Preserve the finite Taylor sum and the source's geometric tail exactly.""" + if type(value) is not Fraction or not 0 <= value <= Fraction(1, 4): + raise ValueError("small nonnegative rational exponential domain") + if type(degree) is not int or not 1 <= degree <= 64: + raise ValueError("Taylor degree must be an integer in 1..64") + a, b = value.numerator, value.denominator + if max(a.bit_length(), b.bit_length()) > 4096: + raise ValueError("rational components exceed 4096 bits") + numerator, denominator = 1, 1 + for index in range(degree, 0, -1): + denominator *= b * index + numerator = denominator + a * numerator + lower = Fraction(numerator, denominator) + tail = Fraction( + a ** (degree + 1) * (degree + 2), + denominator * (degree + 1) * (b * (degree + 2) - a), + ) + if not 1 <= lower <= lower + tail: + raise ArithmeticError("positive Taylor interval invariant") + return lower, lower + tail diff --git a/research/relative-tariff-integer-exp/replay.py b/research/relative-tariff-integer-exp/replay.py new file mode 100644 index 0000000000..5d8c8d84c8 --- /dev/null +++ b/research/relative-tariff-integer-exp/replay.py @@ -0,0 +1,72 @@ +"""Run the complete frozen primary CLI with one optional exact kernel binding.""" + +import argparse +import ast +from hashlib import sha256 +import json +from pathlib import Path +import sys + +HERE = Path(__file__).resolve().parent +KERNEL_PATH = HERE / "exp_series.py" +KERNEL = {"__name__": "integer_exp_series"} +exec(compile(KERNEL_PATH.read_bytes(), str(KERNEL_PATH), "exec"), KERNEL) +exp_interval = KERNEL["exp_interval"] +ORIGINS_SHA256 = "29931ccabb96aa7fe7798baca1baecdaa05665344be10cfa23cf7e2c288ddd25" +SOURCE_SHA256 = "2f3306ed5c52a71bf7f16b5c76e253d49ce20c37a0af3f047e2b2a24809ad478" + + +def check_payload(raw: bytes, expected: str, limit: int, label: str) -> bytes: + if len(raw) > limit or sha256(raw).hexdigest() != expected: + raise ValueError("retained source SHA256/size: " + label) + return raw + + +def checked_bytes(path: Path, expected: str, limit: int = 4_194_304) -> bytes: + with path.open("rb") as stream: + raw = stream.read(limit + 1) + return check_payload(raw, expected, limit, path.name) + + +def authenticate(root: Path = HERE) -> bytes: + raw = checked_bytes(root / "ORIGINS.json", ORIGINS_SHA256, 32_768) + origin = json.loads(raw) + for row in origin["files"]: + data = checked_bytes(root / "source" / row["path"], row["sha256"]) + if len(data) != row["bytes"]: + raise ValueError("retained source byte count") + return checked_bytes(root / "source/verify_tariff.py", SOURCE_SHA256) + + +def load_primary(root: Path = HERE) -> tuple[dict, ast.Module]: + raw = authenticate(root) + source = root / "source/verify_tariff.py" + tree = ast.parse(raw, filename=str(source)) + if not isinstance(tree.body[-1], ast.If): + raise ValueError("frozen primary CLI boundary") + namespace = {"__name__": "retained_tariff", "__file__": str(source)} + exec(compile(tree, str(source), "exec"), namespace) + if namespace["EXP_DEGREE"] != 24: + raise ValueError("frozen Taylor degree") + return namespace, ast.Module(body=[tree.body[-1]], type_ignores=[]) + + +def replay(arm: str) -> None: + if arm not in ("original", "integer"): + raise ValueError("unknown replay arm") + namespace, cli = load_primary() + if arm == "integer": + namespace["exp_positive"] = exp_interval + old_argv = sys.argv + try: + sys.argv = [namespace["__file__"]] + namespace["__name__"] = "__main__" + exec(compile(cli, namespace["__file__"], "exec"), namespace) + finally: + sys.argv = old_argv + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--arm", choices=("original", "integer"), default="integer") + replay(parser.parse_args().arm) diff --git a/research/relative-tariff-integer-exp/source/ORACLE-PROFILES.json b/research/relative-tariff-integer-exp/source/ORACLE-PROFILES.json new file mode 100644 index 0000000000..b62e36883e --- /dev/null +++ b/research/relative-tariff-integer-exp/source/ORACLE-PROFILES.json @@ -0,0 +1,652 @@ +{ + "caller": { + "idles": [ + { + "index": 8, + "size": 4 + }, + { + "index": 18, + "size": 2 + }, + { + "index": 44, + "size": 2 + }, + { + "index": 76, + "size": 7 + }, + { + "index": 86, + "size": 3 + }, + { + "index": 102, + "size": 2 + }, + { + "index": 134, + "size": 4 + }, + { + "index": 144, + "size": 2 + }, + { + "index": 170, + "size": 2 + }, + { + "index": 208, + "size": 8 + }, + { + "index": 218, + "size": 4 + }, + { + "index": 228, + "size": 2 + }, + { + "index": 254, + "size": 2 + }, + { + "index": 286, + "size": 4 + }, + { + "index": 296, + "size": 2 + }, + { + "index": 322, + "size": 2 + } + ], + "opcode_counts": { + "ADD": 112, + "IDLE": 16, + "LOCAL": 19, + "QUERY": 16, + "Q_POWER": 20, + "SCALE": 67, + "SWAP": 103 + }, + "queries": [ + 5, + 15, + 41, + 73, + 83, + 99, + 131, + 141, + 167, + 205, + 215, + 225, + 251, + 283, + 293, + 319 + ], + "topology_node_sizes": { + "2": 9, + "3": 1, + "4": 4, + "7": 1, + "8": 1 + } + }, + "counterfactual_invoice_controls": [ + { + "control": "unpaid_carrier_first_leg_in_nineteen_calls", + "detail": { + "copies": 19, + "event": [ + "MOVE", + 171, + 3, + 106, + false + ], + "event_index": 9242 + }, + "kind": "counterfactual_invoice_counts", + "profile_mismatch": { + "actual_count": 44148, + "expected_count": 44167, + "rank": 1 + } + }, + { + "control": "old_rank9_target_retained_instead_of_new_rank8", + "detail": { + "copies": 19, + "helper": 520, + "productive_fields": 14214 + }, + "kind": "counterfactual_invoice_counts", + "profile_mismatch": { + "actual_count": 703, + "expected_count": 722, + "rank": 8 + } + }, + { + "control": "one_thin_query_unpaid", + "detail": { + "caller_event_index": 5, + "jobs": 104 + }, + "kind": "counterfactual_invoice_counts", + "profile_mismatch": { + "actual_count": 44063, + "expected_count": 44167, + "rank": 1 + } + }, + { + "control": "one_paired_idle_member_unpaid", + "detail": { + "caller_event_index": 8, + "jobs": 104 + }, + "kind": "counterfactual_invoice_counts", + "profile_mismatch": { + "actual_count": 728, + "expected_count": 832, + "rank": 32 + } + }, + { + "control": "one_full_LOCAL_bill_missing", + "detail": { + "omitted_stage": 1 + }, + "kind": "counterfactual_invoice_counts", + "profile_mismatch": { + "actual_count": 41930, + "expected_count": 44167, + "rank": 1 + } + } + ], + "limits": [ + "Paid frame-rank and productive tariffs are retained native/interface premises, not phase or realization proofs.", + "Scalar common frames and temporal ownership are checked; scalar values, restoration, COPY zeros and physical erasure are not admitted.", + "Main target billing assumes the frozen rank-eight LOCAL interface and declared caller diagonal.", + "MOVE multiset cancellation is billing evidence, not a claim that retimed events have identical chronology.", + "Controls corrupt invoice counts only; no valid cheaper modified source program is claimed.", + "This round does not compute a power threshold, raw kappa crossing, uniform compiler or supplier admission." + ], + "local_paid_delta": { + "1": 6, + "3": -3, + "4": 3, + "5": -3 + }, + "local_signed_gain_coefficients": { + "1": -6, + "3": 3, + "4": -3, + "5": 3, + "8": 6, + "9": -6 + }, + "local_target_delta": { + "8": 6, + "9": -6 + }, + "new_complete": { + "paid": { + "1": 44167, + "16": 1872, + "2": 8607, + "24": 208, + "3": 9329, + "32": 832, + "4": 2071, + "5": 2869, + "56": 208, + "6": 152, + "64": 208, + "7": 171, + "8": 19 + }, + "paid_jobs": 70713, + "paid_rank_mass": 200786, + "productive_fields": 14214, + "productive_rank_mass": 201594, + "rank_mass_surplus": 808, + "targets": { + "1": 266, + "153": 208, + "17": 1872, + "2": 152, + "25": 208, + "3": 76, + "33": 832, + "4": 2033, + "5": 285, + "57": 208, + "6": 57, + "65": 208, + "7": 171, + "8": 722, + "9": 6916 + } + }, + "new_local": { + "events": 17768, + "helper_fields": 562, + "opcode_counts": { + "ADD": 13371, + "CLEAR": 43, + "INIT": 43, + "MOVE": 3459, + "SCALE": 852 + }, + "owned_lifetimes": 43, + "paid": { + "1": 2237, + "2": 453, + "3": 491, + "4": 109, + "5": 151, + "6": 8, + "7": 9, + "8": 1 + }, + "paid_jobs": 3459, + "paid_rank_mass": 5926, + "peak_owned": 13, + "productive_rank_mass": 4206, + "targets": { + "1": 14, + "2": 8, + "3": 4, + "4": 107, + "5": 15, + "6": 3, + "7": 9, + "8": 38, + "9": 364 + } + }, + "old_complete": { + "paid": { + "1": 44053, + "16": 1872, + "2": 8607, + "24": 208, + "3": 9386, + "32": 832, + "4": 2014, + "5": 2926, + "56": 208, + "6": 152, + "64": 208, + "7": 171, + "8": 19 + }, + "paid_jobs": 70656, + "paid_rank_mass": 200900, + "productive_fields": 14214, + "productive_rank_mass": 201708, + "rank_mass_surplus": 808, + "targets": { + "1": 266, + "153": 208, + "17": 1872, + "2": 152, + "25": 208, + "3": 76, + "33": 832, + "4": 2033, + "5": 285, + "57": 208, + "6": 57, + "65": 208, + "7": 171, + "8": 608, + "9": 7030 + } + }, + "old_local": { + "events": 17757, + "helper_fields": 562, + "opcode_counts": { + "ADD": 13363, + "CLEAR": 43, + "INIT": 43, + "MOVE": 3456, + "SCALE": 852 + }, + "owned_lifetimes": 43, + "paid": { + "1": 2231, + "2": 453, + "3": 494, + "4": 106, + "5": 154, + "6": 8, + "7": 9, + "8": 1 + }, + "paid_jobs": 3456, + "paid_rank_mass": 5932, + "peak_owned": 13, + "productive_rank_mass": 4212, + "targets": { + "1": 14, + "2": 8, + "3": 4, + "4": 107, + "5": 15, + "6": 3, + "7": 9, + "8": 32, + "9": 370 + } + }, + "rank_mass_changes": { + "paid": -6, + "productive": -6, + "signed": 0 + }, + "schema_version": 1, + "source_binding": { + "added_MOVE_records": [ + [ + [ + "MOVE", + 130, + 3, + 105, + false + ], + 1 + ], + [ + [ + "MOVE", + 130, + 105, + 336, + false + ], + 1 + ], + [ + [ + "MOVE", + 171, + 3, + 106, + false + ], + 1 + ], + [ + [ + "MOVE", + 171, + 106, + 412, + false + ], + 1 + ], + [ + [ + "MOVE", + 208, + 3, + 105, + false + ], + 1 + ], + [ + [ + "MOVE", + 208, + 105, + 450, + false + ], + 1 + ], + [ + [ + "MOVE", + 472, + 105, + 533, + false + ], + 1 + ], + [ + [ + "MOVE", + 520, + 106, + 739, + false + ], + 1 + ], + [ + [ + "MOVE", + 544, + 105, + 748, + false + ], + 1 + ], + [ + [ + "MOVE", + 624, + 105, + 117, + false + ], + 1 + ], + [ + [ + "MOVE", + 655, + 106, + 1052, + false + ], + 1 + ], + [ + [ + "MOVE", + 671, + 105, + 1048, + false + ], + 1 + ] + ], + "changed_initial_frames": { + "472": [ + 3, + 105 + ], + "520": [ + 3, + 106 + ], + "544": [ + 3, + 105 + ], + "624": [ + 3, + 105 + ], + "655": [ + 3, + 106 + ], + "671": [ + 3, + 105 + ] + }, + "clusters": [ + { + "anchor_destination_ranks": [ + 3, + 5 + ], + "anchors": [ + 520, + 655 + ], + "carrier": 171, + "entrance": 106, + "old_carrier_destination": 412, + "old_carrier_rank": 2, + "round": 1 + }, + { + "anchor_destination_ranks": [ + 3, + 5 + ], + "anchors": [ + 544, + 671 + ], + "carrier": 208, + "entrance": 105, + "old_carrier_destination": 450, + "old_carrier_rank": 2, + "round": 1 + }, + { + "anchor_destination_ranks": [ + 3, + 5 + ], + "anchors": [ + 472, + 624 + ], + "carrier": 130, + "entrance": 105, + "old_carrier_destination": 336, + "old_carrier_rank": 2, + "round": 2 + } + ], + "removed_MOVE_records": [ + [ + [ + "MOVE", + 130, + 3, + 336, + false + ], + 1 + ], + [ + [ + "MOVE", + 171, + 3, + 412, + false + ], + 1 + ], + [ + [ + "MOVE", + 208, + 3, + 450, + false + ], + 1 + ], + [ + [ + "MOVE", + 472, + 3, + 533, + false + ], + 1 + ], + [ + [ + "MOVE", + 520, + 3, + 739, + false + ], + 1 + ], + [ + [ + "MOVE", + 544, + 3, + 748, + false + ], + 1 + ], + [ + [ + "MOVE", + 624, + 3, + 117, + false + ], + 1 + ], + [ + [ + "MOVE", + 655, + 3, + 1052, + false + ], + 1 + ], + [ + [ + "MOVE", + 671, + 3, + 1048, + false + ], + 1 + ] + ] + }, + "status": "PASS_CONDITIONAL_PROFILES" +} diff --git a/research/relative-tariff-integer-exp/source/PROFILE-PROOF.md b/research/relative-tariff-integer-exp/source/PROFILE-PROOF.md new file mode 100644 index 0000000000..14fb494b33 --- /dev/null +++ b/research/relative-tariff-integer-exp/source/PROFILE-PROOF.md @@ -0,0 +1,275 @@ +# Exact matched profiles for PR6375 and its retained PR6372 baseline + +This is a finite, source-bound **formal recursive-invoice audit**, not a +supplier-admission result. The two independently written profile extractors +read the literal words and fixed controller as data. Neither executes the +vendored constructor/controller code or imports the author's invoice engine. +The tables and accounting identities below are derived from those data, rather +than copied from the author's RESULT receipt. + +This first checkpoint establishes the exact invoice to which a later +tariff-exponent proof must apply. It does **not** establish the approximately +0.873 relative-gain threshold or any new kappa. In particular, the author's +separate proof that the complete raw-kappa crossing is unique below its cap +is already predecessor coverage; that is not the missing threshold addressed +by the planned continuation. + +## 1. Frozen source and common boundary + +The candidate is PR6375 head +`247b5c319b9f58fe9ee61dbf80697f8a9a429831`. The baseline is the exact PR6372 +word retained by that head, originating at +`b556600ffe14be72406b03a47c661f3c7f1aff06`. The candidate WORD Git blob is +`b1cfd03abe9128cf5a3908fbd82652e5e8a2e292`; the retained baseline WORD blob +is `0af79e58172f85c302c35b193205c0b185b09393`. Their compressed source bytes +are authenticated separately; compression is not used to define mathematical +word equality. [SOURCE-PINS.json](SOURCE-PINS.json) gives their SHA256 pins +and the other exact inputs. + +Both invoices use the same retained controller blob +`1f2e375b24aba5fb25580dfea7fab7a2049f3eb8`: nineteen LOCAL calls, +sixteen thin QUERY calls and sixteen paired whole IDLE calls. Both local words +have 770 public roles, the same 104 live input ports, and 29 owned role labels. +Main public roles are precisely `live` and `live+112`, giving 208 main roles; +the other 562 public roles supply the local helper targets. Owned roles are +not productive public helpers. + +The source frame tables, final public frames, main-role list, ports and owned +inventory are unchanged. Exactly six public initial frames change. All later +comparisons use this common caller and boundary: no target, idle, query or +unchanged paid job is dropped because it cancels in the final difference. + +## 2. Declared rank tariff and its applicability boundary + +For a frame label `a`, let `S_a` be the binary span of its literal generators +in `F_2^9`, and let `d_a=dim(S_a)`. Dimension is established by binary linear +algebra, not by assuming that the supplied generators are independent. + +The retained nested-frame recursive tariff charges a MOVE from `a` to `b` +one job of rank + +`rho(a,b) = |d_b-d_a|`, + +provided the two source spans are strictly nested. The extraction checks the +actual source labels against the evolving role frames and checks strict +containment. This is important: unrelated frames of the same dimensional +difference would not acquire this tariff by a mere rank-count coincidence. +Every literal MOVE is charged, including owned-role MOVEs and both directions +of a trip. The trailing ownership flag changes no recursive charge into a +free operation. + +A public non-main helper whose initial span is contained in its final span +contributes one productive target of rank + +`tau(r) = d_final(r)-d_initial(r)`. + +That is the declared endpoint target contract, conditional on realization of +the corresponding independent native helper channel. Changing an initial frame +therefore changes its productive credit even if the scalar program still has +the same number of roles. No owned lifetime supplies a productive helper +credit. INIT, CLEAR, ADD and SCALE supply no extra recursive job under this +model; their actual ordinary implementation and funding remain obligations. +In particular, excluding them from this recursive histogram does not assign +their physical work zero cost. + +These rules identify the finite invoice being audited. They do not prove that +every charged native transition, output channel or erasure is physically +realized. Strict binary containment establishes the rank geometry needed by +the declared tariff, not native phases, all-column correctness or an all-width +implementation. A frame-valid trace alone does not establish arbitrary-input +scalar or native endpoint equality. + +## 3. Complete local histograms + +Counting all literal MOVE events and all 562 public helper boundaries gives: + +| Rank | Baseline paid | Candidate paid | Baseline helper targets | Candidate helper targets | +|---:|---:|---:|---:|---:| +| 1 | 2231 | 2237 | 14 | 14 | +| 2 | 453 | 453 | 8 | 8 | +| 3 | 494 | 491 | 4 | 4 | +| 4 | 106 | 109 | 107 | 107 | +| 5 | 154 | 151 | 15 | 15 | +| 6 | 8 | 8 | 3 | 3 | +| 7 | 9 | 9 | 9 | 9 | +| 8 | 1 | 1 | 32 | 38 | +| 9 | 0 | 0 | 370 | 364 | +| **Total** | **3456** | **3459** | **562** | **562** | + +Both words include the same 25 owned MOVE charges, distributed as +`{1:11, 2:5, 3:2, 4:6, 5:1}`. These charges are inside the table, not added +afterwards. Each word has 43 INIT and 43 CLEAR occurrences; these event counts +do not assert that a physically valid erasure implementation exists. + +The baseline event census is ADD13363, SCALE852, MOVE3456, INIT43, CLEAR43, +for 17757 events. The candidate is ADD13371, SCALE852, MOVE3459, INIT43, +CLEAR43, for 17768 events. Event counts by themselves are not a complete +ordinary-work tariff or a funding proof. + +### The six endpoint debits and three carrier trips + +Write `Z=3` and `Omega=127`. The literal frame generators give +`S_Z={0}`, `d_Omega=9`, frame106=`span{30}` and +frame105=`span{51}`, both of dimension one. + +| Carrier | Its old first destination | Entrance F | Lifted helper, old first destination | First MOVE ranks old to new | +|---:|---:|---:|---|---| +| 171 | 412, dimension2 | 106 | 520 to739, dimension3; 655 to1052, dimension5 | helper ranks3,5 to2,4; carrier2 to1+1 | +| 208 | 450, dimension2 | 105 | 544 to748, dimension3; 671 to1048, dimension5 | helper ranks3,5 to2,4; carrier2 to1+1 | +| 130 | 336, dimension2 | 105 | 472 to533, dimension3; 624 to117, dimension5 | helper ranks3,5 to2,4; carrier2 to1+1 | + +For each row, `F` is strictly contained in both helper first-destination +spans and the carrier's old first-destination span. The actual candidate +carrier trace replaces `Z -> G_carrier` with the ordered pair +`Z -> F -> G_carrier`. The actual helper first departure begins at `F`. +All remaining MOVE records cancel in the complete old/new MOVE multiset, +while their chronological validity is checked separately. + +One cluster changes its paid profile by + +`(H_2-H_3) + (H_4-H_5) + (2H_1-H_2)` +`= 2H_1-H_3+H_4-H_5`. + +There are three clusters. Thus the local paid difference, candidate minus +baseline, is exactly + +`Delta P = 6H_1-3H_3+3H_4-3H_5`. + +All six lifted helpers formerly began at `Z` and still end at `Omega`; they +now begin at a one-dimensional `F`. Their six target ranks change from9 +to8. Carrier endpoint frames do not change. Hence + +`Delta T = 6H_8-6H_9`. + +This derives the productive debit from literal endpoints, rather than +retaining six rank-nine credits merely because the helper count is unchanged. +It also retains both legs of all three carrier trips. Response/restore ADDs +do not provide an additional recursive target or cancel either trip charge. +Their arbitrary-input correctness is a separate endpoint question. + +## 4. Exact fixed-caller expansion + +Let `p_r,t_r` be the local paid and helper-target multiplicities above, and +let `e_r` denote one job/target at rank `r`. Reading the controller events +directly gives nineteen LOCAL stages, sixteen QUERY events, and IDLE stage-set +sizes with multiplicities + +`m_2=9, m_3=1, m_4=4, m_7=1, m_8=1`. + +The same counts follow from the retained binary forest with root sizes4,7,8: +it has19 leaves and16 internal nodes. Each internal node has one query, one +paired idle and two declared main boundary fields. The two final main fields +have all19 stages. This is an independent finite counting route; it is not an +independent proof of the emitted controller's physical action. + +Under the retained interface, a thin query costs104 rank-one jobs, a whole +paired idle on `k` stages costs208 rank-`8k` jobs, and a main field on `k` +stages contributes104 targets of rank`1+8k`. The signs of the two central +powers do not change these declared absolute ranks. Therefore the complete +profiles are exactly + +`P = 19 p + 1664 e_1 + 208 sum_k m_k e_(8k)`, + +`T = 19 t + 208 e_153 + 208 sum_k m_k e_(1+8k)`. + +The factor208 at a node counts both main fields, each with104 ports; it is +not two credits for one field. LOCAL helper credits occur once per actual +stage. The formulas retain every whole idle and query independently of +whether its relative old/new difference vanishes. + +### Complete paid profiles + +| Rank | Baseline | Candidate | +|---:|---:|---:| +| 1 | 44053 | 44167 | +| 2 | 8607 | 8607 | +| 3 | 9386 | 9329 | +| 4 | 2014 | 2071 | +| 5 | 2926 | 2869 | +| 6 | 152 | 152 | +| 7 | 171 | 171 | +| 8 | 19 | 19 | +| 16 | 1872 | 1872 | +| 24 | 208 | 208 | +| 32 | 832 | 832 | +| 56 | 208 | 208 | +| 64 | 208 | 208 | +| **Total** | **70656** | **70713** | + +### Complete productive profiles + +| Rank | Baseline | Candidate | +|---:|---:|---:| +| 1 | 266 | 266 | +| 2 | 152 | 152 | +| 3 | 76 | 76 | +| 4 | 2033 | 2033 | +| 5 | 285 | 285 | +| 6 | 57 | 57 | +| 7 | 171 | 171 | +| 8 | 608 | 722 | +| 9 | 7030 | 6916 | +| 17 | 1872 | 1872 | +| 25 | 208 | 208 | +| 33 | 832 | 832 | +| 57 | 208 | 208 | +| 65 | 208 | 208 | +| 153 | 208 | 208 | +| **Total** | **14214** | **14214** | + +Both full profiles have target rank mass minus paid rank mass808. That +linear-cost check is a consistency invariant, not a sign proof at a nonlinear +tariff or proof that either complete margin is favorable. + +## 5. What a subsequent threshold certificate must certify + +For any declared rank tariff `H_r`, define the formal complete margin +`M(H)=sum_r(T_r-P_r)H_r`. The exact matched-profile identity is + +`M_new(H)-M_old(H) = 19 g(H)`, + +`g(H) = 6(H_8-H_9)-6H_1+3(H_3-H_4+H_5)`. + +This identity holds coefficient by coefficient, independently of any +monotonicity or concavity assumption on `H`. In particular it is zero at +linear rank cost. For the power tariff `H_r=r^s`, the later question concerns +the zeros and signs of this **relative gain** on the specified exponent +domain. It is different from the zero of either complete margin as a function +of kappa. No grid, Decimal bisection, approximate sign-switch prose or +author-engine agreement establishes a complete root count. + +This checkpoint leaves that whole-domain sign/threshold proof open. The +existing canonical general-rank power-variation tool and prior tariff proofs +are available methods with retained credit, not new general theorems claimed +by this audit. + +## 6. Remaining obligations and predecessor credit + +The finite formal billing gate does not prove the new lift response maps, +arbitrary-input endpoint identity, native phases/all columns, the physical +fixed-caller contact map, owned erasure, complete ordinary funding, +all-width implementation, compiler or outer admission. It supplies no new +selected frontier, no admitted kappa and no global optimality theorem. The +five retained framework assumptions remain: `native_all_columns`, +`owned_erasure`, `compiler`, `precision_tape`, `analytic_recovery`. + +DreamingOfClouds with Claude Opus5.5 assistance supplies PR6375 and its +reported read-only row/ownership and sensitivity audit. Ali Romman supplies +PR6372, PR6353, PR6349 and PR6348 with OpenAI Codex assistance; +PR6349 builds on DreamingOfClouds PR6314. Their source words, joint bases, +native input-lift move class, fixed caller, price engines and complete +retained NOTICE chain remain credited. Cinna Davis supplies the productive +controller/thin-query interface; Jacob Alan Sussman supplies productive +recursion; zxv and Cao Yifan supply the interval/compiler line, with the +remaining P104/native/BIT/analytic authors retained in +[sources/NOTICE](sources/NOTICE). + +Independent PR6359 already audits PR6353's finite invoice and one fixed-saving +sign. PR6376 audits PR6372's two-anchor scalar boundary/endpoint. Their +evidence is preserved and their conclusions are not silently transferred to +PR6375. General rank-exchange thresholds such as PR5174 and the different +P104 chart-tariff switches in PR5772 are earlier mathematical context. +The new work here is the exact matched-source profile extraction and scoped +accounting proof, by ToikY with substantial OpenAI Codex assistance. Agreement +between two agent implementations is reproducibility evidence, not independent +human or proof-kernel acceptance. diff --git a/research/relative-tariff-integer-exp/source/PROFILES.json b/research/relative-tariff-integer-exp/source/PROFILES.json new file mode 100644 index 0000000000..d6f1eb6afe --- /dev/null +++ b/research/relative-tariff-integer-exp/source/PROFILES.json @@ -0,0 +1,465 @@ +{ + "complete": { + "new": { + "paid": { + "1": 44167, + "16": 1872, + "2": 8607, + "24": 208, + "3": 9329, + "32": 832, + "4": 2071, + "5": 2869, + "56": 208, + "6": 152, + "64": 208, + "7": 171, + "8": 19 + }, + "paid_jobs": 70713, + "productive_fields": 14214, + "rank_mass_surplus": 808, + "targets": { + "1": 266, + "153": 208, + "17": 1872, + "2": 152, + "25": 208, + "3": 76, + "33": 832, + "4": 2033, + "5": 285, + "57": 208, + "6": 57, + "65": 208, + "7": 171, + "8": 722, + "9": 6916 + } + }, + "old": { + "paid": { + "1": 44053, + "16": 1872, + "2": 8607, + "24": 208, + "3": 9386, + "32": 832, + "4": 2014, + "5": 2926, + "56": 208, + "6": 152, + "64": 208, + "7": 171, + "8": 19 + }, + "paid_jobs": 70656, + "productive_fields": 14214, + "rank_mass_surplus": 808, + "targets": { + "1": 266, + "153": 208, + "17": 1872, + "2": 152, + "25": 208, + "3": 76, + "33": 832, + "4": 2033, + "5": 285, + "57": 208, + "6": 57, + "65": 208, + "7": 171, + "8": 608, + "9": 7030 + } + } + }, + "complete_margin_delta_coefficients": { + "1": -114, + "3": 57, + "4": -57, + "5": 57, + "8": 114, + "9": -114 + }, + "complete_paid_delta": { + "1": 114, + "3": -57, + "4": 57, + "5": -57 + }, + "complete_productive_delta": { + "8": 114, + "9": -114 + }, + "controls": { + "cases": [ + { + "carrier": 171, + "complete_paid_delta": { + "1": -19 + }, + "complete_target_delta": {}, + "control": "omitted_carrier_trip", + "event_index": 9242, + "omitted_event": [ + "MOVE", + 171, + 3, + 106, + false + ], + "structural_rejection": "active common-frame scalar destination" + }, + { + "carrier": 208, + "complete_paid_delta": { + "1": -19 + }, + "complete_target_delta": {}, + "control": "omitted_carrier_trip", + "event_index": 9218, + "omitted_event": [ + "MOVE", + 208, + 3, + 105, + false + ], + "structural_rejection": "active common-frame scalar destination" + }, + { + "carrier": 130, + "complete_paid_delta": { + "1": -19 + }, + "complete_target_delta": {}, + "control": "omitted_carrier_trip", + "event_index": 8474, + "omitted_event": [ + "MOVE", + 130, + 3, + 105, + false + ], + "structural_rejection": "active common-frame scalar destination" + }, + { + "complete_paid_delta": {}, + "complete_target_delta": { + "8": -19, + "9": 19 + }, + "control": "reverted_lifted_input_520", + "structural_rejection": "active distinct common-frame source" + }, + { + "complete_paid_delta": { + "32": -208 + }, + "complete_target_delta": {}, + "control": "missing_idle", + "event_index": 8, + "omitted_event": [ + "IDLE", + 2, + 3, + [ + 1, + 2, + 3, + 4 + ] + ], + "structural_rejection": "fixed caller occurrence census" + }, + { + "complete_paid_delta": { + "1": -104 + }, + "complete_target_delta": {}, + "control": "missing_query", + "event_index": 5, + "omitted_event": [ + "QUERY", + 2, + 3, + -1 + ], + "structural_rejection": "fixed caller occurrence census" + }, + { + "complete_paid_delta": { + "1": -2237, + "2": -453, + "3": -491, + "4": -109, + "5": -151, + "6": -8, + "7": -9, + "8": -1 + }, + "complete_target_delta": { + "1": -14, + "2": -8, + "3": -4, + "4": -107, + "5": -15, + "6": -3, + "7": -9, + "8": -38, + "9": -364 + }, + "control": "missing_local", + "event_index": 21, + "omitted_event": [ + "LOCAL", + 1, + 0, + 1 + ], + "structural_rejection": "fixed caller occurrence census" + } + ], + "qualification": "These changed literal records give counterfactual invoice differences; structural guards reject them. They are not valid cheaper programs." + }, + "forest_node_sizes": { + "2": 9, + "3": 1, + "4": 4, + "7": 1, + "8": 1 + }, + "limits": [ + "Strict nested-frame ranks use the retained native/tariff premise; no native phase or all-width implementation proof is supplied.", + "Scalar common-frame and owned lifetime syntax is checked, not the public endpoint or shared response algebra.", + "The caller diagonal and primitive contracts are premises; no physical caller or ordinary-work funding is admitted.", + "No relative crossover, power evaluation, raw kappa root, new saving or supplier admission is computed." + ], + "literal_changes": { + "added_MOVE_count": 12, + "carrier_detours": [ + { + "carrier": 171, + "entrance_frame": 106, + "new_first_MOVEs": [ + [ + "MOVE", + 171, + 3, + 106, + false + ], + [ + "MOVE", + 171, + 106, + 412, + false + ] + ], + "new_ranks": [ + 1, + 1 + ], + "old_first_MOVE": [ + "MOVE", + 171, + 3, + 412, + false + ], + "old_rank": 2 + }, + { + "carrier": 208, + "entrance_frame": 105, + "new_first_MOVEs": [ + [ + "MOVE", + 208, + 3, + 105, + false + ], + [ + "MOVE", + 208, + 105, + 450, + false + ] + ], + "new_ranks": [ + 1, + 1 + ], + "old_first_MOVE": [ + "MOVE", + 208, + 3, + 450, + false + ], + "old_rank": 2 + }, + { + "carrier": 130, + "entrance_frame": 105, + "new_first_MOVEs": [ + [ + "MOVE", + 130, + 3, + 105, + false + ], + [ + "MOVE", + 130, + 105, + 336, + false + ] + ], + "new_ranks": [ + 1, + 1 + ], + "old_first_MOVE": [ + "MOVE", + 130, + 3, + 336, + false + ], + "old_rank": 2 + } + ], + "final_frame_changes": {}, + "initial_frame_changes": { + "472": [ + 3, + 105 + ], + "520": [ + 3, + 106 + ], + "544": [ + 3, + 105 + ], + "624": [ + 3, + 105 + ], + "655": [ + 3, + 106 + ], + "671": [ + 3, + 105 + ] + }, + "other_MOVE_records_cancel": true, + "removed_MOVE_count": 9 + }, + "local_margin_delta_coefficients": { + "1": -6, + "3": 3, + "4": -3, + "5": 3, + "8": 6, + "9": -6 + }, + "local_paid_delta": { + "1": 6, + "3": -3, + "4": 3, + "5": -3 + }, + "local_productive_delta": { + "8": 6, + "9": -6 + }, + "new_local": { + "census": { + "COPY_events": 0, + "events": 17768, + "opcode_counts": { + "ADD": 13371, + "CLEAR": 43, + "INIT": 43, + "MOVE": 3459, + "SCALE": 852 + }, + "owned_fields": 29, + "owned_lifetimes": 43, + "peak_owned": 13 + }, + "paid": { + "1": 2237, + "2": 453, + "3": 491, + "4": 109, + "5": 151, + "6": 8, + "7": 9, + "8": 1 + }, + "targets": { + "1": 14, + "2": 8, + "3": 4, + "4": 107, + "5": 15, + "6": 3, + "7": 9, + "8": 38, + "9": 364 + } + }, + "old_local": { + "census": { + "COPY_events": 0, + "events": 17757, + "opcode_counts": { + "ADD": 13363, + "CLEAR": 43, + "INIT": 43, + "MOVE": 3456, + "SCALE": 852 + }, + "owned_fields": 29, + "owned_lifetimes": 43, + "peak_owned": 13 + }, + "paid": { + "1": 2231, + "2": 453, + "3": 494, + "4": 106, + "5": 154, + "6": 8, + "7": 9, + "8": 1 + }, + "targets": { + "1": 14, + "2": 8, + "3": 4, + "4": 107, + "5": 15, + "6": 3, + "7": 9, + "8": 32, + "9": 370 + } + }, + "schema_version": 1, + "scope": "source-bound formal local and complete same-caller rank profiles only" +} diff --git a/research/relative-tariff-integer-exp/source/RELATIVE-RESULT.json b/research/relative-tariff-integer-exp/source/RELATIVE-RESULT.json new file mode 100644 index 0000000000..35f5f0898a --- /dev/null +++ b/research/relative-tariff-integer-exp/source/RELATIVE-RESULT.json @@ -0,0 +1,172 @@ +{ + "analytic_root_count": { + "I0_strict_upper": "-11/201", + "L0": "1", + "L1_negative_log_ratio": { + "denominator": "5559060566555523", + "numerator": "3435973836800000" + }, + "Peano_kernel_pieces": [ + { + "intercept": 2, + "left": 1, + "right": 3, + "slope": -1 + }, + { + "intercept": -1, + "left": 3, + "right": 4, + "slope": 0 + }, + { + "intercept": 3, + "left": 4, + "right": 5, + "slope": -1 + }, + { + "intercept": -2, + "left": 5, + "right": 8, + "slope": 0 + }, + { + "intercept": -18, + "left": 8, + "right": 9, + "slope": 2 + } + ], + "coefficient_sum": -1, + "f_coefficients": { + "1": -2, + "3": 1, + "4": -1, + "5": 1, + "8": 2, + "9": -2 + }, + "f_derivative0_log_ratio": "80/27", + "first_shifted_moment": 1, + "gain_signs": [ + "negative below the unique interior root", + "positive above it up to1", + "zero at1" + ], + "interior_root_multiplicity": 1, + "interior_roots": 1, + "kernel_sign_switch": 2, + "log_ratio0_strict_lower": "212/201", + "proper_integral_factorization": "f(s)=(s-1)*(1+s*integral_1^9 K(x)*x^(s-2) dx)", + "qualification": "Analytic root count follows the accompanying reviewed Taylor/single-crossing proof, not sampled signs.", + "rank_mass": 0 + }, + "complete_factor": 19, + "complete_gain_coefficients": { + "1": -114, + "3": 57, + "4": -57, + "5": 57, + "8": 114, + "9": -114 + }, + "controls": { + "missing_carrier_fee": { + "complete_coefficient_witness": { + "actual": -95, + "expected": -114, + "rank": 1 + }, + "kind": "counterfactual invoice coefficients, not a valid cheaper source program", + "rejection": "complete profile binding mismatch: side1 part0 rank1" + }, + "missing_productive_debit": { + "complete_coefficient_witness": { + "actual": 95, + "expected": 114, + "rank": 8 + }, + "kind": "counterfactual invoice coefficients, not a valid cheaper source program", + "rejection": "complete profile binding mismatch: side1 part1 rank8" + }, + "wrong_endpoint_sign_orientation": { + "rejection": "relative root endpoint sign orientation" + } + }, + "count_tariff_gain": "-3", + "examples": { + "author_claimed_tariff": { + "complete_relative_gain": [ + "41965186627534333868839162059/500000000000000000000000000000", + "83930373255068667737678324517/1000000000000000000000000000000" + ], + "exponent": "1246061/1250000", + "local_gain": [ + "2208694033028122835202061161/500000000000000000000000000000", + "4417388066056245670404122343/1000000000000000000000000000000" + ], + "source_claimed_kappa": "3939/1250000" + }, + "square_root": { + "exponent": "1/2", + "local_gain": [ + "-1125080896316858444569875278787/1000000000000000000000000000000", + "-1125080896316858444569875278757/1000000000000000000000000000000" + ] + } + }, + "interior_bracket": { + "gain_at_lower": [ + "-78834808335305741013/1000000000000000000000000000000", + "-1231793880239152203/15625000000000000000000000000" + ], + "gain_at_upper": [ + "12206898146138879211/1000000000000000000000000000000", + "47683195883354997/3906250000000000000000000000" + ], + "lower": "11712509413/13421772800", + "upper": "5856254707/6710886400", + "width": "1/13421772800" + }, + "interval_method": { + "argument_divisor": 16, + "log_atanh_terms": 48, + "log_work_grid": "10000000000000000000000000000000000000000", + "outward_squarings": 4, + "positive_exp_degree": 24, + "power_grid": "1000000000000000000000000000000" + }, + "limits": [ + "Profile extraction and native/rank-tariff premises remain as stated in the immutable profile evidence.", + "A relative bill improvement does not prove source endpoint/native/caller validity or ordinary funding.", + "No new multiplication saving, raw kappa crossing, supplier admission or selected-frontier change is claimed." + ], + "linear_tariff_gain": "0", + "local_gain_coefficients": { + "1": -6, + "3": 3, + "4": -3, + "5": 3, + "8": 6, + "9": -6 + }, + "preserved_scientific_files": { + "ORACLE-PROFILES.json": "dd9abee4eed9bdf52cd731c2fb61d2ec17022ab136ab255e4325181652ba06e4", + "PROFILE-PROOF.md": "b95cbfc30cfcf85016406801005a8284b0eca61cb8c1cc5661376e242b0a153e", + "PROFILES.json": "985500c0ebda3ba82570cf844d3acaed78d4aec7923956ea889b575e43c4e6d1", + "SOURCE-PINS.json": "5eb5b9458165046dad7170d5801a12f84f92891ac16ef2fd8bcbacf357046237", + "oracle_profiles.py": "4840369f3311369c09762fccaadcbc2a9fecffc53bcf3dd925abf2b059014cb0", + "sources/CONTROLLER.json": "6fd67eaabe659956d6694471d3fd7d2824c0a4a79cf3b8f22922f7189b11b91f", + "sources/LIFTS.json": "38960b70a074888a2aeaf3b543629a7ae747c0c5d4f5c853371a6e7c483766c5", + "sources/NEW-WORD.json.gz": "9e31463a785c18a70f6ae6ef3d04a6560dbb965517109390fe820f9fac3371b3", + "sources/NOTICE": "91f24d68004688bc0a56303a48edcb5ddabd66bfc2326950603bf98dec245bbe", + "sources/OLD-WORD.json.gz": "e3b6f1c25d672b8c85433be97ebad77ae6a6972352ce2ff63507d30835fcb491", + "sources/constructor-source.py": "fe7dc1d9aa55da393465388ee90faaa687b1e5be48dfa816a421069fa3d2de08", + "sources/controller-source.py": "8067ade84815b54d539cbaef9885db9fa4d7a23fdde2e683451d317038a8477c", + "sources/upstream-PROOF.md": "769e0f87e6b85c557b48135d2d898bb485cf77ce9925540e0a3740e6283f41af", + "verify_profiles.py": "e7d2bf27b3ce2cca939d3fc8239876aa82dcdfcd816bd78df4c9171f37e09319" + }, + "schema_version": 1, + "scope": "source-specific exact relative power-tariff crossover, not a raw kappa root" +} diff --git a/research/relative-tariff-integer-exp/source/SOURCE-PINS.json b/research/relative-tariff-integer-exp/source/SOURCE-PINS.json new file mode 100644 index 0000000000..49ddf9c85f --- /dev/null +++ b/research/relative-tariff-integer-exp/source/SOURCE-PINS.json @@ -0,0 +1,71 @@ +{ + "schema": "source-pins/v1", + "upstream_head": "247b5c319b9f58fe9ee61dbf80697f8a9a429831", + "retained_baseline_head": "b556600ffe14be72406b03a47c661f3c7f1aff06", + "files": [ + { + "file": "sources/NEW-WORD.json.gz", + "commit": "247b5c319b9f58fe9ee61dbf80697f8a9a429831", + "path": "research/p104-shared-carrier-lifts/WORD.json.gz", + "git_blob": "b1cfd03abe9128cf5a3908fbd82652e5e8a2e292", + "sha256": "9e31463a785c18a70f6ae6ef3d04a6560dbb965517109390fe820f9fac3371b3", + "bytes": 85485 + }, + { + "file": "sources/OLD-WORD.json.gz", + "commit": "247b5c319b9f58fe9ee61dbf80697f8a9a429831", + "path": "research/p104-shared-carrier-lifts/inputs/pr6372-WORD.json.gz", + "git_blob": "0af79e58172f85c302c35b193205c0b185b09393", + "sha256": "e3b6f1c25d672b8c85433be97ebad77ae6a6972352ce2ff63507d30835fcb491", + "bytes": 85365 + }, + { + "file": "sources/CONTROLLER.json", + "commit": "247b5c319b9f58fe9ee61dbf80697f8a9a429831", + "path": "research/balanced-query-tree/CONTROLLER.json", + "git_blob": "1f2e375b24aba5fb25580dfea7fab7a2049f3eb8", + "sha256": "6fd67eaabe659956d6694471d3fd7d2824c0a4a79cf3b8f22922f7189b11b91f", + "bytes": 27959 + }, + { + "file": "sources/controller-source.py", + "commit": "247b5c319b9f58fe9ee61dbf80697f8a9a429831", + "path": "research/balanced-query-tree/controller.py", + "git_blob": "3b4bf82eba05d57ef4bb1fd934e8ca65780425c1", + "sha256": "8067ade84815b54d539cbaef9885db9fa4d7a23fdde2e683451d317038a8477c", + "bytes": 7474 + }, + { + "file": "sources/LIFTS.json", + "commit": "247b5c319b9f58fe9ee61dbf80697f8a9a429831", + "path": "research/p104-shared-carrier-lifts/LIFTS.json", + "git_blob": "2ee8cb78fd149f9aca8dd953c650b92495a56266", + "sha256": "38960b70a074888a2aeaf3b543629a7ae747c0c5d4f5c853371a6e7c483766c5", + "bytes": 1091 + }, + { + "file": "sources/constructor-source.py", + "commit": "247b5c319b9f58fe9ee61dbf80697f8a9a429831", + "path": "research/p104-shared-carrier-lifts/construct.py", + "git_blob": "c099995bef0e224cbb0ec61c06ed3d0b4d478b33", + "sha256": "fe7dc1d9aa55da393465388ee90faaa687b1e5be48dfa816a421069fa3d2de08", + "bytes": 7874 + }, + { + "file": "sources/upstream-PROOF.md", + "commit": "247b5c319b9f58fe9ee61dbf80697f8a9a429831", + "path": "research/p104-shared-carrier-lifts/PROOF.md", + "git_blob": "bd20fcaf2078691d914d6afbc5cb06a75f47770d", + "sha256": "769e0f87e6b85c557b48135d2d898bb485cf77ce9925540e0a3740e6283f41af", + "bytes": 3940 + }, + { + "file": "sources/NOTICE", + "commit": "247b5c319b9f58fe9ee61dbf80697f8a9a429831", + "path": "research/p104-shared-carrier-lifts/NOTICE", + "git_blob": "638a187d1417bda8976e945a2aeaed116a090e37", + "sha256": "91f24d68004688bc0a56303a48edcb5ddabd66bfc2326950603bf98dec245bbe", + "bytes": 17583 + } + ] +} diff --git a/research/relative-tariff-integer-exp/source/oracle_profiles.py b/research/relative-tariff-integer-exp/source/oracle_profiles.py new file mode 100644 index 0000000000..724e0a79f0 --- /dev/null +++ b/research/relative-tariff-integer-exp/source/oracle_profiles.py @@ -0,0 +1,385 @@ +"""Independent literal frame-rank profile and fixed-caller invoice extractor. + +The author constructor, checkers, result, peer verifier and earlier audit code +are not imported. Native rank tariffs and supplier/interface correctness remain +premises. This file makes no power-threshold or new-kappa calculation. +""" +from collections import Counter +from fractions import Fraction +from hashlib import sha1, sha256 +from pathlib import Path +import gzip +import json +import sys + +HERE = Path(__file__).resolve().parent +PUBLIC, OWNED, PORTS = 770, 29, 104 +PINS = { + "sources/NEW-WORD.json.gz": ("9e31463a785c18a70f6ae6ef3d04a6560dbb965517109390fe820f9fac3371b3", "b1cfd03abe9128cf5a3908fbd82652e5e8a2e292"), + "sources/OLD-WORD.json.gz": ("e3b6f1c25d672b8c85433be97ebad77ae6a6972352ce2ff63507d30835fcb491", "0af79e58172f85c302c35b193205c0b185b09393"), + "sources/CONTROLLER.json": ("6fd67eaabe659956d6694471d3fd7d2824c0a4a79cf3b8f22922f7189b11b91f", "1f2e375b24aba5fb25580dfea7fab7a2049f3eb8"), + "sources/controller-source.py": ("8067ade84815b54d539cbaef9885db9fa4d7a23fdde2e683451d317038a8477c", "3b4bf82eba05d57ef4bb1fd934e8ca65780425c1"), + "sources/LIFTS.json": ("38960b70a074888a2aeaf3b543629a7ae747c0c5d4f5c853371a6e7c483766c5", "2ee8cb78fd149f9aca8dd953c650b92495a56266"), + "sources/constructor-source.py": ("fe7dc1d9aa55da393465388ee90faaa687b1e5be48dfa816a421069fa3d2de08", "c099995bef0e224cbb0ec61c06ed3d0b4d478b33"), + "sources/upstream-PROOF.md": ("769e0f87e6b85c557b48135d2d898bb485cf77ce9925540e0a3740e6283f41af", "bd20fcaf2078691d914d6afbc5cb06a75f47770d"), + "sources/NOTICE": ("91f24d68004688bc0a56303a48edcb5ddabd66bfc2326950603bf98dec245bbe", "638a187d1417bda8976e945a2aeaed116a090e37"), +} + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def integer(value, lower, upper, label): + require(type(value) is int and lower <= value < upper, label) + return value + + +def canonical(value): + return json.dumps(value, sort_keys=True, separators=(",", ":"), allow_nan=False) + + +def authenticate(): + manifest = json.loads((HERE / "SOURCE-PINS.json").read_bytes()) + require(manifest["schema"] == "source-pins/v1" + and manifest["upstream_head"] == "247b5c319b9f58fe9ee61dbf80697f8a9a429831" + and manifest["retained_baseline_head"] == "b556600ffe14be72406b03a47c661f3c7f1aff06", + "Exact source/baseline provenance") + rows = manifest["files"] + require(type(rows) is list and len(rows) == len(PINS) + and {r["file"]: (r["sha256"], r["git_blob"]) for r in rows} == PINS, + "Eight independently pinned source files") + data = {} + for name, (digest, blob) in PINS.items(): + raw = (HERE / name).read_bytes() + require(sha256(raw).hexdigest() == digest, "exact source sha256: " + name) + require(sha1(b"blob " + str(len(raw)).encode() + b"\0" + raw).hexdigest() == blob, + "Exact source Git blob: " + name) + if name.endswith(".json.gz"): + data[Path(name).name] = json.loads(gzip.decompress(raw)) + elif name.endswith(".json"): + data[Path(name).name] = json.loads(raw) + return data + + +def rank(vectors, independent=False): + pivots = {} + require(type(vectors) is list, "Binary vector list") + for vector in vectors: + integer(vector, 1, 512, "Nonzero GF(2)^9 vector") + value = vector + while value: + bit = (value & -value).bit_length() - 1 + if bit not in pivots: + pivots[bit] = value + break + value ^= pivots[bit] + require(value != 0 or not independent, "Independent literal frame basis") + return len(pivots) + + +def q(value): + require(type(value) is str, "Rational scalar string") + result = Fraction(value) + require(result and str(result) == value and result.denominator & (result.denominator - 1) == 0, + "Canonical nonzero dyadic scalar") + return result + + +def encoded(counter): + return {str(r): n for r, n in sorted(counter.items()) if n} + + +def decoded(value): + return Counter({int(r): n for r, n in value.items()}) + + +def mass(counter): + return sum(r * n for r, n in counter.items()) + + +def delta(after, before): + result = Counter(after) + result.subtract(before) + return Counter({r: n for r, n in result.items() if n}) + + +def first_difference(actual, expected): + for r in sorted(actual.keys() | expected.keys()): + if actual.get(r, 0) != expected.get(r, 0): + return {"rank": r, "actual_count": actual.get(r, 0), "expected_count": expected.get(r, 0)} + return None + + +def same_profile(actual, expected, label): + require(first_difference(actual, expected) is None, label + ": " + canonical(first_difference(actual, expected))) + + +def local(word): + require(type(word["public"]) is int and word["public"] == PUBLIC + and type(word["owned_fields"]) is int and word["owned_fields"] == OWNED, + "Fixed arbitrary public/owned inventories") + frames = word["frames"] + require(type(frames) is list, "Frame inventory") + dimensions = [rank(frame, independent=True) for frame in frames] + for key in ("initial", "final"): + require(type(word[key]) is list and len(word[key]) == PUBLIC, "Complete public boundary") + for frame in word[key]: + integer(frame, 0, len(frames), "Boundary frame") + live = word["live"] + require(type(live) is list and len(live) == PORTS, "104 main pairs") + for r in live: + integer(r, 0, PUBLIC - 112, "Main source role") + mains = set(live) | {r + 112 for r in live} + require(len(mains) == 208 and type(word["ports"]) is list and len(word["ports"]) == PORTS, + "Disjoint main role pairs and104 ports") + active = dict(enumerate(word["initial"])) + open_owned, lifetimes, peak = set(), 0, 0 + paid, counts, first = Counter(), Counter(), {} + require(type(word["program"]) is list and len(word["program"]) < 26000, "Bounded literal word") + for index, e in enumerate(word["program"]): + require(type(e) is list and e, "Literal instruction") + op = e[0] + require(op in ("MOVE", "INIT", "CLEAR", "ADD", "COPY", "SCALE"), "Known local opcode") + require(len(e) == {"MOVE": 5, "INIT": 3, "CLEAR": 3, "ADD": 5, "COPY": 5, "SCALE": 4}[op], "Local opcode arity") + r = integer(e[1], 0, PUBLIC + OWNED, "Literal role") + counts[op] += 1 + if op == "MOVE": + a, b = integer(e[2], 0, len(frames), "MOVE source"), integer(e[3], 0, len(frames), "MOVE target") + require(r in active and active[r] == a and type(e[4]) is bool and e[4] == (r in open_owned), + "Chronological MOVE source and owned flag") + da, db = dimensions[a], dimensions[b] + require(rank(frames[a] + frames[b]) == max(da, db), "Nested transport subspaces") + require(db < da if e[4] else da < db, "Strict owned descent or public ascent") + paid[abs(db - da)] += 1 + if a == 3: + require(r not in first, "One first departure from ZERO") + first[r] = {"index": index, "destination": b} + active[r] = b + elif op == "INIT": + frame = integer(e[2], 0, len(frames), "INIT frame") + require(r >= PUBLIC and r not in active, "INIT inactive owned label") + active[r] = frame + open_owned.add(r) + lifetimes += 1 + peak = max(peak, len(open_owned)) + elif op == "CLEAR": + frame = integer(e[2], 0, len(frames), "CLEAR frame") + require(r in open_owned and active[r] == frame, "CLEAR active lifetime and frame") + open_owned.remove(r) + del active[r] + else: + frame = integer(e[-1], 0, len(frames), "Scalar common frame") + require(r in active and active[r] == frame, "Active scalar destination") + q(e[-2]) + if op != "SCALE": + s = integer(e[2], 0, PUBLIC + OWNED, "Scalar source role") + require(s != r and s in active and active[s] == frame, "Active distinct scalar source in common frame") + if op == "COPY": + require(r in open_owned, "COPY owned destination; zero-value premise remains separate") + require(not open_owned and active == dict(enumerate(word["final"])), "Complete public exits and owned retirement") + helpers = Counter() + for r in range(PUBLIC): + if r in mains: + continue + a, b = word["initial"][r], word["final"][r] + da, db = dimensions[a], dimensions[b] + require(da < db and rank(frames[a] + frames[b]) == db, "Strictly productive nested helper boundary") + helpers[db - da] += 1 + require(sum(helpers.values()) == 562, "Exactly562 independent public helper targets") + increments = {dimensions[word["final"][r]] - dimensions[word["initial"][r]] for r in mains} + require(increments == {8}, "Declared rank-eight main stage interface") + return {"paid": encoded(paid), "targets": encoded(helpers), "events": len(word["program"]), + "opcode_counts": dict(sorted(counts.items())), "owned_lifetimes": lifetimes, "peak_owned": peak, + "paid_jobs": sum(paid.values()), "helper_fields": 562, + "paid_rank_mass": mass(paid), "productive_rank_mass": mass(helpers)}, dimensions, first + + +def footprint(old, new, lifts, dimensions, first): + require(set(old) == set(new), "Same word metadata keys") + for key in old: + if key not in ("program", "initial"): + require(canonical(old[key]) == canonical(new[key]), "Unchanged interface/header field: " + key) + expected_initial, removed, added, clusters = {}, Counter(), Counter(), [] + require(type(lifts["rounds"]) is list and len(lifts["rounds"]) == 2, "Two declared lift rounds") + all_anchors, all_carriers = set(), set() + for round_number, spec in enumerate(lifts["rounds"]): + for cluster in spec["clusters"]: + F = integer(cluster["F"], 0, len(dimensions), "Entrance frame") + anchors = sorted(int(r) for r in cluster["anchors"]) + require(len(anchors) == 2 and len(cluster["carriers"]) == 1, "Two lifted helpers share one carrier") + carrier = integer(cluster["carriers"][0], 0, PUBLIC, "Public carrier") + require(carrier not in all_carriers and not (set(anchors) & all_anchors), "Distinct three clusters") + all_carriers.add(carrier) + all_anchors.update(anchors) + require(dimensions[F] == 1, "Rank-one entrance") + for anchor in anchors: + integer(anchor, 0, PUBLIC, "Lifted public helper") + require(old["initial"][anchor] == 3 and old["final"][anchor] == 127, "Old full helper boundary") + expected_initial[str(anchor)] = [3, F] + G = first[anchor]["destination"] + removed[("MOVE", anchor, 3, G, False)] += 1 + added[("MOVE", anchor, F, G, False)] += 1 + Gc = first[carrier]["destination"] + removed[("MOVE", carrier, 3, Gc, False)] += 1 + added[("MOVE", carrier, 3, F, False)] += 1 + added[("MOVE", carrier, F, Gc, False)] += 1 + clusters.append({"round": round_number + 1, "carrier": carrier, "entrance": F, + "anchors": anchors, "old_carrier_destination": Gc, + "old_carrier_rank": dimensions[Gc], + "anchor_destination_ranks": [dimensions[first[r]["destination"]] for r in anchors]}) + actual_initial = {str(r): [old["initial"][r], new["initial"][r]] for r in range(PUBLIC) + if old["initial"][r] != new["initial"][r]} + require(actual_initial == expected_initial and all_anchors == {520, 655, 544, 671, 472, 624} + and all_carriers == {171, 208, 130}, "Exactly six changed initial contracts and three carriers") + old_moves = Counter(tuple(e) for e in old["program"] if e[0] == "MOVE") + new_moves = Counter(tuple(e) for e in new["program"] if e[0] == "MOVE") + require(old_moves - new_moves == removed and new_moves - old_moves == added, + "Complete MOVE multiset delta equals all six lifts plus three two-leg detours") + return {"changed_initial_frames": actual_initial, "clusters": clusters, + "removed_MOVE_records": [[list(e), n] for e, n in sorted(removed.items())], + "added_MOVE_records": [[list(e), n] for e, n in sorted(added.items())]} + + +def complete(local_profile, caller): + require(type(caller["roles"]) is int and caller["roles"] == 34 + and type(caller["stages"]) is int and caller["stages"] == 19, "Fixed34-field19-stage caller") + paid, targets, opcounts = Counter(), Counter(), Counter() + stages, idle_sizes = [], [] + queries = [] + for index, e in enumerate(caller["events"]): + op = e[0] + require(op in ("ADD", "SCALE", "SWAP", "LOCAL", "QUERY", "Q_POWER", "IDLE"), "Known caller opcode") + opcounts[op] += 1 + if op == "LOCAL": + integer(e[1], 1, 20, "LOCAL stage") + stages.append(e[1]) + paid.update(decoded(local_profile["paid"])) + targets.update(decoded(local_profile["targets"])) + elif op == "QUERY": + require(type(e[3]) is int and e[3] in (-1, 1), "Unit thin-query exponent") + paid[1] += PORTS + queries.append(index) + elif op == "IDLE": + require(type(e[3]) is list and e[3] and len(e[3]) == len(set(e[3])), "Distinct idle stages") + for stage in e[3]: + integer(stage, 1, 20, "Idle stage") + paid[8 * len(e[3])] += 2 * PORTS + idle_sizes.append({"index": index, "size": len(e[3])}) + require(sorted(stages) == list(range(1, 20)) and len(queries) == len(idle_sizes) == 16, + "Nineteen complete LOCAL bills and sixteen queries/idles") + require(type(caller["diagonal"]) is list and len(caller["diagonal"]) == 34, "Declared34 main targets") + for term in caller["diagonal"]: + require(type(term) is list and len(term) == 21 and all(type(x) is int for x in term) + and term[0] in (-1, 1) and term[1] == 0 and all(x in (0, 1) for x in term[2:]), + "Declared signed central power and19 distinct stage bits") + targets[1 + 8 * sum(term[2:])] += PORTS + node_sizes = [] + def leaves(tree): + if type(tree) is int: + require(tree == 1, "Native leaf") + return 1 + require(type(tree) is list and len(tree) == 2, "Binary caller subtree") + size = leaves(tree[0]) + leaves(tree[1]) + node_sizes.append(size) + return size + require(type(caller["tree"]) is list and len(caller["tree"]) == 3, "Ternary root") + total_leaves = sum(leaves(tree) for tree in caller["tree"]) + require(total_leaves == 19 and len(node_sizes) == 16, "Independent topology census") + formula_paid = Counter({r: total_leaves * n for r, n in decoded(local_profile["paid"]).items()}) + formula_targets = Counter({r: total_leaves * n for r, n in decoded(local_profile["targets"]).items()}) + formula_paid[1] += PORTS * len(node_sizes) + formula_targets[1 + 8 * total_leaves] += 2 * PORTS + for size in node_sizes: + formula_paid[8 * size] += 2 * PORTS + formula_targets[1 + 8 * size] += 2 * PORTS + same_profile(paid, formula_paid, "Literal versus topology paid invoice") + same_profile(targets, formula_targets, "Declared diagonal versus topology productive invoice") + return {"paid": encoded(paid), "targets": encoded(targets), "paid_jobs": sum(paid.values()), + "productive_fields": sum(targets.values()), "paid_rank_mass": mass(paid), + "productive_rank_mass": mass(targets), "rank_mass_surplus": mass(targets) - mass(paid)}, { + "opcode_counts": dict(sorted(opcounts.items())), "topology_node_sizes": dict(sorted(Counter(node_sizes).items())), + "queries": queries, "idles": idle_sizes} + + +def controls(new_word, new_local, whole, caller_info): + paid, targets = decoded(whole["paid"]), decoded(whole["targets"]) + bad = [] + index, event = next((i, e) for i, e in enumerate(new_word["program"]) + if e[:4] == ["MOVE", 171, 3, 106]) + wrong = Counter(paid) + wrong[1] -= 19 + bad.append(("unpaid_carrier_first_leg_in_nineteen_calls", paid, wrong, {"event_index": index, "event": event, "copies": 19})) + wrong = Counter(targets) + wrong[8] -= 19 + wrong[9] += 19 + require(sum(wrong.values()) == sum(targets.values()), "Target substitution control preserves independent field count") + bad.append(("old_rank9_target_retained_instead_of_new_rank8", targets, wrong, + {"helper": 520, "copies": 19, "productive_fields": sum(wrong.values())})) + wrong = Counter(paid) + wrong[1] -= PORTS + bad.append(("one_thin_query_unpaid", paid, wrong, {"caller_event_index": caller_info["queries"][0], "jobs": PORTS})) + idle = caller_info["idles"][0] + wrong = Counter(paid) + wrong[8 * idle["size"]] -= PORTS + bad.append(("one_paired_idle_member_unpaid", paid, wrong, {"caller_event_index": idle["index"], "jobs": PORTS})) + wrong = Counter(paid) + wrong.subtract(decoded(new_local["paid"])) + bad.append(("one_full_LOCAL_bill_missing", paid, wrong, {"omitted_stage": 1})) + result = [] + for label, expected, corrupted, detail in bad: + witness = first_difference(corrupted, expected) + require(witness is not None, "Counterfactual invoice has a concrete different coefficient") + try: + same_profile(corrupted, expected, label) + except ValueError: + result.append({"control": label, "kind": "counterfactual_invoice_counts", + "profile_mismatch": witness, "detail": detail}) + else: + raise ValueError("Counterfactual invoice was accepted") + return result + + +def run(): + data = authenticate() + old_word, new_word = data["OLD-WORD.json.gz"], data["NEW-WORD.json.gz"] + old, dimensions, first = local(old_word) + new, new_dimensions, _ = local(new_word) + require(dimensions == new_dimensions, "Identical frame dimensions") + binding = footprint(old_word, new_word, data["LIFTS.json"], dimensions, first) + old_whole, caller = complete(old, data["CONTROLLER.json"]) + new_whole, new_caller = complete(new, data["CONTROLLER.json"]) + require(canonical(caller) == canonical(new_caller), "Unchanged caller census") + dp = delta(decoded(new["paid"]), decoded(old["paid"])) + dt = delta(decoded(new["targets"]), decoded(old["targets"])) + same_profile(dp, Counter({1: 6, 3: -3, 4: 3, 5: -3}), "Exact local paid change") + same_profile(dt, Counter({8: 6, 9: -6}), "Exact six-target initial-boundary debit") + same_profile(delta(decoded(new_whole["paid"]), decoded(old_whole["paid"])), Counter({r: 19 * n for r, n in dp.items()}), "All nineteen paid copies") + same_profile(delta(decoded(new_whole["targets"]), decoded(old_whole["targets"])), Counter({r: 19 * n for r, n in dt.items()}), "All nineteen productive copies") + signed = Counter(dt) + signed.subtract(dp) + return {"schema_version": 1, "status": "PASS_CONDITIONAL_PROFILES", + "old_local": old, "new_local": new, "source_binding": binding, "caller": caller, + "old_complete": old_whole, "new_complete": new_whole, + "local_paid_delta": encoded(dp), "local_target_delta": encoded(dt), + "local_signed_gain_coefficients": encoded(signed), + "rank_mass_changes": {"paid": mass(dp), "productive": mass(dt), "signed": mass(signed)}, + "counterfactual_invoice_controls": controls(new_word, new, new_whole, caller), + "limits": ["Paid frame-rank and productive tariffs are retained native/interface premises, not phase or realization proofs.", + "Scalar common frames and temporal ownership are checked; scalar values, restoration, COPY zeros and physical erasure are not admitted.", + "Main target billing assumes the frozen rank-eight LOCAL interface and declared caller diagonal.", + "MOVE multiset cancellation is billing evidence, not a claim that retimed events have identical chronology.", + "Controls corrupt invoice counts only; no valid cheaper modified source program is claimed.", + "This round does not compute a power threshold, raw kappa crossing, uniform compiler or supplier admission."]} + + +if __name__ == "__main__": + require(sys.argv[1:] in ([], ["--emit"]), "Usage: oracle_profiles.py [--emit]") + result = run() + if sys.argv[1:] == ["--emit"]: + print(json.dumps(result, sort_keys=True, indent=2, allow_nan=False)) + else: + retained = json.loads((HERE / "ORACLE-PROFILES.json").read_bytes()) + require(canonical(result) == canonical(retained), "Exact typed retained ORACLE-PROFILES.json receipt") + print("PASS independent conditional profiles and retained receipt") diff --git a/research/relative-tariff-integer-exp/source/sources/CONTROLLER.json b/research/relative-tariff-integer-exp/source/sources/CONTROLLER.json new file mode 100644 index 0000000000..1f2e375b24 --- /dev/null +++ b/research/relative-tariff-integer-exp/source/sources/CONTROLLER.json @@ -0,0 +1,3039 @@ +{ + "ambient_rank": 161, + "diagonal": [ + [ + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + [ + -1, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + [ + -1, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 1, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + -1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 1, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + [ + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + [ + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ], + [ + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ], + [ + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0 + ], + [ + -1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1 + ], + [ + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1 + ] + ], + "events": [ + [ + "SWAP", + 0, + 3 + ], + [ + "SWAP", + 1, + 2 + ], + [ + "SWAP", + 2, + 3 + ], + [ + "ADD", + 0, + 2, + 1 + ], + [ + "ADD", + 3, + 1, + -1 + ], + [ + "QUERY", + 2, + 3, + -1 + ], + [ + "ADD", + 3, + 1, + 1 + ], + [ + "ADD", + 0, + 2, + -1 + ], + [ + "IDLE", + 2, + 3, + [ + 1, + 2, + 3, + 4 + ] + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 1, + 5 + ], + [ + "SWAP", + 0, + 4 + ], + [ + "SWAP", + 4, + 5 + ], + [ + "ADD", + 1, + 4, + 1 + ], + [ + "ADD", + 5, + 0, + -1 + ], + [ + "QUERY", + 4, + 5, + 1 + ], + [ + "ADD", + 5, + 0, + 1 + ], + [ + "ADD", + 1, + 4, + -1 + ], + [ + "IDLE", + 4, + 5, + [ + 1, + 2 + ] + ], + [ + "SCALE", + 0, + -1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "LOCAL", + 1, + 0, + 1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "SCALE", + 0, + -1 + ], + [ + "Q_POWER", + 1, + -2 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "LOCAL", + 2, + 1, + 0 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "Q_POWER", + 1, + 2 + ], + [ + "ADD", + 1, + 4, + 1 + ], + [ + "SCALE", + 4, + -1 + ], + [ + "ADD", + 4, + 1, + 1 + ], + [ + "SWAP", + 0, + 5 + ], + [ + "SCALE", + 5, + -1 + ], + [ + "ADD", + 5, + 0, + 1 + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 0, + 7 + ], + [ + "SWAP", + 1, + 6 + ], + [ + "SWAP", + 6, + 7 + ], + [ + "ADD", + 0, + 6, + 1 + ], + [ + "ADD", + 7, + 1, + -1 + ], + [ + "QUERY", + 6, + 7, + -1 + ], + [ + "ADD", + 7, + 1, + 1 + ], + [ + "ADD", + 0, + 6, + -1 + ], + [ + "IDLE", + 6, + 7, + [ + 3, + 4 + ] + ], + [ + "SCALE", + 1, + -1 + ], + [ + "Q_POWER", + 1, + -2 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "LOCAL", + 3, + 1, + 0 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "Q_POWER", + 1, + 2 + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "LOCAL", + 4, + 0, + 1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "ADD", + 0, + 6, + 1 + ], + [ + "SCALE", + 6, + -1 + ], + [ + "ADD", + 6, + 0, + 1 + ], + [ + "SWAP", + 1, + 7 + ], + [ + "SCALE", + 7, + -1 + ], + [ + "ADD", + 7, + 1, + 1 + ], + [ + "ADD", + 0, + 2, + 1 + ], + [ + "SCALE", + 2, + -1 + ], + [ + "ADD", + 2, + 0, + 1 + ], + [ + "SWAP", + 1, + 3 + ], + [ + "SCALE", + 3, + -1 + ], + [ + "ADD", + 3, + 1, + 1 + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 1, + 9 + ], + [ + "SWAP", + 0, + 8 + ], + [ + "SWAP", + 8, + 9 + ], + [ + "ADD", + 1, + 8, + 1 + ], + [ + "ADD", + 9, + 0, + -1 + ], + [ + "QUERY", + 8, + 9, + 1 + ], + [ + "ADD", + 9, + 0, + 1 + ], + [ + "ADD", + 1, + 8, + -1 + ], + [ + "IDLE", + 8, + 9, + [ + 5, + 6, + 7, + 8, + 9, + 10, + 11 + ] + ], + [ + "SCALE", + 0, + -1 + ], + [ + "SWAP", + 0, + 11 + ], + [ + "SWAP", + 1, + 10 + ], + [ + "SWAP", + 10, + 11 + ], + [ + "ADD", + 0, + 10, + 1 + ], + [ + "ADD", + 11, + 1, + -1 + ], + [ + "QUERY", + 10, + 11, + -1 + ], + [ + "ADD", + 11, + 1, + 1 + ], + [ + "ADD", + 0, + 10, + -1 + ], + [ + "IDLE", + 10, + 11, + [ + 5, + 6, + 7 + ] + ], + [ + "SCALE", + 1, + -1 + ], + [ + "Q_POWER", + 1, + -2 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "LOCAL", + 5, + 1, + 0 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "Q_POWER", + 1, + 2 + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 0, + 13 + ], + [ + "SWAP", + 1, + 12 + ], + [ + "SWAP", + 12, + 13 + ], + [ + "ADD", + 0, + 12, + 1 + ], + [ + "ADD", + 13, + 1, + -1 + ], + [ + "QUERY", + 12, + 13, + -1 + ], + [ + "ADD", + 13, + 1, + 1 + ], + [ + "ADD", + 0, + 12, + -1 + ], + [ + "IDLE", + 12, + 13, + [ + 6, + 7 + ] + ], + [ + "SCALE", + 1, + -1 + ], + [ + "Q_POWER", + 1, + -2 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "LOCAL", + 6, + 1, + 0 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "Q_POWER", + 1, + 2 + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "LOCAL", + 7, + 0, + 1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "ADD", + 0, + 12, + 1 + ], + [ + "SCALE", + 12, + -1 + ], + [ + "ADD", + 12, + 0, + 1 + ], + [ + "SWAP", + 1, + 13 + ], + [ + "SCALE", + 13, + -1 + ], + [ + "ADD", + 13, + 1, + 1 + ], + [ + "ADD", + 0, + 10, + 1 + ], + [ + "SCALE", + 10, + -1 + ], + [ + "ADD", + 10, + 0, + 1 + ], + [ + "SWAP", + 1, + 11 + ], + [ + "SCALE", + 11, + -1 + ], + [ + "ADD", + 11, + 1, + 1 + ], + [ + "SCALE", + 0, + -1 + ], + [ + "SWAP", + 1, + 15 + ], + [ + "SWAP", + 0, + 14 + ], + [ + "SWAP", + 14, + 15 + ], + [ + "ADD", + 1, + 14, + 1 + ], + [ + "ADD", + 15, + 0, + -1 + ], + [ + "QUERY", + 14, + 15, + 1 + ], + [ + "ADD", + 15, + 0, + 1 + ], + [ + "ADD", + 1, + 14, + -1 + ], + [ + "IDLE", + 14, + 15, + [ + 8, + 9, + 10, + 11 + ] + ], + [ + "SCALE", + 0, + -1 + ], + [ + "SWAP", + 0, + 17 + ], + [ + "SWAP", + 1, + 16 + ], + [ + "SWAP", + 16, + 17 + ], + [ + "ADD", + 0, + 16, + 1 + ], + [ + "ADD", + 17, + 1, + -1 + ], + [ + "QUERY", + 16, + 17, + -1 + ], + [ + "ADD", + 17, + 1, + 1 + ], + [ + "ADD", + 0, + 16, + -1 + ], + [ + "IDLE", + 16, + 17, + [ + 8, + 9 + ] + ], + [ + "SCALE", + 1, + -1 + ], + [ + "Q_POWER", + 1, + -2 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "LOCAL", + 8, + 1, + 0 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "Q_POWER", + 1, + 2 + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "LOCAL", + 9, + 0, + 1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "ADD", + 0, + 16, + 1 + ], + [ + "SCALE", + 16, + -1 + ], + [ + "ADD", + 16, + 0, + 1 + ], + [ + "SWAP", + 1, + 17 + ], + [ + "SCALE", + 17, + -1 + ], + [ + "ADD", + 17, + 1, + 1 + ], + [ + "SCALE", + 0, + -1 + ], + [ + "SWAP", + 1, + 19 + ], + [ + "SWAP", + 0, + 18 + ], + [ + "SWAP", + 18, + 19 + ], + [ + "ADD", + 1, + 18, + 1 + ], + [ + "ADD", + 19, + 0, + -1 + ], + [ + "QUERY", + 18, + 19, + 1 + ], + [ + "ADD", + 19, + 0, + 1 + ], + [ + "ADD", + 1, + 18, + -1 + ], + [ + "IDLE", + 18, + 19, + [ + 10, + 11 + ] + ], + [ + "SCALE", + 0, + -1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "LOCAL", + 10, + 0, + 1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "SCALE", + 0, + -1 + ], + [ + "Q_POWER", + 1, + -2 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "LOCAL", + 11, + 1, + 0 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "Q_POWER", + 1, + 2 + ], + [ + "ADD", + 1, + 18, + 1 + ], + [ + "SCALE", + 18, + -1 + ], + [ + "ADD", + 18, + 1, + 1 + ], + [ + "SWAP", + 0, + 19 + ], + [ + "SCALE", + 19, + -1 + ], + [ + "ADD", + 19, + 0, + 1 + ], + [ + "ADD", + 1, + 14, + 1 + ], + [ + "SCALE", + 14, + -1 + ], + [ + "ADD", + 14, + 1, + 1 + ], + [ + "SWAP", + 0, + 15 + ], + [ + "SCALE", + 15, + -1 + ], + [ + "ADD", + 15, + 0, + 1 + ], + [ + "ADD", + 1, + 8, + 1 + ], + [ + "SCALE", + 8, + -1 + ], + [ + "ADD", + 8, + 1, + 1 + ], + [ + "SWAP", + 0, + 9 + ], + [ + "SCALE", + 9, + -1 + ], + [ + "ADD", + 9, + 0, + 1 + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 0, + 21 + ], + [ + "SWAP", + 1, + 20 + ], + [ + "SWAP", + 20, + 21 + ], + [ + "ADD", + 0, + 20, + 1 + ], + [ + "ADD", + 21, + 1, + -1 + ], + [ + "QUERY", + 20, + 21, + -1 + ], + [ + "ADD", + 21, + 1, + 1 + ], + [ + "ADD", + 0, + 20, + -1 + ], + [ + "IDLE", + 20, + 21, + [ + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19 + ] + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 1, + 23 + ], + [ + "SWAP", + 0, + 22 + ], + [ + "SWAP", + 22, + 23 + ], + [ + "ADD", + 1, + 22, + 1 + ], + [ + "ADD", + 23, + 0, + -1 + ], + [ + "QUERY", + 22, + 23, + 1 + ], + [ + "ADD", + 23, + 0, + 1 + ], + [ + "ADD", + 1, + 22, + -1 + ], + [ + "IDLE", + 22, + 23, + [ + 12, + 13, + 14, + 15 + ] + ], + [ + "SCALE", + 0, + -1 + ], + [ + "SWAP", + 0, + 25 + ], + [ + "SWAP", + 1, + 24 + ], + [ + "SWAP", + 24, + 25 + ], + [ + "ADD", + 0, + 24, + 1 + ], + [ + "ADD", + 25, + 1, + -1 + ], + [ + "QUERY", + 24, + 25, + -1 + ], + [ + "ADD", + 25, + 1, + 1 + ], + [ + "ADD", + 0, + 24, + -1 + ], + [ + "IDLE", + 24, + 25, + [ + 12, + 13 + ] + ], + [ + "SCALE", + 1, + -1 + ], + [ + "Q_POWER", + 1, + -2 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "LOCAL", + 12, + 1, + 0 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "Q_POWER", + 1, + 2 + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "LOCAL", + 13, + 0, + 1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "ADD", + 0, + 24, + 1 + ], + [ + "SCALE", + 24, + -1 + ], + [ + "ADD", + 24, + 0, + 1 + ], + [ + "SWAP", + 1, + 25 + ], + [ + "SCALE", + 25, + -1 + ], + [ + "ADD", + 25, + 1, + 1 + ], + [ + "SCALE", + 0, + -1 + ], + [ + "SWAP", + 1, + 27 + ], + [ + "SWAP", + 0, + 26 + ], + [ + "SWAP", + 26, + 27 + ], + [ + "ADD", + 1, + 26, + 1 + ], + [ + "ADD", + 27, + 0, + -1 + ], + [ + "QUERY", + 26, + 27, + 1 + ], + [ + "ADD", + 27, + 0, + 1 + ], + [ + "ADD", + 1, + 26, + -1 + ], + [ + "IDLE", + 26, + 27, + [ + 14, + 15 + ] + ], + [ + "SCALE", + 0, + -1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "LOCAL", + 14, + 0, + 1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "SCALE", + 0, + -1 + ], + [ + "Q_POWER", + 1, + -2 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "LOCAL", + 15, + 1, + 0 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "Q_POWER", + 1, + 2 + ], + [ + "ADD", + 1, + 26, + 1 + ], + [ + "SCALE", + 26, + -1 + ], + [ + "ADD", + 26, + 1, + 1 + ], + [ + "SWAP", + 0, + 27 + ], + [ + "SCALE", + 27, + -1 + ], + [ + "ADD", + 27, + 0, + 1 + ], + [ + "ADD", + 1, + 22, + 1 + ], + [ + "SCALE", + 22, + -1 + ], + [ + "ADD", + 22, + 1, + 1 + ], + [ + "SWAP", + 0, + 23 + ], + [ + "SCALE", + 23, + -1 + ], + [ + "ADD", + 23, + 0, + 1 + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 0, + 29 + ], + [ + "SWAP", + 1, + 28 + ], + [ + "SWAP", + 28, + 29 + ], + [ + "ADD", + 0, + 28, + 1 + ], + [ + "ADD", + 29, + 1, + -1 + ], + [ + "QUERY", + 28, + 29, + -1 + ], + [ + "ADD", + 29, + 1, + 1 + ], + [ + "ADD", + 0, + 28, + -1 + ], + [ + "IDLE", + 28, + 29, + [ + 16, + 17, + 18, + 19 + ] + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 1, + 31 + ], + [ + "SWAP", + 0, + 30 + ], + [ + "SWAP", + 30, + 31 + ], + [ + "ADD", + 1, + 30, + 1 + ], + [ + "ADD", + 31, + 0, + -1 + ], + [ + "QUERY", + 30, + 31, + 1 + ], + [ + "ADD", + 31, + 0, + 1 + ], + [ + "ADD", + 1, + 30, + -1 + ], + [ + "IDLE", + 30, + 31, + [ + 16, + 17 + ] + ], + [ + "SCALE", + 0, + -1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "LOCAL", + 16, + 0, + 1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "SCALE", + 0, + -1 + ], + [ + "Q_POWER", + 1, + -2 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "LOCAL", + 17, + 1, + 0 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "Q_POWER", + 1, + 2 + ], + [ + "ADD", + 1, + 30, + 1 + ], + [ + "SCALE", + 30, + -1 + ], + [ + "ADD", + 30, + 1, + 1 + ], + [ + "SWAP", + 0, + 31 + ], + [ + "SCALE", + 31, + -1 + ], + [ + "ADD", + 31, + 0, + 1 + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 0, + 33 + ], + [ + "SWAP", + 1, + 32 + ], + [ + "SWAP", + 32, + 33 + ], + [ + "ADD", + 0, + 32, + 1 + ], + [ + "ADD", + 33, + 1, + -1 + ], + [ + "QUERY", + 32, + 33, + -1 + ], + [ + "ADD", + 33, + 1, + 1 + ], + [ + "ADD", + 0, + 32, + -1 + ], + [ + "IDLE", + 32, + 33, + [ + 18, + 19 + ] + ], + [ + "SCALE", + 1, + -1 + ], + [ + "Q_POWER", + 1, + -2 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "LOCAL", + 18, + 1, + 0 + ], + [ + "SWAP", + 1, + 0 + ], + [ + "Q_POWER", + 1, + 2 + ], + [ + "SCALE", + 1, + -1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "LOCAL", + 19, + 0, + 1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "ADD", + 0, + 32, + 1 + ], + [ + "SCALE", + 32, + -1 + ], + [ + "ADD", + 32, + 0, + 1 + ], + [ + "SWAP", + 1, + 33 + ], + [ + "SCALE", + 33, + -1 + ], + [ + "ADD", + 33, + 1, + 1 + ], + [ + "ADD", + 0, + 28, + 1 + ], + [ + "SCALE", + 28, + -1 + ], + [ + "ADD", + 28, + 0, + 1 + ], + [ + "SWAP", + 1, + 29 + ], + [ + "SCALE", + 29, + -1 + ], + [ + "ADD", + 29, + 1, + 1 + ], + [ + "ADD", + 0, + 20, + 1 + ], + [ + "SCALE", + 20, + -1 + ], + [ + "ADD", + 20, + 0, + 1 + ], + [ + "SWAP", + 1, + 21 + ], + [ + "SCALE", + 21, + -1 + ], + [ + "ADD", + 21, + 1, + 1 + ], + [ + "SWAP", + 0, + 1 + ], + [ + "SCALE", + 0, + -1 + ] + ], + "nodes": [ + { + "exponent": 1, + "roles": [ + 2, + 3 + ], + "stages": [ + 1, + 2, + 3, + 4 + ] + }, + { + "exponent": -1, + "roles": [ + 4, + 5 + ], + "stages": [ + 1, + 2 + ] + }, + { + "exponent": 1, + "roles": [ + 6, + 7 + ], + "stages": [ + 3, + 4 + ] + }, + { + "exponent": -1, + "roles": [ + 8, + 9 + ], + "stages": [ + 5, + 6, + 7, + 8, + 9, + 10, + 11 + ] + }, + { + "exponent": 1, + "roles": [ + 10, + 11 + ], + "stages": [ + 5, + 6, + 7 + ] + }, + { + "exponent": 1, + "roles": [ + 12, + 13 + ], + "stages": [ + 6, + 7 + ] + }, + { + "exponent": -1, + "roles": [ + 14, + 15 + ], + "stages": [ + 8, + 9, + 10, + 11 + ] + }, + { + "exponent": 1, + "roles": [ + 16, + 17 + ], + "stages": [ + 8, + 9 + ] + }, + { + "exponent": -1, + "roles": [ + 18, + 19 + ], + "stages": [ + 10, + 11 + ] + }, + { + "exponent": 1, + "roles": [ + 20, + 21 + ], + "stages": [ + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19 + ] + }, + { + "exponent": -1, + "roles": [ + 22, + 23 + ], + "stages": [ + 12, + 13, + 14, + 15 + ] + }, + { + "exponent": 1, + "roles": [ + 24, + 25 + ], + "stages": [ + 12, + 13 + ] + }, + { + "exponent": -1, + "roles": [ + 26, + 27 + ], + "stages": [ + 14, + 15 + ] + }, + { + "exponent": 1, + "roles": [ + 28, + 29 + ], + "stages": [ + 16, + 17, + 18, + 19 + ] + }, + { + "exponent": -1, + "roles": [ + 30, + 31 + ], + "stages": [ + 16, + 17 + ] + }, + { + "exponent": 1, + "roles": [ + 32, + 33 + ], + "stages": [ + 18, + 19 + ] + } + ], + "roles": 34, + "schema": "binary-query-tree/1", + "stages": 19, + "tree": [ + [ + [ + 1, + 1 + ], + [ + 1, + 1 + ] + ], + [ + [ + 1, + [ + 1, + 1 + ] + ], + [ + [ + 1, + 1 + ], + [ + 1, + 1 + ] + ] + ], + [ + [ + [ + 1, + 1 + ], + [ + 1, + 1 + ] + ], + [ + [ + 1, + 1 + ], + [ + 1, + 1 + ] + ] + ] + ] +} diff --git a/research/relative-tariff-integer-exp/source/sources/LIFTS.json b/research/relative-tariff-integer-exp/source/sources/LIFTS.json new file mode 100644 index 0000000000..2ee8cb78fd --- /dev/null +++ b/research/relative-tariff-integer-exp/source/sources/LIFTS.json @@ -0,0 +1,83 @@ +{ + "schema_version": 1, + "rounds": [ + { + "clusters": [ + { + "F": 106, + "anchors": { + "520": { + "h": { + "520": "1" + } + }, + "655": { + "h": { + "655": "1", + "659": "-1" + } + } + }, + "carriers": [ + 171 + ] + }, + { + "F": 105, + "anchors": { + "544": { + "h": { + "544": "1" + } + }, + "671": { + "h": { + "671": "1", + "675": "-1" + } + } + }, + "carriers": [ + 208 + ] + } + ] + }, + { + "clusters": [ + { + "F": 105, + "anchors": { + "472": { + "h": { + "472": "1" + } + }, + "624": { + "h": { + "205": "1", + "546": "-2", + "547": "2", + "548": "2", + "549": "2", + "558": "-4", + "568": "4", + "569": "2", + "570": "4", + "575": "2", + "576": "2", + "624": "1", + "625": "-1", + "627": "-1", + "732": "1/2" + } + } + }, + "carriers": [ + 130 + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/research/relative-tariff-integer-exp/source/sources/NEW-WORD.json.gz b/research/relative-tariff-integer-exp/source/sources/NEW-WORD.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..b1cfd03abe9128cf5a3908fbd82652e5e8a2e292 GIT binary patch literal 85485 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 G4hH~184EE0 literal 0 HcmV?d00001 diff --git a/research/relative-tariff-integer-exp/source/sources/NOTICE b/research/relative-tariff-integer-exp/source/sources/NOTICE new file mode 100644 index 0000000000..638a187d14 --- /dev/null +++ b/research/relative-tariff-integer-exp/source/sources/NOTICE @@ -0,0 +1,309 @@ +New contribution: DreamingOfClouds with Claude Opus 5.5 (Anthropic), via Claude Code. +Apache-2.0. + +The PR6372 word, by Ali Romman with substantial OpenAI Codex assistance, is the +source. Exact head: b556600ffe14be72406b03a47c661f3c7f1aff06. The native +input-lift move class is from PR6349; PR6349 builds on DreamingOfClouds PR6314. +PR6353, PR6348 and their source chains supply the joint basis method, the fixed +binary query-tree caller and the price engine. The word is retained unchanged in +inputs. The complete predecessor notice follows. + +New contribution: Ali Romman, with substantial OpenAI Codex assistance. +No subagents. Apache-2.0. + +PR6353 supplies the word, joint basis construction and native transpose. +Exact head: db2a20bc50bc7a8a4db931af85ce7f012ae7c3c3. +The source files in inputs are unchanged. The complete predecessor notice follows. + +Joint native output contraction +Copyright 2026 Ali Romman. Apache-2.0. + +New construction, code, calculations and prose: Ali Romman with substantial +OpenAI Codex assistance. No subagents. All new checks are author checks. + +PR6349 supplies the exact native input-lift source. PR6348 supplies the fixed +binary query-tree caller and price engine. PR6350, by Ali Romman with OpenAI +Codex assistance, supplies the released composition control and its prior +conditional claim. Its source and caller are recounted here from main; no +pending PR6350 code is imported. Cinna Davis supplies the productive caller, +thin-query interface and exact Laurent factorization. + +The new result is the explicit nine-helper joint output contraction, its +literal forward word and complete conditional price. The input/departure basis +identity is elementary linear algebra. No new general linear algebra theorem, +native duality theorem or caller construction is claimed. + +The exact PR6349 and PR6348 notices follow. Their nested source archive retains +all earlier native, helper, recursion, compiler, BIT and analytic attribution. + +Native helper input lifting +Copyright 2026 Ali Romman. Apache-2.0. + +New construction, code, calculations and prose: Ali Romman with substantial +OpenAI Codex assistance. No subagents. All new checks are author checks. + +The direct source is PR6314 at 36533d4d1b4e2dd8672427461b12de3001b85810, +by DreamingOfClouds with Claude Opus 5.5 (Anthropic), via Claude Code. +It compresses the scalar word of PR6167 without a kappa change. +The four native input lifts and their complete conditional price are new here. +The basis identity is elementary linear algebra; no new general theorem +for that identity is claimed. + +The PR6167 source notice follows unchanged. Its nested source archive also +retains the earlier notices. + +Retained-operand descent: Ali Romman, with substantial OpenAI Codex assistance. +Apache-2.0. + +The exact source word and price are from DreamingOfClouds, PR6144 and PR6143, +with Claude Opus 5.5 (Anthropic), via Claude Code. They extend PR6030 and PR5907. +The source reader is adapted from that work. The gzip portability controls +retain Douglas Colkitt and Maxime Fleury credit. + +The pinned PR5827 checker and all earlier source notices are retained below. + +Unread-register path resynthesis +Copyright 2026 Ali Romman. Apache-2.0. + +New construction, code, calculations and prose: Ali Romman with substantial +OpenAI Codex assistance. No subagents. All new checks are author-side. + +Mason Hale supplied PR5811, the complete two-block composition and the exact +role92 remapping and fourth accumulation. The earlier elementary accumulation, +retained-copy and second-block work is by Ali Romman. Joel Pulikkan supplied +R22. Dugongue supplied the concurrent baseline composition proof. Their source +notice and proof are retained byte for byte under inputs/pr5811-*. + +The source closure retains flyingviper, Cinna Davis, David Arias, Gareth +Davidson, Jacob Alan Sussman, zxv, Cao Yifan, Pierre-Loic Doulcet, thu-nmrc, +Scratch-net and all native/helper/controller/compiler/geometry/analytic +predecessors. The exact PR5786 source archive and its nested notices remain. +This package does not claim any predecessor construction as new. + +Exact PR5811 vendor/accumulated/NOTICE follows. Source head: +33d7760d0a6fea6394aefd014eea68f0af02a92e + +Accumulated native updates +New work: Ali Romman with substantial OpenAI Codex assistance. Apache-2.0. +No subagents. The same assistant made the construction and the author checks. + +Concurrent scope: Discussion5125 now tests retained copies in the transposed +supplier. That route uses the same source/destination duality. This package +claims the three fixed forward-supplier groups and their complete result, +not the elementary accumulation identity or the broader transposed search. + +Exact source: PR5786 at 6b936acd68a7e0f9062037900f0fe9bc4b6fdd25. +The complete predecessor notice follows unchanged. + +Asynchronous helper hubs +New work: Ali Romman with substantial OpenAI Codex assistance. Apache-2.0. + +Retained native copies from PR5774 at 7d6ec0cdef31d0c37b7d2563e709979caa0d5eae. +All prior credit follows unchanged. + +Paid intermediate meetings and collective helper splits. +Ali Romman, with substantial OpenAI Codex assistance. Apache-2.0. +No subagents. All checks are author-side calculations. + +The complete PR5718 notice follows unchanged. + +Four paid interior public-basis changes. +Ali Romman, with substantial OpenAI Codex assistance. Apache-2.0. +No subagents. + +The following exact notice is retained from PR5660. + +New helper-subspace construction, proof and replay: +Ali Romman with substantial OpenAI Codex assistance. Apache-2.0. +The same assistant performed the construction and author-side checks. + +Retained contributions: +flyingviper: PR5605 shared relay, PR5612 delayed relay, and the PR5608/PR5613 +relay/split compositions. +Scratch-net: PR5606 prepared-helper identities and target debit. +Pierre-Loic Doulcet (hexapode): PR5565 commuting-contact construction, used as the exact source. +Ali Romman: PR5602 fixed boundary relations, PR5601 three-contact frame +change, PR5580 contact step, +and PR5544/5545 complete P104 caller. +Joel Pulikkan (GamingPuzzled): PR5569 priced helper handoff. +DreamingOfClouds: PR5561 free helper endpoints and PR5568 search tools. +thu-nmrc: PR5551 contact improvements. +Gareth Davidson (bitplane): PR2305 source composition. +David Arias: PR2152 coalesced P104 word. +Cinna Davis: PR2219 private reuse and the controller lineage. +Jacob Alan Sussman: productive mixed-target recursion. +zxv and Cao Yifan: exact intervals, compiler and native/pricing lineage. +GamingPuzzled: PR5472 successor handoff, a predecessor to the split concept. +The retained source notices preserve earlier geometry, BIT and analytic credit. + +The elementary rank-one basis identity is not claimed as a new general +linear-algebra theorem. The contribution is its explicit independent-target +use on this P104 word and the complete conditional kappa improvement. + +New contribution: Ali Romman, with substantial OpenAI Codex assistance. +The four-gate source-version rewrite composes zxv PR5643 and Ali Romman PR5644. +The A2 method retains Chris R/Clear1nsight PR3998 and ToikY PR4019 credit. +The compensated triangle method retains Cinna Davis PR4692 credit. +No subagents were used for this contribution. Apache-2.0. + +Concurrent PR5650 by zxv publishes the PR5643/PR5644 composition. PR5651 by +Ali Romman corroborates it. This package credits that released composition +and contributes the further four-gate placement. + +New work: distributed scalar updates on an unobserved public field interval, the exact witness and complete conditional price. Prepared for Ali Romman with substantial OpenAI Codex assistance. No subagents. Apache-2.0. The source archive retains all predecessor notices. + +Two-boundary main-assisted helper split and early cleanup: flyingviper with substantial +OpenAI Codex assistance, including independent AI review agents. Apache-2.0. + +Retained native-copy construction +Prepared by Ali Romman with substantial OpenAI Codex assistance. No subagents. +The paid-meeting source is PR5751 by Ali Romman with OpenAI Codex assistance. +The dimension-four span [265,194,164,75] is from Joel Pulikkan / GamingPuzzled +PR5739, with Claude Opus 5.5 assistance. The R22 block edits are not included. +The retained-copy mechanism, exact constructor, source-specific verification, +new price and proof are the contribution of this package. Apache-2.0. + +Exact PR5811 vendor/blocks/NOTICE follows. Source head: +33d7760d0a6fea6394aefd014eea68f0af02a92e + +The second block is PR5796 at4b30391e633ba0c7c674f03586ae97d443e9bc9c, by Ali Romman with substantial OpenAI Codex assistance, following Joel Pulikkan/GamingPuzzled R22. Exact notice, plan, proof and source words are retained in source/SECOND-* unchanged. + +The final immediate source is PR5786 asynchronous helper hubs by Ali Romman with substantial OpenAI Codex assistance. Its three temporal helper splits and complete completion parameters are retained and credited. The earlier PR5774-only composition is a superseded checkpoint, not a separate contribution. + +New complete retained-copy and R22 composition: Ali Romman with substantial OpenAI Codex assistance. No subagents. Apache-2.0. + +The thirteen retained native conversions and changed helper targets are by Ali Romman with OpenAI Codex assistance in PR5774. The R22 block and rank-four basis are by Joel Pulikkan (GamingPuzzled), with Claude Opus5.5 assistance, in PR5739/5756. The complete source archive and R22 notice remain unchanged. + +The construction retains Ali Romman PR5751 paid intermediate meetings, flyingviper PR5718 boundary splits, Cinna Davis's productive controller, Jacob Alan Sussman's productive recursion, zxv and Cao Yifan's interval/compiler line, and every P104/native/BIT predecessor in the source notices. The source engines are reused under exact byte bindings, not claimed as new implementations. + +Binary query-tree caller + +New construction, proof and code: Ali Romman, with substantial OpenAI Codex assistance. Apache-2.0. No subagents. + +Cinna Davis supplies the productive path caller, query thinning and exact Laurent factorization. Ali Romman supplies the all-forward P104 binding in PR5544 and the retained-operand word in PR6167. The native word and interval/compiler lineage remain predecessor work. The new contribution is the four-field query extension, its tree composition, complete invoice and conditional price. + +The authenticated PR6167 notice follows. + +Retained-operand descent: Ali Romman, with substantial OpenAI Codex assistance. +Apache-2.0. + +The exact source word and price are from DreamingOfClouds, PR6144 and PR6143, +with Claude Opus 5.5 (Anthropic), via Claude Code. They extend PR6030 and PR5907. +The source reader is adapted from that work. The gzip portability controls +retain Douglas Colkitt and Maxime Fleury credit. + +The pinned PR5827 checker and all earlier source notices are retained below. + +Unread-register path resynthesis +Copyright 2026 Ali Romman. Apache-2.0. + +New construction, code, calculations and prose: Ali Romman with substantial +OpenAI Codex assistance. No subagents. All new checks are author-side. + +Mason Hale supplied PR5811, the complete two-block composition and the exact +role92 remapping and fourth accumulation. The earlier elementary accumulation, +retained-copy and second-block work is by Ali Romman. Joel Pulikkan supplied +R22. Dugongue supplied the concurrent baseline composition proof. Their source +notice and proof are retained byte for byte under inputs/pr5811-*. + +The source closure retains flyingviper, Cinna Davis, David Arias, Gareth +Davidson, Jacob Alan Sussman, zxv, Cao Yifan, Pierre-Loic Doulcet, thu-nmrc, +Scratch-net and all native/helper/controller/compiler/geometry/analytic +predecessors. The exact PR5786 source archive and its nested notices remain. +This package does not claim any predecessor construction as new. + +Exact PR5811 vendor/accumulated/NOTICE follows. Source head: +33d7760d0a6fea6394aefd014eea68f0af02a92e + +Accumulated native updates +New work: Ali Romman with substantial OpenAI Codex assistance. Apache-2.0. +No subagents. The same assistant made the construction and the author checks. + +Concurrent scope: Discussion5125 now tests retained copies in the transposed +supplier. That route uses the same source/destination duality. This package +claims the three fixed forward-supplier groups and their complete result, +not the elementary accumulation identity or the broader transposed search. + +Exact source: PR5786 at 6b936acd68a7e0f9062037900f0fe9bc4b6fdd25. +The complete predecessor notice follows unchanged. + +Asynchronous helper hubs +New work: Ali Romman with substantial OpenAI Codex assistance. Apache-2.0. + +Retained native copies from PR5774 at 7d6ec0cdef31d0c37b7d2563e709979caa0d5eae. +All prior credit follows unchanged. + +Paid intermediate meetings and collective helper splits. +Ali Romman, with substantial OpenAI Codex assistance. Apache-2.0. +No subagents. All checks are author-side calculations. + +The complete PR5718 notice follows unchanged. + +Four paid interior public-basis changes. +Ali Romman, with substantial OpenAI Codex assistance. Apache-2.0. +No subagents. + +The following exact notice is retained from PR5660. + +New helper-subspace construction, proof and replay: +Ali Romman with substantial OpenAI Codex assistance. Apache-2.0. +The same assistant performed the construction and author-side checks. + +Retained contributions: +flyingviper: PR5605 shared relay, PR5612 delayed relay, and the PR5608/PR5613 +relay/split compositions. +Scratch-net: PR5606 prepared-helper identities and target debit. +Pierre-Loic Doulcet (hexapode): PR5565 commuting-contact construction, used as the exact source. +Ali Romman: PR5602 fixed boundary relations, PR5601 three-contact frame +change, PR5580 contact step, +and PR5544/5545 complete P104 caller. +Joel Pulikkan (GamingPuzzled): PR5569 priced helper handoff. +DreamingOfClouds: PR5561 free helper endpoints and PR5568 search tools. +thu-nmrc: PR5551 contact improvements. +Gareth Davidson (bitplane): PR2305 source composition. +David Arias: PR2152 coalesced P104 word. +Cinna Davis: PR2219 private reuse and the controller lineage. +Jacob Alan Sussman: productive mixed-target recursion. +zxv and Cao Yifan: exact intervals, compiler and native/pricing lineage. +GamingPuzzled: PR5472 successor handoff, a predecessor to the split concept. +The retained source notices preserve earlier geometry, BIT and analytic credit. + +The elementary rank-one basis identity is not claimed as a new general +linear-algebra theorem. The contribution is its explicit independent-target +use on this P104 word and the complete conditional kappa improvement. + +New contribution: Ali Romman, with substantial OpenAI Codex assistance. +The four-gate source-version rewrite composes zxv PR5643 and Ali Romman PR5644. +The A2 method retains Chris R/Clear1nsight PR3998 and ToikY PR4019 credit. +The compensated triangle method retains Cinna Davis PR4692 credit. +No subagents were used for this contribution. Apache-2.0. + +Concurrent PR5650 by zxv publishes the PR5643/PR5644 composition. PR5651 by +Ali Romman corroborates it. This package credits that released composition +and contributes the further four-gate placement. + +New work: distributed scalar updates on an unobserved public field interval, the exact witness and complete conditional price. Prepared for Ali Romman with substantial OpenAI Codex assistance. No subagents. Apache-2.0. The source archive retains all predecessor notices. + +Two-boundary main-assisted helper split and early cleanup: flyingviper with substantial +OpenAI Codex assistance, including independent AI review agents. Apache-2.0. + +Retained native-copy construction +Prepared by Ali Romman with substantial OpenAI Codex assistance. No subagents. +The paid-meeting source is PR5751 by Ali Romman with OpenAI Codex assistance. +The dimension-four span [265,194,164,75] is from Joel Pulikkan / GamingPuzzled +PR5739, with Claude Opus 5.5 assistance. The R22 block edits are not included. +The retained-copy mechanism, exact constructor, source-specific verification, +new price and proof are the contribution of this package. Apache-2.0. + +Exact PR5811 vendor/blocks/NOTICE follows. Source head: +33d7760d0a6fea6394aefd014eea68f0af02a92e + +The second block is PR5796 at4b30391e633ba0c7c674f03586ae97d443e9bc9c, by Ali Romman with substantial OpenAI Codex assistance, following Joel Pulikkan/GamingPuzzled R22. Exact notice, plan, proof and source words are retained in source/SECOND-* unchanged. + +The final immediate source is PR5786 asynchronous helper hubs by Ali Romman with substantial OpenAI Codex assistance. Its three temporal helper splits and complete completion parameters are retained and credited. The earlier PR5774-only composition is a superseded checkpoint, not a separate contribution. + +New complete retained-copy and R22 composition: Ali Romman with substantial OpenAI Codex assistance. No subagents. Apache-2.0. + +The thirteen retained native conversions and changed helper targets are by Ali Romman with OpenAI Codex assistance in PR5774. The R22 block and rank-four basis are by Joel Pulikkan (GamingPuzzled), with Claude Opus5.5 assistance, in PR5739/5756. The complete source archive and R22 notice remain unchanged. + +The construction retains Ali Romman PR5751 paid intermediate meetings, flyingviper PR5718 boundary splits, Cinna Davis's productive controller, Jacob Alan Sussman's productive recursion, zxv and Cao Yifan's interval/compiler line, and every P104/native/BIT predecessor in the source notices. The source engines are reused under exact byte bindings, not claimed as new implementations. diff --git a/research/relative-tariff-integer-exp/source/sources/OLD-WORD.json.gz b/research/relative-tariff-integer-exp/source/sources/OLD-WORD.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..0af79e58172f85c302c35b193205c0b185b09393 GIT binary patch literal 85365 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 MKL*@x54sHp0P&x6k^lez literal 0 HcmV?d00001 diff --git a/research/relative-tariff-integer-exp/source/sources/constructor-source.py b/research/relative-tariff-integer-exp/source/sources/constructor-source.py new file mode 100644 index 0000000000..c099995bef --- /dev/null +++ b/research/relative-tariff-integer-exp/source/sources/constructor-source.py @@ -0,0 +1,195 @@ +"""Rebuild the shared-carrier input-lift word from the PR6372 word. + +DreamingOfClouds with Claude Opus 5.5 (Anthropic), via Claude Code. Apache-2.0. +The source word, the native input-lift move class and the checkers retain +their credits in NOTICE. + +Each lift cluster has an entrance frame F, a list of anchors and a list of +carriers. An anchor q is an unwritten Z-born full helper. It starts at F +instead of the preparation frame Z. Its Z-column response a = A h is + - delivered at F to the carriers (carrier detour Z -> F, ADDs, F -> old + first destination), placed before every anchor of the cluster departs; + - delivered at the anchor's first-destination frame G_q to the other + recipients in that group, right after their arrival; + - restored at the final frame by c += -h_c q. +Every response, restore and carrier trip is an ordinary ADD or MOVE. All +arithmetic is exact (Fractions) and every assumption is asserted. +""" +from collections import defaultdict +from copy import deepcopy +from fractions import Fraction as Fr + +from support import need + +Z, OMEGA = 3, 127 + + +def fstr(x): + x = Fr(x) + return str(x.numerator) if x.denominator == 1 else f'{x.numerator}/{x.denominator}' + + +def span_mask(gens): + """Bitmask over the 512 vectors of the span of the generators.""" + S = {0} + for g in gens: + if g not in S: + S |= {s ^ g for s in S} + m = 0 + for s in S: + m |= 1 << s + return m + + +def frame_masks(w): + return [span_mask(f) for f in w['frames']] + + +def prep(w): + """Value of every Z-born register (sparse rows over the inputs) when it + first leaves Z, and the first destination frame of each.""" + P, ini = w['program'], w['initial'] + val = {r: {r: Fr(1)} for r in range(w['public']) if ini[r] == Z} + G = {} + for e in P: + op = e[0] + if op == 'INIT' and e[-1] == Z: + val[e[1]] = {} + elif op == 'ADD' and e[-1] == Z: + d, s, c = e[1], e[2], Fr(e[3]) + vd = val.setdefault(d, {}) + for k, x in val[s].items(): + y = vd.get(k, 0) + c * x + if y: + vd[k] = y + else: + vd.pop(k, None) + elif op == 'SCALE' and e[-1] == Z: + c = Fr(e[2]) + val[e[1]] = {k: c * x for k, x in val[e[1]].items()} + elif op == 'COPY' and e[-1] == Z: + raise ValueError('COPY at Z') + elif op == 'MOVE' and e[2] == Z and e[1] not in G: + G[e[1]] = e[3] + return val, G + + +def lift(word, spec): + w = deepcopy(word) + P = w['program'] + val, G = prep(word) + Mk = frame_masks(word) + mv_from_Z = {} + for i, e in enumerate(P): + if e[0] == 'MOVE' and e[2] == Z and e[1] not in mv_from_Z: + mv_from_Z[e[1]] = i + zmax = defaultdict(int) + for i, e in enumerate(P): + if e[-1] == Z and e[0] in ('ADD', 'SCALE'): + zmax[e[1]] = max(zmax[e[1]], i) + if e[0] == 'ADD': + zmax[e[2]] = max(zmax[e[2]], i) + hoisted, delete, restore = set(), set(), [] + pre_carr, insert_before = defaultdict(list), defaultdict(list) + for cl in spec['clusters']: + F = cl['F'] + anchors = {int(q): {int(k): Fr(v) for k, v in d['h'].items()} for q, d in cl['anchors'].items()} + carriers = [int(c) for c in cl['carriers']] + for q, h in anchors.items(): + need(word['initial'][q] == Z and word['final'][q] == OMEGA, 'Anchor must be a Z-born full helper') + need(h[q] == 1 and all(h.get(q2, 0) == 0 for q2 in anchors if q2 != q), 'Unit anchor coordinates') + need(Mk[F] & ~Mk[G[q]] == 0, 'Entrance frame inside the first destination') + resp = {} + for q, h in anchors.items(): + for r, row in val.items(): + a = sum(row.get(k, 0) * c for k, c in h.items()) + if a != 0: + resp.setdefault(r, {})[q] = a + Gq = {q: G[q] for q in anchors} + Tq = {q: mv_from_Z[q] for q in anchors} + writes = {} + for q in anchors: + ws = [(i, e[2], e[3]) for i, e in enumerate(P) if e[-1] == Z and e[0] == 'ADD' and e[1] == q] + need(not [i for i, e in enumerate(P) if e[-1] == Z and e[0] == 'SCALE' and e[1] == q], + 'No SCALE of an anchor at Z') + for i, sr, cf in ws: + need(G.get(sr) == G[q], 'Postponed source lies in the first-destination group') + need(not any(e[-1] == Z and e[0] in ('ADD', 'SCALE') and e[1] == sr for e in P[i + 1:]), + 'Source unchanged at Z after the write') + need(not any(e[-1] == Z and e[0] == 'ADD' and e[2] == q and j > i for j, e in enumerate(P)), + 'Anchor not read at Z after being written') + need(sr not in anchors, 'Source is not an anchor') + Tq[q] = min(Tq[q], mv_from_Z[sr]) + writes[q] = ws + recipients = defaultdict(list) + carr_resp = defaultdict(dict) + for r, d in resp.items(): + for q, a in d.items(): + if r == q: + need(a == 1, 'Unit self response') + continue + if r in carriers: + carr_resp[r][q] = a + elif G.get(r, -1) == Gq[q]: + recipients[q].append((r, a)) + else: + raise ValueError(f'Unplaced response row {r} of anchor {q}') + deps = {q: [r for r, a in recipients[q]] + [sr for i, sr, cf in writes[q]] for q in anchors} + for q in anchors: + for d in deps[q]: + Tq[q] = min(Tq[q], mv_from_Z[d]) + X = min(Tq.values()) + for q, h in anchors.items(): + for i, e in enumerate(P): + if e[-1] == Z and e[0] == 'ADD' and e[2] == q: + delete.add(i) + w['initial'][q] = F + iq = mv_from_Z[q] + need(P[iq] == ['MOVE', q, Z, Gq[q], False], 'Anchor departure event') + delete.add(iq) + insert_before[Tq[q]].append(['MOVE', q, F, Gq[q], False]) + seq = [] + for d in dict.fromkeys(deps[q]): + idd = mv_from_Z[d] + need(P[idd][3] == Gq[q] and P[idd][2] == Z, 'Dependent departs to the same group') + need(zmax[d] < Tq[q], 'Dependent unused at Z after the hoist') + if d not in hoisted: + seq.append(['MOVE', d, Z, Gq[q], False]) + hoisted.add(d) + delete.add(idd) + for r, a in recipients[q]: + seq.append(['ADD', r, q, fstr(a), Gq[q]]) + for i, sr, cf in writes[q]: + delete.add(i) + seq.append(['ADD', q, sr, cf, Gq[q]]) + insert_before[Tq[q]].extend(seq) + for c, cf in h.items(): + if c != q: + restore.append(['ADD', c, q, fstr(-cf), OMEGA]) + for c in carriers: + ic = mv_from_Z[c] + need(P[ic][0] == 'MOVE' and P[ic][2] == Z, 'Carrier departure event') + delete.add(ic) + pos = min(ic, X) + need(pos > zmax[c], 'Carrier unused at Z after the hoist position') + blk = [['MOVE', c, Z, F, False]] + blk += [['ADD', c, q, fstr(a), F] for q, a in sorted(carr_resp[c].items())] + blk += [['MOVE', c, F, P[ic][3], False]] + pre_carr[pos].extend(blk) + out = [] + for i, e in enumerate(P): + out.extend(pre_carr.get(i, [])) + out.extend(insert_before.get(i, [])) + if i not in delete: + out.append(e) + out.extend(restore) + w['program'] = out + return w + + +def construct(source, lifts): + """Apply the lift rounds in order; return the word.""" + word = source + for spec in lifts['rounds']: + word = lift(word, spec) + return word diff --git a/research/relative-tariff-integer-exp/source/sources/controller-source.py b/research/relative-tariff-integer-exp/source/sources/controller-source.py new file mode 100644 index 0000000000..3b4bf82eba --- /dev/null +++ b/research/relative-tariff-integer-exp/source/sources/controller-source.py @@ -0,0 +1,212 @@ +"""Build a binary tree of query suppliers and check every Laurent coefficient. + +Ali Romman, with substantial OpenAI Codex assistance. Apache-2.0. +The local interface and thin query are from Cinna Davis and the P104 authors. +""" +from collections import Counter +from copy import deepcopy +from fractions import Fraction as Q +from hashlib import sha256 +import json + + +def need(ok, message): + if not ok: + raise ValueError(message) + + +T2 = (1, 1) +T3 = (1, T2) +T4 = (T2, T2) +T7 = (T3, T4) +T8 = (T4, T4) +TREE = (T4, T7, T8) + + +def construct(): + """Emit all scalar steps, native wrappers, thin queries and whole idles.""" + stage = 0 + def label(tree): + nonlocal stage + if tree == 1: + stage += 1 + return {'stage': stage, 'stages': [stage]} + left, right = map(label, tree) + return {'left': left, 'right': right, + 'stages': left['stages'] + right['stages']} + roots = [label(tree) for tree in TREE] + need(stage == 19, 'Nineteen independent native stages') + events, targets, nodes = [], {}, [] + next_role = 2 + def emit(op, *args): + events.append([op, *args]) + def supplier(tree, x, y, exponent): + nonlocal next_role + if 'stage' in tree: + # q = Q^-1. Conjugation by Q^2 changes q to q^-1. + if exponent == -1: + emit('Q_POWER', x, -2) + emit('SWAP', x, y) + emit('LOCAL', tree['stage'], x, y) + emit('SWAP', x, y) + if exponent == -1: + emit('Q_POWER', x, 2) + return + a, b = next_role, next_role + 1 + next_role += 2 + stages = tree['stages'] + nodes.append({'roles': [a, b], 'stages': stages, + 'exponent': exponent}) + # R(x,y,a,b) = (x+b,a,x,y). + emit('SWAP', x, b) + emit('SWAP', y, a) + emit('SWAP', a, b) + emit('ADD', x, a, 1) + # C(q): a <- a + q*(b-y). One paid query. + emit('ADD', b, y, -1) + emit('QUERY', a, b, -exponent) + emit('ADD', b, y, 1) + # S^-1 makes the A and B query planes the first two fields. + emit('ADD', x, a, -1) + emit('IDLE', a, b, stages) + emit('SCALE', y, -1) + supplier(tree['left'], y, x, -exponent) + emit('SCALE', y, -1) + supplier(tree['right'], x, y, exponent) + emit('ADD', x, a, 1) + # L(x,y,a,b) = (x,b,x-a,b-y). + emit('SCALE', a, -1) + emit('ADD', a, x, 1) + emit('SWAP', y, b) + emit('SCALE', b, -1) + emit('ADD', b, y, 1) + targets[a] = (-exponent, stages) + targets[b] = (exponent, stages) + supplier(roots[0], 0, 1, 1) + emit('SCALE', 1, -1) + supplier(roots[1], 1, 0, -1) + emit('SCALE', 1, -1) + supplier(roots[2], 0, 1, 1) + emit('SWAP', 0, 1) + emit('SCALE', 0, -1) + targets[0], targets[1] = (1, list(range(1, 20))), (-1, list(range(1, 20))) + need(next_role == 34 and len(targets) == 34, 'All main fields have one target') + diagonal = [[targets[r][0], 0] + + [int(s in targets[r][1]) for s in range(1, 20)] + for r in range(34)] + return {'schema': 'binary-query-tree/1', 'tree': TREE, + 'roles': 34, 'stages': 19, 'nodes': nodes, + 'events': events, 'diagonal': diagonal, + 'ambient_rank': 161} + + +def plus(dst, src, coefficient): + for key, value in src.items(): + value = dst.get(key, 0) + coefficient * value + if value: + dst[key] = value + else: + dst.pop(key, None) + + +def shifted(row, term): + return [{tuple(a+b for a, b in zip(key, term)): value + for key, value in cell.items()} for cell in row] + + +def replay(word): + """Use sparse rational polynomials for every input and output field.""" + n, width = word['roles'], 21 + zero = (0,) * width + rows = [[{zero: Q(1)} if i == j else {} for j in range(n)] + for i in range(n)] + seen = [] + for event in word['events']: + op = event[0] + if op == 'ADD': + _, dst, src, coefficient = event + for a, b in zip(rows[dst], rows[src]): + plus(a, b, coefficient) + elif op == 'SCALE': + _, dst, coefficient = event + rows[dst] = [{key: coefficient*value for key, value in cell.items()} + for cell in rows[dst]] + elif op == 'SWAP': + _, a, b = event + rows[a], rows[b] = rows[b], rows[a] + elif op in ('LOCAL', 'QUERY'): + if op == 'LOCAL': + _, stage, src, dst = event + exponent = -1 + seen.append(stage) + else: + _, dst, src, exponent = event + term = (exponent,) + (0,) * 20 + for a, b in zip(rows[dst], shifted(rows[src], term)): + plus(a, b, 1) + if op == 'LOCAL': + term = (0,) + tuple(int(s == stage) for s in range(20)) + for r in (src, dst): + rows[r] = shifted(rows[r], term) + elif op == 'Q_POWER': + _, r, exponent = event + need(exponent in (-2, 2), 'Only even central powers are ordinary') + rows[r] = shifted(rows[r], (exponent,) + (0,) * 20) + elif op == 'IDLE': + _, a, b, stages = event + need(len(stages) == len(set(stages)), 'No repeated idle stage') + term = (0,) + tuple(int(s in stages) for s in range(20)) + for r in (a, b): + rows[r] = shifted(rows[r], term) + else: + raise ValueError('Unknown caller opcode: ' + op) + need(sorted(seen) == list(range(1, 20)), 'Each native stage occurs once') + expected = [[{tuple(word['diagonal'][i]): Q(1)} if i == j else {} + for j in range(n)] for i in range(n)] + need(rows == expected, 'All exact Laurent endpoint coefficients') + return {'inputs': n, 'coefficients': n*n, + 'native_stages': len(seen), 'events': len(word['events']), + 'event_sha256': sha256(json.dumps(word['events'], separators=(',', ':')).encode()).hexdigest()} + + +def controls(word): + out = {} + for label, opcode in [('unpaid_idle', 'IDLE'), + ('missing_translation', 'Q_POWER'), + ('missing_thin_query', 'QUERY')]: + bad = deepcopy(word) + del bad['events'][next(i for i, e in enumerate(bad['events']) if e[0] == opcode)] + try: + replay(bad) + except ValueError as error: + out[label] = str(error) + else: + raise ValueError('Changed caller accepted: ' + label) + bad = deepcopy(word) + event = next(e for e in bad['events'] if e[0] == 'QUERY') + event[3] *= -1 + try: + replay(bad) + except ValueError as error: + out['wrong_central_orientation'] = str(error) + else: + raise ValueError('Wrong central orientation accepted') + return out + + +def formula_invoice(local): + """Count the fixed tree without reading the emitted word.""" + targets = Counter({r: 19*n for r, n in local['helpers'].items()}) + paid = Counter({r: 19*n for r, n in local['paid'].items()}) + paid[1] += 16*104 + targets[153] += 208 + for size, count in {2: 9, 3: 1, 4: 4, 7: 1, 8: 1}.items(): + targets[1+8*size] += 208*count + paid[8*size] += 208*count + return targets, paid + + +if __name__ == '__main__': + word = construct() + print(replay(word)) + print(controls(word)) diff --git a/research/relative-tariff-integer-exp/source/sources/upstream-PROOF.md b/research/relative-tariff-integer-exp/source/sources/upstream-PROOF.md new file mode 100644 index 0000000000..bd20fcaf20 --- /dev/null +++ b/research/relative-tariff-integer-exp/source/sources/upstream-PROOF.md @@ -0,0 +1,79 @@ +# Shared-carrier input lifts + +The source is the PR6372 word. The consumer is the unchanged PR6348 binary +query tree. The construction uses the native input-lift move class of PR6349 +for six helpers, with a carrier shared by each pair. `construct.py` and +`LIFTS.json` give the exact event edits; the verifier regenerates the word. + +## 1. One lift + +Let `Z` be frame 3 and `Omega` frame 127. A helper `q` is a public input born +at `Z` and ending at `Omega`, never written by the preparation after its own +departure except by postponed ADDs. Let `A` be the scalar preparation at `Z` +and `G` the first-destination frame of `q`. Let `F` be an entrance frame whose +span lies inside `G`. + +Start `q` at `F` instead of `Z`. For a lift coordinate set `h` (here `h = e_q`, +or `e_q - e_k` for the second helper of each pair), the response of every other +register `r` is `a_r = (A h)_r`. Then: + +* rows whose first destination is `G` receive `a_r q` by an ADD at `G` + immediately after they arrive; +* a carrier row `c` makes the detour `Z -> F`, receives `a_c q` at `F` and + moves on to its old destination. The detour is hoisted before the first + departure of any helper of the cluster, so both helpers of a pair use the + same trip; +* any `Z`-time ADD into `q` is postponed to `G`, where its source has arrived; +* at `Omega`, `c += -h_c q` restores each coordinate. + +Every response, restore and carrier trip is an ordinary ADD or MOVE and is +charged by the unchanged checkers. `construct.py` asserts the side conditions: +the entrance lies inside the first destination, each response row has a place +(a carrier or a row of the same first-destination group), postponed sources +are unchanged and arrive in the same group, dependents are unused at `Z` after +the hoist, and the departure events have the expected shape. All arithmetic is +exact. + +Because the prepared value of each register when it first leaves `Z` is +unchanged and every lifted helper reaches its first destination with the same +value, the word computes the same endpoint map. The common-frame induction +and the native checker supply the relation at each tensor width, with every +local chart map and absolute phase verified. + +## 2. The three clusters + +Two rounds are applied in order (`LIFTS.json`): the pairs (520,655) with +carrier 171 and (544,671) with carrier 208, then the pair (472,624) with +carrier 130. The final output frames, public inputs and interface are +unchanged; only six initial frames change. + +## 3. Complete signed change + +Per full caller copy the paid ranks change by `{1:+6, 3:-3, 4:+3, 5:-3}` and +the target ranks by `{8:+6, 9:-6}`. The verifier recounts these from the +replay. There are no new owned fields or lifetimes: PR6372's word already has +43 lifetimes and peak storage 13. The scalar allowance rises by 52 to +129,670; the retained ordinary-work reserve funds it. Paid calls are 70,713. +Recounting the emitted caller agrees with the separate tree formula. + +The complete rational crossing lies in +`(0.00315120852329, 0.0031512085233)`. Use tested saving `0.003151205` and +claim `0.00315120`. Two interval engines agree. The PR6372 word with the same +caller fails at the new claim. + +## 4. Tariff scope + +With `H_r = r^s`, the margin change per copy is +`g(s) = 6(H8-H9) - 6H1 + 3(H3-H4+H5)`. At `s = 1` it is exactly zero, so the +gain is a curvature effect. It is positive for `s` of about 0.873 to 1 and ++0.0044 per copy (+0.0839 over 19 copies) at `s = 1 - 0.00315`. It is +negative for smaller `s` and for tariffs such as the square root. The claim +holds at the stated exponent only, not for every concave tariff, and there is +no uniform-improvement statement as in PR6372's two-sided concavity argument. + +## 5. Scope + +This is a source-bound conditional improvement under the five inherited +assumptions. It is not a proof of a global optimum, a new selected frontier, a +materialized rounded multiplier or a practical speedup. The gain is about +0.0105 percent. diff --git a/research/relative-tariff-integer-exp/source/verify_profiles.py b/research/relative-tariff-integer-exp/source/verify_profiles.py new file mode 100644 index 0000000000..b1d52ab008 --- /dev/null +++ b/research/relative-tariff-integer-exp/source/verify_profiles.py @@ -0,0 +1,414 @@ +#!/usr/bin/env python3 +"""Source-bound formal rank-profile extraction for the frozen PR6375 words. + +All source files are authenticated data; no author or peer module is imported. +The paid-rank premise is the retained strict-nesting frame tariff, as used by +PR6359. This is bookkeeping, not native phase, endpoint or supplier admission. +""" +import argparse +from collections import Counter +from copy import deepcopy +from fractions import Fraction +import gzip +from hashlib import sha1, sha256 +import json +from pathlib import Path +import sys + +HERE = Path(__file__).resolve().parent +PUBLIC, OWNED, PORTS = 770, 29, 104 +PINNED = { + "sources/NEW-WORD.json.gz": [ + "9e31463a785c18a70f6ae6ef3d04a6560dbb965517109390fe820f9fac3371b3", + "b1cfd03abe9128cf5a3908fbd82652e5e8a2e292" + ], + "sources/OLD-WORD.json.gz": [ + "e3b6f1c25d672b8c85433be97ebad77ae6a6972352ce2ff63507d30835fcb491", + "0af79e58172f85c302c35b193205c0b185b09393" + ], + "sources/CONTROLLER.json": [ + "6fd67eaabe659956d6694471d3fd7d2824c0a4a79cf3b8f22922f7189b11b91f", + "1f2e375b24aba5fb25580dfea7fab7a2049f3eb8" + ], + "sources/controller-source.py": [ + "8067ade84815b54d539cbaef9885db9fa4d7a23fdde2e683451d317038a8477c", + "3b4bf82eba05d57ef4bb1fd934e8ca65780425c1" + ], + "sources/LIFTS.json": [ + "38960b70a074888a2aeaf3b543629a7ae747c0c5d4f5c853371a6e7c483766c5", + "2ee8cb78fd149f9aca8dd953c650b92495a56266" + ], + "sources/constructor-source.py": [ + "fe7dc1d9aa55da393465388ee90faaa687b1e5be48dfa816a421069fa3d2de08", + "c099995bef0e224cbb0ec61c06ed3d0b4d478b33" + ], + "sources/upstream-PROOF.md": [ + "769e0f87e6b85c557b48135d2d898bb485cf77ce9925540e0a3740e6283f41af", + "bd20fcaf2078691d914d6afbc5cb06a75f47770d" + ], + "sources/NOTICE": [ + "91f24d68004688bc0a56303a48edcb5ddabd66bfc2326950603bf98dec245bbe", + "638a187d1417bda8976e945a2aeaed116a090e37" + ] +} + + +def require(ok, message): + if not ok: + raise ValueError(message) + + +def canonical(value): + return json.dumps(value, sort_keys=True, separators=(",", ":"), allow_nan=False) + + +def authenticate(): + manifest = json.loads((HERE / "SOURCE-PINS.json").read_bytes()) + require(manifest["schema"] == "source-pins/v1" and len(manifest["files"]) == 8 and + {r["file"]: [r["sha256"], r["git_blob"]] for r in manifest["files"]} == PINNED, + "eight independently fixed source pins") + data = {} + for name, (digest, blob) in PINNED.items(): + raw = (HERE / name).read_bytes() + require(sha256(raw).hexdigest() == digest, "source SHA256: " + name) + require(sha1(b"blob " + str(len(raw)).encode() + b"\0" + raw).hexdigest() == blob, + "source Git blob: " + name) + if name.endswith(".json.gz"): + data[Path(name).name] = json.loads(gzip.decompress(raw)) + elif name.endswith(".json"): + data[Path(name).name] = json.loads(raw) + return data + + +def integer(value, lower, upper, label): + require(type(value) is int and lower <= value < upper, label) + + +def rational(value): + require(type(value) is str, "rational coefficient string") + q = Fraction(value) + require(q and str(q) == value and q.denominator & (q.denominator - 1) == 0, + "canonical nonzero dyadic coefficient") + return q + + +def frame_spaces(frames): + result = [] + require(type(frames) is list and len(frames) == 1095, "fixed frame inventory") + for basis in frames: + require(type(basis) is list, "binary frame basis") + space = {0} + for vector in basis: + integer(vector, 1, 512, "nonzero binary nine-axis vector") + require(vector not in space, "independent frame basis") + space |= {point ^ vector for point in tuple(space)} + result.append(frozenset(space)) + return result + + +def dimension(space): + return len(space).bit_length() - 1 + + +def raw_local(word, spaces): + paid = Counter() + for event in word["program"]: + if event[0] == "MOVE": + paid[abs(dimension(spaces[event[3]]) - dimension(spaces[event[2]]))] += 1 + main = set(word["live"]) | {r + 112 for r in word["live"]} + helpers = Counter(dimension(spaces[word["final"][r]]) - dimension(spaces[word["initial"][r]]) + for r in range(PUBLIC) if r not in main) + require(min(paid) > 0 and min(helpers) > 0, "positive literal paid and productive ranks") + return paid, helpers + + +def validate_word(word, spaces): + require(type(word["public"]) is int and word["public"] == PUBLIC and + type(word["owned_fields"]) is int and word["owned_fields"] == OWNED, "fixed role inventory") + require(len(word["initial"]) == len(word["final"]) == PUBLIC and + len(word["live"]) == len(set(word["live"])) == len(word["ports"]) == PORTS, "public/main interface") + main = set(word["live"]) | {r + 112 for r in word["live"]} + require(len(main) == 208, "disjoint104 main pairs") + for value in word["initial"] + word["final"]: + integer(value, 0, len(spaces), "public frame label") + current = dict(enumerate(word["initial"])) + counts = Counter() + lifetimes, active, peak = 0, set(), 0 + for event in word["program"]: + op, r = event[:2] + integer(r, 0, PUBLIC + OWNED, "literal role") + counts[op] += 1 + if op == "MOVE": + require(len(event) == 5, "MOVE arity") + a, b, private = event[2:] + integer(a, 0, len(spaces), "MOVE source frame") + integer(b, 0, len(spaces), "MOVE destination frame") + require(current.get(r) == a and type(private) is bool and private == (r in active), + "MOVE source frame and active ownership") + require(spaces[b] < spaces[a] if private else spaces[a] < spaces[b], + "strict nested MOVE descent/ascent") + current[r] = b + elif op == "INIT": + require(len(event) == 3 and r >= PUBLIC and r not in current, "inactive owned INIT") + integer(event[2], 0, len(spaces), "INIT frame") + current[r] = event[2] + active.add(r) + lifetimes += 1 + peak = max(peak, len(active)) + elif op == "CLEAR": + require(len(event) == 3 and r in active and current[r] == event[2], "active owned CLEAR frame") + integer(event[2], 0, len(spaces), "CLEAR frame") + active.remove(r) + del current[r] + else: + require(op in ("ADD", "SCALE") and len(event) == (5 if op == "ADD" else 4), + "actual pinned words contain only ADD/SCALE scalar updates, no COPY") + integer(event[-1], 0, len(spaces), "scalar frame") + require(current.get(r) == event[-1], "active common-frame scalar destination") + q = rational(event[-2]) + if op == "ADD": + s = event[2] + integer(s, 0, PUBLIC + OWNED, "scalar source role") + require(s != r and s in current and current[s] == event[-1], "active distinct common-frame source") + else: + require(abs(q.numerator) & (abs(q.numerator) - 1) == 0, "dyadic-unit SCALE") + require(not active and current == dict(enumerate(word["final"])), "all public exits and owned lifetimes") + require(all(dimension(spaces[word["final"][r]]) - dimension(spaces[word["initial"][r]]) == 8 + for r in main), "retained main-stage rank increment8") + return {"events": len(word["program"]), "opcode_counts": dict(sorted(counts.items())), + "owned_fields": OWNED, "owned_lifetimes": lifetimes, "peak_owned": peak, + "COPY_events": counts["COPY"]} + + +def complete_from_events(local, caller, strict=True): + paid, helpers = local + full_paid, full_targets = Counter(), Counter() + native_stages, queries, idles = [], [], [] + for event in caller["events"]: + op = event[0] + if op == "LOCAL": + native_stages.append(event[1]) + full_paid.update(paid) + full_targets.update(helpers) + elif op == "QUERY": + require(type(event[3]) is int and event[3] in (-1, 1), "unit central query exponent") + full_paid[1] += PORTS + queries.append(event) + elif op == "IDLE": + labels = event[3] + require(type(labels) is list and labels and len(labels) == len(set(labels)) and + all(type(s) is int and 1 <= s <= 19 for s in labels), + "distinct idle stage labels") + full_paid[8 * len(labels)] += 2 * PORTS + idles.append(event) + else: + require(op in ("ADD", "SCALE", "SWAP", "Q_POWER"), "declared ordinary caller event") + for row in caller["diagonal"]: + require(type(row) is list and len(row) == 21 and type(row[0]) is int and row[0] in (-1, 1) + and row[1] == 0 and all(type(s) is int and s in (0, 1) for s in row[2:]), + "literal main target monomial") + full_targets[abs(row[0]) + 8 * sum(row[2:])] += PORTS + if strict: + require(type(caller["stages"]) is int and caller["stages"] == 19 and + sorted(native_stages) == list(range(1, 20)) and len(queries) == len(idles) == 16 and + caller["roles"] == len(caller["diagonal"]) == 34, "fixed caller occurrence census") + return full_paid, full_targets + + +def complete_from_forest(local, caller): + node_sizes = Counter() + def leaves(tree): + if type(tree) is int: + require(tree == 1, "unit native leaf") + return 1 + require(type(tree) is list and len(tree) == 2, "binary caller subtree") + count = leaves(tree[0]) + leaves(tree[1]) + node_sizes[count] += 1 + return count + require([leaves(tree) for tree in caller["tree"]] == [4, 7, 8], "fixed three-root forest") + require(node_sizes == Counter({2: 9, 3: 1, 4: 4, 7: 1, 8: 1}), "independent internal-node size census") + paid, targets = [Counter({r: 19 * n for r, n in profile.items()}) for profile in local] + paid[1] += PORTS * sum(node_sizes.values()) + targets[153] += 2 * PORTS + for size, count in node_sizes.items(): + paid[8 * size] += 2 * PORTS * count + targets[1 + 8 * size] += 2 * PORTS * count + return paid, targets, dict(sorted(node_sizes.items())) + + +def profile(value): + return {str(rank): count for rank, count in sorted(value.items()) if count} + + +def delta(after, before): + result = Counter(after) + result.subtract(before) + return result + + +def first_departure(word, role): + return next(event for event in word["program"] if event[0] == "MOVE" and event[1] == role) + + +def bind_changes(old, new, lifts, spaces): + require(set(old) == set(new), "same local word schema") + for key in old: + if key not in ("initial", "program"): + require(canonical(old[key]) == canonical(new[key]), "unchanged shared local interface: " + key) + clusters = [cluster for round_ in lifts["rounds"] for cluster in round_["clusters"]] + require(len(clusters) == 3, "three shared-carrier clusters") + expected_initial, expected_removed, expected_added, carriers = {}, Counter(), Counter(), [] + for cluster in clusters: + entrance = cluster["F"] + integer(entrance, 0, len(spaces), "lift entrance label") + require(dimension(spaces[entrance]) == 1 and len(cluster["carriers"]) == 1 and + len(cluster["anchors"]) == 2, "one rank1 entrance and one carrier shared by two helpers") + carrier = cluster["carriers"][0] + old_event = first_departure(old, carrier) + require(old_event[2] == 3 and dimension(spaces[old_event[3]]) == 2, "carrier old rank2 first destination") + first = ("MOVE", carrier, 3, entrance, False) + second = ("MOVE", carrier, entrance, old_event[3], False) + old_role = Counter(tuple(e) for e in old["program"] if e[0] == "MOVE" and e[1] == carrier) + new_role = Counter(tuple(e) for e in new["program"] if e[0] == "MOVE" and e[1] == carrier) + require(old_role - new_role == Counter({tuple(old_event): 1}) and + new_role - old_role == Counter({first: 1, second: 1}), "exact shared carrier detour") + expected_removed.update([tuple(old_event)]) + expected_added.update([first, second]) + carriers.append({"carrier": carrier, "entrance_frame": entrance, "old_first_MOVE": old_event, + "new_first_MOVEs": [list(first), list(second)], + "old_rank": 2, "new_ranks": [1, 1]}) + for text_role in cluster["anchors"]: + role = int(text_role) + require(str(role) not in expected_initial and old["initial"][role] == 3, "distinct independent lifted input") + expected_initial[str(role)] = [3, entrance] + event = first_departure(old, role) + require(event[2] == 3 and dimension(spaces[event[3]]) in (3, 5) and spaces[entrance] < spaces[event[3]], + "lift entrance nested in actual first destination") + replacement = ("MOVE", role, entrance, event[3], False) + expected_removed.update([tuple(event)]) + expected_added.update([replacement]) + initial = {str(r): [a, b] for r, (a, b) in enumerate(zip(old["initial"], new["initial"])) if a != b} + require(initial == expected_initial and set(initial) == {"472", "520", "544", "624", "655", "671"}, + "exact six initial endpoint changes") + old_moves = Counter(tuple(e) for e in old["program"] if e[0] == "MOVE") + new_moves = Counter(tuple(e) for e in new["program"] if e[0] == "MOVE") + require(old_moves - new_moves == expected_removed and new_moves - old_moves == expected_added, + "all MOVE changes are the six entrances and three shared detours") + return {"initial_frame_changes": initial, "final_frame_changes": {}, + "carrier_detours": carriers, "removed_MOVE_count": sum(expected_removed.values()), + "added_MOVE_count": sum(expected_added.values()), + "other_MOVE_records_cancel": True} + + +def rejection(action): + try: + action() + except ValueError as error: + return str(error) + raise ValueError("invalid mutated occurrence inventory accepted") + + +def controls(new, caller, local, complete, spaces, bindings): + result = [] + baseline_paid, baseline_targets = complete + for carrier in (171, 208, 130): + changed = deepcopy(new) + index = next(i for i, e in enumerate(changed["program"]) + if e[0] == "MOVE" and e[1] == carrier and e[2] == 3) + omitted = changed["program"].pop(index) + counter_local = raw_local(changed, spaces) + counter_paid, counter_targets = complete_from_events(counter_local, caller) + require(delta(counter_paid, baseline_paid) == Counter({1: -19}) and counter_targets == baseline_targets, + "omitted actual carrier trip loses nineteen charged H1 occurrences") + result.append({"control": "omitted_carrier_trip", "carrier": carrier, "event_index": index, + "omitted_event": omitted, "complete_paid_delta": profile(delta(counter_paid, baseline_paid)), + "complete_target_delta": profile(delta(counter_targets, baseline_targets)), + "structural_rejection": rejection(lambda: validate_word(changed, spaces))}) + changed = deepcopy(new) + changed["initial"][520] = 3 + counter_paid, counter_targets = complete_from_events(raw_local(changed, spaces), caller) + require(delta(counter_targets, baseline_targets) == Counter({9: 19, 8: -19}) and counter_paid == baseline_paid, + "reverted productive input omits exactly nineteen target debits") + result.append({"control": "reverted_lifted_input_520", "complete_paid_delta": {}, + "complete_target_delta": profile(delta(counter_targets, baseline_targets)), + "structural_rejection": rejection(lambda: validate_word(changed, spaces))}) + for opcode in ("IDLE", "QUERY", "LOCAL"): + altered = deepcopy(caller) + index = next(i for i, e in enumerate(altered["events"]) if e[0] == opcode) + omitted = altered["events"].pop(index) + paid, targets = complete_from_events(local, altered, strict=False) + changed_paid, changed_targets = delta(paid, baseline_paid), delta(targets, baseline_targets) + expected_paid = (Counter({8 * len(omitted[3]): -208}) if opcode == "IDLE" else + Counter({1: -104}) if opcode == "QUERY" else + Counter({rank: -count for rank, count in local[0].items()})) + expected_targets = Counter({rank: -count for rank, count in local[1].items()}) if opcode == "LOCAL" else Counter() + require(dict(profile(changed_paid)) == dict(profile(expected_paid)) and + dict(profile(changed_targets)) == dict(profile(expected_targets)), "actual caller omission invoice") + result.append({"control": "missing_" + opcode.lower(), "event_index": index, "omitted_event": omitted, + "complete_paid_delta": profile(changed_paid), "complete_target_delta": profile(changed_targets), + "structural_rejection": rejection(lambda: complete_from_events(local, altered))}) + return {"qualification": "These changed literal records give counterfactual invoice differences; structural guards reject them. They are not valid cheaper programs.", + "cases": result} + + +def run(): + data = authenticate() + old, new, caller = data["OLD-WORD.json.gz"], data["NEW-WORD.json.gz"], data["CONTROLLER.json"] + require(canonical(old["frames"]) == canonical(new["frames"]), "unchanged native frame coordinates") + spaces = frame_spaces(old["frames"]) + old_census, new_census = validate_word(old, spaces), validate_word(new, spaces) + old_local, new_local = raw_local(old, spaces), raw_local(new, spaces) + bindings = bind_changes(old, new, data["LIFTS.json"], spaces) + old_complete, new_complete = complete_from_events(old_local, caller), complete_from_events(new_local, caller) + for local, complete in ((old_local, old_complete), (new_local, new_complete)): + paid, targets, node_sizes = complete_from_forest(local, caller) + require((paid, targets) == complete, "independent emitted and forest-formula profiles") + paid_delta, target_delta = delta(new_local[0], old_local[0]), delta(new_local[1], old_local[1]) + require(profile(paid_delta) == {"1": 6, "3": -3, "4": 3, "5": -3} and + profile(target_delta) == {"8": 6, "9": -6}, "exact local signed changes") + require(old_census["owned_lifetimes"] == new_census["owned_lifetimes"] == 43 and + old_census["peak_owned"] == new_census["peak_owned"] == 13, "unchanged owned resource census") + complete_records = {} + for name, value in (("old", old_complete), ("new", new_complete)): + paid, targets = value + complete_records[name] = {"paid": profile(paid), "targets": profile(targets), + "paid_jobs": sum(paid.values()), "productive_fields": sum(targets.values()), + "rank_mass_surplus": sum(r*n for r,n in targets.items()) - sum(r*n for r,n in paid.items())} + require(complete_records["old"]["paid_jobs"] == 70656 and complete_records["new"]["paid_jobs"] == 70713 and + all(r["productive_fields"] == 14214 and r["rank_mass_surplus"] == 808 for r in complete_records.values()), + "complete same-caller inventories") + margin_delta = delta(target_delta, paid_delta) + return {"schema_version": 1, "scope": "source-bound formal local and complete same-caller rank profiles only", + "old_local": {"paid": profile(old_local[0]), "targets": profile(old_local[1]), "census": old_census}, + "new_local": {"paid": profile(new_local[0]), "targets": profile(new_local[1]), "census": new_census}, + "literal_changes": bindings, "forest_node_sizes": {str(k): v for k,v in node_sizes.items()}, + "complete": complete_records, + "local_paid_delta": profile(paid_delta), "local_productive_delta": profile(target_delta), + "local_margin_delta_coefficients": profile(margin_delta), + "complete_paid_delta": profile(delta(new_complete[0], old_complete[0])), + "complete_productive_delta": profile(delta(new_complete[1], old_complete[1])), + "complete_margin_delta_coefficients": profile(Counter({r: 19*n for r,n in margin_delta.items()})), + "controls": controls(new, caller, new_local, new_complete, spaces, bindings), + "limits": ["Strict nested-frame ranks use the retained native/tariff premise; no native phase or all-width implementation proof is supplied.", + "Scalar common-frame and owned lifetime syntax is checked, not the public endpoint or shared response algebra.", + "The caller diagonal and primitive contracts are premises; no physical caller or ordinary-work funding is admitted.", + "No relative crossover, power evaluation, raw kappa root, new saving or supplier admission is computed."]} + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--emit", action="store_true", help="emit fresh canonical-profile receipt bytes") + options = parser.parse_args() + result = run() + payload = (json.dumps(result, sort_keys=True, indent=2, allow_nan=False) + "\n").encode() + if options.emit: + sys.stdout.buffer.write(payload) + else: + retained = HERE / "PROFILES.json" + require(retained.is_file(), "retained PROFILES.json receipt must exist") + raw = retained.read_bytes() + parsed = json.loads(raw) + require(type(parsed) is dict and type(parsed.get("schema_version")) is int and parsed["schema_version"] == 1, + "typed profile receipt schema") + require(canonical(parsed) == canonical(result) and raw == payload, "exact typed byte PROFILES.json receipt") + print("PASS exact source-bound rank profiles and retained receipt") diff --git a/research/relative-tariff-integer-exp/source/verify_tariff.py b/research/relative-tariff-integer-exp/source/verify_tariff.py new file mode 100644 index 0000000000..9c3327468f --- /dev/null +++ b/research/relative-tariff-integer-exp/source/verify_tariff.py @@ -0,0 +1,358 @@ +#!/usr/bin/env python3 +"""Whole-domain relative power-tariff certificate for the frozen PR6375 bills. + +Profiles and their two producer engines are authenticated data, never imports. +The numerical proof uses rational arctanh and positive exponential series. +The unique relative crossover is not the author's complete-bill kappa root. +""" +import argparse +from collections import Counter +from copy import deepcopy +from fractions import Fraction +from functools import lru_cache +from hashlib import sha256 +import json +from pathlib import Path +import sys + +HERE = Path(__file__).resolve().parent +FROZEN = { + "SOURCE-PINS.json": "5eb5b9458165046dad7170d5801a12f84f92891ac16ef2fd8bcbacf357046237", + "verify_profiles.py": "e7d2bf27b3ce2cca939d3fc8239876aa82dcdfcd816bd78df4c9171f37e09319", + "oracle_profiles.py": "4840369f3311369c09762fccaadcbc2a9fecffc53bcf3dd925abf2b059014cb0", + "PROFILES.json": "985500c0ebda3ba82570cf844d3acaed78d4aec7923956ea889b575e43c4e6d1", + "ORACLE-PROFILES.json": "dd9abee4eed9bdf52cd731c2fb61d2ec17022ab136ab255e4325181652ba06e4", + "PROFILE-PROOF.md": "b95cbfc30cfcf85016406801005a8284b0eca61cb8c1cc5661376e242b0a153e", + "sources/CONTROLLER.json": "6fd67eaabe659956d6694471d3fd7d2824c0a4a79cf3b8f22922f7189b11b91f", + "sources/LIFTS.json": "38960b70a074888a2aeaf3b543629a7ae747c0c5d4f5c853371a6e7c483766c5", + "sources/NEW-WORD.json.gz": "9e31463a785c18a70f6ae6ef3d04a6560dbb965517109390fe820f9fac3371b3", + "sources/NOTICE": "91f24d68004688bc0a56303a48edcb5ddabd66bfc2326950603bf98dec245bbe", + "sources/OLD-WORD.json.gz": "e3b6f1c25d672b8c85433be97ebad77ae6a6972352ce2ff63507d30835fcb491", + "sources/constructor-source.py": "fe7dc1d9aa55da393465388ee90faaa687b1e5be48dfa816a421069fa3d2de08", + "sources/controller-source.py": "8067ade84815b54d539cbaef9885db9fa4d7a23fdde2e683451d317038a8477c", + "sources/upstream-PROOF.md": "769e0f87e6b85c557b48135d2d898bb485cf77ce9925540e0a3740e6283f41af" +} +EXPECTED_G = {1: -6, 3: 3, 4: -3, 5: 3, 8: 6, 9: -6} +LOG_TERMS, EXP_DEGREE = 48, 24 +WORK_GRID, POWER_GRID = 10 ** 40, 10 ** 30 +BRACKET_LOW = Fraction(11712509413, 13421772800) +BRACKET_HIGH = Fraction(5856254707, 6710886400) +CLAIMED_KAPPA = Fraction(3939, 1250000) + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def canonical(value): + return json.dumps(value, sort_keys=True, separators=(",", ":"), allow_nan=False) + + +def strict_json(raw): + def pairs(items): + result = {} + for key, value in items: + require(key not in result, "duplicate JSON receipt key") + result[key] = value + return result + def bad_constant(value): + raise ValueError("nonfinite JSON receipt constant: " + value) + return json.loads(raw, object_pairs_hook=pairs, parse_constant=bad_constant) + + +def authenticated_receipts(): + raw = {} + for filename, expected in FROZEN.items(): + data = (HERE / filename).read_bytes() + require(sha256(data).hexdigest() == expected, "frozen source SHA256: " + filename) + raw[filename] = data + return strict_json(raw["PROFILES.json"]), strict_json(raw["ORACLE-PROFILES.json"]) + + +def positive_profile(value): + require(type(value) is dict, "integer rank-profile receipt") + result = Counter() + for key, count in value.items(): + require(type(key) is str and key.isdecimal() and str(int(key)) == key and + 1 <= int(key) <= 1000000, "canonical positive rank receipt key") + require(type(count) is int and 0 < count <= 1000000000, "positive integer profile receipt count") + result[int(key)] = count + return result + + +def cleaned(counter): + return {rank: count for rank, count in sorted(counter.items()) if count} + + +def gain(old, new): + result = Counter(new[1]) + result.subtract(new[0]) + result.subtract(old[1]) + result.update(old[0]) + return cleaned(result) + + +def parse_pair(receipt, engine, level): + require(type(receipt) is dict and type(receipt.get("schema_version")) is int and receipt["schema_version"] == 1, + "typed profile receipt schema") + if level == "complete": + records = (receipt["complete"]["old"], receipt["complete"]["new"]) if engine == "primary" else ( + receipt["old_complete"], receipt["new_complete"]) + else: + records = receipt["old_local"], receipt["new_local"] + return tuple((positive_profile(record["paid"]), positive_profile(record["targets"])) for record in records) + + +def require_equal_profiles(first, second): + for side, (a, b) in enumerate(zip(first, second)): + for part, (x, y) in enumerate(zip(a, b)): + for rank in sorted(x.keys() | y.keys()): + require(x[rank] == y[rank], "complete profile binding mismatch: side%d part%d rank%d" % (side, part, rank)) + + +def bound_coefficients(primary, oracle): + a = parse_pair(primary, "primary", "complete") + b = parse_pair(oracle, "oracle", "complete") + require_equal_profiles(a, b) + whole_a, whole_b = gain(*a), gain(*b) + require(whole_a == whole_b and all(type(c) is int and c % 19 == 0 for c in whole_a.values()), + "exact complete relative coefficients and factor19") + local = {rank: coefficient // 19 for rank, coefficient in whole_a.items()} + require(local == EXPECTED_G, "source-bound local relative coefficient vector") + require(gain(*parse_pair(primary, "primary", "local")) == local and + gain(*parse_pair(oracle, "oracle", "local")) == local, "independent local/complete coefficient binding") + return local, whole_a, a + + +def prime_exponents(coefficients, endpoint): + result = Counter() + for rank, coefficient in coefficients.items(): + value, prime = rank, 2 + while prime * prime <= value: + while value % prime == 0: + result[prime] += coefficient * rank ** endpoint + value //= prime + prime += 1 + if value > 1: + result[value] += coefficient * rank ** endpoint + return cleaned(result) + + +def prime_ratio(exponents): + numerator, denominator = 1, 1 + for prime, exponent in exponents.items(): + if exponent >= 0: + numerator *= prime ** exponent + else: + denominator *= prime ** (-exponent) + return Fraction(numerator, denominator) + + +def global_certificate(coefficients): + require(all(c % 3 == 0 for c in coefficients.values()), "integer factor3") + f = {rank: c // 3 for rank, c in coefficients.items()} + require(sum(f.values()) == -1 and sum(rank*c for rank, c in f.items()) == 0, + "exact count and linear-rank balance") + boundaries = [1, 3, 4, 5, 8, 9] + pieces = [] + expected = [(-1, 2), (0, -1), (-1, 3), (0, -2), (2, -18)] + for left, right, pair in zip(boundaries, boundaries[1:], expected): + midpoint = Fraction(left + right, 2) + active = {rank: c for rank, c in f.items() if rank > midpoint} + slope, intercept = -sum(active.values()), sum(rank*c for rank, c in active.items()) + require((slope, intercept) == pair, "exact Peano kernel segment") + pieces.append({"left": left, "right": right, "slope": slope, "intercept": intercept}) + def kernel(x): + return sum(c * max(Fraction(rank) - x, 0) for rank, c in f.items()) + cuts = [1, 2, 3, 4, 5, 8, 9] + for left, right in zip(cuts, cuts[1:]): + a, b, middle = kernel(Fraction(left)), kernel(Fraction(right)), kernel(Fraction(left + right, 2)) + require((a >= 0 and b >= 0 and middle > 0) if right <= 2 else + (a <= 0 and b <= 0 and middle < 0), "single kernel sign switch at2") + require(kernel(Fraction(1)) == 1 and kernel(Fraction(2)) == kernel(Fraction(9)) == 0, + "kernel endpoint values") + at_zero, at_one = prime_ratio(prime_exponents(f, 0)), prime_ratio(prime_exponents(f, 1)) + require(at_zero == Fraction(80, 27), "exact f'(0) logarithm") + logarithm_lower = Fraction(2, 3) + Fraction(26, 67) + require(logarithm_lower == Fraction(212, 201) and logarithm_lower > 1, "strict rational log lower bound") + require(at_one == Fraction(2 ** 40 * 5 ** 5, 3 ** 33) and at_one < 1, "strict negative L(1)=f'(1) logarithm") + # The accompanying proof applies Taylor's proper integral identity: + # f(s)=(s-1)L(s), L=1+sI, I=int_1^9 K(x)x^(s-2)dx. + # The checked single sign switch implies + # I(s)-2^s I(0)<0 for s>0 and I'(s)-log(2)I(s)<0. + # I(0)<0 therefore makes I,I' negative and L strictly decreasing. + return {"f_coefficients": {str(r): c for r, c in sorted(f.items())}, + "coefficient_sum": -1, "rank_mass": 0, "first_shifted_moment": 1, + "Peano_kernel_pieces": pieces, "kernel_sign_switch": 2, + "f_derivative0_log_ratio": str(at_zero), "log_ratio0_strict_lower": str(logarithm_lower), + "I0_strict_upper": str(1 - logarithm_lower), "L0": "1", + "L1_negative_log_ratio": {"numerator": str(at_one.numerator), "denominator": str(at_one.denominator)}, + "proper_integral_factorization": "f(s)=(s-1)*(1+s*integral_1^9 K(x)*x^(s-2) dx)", + "interior_roots": 1, "interior_root_multiplicity": 1, + "gain_signs": ["negative below the unique interior root", "positive above it up to1", "zero at1"], + "qualification": "Analytic root count follows the accompanying reviewed Taylor/single-crossing proof, not sampled signs."} + + +def outward(value, grid, upper=False): + numerator = value.numerator * grid + rounded = -((-numerator) // value.denominator) if upper else numerator // value.denominator + return Fraction(rounded, grid) + + +def log_atanh(z): + require(0 <= z <= Fraction(1, 3), "reduced positive logarithm domain") + square, power, total = z*z, z, Fraction(0) + for index in range(LOG_TERMS): + total += power / (2*index + 1) + power *= square + lower = 2*total + return lower, lower + 2*power / ((2*LOG_TERMS + 1)*(1-square)) + + +@lru_cache(None) +def logarithm(rank): + require(type(rank) is int and rank >= 1, "positive integer power rank") + exponent = rank.bit_length() - 1 + scale = 1 << exponent + a, b = log_atanh(Fraction(1, 3)) + c, d = log_atanh(Fraction(rank - scale, rank + scale)) + return outward(exponent*a + c, WORK_GRID), outward(exponent*b + d, WORK_GRID, True) + + +def exp_positive(value): + require(0 <= value <= Fraction(1, 4), "small nonnegative exponential domain") + total, term = Fraction(1), Fraction(1) + for index in range(1, EXP_DEGREE + 1): + term *= value / index + total += term + following = term * value / (EXP_DEGREE + 1) + tail = following / (1 - value / (EXP_DEGREE + 2)) + return total, total + tail + + +def power_bounds(rank, exponent): + require(0 <= exponent <= 1, "closed tariff exponent domain") + a, b = logarithm(rank) + low_argument, high_argument = exponent*a/16, exponent*b/16 + require(0 <= low_argument <= high_argument <= Fraction(1, 4), "complete exponential argument enclosure") + low = outward(exp_positive(low_argument)[0], WORK_GRID) + high = outward(exp_positive(high_argument)[1], WORK_GRID, True) + for _ in range(4): + low = outward(low*low, WORK_GRID) + high = outward(high*high, WORK_GRID, True) + require(0 < low <= high, "ordered positive power bounds") + return outward(low, POWER_GRID), outward(high, POWER_GRID, True) + + +def gain_bounds(exponent, coefficients=EXPECTED_G): + lower, upper = Fraction(0), Fraction(0) + for rank, coefficient in coefficients.items(): + a, b = power_bounds(rank, exponent) + lower += coefficient*(a if coefficient >= 0 else b) + upper += coefficient*(b if coefficient >= 0 else a) + require(lower <= upper, "ordered signed gain interval") + return lower, upper + + +def strict_sign(interval): + low, high = interval + if low > 0: + return 1 + if high < 0: + return -1 + if low == high == 0: + return 0 + raise ValueError("undecidable gain interval sign") + + +def checked_bracket(low, high, required=(-1, 1)): + require(0 < low < high < 1 and high-low <= Fraction(1, 10**10), "strict rational interior bracket ordering/width") + intervals = gain_bounds(low), gain_bounds(high) + signs = tuple(strict_sign(interval) for interval in intervals) + require(signs == required, "relative root endpoint sign orientation") + return intervals + + +def encoded_interval(value): + return [str(endpoint) for endpoint in value] + + +def rejected(action): + try: + action() + except ValueError as error: + return str(error) + raise ValueError("counterfactual certificate accepted") + + +def counterfactual_controls(primary, oracle): + result = {} + for label in ("missing_carrier_fee", "missing_productive_debit"): + bad = deepcopy(primary) + if label == "missing_carrier_fee": + bad["complete"]["new"]["paid"]["1"] -= 19 + else: + bad["complete"]["new"]["targets"]["8"] -= 19 + bad["complete"]["new"]["targets"]["9"] += 19 + actual = gain(*parse_pair(bad, "primary", "complete")) + baseline = gain(*parse_pair(primary, "primary", "complete")) + rank = next(r for r in sorted(actual.keys() | baseline.keys()) if actual.get(r, 0) != baseline.get(r, 0)) + result[label] = {"kind": "counterfactual invoice coefficients, not a valid cheaper source program", + "complete_coefficient_witness": {"rank": rank, "actual": actual.get(rank, 0), + "expected": baseline.get(rank, 0)}, + "rejection": rejected(lambda: bound_coefficients(bad, oracle))} + result["wrong_endpoint_sign_orientation"] = { + "rejection": rejected(lambda: checked_bracket(BRACKET_LOW, BRACKET_HIGH, required=(1, -1)))} + return result + + +def run(): + primary, oracle = authenticated_receipts() + local, complete, _ = bound_coefficients(primary, oracle) + analytic = global_certificate(local) + left, right = checked_bracket(BRACKET_LOW, BRACKET_HIGH) + square_root = gain_bounds(Fraction(1, 2)) + claimed_exponent = 1 - CLAIMED_KAPPA + claimed = gain_bounds(claimed_exponent) + require(strict_sign(square_root) == -1 and strict_sign(claimed) == 1, "source-relative example tariff signs") + return {"schema_version": 1, "scope": "source-specific exact relative power-tariff crossover, not a raw kappa root", + "preserved_scientific_files": FROZEN, + "local_gain_coefficients": {str(r): c for r, c in local.items()}, + "complete_gain_coefficients": {str(r): c for r, c in complete.items()}, + "complete_factor": 19, "analytic_root_count": analytic, + "interior_bracket": {"lower": str(BRACKET_LOW), "upper": str(BRACKET_HIGH), + "width": str(BRACKET_HIGH - BRACKET_LOW), + "gain_at_lower": encoded_interval(left), "gain_at_upper": encoded_interval(right)}, + "linear_tariff_gain": "0", "count_tariff_gain": "-3", + "examples": {"square_root": {"exponent": "1/2", "local_gain": encoded_interval(square_root)}, + "author_claimed_tariff": {"source_claimed_kappa": str(CLAIMED_KAPPA), + "exponent": str(claimed_exponent), + "local_gain": encoded_interval(claimed), + "complete_relative_gain": encoded_interval(tuple(19*x for x in claimed))}}, + "interval_method": {"log_atanh_terms": LOG_TERMS, "log_work_grid": str(WORK_GRID), + "positive_exp_degree": EXP_DEGREE, "argument_divisor": 16, + "outward_squarings": 4, "power_grid": str(POWER_GRID)}, + "controls": counterfactual_controls(primary, oracle), + "limits": ["Profile extraction and native/rank-tariff premises remain as stated in the immutable profile evidence.", + "A relative bill improvement does not prove source endpoint/native/caller validity or ordinary funding.", + "No new multiplication saving, raw kappa crossing, supplier admission or selected-frontier change is claimed."]} + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--emit", action="store_true", help="emit fresh certificate JSON without retained-receipt comparison") + options = parser.parse_args() + result = run() + payload = (json.dumps(result, sort_keys=True, indent=2, allow_nan=False) + "\n").encode() + if options.emit: + sys.stdout.buffer.write(payload) + else: + retained = HERE / "RELATIVE-RESULT.json" + require(retained.is_file(), "retained RELATIVE-RESULT.json receipt must exist") + raw = retained.read_bytes() + parsed = strict_json(raw) + require(type(parsed) is dict and type(parsed.get("schema_version")) is int and parsed["schema_version"] == 1, + "typed relative receipt schema") + require(canonical(parsed) == canonical(result) and raw == payload, "exact typed byte RELATIVE-RESULT.json receipt") + print("PASS exact relative tariff threshold and retained receipt") diff --git a/research/relative-tariff-integer-exp/verify.py b/research/relative-tariff-integer-exp/verify.py new file mode 100644 index 0000000000..0c06d3fa05 --- /dev/null +++ b/research/relative-tariff-integer-exp/verify.py @@ -0,0 +1,160 @@ +"""Exact conformance and full-CLI controls for the integer Taylor adapter.""" + +import ast +from fractions import Fraction +from hashlib import sha256 +import json +from math import factorial +from pathlib import Path +import runpy +import statistics +import subprocess +import sys + + +HERE = Path(__file__).resolve().parent +ADAPTER = runpy.run_path(str(HERE / "replay.py")) +integer_exp = ADAPTER["exp_interval"] + + +def require(condition: bool, message: str) -> None: + if not condition: + raise ValueError(message) + + +def direct_interval(x: Fraction, degree: int) -> tuple[Fraction, Fraction]: + lower = sum((x ** k / factorial(k) for k in range(degree + 1)), Fraction()) + next_term = x ** (degree + 1) / factorial(degree + 1) + return lower, lower + next_term / (1 - x / (degree + 2)) + + +def polynomial_cases() -> int: + cases = 0 + for denominator in range(1, 42): + for numerator in range(denominator // 4 + 1): + x = Fraction(numerator, denominator) + for degree in (1, 2, 3, 8, 24, 64): + require(integer_exp(x, degree) == direct_interval(x, degree), + "direct finite-polynomial/tail oracle") + cases += 1 + for bits in (53, 127, 521): + x = Fraction((1 << (bits - 3)) + 1, (1 << bits) + 1) + require(integer_exp(x) == direct_interval(x, 24), "large rational oracle") + cases += 1 + return cases + + +def traced_run(arm: str) -> tuple[dict, list[Fraction]]: + namespace, _ = ADAPTER["load_primary"]() + original = namespace["exp_positive"] + arguments = [] + + def tracked(x): + require(len(arguments) < 80, "bounded complete-call trace") + require(type(x) is Fraction, "source rational argument boundary") + arguments.append(x) + return original(x) if arm == "original" else integer_exp(x) + + namespace["exp_positive"] = tracked + return namespace["run"](), arguments + + +def complete_conformance() -> dict: + original, old_arguments = traced_run("original") + candidate, new_arguments = traced_run("integer") + require(original == candidate, "complete primary result equality") + require(old_arguments == new_arguments and len(old_arguments) == 72, + "complete ordered exponential-call trace") + raw = (json.dumps(candidate, sort_keys=True, indent=2, allow_nan=False) + "\n").encode() + require(raw == (HERE / "source/RELATIVE-RESULT.json").read_bytes(), + "complete retained result byte equality") + for x in old_arguments: + require(integer_exp(x) == direct_interval(x, 24), "every reached source interval") + for arm in ("original", "integer"): + optimization = ["-O"] if sys.flags.optimize else [] + result = subprocess.run( + [sys.executable, "-I", "-W", "error", *optimization, "-B", str(HERE / "replay.py"), + "--arm", arm], capture_output=True, timeout=30, check=False) + require(result.returncode == 0 and not result.stderr and result.stdout == + b"PASS exact relative tariff threshold and retained receipt\n", + "unchanged complete primary CLI, including receipt checks") + return {"complete_result_sha256": sha256(raw).hexdigest(), + "source_exp_calls": len(old_arguments), + "source_taylor_iterations": 24 * len(old_arguments), + "max_argument_denominator_bits": max(x.denominator.bit_length() for x in old_arguments), + "retained_source_controls": sorted(candidate["controls"])} + + +def rejects(action) -> None: + try: + action() + except ValueError: + return + raise ValueError("negative control accepted") + + +def negative_controls() -> int: + for x in (Fraction(-1, 8), Fraction(1, 3), 0.1, 0): + rejects(lambda: integer_exp(x)) + for degree in (0, 65, True): + rejects(lambda: integer_exp(Fraction(1, 8), degree)) + rejects(lambda: integer_exp(Fraction(1, (1 << 4096) + 1))) + x = Fraction(1, 4) + correct = direct_interval(x, 24) + rejects(lambda: require((correct[0], correct[0]) == correct, "omitted tail")) + rejects(lambda: require((correct[0] + Fraction(1, 10**40), correct[1]) == correct, + "premature outward rounding")) + raw = (HERE / "ORIGINS.json").read_bytes() + check = ADAPTER["check_payload"] + rejects(lambda: check(raw + b" ", ADAPTER["ORIGINS_SHA256"], 32768, "manifest")) + rejects(lambda: check(raw, ADAPTER["ORIGINS_SHA256"], len(raw) - 1, "limit")) + source = (HERE / "source/verify_tariff.py").read_bytes() + rejects(lambda: check(source + b"\n", ADAPTER["SOURCE_SHA256"], 4194304, "source")) + rejects(lambda: ADAPTER["replay"]("unknown")) + return 14 + + +def benchmark_receipt() -> dict: + raw = (HERE / "BENCHMARK.json").read_bytes() + require(len(raw) < 65536, "bounded benchmark receipt") + report = json.loads(raw) + require(report["schema_version"] == 1 and 5 <= report["pairs"] <= 15, + "benchmark schema and repetitions") + origin = json.loads(ADAPTER["checked_bytes"]( + HERE / "ORIGINS.json", ADAPTER["ORIGINS_SHA256"], 32768)) + expected_names = {"benchmark.py", "exp_series.py", "replay.py", "ORIGINS.json"} + expected_names.update("source/" + row["path"] for row in origin["files"]) + require(set(report["inputs"]) == expected_names, "complete benchmark input inventory") + for name, digest in report["inputs"].items(): + require(sha256((HERE / name).read_bytes()).hexdigest() == digest, + "benchmark source binding: " + name) + expected = sha256(b"PASS exact relative tariff threshold and retained receipt\n").hexdigest() + require(len(report["samples"]) == 2 * report["pairs"] and report["failures"] == 0, + "all complete benchmark samples succeeded") + for index, row in enumerate(report["samples"]): + require(row["arm"] == ("original", "integer")[index % 2] and + row["nanoseconds"] > 0 and row["exit_code"] == row["stderr_bytes"] == 0 and + row["stdout_sha256"] == expected, "alternating valid sample") + for arm in ("original", "integer"): + times = [row["nanoseconds"] for row in report["samples"] if row["arm"] == arm] + require(report["summary"][arm] == {"median_ns": statistics.median(times), + "min_ns": min(times), "max_ns": max(times)}, "recomputed timing summary") + saving = 1 - report["summary"]["integer"]["median_ns"] / report["summary"]["original"]["median_ns"] + require(report["reduction_fraction"] == saving and saving > 0, "recorded measured improvement") + return {"pairs": report["pairs"], "source_bound_inputs": len(report["inputs"])} + + +def main() -> None: + for name in ("exp_series.py", "replay.py", "verify.py", "benchmark.py"): + ast.parse((HERE / name).read_bytes(), filename=name) + report = {"status": "PASS_RELATIVE_TARIFF_INTEGER_EXP", + "polynomial_cases": polynomial_cases(), "complete": complete_conformance(), + "negative_controls": negative_controls(), "benchmark": benchmark_receipt()} + report["package_code_sha256"] = { + name: sha256((HERE / name).read_bytes()).hexdigest() + for name in ("exp_series.py", "replay.py", "verify.py", "benchmark.py")} + print(json.dumps(report, sort_keys=True, indent=2)) + + +if __name__ == "__main__": + main()