diff --git a/research/x4-four-source-horner/CLAIM.md b/research/x4-four-source-horner/CLAIM.md new file mode 100644 index 0000000000..fc6a33a0c8 --- /dev/null +++ b/research/x4-four-source-horner/CLAIM.md @@ -0,0 +1,31 @@ +# Complex supplier claim — seed 22 + +- Start: 2026-10-13 08:05 PDT. Planned finish: 09:05 PDT. Stop experiments by 08:50 and reserve the final 15 minutes for verification and handoff; finish sooner if verification is complete. +- Fresh OS assignment: `secrets.randbelow(100)` returned **22**, complex supplier. +- Exact fetched base: `007664306fff84fbb1c9a1b4053b69f439764034`. +- Current selected result: PR890 U8/T21, conditional kappa `0.001661957774647029`; unchanged by this work. Its construction, selected source pointers and maintainer review were read. +- Three narrow candidates: (0) another factory diagonal gauge (already bounded by PR949); (1) joint Horner windows of up to four distinct sources in historical X4 nonzero-frame backward runs; (2) two-scratch single-coefficient synthesis after PR882 (higher search cost and an extra scratch clearing bill). Seed `22 % 3 = 1` chooses candidate 1; `3 + 22 % 3 = 4` sets the maximum fan-in. +- Object: the byte-pinned PR799 backward scalar program retained under `research/complex-x4-compensation-pairs/inputs/`. Candidate windows are consecutive ADDs with one common target, one identical nonzero frame and 2–4 distinct immutable sources. No aliases or crossing non-scalar events. +- Method: shared binary Horner preparation at a common denominator in the existing coefficient stream; charge every copy, source addition, shift, accumulation and clear. Exact interval scheduling maximizes savings among disjoint windows that beat redundant-clear removal alone. +- New class: PR945 handles pairs. This permits simultaneous three/four-source work, whose shared shifts and accumulation can beat every partition into pairs. Not merely a longer search of the pair class. Credit PR945's mechanism and 13,072 saving separately; no assumption of additive savings. +- Optimistic complete arithmetic pricing before implementation: backward pair-only saving 13,072; maximum-four saving 22,048 real-component primitives over PR696. Forward is retained, so it will bind the orientation maximum. This is not a kappa gain. +- Deliverable: exact emitted words, complete scalar endpoint/prefix accounting, an independently implemented census/selection/replay, source pins, adverse controls, and a focused finite-construction PR if verified. One completed 2–4 window census is the stopping rule. +- Coordination: no pinned sprint issue found (open issues 650 and 913 are unrelated). Local claim used. Refreshed open PRs through #966 and all-state Horner search. PR945 at `a3245bf22fa2a2eb778b11128cbc605b130d737f` is the direct comparator. PR751/830 cover historical JP8 fan-in; PR769 CK ladders; PR932/961 zero-frame target forests; PR949 factory scales. These are distinct and not composed. +- Scope: only this new research package. No changes to upstream, selected certificates, production emitters or predecessor packages. Inherited uniform, physical/frame/phase, hosting, precision/tape and analytic obligations remain. Subagents stay within this claim. +- Attribution: prepared for ToikY with substantial OpenAI Codex assistance; Apache-2.0. Full predecessor credits and exact verification limits will accompany the result. + +## Result update + +The complete 16,431-window census finished. The chosen 1,174 disjoint windows +reduce backward scalar primitives from 143,674 to 121,626: 22,048 saved, +including 8,976 beyond PR945. The unchanged forward count 143,658 still binds; +there is no further orientation-maximum gain over PR945 and no new kappa. +Two exact engines, all 737 input columns, nine independent controls and seven +package test groups pass. Typed physical/hosted integration remains open. + +Final overlap refresh through #971 found no duplicate of this extension; +PR945's head is unchanged. Main advanced to +`bbc600db2fc15007b7c914f4f2b2ed55fa909c87` (PR942 U8/T37). All nine historical +input pins are unchanged. [Validation](VALIDATION.md) records the checks. +The completed contribution is on +[codex/complex-supplier-seed22](https://github.com/ToikY/integer-mult-bounds/tree/codex/complex-supplier-seed22/research/x4-four-source-horner). diff --git a/research/x4-four-source-horner/EXPECTED.json b/research/x4-four-source-horner/EXPECTED.json new file mode 100644 index 0000000000..2475daaefc --- /dev/null +++ b/research/x4-four-source-horner/EXPECTED.json @@ -0,0 +1,1370 @@ +{ + "after": { + "exact_prefix_fraction_bits": 19, + "exact_prefix_row_l1": "5338828", + "nonwork_source_reads": 19723, + "operand_reads": 65431, + "per_component_opcodes": { + "add": 9628, + "clear": 15105, + "copy": 9332, + "double": 3511, + "halve": 12494, + "negate": 648, + "subtract": 10095 + }, + "per_component_primitives": 60813, + "positive_prefix_row_l1": "48299247699832632898063/16", + "real_component_primitives": 121626, + "work_source_reads": 13966 + }, + "assignment_seed": 22, + "base_commit": "007664306fff84fbb1c9a1b4053b69f439764034", + "baseline_stream_sha256": "466a7cd4108886ef8e5b413913cb084cd65eedb46025c2b405e9e712985bb3ec", + "before": { + "exact_prefix_fraction_bits": 19, + "exact_prefix_row_l1": "5338828", + "nonwork_source_reads": 19723, + "operand_reads": 73196, + "per_component_opcodes": { + "add": 10258, + "clear": 18364, + "copy": 11928, + "double": 6946, + "halve": 14228, + "negate": 648, + "subtract": 9465 + }, + "per_component_primitives": 71837, + "positive_prefix_row_l1": "48299247699832632898063/16", + "real_component_primitives": 143674, + "work_source_reads": 13303 + }, + "boundaries": 1174, + "candidate_counts": { + "2": 6112, + "3": 5455, + "4": 4864 + }, + "candidate_stream_sha256": "d95c2ce750263e09c1051dad011e0bb436b696424e8d98513efba09908d757a3", + "candidates_sha256": "bfb4fa2c16758ee441c0b437531b1a3d6444aba0a756ea5a65120f419a004845", + "eligible_beyond_clear_only": 9652, + "extra_beyond_pairs_real": 8976, + "formal_columns": 737, + "forward_retained_real": 143658, + "independent": { + "adverse_controls_rejected": 9, + "backward_baseline": { + "checked_columns": 737, + "component_primitives": 71837, + "endpoint_sha256": "f0419934aaf18082a201d777636a17ecbed52f07aad7d1d39ea0e349bceaabc6", + "exact_prefix_l1": [ + 5338828, + 1 + ], + "logical_endpoint_verified": true, + "max_grid_exponent": 19, + "nonwork_source_reads": 19723, + "operand_reads": 73196, + "positive_prefix_l1": [ + 48299247699832632898063, + 16 + ], + "primitive_histogram": { + "add": 10258, + "clear": 18364, + "copy": 11928, + "double": 6946, + "halve": 14228, + "negate": 648, + "subtract": 9465 + }, + "private_erasure_verified": true, + "real_component_primitives": 143674, + "source_reads_into_work": 13303, + "stream_sha256": "466a7cd4108886ef8e5b413913cb084cd65eedb46025c2b405e9e712985bb3ec", + "window_boundaries_checked": 0 + }, + "backward_candidate": { + "checked_columns": 737, + "component_primitives": 60813, + "endpoint_sha256": "f0419934aaf18082a201d777636a17ecbed52f07aad7d1d39ea0e349bceaabc6", + "exact_prefix_l1": [ + 5338828, + 1 + ], + "logical_endpoint_verified": true, + "max_grid_exponent": 19, + "nonwork_source_reads": 19723, + "operand_reads": 65431, + "positive_prefix_l1": [ + 48299247699832632898063, + 16 + ], + "primitive_histogram": { + "add": 9628, + "clear": 15105, + "copy": 9332, + "double": 3511, + "halve": 12494, + "negate": 648, + "subtract": 10095 + }, + "private_erasure_verified": true, + "real_component_primitives": 121626, + "source_reads_into_work": 13966, + "stream_sha256": "d95c2ce750263e09c1051dad011e0bb436b696424e8d98513efba09908d757a3", + "window_boundaries_checked": 1174 + }, + "census": { + "2": { + "census_sha256": "136edfb4a6dfe3d169c47435302328c146883f4e319b7fa21b5d17c664f51413", + "eligible": 6112, + "gain_component": 6536, + "gain_real": 13072, + "selected": 1586, + "strictly_beyond_clear_only": 2764 + }, + "3": { + "census_sha256": "e6d744fcad0786636b78979b0dba8a26015327c2a5303fa02603a7da9763b42f", + "eligible": 11567, + "gain_component": 9232, + "gain_real": 18464, + "selected": 1342, + "strictly_beyond_clear_only": 6113 + }, + "4": { + "census_sha256": "5a97a98aa77d2165a5dc18ed081a0b1d8bba747c6456b1051f4de5dbe305b46c", + "eligible": 16431, + "gain_component": 11024, + "gain_real": 22048, + "selected": 1167, + "strictly_beyond_clear_only": 9652 + } + }, + "forward_retained": { + "checked_columns": 737, + "component_primitives": 71829, + "endpoint_sha256": "9881fc8682969eb18c46adbb29fd3c917f8c3716dfde7b6962cacfb87840d1e0", + "exact_prefix_l1": [ + 525312, + 1 + ], + "logical_endpoint_verified": true, + "max_grid_exponent": 3, + "nonwork_source_reads": 19723, + "operand_reads": 73188, + "positive_prefix_l1": [ + 6812058044968180837, + 256 + ], + "primitive_histogram": { + "add": 10944, + "clear": 18356, + "copy": 11936, + "double": 6946, + "halve": 14228, + "negate": 648, + "subtract": 8771 + }, + "private_erasure_verified": true, + "real_component_primitives": 143658, + "source_reads_into_work": 13303, + "stream_sha256": "2930eaf032087710865a19a1985632cdddd1a6bdfbc097b3fdaa9ce480c1e4f1", + "window_boundaries_checked": 0 + }, + "local_candidate_identities": 16431, + "recipe_sha256": "25f74303456ea46951aa61f986fc565a0cfa980756bc6de4406983b5db0032e1" + }, + "local_candidate_identities": 16431, + "no_new_kappa": true, + "non_scalar_sha256": "a802da12c169920c03a2625d8c50015c09c91d2fafeb14ec5c4a6213f3cd358e", + "orientation_max_after": 143658, + "orientation_max_before": 143674, + "pair_only_saved_real": 13072, + "pair_only_windows": 1586, + "recipe": [ + [7279, 4], + [9516, 4], + [9520, 3], + [9526, 4], + [9734, 4], + [9738, 3], + [9744, 4], + [9952, 4], + [9956, 3], + [9962, 4], + [10170, 4], + [10174, 3], + [10180, 4], + [10388, 4], + [10392, 3], + [10398, 4], + [10606, 4], + [10610, 3], + [10616, 4], + [10824, 4], + [10828, 3], + [10834, 4], + [11042, 4], + [11046, 3], + [11052, 4], + [11260, 4], + [11264, 3], + [11270, 4], + [11478, 4], + [11482, 3], + [11488, 4], + [11696, 4], + [11700, 3], + [11706, 4], + [11914, 4], + [11918, 3], + [11924, 4], + [12132, 4], + [12136, 3], + [12142, 4], + [12350, 4], + [12354, 3], + [12360, 4], + [12814, 2], + [12816, 2], + [12851, 2], + [12862, 2], + [12864, 2], + [12872, 2], + [12874, 2], + [12915, 4], + [12919, 4], + [12923, 4], + [12927, 4], + [12932, 2], + [12935, 2], + [12937, 4], + [12941, 4], + [12945, 4], + [12949, 4], + [12953, 4], + [12957, 4], + [12961, 4], + [12968, 3], + [12971, 4], + [12975, 4], + [12979, 4], + [12985, 3], + [12988, 4], + [12992, 4], + [13000, 2], + [13005, 3], + [13008, 4], + [13012, 4], + [13020, 2], + [13024, 3], + [13031, 2], + [13033, 4], + [13037, 4], + [13042, 3], + [13047, 4], + [13051, 4], + [13055, 4], + [13059, 3], + [13064, 4], + [13068, 4], + [13072, 4], + [13077, 3], + [13082, 4], + [13086, 4], + [13090, 4], + [13094, 3], + [13099, 4], + [13103, 4], + [13111, 2], + [13121, 4], + [13125, 4], + [13129, 4], + [13135, 2], + [13139, 4], + [13143, 4], + [13147, 4], + [13151, 4], + [13155, 4], + [13159, 4], + [13163, 4], + [13233, 4], + [13275, 2], + [13279, 3], + [13282, 3], + [13291, 2], + [13295, 3], + [13298, 3], + [13307, 2], + [13311, 3], + [13314, 3], + [13387, 2], + [13391, 3], + [13394, 3], + [18162, 4], + [18171, 2], + [18174, 4], + [18178, 3], + [18181, 3], + [18205, 3], + [18208, 3], + [18211, 3], + [18214, 3], + [18217, 3], + [18220, 3], + [18229, 2], + [18233, 4], + [18245, 4], + [18257, 4], + [18286, 4], + [18350, 4], + [18354, 4], + [18358, 4], + [18367, 4], + [18371, 4], + [18375, 4], + [18384, 4], + [18388, 4], + [18392, 4], + [18401, 4], + [18405, 4], + [18409, 4], + [18519, 4], + [18526, 3], + [18540, 4], + [18545, 3], + [18548, 4], + [18553, 3], + [18556, 4], + [18561, 4], + [18565, 3], + [18569, 4], + [18573, 3], + [18594, 3], + [18602, 4], + [18623, 4], + [18627, 4], + [18653, 4], + [18662, 4], + [18667, 2], + [18670, 4], + [18677, 4], + [18700, 4], + [18704, 4], + [18710, 4], + [18718, 4], + [18724, 4], + [18728, 4], + [18733, 4], + [18737, 4], + [18743, 4], + [18751, 4], + [18757, 4], + [18761, 4], + [18766, 4], + [18770, 4], + [18776, 4], + [18780, 4], + [18786, 4], + [18792, 4], + [18808, 4], + [18812, 4], + [18818, 4], + [18822, 4], + [18830, 4], + [18836, 4], + [18840, 4], + [18845, 4], + [18852, 2], + [18855, 3], + [18860, 3], + [18867, 4], + [18871, 3], + [18892, 4], + [18897, 4], + [18901, 3], + [18905, 4], + [18909, 2], + [18915, 4], + [18920, 4], + [18925, 4], + [18930, 4], + [18935, 4], + [18940, 4], + [18945, 4], + [18952, 4], + [18957, 3], + [18960, 4], + [18964, 4], + [18970, 4], + [18974, 3], + [18977, 3], + [18984, 4], + [18988, 4], + [18995, 4], + [18999, 4], + [19014, 4], + [19018, 4], + [19022, 4], + [19034, 4], + [19039, 4], + [19044, 4], + [19048, 4], + [19059, 4], + [19064, 3], + [19067, 4], + [19071, 4], + [19075, 2], + [19082, 4], + [19086, 4], + [19105, 4], + [19109, 4], + [19113, 4], + [19118, 2], + [19120, 4], + [19124, 3], + [19128, 4], + [19141, 4], + [19145, 4], + [19149, 4], + [19155, 4], + [19159, 4], + [19163, 2], + [19166, 3], + [19173, 4], + [19177, 4], + [19186, 4], + [19190, 3], + [19193, 4], + [19197, 4], + [19208, 4], + [19231, 4], + [19235, 4], + [19240, 3], + [19250, 3], + [19253, 4], + [19257, 4], + [19261, 4], + [19265, 4], + [19269, 4], + [19274, 4], + [19278, 4], + [19282, 4], + [19286, 4], + [19290, 3], + [19293, 4], + [19297, 4], + [19301, 4], + [19305, 4], + [19311, 4], + [19315, 3], + [19318, 4], + [19324, 4], + [19328, 2], + [19330, 4], + [19351, 4], + [19355, 4], + [19359, 4], + [19363, 4], + [19368, 3], + [19372, 4], + [19376, 4], + [19380, 4], + [19389, 4], + [19393, 4], + [19398, 4], + [19402, 4], + [19411, 3], + [19414, 4], + [19420, 4], + [19427, 4], + [19440, 4], + [19444, 4], + [19448, 4], + [19452, 4], + [19456, 4], + [19462, 4], + [19466, 4], + [19470, 4], + [19474, 4], + [19480, 4], + [19485, 4], + [19489, 4], + [19493, 4], + [19497, 4], + [19501, 4], + [19510, 3], + [19513, 4], + [19519, 4], + [19523, 4], + [19527, 4], + [19531, 2], + [19534, 3], + [19537, 4], + [19541, 4], + [19545, 4], + [19557, 4], + [19561, 4], + [19567, 4], + [19572, 4], + [19576, 4], + [19581, 4], + [19587, 4], + [19592, 4], + [19596, 4], + [19601, 3], + [19605, 3], + [19609, 4], + [19613, 4], + [19617, 4], + [19623, 4], + [19646, 4], + [19650, 4], + [19654, 4], + [19658, 4], + [19662, 4], + [19666, 4], + [19672, 4], + [19676, 4], + [19680, 4], + [19684, 4], + [19706, 4], + [19711, 4], + [19715, 4], + [19732, 4], + [19736, 4], + [19742, 4], + [19746, 4], + [19750, 4], + [19755, 4], + [19760, 4], + [19765, 4], + [19769, 4], + [19773, 4], + [19780, 3], + [19831, 4], + [19835, 4], + [19839, 4], + [19843, 4], + [19852, 3], + [19855, 4], + [19859, 4], + [19863, 4], + [19867, 4], + [19880, 4], + [19889, 2], + [19891, 4], + [19895, 3], + [19898, 4], + [19905, 4], + [19910, 4], + [19915, 2], + [19917, 4], + [19921, 4], + [19925, 4], + [19931, 4], + [19936, 4], + [19941, 2], + [19943, 4], + [19947, 4], + [19951, 4], + [19955, 4], + [19962, 4], + [19983, 4], + [19988, 4], + [19993, 4], + [19999, 4], + [20003, 4], + [20008, 4], + [20016, 4], + [20020, 4], + [20024, 4], + [20042, 2], + [20044, 4], + [20048, 3], + [20051, 3], + [20054, 4], + [20060, 3], + [20063, 4], + [20072, 4], + [20077, 3], + [20080, 3], + [20083, 4], + [20087, 4], + [20091, 4], + [20095, 4], + [20109, 4], + [20113, 4], + [20118, 4], + [20122, 4], + [20126, 4], + [20133, 4], + [20137, 4], + [20141, 4], + [20146, 4], + [20152, 3], + [20155, 3], + [20158, 4], + [20162, 4], + [20167, 4], + [20172, 3], + [20203, 4], + [20207, 4], + [20211, 4], + [20215, 2], + [20217, 4], + [20222, 4], + [20226, 4], + [20230, 4], + [20234, 4], + [20242, 3], + [20245, 4], + [20249, 4], + [20253, 4], + [20257, 4], + [20261, 4], + [20306, 2], + [20309, 4], + [20315, 3], + [20324, 4], + [20328, 4], + [20332, 4], + [20336, 4], + [20340, 4], + [20358, 4], + [20366, 3], + [20369, 4], + [20373, 4], + [20377, 4], + [20381, 4], + [20385, 4], + [20389, 4], + [20394, 3], + [20401, 3], + [20404, 4], + [20408, 3], + [20411, 4], + [20415, 4], + [20419, 4], + [20441, 4], + [20445, 4], + [20449, 4], + [20453, 4], + [20457, 4], + [20461, 3], + [20464, 4], + [20489, 4], + [20493, 4], + [20497, 4], + [20501, 4], + [20505, 4], + [20509, 4], + [20513, 3], + [20516, 4], + [20571, 4], + [20575, 4], + [20579, 4], + [20583, 4], + [20587, 4], + [20605, 4], + [20613, 4], + [20617, 4], + [20621, 4], + [20625, 4], + [20629, 4], + [20633, 4], + [20640, 2], + [20642, 4], + [20663, 4], + [20667, 4], + [20671, 4], + [20675, 4], + [20679, 4], + [20683, 4], + [20688, 4], + [20692, 4], + [20706, 4], + [20710, 4], + [20714, 4], + [20718, 4], + [20728, 4], + [20732, 4], + [20736, 4], + [20740, 4], + [20744, 4], + [20749, 4], + [20754, 3], + [20758, 4], + [20763, 4], + [20768, 3], + [20771, 4], + [20779, 4], + [20784, 4], + [20789, 4], + [20793, 4], + [20798, 4], + [20802, 4], + [20806, 4], + [20810, 4], + [20814, 4], + [20819, 4], + [20823, 4], + [20827, 4], + [20831, 4], + [20837, 4], + [20841, 4], + [20846, 4], + [20863, 2], + [20866, 4], + [20872, 4], + [20876, 4], + [20880, 4], + [20884, 3], + [20887, 4], + [20891, 4], + [20896, 2], + [20898, 4], + [20904, 4], + [20908, 3], + [20911, 4], + [20915, 4], + [20919, 4], + [20923, 4], + [20928, 3], + [20931, 4], + [20942, 3], + [20945, 4], + [20950, 4], + [20955, 4], + [20962, 4], + [20966, 4], + [20970, 4], + [20974, 4], + [20981, 2], + [20983, 4], + [20988, 4], + [20992, 4], + [20999, 4], + [21003, 4], + [21007, 4], + [21011, 4], + [21015, 4], + [21019, 4], + [21023, 4], + [21027, 4], + [21032, 4], + [21037, 4], + [21041, 4], + [21045, 4], + [21049, 4], + [21054, 4], + [21058, 4], + [21068, 4], + [21072, 4], + [21076, 3], + [21079, 4], + [21083, 4], + [21087, 4], + [21091, 4], + [21100, 4], + [21104, 4], + [21108, 4], + [21112, 4], + [21116, 4], + [21120, 4], + [21124, 4], + [21134, 4], + [21158, 3], + [21161, 4], + [21165, 4], + [21169, 4], + [21174, 4], + [21178, 4], + [21183, 2], + [21185, 4], + [21200, 4], + [21206, 4], + [21210, 2], + [21212, 4], + [21216, 4], + [21220, 4], + [21224, 4], + [21228, 4], + [21232, 4], + [21265, 4], + [21269, 4], + [21279, 4], + [21283, 4], + [21287, 4], + [21291, 4], + [21295, 4], + [21300, 2], + [21304, 4], + [21308, 4], + [21312, 4], + [21316, 4], + [21320, 4], + [21325, 4], + [21329, 4], + [21337, 4], + [21341, 2], + [21343, 4], + [21347, 4], + [21351, 4], + [21355, 3], + [21358, 4], + [21362, 4], + [21366, 4], + [21374, 4], + [21378, 4], + [21382, 4], + [21386, 4], + [21390, 4], + [21394, 3], + [21397, 4], + [21406, 4], + [21410, 4], + [21414, 4], + [21418, 4], + [21422, 4], + [21428, 4], + [21432, 4], + [21436, 4], + [21440, 4], + [21444, 4], + [21448, 4], + [21484, 4], + [21488, 4], + [21498, 4], + [21503, 4], + [21522, 4], + [21538, 4], + [21543, 4], + [21547, 4], + [21566, 4], + [21570, 3], + [21574, 4], + [21578, 4], + [21582, 4], + [21586, 4], + [21590, 4], + [21594, 4], + [21599, 4], + [21603, 4], + [21610, 3], + [21614, 4], + [21618, 4], + [21622, 4], + [21633, 4], + [21638, 4], + [21642, 4], + [21646, 4], + [21650, 4], + [21657, 4], + [21661, 4], + [21665, 4], + [21669, 4], + [21673, 4], + [21677, 4], + [21682, 4], + [21692, 4], + [21698, 3], + [21701, 4], + [21706, 3], + [21709, 4], + [21714, 3], + [21731, 4], + [21735, 3], + [21738, 4], + [21755, 4], + [21759, 4], + [21763, 4], + [21767, 4], + [21771, 3], + [21774, 4], + [21778, 4], + [21782, 4], + [21786, 3], + [21789, 4], + [21793, 4], + [21798, 4], + [21802, 4], + [21806, 4], + [21812, 4], + [21819, 4], + [21823, 4], + [21827, 4], + [21836, 3], + [21839, 4], + [21843, 4], + [21847, 4], + [21851, 4], + [21855, 4], + [21859, 4], + [21863, 4], + [21867, 4], + [21871, 3], + [21874, 4], + [21882, 3], + [21887, 4], + [21915, 4], + [21922, 4], + [21926, 4], + [21931, 4], + [21935, 2], + [21937, 4], + [21942, 4], + [21946, 4], + [21950, 4], + [21954, 4], + [21958, 4], + [21962, 4], + [21970, 3], + [21973, 4], + [21977, 3], + [21981, 4], + [21985, 4], + [21989, 4], + [21994, 4], + [21999, 3], + [22002, 4], + [22006, 4], + [22013, 4], + [22017, 4], + [22021, 4], + [22025, 4], + [22029, 4], + [22033, 4], + [22043, 4], + [22047, 4], + [22052, 4], + [22056, 4], + [22063, 4], + [22067, 4], + [22071, 4], + [22077, 4], + [22081, 4], + [22086, 4], + [22091, 4], + [22095, 4], + [22099, 4], + [22103, 4], + [22109, 4], + [22116, 4], + [22120, 4], + [22124, 4], + [22136, 4], + [22143, 3], + [22147, 4], + [22160, 4], + [22164, 4], + [22169, 4], + [22180, 4], + [22187, 4], + [22196, 4], + [22200, 4], + [22207, 4], + [22211, 4], + [22215, 4], + [22222, 4], + [22226, 4], + [22244, 4], + [22255, 4], + [22260, 4], + [22267, 4], + [22272, 4], + [22279, 4], + [22283, 4], + [22304, 2], + [22306, 4], + [22310, 4], + [22314, 4], + [22318, 4], + [22322, 4], + [22326, 4], + [22330, 4], + [22354, 4], + [22359, 4], + [22363, 3], + [22368, 4], + [22372, 4], + [22376, 4], + [22380, 4], + [22385, 4], + [22458, 4], + [22463, 4], + [22469, 4], + [22473, 4], + [22477, 3], + [22480, 4], + [22485, 3], + [22488, 4], + [22494, 4], + [22498, 4], + [22503, 3], + [22506, 4], + [22511, 2], + [22513, 3], + [22516, 4], + [22520, 4], + [22531, 3], + [22534, 4], + [22539, 4], + [22543, 4], + [22547, 3], + [22552, 4], + [22556, 3], + [22559, 4], + [22563, 4], + [22567, 4], + [22571, 4], + [22577, 4], + [22581, 4], + [22585, 4], + [22589, 4], + [22594, 3], + [22598, 4], + [22603, 4], + [22607, 4], + [22612, 3], + [22615, 3], + [22618, 4], + [22622, 4], + [22626, 3], + [22629, 4], + [22633, 4], + [22638, 4], + [22642, 4], + [22646, 4], + [22667, 4], + [22672, 4], + [22676, 4], + [22680, 4], + [22684, 4], + [22699, 4], + [22703, 3], + [22706, 4], + [22711, 4], + [22716, 4], + [22732, 4], + [22738, 2], + [22740, 3], + [22743, 4], + [22747, 2], + [22749, 4], + [22754, 4], + [22758, 4], + [22762, 4], + [22766, 4], + [22772, 4], + [22776, 4], + [22794, 4], + [22799, 4], + [22803, 4], + [22807, 4], + [22811, 4], + [22815, 4], + [22819, 4], + [22823, 4], + [22827, 4], + [22831, 4], + [22835, 4], + [22839, 4], + [22845, 4], + [22849, 4], + [22853, 4], + [22857, 4], + [22861, 4], + [22865, 4], + [22869, 4], + [22873, 4], + [22877, 4], + [22881, 4], + [22885, 4], + [22889, 4], + [22893, 3], + [22896, 4], + [22900, 4], + [22905, 3], + [22908, 4], + [22912, 4], + [22916, 4], + [22920, 4], + [22924, 4], + [22928, 4], + [22932, 4], + [22936, 4], + [22940, 4], + [22944, 4], + [22948, 4], + [22952, 4], + [22957, 2], + [22959, 4], + [22976, 4], + [22980, 4], + [22984, 4], + [22989, 4], + [22994, 4], + [22998, 4], + [23002, 4], + [23006, 4], + [23010, 4], + [23014, 4], + [23018, 3], + [23025, 4], + [23035, 4], + [23045, 4], + [23061, 4], + [23068, 3], + [23071, 3], + [23076, 4], + [23080, 4], + [23085, 4], + [23091, 4], + [23095, 4], + [23099, 4], + [23104, 2], + [23106, 4], + [23116, 4], + [23121, 4], + [23125, 4], + [23134, 4], + [23138, 3], + [23141, 4], + [23145, 4], + [23150, 4], + [23157, 4], + [23161, 4], + [23167, 4], + [23171, 4], + [23175, 4], + [23180, 2], + [23182, 4], + [23186, 4], + [23190, 2], + [23192, 4], + [23196, 4], + [23202, 4], + [23206, 4], + [23210, 4], + [23215, 4], + [23219, 3], + [23222, 4], + [23226, 4], + [23243, 4], + [23248, 4], + [23252, 4], + [23256, 4], + [23261, 4], + [23266, 4], + [23270, 4], + [23274, 4], + [23280, 4], + [23284, 4], + [23288, 4], + [23292, 4], + [23296, 3], + [23299, 4], + [23303, 4], + [23321, 4], + [23326, 4], + [23330, 4], + [23334, 4], + [23338, 4], + [23342, 4], + [23346, 4], + [23351, 4], + [23360, 4], + [23364, 3], + [23377, 4], + [23381, 4], + [23385, 4], + [23389, 4], + [23394, 4], + [23398, 3], + [23401, 4], + [23406, 4], + [23410, 4], + [23414, 4], + [23418, 4], + [23422, 4], + [23426, 4], + [23430, 4], + [23435, 3], + [23438, 4], + [23442, 4], + [23446, 4], + [23450, 4], + [23454, 4], + [23458, 4], + [23462, 4], + [23466, 4], + [23470, 4], + [23474, 4], + [23479, 4], + [23483, 4], + [23487, 3], + [23490, 4], + [23494, 4], + [23500, 4], + [23517, 4], + [23523, 4], + [23527, 4], + [23531, 4], + [23535, 4], + [23540, 3], + [23543, 4], + [23547, 4], + [23551, 4], + [23557, 4], + [23561, 4], + [23565, 4], + [23570, 4], + [23574, 3], + [23577, 3], + [23580, 4], + [23584, 4], + [23588, 3], + [23591, 4], + [23595, 4], + [23599, 4], + [23604, 4], + [23608, 4], + [23612, 3], + [23615, 3], + [23618, 4], + [23622, 4], + [23626, 4], + [23630, 4], + [23637, 4], + [23641, 4], + [23645, 2], + [23648, 4], + [23654, 4], + [23658, 4], + [23662, 4], + [23666, 4], + [23670, 4], + [23674, 4], + [23678, 4], + [23683, 4], + [23687, 4], + [23691, 4], + [23695, 4], + [23699, 4], + [23704, 4], + [23709, 4], + [23713, 4], + [23717, 4], + [23721, 4], + [23725, 4], + [23729, 4], + [23733, 4], + [23737, 4], + [23742, 4], + [23746, 4], + [23750, 3], + [23753, 4], + [23757, 4], + [23761, 4], + [23766, 2], + [23768, 4], + [23772, 4], + [23776, 2], + [23778, 4], + [23782, 4], + [23786, 4], + [23790, 4], + [23794, 4], + [23799, 4], + [23803, 4], + [23807, 4], + [23811, 4], + [23815, 3], + [23818, 4], + [23822, 4], + [23826, 2], + [23828, 4], + [23832, 4], + [23836, 4], + [23840, 3], + [23843, 4], + [23847, 4], + [23851, 4], + [23855, 4], + [23859, 3], + [23862, 4], + [23866, 4], + [23870, 4], + [23874, 4], + [23878, 4], + [23882, 4], + [23887, 4], + [23891, 4], + [23895, 4], + [23899, 4], + [23903, 4], + [23907, 4], + [23911, 4], + [23915, 4], + [23919, 4], + [23923, 4], + [23927, 4], + [23931, 4], + [23935, 4], + [23940, 2], + [23942, 4], + [23946, 4], + [23951, 4], + [23955, 4], + [23959, 4], + [23963, 4], + [23967, 4], + [23971, 2], + [23973, 4], + [23977, 4], + [23981, 4], + [23985, 4], + [23989, 3], + [23992, 4], + [23996, 4], + [24000, 2], + [24002, 4], + [24006, 4], + [24010, 4], + [24014, 4], + [24018, 4], + [24022, 4], + [24026, 4], + [24030, 4], + [24034, 4], + [24038, 4], + [24042, 4], + [24046, 4], + [24050, 4], + [24054, 4], + [24059, 4], + [24063, 4], + [24067, 4], + [24071, 4], + [24075, 4], + [24079, 4], + [24083, 4], + [24087, 4], + [24091, 3], + [24094, 4], + [24098, 4], + [24102, 4], + [24106, 4] + ], + "recipe_sha256": "25f74303456ea46951aa61f986fc565a0cfa980756bc6de4406983b5db0032e1", + "saved_real": 22048, + "selected_lengths": { + "2": 58, + "3": 147, + "4": 969 + }, + "status": "PASS_X4_FOUR_SOURCE_HORNER" +} diff --git a/research/x4-four-source-horner/NOTICE.md b/research/x4-four-source-horner/NOTICE.md new file mode 100644 index 0000000000..f5c541cde2 --- /dev/null +++ b/research/x4-four-source-horner/NOTICE.md @@ -0,0 +1,29 @@ +# Attribution and license + +Prepared for ToikY with substantial OpenAI Codex assistance in task selection, +construction, verification, independent integer implementation, mathematical +review and writing. The two implementations were written by separate Codex +agents; this is not independent human peer review. + +The shared binary-Horner method and pair comparison follow Ross Richardson's +PR945 at `a3245bf22fa2a2eb778b11128cbc605b130d737f`, especially +`research/x4-joint-horner-seed29/joint.py`. The primary constructor adapts its +signed leading-digit convention, cost formula, eligibility and suffix-DP +method to fan-in three/four. No pending executable source is imported at +runtime. PR945's 13,072 backward saving is explicitly credited. + +The copy/unit baseline is Sagar Thakrar's PR696, following icekylinx's +scalar primitive, coefficient work and Horner architecture. The literal +historical X4 word is Jeremy Kothe's PR799 on Chafik Boukhalfa's PR741/SW4 +frames. Douglas R. Colkitt's retained maintainer replay supplies the source +artifacts; their existing source notices remain unchanged. The construction +lineage includes DreamingOfClouds, Dominik Scholz, Dugongue, eumemic, Rohan Arun +and the contributors credited in the inherited packages. + +Related precedent includes PR751's equal-coefficient JP8 fan-in and PR830's +transposed shared work. This package neither claims joint Horner arithmetic +as new nor composes their pending circuits. PR932/961's target forests concern +the separate zero-frame panel and are not combined with this experiment. + +All new files are under the repository's Apache License 2.0. No predecessor +copyright, source notice, license or file under `upstream/` is changed. diff --git a/research/x4-four-source-horner/PROOF.md b/research/x4-four-source-horner/PROOF.md new file mode 100644 index 0000000000..ed82ac1967 --- /dev/null +++ b/research/x4-four-source-horner/PROOF.md @@ -0,0 +1,208 @@ +# Shared Horner work for at most four immutable sources + +This is a finite scalar-circuit construction on the pinned historical PR799 +X4 backward program. It extends Ross Richardson's PR945 pair mechanism to +three and four sources, using the existing PR696 copy/unit lowering as the +baseline. The exact repository base is +`007664306fff84fbb1c9a1b4053b69f439764034`; input byte and Git-object bindings +are recorded in `SOURCES.json`. It does not change the selected certificate or +claim a new kappa. + +## Eligibility and complete boundary identity + +A candidate is a consecutive window of two, three or four scalar ADD events + +`T <- T + q_i S_i`, + +with one identical positive, nonzero frame label. Every `q_i` is a nonzero +dyadic rational. All sources are distinct, none is the target, and neither +the target nor any source is the private coefficient register `W`. No scale, +copy, clear, phase, centre, climb, adapter or other event may intervene. +Consequently every source is immutable throughout the window. Repeated-source +aggregation, source mutation, frame changes and nonconsecutive grouping are +outside this candidate class. + +Write `q_i = sign_i a_i / 2^d_i` in reduced form, with `a_i > 0`. Define + +`k = max_i d_i`, `A_i = a_i 2^(k-d_i)`, +`b = max_i bit_length(A_i)` and `P = sum_i popcount(A_i)`. + +Choose the first source whose `A_i` has its top bit set. Let `sigma` be that +coefficient's sign and initialize `W` by a charged COPY from that source. +Process all remaining set bits in descending bit position. Between positions, +double `W`; for each set bit, add or subtract its source according to +`sigma * sign_i`. After the last bit, the invariant is + +`W = sigma sum_i sign_i A_i S_i = sigma 2^k sum_i q_i S_i`. + +Apply `k` halvings, accumulate `sigma W` into `T`, and clear `W`. Choosing the +leading coefficient's sign as the common sign avoids an extra negation even +when every highest-position contribution is negative. The complete map is + +`(T, S_1, ..., S_m, W) -> (T + sum_i q_i S_i, S_1, ..., S_m, 0)`. + +The entry value of `W` may be arbitrary: COPY overwrites it. The final CLEAR +is charged and erases private work; it does not restore private dirt. The +target may also be arbitrary, and no source is changed. The identity is over +the rationals and applies separately to real and imaginary components. + +The old sequence has the same map and clears `W` after each ADD. The candidate +clears it at the end of the whole window. The states agree at that boundary, +but need not agree at the removed internal macro boundaries. Substitution is +valid in the scalar event projection because no intervening event observes +those internal boundaries. Repeating this argument over disjoint windows +preserves the final scalar map. + +## Full arithmetic price and source access + +The exact count per real component is + +| Operation | Count | +| --- | ---: | +| Initial source COPY | 1 | +| Doublings between bit positions | `b - 1` | +| Other signed source additions | `P - 1` | +| Halvings | `k` | +| Signed target accumulation | 1 | +| Final private CLEAR | 1 | +| **Total** | **`b + P + k + 1`** | + +Each source access is explicit: there are `P` reads of source operands in +this word, including the initializing COPY. Shifting a numerator to align +denominators does not change its popcount. Thus grouping preserves the number +of nonwork source-operand occurrences from the corresponding PR696 words. +It saves shared shifts, target accumulations and clears; it does not obtain +free source access. No new helper or second coefficient register is used. +The complex count is twice the per-component count. + +For the complete backward scalar projection, the recorded count changes +from 71,837 to 60,813 per component, or **143,674 to 121,626** across both +components. The explicit source-operand count remains **19,723** per component. +Counting one read for COPY and unary operations, two for ADD/SUBTRACT and zero +for CLEAR, total operand reads change from **73,196 to 65,431**. These are +literal arithmetic operand occurrences, not a physical source-access or +memory-movement invoice. + +All non-scalar events remain identical and in order. In particular the recorded +paid child profile remains `{1:2548, 2:338, 3:430, 4:194, 5:56, 8:8}`. This +retains the declared child, centre, phase and frame schedule; it does not +independently admit the replacement to the native or hosted supplier compiler. + +## A strict separation from pair partitions + +Zero-based backward program events **9519 through 9522** have frame **37**, +target `L227`, sources `L224, L81, L57, L92`, and coefficients + +`(-1/2, +1/2, -1/2, +1/2)`. + +The four-source word has `b=1`, `P=4`, `k=1`, so costs **7** primitives per +component. A PR696 singleton costs 4, while any shared-Horner pair of these +terms costs 5. Even allowing every partition into arbitrary singles and pairs, +and deleting every intermediate work clear between groups, the minimum is +`5 + 5 - 1 = 9`. A pair with two singletons costs at least 11, and all +singletons cost 13 under the same generous clear discount. The quartet is +therefore strictly better than every partition in that pair/singleton class. +The first three events similarly cost 6 jointly versus at least 8 for pairs +and singletons after clear discounts. These are examples of the larger +candidate class; they are not claims that the optimal global recipe selects +these particular overlapping windows, or lower bounds for arbitrary circuits. + +## Exact selection within a stated finite class + +The complete census contains **16,431** compatible windows: 6,112 pairs, +5,455 triples and 4,864 quartets. The stopping rule is completion of this +census and one exact interval optimization; there is no stochastic circuit +search. The OS assignment seed 22 chose this object and the fan-in cap four. + +Let `g(i,m)` be the PR696 primitive price of the original length-`m` window +starting at event `i`, minus the joint word's price. Admit only windows with +`g(i,m) > m-1`, so their saving strictly exceeds the saving from merely +omitting the window's `m-1` internal work clears. All events outside selected +windows retain the baseline lowering. For suffix optimum `F(i)`, + +`F(i) = max(F(i+1), max_admitted_m [g(i,m) + F(i+m)])`, + +with zero after the final event. Every legal disjoint selection either skips +event `i` or starts one admitted window there, which proves the recurrence by +backward induction. Ties deterministically skip, then prefer the shorter +starting window. The selected recipe has **1,174** windows: 58 pairs, 147 +triples and 969 quartets, saving **11,024** primitives per component. + +This proves optimal disjoint selection only among the admitted windows with +the unchanged lowering elsewhere. It does not prove unrestricted optimality +for fan-in four, arbitrary rescheduling, signed-digit synthesis, general +circuits, or a combined pass that also removes every other redundant clear. + +The same domain and recurrence restricted to pairs produce PR945's **13,072** +two-component saving. This construction saves **22,048**, an additional +**8,976** in the backward orientation. These are alternative recipes, not +additive passes. The retained forward orientation costs **143,658**. The +orientation maximum consequently falls only from **143,674 to 143,658**; +PR945 already achieves that maximum. The additional backward reduction gives +no further improvement to the maximum and no new recurrence exponent. + +## Grid containment and magnitude are separate obligations + +Consider exact symbolic rows in the common formal input basis at a window's +entry. At every integer Horner prefix, `W` is an integer linear combination +of immutable source rows. Its dyadic denominator depth is therefore no +greater than the largest source-row denominator depth. After the full integer +numerator is formed, the value after `h` halvings, for `0 <= h <= k`, is + +`W = sigma 2^(k-h) sum_i q_i S_i`. + +Each summand is an integer multiple, up to sign, of the old per-source final +work value `q_i S_i`. For unit coefficients the source itself supplies the +same grid bound. Sums of dyadic rows cannot have a finer denominator than the +finest summand. The target is untouched until its final update, which equals +the old complete-window target. The arbitrary entry `W` also appears in the +old entry state. Thus the largest exact row-coefficient denominator depth +does not increase under substitution. + +This does **not** establish containment of magnitudes in the old prefix +trace. Joint work can sum several source magnitudes, and common-denominator +alignment can create larger integer intermediates. PR696's single-source +prefix-subsequence proof cannot be reused for this purpose. A positive work +envelope is bounded locally by `sum_i A_i B_i`, where `B_i` bounds source `i`, +and the target endpoint envelope is `B_T + sum_i abs(q_i) B_i`; these must be +checked in the actual program, not assumed smaller. + +The complete exact scalar replay includes **737** formal columns: 728 logical +registers, eight arbitrary private centre inputs and arbitrary `W`. Both the +baseline and candidate attain exact maximum row L1 norm **5,338,828** and +maximum dyadic denominator exponent **19**. The separately implemented +integer-row replay agrees. Its positive scalar-prefix envelope is also +unchanged at **48,299,247,699,832,632,898,063 / 16**. Exact row norm and the +positive envelope are different quantities; both account for coefficient-work +intermediates. The replay verifies the backward shear, restoration of the +504 public dirty helpers, and erasure of the nine private inputs at exit. + +These are exact-arithmetic scalar facts. They do not prove a 192-bit runtime +payload admission, a rounding-error budget, or the all-size precision/tape +theorem. In particular, equal global maxima do not say every individual new +work row occurs in the old trace. + +## Remaining interfaces and provenance + +Every primitive is emitted with the window's common frame label, and no source +is written. This avoids an explicit frame transition inside a replacement. +It does not by itself prove the physical realization, common-label access, +mutable-source contract, or native/hosted source-access pricing. The inherited +emitter advertised private clearing after each scalar macro; the new typed +group would instead advertise clearing after each joint window. Production +integration must represent and admit that changed boundary before treating +the word as a drop-in supplier replacement. + +The abstract non-scalar profile, helper allocation and schedule are retained; +whole-call hosting, physical/frame/phase admission, global invoices, uniform +compilation, rounding/tape and analytic transfer remain unresolved by this +package. A finite all-column replay is not a formal proof of the complete +multiplication theorem. No current frontier, native supplier implementation, +or `upstream/` file is changed. + +Credit goes to Ross Richardson's PR945 for shared pair Horner work, Sagar +Thakrar's PR696 for the copy/unit lowering, icekylinx's scalar primitive and +coefficient-stream lineage, Jeremy Kothe's PR799 X4 program and its retained +construction ancestry. Prepared for ToikY with substantial OpenAI Codex +assistance, including separate implementation and mathematical review. +Apache-2.0; no independent human review is claimed. diff --git a/research/x4-four-source-horner/README.md b/research/x4-four-source-horner/README.md new file mode 100644 index 0000000000..a78342ecdf --- /dev/null +++ b/research/x4-four-source-horner/README.md @@ -0,0 +1,139 @@ +# Four-source Horner work in historical X4 + +**Finite complex-supplier scalar construction; no new kappa.** Sharing one +coefficient-work stream across up to four consecutive source additions saves +**8,976 more backward real-component primitives than PR945's pair-only +construction**. The complete backward scalar projection costs **121,626**, +down from 143,674 under PR696 and 130,602 under PR945. + +The forward orientation is unchanged at 143,658 and binds the maximum. +Consequently the orientation maximum receives **no additional improvement +beyond PR945**. This is useful finite circuit evidence, not a better selected +supplier, global invoice, runtime result or recurrence exponent. + +| Complete scalar projection | PR696 | PR945 pairs | This recipe | +| --- | ---: | ---: | ---: | +| Backward real-component primitives | 143,674 | 130,602 | **121,626** | +| Forward, retained | 143,658 | 143,658 | 143,658 | +| Maximum over orientations | 143,674 | 143,658 | 143,658 | + +The old pre-PR696 backward count is 193,210. PR696's savings are credited to +Sagar Thakrar and are not counted again as new. The pair and four-source +recipes are alternatives; their savings must not be added together. + +## Reproduce + +Run from the repository root with Python 3.11+ and its standard library: + +```sh +python3 -I -B research/x4-four-source-horner/verify.py +python3 -I -B research/x4-four-source-horner/independent.py +python3 -I -B research/x4-four-source-horner/test_package.py +``` + +Expected primary result: + +```text +PASS_X4_FOUR_SOURCE_HORNER candidates=16431 windows=1174 saved=22048 extra_vs_pairs=8976 columns=737 no_new_kappa +``` + +The primary command recomputes the entire census, selection and both complete +backward primitive traces; it also invokes the separate integer implementation, +which checks the retained forward trace. The independent command imports +neither the constructor nor its Fraction replay. Both commands work with `-O`, +use no network or solver, and leave their inputs unchanged. `--json` prints +the checked receipt. `verify.py --emit /absolute/new-file.json` saves the exact +complete backward primitive event stream and refuses an existing destination. + +## New mechanism and complete coverage + +PR945 uses two-source binary Horner words. The new words jointly prepare three +or four dyadic source terms in the same existing private stream, sharing the +shifts, accumulation and final clear. Each source remains unchanged, every +read is charged, and the first COPY handles arbitrary incoming private dirt. +There is no additional helper, frame transition or recursive child. + +A concrete four-source window costs **7** primitives per real component. +Every partition of those four terms into singletons and pairs costs at least +**9**, even after discounting all intermediate clears. This establishes a +strictly larger circuit class, not just more computation in the closed pair +class. [PROOF.md](PROOF.md) gives the literal event indices and full argument. + +The domain is every consecutive length-2/3/4 ADD window in the pinned PR799 +backward program with one target, distinct immutable sources and an identical +nonzero frame. It contains **6,112 pairs, 5,455 triples and 4,864 quartets**. +Of these, 9,652 beat removal of redundant clears alone. Exact interval DP +selects 1,174 disjoint windows: 58 pairs, 147 triples and 969 quartets. This is +optimal only among those admitted windows with PR696 lowering elsewhere. +The search completed its entire domain and stopped. Longer windows, source +reordering, repeated-source aggregation, signed-digit words and arbitrary +circuits are outside scope. + +Two implementations check all 16,431 candidate identities and agree on every +cost record. A suffix DP and a separate prefix DP establish the same optimum. +Their tie policies differ; the receipt distinguishes the independent chosen +window count from the published recipe. The independent engine then checks +the published recipe's optimality and literally emits the same full stream: + +```text +d95c2ce750263e09c1051dad011e0bb436b696424e8d98513efba09908d757a3 +``` + +[EXPECTED.json](EXPECTED.json) includes the complete recipe, census and stream +digests, counts, prefix bounds and separate-engine receipt. [SOURCES.json](SOURCES.json) +pins nine inherited files to the exact base by SHA256 and Git blob ID, and +records PR945's source head. No pending code is imported or executed. + +## Verification and interface limits + +Both exact engines replay all **737** independent input columns: 728 logical +registers, eight private centers and coefficient work. They check every +selected window boundary, the complete signed shear, all 504 dirty-helper +restorations and erasure of all nine private inputs. + +The backward exact maximum row L1 norm remains **5,338,828** and maximum +fractional denominator exponent remains **19**. The positive scalar envelope +also remains **48,299,247,699,832,632,898,063 / 16**. These are different bounds; +the proof does not assume that every joint intermediate matches an old one. +Nonwork source reads remain 19,723 per real component; total arithmetic +operand reads fall from 73,196 to 65,431. These are syntactic counts, not a +physical memory-access invoice. + +Nine independent adverse controls and seven package test groups cover dirty +work, signs, denominator alignment, frame/source aliases, suboptimal and +overlapping recipes, a valid but suboptimal greedy circuit, corrupt pins and +receipts, and minimal offline optimized replay. The baseline lowerer is +compared with retained PR696 on every one of the 38,394 source macros. +See [VALIDATION.md](VALIDATION.md) for executed checks and environment. + +Non-scalar events and their paid profile are retained literally, but these +interpreters do not execute the physical frame, phase or Clifford operations. +Work clears at a joint-window boundary rather than every old macro boundary; +typed production integration and fresh native/hosted admission remain undone. +Uniform compilation, common-label/mutable-source realization, whole-call +hosting, rounding/precision/tape and analytic transfer remain inherited +obligations. No full repository suite, selected cold replay, formal theorem +proof, global invoice or hosted CI success is claimed. + +## Provenance + +Exact base: `007664306fff84fbb1c9a1b4053b69f439764034`. +OS assignment seed **22**, complex supplier. The selected result at that base +is PR890's conditional kappa **0.001661957774647029**, left unchanged. The +historical X4 program is deliberately the object here. [CLAIM.md](CLAIM.md) +records candidate selection, overlap checks, timing and stopping rule. + +At the final refresh, main `bbc600db2fc15007b7c914f4f2b2ed55fa909c87` +selected PR942 U8/T37 at conditional kappa **0.001661960547713947**. +All nine historical inputs remain byte-identical there; this contribution +does not change that selection. See [VALIDATION.md](VALIDATION.md). + +Credit **Ross Richardson's PR945** (`a3245bf22fa2a2eb778b11128cbc605b130d737f`) +for the shared pair-Horner mechanism and comparator, **Sagar Thakrar's PR696**, +**Jeremy Kothe's PR799**, **Chafik Boukhalfa's PR741**, icekylinx and the +retained construction lineage. PR751/830's JP8 fan-in work supplies related +precedent; no first-invention claim is made for joint Horner arithmetic. + +Prepared for **ToikY with substantial OpenAI Codex assistance**, including +separate implementation and mathematical review. No independent human review +is claimed. Apache-2.0; see [NOTICE.md](NOTICE.md). diff --git a/research/x4-four-source-horner/SOURCES.json b/research/x4-four-source-horner/SOURCES.json new file mode 100644 index 0000000000..c8f050849d --- /dev/null +++ b/research/x4-four-source-horner/SOURCES.json @@ -0,0 +1,61 @@ +{ + "base_commit": "007664306fff84fbb1c9a1b4053b69f439764034", + "files": { + "certificates/checkpoints/frontier799.json": { + "git_blob": "1f107b55a2f045fa66d9c35d658b3b79549f5ba6", + "sha256": "9873519224e2db72d6a8c926f51e3e75129671e467948c6f6b03744f8bcfc699" + }, + "docs/research/community-frontier799-review.md": { + "git_blob": "7a2cd0a64199e0aaf93451377acbed3e8c7ae6b7", + "sha256": "bd91c10c67f2a873fd456b95cbb43f715a43dac0e0a66938737d591c6b754052" + }, + "research/complex-dyadic-lowering/lower.py": { + "git_blob": "a2c2889e5be41a0fc30d4dfa5dfcebb03d6d47f8", + "sha256": "eb37d00063dc09323e9aca041d23da749ce17fbd71dade9aaf1c059cab0b9753" + }, + "research/complex-x4-compensation-pairs/SOURCES.json": { + "git_blob": "1ec0330d01ca42155128b68bd85eba17a34d465e", + "sha256": "249aa739194cd8b66562cf4cbeb6b56dceb309eedba8e4e13257a91f80371e8e" + }, + "research/complex-x4-compensation-pairs/inputs/CANONICAL-WORD.json.gz": { + "git_blob": "416757e153fc8095f3827b4ef7dc5ac80986878f", + "sha256": "f1c2ede9276d4447c5857d0e9d32adb52f987b8adb643b45bde2c172d88c6ee9" + }, + "research/complex-x4-compensation-pairs/inputs/LOCAL-CHECKS.json": { + "git_blob": "1c8b6b8dd4819384598dc3fe333ada3f77c90f55", + "sha256": "bbde5cea7bfd5df3d3ee7dfada0ff9d165af43a4d1dec6a9597cbfd8f87cc3b2" + }, + "research/complex-x4-compensation-pairs/inputs/LOCAL-PROGRAMS.json.gz": { + "git_blob": "f3cb79ae401b298bb7514edc5444f77d1a71fdef", + "sha256": "ce194f8465079db575a9ce17ccee1396fa4de0210e2817da2525f95f4f93ebde" + }, + "research/gauge44-frames-x/PROOF-NOTE-FRAMES-X4.md": { + "git_blob": "a456a8127badf654c6b2ac64e54818bfa6ec0837", + "sha256": "39c50420ebb6e8813706a49b2cf759f277c4afac9f6780fc0a7ac6a5fb86e036" + }, + "research/gauge44-frames-x/construction/jx/LOCAL-PINS-jx-X4.json": { + "git_blob": "417e4ba7a1d731f56b24ae68563a963703e33a0b", + "sha256": "95c5114c8e937c2737a1b9f9da97303f2e5e129d39e6dfcc4010e99bfdb9c974" + } + }, + "prior_pair_method": { + "adaptation": "Shared binary Horner and pair eligibility generalized to four sources; separate forward DP and integer replay provided.", + "contributor": "Ross Richardson", + "expected_pair_real_saving": 13072, + "expected_pair_windows": 1586, + "head": "a3245bf22fa2a2eb778b11128cbc605b130d737f", + "path": "research/x4-joint-horner-seed29/joint.py", + "pr": 945, + "source_code_imported": false + }, + "selection_context": { + "kappa": "1661957774647029/1000000000000000000", + "scope": "Context at recorded base, not a runtime dependence or a new bound.", + "selected_record_sha256": "41fb066ff0f43ce472323195e9088d6d888715c13c54eae7b42e357ed5bfc726", + "source_pr": 890 + }, + "source_heads": { + "pr741": "e516b1463606840a15f80aac1995d64ce0092e89", + "pr799": "80e6463157cfc80b85af09e7e2f14748fe2dac60" + } +} diff --git a/research/x4-four-source-horner/VALIDATION.md b/research/x4-four-source-horner/VALIDATION.md new file mode 100644 index 0000000000..e416b321ff --- /dev/null +++ b/research/x4-four-source-horner/VALIDATION.md @@ -0,0 +1,89 @@ +# Executed validation + +Local validation on 2026-10-13 used CPython 3.12.14, macOS 26.5.2 arm64, +and only the Python standard library. The executable was the Codex bundled +Python runtime. No hosted CI, Linux run or independent human review is claimed. + +The exact development base is `007664306fff84fbb1c9a1b4053b69f439764034`. +The experiment was selected and claimed by 08:12 PDT; the completed census +and candidate were available by 08:17. Subsequent work was verification, +fault controls, documentation, overlap checking and publication preparation. +The bounded experiment stopped after the declared complete length-2/3/4 census. + +## Commands and outcomes + +From the repository root, with Python 3.11+: + +```sh +python3 -I -B research/x4-four-source-horner/verify.py +python3 -I -B research/x4-four-source-horner/independent.py +python3 -I -B research/x4-four-source-horner/test_package.py +python3 -I -B scripts/verify_selected_result.py +python3 -B -m unittest discover -s tests -p 'test_selected*.py' +``` + +- Primary full replay: PASS, all 16,431 candidate identities, 1,174 chosen + boundaries, 737 arbitrary input columns, exact stream equality between + engines, 22,048 saved backward primitives and 8,976 beyond pairs. +- Independent integer replay: PASS, all candidate prices and identities, + separate prefix DP at caps 2/3/4, nine adverse controls, retained forward + and both backward traces. Its default command checks 14 shared receipt + fields without importing the primary constructor or Fraction interpreter. +- Seven package test groups: PASS in 68.790 seconds. This includes literal + equality with PR696 on all 38,394 source macros, 216 signed/denominator + triples plus quartet cases, gate-deletion and sign controls, source/frame + boundaries, the strict quartet-versus-pairs example, an endpoint-valid but + suboptimal greedy recipe, and DP versus exhaustive toy partitions. +- Minimal offline relocation under a path containing spaces: both full + checkers PASS under `-I -O -B`, with all package/input bytes preserved. + Corrupt input digest, omitted source pin and integer-to-float receipt + mutation are rejected. These checks are in the seven test groups. +- Selected-record verification at the development base: PASS. All 17 + selected-record regression tests: PASS. The selected record is unchanged. +- Final `verify.py --emit /absolute/new-file.json`: PASS in 12.02 seconds + wall time. Decoding/canonical hashing of the exported stream agrees with + `EXPECTED.json`; a second call to the existing path fails immediately and + preserves its bytes. Timing is a reproduction observation, not a claimed + performance improvement. +- Staged whitespace and local Markdown-link checks: PASS. The patch adds + exactly eleven files under this package and applies cleanly to refreshed + main using a separate temporary Git index. + +Expected primary line: + +```text +PASS_X4_FOUR_SOURCE_HORNER candidates=16431 windows=1174 saved=22048 extra_vs_pairs=8976 columns=737 no_new_kappa +``` + +Candidate stream SHA256 (canonical JSON excluding the final newline): + +```text +d95c2ce750263e09c1051dad011e0bb436b696424e8d98513efba09908d757a3 +``` + +Exact input bytes, including immutable gzip archives, are source-pinned in +`SOURCES.json`. Regenerated event streams are compared as canonical JSON, +not by a compression-container hash. No source archive is regenerated. + +## Refresh and scope + +Before submission, main advanced to +`bbc600db2fc15007b7c914f4f2b2ed55fa909c87`, selecting Jonathan Capalbo's PR942 +U8/T37 at conditional kappa `0.001661960547713947`. Its selected record and +maintainer review were read. Every one of this package's nine input files +was checked against that exact main Git object and remains byte-identical. +This is still a historical PR799 scalar construction, not a proposed T37 +replacement. The base-era PR890 number is context, not the current frontier. + +Recent open PRs were refreshed through #971, together with an all-state +Horner search. PR945 remains open at its recorded head. New #967 concerns +bit helper stars, #968 frame-pair decoders, #969 deferred historical swaps, +#970 bit provenance and #971 triple-decoder verification. None supplies this +three/four-source X4 construction. No savings from those passes are composed. + +Full `make verify`, cold supplier reconstruction, native/hosted admission, +global invoice/assembly, rounding/tape certification and Lean verification +were not run. The only changes are in this new research package. Existing +generators, selected certificates, predecessor files and `upstream/` remain +unchanged. The reproducible exact finite evidence has the limits described +in `PROOF.md`; it is not a proof of the full multiplication theorem. diff --git a/research/x4-four-source-horner/circuits.py b/research/x4-four-source-horner/circuits.py new file mode 100644 index 0000000000..175084886c --- /dev/null +++ b/research/x4-four-source-horner/circuits.py @@ -0,0 +1,146 @@ +"""Bounded fan-in Horner words, extending Ross Richardson's PR945 pair method. + +Prepared for ToikY with substantial OpenAI Codex assistance. Apache-2.0. +Primitive vocabulary and copy/unit lowering credit icekylinx and PR696. +""" +from fractions import Fraction as Q + +WORK = ("W", 0) + + +def need(ok, message): + if not ok: + raise ValueError(message) + + +def coefficient(op): + need(len(op) == 5 and op[0] == "add", "expected ADD") + need(type(op[3]) is int and type(op[4]) is int and op[4] > 0, "rational encoding") + q = Q(op[3], op[4]) + need(q and q.denominator & (q.denominator - 1) == 0, "nonzero dyadic required") + return q + + +def lower(op): + """PR696 baseline, including the per-ADD private clear.""" + tag, target = op[0], tuple(op[1]) + need(target != WORK, "work alias") + if tag == "clear": + return [("clear", target)] + if tag == "copy": + source = tuple(op[2]); need(source != WORK, "work source") + return [("copy", target, source)] + if tag == "scale": + q = Q(op[2], op[3]); a, d = abs(q.numerator), q.denominator + need(a > 0 and a & (a-1) == 0 and d & (d-1) == 0, "nonbinary scale") + shift = a.bit_length() - d.bit_length() + return [("double" if shift > 0 else "halve", target)] * abs(shift) + ([("negate", target)] if q < 0 else []) + q = coefficient(op); source = tuple(op[2]) + need(len({target, source, WORK}) == 3, "ADD alias") + accumulate = "add" if q > 0 else "subtract" + if abs(q) == 1: + return [(accumulate, target, source), ("clear", WORK)] + result = [("copy", WORK, source)] + for bit in bin(abs(q.numerator))[3:]: + result.append(("double", WORK)) + if bit == "1": + result.append(("add", WORK, source)) + result += [("halve", WORK)] * (q.denominator.bit_length() - 1) + return result + [(accumulate, target, WORK), ("clear", WORK)] + + +def compatible(window): + if not 2 <= len(window) <= 4: + return False + if any(len(e) != 3 or e[0] != "scalar" or e[1][0] != "add" or + type(e[2]) is not int or e[2] <= 0 for e in window): + return False + if len({e[2] for e in window}) != 1 or len({tuple(e[1][1]) for e in window}) != 1: + return False + regs = [tuple(window[0][1][1]), WORK] + [tuple(e[1][2]) for e in window] + return len(set(regs)) == len(regs) + + +def joint(window): + need(compatible(window), "incompatible joint window") + qs = [coefficient(e[1]) for e in window] + target = tuple(window[0][1][1]); sources = [tuple(e[1][2]) for e in window] + k = max(q.denominator.bit_length() - 1 for q in qs) + ns = [q.numerator * ((1 << k) // q.denominator) for q in qs] + height = max(abs(n).bit_length() for n in ns) + word, sign = [], None + for bit in range(height - 1, -1, -1): + if sign is not None: + word.append(("double", WORK)) + for n, source in zip(ns, sources): + if abs(n) >> bit & 1: + direction = 1 if n > 0 else -1 + if sign is None: + sign = direction + word.append(("copy", WORK, source)) + else: + word.append(("add" if direction == sign else "subtract", WORK, source)) + word += [("halve", WORK)] * k + word += [("add" if sign == 1 else "subtract", target, WORK), ("clear", WORK)] + need(len(word) == height + sum(abs(n).bit_count() for n in ns) + k + 1, "joint bill") + return word + + +def census(events): + rows = [] + for start in range(len(events)): + for length in (2, 3, 4): + w = events[start:start+length] + if len(w) != length or not compatible(w): + continue + before = sum(len(lower(e[1])) for e in w) + after = len(joint(w)) + rows.append(dict(start=start, length=length, frame=w[0][2], + coefficients=[str(coefficient(e[1])) for e in w], + before=before, after=after, saving=before-after)) + return rows + + +def choose(events, rows, limit=4): + """Exact interval DP; ties skip, then prefer the shorter first window.""" + options = {} + for r in rows: + if r["length"] <= limit and r["saving"] > r["length"] - 1: + options.setdefault(r["start"], []).append(r) + scores = [0] * (len(events) + 5); take = {} + for i in range(len(events)-1, -1, -1): + scores[i] = scores[i+1] + for r in options.get(i, []): + score = r["saving"] + scores[i+r["length"]] + if score > scores[i]: + scores[i] = score; take[i] = r["length"] + selected, i = [], 0 + while i < len(events): + if i in take: + selected.append([i, take[i]]); i += take[i] + else: + i += 1 + return selected, scores[0] + + +def emitted(events, recipe): + lookup = dict(recipe) + need(len(lookup) == len(recipe) and recipe == sorted(recipe), "duplicate or unsorted recipe") + i = 0 + while i < len(events): + e = events[i] + if i in lookup: + length = lookup[i]; window = events[i:i+length] + need(type(length) is int and len(window) == length and compatible(window), "recipe window") + need(not any(j in lookup for j in range(i+1, i+length)), "overlapping recipe") + for op in joint(window): + yield ["primitive", list(op), e[2]] + i += length + else: + if e[0] == "scalar": + for op in lower(e[1]): + yield ["primitive", list(op), e[2]] + else: + yield e + i += 1 + need(all(type(start) is int and 0 <= start < len(events) for start in lookup), "recipe index") diff --git a/research/x4-four-source-horner/independent.py b/research/x4-four-source-horner/independent.py new file mode 100644 index 0000000000..c531782789 --- /dev/null +++ b/research/x4-four-source-horner/independent.py @@ -0,0 +1,515 @@ +"""Independent finite X4 Horner census, forward DP, and integer-dyadic replay. + +No constructor, inherited checker, or sibling implementation is imported. +Prepared for ToikY with substantial OpenAI Codex assistance. Apache-2.0. +""" +import argparse +from collections import Counter +import gzip +import hashlib +import json +import math +from pathlib import Path +import sys + +sys.dont_write_bytecode = True +HERE = Path(__file__).resolve().parent +W = ('W', 0) +INPUTS = HERE.parent / 'complex-x4-compensation-pairs' / 'inputs' +INPUT_HASHES = { + 'CANONICAL-WORD.json.gz': '1c0e9da767d4418f70016af599e4a447a3f7777acabe930318459c0fbbd260aa', + 'LOCAL-CHECKS.json': '4cca9475a0d9a93041696c570cbc8d91a40be76e63196a670256ce7e79521580', + 'LOCAL-PROGRAMS.json.gz': '223c2bb27ad68a4e9468c3ddaece1899d577b661190922fdd25f5976052c4cab', +} + + +def demand(condition, explanation): + if not condition: + raise ValueError(explanation) + + +def canonical(value): + return json.dumps(value, sort_keys=True, separators=(',', ':')).encode() + + +def digest(value): + return hashlib.sha256(canonical(value)).hexdigest() + + +def load_inputs(root=None): + location = Path(root) if root is not None else INPUTS + data = {} + for name, expected in INPUT_HASHES.items(): + raw = (location / name).read_bytes() + data[name] = json.loads(gzip.decompress(raw) if name.endswith('.gz') else raw) + demand(digest(data[name]) == expected, 'immutable input mismatch: ' + name) + return data['LOCAL-PROGRAMS.json.gz'], data['CANONICAL-WORD.json.gz'], data['LOCAL-CHECKS.json'] + + +def dyadic(num, den): + demand(type(num) is int and type(den) is int and den != 0, 'invalid scalar') + if den < 0: + num, den = -num, -den + g = math.gcd(abs(num), den) + num, den = num // g, den // g + demand(num != 0 and den & (den - 1) == 0, 'not a nonzero dyadic') + return num, den.bit_length() - 1 + + +def lower_baseline(scalar): + """PR696 binary expansion independently spelled as primitive instructions.""" + tag, dst = scalar[0], tuple(scalar[1]) + demand(dst != W, 'coefficient work aliases scalar destination') + if tag == 'copy': + demand(tuple(scalar[2]) != W, 'coefficient work aliases scalar source') + return [('copy', dst, tuple(scalar[2]))] + if tag == 'clear': + return [('clear', dst)] + if tag == 'scale': + num, exp = dyadic(*scalar[2:4]) + magnitude = abs(num) + demand(magnitude & (magnitude - 1) == 0, 'nonbinary scale') + shift = magnitude.bit_length() - 1 - exp + result = [('double' if shift > 0 else 'halve', dst)] * abs(shift) + if num < 0: + result.append(('negate', dst)) + return result + demand(tag == 'add' and tuple(scalar[2]) not in (dst, W), 'invalid additive macro') + src = tuple(scalar[2]) + num, exp = dyadic(*scalar[3:5]) + magnitude = abs(num) + if magnitude == 1 and exp == 0: + return [('add' if num > 0 else 'subtract', dst, src), ('clear', W)] + result = [('copy', W, src)] + for digit in reversed(range(magnitude.bit_length() - 1)): + result.append(('double', W)) + if magnitude & (1 << digit): + result.append(('add', W, src)) + result.extend([('halve', W)] * exp) + result.extend([('add' if num > 0 else 'subtract', dst, W), ('clear', W)]) + return result + + +def eligible(window): + if not 2 <= len(window) <= 4: + return False + if any(event[0] != 'scalar' or event[1][0] != 'add' for event in window): + return False + frame = window[0][2] + dst = window[0][1][1] + sources = [tuple(event[1][2]) for event in window] + return (frame != 0 and all(event[2] == frame and event[1][1] == dst for event in window) + and len(set(sources)) == len(window) and tuple(dst) not in sources and W not in sources + and tuple(dst) != W) + + +def lower_joint(window): + """Shared signed binary Horner, overwriting W and charging its final clear.""" + demand(eligible(window), 'window outside the frozen class') + scalars = [event[1] for event in window] + coeff = [dyadic(*scalar[3:5]) for scalar in scalars] + exp = max(pair[1] for pair in coeff) + integers = [num << (exp - e) for num, e in coeff] + top = max(abs(n).bit_length() for n in integers) - 1 + initial = next(i for i, n in enumerate(integers) if abs(n) & (1 << top)) + sign = 1 if integers[initial] > 0 else -1 + result = [('copy', W, tuple(scalars[initial][2]))] + for digit in range(top, -1, -1): + if digit != top: + result.append(('double', W)) + for i, (num, scalar) in enumerate(zip(integers, scalars)): + if digit == top and i == initial: + continue + if abs(num) & (1 << digit): + result.append(('add' if num * sign > 0 else 'subtract', W, tuple(scalar[2]))) + result.extend([('halve', W)] * exp) + result.extend([('add' if sign > 0 else 'subtract', tuple(scalars[0][1]), W), ('clear', W)]) + return result + + +def census(events, max_sources=4): + demand(max_sources in (2, 3, 4), 'invalid fan-in') + result = [] + for start in range(len(events)): + for size in range(2, max_sources + 1): + window = events[start:start + size] + if len(window) != size or not eligible(window): + continue + old = sum(len(lower_baseline(event[1])) for event in window) + new = len(lower_joint(window)) + result.append([start, size, old, new, old - new]) + return result + + +def select_forward(events, candidates): + """Prefix dynamic program; tie policy intentionally independent of suffix DP.""" + ending = {} + for start, size, before, after, saving in candidates: + demand(saving == before - after, 'inconsistent candidate') + if saving > size - 1: + ending.setdefault(start + size, []).append((start, size, saving)) + scores = [0] * (len(events) + 1) + predecessor = [None] * (len(events) + 1) + for end in range(1, len(events) + 1): + scores[end] = scores[end - 1] + predecessor[end] = (end - 1, None) + for start, size, saving in ending.get(end, []): + proposed = scores[start] + saving + if proposed > scores[end]: + scores[end] = proposed + predecessor[end] = (start, [start, size]) + selected, end = [], len(events) + while end: + end, window = predecessor[end] + if window is not None: + selected.append(window) + selected.reverse() + return scores[-1], selected + + +def check_recipe(events, recipe, candidates=None, require_optimal=True): + candidates = census(events) if candidates is None else candidates + by_window = {(row[0], row[1]): row for row in candidates} + previous_end, saving = 0, 0 + for entry in recipe: + demand(isinstance(entry, (list, tuple)) and len(entry) == 2 + and all(type(x) is int for x in entry), 'invalid recipe entry') + start, size = entry + demand(start >= previous_end, 'overlapping or unsorted recipe') + demand((start, size) in by_window, 'ineligible recipe window') + row = by_window[start, size] + demand(row[4] > size - 1, 'does not beat redundant clears alone') + saving += row[4] + previous_end = start + size + optimum, _ = select_forward(events, candidates) + if require_optimal: + demand(saving == optimum, 'recipe is not optimal in the finite window class') + return saving + + +# A row is (denominator exponent, sparse integer numerators). Each operation +# allocates a new row: shallow state copies are safe for boundary comparison. +def row(exp, entries): + entries = {k: n for k, n in entries.items() if n} + if not entries: + return 0, {} + if exp: + cancel = min(exp, min((abs(n) & -abs(n)).bit_length() - 1 for n in entries.values())) + if cancel: + entries = {k: n >> cancel for k, n in entries.items()} + exp -= cancel + return exp, entries + + +def add_rows(left, right, sign=1): + exponent = max(left[0], right[0]) + values = {k: n << (exponent - left[0]) for k, n in left[1].items()} + shift = exponent - right[0] + for k, n in right[1].items(): + values[k] = values.get(k, 0) + sign * (n << shift) + return row(exponent, values) + + +def scalar_pair(num, exp): + if num == 0: + return (0, 0) + cancel = min(exp, (abs(num) & -abs(num)).bit_length() - 1) + return num >> cancel, exp - cancel + + +def add_pairs(left, right): + exp = max(left[1], right[1]) + return scalar_pair((left[0] << (exp - left[1])) + (right[0] << (exp - right[1])), exp) + + +def larger(left, right): + return (left[0] << right[1]) > (right[0] << left[1]) + + +def execute(state, op): + tag, dst = op[:2] + if tag == 'clear': + state[dst] = (0, {}) + elif tag == 'copy': + state[dst] = state[op[2]] + elif tag in ('add', 'subtract'): + state[dst] = add_rows(state[dst], state[op[2]], 1 if tag == 'add' else -1) + elif tag == 'double': + exp, values = state[dst] + state[dst] = (exp - 1, values) if exp else (0, {k: n * 2 for k, n in values.items()}) + elif tag == 'halve': + exp, values = state[dst] + state[dst] = row(exp + 1, values) + elif tag == 'negate': + exp, values = state[dst] + state[dst] = exp, {k: -n for k, n in values.items()} + else: + raise ValueError('unknown primitive ' + str(tag)) + + +def replay(events, selected=None, orientation='backward', logical_count=728, width=112): + demand(orientation in ('forward', 'backward'), 'unknown orientation') + selected = [] if selected is None else selected + if selected: + check_recipe(events, selected, require_optimal=False) + starts = dict(selected) + keys = [('L', i) for i in range(logical_count)] + [('C', i) for i in range(8)] + [W] + state = {key: (0, {i: 1}) for i, key in enumerate(keys)} + envelope = {key: (1, 0) for key in keys} + exact_peak = envelope_peak = (1, 0) + grid_exp = component_count = source_reads = nonwork_reads = operand_reads = boundaries = 0 + counts = Counter() + stream = [] + index = 0 + + def update(op, frame): + nonlocal exact_peak, envelope_peak, grid_exp, component_count, source_reads, nonwork_reads, operand_reads + tag, dst = op[:2] + demand(dst in state and (len(op) == 2 or op[2] in state), 'unknown register') + execute(state, op) + if tag == 'clear': + envelope[dst] = (0, 0) + elif tag == 'copy': + envelope[dst] = envelope[op[2]] + operand_reads += 1 + elif tag in ('add', 'subtract'): + envelope[dst] = add_pairs(envelope[dst], envelope[op[2]]) + operand_reads += 2 + elif tag == 'double': + envelope[dst] = scalar_pair(2 * envelope[dst][0], envelope[dst][1]) + operand_reads += 1 + elif tag == 'halve': + envelope[dst] = scalar_pair(envelope[dst][0], envelope[dst][1] + 1) + operand_reads += 1 + elif tag == 'negate': + operand_reads += 1 + if tag in ('copy', 'add', 'subtract') and dst == W and op[2] != W: + source_reads += 1 + if tag in ('copy', 'add', 'subtract') and op[2] != W: + nonwork_reads += 1 + exact = scalar_pair(sum(abs(n) for n in state[dst][1].values()), state[dst][0]) + if larger(exact, exact_peak): + exact_peak = exact + if larger(envelope[dst], envelope_peak): + envelope_peak = envelope[dst] + grid_exp = max(grid_exp, state[dst][0]) + counts[tag] += 1 + component_count += 1 + stream.append(['primitive', list(op), frame]) + + while index < len(events): + event = events[index] + if index in starts: + size = starts[index] + window = events[index:index + size] + shadow = dict(state) + for entry in window: + for op in lower_baseline(entry[1]): + execute(shadow, op) + for op in lower_joint(window): + update(op, event[2]) + demand(state == shadow, 'all-column window boundary mismatch at ' + str(index)) + boundaries += 1 + index += size + else: + if event[0] == 'scalar': + for op in lower_baseline(event[1]): + update(op, event[2]) + else: + stream.append(event) + index += 1 + for i in range(logical_count): + expected = {i: 1} + if orientation == 'forward' and width <= i < 2 * width: + expected[i - width] = 1 + if orientation == 'backward' and i < width: + expected[i + width] = -1 + demand(state[('L', i)] == (0, expected), 'logical endpoint failure at ' + str(i)) + demand(all(state[key] == (0, {}) for key in keys[logical_count:]), 'private erasure failure') + endpoint = [[list(key), exp, sorted(values.items())] for key, (exp, values) in state.items()] + return { + 'component_primitives': component_count, + 'real_component_primitives': 2 * component_count, + 'primitive_histogram': dict(sorted(counts.items())), + 'source_reads_into_work': source_reads, + 'nonwork_source_reads': nonwork_reads, + 'operand_reads': operand_reads, + 'stream_sha256': digest(stream), + 'endpoint_sha256': digest(endpoint), + 'exact_prefix_l1': [exact_peak[0], 1 << exact_peak[1]], + 'positive_prefix_l1': [envelope_peak[0], 1 << envelope_peak[1]], + 'max_grid_exponent': grid_exp, + 'checked_columns': len(keys), + 'window_boundaries_checked': boundaries, + 'logical_endpoint_verified': True, + 'private_erasure_verified': True, + } + + +def local_identity(window, replacement=None): + """Compare on independent target/source/dirty-W coordinates, before context.""" + demand(eligible(window), 'ineligible local identity') + keys = [tuple(window[0][1][1])] + [tuple(event[1][2]) for event in window] + [W] + original = {key: (0, {i: 1}) for i, key in enumerate(keys)} + changed = dict(original) + for event in window: + for op in lower_baseline(event[1]): + execute(original, op) + for op in lower_joint(window) if replacement is None else replacement: + execute(changed, op) + demand(original == changed, 'local arbitrary-input identity failed') + + +def adverse_controls(events, recipe): + import copy + + def rejected(action, label): + try: + action() + except ValueError: + return + raise ValueError('negative control accepted: ' + label) + + # The highest first digit is on the second source, with negative sign; + # coefficients have unequal denominators and W starts arbitrarily dirty. + coefficients = [(1, 8), (-9, 2), (3, 4), (-1, 1)] + specimen = [['scalar', ['add', ['L', 0], ['L', i + 1], num, den], 7] + for i, (num, den) in enumerate(coefficients)] + local_identity(specimen) + word = lower_joint(specimen) + demand(word[0] == ('copy', W, ('L', 2)) and word[-2][0] == 'subtract', + 'signed high-digit control not exercised') + half = next(i for i, op in enumerate(word) if op[0] == 'halve') + mutants = { + 'omitted final clear': word[:-1], + 'omitted initial copy with dirty work': word[1:], + 'wrong global high-digit sign': word[:-2] + [('add', ('L', 0), W), word[-1]], + 'omitted halving': word[:half] + word[half + 1:], + } + for label, changed in mutants.items(): + rejected(lambda changed=changed: local_identity(specimen, changed), label) + aliased = copy.deepcopy(specimen) + aliased[0][1][2] = ['L', 0] + rejected(lambda: lower_joint(aliased), 'target aliases source') + duplicate = copy.deepcopy(specimen) + duplicate[1][1][2] = duplicate[0][1][2] + rejected(lambda: lower_joint(duplicate), 'duplicate source') + shifted = copy.deepcopy(specimen) + shifted[1][2] = 8 + rejected(lambda: lower_joint(shifted), 'frame change') + rejected(lambda: check_recipe(events, []), 'suboptimal empty recipe') + rejected(lambda: check_recipe(events, [recipe[0], recipe[0]]), 'overlapping recipe') + return 9 + + +def run(root=None, recipe=None): + programs, word, checks = load_inputs(root) + per_size, pair_score = {}, None + for maximum in (2, 3, 4): + cases = census(programs['backward'], maximum) + gain, chosen = select_forward(programs['backward'], cases) + per_size[str(maximum)] = { + 'eligible': len(cases), 'strictly_beyond_clear_only': sum(r[4] > r[1] - 1 for r in cases), + 'gain_component': gain, 'gain_real': 2 * gain, + 'selected': len(chosen), 'census_sha256': digest(cases), + } + if maximum == 2: + pair_score = gain + demand(pair_score * 2 == 13072, 'pair-only comparison changed') + demand(gain * 2 == 22048, 'four-source optimum changed') + if recipe is None: + recipe = chosen + check_recipe(programs['backward'], recipe, cases) + for start, size, _before, _after, _saving in cases: + local_identity(programs['backward'][start:start + size]) + results = { + 'census': per_size, + 'recipe_sha256': digest(recipe), + 'local_candidate_identities': len(cases), + 'adverse_controls_rejected': adverse_controls(programs['backward'], recipe), + 'backward_baseline': replay(programs['backward']), + 'backward_candidate': replay(programs['backward'], recipe), + 'forward_retained': replay(programs['forward'], orientation='forward'), + } + for orientation in ('forward', 'backward'): + key = 'forward_retained' if orientation == 'forward' else 'backward_baseline' + additions = [e[1] for e in programs[orientation] if e[0] == 'scalar' and e[1][0] == 'add'] + units = sum(dyadic(*op[3:5]) in ((1, 0), (-1, 0)) for op in additions) + discount = 2 * (len(additions) + units) + demand(results[key]['real_component_primitives'] + discount == checks[orientation]['real_component_primitive_bound'], + 'PR696 closed-form discount against inherited original invoice mismatch') + demand(results['backward_baseline']['real_component_primitives'] - + results['backward_candidate']['real_component_primitives'] == 22048, + 'emitted saving does not match interval optimum') + demand(results['backward_candidate']['endpoint_sha256'] == results['backward_baseline']['endpoint_sha256'], + 'full endpoint digest mismatch') + return results + + +def check_expected(results, expected): + """Compare immutable receipt fields without importing the other checker.""" + def core(result): + num, den = result['exact_prefix_l1'] + positive_num, positive_den = result['positive_prefix_l1'] + return { + 'exact_prefix_fraction_bits': result['max_grid_exponent'], + 'exact_prefix_row_l1': str(num) if den == 1 else str(num) + '/' + str(den), + 'positive_prefix_row_l1': str(positive_num) if positive_den == 1 else str(positive_num) + '/' + str(positive_den), + 'work_source_reads': result['source_reads_into_work'], + 'nonwork_source_reads': result['nonwork_source_reads'], + 'operand_reads': result['operand_reads'], + 'per_component_opcodes': result['primitive_histogram'], + 'per_component_primitives': result['component_primitives'], + 'real_component_primitives': result['real_component_primitives'], + } + before, after = results['backward_baseline'], results['backward_candidate'] + census_result = results['census'] + observed = { + 'before': core(before), 'after': core(after), + 'baseline_stream_sha256': before['stream_sha256'], + 'candidate_stream_sha256': after['stream_sha256'], + 'boundaries': after['window_boundaries_checked'], + 'recipe_sha256': results['recipe_sha256'], + 'candidate_counts': { + '2': census_result['2']['eligible'], + '3': census_result['3']['eligible'] - census_result['2']['eligible'], + '4': census_result['4']['eligible'] - census_result['3']['eligible'], + }, + 'pair_only_saved_real': census_result['2']['gain_real'], + 'pair_only_windows': census_result['2']['selected'], + 'saved_real': census_result['4']['gain_real'], + 'extra_beyond_pairs_real': census_result['4']['gain_real'] - census_result['2']['gain_real'], + 'formal_columns': after['checked_columns'], + 'local_candidate_identities': results['local_candidate_identities'], + 'forward_retained_real': results['forward_retained']['real_component_primitives'], + } + for key, value in observed.items(): + demand(key in expected and canonical(value) == canonical(expected[key]), + 'independent receipt disagreement: ' + key) + return len(observed) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--inputs', type=Path) + parser.add_argument('--recipe', type=Path, help='JSON list of [start event index, length]') + parser.add_argument('--out', type=Path, help='optional JSON result destination') + parser.add_argument('--json', action='store_true', help='print detailed result JSON') + args = parser.parse_args() + expected = json.loads((HERE / 'EXPECTED.json').read_text()) + recipe = json.loads(args.recipe.read_text()) if args.recipe else expected['recipe'] + if isinstance(recipe, dict): + recipe = recipe['recipe'] if 'recipe' in recipe else recipe['windows'] + results = run(args.inputs, recipe) + if not args.recipe: + check_expected(results, expected) + if args.out: + demand(not args.out.exists(), 'output already exists') + args.out.write_text(json.dumps(results, indent=2, sort_keys=True) + '\n') + if args.json: + print(json.dumps(results, indent=2, sort_keys=True)) + print('PASS_X4_FOUR_SOURCE_INDEPENDENT pair_gain_real=13072 four_gain_real=22048 columns=737 no_new_kappa') + + +if __name__ == '__main__': + main() diff --git a/research/x4-four-source-horner/test_package.py b/research/x4-four-source-horner/test_package.py new file mode 100644 index 0000000000..7bea730bcd --- /dev/null +++ b/research/x4-four-source-horner/test_package.py @@ -0,0 +1,132 @@ +"""Mathematical fault controls and portable package tests; Apache-2.0.""" +import copy +from fractions import Fraction as Q +import importlib.util +import itertools +import json +import os +from pathlib import Path +import shutil +import subprocess +import sys +import tempfile +import unittest +sys.dont_write_bytecode = True +HERE = Path(__file__).resolve().parent +ROOT = HERE.parents[1] +sys.path.insert(0, str(HERE)) +import circuits as C +import verify as V +import independent as I + + +def toy(coefficients): + return [["scalar", ["add", ["L", 0], ["L", i+1], q.numerator, q.denominator], 7] + for i, q in enumerate(map(Q, coefficients))] + + +class PackageTests(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.word, cls.programs, cls.checks = V.inputs() + cls.events = cls.programs["backward"] + + def test_baseline_is_retained_pr696_on_every_macro(self): + spec = importlib.util.spec_from_file_location("p696_checked", ROOT / "research/complex-dyadic-lowering/lower.py") + module = importlib.util.module_from_spec(spec); spec.loader.exec_module(module) + count = 0 + for program in self.programs.values(): + for event in program: + if event[0] == "scalar": + self.assertEqual(C.lower(event[1]), module.lower(event[1])); count += 1 + self.assertEqual(count, 38394) + + def test_signed_denominator_alignment_and_dirty_work(self): + for qs in itertools.product((Q(-5,4), Q(-1), Q(-1,2), Q(1,2), Q(1), Q(5,4)), repeat=3): + V.local_check(toy(qs)) + for qs in ((-3, Q(1,4), Q(-7,8), 2), (Q(-1,2),)*4, (Q(3,8),Q(-5,4),7,Q(-1,16))): + V.local_check(toy(qs)) + w = toy((Q(-3,4), Q(5,8), Q(-1,2), 2)); good = C.joint(w) + for i in range(len(good)): + with self.assertRaises(ValueError): V.local_check(w, good[:i]+good[i+1:]) + changed = list(good); changed[-2] = ("subtract" if good[-2][0] == "add" else "add", *good[-2][1:]) + with self.assertRaises(ValueError): V.local_check(w, changed) + + def test_source_and_frame_boundaries(self): + w = toy((Q(1,2), Q(-3,4), Q(5,8))) + variants=[] + z=copy.deepcopy(w); z[1][2]=8; variants.append(z) + z=copy.deepcopy(w); z[1][1][1]=["L",8]; variants.append(z) + z=copy.deepcopy(w); z[1][1][2]=["L",0]; variants.append(z) + z=copy.deepcopy(w); z[1][1][2]=["L",1]; variants.append(z) + z=copy.deepcopy(w); z[1][1][2]=["W",0]; variants.append(z) + z=copy.deepcopy(w); z[1]=["phase","boundary"]; variants.append(z) + z=copy.deepcopy(w) + for e in z:e[2]=0 + variants.append(z) + for z in variants: + self.assertFalse(C.compatible(z)) + with self.assertRaises(ValueError): C.joint(z) + for n,d in ((True,2),(1,True),(1,3),(0,1),(1,0)): + z=copy.deepcopy(w); z[1][1][3:]=[n,d] + with self.assertRaises(ValueError): C.joint(z) + + def test_quartet_beats_every_pair_partition_after_clear_discount(self): + w=self.events[9519:9523] + self.assertEqual([str(C.coefficient(e[1])) for e in w], ["-1/2","1/2","-1/2","1/2"]) + self.assertEqual(len(C.joint(w)),7) + def prices(i): + if i==len(w):return [(0,0)] + answers=[] + for n in (1,2): + if i+n<=len(w): + cost=len(C.lower(w[i][1])) if n==1 else len(C.joint(w[i:i+n])) + answers.extend((cost+c,1+b) for c,b in prices(i+n)) + return answers + self.assertEqual(min(cost-(blocks-1) for cost,blocks in prices(0)),9) + + def test_greedy_endpoint_success_is_not_optimality(self): + w=self.events[18626:18631]; rows=C.census(w); recipe,score=C.choose(w,rows) + self.assertEqual(score,9); self.assertEqual(recipe,[[0,3],[3,2]]) + greedy=[[0,4]] + V.local_check(w[:4]) # A valid endpoint still loses two primitives. + with self.assertRaisesRegex(ValueError,"not optimal"): I.check_recipe(w,greedy) + self.assertEqual(I.check_recipe(w,recipe),9) + for recipe in ([[0,3],[2,3]],[[True,4]],[[0,5]],[]): + with self.assertRaises(ValueError): I.check_recipe(w,recipe) + + def test_interval_dp_against_exhaustive_partitions(self): + coeff=(Q(-3,4),Q(1,2),Q(5,4),Q(-1),Q(2),Q(-5,8)) + for length in range(2,7): + w=toy(coeff[:length]); rows=C.census(w); opts={} + for row in rows: + if row['saving']>row['length']-1:opts.setdefault(row['start'],[]).append(row) + def brute(i): + if i>=length:return 0 + return max([brute(i+1)]+[r['saving']+brute(i+r['length']) for r in opts.get(i,[])]) + self.assertEqual(C.choose(w,rows)[1],brute(0)) + self.assertEqual(I.select_forward(w,I.census(w))[0],brute(0)) + + def test_minimal_offline_optimized_replay_and_corruption(self): + with tempfile.TemporaryDirectory(prefix="four source package ") as d: + root=Path(d)/"repository with spaces"; package=root/"research/x4-four-source-horner" + shutil.copytree(HERE,package,ignore=shutil.ignore_patterns("__pycache__")) + for name in V.REQUIRED: + dest=root/name; dest.parent.mkdir(parents=True,exist_ok=True); shutil.copyfile(ROOT/name,dest) + before={str(p.relative_to(root)):p.read_bytes() for p in root.rglob('*') if p.is_file()} + env=dict(os.environ);env.pop("PYTHONPATH",None); env["PYTHONDONTWRITEBYTECODE"]="1" + def run(script="verify.py"): + return subprocess.run([sys.executable,"-I","-O","-B",str(package/script)],cwd=root,env=env,text=True,capture_output=True,timeout=180) + result=run(); self.assertEqual(result.returncode,0,result.stdout+result.stderr) + result=run("independent.py");self.assertEqual(result.returncode,0,result.stdout+result.stderr) + self.assertEqual(before,{str(p.relative_to(root)):p.read_bytes() for p in root.rglob('*') if p.is_file()}) + source=root/(V.INPUT+"LOCAL-CHECKS.json"); original=source.read_bytes(); source.write_bytes(original+b" ") + result=run();self.assertNotEqual(result.returncode,0);self.assertIn("source digest",result.stderr);source.write_bytes(original) + source=package/"SOURCES.json";original=source.read_bytes(); data=json.loads(original);data['files'].pop(next(iter(data['files'])));source.write_text(json.dumps(data)) + result=run();self.assertNotEqual(result.returncode,0);self.assertIn("source pin",result.stderr);source.write_bytes(original) + # Change only receipt type; the canonical comparison must not accept int == float. + source=package/"EXPECTED.json";data=json.loads(source.read_bytes());data['saved_real']=22048.0;source.write_text(json.dumps(data)) + result=run();self.assertNotEqual(result.returncode,0);self.assertIn("receipt mismatch",result.stderr) + + +if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/research/x4-four-source-horner/verify.py b/research/x4-four-source-horner/verify.py new file mode 100644 index 0000000000..50a57b0d15 --- /dev/null +++ b/research/x4-four-source-horner/verify.py @@ -0,0 +1,220 @@ +#!/usr/bin/env python3 +"""Exact four-source X4 Horner construction; finite scalar evidence, no kappa.""" +import argparse +from collections import Counter +from fractions import Fraction as Q +import gzip +import hashlib +import json +from pathlib import Path +import sys +sys.dont_write_bytecode = True +HERE = Path(__file__).resolve().parent +ROOT = HERE.parents[1] +sys.path.insert(0, str(HERE)) +import circuits as C + +INPUT = "research/complex-x4-compensation-pairs/inputs/" +BASE = "007664306fff84fbb1c9a1b4053b69f439764034" +REQUIRED = { + INPUT + "CANONICAL-WORD.json.gz", INPUT + "LOCAL-PROGRAMS.json.gz", INPUT + "LOCAL-CHECKS.json", + "research/complex-x4-compensation-pairs/SOURCES.json", "research/complex-dyadic-lowering/lower.py", + "research/gauge44-frames-x/PROOF-NOTE-FRAMES-X4.md", + "research/gauge44-frames-x/construction/jx/LOCAL-PINS-jx-X4.json", + "certificates/checkpoints/frontier799.json", "docs/research/community-frontier799-review.md", +} +need = C.need + + +def canonical(x): + return json.dumps(x, sort_keys=True, separators=(",", ":"), allow_nan=False) + + +def digest(x): + return hashlib.sha256(canonical(x).encode()).hexdigest() + + +def read(p): + b = p.read_bytes() + return json.loads(gzip.decompress(b) if p.suffix == ".gz" else b) + + +def inputs(root=ROOT): + pins = read(HERE / "SOURCES.json") + need(pins["base_commit"] == BASE, "source base") + need(REQUIRED == set(pins["files"]), "missing or unexpected source pin") + for name, record in pins["files"].items(): + b = (root / name).read_bytes() + need(hashlib.sha256(b).hexdigest() == record["sha256"], "source digest: " + name) + need(hashlib.sha1(b"blob " + str(len(b)).encode() + b"\0" + b).hexdigest() == record["git_blob"], "source blob: " + name) + word = read(root / INPUT / "CANONICAL-WORD.json.gz") + programs = read(root / INPUT / "LOCAL-PROGRAMS.json.gz") + checks = read(root / INPUT / "LOCAL-CHECKS.json") + need((word["v"], word["R"]) == (112, 504), "X4 dimensions") + for orientation in ("forward", "backward"): + need(digest(programs[orientation]) == checks[orientation]["sha256"], "source program binding") + return word, programs, checks + + +class Replay: + def __init__(self, n=728): + regs = [("L", i) for i in range(n)] + [("C", i) for i in range(8)] + [C.WORK] + self.rows = {r: {i: Q(1)} for i, r in enumerate(regs)} + self.envelope = {r: Q(1) for r in regs}; self.positive_peak = Q(1) + self.count = 0; self.opcodes = Counter(); self.peak = Q(1); self.grid = 0 + self.operand_reads = 0; self.nonwork_source_reads = 0; self.work_source_reads = 0 + + def apply(self, op): + tag, target = op[0], tuple(op[1]) + need(target in self.rows, "unknown target") + if tag == "clear": + row = {}; bound = Q(0) + elif tag == "copy": + source = tuple(op[2]); row = dict(self.rows[source]); self.operand_reads += 1 + self.nonwork_source_reads += source != C.WORK + bound = self.envelope[source] + elif tag in ("double", "halve", "negate"): + factor = {"double": Q(2), "halve": Q(1, 2), "negate": Q(-1)}[tag] + row = {j: x * factor for j, x in self.rows[target].items()}; self.operand_reads += 1 + bound = self.envelope[target] * abs(factor) + elif tag in ("add", "subtract"): + source = tuple(op[2]); need(source != target, "primitive alias") + sign = 1 if tag == "add" else -1 + row = dict(self.rows[target]); self.operand_reads += 2 + self.nonwork_source_reads += source != C.WORK + bound = self.envelope[target] + self.envelope[source] + for j, x in self.rows[source].items(): + value = row.get(j, Q(0)) + sign*x + if value: row[j] = value + else: row.pop(j, None) + else: + raise ValueError("unknown primitive") + self.rows[target] = row; self.count += 1; self.opcodes[tag] += 1 + self.envelope[target] = bound; self.positive_peak = max(self.positive_peak, bound) + if tag in ("copy", "add", "subtract") and target == C.WORK and tuple(op[2]) != C.WORK: + self.work_source_reads += 1 + self.peak = max(self.peak, sum(map(abs, row.values()), Q(0))) + for value in row.values(): + need(value.denominator & (value.denominator-1) == 0, "nondyadic prefix") + self.grid = max(self.grid, value.denominator.bit_length()-1) + + def endpoint(self, backward=True): + for r in range(728): + expected = {r: Q(1)} + if backward and r < 112: expected[r+112] = Q(-1) + if not backward and 112 <= r < 224: expected[r-112] = Q(1) + need(self.rows[("L", r)] == expected, "scalar endpoint row " + str(r)) + need(all(not row for r, row in self.rows.items() if r[0] != "L"), "dirty private endpoint") + + def receipt(self): + return dict(per_component_primitives=self.count, real_component_primitives=2*self.count, + exact_prefix_row_l1=str(self.peak), exact_prefix_fraction_bits=self.grid, + positive_prefix_row_l1=str(self.positive_peak), work_source_reads=self.work_source_reads, + per_component_opcodes=dict(sorted(self.opcodes.items())), + operand_reads=self.operand_reads, nonwork_source_reads=self.nonwork_source_reads) + + +def local_check(window, primitive_word=None): + target = tuple(window[0][1][1]); regs = [target] + [tuple(e[1][2]) for e in window] + [C.WORK] + replay = Replay(); replay.rows = {r: {i: Q(1)} for i, r in enumerate(regs)} + replay.envelope = {r: Q(1) for r in regs} + for op in primitive_word if primitive_word is not None else C.joint(window): replay.apply(op) + expected = {0: Q(1)} + expected.update({i+1: C.coefficient(e[1]) for i,e in enumerate(window)}) + need(replay.rows[target] == expected, "joint local target") + need(not replay.rows[C.WORK], "joint dirty work not cleared") + for i, r in enumerate(regs[1:-1], 1): need(replay.rows[r] == {i: Q(1)}, "source changed") + + +def replay_full(events, recipe): + before, after = Replay(), Replay() + choices = dict(recipe); i = 0; boundaries = 0 + while i < len(events): + event = events[i] + if i in choices: + length = choices[i]; window = events[i:i+length] + for e in window: + for op in C.lower(e[1]): before.apply(op) + for op in C.joint(window): after.apply(op) + target = tuple(event[1][1]) + need(before.rows[target] == after.rows[target] and not before.rows[C.WORK] and not after.rows[C.WORK], "window boundary") + boundaries += 1; i += length + else: + if event[0] == "scalar": + for op in C.lower(event[1]): before.apply(op); after.apply(op) + i += 1 + before.endpoint(); after.endpoint() + need(before.rows == after.rows, "full endpoint differs") + return before.receipt(), after.receipt(), boundaries + + +def verify(root=ROOT): + word, programs, checks = inputs(root) + events = programs["backward"]; rows = C.census(events) + recipe, saving = C.choose(events, rows) + pairs, pair_saving = C.choose(events, rows, 2) + for row in rows: local_check(events[row["start"]:row["start"]+row["length"]]) + before, after, boundaries = replay_full(events, recipe) + need(before["real_component_primitives"] == 143674, "PR696 baseline count") + need(pair_saving*2 == 13072 and len(pairs) == 1586, "PR945 pair comparator") + need(before["per_component_primitives"] - after["per_component_primitives"] == saving, "complete saving") + need(after["exact_prefix_fraction_bits"] <= before["exact_prefix_fraction_bits"], "full scalar grid increased") + need(Q(after["exact_prefix_row_l1"]) <= Q(before["exact_prefix_row_l1"]), "full scalar prefix increased") + need(Q(after["positive_prefix_row_l1"]) <= Q(before["positive_prefix_row_l1"]), "full positive envelope increased") + emitted = list(C.emitted(events, recipe)); baseline = list(C.emitted(events, [])) + need([e for e in emitted if e[0] != "primitive"] == [e for e in events if e[0] != "scalar"], "non-scalar stream") + forward_count = sum(len(C.lower(e[1])) for e in programs["forward"] if e[0] == "scalar")*2 + import independent as I + independent = I.run(recipe=recipe) + alternate_rows = [[r["start"],r["length"],r["before"],r["after"],r["saving"]] for r in rows] + need(alternate_rows == I.census(events,4), "independent complete census differs") + for label, actual, stream in (("backward_baseline", before, baseline), ("backward_candidate", after, emitted)): + other = independent[label] + need(other["real_component_primitives"] == actual["real_component_primitives"], "independent price") + need(other["primitive_histogram"] == actual["per_component_opcodes"], "independent opcodes") + need(other["stream_sha256"] == digest(stream), "independent emitted stream") + need(Q(*other["exact_prefix_l1"]) == Q(actual["exact_prefix_row_l1"]), "independent exact prefix") + need(Q(*other["positive_prefix_l1"]) == Q(actual["positive_prefix_row_l1"]), "independent positive prefix") + need(other["max_grid_exponent"] == actual["exact_prefix_fraction_bits"], "independent grid") + need(other["operand_reads"] == actual["operand_reads"] and other["source_reads_into_work"] == actual["work_source_reads"] + and other["nonwork_source_reads"] == actual["nonwork_source_reads"], "independent reads") + need(independent["forward_retained"]["real_component_primitives"] == forward_count, "forward retained invoice") + result = dict(status="PASS_X4_FOUR_SOURCE_HORNER", base_commit=BASE, assignment_seed=22, + candidate_counts=dict(sorted(Counter(r["length"] for r in rows).items())), + candidates_sha256=digest(rows), recipe=recipe, recipe_sha256=digest(recipe), + selected_lengths=dict(sorted(Counter(n for _,n in recipe).items())), + before=before, after=after, boundaries=boundaries, formal_columns=737, + pair_only_saved_real=2*pair_saving, pair_only_windows=len(pairs), + saved_real=2*saving, extra_beyond_pairs_real=2*(saving-pair_saving), + forward_retained_real=forward_count, orientation_max_before=max(forward_count,before["real_component_primitives"]), + orientation_max_after=max(forward_count,after["real_component_primitives"]), + baseline_stream_sha256=digest(baseline), candidate_stream_sha256=digest(emitted), + non_scalar_sha256=digest([e for e in events if e[0] != "scalar"]), + local_candidate_identities=len(rows), no_new_kappa=True) + result["independent"] = independent + result["eligible_beyond_clear_only"] = sum(r["saving"] > r["length"]-1 for r in rows) + return result + + +def main(): + p=argparse.ArgumentParser(); p.add_argument("--write", type=Path); p.add_argument("--json", action="store_true") + p.add_argument("--emit", type=Path, help="save the checked complete backward primitive event stream to a new JSON file") + args=p.parse_args() + for destination in (args.write, args.emit): + if destination is not None: need(not destination.exists(), "output already exists") + result=verify() + if args.write: + with args.write.open("x") as f: f.write(json.dumps(result,indent=2,sort_keys=True)+"\n") + else: + need(canonical(result) == canonical(read(HERE / "EXPECTED.json")), "result receipt mismatch") + if args.emit: + _, programs, _ = inputs() + stream = list(C.emitted(programs["backward"], result["recipe"])) + need(digest(stream) == result["candidate_stream_sha256"], "emitted output hash") + with args.emit.open("x") as f: f.write(canonical(stream)+"\n") + if args.json: print(json.dumps(result, sort_keys=True)) + print("PASS_X4_FOUR_SOURCE_HORNER candidates=%d windows=%d saved=%d extra_vs_pairs=%d columns=737 no_new_kappa" % + (result["local_candidate_identities"], result["boundaries"], result["saved_real"], result["extra_beyond_pairs_real"])) + + +if __name__ == "__main__": main()