From c36e45b1897325517a88930f6d815d1dd9a7ef47 Mon Sep 17 00:00:00 2001 From: DominikScholz Date: Thu, 8 Oct 2026 22:12:08 +0200 Subject: [PATCH 1/2] feat(bounds): compose balanced columns with envelope carry exchanges --- research/round6-pr71/.gitignore | 1 + research/round9-balanced-columns/README.md | 55 + research/round9-balanced-columns/SOURCE.json | 14 + .../cache-stale-failure.log | 25 + .../round9-balanced-columns/coarse_graph.py | 68 ++ .../round9-balanced-columns/dense-audit.json | 28 + .../round9-balanced-columns/dense_audit.py | 53 + .../round9-balanced-columns/inherited/NOTICE | 28 + .../inherited/README.md | 90 ++ .../inherited/SOURCE.json | 64 ++ .../inherited/graph.py | 68 ++ .../inherited/vendor/pr69-compiler.py | 93 ++ .../provenance/frozen-manifest.json | 193 ++++ research/round9-balanced-columns/run.py | 102 ++ .../schedule_variant.py | 37 + .../round9-balanced-columns/screen_width.py | 59 ++ .../selected-both/MANIFEST.json | 196 ++++ .../selected-both/PROOF.md | 101 ++ .../selected-both/arithmetic.json | 945 ++++++++++++++++++ .../selected-both/comparison.json | 10 + .../selected-both/profile-23.json | 38 + .../selected-both/profile-25.json | 40 + .../selected-both/result-23.json | 79 ++ .../selected-both/result-25.json | 81 ++ .../selected-both/transitions-23.bin.json | 35 + .../selected-both/transitions-25.bin.json | 37 + .../selected-both/word-23.json.gz | Bin 0 -> 3013581 bytes .../selected-both/word-25.json.gz | Bin 0 -> 4090915 bytes .../validate_selected.py | 49 + .../validation-receipt.json | 160 +++ .../round9-balanced-columns/width_bridge.py | 22 + 31 files changed, 2771 insertions(+) create mode 100644 research/round6-pr71/.gitignore create mode 100644 research/round9-balanced-columns/README.md create mode 100644 research/round9-balanced-columns/SOURCE.json create mode 100644 research/round9-balanced-columns/cache-stale-failure.log create mode 100644 research/round9-balanced-columns/coarse_graph.py create mode 100644 research/round9-balanced-columns/dense-audit.json create mode 100644 research/round9-balanced-columns/dense_audit.py create mode 100644 research/round9-balanced-columns/inherited/NOTICE create mode 100644 research/round9-balanced-columns/inherited/README.md create mode 100644 research/round9-balanced-columns/inherited/SOURCE.json create mode 100644 research/round9-balanced-columns/inherited/graph.py create mode 100644 research/round9-balanced-columns/inherited/vendor/pr69-compiler.py create mode 100644 research/round9-balanced-columns/provenance/frozen-manifest.json create mode 100644 research/round9-balanced-columns/run.py create mode 100644 research/round9-balanced-columns/schedule_variant.py create mode 100644 research/round9-balanced-columns/screen_width.py create mode 100644 research/round9-balanced-columns/selected-both/MANIFEST.json create mode 100644 research/round9-balanced-columns/selected-both/PROOF.md create mode 100644 research/round9-balanced-columns/selected-both/arithmetic.json create mode 100644 research/round9-balanced-columns/selected-both/comparison.json create mode 100644 research/round9-balanced-columns/selected-both/profile-23.json create mode 100644 research/round9-balanced-columns/selected-both/profile-25.json create mode 100644 research/round9-balanced-columns/selected-both/result-23.json create mode 100644 research/round9-balanced-columns/selected-both/result-25.json create mode 100644 research/round9-balanced-columns/selected-both/transitions-23.bin.json create mode 100644 research/round9-balanced-columns/selected-both/transitions-25.bin.json create mode 100644 research/round9-balanced-columns/selected-both/word-23.json.gz create mode 100644 research/round9-balanced-columns/selected-both/word-25.json.gz create mode 100644 research/round9-balanced-columns/validate_selected.py create mode 100644 research/round9-balanced-columns/validation-receipt.json create mode 100644 research/round9-balanced-columns/width_bridge.py diff --git a/research/round6-pr71/.gitignore b/research/round6-pr71/.gitignore new file mode 100644 index 0000000000..1efebcb3ce --- /dev/null +++ b/research/round6-pr71/.gitignore @@ -0,0 +1 @@ +baseline/ diff --git a/research/round9-balanced-columns/README.md b/research/round9-balanced-columns/README.md new file mode 100644 index 0000000000..4521410dc9 --- /dev/null +++ b/research/round9-balanced-columns/README.md @@ -0,0 +1,55 @@ +# Balanced columns with envelope ordering and carried-signal exchanges + +The selected conditional witness has κ = **51915547765237/10^18** +(**5.1915547765237e-5**) and bit saving **3244890195589/62500000000000000**. +It combines balanced coarse columns with anchored split frames, envelope +ordering and carried-signal exchanges. Physical width is **133,585,058**, +with auxiliary role counts **27,128 / 35,598**. + +Compared with PR #74 at `5830ccfca8466aff613767222558e29b57fa8225`, the +conditional κ improves by approximately **0.163125609609%**. Compared with +PR #76 it improves by **0.3418559067%**. These are comparisons of pinned +conditional claims; no global optimality or unconditional theorem is claimed. + +[Proof and attribution](selected-both/PROOF.md) · +[Exact certificate](selected-both/arithmetic.json) · +[Source and word manifest](selected-both/MANIFEST.json) · +[Completed finite validation](validation-receipt.json) · +[Exact comparison](selected-both/comparison.json) + +Passed checks include dense scalar/data-output identities, full compiler +input/dirty bases, independent serialized-word replay in both orientations, +exact frame/event reconstruction, regenerated fixed-basis profiles with zero +CRT disagreements, independent rational moments, all 47 strict assembly +constraints and seven margins, and adjacent-grid rejection. Fresh portable +deterministic compilation and broad repository checks remain pending. + +The original validation receipt binds the original freeze manifest archived +in `provenance/frozen-manifest.json`. Runtime sources, words, profiles and +arithmetic are byte-identical to that freeze; only proof/comparison metadata +has been updated for this publication. The current manifest records those +two documentation changes. No CI configuration or dependencies are changed. + +From the repository root, restore the exact inherited source archive: + +```sh +git fetch https://github.com/CrocSwap/integer-mult-bounds.git 1bef94fd40a746452548c84a4a8f8834670a3113 +mkdir -p research/round6-pr71/baseline +git archive 1bef94fd40a746452548c84a4a8f8834670a3113 | tar -x -C research/round6-pr71/baseline +python3 research/round9-balanced-columns/dense_audit.py +python3 research/round9-balanced-columns/validate_selected.py --bundle research/round9-balanced-columns/selected-both --output /tmp/balanced-columns-validation.json +``` + +The proof gives sequential compiler regeneration commands. Use assert-enabled +Python and C++17; `CXX` can select a compiler and SDK. All inherited all-size +compiler, fixed-tape, analytic, routing, prime-selection, precision and recovery +hypotheses remain conditional. Finite checks do not establish practical speedup. + +Credit eumemic's PR #69 balanced coarse columns; huxint's PR #77 anchored +adapter; Thomas DiFiore's PR #74 envelope ordering; Chafik Boukhalfa's PR #71 +anchored splits and next-use scoring; Alejandro Zarzuelo Urdiales's PR #70 +exchanges; Rohan Arun's PR #65/#67 schedules, costs and arithmetic; Dominik +Scholz's PR #68/#76 controls and composition; Avi Eisenberg's PR #62, +eumemic's PR #57 and the complete inherited contributor chain. This composition +was prepared by Dominik Scholz with substantial OpenAI GPT-6 Astra assistance. +All original notices and Apache-2.0 terms remain preserved. diff --git a/research/round9-balanced-columns/SOURCE.json b/research/round9-balanced-columns/SOURCE.json new file mode 100644 index 0000000000..5e26581927 --- /dev/null +++ b/research/round9-balanced-columns/SOURCE.json @@ -0,0 +1,14 @@ +{ + "pr77_commit": "83298467291d3bd4b53f76faaef60dbf585be171", + "pr76_base_manifest_sha256": "52c1a59a4372376f64df937a2f19268e2ebd553574386fcdda08b01db9a5c345", + "base_pair_graph_sha256": "3d47e89d2649c90800a276bdd0480131def50e0bdf92c122a19494b55bf17420", + "base_pair_graph_matches_pr77_bytes": true, + "inherited_files": { + "inherited/SOURCE.json": "813564d76569fd54a5aa1645da15f1a33b12de8a0bcc53056e69087394b0cfcd", + "inherited/graph.py": "349c74a3684cc26c14f4b7001efb086825a4398461709ba13ade2cd10e336d23", + "inherited/NOTICE": "3bfe7a693e10fbe710e7fadedb7caeb21e272ce5899f48d043f636e2b06562b0", + "inherited/README.md": "e9d7ae955d27fb1832744583f1d251263e9fc499bae2d664b31f28fc83dc2592", + "inherited/vendor/pr69-compiler.py": "bd8169bf9f5df185a8aa4aec22234b4fd483000a1cecc78b71bf32e479af1499" + }, + "scope": "Only PR69/77 balanced coarse-column graph mechanism composed with PR76 node ordering + carry exchanges; no PR77 cost-basis compiler changes." +} diff --git a/research/round9-balanced-columns/cache-stale-failure.log b/research/round9-balanced-columns/cache-stale-failure.log new file mode 100644 index 0000000000..6667276f30 --- /dev/null +++ b/research/round9-balanced-columns/cache-stale-failure.log @@ -0,0 +1,25 @@ +Traceback (most recent call last): + File "/Users/dominik/integer-mult-bounds-incremental/research/round9-balanced-columns/run.py", line 102, in + if __name__=='__main__':main() + ~~~~^^ + File "/Users/dominik/integer-mult-bounds-incremental/research/round9-balanced-columns/run.py", line 93, in main + try:result,word=compiler.compile_(a.h,matching=True,reclaim=True,dirty=True) + ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/dominik/integer-mult-bounds-incremental/research/round6-pr71/baseline/scripts/experiments/split_pair_engine.py", line 120, in compile_ + t0=time.time();c,blocks,uses,value_uses,owner,signal,order,contains=build(h);v=len(c.inputs) + ~~~~~^^^ + File "/Users/dominik/integer-mult-bounds-incremental/research/round6-pr71/baseline/references/frame-compiler/pr65/research/reordered-rank-pair/verify.py", line 34, in build + parts=list(original(h)) + ~~~~~~~~^^^ + File "/Users/dominik/integer-mult-bounds-incremental/research/round6-pr71/baseline/scripts/experiments/split_pair_engine.py", line 39, in build + c=graph(h);groups={};owner={};signal={};blocks=[] + File "/Users/dominik/integer-mult-bounds-incremental/research/round9-balanced-columns/run.py", line 33, in + compiler.graph=lambda h: schedule_variant.reorder(coarse_graph.graph(h,coarse='columns'));compiler.build=producer.ordered_build(compiler.build,a.h) + ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/dominik/integer-mult-bounds-incremental/research/round9-balanced-columns/schedule_variant.py", line 34, in reorder + c.verify() + ~~~~~~~~^^ + File "/Users/dominik/integer-mult-bounds-incremental/research/round6-pr71/baseline/references/frame-compiler/pr48/scripts/partial_swap/shared.py", line 111, in verify + assert not A&B + ^^^^^^^ +AssertionError diff --git a/research/round9-balanced-columns/coarse_graph.py b/research/round9-balanced-columns/coarse_graph.py new file mode 100644 index 0000000000..03ac7d8723 --- /dev/null +++ b/research/round9-balanced-columns/coarse_graph.py @@ -0,0 +1,68 @@ +"""Controlled combinations of the PR62, PR69 and PR71 scalar graphs. + +PR62 graph: Avi Eisenberg with Claude assistance. PR59 split operation: +Rohan Garg. PR69 balanced coarse columns: eumemic with Codex assistance. +PR71 anchored split vector: Chafik Boukhalfa with Codex assistance. +This configurable composition/search adapter: huxint with Codex assistance. +Apache-2.0 and all inherited notices apply. No global search claim. +""" +import sys +if sys.flags.optimize: + raise ValueError('Assertions must remain enabled') +from hashlib import sha256 +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent/'round6-pr71/baseline/references/frame-compiler/pr65' +BASE = ROOT/'research/pair-assembly/pair_graph.py' +BEFORE = ''' coarse = {(i, j): self.total([e(a, b) for a in groups[i] for b in groups[j]]) + for i, j in combinations(range(ng), 2)}''' +AFTER_COLUMNS = ''' def coarse_sum(i, j): + columns = [self.total([e(a,b) for a in groups[i]]) for b in groups[j]] + return self.total(columns) + coarse = {(i,j):coarse_sum(i,j) for i,j in combinations(range(ng),2)}''' +AFTER_ROWS = ''' def coarse_sum(i, j): + rows = [self.total([e(a,b) for b in groups[j]]) for a in groups[i]] + return self.total(rows) + coarse = {(i,j):coarse_sum(i,j) for i,j in combinations(range(ng),2)}''' + + +def graph(h, groups=(1, 1, 2), anchor='first', coarse='none'): + if h not in (23, 25) or any(type(x) is not int or not 0 <= x <= 3 for x in groups): + raise ValueError('Unsupported finite graph configuration') + source = BASE.read_text() + if coarse != 'none': + assert source.count(BEFORE) == 1 + source = source.replace(BEFORE, {'columns': AFTER_COLUMNS, 'rows': AFTER_ROWS}[coarse]) + namespace = {'__file__': str(BASE), '__name__': 'next_use_graph_composition'} + exec(compile(source, str(BASE)+':next_use_composition', 'exec'), namespace) + original_class = namespace['circuit_class'] + + def circuit_class(dimension): + class SplitPair(original_class(dimension)): + def grouping(self, points): + partition = super().grouping(points) + choice = groups[self._level] if self._level < len(groups) else 0 + if len(points) > 3 and choice: + index = {1: 0, 2: (len(partition)-1)//2, 3: len(partition)-1}[choice] + if len(partition[index]) == 2: + partition[index:index+1] = [[x] for x in partition[index]] + assert all(len(g) in (1, 2) for g in partition) + assert len(partition) < len(points) + assert sorted(x for g in partition for x in g) == sorted(points) + return partition + return SplitPair + + namespace['circuit_class'] = circuit_class + original_points = namespace['alternating_points'] + if anchor != 'none': + def points(dimension, common): + old = original_points(dimension, common) + pairs = [(a, a+1) for a in range(0, dimension-1, 2) if common not in (a, a+1)] + chosen = {'first': pairs[0], 'second': pairs[min(1, len(pairs)-1)], 'last': pairs[-1]}[anchor] + result = list(chosen)+[x for x in old if x not in chosen] + assert sorted(result) == [x for x in range(dimension) if x != common] + return result + namespace['alternating_points'] = points + result = namespace['graph'](h) + result.verify() + return result diff --git a/research/round9-balanced-columns/dense-audit.json b/research/round9-balanced-columns/dense-audit.json new file mode 100644 index 0000000000..c40a04a61d --- /dev/null +++ b/research/round9-balanced-columns/dense-audit.json @@ -0,0 +1,28 @@ +{ + "scope": "Finite dense scalar/data-output identity audit", + "axes": { + "23": { + "h": 23, + "inputs": 1771, + "additions": 67460, + "outputs": 5336, + "all_dense_additions_disjoint": true, + "all_dense_partial_outputs_exact": true, + "original_common_point_envelopes_exact": true + }, + "25": { + "h": 25, + "inputs": 2300, + "additions": 94993, + "outputs": 6925, + "all_dense_additions_disjoint": true, + "all_dense_partial_outputs_exact": true, + "original_common_point_envelopes_exact": true + } + }, + "sources": { + "dense_audit.py": "b282e743d9d8c48cbc97eb2c2597a6c52894d33ea1967dd1ff4c269b0e0a72e3", + "coarse_graph.py": "b5bbabb8e5bf69769af4b6cd67163954d990dc489e3c9488ed84bd09f0a767c8", + "schedule_variant.py": "3ce3b4c0886868e3fcd2b75c54b61180d103447cfdb9d3ece1de47dd6d46eecc" + } +} diff --git a/research/round9-balanced-columns/dense_audit.py b/research/round9-balanced-columns/dense_audit.py new file mode 100644 index 0000000000..979cfe41cc --- /dev/null +++ b/research/round9-balanced-columns/dense_audit.py @@ -0,0 +1,53 @@ +"""Independent dense supports for both balanced-column scalar graphs. + +Dominik Scholz with substantial OpenAI GPT-6 Astra assistance. Apache-2.0. +Does not use the graph's memoized/provenance-based support routine. +""" +from hashlib import sha256 +from pathlib import Path +import json +import run + + +def audit(h): + c = run.schedule_variant.reorder(run.coarse_graph.graph(h, coarse='columns')) + support = [0] * len(c.args) + point_rows = [0] * h + for i, triple in enumerate(c.inputs): + support[i + 1] = 1 << i + for point in triple: + point_rows[point] |= 1 << i + additions = 0 + for node in sorted(c.active): + if not c.args[node]: + assert node <= len(c.inputs) + continue + a, b = c.args[node] + assert a < node and b < node + assert support[a] and support[b] + assert not support[a] & support[b] + support[node] = support[a] | support[b] + assert c.core[node] == c.core[a] & c.core[b] + assert c.union[node] == c.union[a] | c.union[b] + additions += 1 + for (common, target), node in c.outputs.items(): + expected = point_rows[common] + for point in target: + if point != common: + expected &= ~point_rows[point] + assert support[node] == expected + return dict(h=h, inputs=len(c.inputs), additions=additions, + outputs=len(c.outputs), all_dense_additions_disjoint=True, + all_dense_partial_outputs_exact=True, + original_common_point_envelopes_exact=True) + + +if __name__ == '__main__': + root = Path(__file__).resolve().parent + result = {'scope': 'Finite dense scalar/data-output identity audit', + 'axes': {str(h): audit(h) for h in (23, 25)}, + 'sources': {name: sha256((root/name).read_bytes()).hexdigest() + for name in ('dense_audit.py', 'coarse_graph.py', + 'schedule_variant.py')}} + (root/'dense-audit.json').write_text(json.dumps(result, indent=2) + '\n') + print(json.dumps(result, indent=2)) diff --git a/research/round9-balanced-columns/inherited/NOTICE b/research/round9-balanced-columns/inherited/NOTICE new file mode 100644 index 0000000000..be4f46cf39 --- /dev/null +++ b/research/round9-balanced-columns/inherited/NOTICE @@ -0,0 +1,28 @@ +Balanced coarse sums on anchored split frames +Prepared for huxint with substantial OpenAI Codex assistance, October 9, 2026. +Distributed under the repository's Apache License 2.0. + +The selected finite network composes previously attributed constructions. +Preserve all repository notices and these source-specific attributions: + +eumemic: PR57 joint reversible frame compiler and independent physical replay; +PR69 balanced coarse column sums, with OpenAI Codex assistance. +Avi Eisenberg / ikeboy: PR62 interval strips and core-aware pair assembly, +with Anthropic Claude assistance. +Rohan Garg / rohangar1: PR59 split-pair operation, with OpenAI Codex assistance. +Rohan Arun: PR65 schedule/refined arithmetic and PR67 profile-cost compiler, +with OpenAI Codex assistance. +Dominik Scholz: PR63 ranked composition and PR68 compatible pending controls, +with OpenAI GPT-6 Astra / Codex assistance. +Chafik Boukhalfa: PR60 ranked reclamation and PR71 anchored split graph and +next-use scoring, with OpenAI Codex assistance. + +The original code comments and preserved vendor snapshots retain their own +attributions. The inherited framework also credits icekylinx, RaD / hipotures, +James Chang, Zhihao Chen / jacklightChen, Aurel Prosz / Paureel, Swapnil Jain, +Douglas Colkitt, OpenAI, David Harvey, Joris van der Hoeven, and other +contributors identified in the root NOTICE and inherited source files. + +The new package's finite checks are conditional evidence. They are not a +complete theorem formalization, an independent human referee report, or a +practical multiplication benchmark. diff --git a/research/round9-balanced-columns/inherited/README.md b/research/round9-balanced-columns/inherited/README.md new file mode 100644 index 0000000000..bd922144c1 --- /dev/null +++ b/research/round9-balanced-columns/inherited/README.md @@ -0,0 +1,90 @@ +# Balanced coarse sums on anchored split frames + +The selected finite construction gives the conditional integer-multiplication +bound + +\[ +T(n)=O\bigl(n(\log n)^{1-\kappa}\bigr),\qquad +\kappa=\frac{12886963972497}{250000000000000000} +=5.1547855889988\times10^{-5}. +\] + +This is **0.2590891819% above PR71** at commit +`1bef94fd40a746452548c84a4a8f8834670a3113`. It is a comparison of conditional +asymptotic exponent bounds, with no global-optimality or measured-runtime claim. + +The construction combines eumemic's PR69 balanced coarse columns with Chafik +Boukhalfa's PR71 anchored `[1,1,2]` split graph. It uses the inherited joint +reversible frame compiler and compatible pending controls, and orders both +eligible live controls and retired dependency candidates by their actual +profile cost. The latter changes the temporary dependency basis, not just the +choice among the first basis's dependent rows. Pending controls are priced +against their known next use. Every selected clearing expression is emitted +as literal XORs, and all frame moves and final cleanup remain charged. + +| Quantity | Pinned PR71 | This construction | +|---|---:|---:| +| Roles at h=23 | 27,455 | 27,338 | +| Roles at h=25 | 36,015 | 35,939 | +| Physical width W | 135,075,665 | 134,671,969 | +| Complete rank mass | 77,666,660,475 | 77,434,535,275 | +| Rank deficit | 1,846,900 | 1,846,900 | + +The strict bit-saving witness is `51550513208569/10^18`. The full paid child +list of PR71 has a rigorous moment lower bound above one at this value. The +new list has a rigorous upper bound below one. Its next `10^-18` bit grid +point is rejected, as is the next kappa grid point in the unchanged balanced +assembly. All 47 strict inequalities and seven margins are checked exactly. + +## Reproduction + +From the repository root, with Python 3.11+ and a C++17 compiler: + +```sh +make -C research/balanced-split-reclamation verify +make -j1 verify +``` + +The first command regenerates both selected words byte-for-byte, independently +replays every input/target/dirty basis vector in both orientations, derives +all physical transitions from literal XOR incidences, recomputes every +fixed-basis profile with the inherited bounded-minor/CRT checks, rebuilds +the complete global profile and exact arithmetic, and runs twelve failure-mode +tests. A second logarithm/exponential evaluation uses a different range +reduction and Taylor degree. This is a second arithmetic implementation, +not independent expert review of the theorem. + +`selected/` contains the words, actual profiles, receipts and exact certificate. +`SOURCE.json` freezes consumed sources and deliverables; verification never +rewrites this manifest. `pin.py` is an explicit maintenance operation. +`generate.py --output ` produces fresh artifacts without modifying +the selected witness. The proof is in [paper.tex](paper.tex) and [paper.pdf](paper.pdf). + +The selected graph uses columns rather than a three-addition coarse chain, +split vector `[1,1,2]`, and the lowest intact pair first in each common-point +ordering. The h23 region order is `cover-core`; h25 uses `reverse-node`. +The oracle's integer entropy score is only a deterministic search heuristic. +The final complete physical profile, not the score, determines acceptance. + +## Proof boundary and attribution + +The original-envelope interpretation, all-size residual/frame compiler, +fixed finite-alphabet tape layout, semantic and analytic multiplication +reduction, routing, prime setup and exact recovery remain inherited +assumptions. The complex branch is unchanged. Exact finite checks do not +constitute a complete formal proof of the multiplication theorem. + +This composition, cost-ordered dependency basis experiment, independent +reproduction and package were prepared for **huxint with OpenAI Codex +assistance**. Credit eumemic for PR57's reversible region compiler and PR69's +coarse-column identity; Avi Eisenberg for PR62's interval/core-aware graph; +Rohan Garg for PR59's split operation; Rohan Arun for PR65's schedules and +PR67's cost oracle and numerical refinement; Dominik Scholz for PR63's +composition and PR68's compatible pending controls; and Chafik Boukhalfa for +PR60's ranked reclamation and PR71's anchored split/next-use composition. +All prior contributors retain their original notices. See [NOTICE](NOTICE). + +The preserved contributor files in `vendor/` are unmodified snapshots, used +for provenance and the complete PR71 comparison. The inherited repository +files are retained unchanged. No endorsement or completed expert review by +those contributors is implied. diff --git a/research/round9-balanced-columns/inherited/SOURCE.json b/research/round9-balanced-columns/inherited/SOURCE.json new file mode 100644 index 0000000000..cc93786f91 --- /dev/null +++ b/research/round9-balanced-columns/inherited/SOURCE.json @@ -0,0 +1,64 @@ +{ + "files": { + ".github/workflows/balanced-split.yml": "9f45519e842d7412c2c68d349252b57872a1a73e25447ca2ac63c625eb3849d3", + "references/frame-compiler/pr48/SOURCE.json": "6ccc673f88d3650d75ed600b082fe2fc2866dd88a172d182a38c1d0cd27d24b3", + "references/frame-compiler/pr48/research/copied-fixed/balanced_assembly.py": "4d27575dcad2b45a281a34054d311409ecd954f373c0c3a62c29bcc843f06a86", + "references/frame-compiler/pr48/research/copied-fixed/certificate.json": "33b3373c04e18a7f4cee33ba68da6ed71934acc3e0179cca6197696be4befa22", + "references/frame-compiler/pr48/research/copied-fixed/changed_graph.py": "375a7ca6cac6d153c1880fd5ea5b4525e5dca9d4ee3018d24d679c219b59c5b3", + "references/frame-compiler/pr48/research/copied-fixed/profiles.cpp": "b9fbd71c746609948b60c441ba4601e88436956fe636d1810f270ce4ce6a63a6", + "references/frame-compiler/pr48/research/copied-fixed/verify.py": "44932182ce6c4d39776650311262ef0ac1ea9b5da7220bc0f728e2789881f84a", + "references/frame-compiler/pr48/scripts/exclusion_circuit.py": "b253f9d7318becda1c1f3b24e2287ed44a9c27fcea00cf9d531afb950d0457a0", + "references/frame-compiler/pr48/scripts/partial_swap/binary_io.hpp": "7e143eb75bb342ac8f0c82a60005e7c35c9ec827de479bf6fb773151f3af5fa1", + "references/frame-compiler/pr48/scripts/partial_swap/paired.py": "ddcecace3a8e04d690914cbd64873ab8dde8c0c3477a255767b0ed6f639bb0c7", + "references/frame-compiler/pr48/scripts/partial_swap/shared.py": "81e9af92cdf38243a540cdcff2062778e449467848d444da37a9553c12ca4c34", + "research/balanced-split-reclamation/Makefile": "2417f68960e98c9fc5cba82511236c555a3dc8c93650da2b61a7011573d0e015", + "research/balanced-split-reclamation/NOTICE": "3bfe7a693e10fbe710e7fadedb7caeb21e272ce5899f48d043f636e2b06562b0", + "research/balanced-split-reclamation/README.md": "e9d7ae955d27fb1832744583f1d251263e9fc499bae2d664b31f28fc83dc2592", + "research/balanced-split-reclamation/arithmetic.py": "574873dd24ed83592abe198340af94918d484095c0c077c8886628200439eae6", + "research/balanced-split-reclamation/compiler.py": "8cf9687d676c7df5c2b54cb8ecc041d5dab6e5512538699d11f4f9ac5ee44409", + "research/balanced-split-reclamation/generate.py": "468ad9e2e21ffbab5ef26760c89cc429330a683d258491486e3e14a35388a805", + "research/balanced-split-reclamation/graph.py": "349c74a3684cc26c14f4b7001efb086825a4398461709ba13ade2cd10e336d23", + "research/balanced-split-reclamation/paper.pdf": "960361b250fd3033cb1b5a7c5f8ce738432a525bc4795f9bf503c28d8fcd4c42", + "research/balanced-split-reclamation/paper.tex": "875411ec7f0578c521645fb07ede2071a1b0e1b0d98c90e27c1d41abbc434538", + "research/balanced-split-reclamation/pin.py": "16734634d7856d6001a4fe8f5247bb1da47bd6852210d51c881b14afde6babc7", + "research/balanced-split-reclamation/profile_oracle.cpp": "d1f6b650de9fb5842b412595369271d9eeb6f54045c76c0fb5cad29854955c35", + "research/balanced-split-reclamation/selected/audit.json": "10040d0a140cf6185881801687985134d3b950400db73192be5e995cde4e81c7", + "research/balanced-split-reclamation/selected/certificate.json": "683bc658daf2fd4da8083c2853932ebe641607df84dcf5bb8701713a318df72f", + "research/balanced-split-reclamation/selected/compiled-23.json": "7ca13046c2a84f86d97eb056d609c8d635bff2670d2f4e622f9444e4e3f1593c", + "research/balanced-split-reclamation/selected/compiled-25.json": "05cb986a003482f7fb6c4dbc0a1a2c3984a9c06aabddb9b2ddccb53c8efd48da", + "research/balanced-split-reclamation/selected/config-23.json": "cb095dbd7005d61a6b373be96142cbc2441729458abbb0bd27c3d2d7a0ca5a1f", + "research/balanced-split-reclamation/selected/config-25.json": "64f220245ed27d529ac10dbba3cbd8a31c89544e6e730281209eabfdd09afcec", + "research/balanced-split-reclamation/selected/profile-23.json": "5df89d1595ecf78df7ce61a1e86421a46c9ccab4bf9e2d6bb774822f220ebe7d", + "research/balanced-split-reclamation/selected/profile-25.json": "6ffa4803bf1e71533bf0eabf7ea49d41466efc2d47354ad9f6f73fd6d02f8152", + "research/balanced-split-reclamation/selected/replay-23.json": "aca1abc38286c9f38667d2a7f09ca7b4db699ac813d1132fb2628d11ffe6ab29", + "research/balanced-split-reclamation/selected/replay-25.json": "9c242fbc919d2b57ac47a82f7aff85597b04e53d343aa0bcfe04dc8ad5801522", + "research/balanced-split-reclamation/selected/transitions-23.json": "2d76625e37927034195dfb2fc69b7c57b0f8b01fa72ba1de0050c10feba2c8c8", + "research/balanced-split-reclamation/selected/transitions-25.json": "007ab21779d85f7ea15abebdcaf5572767c947044cd8a90ddbb3bdb1ea9adf6d", + "research/balanced-split-reclamation/selected/word-23.json.gz": "318e7e5c767f376e587a5fe44baa05e7b7e357f01ccef178b3117cce47ab8980", + "research/balanced-split-reclamation/selected/word-25.json.gz": "8c89971f329121e77895d14171e5f156a4d7e3840c02aff80b1cbcd7aab95f23", + "research/balanced-split-reclamation/support.py": "4ad040edc00df208b4d756ef8776e9c630e3b2f6a76b07ff59c68e180d00a093", + "research/balanced-split-reclamation/test_witness.py": "f2101ba2e43ee0170bd93c119d6e5883d5e1613ff4e07923b9a90194e1a44920", + "research/balanced-split-reclamation/vendor/pr68-compiler.py": "58caca9b5336a2d50fcc45b56abfac60bbb795856b5c806ba4bfa5f649412642", + "research/balanced-split-reclamation/vendor/pr69-compiler.py": "bd8169bf9f5df185a8aa4aec22234b4fd483000a1cecc78b71bf32e479af1499", + "research/balanced-split-reclamation/vendor/pr71-certificate.json": "0fcb53fa374273efab6370953c966e8fa065dbfdba43691843a4788cb2cda42e", + "research/balanced-split-reclamation/vendor/pr71-graph.py": "9d4ee7179f880f9576e81c7ad3a5290fe61380a7531d559ef3cf0939bb30089c", + "research/balanced-split-reclamation/verify.py": "a205f2f73cd07cd6af94a4cf11f2c669cdd18b44fcd810df0ac6193eaff5a613", + "research/pair-assembly/frame/frame-compiler.json": "86eeb10989a61e571938178b91dfe1b81ba39ec97cc93124c00cecd91dc6ef13", + "research/pair-assembly/frame/frame_verify.py": "fafe25d57166a747eeb847444a2e02dd7eed19038b93a2c495014d147d04a8fb", + "research/pair-assembly/pair_graph.py": "3d47e89d2649c90800a276bdd0480131def50e0bdf92c122a19494b55bf17420", + "scripts/exclusion_circuit.py": "b253f9d7318becda1c1f3b24e2287ed44a9c27fcea00cf9d531afb950d0457a0", + "scripts/experiments/binary_frame_math.py": "1f96e8aafc8ae89f8eeec5d03800131d93d58e01bf8a7fca8feb03702d1740d0", + "scripts/experiments/binary_frame_profile_prepare.py": "8a50381cab00b33e62b3a057d199ba5e19647929135c95b0fd63fc8a8ef7c9b3", + "scripts/experiments/binary_frame_profiles.cpp": "8e2e391d3ee57cbb1372c68e4aa031e1b861321536eabd642ada54e12e678669", + "scripts/experiments/binary_frame_replay.py": "392e78e62d7685c99a5888a7da743ea6c3dcad631af4a743c91e0c09348442bc", + "scripts/partial_swap/paired.py": "ddcecace3a8e04d690914cbd64873ab8dde8c0c3477a255767b0ed6f639bb0c7", + "scripts/partial_swap/shared.py": "81e9af92cdf38243a540cdcff2062778e449467848d444da37a9553c12ca4c34" + }, + "scope": "Explicit source and artifact freeze; no automatic refresh in verification", + "upstream": { + "pr67": "b3745601e947a94316bf25c2c6263d93c06e3364", + "pr68": "8778fdb52e834a2a14371590d80ea6e0c734a866", + "pr69": "91aa1f17e6e3fc063241686a41a34ddd0dc24c50", + "pr71": "1bef94fd40a746452548c84a4a8f8834670a3113" + } +} diff --git a/research/round9-balanced-columns/inherited/graph.py b/research/round9-balanced-columns/inherited/graph.py new file mode 100644 index 0000000000..ba0382efaa --- /dev/null +++ b/research/round9-balanced-columns/inherited/graph.py @@ -0,0 +1,68 @@ +"""Controlled combinations of the PR62, PR69 and PR71 scalar graphs. + +PR62 graph: Avi Eisenberg with Claude assistance. PR59 split operation: +Rohan Garg. PR69 balanced coarse columns: eumemic with Codex assistance. +PR71 anchored split vector: Chafik Boukhalfa with Codex assistance. +This configurable composition/search adapter: huxint with Codex assistance. +Apache-2.0 and all inherited notices apply. No global search claim. +""" +import sys +if sys.flags.optimize: + raise ValueError('Assertions must remain enabled') +from hashlib import sha256 +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +BASE = ROOT/'research/pair-assembly/pair_graph.py' +BEFORE = ''' coarse = {(i, j): self.total([e(a, b) for a in groups[i] for b in groups[j]]) + for i, j in combinations(range(ng), 2)}''' +AFTER_COLUMNS = ''' def coarse_sum(i, j): + columns = [self.total([e(a,b) for a in groups[i]]) for b in groups[j]] + return self.total(columns) + coarse = {(i,j):coarse_sum(i,j) for i,j in combinations(range(ng),2)}''' +AFTER_ROWS = ''' def coarse_sum(i, j): + rows = [self.total([e(a,b) for b in groups[j]]) for a in groups[i]] + return self.total(rows) + coarse = {(i,j):coarse_sum(i,j) for i,j in combinations(range(ng),2)}''' + + +def graph(h, groups=(1, 1, 2), anchor='first', coarse='none'): + if h not in (23, 25) or any(type(x) is not int or not 0 <= x <= 3 for x in groups): + raise ValueError('Unsupported finite graph configuration') + source = BASE.read_text() + if coarse != 'none': + assert source.count(BEFORE) == 1 + source = source.replace(BEFORE, {'columns': AFTER_COLUMNS, 'rows': AFTER_ROWS}[coarse]) + namespace = {'__file__': str(BASE), '__name__': 'next_use_graph_composition'} + exec(compile(source, str(BASE)+':next_use_composition', 'exec'), namespace) + original_class = namespace['circuit_class'] + + def circuit_class(dimension): + class SplitPair(original_class(dimension)): + def grouping(self, points): + partition = super().grouping(points) + choice = groups[self._level] if self._level < len(groups) else 0 + if len(points) > 3 and choice: + index = {1: 0, 2: (len(partition)-1)//2, 3: len(partition)-1}[choice] + if len(partition[index]) == 2: + partition[index:index+1] = [[x] for x in partition[index]] + assert all(len(g) in (1, 2) for g in partition) + assert len(partition) < len(points) + assert sorted(x for g in partition for x in g) == sorted(points) + return partition + return SplitPair + + namespace['circuit_class'] = circuit_class + original_points = namespace['alternating_points'] + if anchor != 'none': + def points(dimension, common): + old = original_points(dimension, common) + pairs = [(a, a+1) for a in range(0, dimension-1, 2) if common not in (a, a+1)] + chosen = {'first': pairs[0], 'second': pairs[min(1, len(pairs)-1)], 'last': pairs[-1]}[anchor] + result = list(chosen)+[x for x in old if x not in chosen] + assert sorted(result) == [x for x in range(dimension) if x != common] + return result + namespace['alternating_points'] = points + result = namespace['graph'](h) + result.verify() + return result diff --git a/research/round9-balanced-columns/inherited/vendor/pr69-compiler.py b/research/round9-balanced-columns/inherited/vendor/pr69-compiler.py new file mode 100644 index 0000000000..271b44d795 --- /dev/null +++ b/research/round9-balanced-columns/inherited/vendor/pr69-compiler.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +"""Balance each four-edge coarse sum in PR62 into two column pair-star sums. + +Instead of a three-addition chain, use (e(a,b)+e(a2,b))+(e(a,b2)+e(a2,b2)). +The existing interning shares pair-star sums with the strip computations. +Only the coarse-edge construction changes. The full graph is checked and +compiled, so all remaining copies and clearing operations remain charged. + +Base graph: Avi Eisenberg / ikeboy, with Anthropic Claude assistance (#62). +Compiler: eumemic with OpenAI Codex assistance (#57). Rank priority: Chafik +Boukhalfa with OpenAI Codex assistance (#60). Their unchanged composition +is also published by Dominik Scholz with OpenAI Codex assistance (#63). +This coarse-sum experiment was prepared with OpenAI Codex assistance. +All inherited licenses and notices remain. +""" +import sys +sys.dont_write_bytecode = True +if sys.flags.optimize: + raise ValueError('Assertions must remain enabled') +import argparse +import gzip +from hashlib import sha256 +import inspect +import json +from pathlib import Path + +import binary_frame_compiler as compiler +import ranked_interval_compiler as predecessor + +ROOT = Path(__file__).resolve().parents[2] +PIN = ROOT / 'references/frame-compiler/balanced-coarse' +BEFORE = ''' coarse = {(i, j): self.total([e(a, b) for a in groups[i] for b in groups[j]]) + for i, j in combinations(range(ng), 2)}''' +AFTER = ''' def coarse_sum(i, j): + columns = [self.total([e(a,b) for a in groups[i]]) for b in groups[j]] + return self.total(columns) + coarse = {(i,j):coarse_sum(i,j) for i,j in combinations(range(ng),2)}''' + + +def check_sources(): + predecessor.check_sources() + manifest = json.loads((PIN / 'SOURCE.json').read_text()) + for name, digest in manifest['files'].items(): + assert sha256((PIN / name).read_bytes()).hexdigest() == digest, name + dependency = PIN / manifest['shared_dependency_manifest'] + assert sha256(dependency.read_bytes()).hexdigest() == manifest['shared_dependency_manifest_sha256'] + return manifest + + +def graph(h): + assert h in (23, 25) + check_sources() + path = predecessor.PIN / 'research/pair-assembly/pair_graph.py' + source = path.read_text() + assert source.count(BEFORE) == 1 + namespace = {'__file__': str(path), '__name__': 'balanced_coarse_pr62'} + exec(compile(source.replace(BEFORE, AFTER), str(path) + ':balanced_coarse', 'exec'), namespace) + result = namespace['graph'](h) + result.verify() + return result + + +def compile_axis(h): + circuit = graph(h) + source = inspect.getsource(compiler.compile_) + before = 'for s in sorted(retired):' + after = "for s in sorted(retired, key=lambda s: (-blocks[frames[s]]['rank'], s)):" + assert source.count(before) == 1 + namespace = dict(vars(compiler)) + exec(compile(source.replace(before, after), __file__ + ':ranked_compile', 'exec'), namespace) + # build() is the original function and resolves graph in compiler's globals. + previous = compiler.graph + compiler.graph = lambda _: circuit + try: + result, word = namespace['compile_'](h, matching=True, reclaim=True, dirty=True) + finally: + compiler.graph = previous + result['scalar'] = circuit.verify() + result['baseline_pr62_stacked_roles'] = {23: 27918, 25: 36586}[h] + return result, word + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--h', type=int, choices=(23, 25), required=True) + parser.add_argument('--output', type=Path, required=True) + parser.add_argument('--word', type=Path, required=True) + args = parser.parse_args() + result, word = compile_axis(args.h) + raw = (json.dumps(word, separators=(',', ':')) + '\n').encode() + args.word.write_bytes(gzip.compress(raw, mtime=0)) + args.output.write_text(json.dumps(result, indent=2) + '\n') + print(json.dumps(result), flush=True) diff --git a/research/round9-balanced-columns/provenance/frozen-manifest.json b/research/round9-balanced-columns/provenance/frozen-manifest.json new file mode 100644 index 0000000000..c269419787 --- /dev/null +++ b/research/round9-balanced-columns/provenance/frozen-manifest.json @@ -0,0 +1,193 @@ +{ + "baseline_files": { + "certificates/split-pair-compiler.json": "6561fab8609e8aa3a291a8197cd8b834b0881ee0b9a5b991926c2c93c4d5f884", + "certificates/split-pair-kappa.json": "0fcb53fa374273efab6370953c966e8fa065dbfdba43691843a4788cb2cda42e", + "certificates/split-pair-profiles-23.json": "867302152b62abf28a6e1b119580b99eaffa237082b1d295000a3ee2637d5db4", + "certificates/split-pair-profiles-25.json": "1ecc63972ae4df2ed7af7278d5f65790dd4aca3032cc17304f39ac063cd2c067", + "certificates/split-pair-repository-validation.json": "a4700ef48968e0bc6afadf8048d82bb4f4cfc9f21db9a8bf355bd9c2745da53e", + "certificates/split-pair-transitions-23.json": "6ca709c1e101f7c9a828d9ceb8a7f2991a2d954b84c9ae8c616deabfc1e321c8", + "certificates/split-pair-transitions-25.json": "4364441b6a7c444bb2c84ab5b973c81e4069d753be7f1cf5a3c836096a739f1e", + "certificates/split-pair-validation.json": "9b64dd6382fc592e2cda6bb54be27ba8f705ede24c50fd2f9b4336ce2e402c7e", + "certificates/split-pair-word-23.json.gz": "ca504cb3912358a9560d4916eaeea2e415c24991db0bc7d397e50ea53d9cb24b", + "certificates/split-pair-word-25.json.gz": "54f612f688d6ba3b1fffdd83aa6053035006fee90cb4b3899fc7880f35c38b4f", + "references/frame-compiler/pr48/LICENSE": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4", + "references/frame-compiler/pr48/NOTICE": "dfc4c460aad4eb08d7b980792bd78d6258b24fa166272d50e2e7cdf58507de4e", + "references/frame-compiler/pr48/SOURCE.json": "6ccc673f88d3650d75ed600b082fe2fc2866dd88a172d182a38c1d0cd27d24b3", + "references/frame-compiler/pr48/research/copied-fixed/balanced_assembly.py": "4d27575dcad2b45a281a34054d311409ecd954f373c0c3a62c29bcc843f06a86", + "references/frame-compiler/pr48/research/copied-fixed/certificate.json": "33b3373c04e18a7f4cee33ba68da6ed71934acc3e0179cca6197696be4befa22", + "references/frame-compiler/pr48/research/copied-fixed/changed_graph.py": "375a7ca6cac6d153c1880fd5ea5b4525e5dca9d4ee3018d24d679c219b59c5b3", + "references/frame-compiler/pr48/research/copied-fixed/profiles.cpp": "b9fbd71c746609948b60c441ba4601e88436956fe636d1810f270ce4ce6a63a6", + "references/frame-compiler/pr48/research/copied-fixed/verify.py": "44932182ce6c4d39776650311262ef0ac1ea9b5da7220bc0f728e2789881f84a", + "references/frame-compiler/pr48/scripts/exclusion_circuit.py": "b253f9d7318becda1c1f3b24e2287ed44a9c27fcea00cf9d531afb950d0457a0", + "references/frame-compiler/pr48/scripts/partial_swap/binary_io.hpp": "7e143eb75bb342ac8f0c82a60005e7c35c9ec827de479bf6fb773151f3af5fa1", + "references/frame-compiler/pr48/scripts/partial_swap/paired.py": "ddcecace3a8e04d690914cbd64873ab8dde8c0c3477a255767b0ed6f639bb0c7", + "references/frame-compiler/pr48/scripts/partial_swap/shared.py": "81e9af92cdf38243a540cdcff2062778e449467848d444da37a9553c12ca4c34", + "references/frame-compiler/pr59-split-operation/LICENSE": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4", + "references/frame-compiler/pr59-split-operation/NOTICE": "f85437ee441f2a028660dd5e8dbdc0ec7b52bb55c04ea34fa4829c154bfd0ac1", + "references/frame-compiler/pr59-split-operation/SOURCE.json": "bd0c5dd41b7fc797c8c28b7c738f6c4d709103908e1394c3dee18ecaf39ba38d", + "references/frame-compiler/pr59-split-operation/research/split-skip/SOURCE.json": "7c2b4646a3ecfef6f881da5c43e4bd0fa9a4d1b00548b8ab458d897e16735134", + "references/frame-compiler/pr59-split-operation/research/split-skip/split_graph.py": "9b16ba907cbd58611fb64bfb9211be7809d54822d44c78fc6167cf4ba79eb905", + "references/frame-compiler/pr65/LICENSE": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4", + "references/frame-compiler/pr65/NOTICE": "5931cb7d43e09380594b113018cac70258fb66e0673b91f706b01ea482c1be1a", + "references/frame-compiler/pr65/SOURCE.json": "6ad67c1dbbc9f10fd4cf3d396405e3d02364ead5fb56961f01da7f8200d55c8a", + "references/frame-compiler/pr65/references/frame-compiler/pr48/SOURCE.json": "6ccc673f88d3650d75ed600b082fe2fc2866dd88a172d182a38c1d0cd27d24b3", + "references/frame-compiler/pr65/references/frame-compiler/pr48/research/copied-fixed/balanced_assembly.py": "4d27575dcad2b45a281a34054d311409ecd954f373c0c3a62c29bcc843f06a86", + "references/frame-compiler/pr65/references/frame-compiler/pr48/research/copied-fixed/certificate.json": "33b3373c04e18a7f4cee33ba68da6ed71934acc3e0179cca6197696be4befa22", + "references/frame-compiler/pr65/references/frame-compiler/pr48/research/copied-fixed/changed_graph.py": "375a7ca6cac6d153c1880fd5ea5b4525e5dca9d4ee3018d24d679c219b59c5b3", + "references/frame-compiler/pr65/references/frame-compiler/pr48/research/copied-fixed/profiles.cpp": "b9fbd71c746609948b60c441ba4601e88436956fe636d1810f270ce4ce6a63a6", + "references/frame-compiler/pr65/references/frame-compiler/pr48/research/copied-fixed/verify.py": "44932182ce6c4d39776650311262ef0ac1ea9b5da7220bc0f728e2789881f84a", + "references/frame-compiler/pr65/references/frame-compiler/pr48/scripts/exclusion_circuit.py": "b253f9d7318becda1c1f3b24e2287ed44a9c27fcea00cf9d531afb950d0457a0", + "references/frame-compiler/pr65/references/frame-compiler/pr48/scripts/partial_swap/binary_io.hpp": "7e143eb75bb342ac8f0c82a60005e7c35c9ec827de479bf6fb773151f3af5fa1", + "references/frame-compiler/pr65/references/frame-compiler/pr48/scripts/partial_swap/paired.py": "ddcecace3a8e04d690914cbd64873ab8dde8c0c3477a255767b0ed6f639bb0c7", + "references/frame-compiler/pr65/references/frame-compiler/pr48/scripts/partial_swap/shared.py": "81e9af92cdf38243a540cdcff2062778e449467848d444da37a9553c12ca4c34", + "references/frame-compiler/pr65/research/pair-assembly/PROOF.md": "30685624bf922bb9d9f7ed4b0d367a660fe373cc9ee28fec33585bd8c7023e75", + "references/frame-compiler/pr65/research/pair-assembly/SOURCE.json": "8f8c0fb7ca012ec5092136744eb52a0222697a8275d14aa8f667339c86baf9d0", + "references/frame-compiler/pr65/research/pair-assembly/frame/frame-compiler.json": "86eeb10989a61e571938178b91dfe1b81ba39ec97cc93124c00cecd91dc6ef13", + "references/frame-compiler/pr65/research/pair-assembly/frame/frame_verify.py": "fafe25d57166a747eeb847444a2e02dd7eed19038b93a2c495014d147d04a8fb", + "references/frame-compiler/pr65/research/pair-assembly/pair_graph.py": "3d47e89d2649c90800a276bdd0480131def50e0bdf92c122a19494b55bf17420", + "references/frame-compiler/pr65/research/reordered-rank-pair/README.md": "13fbcfe41a4cb22ea6f1d59c98305add85a86a4db4677ab3450fd34b139cf39c", + "references/frame-compiler/pr65/research/reordered-rank-pair/arithmetic/README.md": "93a1e4eb52ff3b3f3b24464ce1e7b5498fac2da2789cab5deb76e7342fe36775", + "references/frame-compiler/pr65/research/reordered-rank-pair/arithmetic/audit-receipt.json": "f481198b192790b65dde2f93a837fb5e2e7508322f25bbf26f73530febd1f659", + "references/frame-compiler/pr65/research/reordered-rank-pair/arithmetic/audit.py": "aa297fffcdaa133f5dee17d97fac72aa5ba2cf943da5a8a5e3f4d62f6f0a7f79", + "references/frame-compiler/pr65/research/reordered-rank-pair/arithmetic/certificate.json": "6474f4c638b5a16de5a7ed6054f3ad28404eac17eaa4570aab2ef378d6e7e1a3", + "references/frame-compiler/pr65/research/reordered-rank-pair/arithmetic/refine.py": "e0488c919e76850313ff93d7da704a7fcc14a316eee2cac81e2b8dff9c145b5d", + "references/frame-compiler/pr65/research/reordered-rank-pair/arithmetic/test_arithmetic.py": "d4824c8c1cc6c726daf9104c820aefe1e57ce6a8625871954a54a538b5af0524", + "references/frame-compiler/pr65/research/reordered-rank-pair/current-comparison.json": "be8713b049b34b41d82ef3e03380f6b45d7b33bf8611af9942dea7597406dc07", + "references/frame-compiler/pr65/research/reordered-rank-pair/frame-compiler.json": "48f86ffe2c2a16d3817ed3ab814cd1442442ec15f827d43a7383a0a953ff4337", + "references/frame-compiler/pr65/research/reordered-rank-pair/frame-profiles-23.json": "fec377bcf1512a427674983256b900229d4133026445b6e680c6e1e6dde5af7d", + "references/frame-compiler/pr65/research/reordered-rank-pair/frame-profiles-25.json": "28b4b911e26fbc02dde0d2e1458ed16227f756126ab8144d6d45e164d1165262", + "references/frame-compiler/pr65/research/reordered-rank-pair/frame-transitions-23.json": "86646f1110595294cccc15603c552f0a153574a690b69c3b144d84a449891103", + "references/frame-compiler/pr65/research/reordered-rank-pair/frame-transitions-25.json": "c333c348665d12b95e168ca4fac48bfdca335104edd0f29c81fe94bec292e774", + "references/frame-compiler/pr65/research/reordered-rank-pair/frame-word-23.json.gz": "a44e038e1c548ea8ac31dd04acc2bba7951b22e17df7b7ad3464ea2b504a8da4", + "references/frame-compiler/pr65/research/reordered-rank-pair/frame-word-25.json.gz": "ad8b299697f90b185b6b791313b505586be97965519052100d097df6199e00c5", + "references/frame-compiler/pr65/research/reordered-rank-pair/paired-candidate.json": "34a500d739537235dfc5d24325c22856ca4567b9eac998a3bce9b13db5501940", + "references/frame-compiler/pr65/research/reordered-rank-pair/test_negative.py": "88832242e6f74e3fe08d109d4f21ff188a9ca0ae50c3e8f31da0243fe9501510", + "references/frame-compiler/pr65/research/reordered-rank-pair/verify.py": "e84ed21dad24f9b8c429441caae49c13ccae883be2f04e696993cfe665b57352", + "references/frame-compiler/pr65/scripts/exclusion_circuit.py": "b253f9d7318becda1c1f3b24e2287ed44a9c27fcea00cf9d531afb950d0457a0", + "references/frame-compiler/pr65/scripts/experiments/binary_frame_math.py": "1f96e8aafc8ae89f8eeec5d03800131d93d58e01bf8a7fca8feb03702d1740d0", + "references/frame-compiler/pr65/scripts/experiments/binary_frame_profile_prepare.py": "8a50381cab00b33e62b3a057d199ba5e19647929135c95b0fd63fc8a8ef7c9b3", + "references/frame-compiler/pr65/scripts/experiments/binary_frame_profiles.cpp": "8e2e391d3ee57cbb1372c68e4aa031e1b861321536eabd642ada54e12e678669", + "references/frame-compiler/pr65/scripts/experiments/binary_frame_replay.py": "392e78e62d7685c99a5888a7da743ea6c3dcad631af4a743c91e0c09348442bc", + "references/frame-compiler/pr65/scripts/experiments/rank_pair_compiler.py": "9984aaccf880e4840402322d76678bfddb33ce7e494af78430a43429f51b85fd", + "references/frame-compiler/pr65/scripts/partial_swap/paired.py": "ddcecace3a8e04d690914cbd64873ab8dde8c0c3477a255767b0ed6f639bb0c7", + "references/frame-compiler/pr65/scripts/partial_swap/shared.py": "81e9af92cdf38243a540cdcff2062778e449467848d444da37a9553c12ca4c34", + "references/frame-compiler/pr67/LICENSE": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4", + "references/frame-compiler/pr67/NOTICE": "5931cb7d43e09380594b113018cac70258fb66e0673b91f706b01ea482c1be1a", + "references/frame-compiler/pr67/SOURCE.json": "6c103bd7e29cb737003d0bfa42c541a4eea2f3618bfff980992eeab1b8c16e70", + "references/frame-compiler/pr67/research/slot-cost-rank-pair/README.md": "e0fcd8e732c8b8becb3d860eb83dc979ed5e6b33ba16caf9dca1e44f7929c340", + "references/frame-compiler/pr67/research/slot-cost-rank-pair/arithmetic/certificate.json": "e66f955f1b76ce3db7ecb84294993a072f42f972b8f3040015c12e6dc953d698", + "references/frame-compiler/pr67/research/slot-cost-rank-pair/compiler.py": "29296211e0532aaf19101a6b2f2ceaebe374af95ae3acd63e63656db0afef7ae", + "references/frame-compiler/pr67/research/slot-cost-rank-pair/frame-compiler.json": "eb5c0b401e677d3958ecfcd6d8de3bc825c4fb66d1cf79c3fcbcf23938ca6e69", + "references/frame-compiler/pr67/research/slot-cost-rank-pair/paired-candidate.json": "be0322ad60f73923953f242eaffaf114ff12438e8617dae38888b77fa03184cc", + "references/frame-compiler/pr67/research/slot-cost-rank-pair/profile_oracle.cpp": "d1f6b650de9fb5842b412595369271d9eeb6f54045c76c0fb5cad29854955c35", + "references/frame-compiler/pr67/research/slot-cost-rank-pair/verify.py": "3c1d2eac9d3d2f13b60503deaa84e11ab2975aa84af71c8ad74584c5902b2d77", + "references/frame-compiler/pr68/LICENSE": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4", + "references/frame-compiler/pr68/NOTICE": "d9db68e85db965bf7037d535ddc354b096b7c3b8f4cb0eb4887dc61eba5eae23", + "references/frame-compiler/pr68/SOURCE.json": "6473ccc29182212770ae4fd747b50a607c2a9b302e21c5c4355ec1b25bafe2e2", + "references/frame-compiler/pr68/research/global-anchor-screen/PROOF.md": "3023c8c039acb3afc2a1e0c2ee55dcffaa4a1a2961076222ae20b03d0f3c6a38", + "references/frame-compiler/pr68/research/global-anchor-screen/SOURCE.json": "f6249b8f91c7721a59ecc6d43a3f2ec65162578203bd430ef76732a3937399f3", + "references/frame-compiler/pr68/research/global-anchor-screen/compiler-frozen.py": "12d646fa9ad69e4f3c532fe69080d8fe1509cde0968a6ab52a9d60273803adc0", + "references/frame-compiler/pr68/research/global-anchor-screen/selected-manifest.json": "97bd86fc20fb3aee2d1adacd6a485b12e918b7340d2d3ca70e1318889e13e3a0", + "references/frame-compiler/pr68/research/global-anchor-screen/selected_compile.py": "86bdfcf599c6b131e376773fe177bca57a9f63c9b60bad5de8aa00982d779b22", + "research/split-pair/PROOF.md": "467d4819e9f2db61f8ea7f270b8b6696d99f7980d762aad0d19beced5e24a82a", + "research/split-pair/README.md": "6efd6ed7d3ee72167bea586f3186bcc5973493d6560152c4bb66d15fbaeb5c2d", + "research/split-pair/SOURCE.json": "9d5a4a7c4cf459f4c5731809de93cfb4b873cb8c9ea95a1be9239733a9a93c72", + "research/split-pair/config-23.json": "9a2cbaf8de500722844bc8dff09fb994a00d47b0319b3aad4e612435c32308b6", + "research/split-pair/config-25.json": "706c5998f8414d495e4da8cdcf4fe7c718762649967f16b36513826df6df5b13", + "research/split-pair/engine-changes.patch": "47c612dad40164b04fa7ade38012c904d81785688dad2640daa0c9ccaaeeb48f", + "research/split-pair/engine-provenance.json": "a56ea22dafee35523fcff9d0e046cc437b91ee4410f00300a887319d58a1ffaf", + "research/split-pair/parameters.json": "d1385be76dd427d621d73760161c9e87b9d4a0a927a94df0b3fe450f3cd67e24", + "scripts/experiments/affine_vector_screens.py": "756778eeca27f490adc7354a122dc50c40375156259991469c47a90949118ea1", + "scripts/experiments/affine_vector_witnesses.json": "672a4318c48f5286ce088d34736c38957b7f662a5f753d440dbc638e7da5f62a", + "scripts/experiments/balanced_fano.py": "1586fb1db4f40e79e97bae59f47192675663403bbcacbf5f4e0b702edfd22b0a", + "scripts/experiments/binary_frame_compiler.py": "bc6910c8bbe8224285164323d3c06e9035ad3eaa55416abc2867ae0066454a0c", + "scripts/experiments/binary_frame_math.py": "1f96e8aafc8ae89f8eeec5d03800131d93d58e01bf8a7fca8feb03702d1740d0", + "scripts/experiments/binary_frame_profile_prepare.py": "8a50381cab00b33e62b3a057d199ba5e19647929135c95b0fd63fc8a8ef7c9b3", + "scripts/experiments/binary_frame_profiles.cpp": "8e2e391d3ee57cbb1372c68e4aa031e1b861321536eabd642ada54e12e678669", + "scripts/experiments/binary_frame_replay.py": "392e78e62d7685c99a5888a7da743ea6c3dcad631af4a743c91e0c09348442bc", + "scripts/experiments/bit_compression.py": "d1e6726341b3619262cc07246c3420584f46bdf57d44f1946d8dab18334cbca8", + "scripts/experiments/block_completion.py": "58d928accb928fff0230eef4901a876e6d7a2ec24a3694e4784614f340a03b8d", + "scripts/experiments/block_core.py": "af94018e8f4b80219a8e9e104eae21e34b66fc670217d03ef54862b59c051fc9", + "scripts/experiments/complex_centers.py": "3744396587d729253d80980f6310b56e7bf0ea21b165bd178d0d6d4c49faf2e2", + "scripts/experiments/core_limits.py": "a31a27cc24cf0349a507d1141a2b965ea25f1c60f355d7e13c581305a12d3a43", + "scripts/experiments/cube_core_family.py": "e58f1f4067bda2d4838343f42ec2505316f006561f0702e869847d88b85413a8", + "scripts/experiments/disjoint_tensor.py": "102dd59bf96033f96ba0dab4c2aba77b3a7a73b67b0f96929ff8b20a98b91cd8", + "scripts/experiments/early_sharing.py": "1dd42768536bac13727528e51a999152cf9516a53c4001f2c390323e7f453378", + "scripts/experiments/exclusion_greedy.py": "d8fa918119a6d944174522a5f7a2f55dc9f905aeca98e1864dc9bbf672876902", + "scripts/experiments/fano_completion.py": "6cade2a36b910bf7e68a872dc4fd3560837935cffe80f9526cd012a28b247738", + "scripts/experiments/fano_permuted_completion.py": "0b48e0ba6399ac9864b733998ff32222e7c25c99de052ab8ea5196872f8010d4", + "scripts/experiments/fano_permuted_routing_witnesses.json": "b7093d006713f0b026c49b62ac4c502731630d17d15f56a2b63284ad8f4f8102", + "scripts/experiments/fano_routing_witnesses.json": "2017a4401c16ac58ccd7911b1d2128f1a93a98b108672db709e0c21cda4bb693", + "scripts/experiments/inplace_side.py": "4e7cb3df2e263f6c7f5907c55e3ee04c08926e6dbc984bbda1722a27b0a48ff6", + "scripts/experiments/inplace_side_witnesses.json": "90fe710f5daa35cc9e4892b29d712d66110b7b2b4c404da95a960ea7041618b9", + "scripts/experiments/intersection_circuit.py": "a877cb59aca1f003fc5db4bff5cd873af57be6d8d2465835d6fbe2c396ee5c09", + "scripts/experiments/intersection_greedy.py": "e7faceecad5d1efdc849c52ebe7258453e1579308fc8e31d9a4b3256f6ca9d0e", + "scripts/experiments/joint_dual_compiler.py": "853d3fc4a740c5b74c23b3a6af5d4dc9b41fb38e9b55678539a7e0ee71947c13", + "scripts/experiments/joint_dual_compose.py": "741900aa6f69c0e3458700f3b534334269004ad80c50405ecfeda18e6d3f2800", + "scripts/experiments/joint_dual_reclaim_compiler.py": "9984aaccf880e4840402322d76678bfddb33ce7e494af78430a43429f51b85fd", + "scripts/experiments/mixed_point_circuit.py": "f509362b5031976a22af351fd158ae0b4520fa4f286a5176ec37023d672a7ddc", + "scripts/experiments/parity_phase_repair.py": "1f76f3b96ed556ed901835bd101d0e2588c997d2ed39bdfca097f0187aa86d40", + "scripts/experiments/parity_side.py": "1363ebf82d4c39e458e7bede8253688271008374db70ed4284df84253c8d092b", + "scripts/experiments/partial_routing.py": "dd67bf46aa70f1372d49c30c4fbbaff5664e27331a79ca3319251ceeec11ec00", + "scripts/experiments/pin_joint_dual_sources.py": "4d31cc0e38b7902709ca5f8f714cba109760d2592346dd7f8dc0b900a2d9fe00", + "scripts/experiments/pin_split_pair_sources.py": "511618d0095435ced888c2d2dd78fb92e59f10866160c787acb354da6cfe4b44", + "scripts/experiments/positive_side_core.py": "0d453ab7e869d2cf6a43d6865de82583edb390d3c75038271f0fc09e0f3828ba", + "scripts/experiments/prime_core.py": "080a89a2c91505b509068698542843c9d7af3cdec01b5c88972107dc9c688c62", + "scripts/experiments/prime_subset_limits.py": "3768743ebfd982b7704fdda9c8ee8dd8cfbb4fd126a78396349d075560c047fb", + "scripts/experiments/probe_pair_ranked.py": "aed43df0d61701b5819cd50fd4e028b26f32e65fd7b9074d93e1423a3453fe7d", + "scripts/experiments/quadratic_affine.py": "8f9252bd092eb14779997c6767e090377e91f4d57e6526e9840ae0dd7dcc8f9c", + "scripts/experiments/quadratic_affine_witnesses.json": "3efcebf41650681a8a21a901cd2f81dc07a0c4d28064b883af16b10c3e0036c3", + "scripts/experiments/rank_product_core.py": "7a91c1188c5d42e864a5d2e42397b09c435b526ae4f4210c44bf615de488708e", + "scripts/experiments/shared_core.py": "d3c59b61229956cb54ae1ef9145ed213abdf1ae743929de145a77c43656f01a8", + "scripts/experiments/signed_sparse_core.py": "21da8e1de5ab6ac8479183326c2000313d24b47cc5be2f46b4fe6ac3cd59779f", + "scripts/experiments/single_intersection.py": "08ddae46e5621a5b4c525b504e67ae655abe9b49461d894feaa7abc89a51847d", + "scripts/experiments/single_intersection_witnesses.json": "c2308a3d21991f5828b0519b191b470f48b2fbbcaa5af0f7aed3986cc7534185", + "scripts/experiments/skip_frame_README.txt": "c92a53e608edb95a266ad27f4543c27668451a009c72fd5860619e6f0a355852", + "scripts/experiments/skip_frame_compiler.py": "8ffd079fd2e4f055b5befefecc5f33e686de9898219e9252f5d3913df8b195d8", + "scripts/experiments/skip_frame_compose.py": "d48e688ebb9a490f4eaf50d9ab0a4d4e3e76b6588b55d213df14c703c27a7f66", + "scripts/experiments/split_pair_arithmetic.py": "fb982a0ac8758b2e308dc8bd145f21548c28f4f2ee97d28e77fa849b9560de4a", + "scripts/experiments/split_pair_compiler.py": "3de0ececd6ab108d8780834c3f1a1a84ce7cae49dca4019882bea7f63b588661", + "scripts/experiments/split_pair_compose.py": "9c6337096d5517344cc5029bd80a1379fa407047662ab54c469db7b11e9daa34", + "scripts/experiments/split_pair_engine.py": "58f13f82ce1bb7f2b5549e17628bc6034e5e05cb24db2acb9a91c24820872f70", + "scripts/experiments/split_pair_graph.py": "9d4ee7179f880f9576e81c7ad3a5290fe61380a7531d559ef3cf0939bb30089c", + "scripts/experiments/subset_core_family.py": "373a45a8fb4294cdf72d510d54e16d21535227b085aefb008aa092b3ad26e4de", + "scripts/experiments/ternary_side.py": "93379b6e70cf58bb55432d9f2d1c0e0305c20a075bfe3cc219deabd927afd375", + "scripts/experiments/verify_joint_dual.py": "7a31bba1e9c0ded32ae285df2ca9bc91ef20c330f6789fdba361876f3c7a1985", + "scripts/experiments/verify_skip_frame.py": "fc42dc3d59239ee3908d0e3e95402eb53fd6815a100521911fde1b541070c292", + "scripts/experiments/verify_split_pair.py": "5cc7031569b17b560f68d4238191a32e5d7f66e7fdcbaabd0ca87020c89f89c8" + }, + "bit_saving": "3244890195589/62500000000000000", + "files": { + "SOURCE.json": "20273d507b6074ce91fd7467e2d23101bf35f8d60a2d81684c58f611d91f9108", + "cache-stale-failure.log": "edb8b32a81ab277326e3deb19d34119982c10e998ca0f1ae9cf22b1fa4afea21", + "coarse_graph.py": "b5bbabb8e5bf69769af4b6cd67163954d990dc489e3c9488ed84bd09f0a767c8", + "dense-audit.json": "055a31465e8c42c27b8c80115cb9a2edef5b32b52b61ce3c4dac9f718c86f954", + "dense_audit.py": "b282e743d9d8c48cbc97eb2c2597a6c52894d33ea1967dd1ff4c269b0e0a72e3", + "inherited/NOTICE": "3bfe7a693e10fbe710e7fadedb7caeb21e272ce5899f48d043f636e2b06562b0", + "inherited/README.md": "e9d7ae955d27fb1832744583f1d251263e9fc499bae2d664b31f28fc83dc2592", + "inherited/SOURCE.json": "813564d76569fd54a5aa1645da15f1a33b12de8a0bcc53056e69087394b0cfcd", + "inherited/graph.py": "349c74a3684cc26c14f4b7001efb086825a4398461709ba13ade2cd10e336d23", + "inherited/vendor/pr69-compiler.py": "bd8169bf9f5df185a8aa4aec22234b4fd483000a1cecc78b71bf32e479af1499", + "run.py": "3b8f3a355799882fd1431e3ced934e34149c77e36dce09f62e214fc6156e4c0a", + "schedule_variant.py": "3ce3b4c0886868e3fcd2b75c54b61180d103447cfdb9d3ece1de47dd6d46eecc", + "screen_width.py": "9087cac4d745d3525814323462efa7927db820e86bcc9e93b81a9fd7dcf6d372", + "selected-both/PROOF.md": "5343fcb8dca9ab48c86a8c0a6735b2afbb07fca75f6d0e62b3d3d640f7f190d0", + "selected-both/arithmetic.json": "7ed59a2d4b546f3375b4f95e9005831ca9741bb56092bc49a61bc7b2e770eebb", + "selected-both/comparison.json": "c69207a10663d760232439ae82f18785bb14172c5422ab7092aee93d69f3e41b", + "selected-both/profile-23.json": "af5194d09494e76a9c02cfb4b102dab07f20ad7758acaf2867158af0cf6a4731", + "selected-both/profile-25.json": "4c915181d485f4d4fcb64b6f9d0a73ccd87c28cea3dd45fc5297e41d15c41ae7", + "selected-both/result-23.json": "7ef1ed08ffcd9782419dabb2cb1f40a6541ffc479a0cfaaedb07314704a7864c", + "selected-both/result-25.json": "561326c6f0f188736c73f05a999b773a65b78b568c2df15fa0c7092cd14b7225", + "selected-both/transitions-23.bin.json": "8905306796e045dd91d711f3696e05785c0db07cd0f90cfd93690ab438ff239b", + "selected-both/transitions-25.bin.json": "28a702c6d487e1e878c307f40191c1386acbb58139ed9573bb139a27aee4ad83", + "selected-both/word-23.json.gz": "7c33d64688332fce70c5e451fd00e86e58d2d44bdc648ff7139756f6a6c774fe", + "selected-both/word-25.json.gz": "eec0b667f3c2ba199fe291c11f19d6d0112576dc34a113372a9867ca5509f4ba", + "validate_selected.py": "45f8d580df7c6897b8c8f96d552ca0dfa3c78bbeed837c8c4f2ead4e21e4036b", + "width_bridge.py": "6486e6b9508357e33a3e8ee6740bf4ae46e306dfdd8f270eb2dd235270e77dfd" + }, + "kappa": "51915547765237/1000000000000000000", + "public_PR76": "51738676045141/1000000000000000000", + "publication_eligible": false, + "status": "Internal subthreshold composition; compiler dirty bases/dense scalar audit/actual profiles/exact47/7 PASS. Separate independent receipt follows.", + "threshold_difference": "-16364332025941/200000000000000000000" +} diff --git a/research/round9-balanced-columns/run.py b/research/round9-balanced-columns/run.py new file mode 100644 index 0000000000..9d292dfb1b --- /dev/null +++ b/research/round9-balanced-columns/run.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 +"""PR70 bounded carried-signal exchanges composed with pinned PR71. + +PR70 exchanges: Alejandro; PR71 split/next-use compiler: Chafik Boukhalfa. +PR67 profile oracle/cost: Rohan Arun; PR68 live controls: Dominik Scholz. +Composition and integer-entropy pricing prepared with substantial OpenAI +Codex assistance. Discovery heuristic only; exact profiles accept candidates. +""" +from pathlib import Path +from collections import Counter +from hashlib import sha256 +import argparse,gzip,json,os,shlex,struct,subprocess,sys,time +if sys.flags.optimize:raise ValueError('Assertions must remain enabled') +sys.dont_write_bytecode=True +HERE=Path(__file__).resolve().parent +BASE=HERE.parent/'round6-pr71/baseline' +sys.path.insert(0,str(BASE/'scripts/experiments')) +import split_pair_engine as compiler +import split_pair_graph as producer +import schedule_variant +import coarse_graph +from binary_frame_math import logs + + +def main(): + p=argparse.ArgumentParser();p.add_argument('--h',type=int,choices=(23,25),required=True);p.add_argument('--work-dir',type=Path,required=True);p.add_argument('--passes',type=int,default=3);a=p.parse_args() + a.work_dir.mkdir(parents=True,exist_ok=True) + source=Path(compiler.__file__) + expected=json.loads((BASE/'research/split-pair/engine-provenance.json').read_text())['portable_engine_sha256'] + assert sha256(source.read_bytes()).hexdigest()==expected + executable=a.work_dir/'oracle' + subprocess.run([*shlex.split(os.environ.get('CXX','c++')),'-O3','-std=c++17','-I',str(BASE/'references/frame-compiler/pr48/scripts/partial_swap'),str(BASE/'references/frame-compiler/pr67/research/slot-cost-rank-pair/profile_oracle.cpp'),'-o',str(executable)],check=True) + compiler.graph=lambda h: schedule_variant.reorder(coarse_graph.graph(h,coarse='columns'));compiler.build=producer.ordered_build(compiler.build,a.h) + original_match=compiler.match + def exchange_match(blocks,uses,enabled): + result=original_match(blocks,uses,enabled) + edges,chosen,right,stats=result + initial_cardinality=len(chosen) + if not a.passes:return result + owner={x:g for g,b in enumerate(blocks) for x in b['nodes']} + path=a.work_dir/'matching-oracle.bin' + with path.open('wb')as stream: + h=a.h;v=h*(h-1)*(h-2)//6 + stream.write(struct.pack('<6I2Q',h,v,0,len(blocks)+2,0,0,h*(h-1),h*(h-1))) + stream.write(struct.pack('<2QI',0,0,0));stream.write(struct.pack('<2QI',0,0,h)) + for b in blocks:stream.write(struct.pack('<2QI',*b['frame'],b['rank'])) + oracle=subprocess.Popen([str(executable),str(path)],stdin=subprocess.PIPE,stdout=subprocess.PIPE,text=True,bufsize=1) + weights=[0]+[int(t*sum(logs(t))*10**30//2)for t in range(1,h+1)];cache={} + def entropy(x,y): + if (x,y)not in cache: + oracle.stdin.write(f'{x} {y}\n');oracle.stdin.flush();line=oracle.stdout.readline();assert line + values=list(map(int,line.split()));assert len(values)==h+1 + cache[x,y]=sum(n*w for n,w in zip(values,weights)) + return cache[x,y] + def cost(edge): + g,u,i=edge;p=owner[blocks[g]['inputs'][i]];t=uses[u][1] + return -entropy(g+2,t+2)+entropy(g+2,1)+entropy(0,p+2)+entropy(p+2,t+2) + try: + prices=[] + for j,e in enumerate(edges): + prices.append(cost(e)) + if j%20000==0:print('edge prices',j,len(edges),'pairs',len(cache),flush=True) + finally: + oracle.stdin.close();assert oracle.wait(timeout=10)==0 + priority=sorted(range(len(edges)),key=lambda e:(prices[e],edges[e]));initial=sum(prices[e]for e in chosen) + def can(e,drop=None): + g,u,i=edges[e] + rows=blocks[g]['outbasis']+[1<=prices[f]:continue + if not can(e,f if edges[f][0]==g else None):continue + else: + f=next((z for z in sorted(blocks[g]['selected'],key=lambda z:(-prices[z],z)) if prices[e]=1:k-=1 + while refine.exact_moment(m,W,rows,Q(k+1,den))['upper']<1:k+=1 + bit=Q(k,den);accepted=refine.exact_moment(m,W,rows,bit);excluded=refine.exact_moment(m,W,rows,bit+Q(1,den));assert accepted['upper']<1= j+1 proves persistence.", + "additional_eventual_conditions": [ + "BHP prime threshold and distinct-prime packing", + "Fixed rational basis, eligible common prime and native table setup", + "Catalogue/descriptor domination, logarithm absorption, exact recovery" + ], + "practical_runtime_claim": false + } + }, + "independent_serialized_replay": false, + "profile_reconstruction": { + "h": 25, + "v": 2300, + "R": 35598, + "frames": 84845, + "distinct_transitions": 212411, + "singles": 20700, + "rank_mass": 890550, + "rank_histogram_with_side_growth_split_into_singletons": { + "1": 90752, + "2": 111403, + "3": 13346, + "4": 18638, + "5": 8916, + "6": 3400, + "7": 576, + "8": 1196, + "9": 553, + "10": 854, + "11": 21, + "12": 776, + "13": 162, + "14": 756, + "15": 125, + "16": 2229, + "17": 583, + "18": 572, + "19": 879, + "20": 4217, + "21": 8479, + "23": 462, + "24": 25 + }, + "word_sha256": "fc6f429363b3c8208fd9bff10ec20386de280a3e1ea4f109ca5e0834d2c60fc4", + "copied_centers": 25, + "transition_events_equal_independent_xor_word_reconstruction": true + }, + "comparison_pr71": "250450830599/500000000000000000" +} diff --git a/research/round9-balanced-columns/selected-both/comparison.json b/research/round9-balanced-columns/selected-both/comparison.json new file mode 100644 index 0000000000..748f9f9a80 --- /dev/null +++ b/research/round9-balanced-columns/selected-both/comparison.json @@ -0,0 +1,10 @@ +{ + "kappa": "51915547765237/1000000000000000000", + "pr74_commit": "5830ccfca8466aff613767222558e29b57fa8225", + "pr74_kappa": "10366199626713/200000000000000000", + "difference_pr74": "10568703959/125000000000000000", + "relative_gain_pr74": "84549631672/51830998133565", + "pr76_kappa": "51738676045141/1000000000000000000", + "difference_pr76": "5527241253/31250000000000000", + "relative_gain_pr76": "176871720096/51738676045141" +} diff --git a/research/round9-balanced-columns/selected-both/profile-23.json b/research/round9-balanced-columns/selected-both/profile-23.json new file mode 100644 index 0000000000..869fbc9e8b --- /dev/null +++ b/research/round9-balanced-columns/selected-both/profile-23.json @@ -0,0 +1,38 @@ +{ + "h": 23, + "v": 1771, + "R": 27128, + "loss": 506, + "rank_sum": 624450, + "field_prime": 2305843009213693951, + "frames": 59803, + "distinct_matrices": 38046, + "crt_matrices": 5533, + "crt_disagreements": 0, + "blocks": [ + 0, + 356829, + 20591, + 7982, + 5322, + 3971, + 3684, + 3110, + 2577, + 1993, + 1718, + 1471, + 972, + 832, + 537, + 482, + 225, + 172, + 22, + 49, + 0, + 23, + 0, + 0 + ] +} diff --git a/research/round9-balanced-columns/selected-both/profile-25.json b/research/round9-balanced-columns/selected-both/profile-25.json new file mode 100644 index 0000000000..b98279deab --- /dev/null +++ b/research/round9-balanced-columns/selected-both/profile-25.json @@ -0,0 +1,40 @@ +{ + "h": 25, + "v": 2300, + "R": 35598, + "loss": 600, + "rank_sum": 890550, + "field_prime": 2305843009213693951, + "frames": 84845, + "distinct_matrices": 51195, + "crt_matrices": 7344, + "crt_disagreements": 0, + "blocks": [ + 0, + 492973, + 27296, + 10319, + 7656, + 5373, + 4880, + 3987, + 3753, + 2926, + 2452, + 2021, + 1735, + 1408, + 1101, + 871, + 514, + 458, + 241, + 176, + 65, + 51, + 0, + 25, + 0, + 0 + ] +} diff --git a/research/round9-balanced-columns/selected-both/result-23.json b/research/round9-balanced-columns/selected-both/result-23.json new file mode 100644 index 0000000000..0de212965f --- /dev/null +++ b/research/round9-balanced-columns/selected-both/result-23.json @@ -0,0 +1,79 @@ +{ + "h": 23, + "mode": { + "matching": true, + "reclaim": true + }, + "roles": 27128, + "baseline_pr48_roles": 36432, + "histogram": { + "1": 58230, + "0": 336047, + "2": 81090, + "4": 14624, + "3": 10015, + "5": 6757, + "6": 2127, + "8": 1105, + "10": 599, + "9": 364, + "12": 691, + "14": 1893, + "13": 208, + "11": 97, + "16": 430, + "17": 543, + "18": 3197, + "19": 6482, + "15": 267, + "22": 23, + "7": 278, + "21": 429 + }, + "rank_mass": 624450, + "elementary_xors": 167539, + "stats": { + "augmentations": 58, + "carried_signal_exchanges": 870, + "exchange_entropy_gain_1e30": 2790077775929094410673602180165521, + "exchange_profile_pairs": 262461, + "regions": 59801, + "matched": 41730, + "multi_node_regions": 8694, + "live_anchor_candidates": 73112, + "reclaimed": 2282, + "clearing_xors": 4862, + "live_anchor_xors": 533 + }, + "dirty_basis_vectors": 30670, + "complete_dirty_basis_both_orientations": true, + "all_physical_frame_inclusions": true, + "scalar": { + "h": 23, + "inputs": 1771, + "partial_outputs": 5336, + "additions": 67460, + "roles": 72796, + "merged_additions": 11937, + "all_additions_disjoint": true, + "all_partial_outputs_exact": true, + "every_node_has_common_point": true, + "circuit_sha256": "c576293d88ef09bb28747488a7799141f6e4761729e5fc897fca838bf413206c" + }, + "graph_configuration": { + "groups": [ + 1, + 1, + 2 + ], + "schedule": "cover-core", + "anchor": true, + "scalar_node_order": "core-reverse", + "coarse": "columns" + }, + "source_sha256": { + "run.py": "3b8f3a355799882fd1431e3ced934e34149c77e36dce09f62e214fc6156e4c0a", + "schedule_variant.py": "3ce3b4c0886868e3fcd2b75c54b61180d103447cfdb9d3ece1de47dd6d46eecc", + "coarse_graph.py": "b5bbabb8e5bf69769af4b6cd67163954d990dc489e3c9488ed84bd09f0a767c8" + } +} diff --git a/research/round9-balanced-columns/selected-both/result-25.json b/research/round9-balanced-columns/selected-both/result-25.json new file mode 100644 index 0000000000..540287acb9 --- /dev/null +++ b/research/round9-balanced-columns/selected-both/result-25.json @@ -0,0 +1,81 @@ +{ + "h": 25, + "mode": { + "matching": true, + "reclaim": true + }, + "roles": 35598, + "baseline_pr48_roles": 48329, + "histogram": { + "1": 76952, + "0": 470952, + "2": 118303, + "3": 13346, + "4": 18638, + "5": 8916, + "6": 3400, + "8": 1196, + "7": 576, + "9": 553, + "10": 854, + "12": 776, + "14": 756, + "13": 162, + "16": 2229, + "18": 572, + "19": 879, + "11": 21, + "15": 125, + "17": 583, + "20": 4217, + "21": 8479, + "24": 25, + "23": 462 + }, + "rank_mass": 890550, + "elementary_xors": 235195, + "stats": { + "augmentations": 85, + "carried_signal_exchanges": 1598, + "exchange_entropy_gain_1e30": 12525907879699441579426280229946796, + "exchange_profile_pairs": 409601, + "regions": 84843, + "matched": 60971, + "multi_node_regions": 11575, + "live_anchor_candidates": 99952, + "live_anchor_xors": 1365, + "reclaimed": 3349, + "clearing_xors": 8037 + }, + "dirty_basis_vectors": 40198, + "complete_dirty_basis_both_orientations": true, + "all_physical_frame_inclusions": true, + "scalar": { + "h": 25, + "inputs": 2300, + "partial_outputs": 6925, + "additions": 94993, + "roles": 101918, + "merged_additions": 17168, + "all_additions_disjoint": true, + "all_partial_outputs_exact": true, + "every_node_has_common_point": true, + "circuit_sha256": "accd79690903b340ec1e60531b9496c0a81aac147d182ed49d5540fd684cd49f" + }, + "graph_configuration": { + "groups": [ + 1, + 1, + 2 + ], + "schedule": "reverse-node", + "anchor": true, + "scalar_node_order": "core-reverse", + "coarse": "columns" + }, + "source_sha256": { + "run.py": "3b8f3a355799882fd1431e3ced934e34149c77e36dce09f62e214fc6156e4c0a", + "schedule_variant.py": "3ce3b4c0886868e3fcd2b75c54b61180d103447cfdb9d3ece1de47dd6d46eecc", + "coarse_graph.py": "b5bbabb8e5bf69769af4b6cd67163954d990dc489e3c9488ed84bd09f0a767c8" + } +} diff --git a/research/round9-balanced-columns/selected-both/transitions-23.bin.json b/research/round9-balanced-columns/selected-both/transitions-23.bin.json new file mode 100644 index 0000000000..fbc07d359c --- /dev/null +++ b/research/round9-balanced-columns/selected-both/transitions-23.bin.json @@ -0,0 +1,35 @@ +{ + "h": 23, + "v": 1771, + "R": 27128, + "frames": 59803, + "distinct_transitions": 151935, + "singles": 15939, + "rank_mass": 624450, + "rank_histogram_with_side_growth_split_into_singletons": { + "1": 68856, + "2": 75777, + "3": 10015, + "4": 14624, + "5": 6757, + "6": 2127, + "7": 278, + "8": 1105, + "9": 364, + "10": 599, + "11": 97, + "12": 691, + "13": 208, + "14": 1893, + "15": 267, + "16": 430, + "17": 543, + "18": 3197, + "19": 6482, + "21": 429, + "22": 23 + }, + "word_sha256": "7e452d6cec73d2433c9ec996fac2bfaf97317294ee515f86cef95c3ad9f154d7", + "copied_centers": 23, + "transition_events_equal_independent_xor_word_reconstruction": true +} diff --git a/research/round9-balanced-columns/selected-both/transitions-25.bin.json b/research/round9-balanced-columns/selected-both/transitions-25.bin.json new file mode 100644 index 0000000000..dac6567ef8 --- /dev/null +++ b/research/round9-balanced-columns/selected-both/transitions-25.bin.json @@ -0,0 +1,37 @@ +{ + "h": 25, + "v": 2300, + "R": 35598, + "frames": 84845, + "distinct_transitions": 212411, + "singles": 20700, + "rank_mass": 890550, + "rank_histogram_with_side_growth_split_into_singletons": { + "1": 90752, + "2": 111403, + "3": 13346, + "4": 18638, + "5": 8916, + "6": 3400, + "7": 576, + "8": 1196, + "9": 553, + "10": 854, + "11": 21, + "12": 776, + "13": 162, + "14": 756, + "15": 125, + "16": 2229, + "17": 583, + "18": 572, + "19": 879, + "20": 4217, + "21": 8479, + "23": 462, + "24": 25 + }, + "word_sha256": "fc6f429363b3c8208fd9bff10ec20386de280a3e1ea4f109ca5e0834d2c60fc4", + "copied_centers": 25, + "transition_events_equal_independent_xor_word_reconstruction": true +} diff --git a/research/round9-balanced-columns/selected-both/word-23.json.gz b/research/round9-balanced-columns/selected-both/word-23.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..8d077760e37e6296e19da558a165e02a0f55ff7e GIT binary patch literal 3013581 zcmZ5|c_3Bm_kJoVl4R@<&54k5G84j037N+uQXF$3GKI_zHw{W6WIV#~ZeD3;b{Erg3TM>!a_!o>~%8;YpZf z@{E*U=xR%Ua6>fdL-dKmEVolWB=<}y+?Cui7) zkhNLXwdv)uQAVU}mSy-DE^7^1t}eaa^pMynjombzlAF}Enq67*=%N1cl3eNf*!cTM zAK?*7^h96X`t;E9be-l#_^Qw80hjgn_VFF-^LIT>8yhFqZ+06l$Bpz&EU&&7itkvM zFYz*sl$-Z9zl+~oC9W^EZA_Erm)cg=mvq)|`<$_PZ@X!_=p$T1iJtGPTL9O6^E>Hf z$Lf;1iEPfqh|B7G9-qbaktVsixJ}b+AK@iR^aw?`ak{T=ZrXD7_EhA2@ZVc6xR=W1 zG*UW-?)cDnQ�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

wPI^Zf67AT_(4bE2e&RE@7o# zN(!hr&~69b8LV;TB7k-b+8h%uk)0SO<6Xx!{NW-#3$>q-ggLlE*~8;YM+vl^yHa-$ z1j9QZ7J${FxrG#2;6COn!Mw6=VV0#1_!a698rT+3dPG5M4c^Y$f zaKe?Zlbt1wjh=?jB3)T!Yg}~mjm;FSq8nekTfszkeADTIqsSSZAZxzUl1k(LaNe$! z9-KORP$W7NZ2NK;!Koe$LS_YpZ&sKj2SWvS)k>v84uFTxA&-*SmZ3}jqE|