diff --git a/.github/workflows/connector-domain-completeness.yml b/.github/workflows/connector-domain-completeness.yml new file mode 100644 index 0000000000..5746729b7d --- /dev/null +++ b/.github/workflows/connector-domain-completeness.yml @@ -0,0 +1,27 @@ +name: Connector representation domain audit + +on: + workflow_dispatch: + pull_request: + paths: + - 'research/connector-domain-completeness/**' + - 'research/connector-covering-code/cycle_search.cpp' + - 'research/connector-covering-code/README.md' + - '.github/workflows/connector-domain-completeness.yml' + +permissions: + contents: read + +jobs: + verify: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Exact representation domains and compiled rejection controls + env: + CXX: g++ + run: python -I -O -B research/connector-domain-completeness/verify.py --controls diff --git a/research/connector-domain-completeness/README.md b/research/connector-domain-completeness/README.md new file mode 100644 index 0000000000..dc58535f17 --- /dev/null +++ b/research/connector-domain-completeness/README.md @@ -0,0 +1,190 @@ +# Complete representation domains for the simple seven-source search + +Every simple restored universal word in the pinned search's A/B multiplicity +classes has a representative in its low-template, high-path, gap and initial +domain construction. This closes the **representation** part of +[PR3244's handoff](https://github.com/CrocSwap/integer-mult-bounds/discussions/1317#discussioncomment-19002964). +It does not certify a completed search or the full `f(7)=24` claim. + +The executable subject is conorholds' +[`cycle_search.cpp`](../connector-covering-code/cycle_search.cpp), SHA256 +`597844fc32cde19c1d4104633fa6d3eb0d28c1ca140f8f3d2ba2cb632ecd30d1`, +on canonical main `463113d675af7410ac91d53a4fed51ec6494eb9a`. +Predecessor [PR3224](https://github.com/CrocSwap/integer-mult-bounds/pull/3224) +checks capacity; [PR3244](https://github.com/CrocSwap/integer-mult-bounds/pull/3244), +head `5964d7f22ad9cd9c27a1d2eb0b897f52b9425a13`, checks propagation and the +incidence of *emitted* templates. Neither establishes that the emitted +representation domain covers every allowed word. Their executables are not +dependencies of this package, and their findings are not rerun here. + +## Contract and result + +A word toggles one coordinate of `F2^7` at each step. Its prefix set contains +the states immediately before the steps. It is restored when its final state +is zero, simple when its prefix states are distinct, and universal when their +pairwise XORs cover `F2^7`. The two classes are: + +| Pattern | Three high-coordinate counts | Four low-coordinate counts | +| --- | --- | --- | +| A | `(6,4,4)` | `(2,2,2,2)` | +| B | `(4,4,4)` | `(4,2,2,2)` | + +These are premises, not an assertion that all possible seven-source words +belong to these classes. Full-word rotation/reversal and permutations among +equal-count coordinates are allowed. The proof concerns representation before +`capacity` and `propagate`; those are separate soundness obligations. + +The independent checks establish exact set equality, not just matching totals: + +| Domain | Independent enumeration | Source result | +| --- | --- | --- | +| Low A | All 2,520 labeled multiset words; 624 universal | Exactly 5 symmetry orbits | +| Low B | All 18,900 labeled multiset words; 7,860 universal | Exactly 77 symmetry orbits | +| Simple high paths from zero | All vertex sequences in `Q3`; 112 paths | Exactly 106 signatures | +| Translated high candidates | Every signature at each of 8 origins | Exactly 848 candidates | +| Initial domains | Both patterns, all first/second lengths 0..7 | 256 exact comparisons | +| A gap vectors | Eight entries in 0..7 summing to 14 | All 102,552, in the same order | +| B gap vectors | Ten entries in 0..7 summing to 12 | All 286,780, in the same order | + +The 106 high-path classes comprise 100 singleton and six two-path classes. +All 82 native template constructors execute successfully before their rows +are admitted to the comparison. +All six nontrivial replacements are also checked inside a restored full-word +fixture at all eight high origins. The fixtures need not be simple or +universal: their purpose is to test preservation of the entire prefix set, +endpoint and coordinate counts under the replacement. + +## Representation proof + +**1. Project and choose a low orbit.** Delete the high-coordinate letters of +an allowed full word. The resulting low word is restored with the tabulated +counts. Every full prefix projects to a low prefix, so universality of the +full word implies all 16 low differences occur. Rotation of a restored word +translates its prefix set, reversal reverses the closed walk, and coordinate +permutations are invertible linear maps. Each preserves simplicity, restoration +and difference coverage. In B the four-use low label is fixed; the other three +labels may be permuted. + +The Python oracle assigns position subsets to each label, without the source's +first-appearance restriction. It constructs complete group orbits using every +allowed permutation, both orientations and every rotation. The exact minimum +representative of each orbit equals the source output. In particular, B words +beginning with a two-use label are included. The orbit sizes are A: +`48 x 1, 96 x 2, 192 x 2`; B: `30 x 2, 60 x 20, 120 x 55`. +First-appearance renaming used by the source yields the lexicographically +smallest allowed relabeling, so it agrees with this explicit group action. + +**2. Split into high paths.** Rotate at a block boundary and write the full +word as a high run followed by one low step, repeated 8 or 10 times. The low +state is fixed during a high run. Simplicity therefore makes each run a simple +path in the eight-vertex `Q3`, including its initial and final high states. +It has length between zero and seven. Its endpoint is a prefix state before +the following low step, so the entire visited high set is part of the block's +full prefix set. Empty runs are allowed and contribute one prefix state. + +**3. Compress only by sufficient data.** Translate a high path to start at +zero. Its signature is `(visited vertex mask, final vertex, three coordinate +counts)`. Replacing it by another path with that signature preserves its +translated prefix set and final state. Later block origins therefore remain +unchanged, as do all coordinate totals. Replacing any or every block preserves +the full prefix set, restoration and simplicity, including disjointness of +blocks with the same low state. Hence it also preserves universality. + +The independent oracle lists all ordered subsets of the seven nonzero vertices +and keeps precisely those with Hamming-adjacent successive vertices, rather +than using the source's coordinate DFS. It checks every source signature, +every retained representative and all eight translations. Order is genuinely +discarded: `[1,0,2,0,1,0,2]` and `[2,0,1,0,2,0,1]` share signature +`(255,1,3,2,2)`. The proof above explains why this collision is safe. + +**4. Enumerate gaps and include the starting candidate.** The high-run lengths +sum to 14 in A and 12 in B. `Engine::enumerate` visits every vector in +`{0,...,7}^blocks` with that sum exactly once: at each recursive level it tries +every allowed next entry, and accepts a terminal prefix exactly when the +remaining sum is zero. The independent oracle chooses separator positions +(stars and bars), filters entries above seven and compares the complete ordered +byte stream. Inclusion-exclusion independently gives the same cardinalities: + +`sum_j (-1)^j binom(blocks,j) binom(total-8j+blocks-1,blocks-1)`. + +Normalize the high starting state to zero. Each high step reverses Hamming +parity; low steps leave high parity unchanged. Thus the parity required by +`domains_for` is exactly the parity of the preceding gap sum. The first domain +requires origin zero; later domains allow every origin of that parity. The +translated candidate is present by step 3. The 256 source comparisons exercise +every first-domain length and every later-domain length/parity combination in +both patterns. Although they use the first two slots as representatives, the +source loop uses only the gap length, the carried parity and whether the slot +is first. This last observation is a source-inspected induction, not an +exhaustive test of every position in every composition. + +Together these steps give an admitted representation for every allowed word, +up to the stated symmetries and safe path replacement. They do not prove that +later pruning or branching exhausts all those representations. + +## Reproduce and failure controls + +Requires Python 3.12 and a C++17 compiler (`CXX`, default `c++`); no Python +third-party packages. Builds and captures use a private temporary directory. +Direct replay needs only this package and the two declared inputs, not Git. +Local ordinary and optimized replays used CPython 3.12.12 and Apple Clang +21.0.0 on macOS arm64. The dedicated Linux workflow declares the native build; +hosted CI is separate from this local evidence. + +```sh +python3.12 -I -B scripts/research_package.py --package research/connector-domain-completeness +python3.12 -I -O -B research/connector-domain-completeness/verify.py --controls +``` + +[RESULT.json](RESULT.json) contains the deterministic counts, complete-domain +digests and a quotient collision. Normal replay compares against this receipt; +`--emit` prints a newly computed receipt without overwriting it. + +The catalogue and initial domains are read from an unchanged, compiled private +snapshot of the pinned C++ source. **Gap enumeration uses two explicit, +uniqueness-checked instrumentation replacements**: emit a gap at the existing +composition counter; return at the capacity call. This retains the recursive +loop, terminal test and bounds while bypassing capacity and all word search. +The claim about the original loop also depends on the written source +correspondence above. The instrumentation is not a full native census. + +Four compiled semantic mutants remove a low orbit, discard path counts, reset +the carried starting parity, or exclude length-seven gaps. All must be rejected +by the independent oracle. Truncated catalogue/gap streams and an ambiguous +instrumentation anchor must also fail. Explicit Python checks remain enabled +under `-O`. Input hashes are checked before compilation. + +## Limits + +This is author-checked executable and written evidence, with a separate AI +worker's low-word/path enumeration agreeing; it is not independent human or +formal-kernel verification. The retained scientific baseline and selected +frontier are unchanged. No full B census, complete `f(7)=24` validation, new +supplier, physical cost reduction or new kappa is claimed. + +## Open next questions + +The remaining search obligation is to connect complete domain coverage to the +actual branching and exhaustion receipts: inspect every leaf/abort transition +and bind all requested template IDs and flags to a complete, source-pinned +run. A useful first step is a small explicit Cartesian-domain oracle for +`Engine::search` with successful, unsatisfiable and interrupted controls; it +should precede a separately budgeted independent full B run. Capacity and +propagation findings in PR3224/3244 remain separately scoped evidence. The +literature/classification, multiplicity reduction and non-simple branch also +remain outside this audit. No further census is automatically proposed. + +## Credit + +Submitted for @krzysztofwojt with substantial OpenAI Codex assistance in +investigation, proof, implementation, checking and writing. A Luna worker +performed read-only overlap extraction and a separate low-word/path enumeration; +the primary agent checked its counts against the production replay. New material +is Apache-2.0. + +Credit conorholds for the source construction and search; commdata2338 for +PR3224's capacity audit; Nick Petalas for PR3244's propagation audit and the +released handoff; Nicholas Stone for the parity correction; Aaron Wang for the +earlier word/set engines; James Reed for the false-prune audit; Ross Richardson +for the paired-readout model; and Douglas Colkitt for the retained framework and +Gray upper witness. Their source notices and frozen evidence are unchanged. diff --git a/research/connector-domain-completeness/RESULT.json b/research/connector-domain-completeness/RESULT.json new file mode 100644 index 0000000000..a1ab8d405e --- /dev/null +++ b/research/connector-domain-completeness/RESULT.json @@ -0,0 +1,86 @@ +{ + "gaps": { + "A": { + "blocks": 8, + "compositions": 102552, + "high_steps": 14, + "ordered_bytes_sha256": "5ab7d9f9097902bbd4d3bc17b86a64f390a73a55314f6381bd9c32968db6c2bc" + }, + "B": { + "blocks": 10, + "compositions": 286780, + "high_steps": 12, + "ordered_bytes_sha256": "d8bc5a7da0b2fb50d682af11918fea76642c22f91f71257a70d17253771c3835" + } + }, + "high_paths": { + "class_size_histogram": { + "1": 100, + "2": 6 + }, + "collision_example": { + "key": [ + 255, + 1, + 3, + 2, + 2 + ], + "words": [ + [ + 1, + 0, + 2, + 0, + 1, + 0, + 2 + ], + [ + 2, + 0, + 1, + 0, + 2, + 0, + 1 + ] + ] + }, + "literal_paths": 112, + "quotient_classes": 106, + "quotient_keys_sha256": "2bb00bb7d60fd10589456d2b0c1531d093a609932690b237f1a91b22d985c7c0", + "translated_replacement_controls": 48 + }, + "low_words": { + "A": { + "labeled_words": 2520, + "orbit_sizes": { + "48": 1, + "96": 2, + "192": 2 + }, + "orbits": 5, + "representatives_sha256": "9a38385bc5d0d689b43a8ced78f8a44cc3b748440dedbcba5ffb47cc94c27fac", + "universal_words": 624 + }, + "B": { + "labeled_words": 18900, + "orbit_sizes": { + "30": 2, + "60": 20, + "120": 55 + }, + "orbits": 77, + "representatives_sha256": "f97d1ead4847a1e9daa7f22c32a7350c7a71add18c8de644502a24c1bd0f0f71", + "universal_words": 7860 + } + }, + "native_catalogue": { + "candidates": 848, + "catalogue_sha256": "6146eec89b9d255a6d6f932b09f79e6bd673b797642fce32b5a5e5124195cff5", + "initial_domain_cases": 256 + }, + "scope": "Complete representation domains for the pinned simple A/B contract; no full census or kappa claim.", + "source_sha256": "597844fc32cde19c1d4104633fa6d3eb0d28c1ca140f8f3d2ba2cb632ecd30d1" +} diff --git a/research/connector-domain-completeness/SOURCES.json b/research/connector-domain-completeness/SOURCES.json new file mode 100644 index 0000000000..8910aef370 --- /dev/null +++ b/research/connector-domain-completeness/SOURCES.json @@ -0,0 +1,30 @@ +{ + "schema_version": 1, + "base_commit": "463113d675af7410ac91d53a4fed51ec6494eb9a", + "files": [ + { + "path": "certificates/selected-result.json", + "usage": "provenance", + "git_blob": "b1fea0c94436b236cc2b7d41a7be032811b94c81", + "sha256": "bb2eaa58647b353f88d0aec2eafb9d30df1be53589231b23e12ceef3e4bad129" + }, + { + "path": "docs/research/agent-task-catalog.json", + "usage": "provenance", + "git_blob": "67f085acd86acd7d4e03922d9cf4b26bca66fed5", + "sha256": "47b42433f5a85809a3aadd29c2c339da2c6ed728e4f7762df6b88bccb7874cf0" + }, + { + "path": "research/connector-covering-code/README.md", + "usage": "input", + "git_blob": "c194503e34e43988d5f83fec70a6f94e89e3db5d", + "sha256": "35252e16e58481df87fc7ac3eb7326bf87e991f9fd8f7e30d14716c16f2152e4" + }, + { + "path": "research/connector-covering-code/cycle_search.cpp", + "usage": "input", + "git_blob": "72c8255384c117a0c616398d7982451e6f7a1021", + "sha256": "597844fc32cde19c1d4104633fa6d3eb0d28c1ca140f8f3d2ba2cb632ecd30d1" + } + ] +} diff --git a/research/connector-domain-completeness/TASK.json b/research/connector-domain-completeness/TASK.json new file mode 100644 index 0000000000..db780e0891 --- /dev/null +++ b/research/connector-domain-completeness/TASK.json @@ -0,0 +1,111 @@ +{ + "schema_version": 1, + "task_id": "census-pruning-audit", + "priority_revision": 6, + "base_commit": "463113d675af7410ac91d53a4fed51ec6494eb9a", + "original_card": { + "id": "census-pruning-audit", + "question": "Does the reported word-census parity-pruning error invalidate a specific exclusion we still rely on, and what bounded repair is justified?", + "starting_points": [ + "research/f7-weight-parity-census-correction/README.md", + "docs/research/research-family-status.md" + ], + "methods": [ + "Independently reconstruct the tiny counterexample and trace one affected exclusion to its exact pruning code.", + "Compare corrected and unpruned enumeration on a small exhaustive domain, then audit the changed pruning implication." + ], + "acceptance_gate": "Pin the old and proposed corrected engines, distinguish a disproved pruning rule from a disproved final bound, and state exactly which downstream exclusions need revalidation. #2973 is an author-checked source archive; neither its new f(7) claim nor all old conclusions are automatically accepted or rejected.", + "first_step": { + "command": [ + "python3", + "-B", + "scripts/research_baseline.py" + ], + "expected": "PASS_RESEARCH_BASELINE_BINDINGS_ONLY", + "inspect": "Read #2973 error description and MATH.md; manually reconstruct the prefix states of 01021323 before running any large census.", + "scope": "Source-binding orientation only; no full enumeration or mathematical validation." + }, + "first_experiment": "Reconstruct the eight prefix states of 01021323 and compare bit-0 versus Hamming-weight parity budgets independently. Trace the reported false prune to one pinned predecessor (#2542, #2634 or #2691), then test a small exhaustive domain. Stop after a source-impact handoff or corrected-prune proof; a full seven-label replay needs a separate resource budget and a named research decision it can change.", + "bottleneck_link": "An unsound exclusion can wrongly close a mechanism; correcting its dependency boundary is more useful than extending the same census.", + "allowed_variations": [ + "One predecessor pruning rule, one independently exhaustive small domain, or one downstream dependency audit." + ], + "scope_change_triggers": [ + "Launching a larger census before validating the prune and explaining which active decision it changes.", + "Treating a small-domain counterexample to the old rule as a counterexample to every reported seven-label bound." + ], + "overlap_terms": [ + "2973", + "2542", + "2634", + "2691", + "weight parity", + "bit-0", + "01021323", + "census pruning" + ] + }, + "scope_status": "refined", + "actual_scope": "Completeness of low templates, the simple Q3 path quotient, translated initial domains and bounded gap enumeration in the pinned connector-covering-code A/B representation, before capacity/propagation/search.", + "scope_change_reason": "Follow PR3244's released search-domain handoff rather than repeating the independently implemented corrected seven-label census or its already-audited capacity/propagation predicates.", + "bottleneck_link": "An exclusion requires complete candidate representation as well as sound pruning. This closes the named representation implication without repeating verified exclusions or extending a supplier search.", + "budget_minutes": 60, + "stop_rule": "Stop after exact independent domain equality and the scoped representation proof, or a counterexample; no full B census, downstream implementation expansion or selected-frontier changes.", + "outcome": "completed", + "evidence": "README.md proof; RESULT.json exact domain receipts; compiled original-source catalogues and explicit gap-loop instrumentation; four compiled semantic mutants and three stream/correspondence controls.", + "author": "@krzysztofwojt", + "ai_assistance": "Substantial OpenAI Codex assistance in investigation, proof, implementation, checking and writing. A Luna worker performed read-only overlap extraction and an independent low-word/path enumeration, verified against the primary replay. No independent human or formal-kernel review.", + "open_questions": [ + { + "question": "Does the actual branching and exhaustion reporting cover every represented candidate and every requested template without a lost branch or an unreported abort?", + "why_it_matters": "Domain completeness alone cannot turn a zero-hit or capped run into an exclusion.", + "first_step": "Compare Engine::search against a small explicit Cartesian-domain oracle with satisfying, unsatisfiable and interrupted cases; bind template IDs, flags and source hashes before independently replaying all B templates.", + "blocked_by": "The branching/exhaustion audit and a separately budgeted independent B run remain undone; other scoped proof premises remain separate." + } + ], + "scope_key": "connector-covering-code-simple-ab-domain-completeness", + "canonical_discussion": "https://github.com/CrocSwap/integer-mult-bounds/discussions/1317#discussioncomment-19003334", + "predecessors": [ + { + "pr": 3224, + "head": "69567e40e8d92542248eda0d6a400d83adc1d3a3", + "scope": "capacity only; not executed by this package" + }, + { + "pr": 3244, + "head": "5964d7f22ad9cd9c27a1d2eb0b897f52b9425a13", + "scope": "propagation and emitted-template incidence; not executed by this package" + } + ], + "overlap": { + "open_prs": { + "records": 301, + "fetched_at": "2026-10-17T19:29:11.908061+00:00", + "complete_pagination": true + }, + "discussions": { + "records": 2082, + "fetched_at": "2026-10-17T19:30:34.629668+00:00", + "complete_pagination": true + }, + "queries": [ + "census-pruning-audit", + "universal_templates", + "normalized Q3", + "path compression", + "template/gap", + "gap enumeration" + ], + "value_check": "PR3244 explicitly leaves representation completeness open. Targeted live #1317/#1166 and open PR bodies found no matching successor before the claim. No novelty guarantee; closed arbitrary diffs and unpublished work are outside coverage." + }, + "unrun": [ + "full B exhaustion", + "complete f(7)=24 validation", + "literature/classification premises", + "multiplicity reduction", + "non-simple branch", + "formal-kernel verification", + "selected cold replay", + "supplier admission" + ] +} diff --git a/research/connector-domain-completeness/VERIFY.json b/research/connector-domain-completeness/VERIFY.json new file mode 100644 index 0000000000..d6ad0f968a --- /dev/null +++ b/research/connector-domain-completeness/VERIFY.json @@ -0,0 +1,24 @@ +{ + "schema_version": 1, + "status": "ready", + "python": "3.12", + "requirements": [], + "inputs": [ + "research/connector-covering-code/README.md", + "research/connector-covering-code/cycle_search.cpp" + ], + "commands": [ + { + "argv": [ + "{python}", + "-I", + "-O", + "-B", + "{package}/verify.py", + "--controls" + ], + "timeout_seconds": 180, + "checks": "Exact independent low-orbit, Q3 path, translated-domain and bounded-gap comparisons; four compiled semantic mutants and three stream/source-correspondence controls. Requires C++17; never runs the full census." + } + ] +} diff --git a/research/connector-domain-completeness/audit.cpp b/research/connector-domain-completeness/audit.cpp new file mode 100644 index 0000000000..e9f8faf21c --- /dev/null +++ b/research/connector-domain-completeness/audit.cpp @@ -0,0 +1,63 @@ +// @krzysztofwojt with substantial OpenAI Codex assistance. Apache-2.0. +#include +#include + +void audit_gap(const std::vector& gaps) { + for (int gap : gaps) std::cout.put(static_cast(gap)); +} +#define main retained_main +#include "subject.cpp" // authenticated private snapshot supplied by verify.py +#undef main + +template void emit(const Container& values) { + for (auto value : values) std::cout << ' ' << value; + std::cout << '\n'; +} + +int main(int argc, char** argv) { + try { + Tables tables; + if (argc == 2) { + const bool b = std::string(argv[1]) == "B"; + if (!b && std::string(argv[1]) != "A") throw std::runtime_error("expected A/B"); + Engine engine(tables, universal_templates(b).front(), b ? Counts{4,4,4} : Counts{6,4,4}, + Clock::now() + std::chrono::seconds(120)); + // Only used with the explicitly instrumented gap body: no word search. + if (!engine.enumerate() || engine.found || engine.timed_out) + throw std::runtime_error("gap enumeration incomplete"); + return 0; + } + for (bool b : {false, true}) { + const auto templates = universal_templates(b); + for (const auto& word : templates) { + Engine instance(tables, word, b ? Counts{4,4,4} : Counts{6,4,4}, + Clock::now() + std::chrono::seconds(120)); + if (instance.blocks != (b ? 10 : 8)) throw std::runtime_error("wrong block count"); + std::cout << "T " << b; emit(word); + } + Engine engine(tables, templates.front(), b ? Counts{4,4,4} : Counts{6,4,4}, + Clock::now() + std::chrono::seconds(120)); + for (int first = 0; first <= 7; ++first) for (int second = 0; second <= 7; ++second) { + LowWord gaps(engine.blocks, 0); gaps[0] = first; gaps[1] = second; + const auto domains = engine.domains_for(gaps); + for (int slot : {0, 1}) { + std::vector ids; + domains[slot].each([&](int id) { ids.push_back(id); }); + std::cout << "D " << b << ' ' << first << ' ' << second << ' ' << slot; emit(ids); + } + } + } + for (const auto& path : tables.paths) { + std::cout << "P " << path.mask << ' ' << path.end; + for (int count : path.counts) std::cout << ' ' << count; + emit(path.word); + } + for (const auto& c : tables.candidates) { + std::cout << "C"; + emit(std::vector{c.normal, c.start, c.end, c.mask, c.length, + c.counts[0], c.counts[1], c.counts[2]}); + } + } catch (const std::exception& error) { + std::cerr << "AUDIT_ERROR " << error.what() << '\n'; return 1; + } +} diff --git a/research/connector-domain-completeness/verify.py b/research/connector-domain-completeness/verify.py new file mode 100644 index 0000000000..c8ebc7e4a3 --- /dev/null +++ b/research/connector-domain-completeness/verify.py @@ -0,0 +1,301 @@ +#!/usr/bin/env python3 +"""Independent search-domain oracle; never run the retained full census. + +@krzysztofwojt with substantial OpenAI Codex assistance. Apache-2.0. +""" + +import argparse +import hashlib +import itertools +import json +import math +import os +import pathlib +import shutil +import subprocess +import tempfile +from collections import Counter + +HERE = pathlib.Path(__file__).resolve().parent +ROOT = HERE.parents[1] +SOURCE = "research/connector-covering-code/cycle_search.cpp" +SOURCE_SHA = "597844fc32cde19c1d4104633fa6d3eb0d28c1ca140f8f3d2ba2cb632ecd30d1" + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def digest(value): + return hashlib.sha256(json.dumps(value, sort_keys=True, separators=(",", ":")).encode()).hexdigest() + + +def source_bytes(): + pins = json.loads((HERE / "SOURCES.json").read_text()) + for row in pins["files"]: + if row["usage"] == "input": + require(hashlib.sha256((ROOT / row["path"]).read_bytes()).hexdigest() == row["sha256"], + "live input changed: " + row["path"]) + data = (ROOT / SOURCE).read_bytes() + require(hashlib.sha256(data).hexdigest() == SOURCE_SHA, "unexpected census source") + return data.decode() + + +def prefix_points(word): + state, points = 0, [] + for label in word: + points.append(state) + state ^= 1 << label + return points, state + + +def multiset_words(counts): + """Assign position subsets, with no first-appearance or dihedral pruning.""" + word = [-1] * sum(counts) + + def assign(label, slots): + if label == len(counts) - 1: + for slot in slots: + word[slot] = label + yield tuple(word) + return + for chosen in itertools.combinations(slots, counts[label]): + occupied = set(chosen) + for slot in chosen: + word[slot] = label + yield from assign(label + 1, tuple(slot for slot in slots if slot not in occupied)) + + yield from assign(0, tuple(range(len(word)))) + + +def low_oracle(pattern_b): + counts = (4, 2, 2, 2) if pattern_b else (2, 2, 2, 2) + universal, all_words = set(), 0 + for word in multiset_words(counts): + all_words += 1 + points, end = prefix_points(word) + require(end == 0, "multiset restoration") + if len({a ^ b for a in points for b in points}) == 16: + universal.add(word) + expected_total = math.factorial(sum(counts)) // math.prod(math.factorial(c) for c in counts) + require(all_words == expected_total, "multiset cardinality") + permutations = [(0,) + p for p in itertools.permutations((1, 2, 3))] if pattern_b else list(itertools.permutations(range(4))) + unseen, representatives, orbit_sizes = set(universal), [], Counter() + while unseen: + seed, orbit = min(unseen), set() + for mapping in permutations: + renamed = tuple(mapping[label] for label in seed) + for oriented in (renamed, renamed[::-1]): + for rotation in range(len(seed)): + orbit.add(oriented[rotation:] + oriented[:rotation]) + require(orbit <= universal, "symmetry changed low coverage or multiplicities") + require(orbit <= unseen, "overlapping group orbits") + unseen.difference_update(orbit) + representatives.append(min(orbit)) + orbit_sizes[len(orbit)] += 1 + return representatives, {"labeled_words": all_words, "universal_words": len(universal), + "orbits": len(representatives), "orbit_sizes": dict(sorted(orbit_sizes.items())), + "representatives_sha256": digest(representatives)} + + +def vertex_path_oracle(): + """Every ordered subset of the nonzero vertices; no coordinate DFS.""" + grouped = {} + for size in range(8): + for tail in itertools.permutations(range(1, 8), size): + vertices = (0,) + tail + differences = tuple(a ^ b for a, b in zip(vertices, vertices[1:])) + if any(d not in (1, 2, 4) for d in differences): + continue + counts = tuple(differences.count(1 << axis) for axis in range(3)) + key = (sum(1 << v for v in vertices), vertices[-1], *counts) + grouped.setdefault(key, []).append(tuple(d.bit_length() - 1 for d in differences)) + return grouped + + +def replacement_controls(paths): + """Every nontrivial quotient collision, translated to every high origin.""" + cases = 0 + for words in paths.values(): + if len(words) < 2: + continue + reference = words[0] + # Close the full word after a fixed restored low excursion. The final + # high suffix is held fixed when the first path is replaced. + low = tuple(label + 3 for label in (0, 1, 0, 1, 2, 3, 2, 3)) + original = reference + low + reference[::-1] + points, end = prefix_points(original) + require(end == 0, "replacement positive fixture is not restored") + for alternative in words[1:]: + changed = alternative + low + reference[::-1] + other, end = prefix_points(changed) + require(end == 0 and Counter(original) == Counter(changed), "replacement endpoint/counts") + for origin in range(8): + require({point ^ origin for point in points} == {point ^ origin for point in other}, + "path replacement changed full prefix set") + cases += 1 + require(cases > 0, "path quotient replacement controls vacuous") + return cases + + +def replace_once(source, old, new): + require(source.count(old) == 1, "source correspondence anchor not unique: " + old) + return source.replace(old, new, 1) + + +def gap_instrumentation(source): + # Preserve recursive loop, bounds, terminal test, flags and counters. + # Capture terminal compositions; stop before capacity or word search. + source = replace_once(source, "++stats.compositions;", "++stats.compositions; audit_gap(gaps);") + return replace_once(source, "if (!capacity(gaps)) return;", "return; // domain audit: no word search") + + +def build(directory, source): + (directory / "subject.cpp").write_text(source) + (directory / "audit.cpp").write_bytes((HERE / "audit.cpp").read_bytes()) + compiler = shutil.which(os.environ.get("CXX", "c++")) + require(compiler is not None, "C++17 compiler required (CXX or c++)") + result = subprocess.run([compiler, "-std=c++17", "-O2", "-Wall", "-Wextra", + str(directory / "audit.cpp"), "-o", str(directory / "audit")], + capture_output=True, timeout=60) + require(result.returncode == 0, "compile failed: " + result.stderr.decode(errors="replace")) + return directory / "audit" + + +def run(executable, *arguments): + result = subprocess.run([str(executable), *arguments], capture_output=True, timeout=120) + require(result.returncode == 0, "native audit failed: " + result.stderr.decode(errors="replace")) + return result.stdout + + +def check_catalogue(raw, low, paths): + rows = [(line[:1].decode(), tuple(map(int, line[2:].split()))) for line in raw.splitlines()] + require(Counter(kind for kind, _ in rows) == {"T": 82, "P": len(paths), "C": 8*len(paths), "D": 256}, + "catalogue record inventory") + for pattern in (0, 1): + actual = [row[1:] for kind, row in rows if kind == "T" and row[0] == pattern] + require(actual == low[pattern][0], "complete low orbit representatives differ") + actual_paths = [row for kind, row in rows if kind == "P"] + require([row[:5] for row in actual_paths] == sorted(paths), "complete path quotient differs") + for row in actual_paths: + require(row[5:] in paths[row[:5]], "invalid compressed-path representative") + candidates = [row for kind, row in rows if kind == "C"] + expected = [] + for normal, (mask, end, *counts) in enumerate(sorted(paths)): + for start in range(8): + translated = sum(1 << (v ^ start) for v in range(8) if (mask >> v) & 1) + expected.append((normal, start, end ^ start, translated, sum(counts), *counts)) + require(candidates == expected, "translated candidate catalogue differs") + specifications = set() + for kind, row in rows: + if kind != "D": + continue + pattern, first_length, second_length, slot = row[:4] + spec = row[:4] + require(spec not in specifications, "duplicate initial domain case") + specifications.add(spec) + first = slot == 0 + length = first_length if first else second_length + parity = 0 if first else first_length % 2 + ids = tuple(i for i, c in enumerate(expected) if c[4] == length and + (c[1] == 0 if first else c[1].bit_count() % 2 == parity)) + require(row[4:] == ids, "incorrect initial domain: " + str(spec)) + require(specifications == set(itertools.product(range(2), range(8), range(8), range(2))), + "missing initial domain case") + return {"candidates": len(candidates), "initial_domain_cases": len(specifications), + "catalogue_sha256": digest(rows)} + + +def gap_oracle(blocks, total): + """Stars-and-bars subsets, independent of the native recursive loop.""" + vectors = [] + for bars in itertools.combinations(range(total + blocks - 1), blocks - 1): + positions = (-1,) + bars + (total + blocks - 1,) + gaps = tuple(b - a - 1 for a, b in zip(positions, positions[1:])) + if max(gaps) <= 7: + vectors.append(bytes(gaps)) + return vectors + + +def check_gaps(raw, expected, blocks, total): + require(len(raw) % blocks == 0, "truncated gap capture") + actual = [raw[i:i + blocks] for i in range(0, len(raw), blocks)] + require(actual == expected, "incomplete or reordered bounded composition domain") + count = sum((-1)**j * math.comb(blocks, j) * math.comb(total - 8*j + blocks - 1, blocks - 1) + for j in range(min(blocks, total // 8) + 1)) + require(len(actual) == count and len(set(actual)) == count, "gap count/uniqueness identity") + require(any(0 in row for row in actual) and any(7 in row for row in actual), "missing gap boundaries") + return {"blocks": blocks, "high_steps": total, "compositions": count, + "ordered_bytes_sha256": hashlib.sha256(raw).hexdigest()} + + +def expect_rejected(action, label): + try: + action() + except (ValueError, subprocess.SubprocessError): + return label + raise ValueError("control unexpectedly accepted: " + label) + + +def audit(controls=False): + source = source_bytes() + low = {0: low_oracle(False), 1: low_oracle(True)} + paths = vertex_path_oracle() + replacements = replacement_controls(paths) + expected_gaps = {"A": gap_oracle(8, 14), "B": gap_oracle(10, 12)} + with tempfile.TemporaryDirectory(prefix="connector-domain-") as temporary: + directory = pathlib.Path(temporary) + executable = build(directory, source) + catalogue_raw = run(executable) + catalogue = check_catalogue(catalogue_raw, low, paths) + executable = build(directory, gap_instrumentation(source)) + gap_receipts = {} + for pattern, blocks, total in (("A", 8, 14), ("B", 10, 12)): + gap_receipts[pattern] = check_gaps(run(executable, pattern), expected_gaps[pattern], blocks, total) + if controls: + mutations = [ + ("omit low orbit", 'throw std::runtime_error("low-dihedral orbit count mismatch");\n return result;', + 'throw std::runtime_error("low-dihedral orbit count mismatch");\n result.pop_back(); return result;'), + ("discard path counts", "paths.push_back({mask, end, frequency, representative});", + "paths.push_back({mask, end, Counts{}, representative});"), + ("reset high start parity", "start_parity ^= gaps[i] & 1;", "start_parity = 0;"), + ] + for label, old, new in mutations: + executable = build(directory, replace_once(source, old, new)) + expect_rejected(lambda: check_catalogue(run(executable), low, paths), label) + mutant = replace_once(gap_instrumentation(source), "std::min(7, remaining)", "std::min(6, remaining)") + executable = build(directory, mutant) + expect_rejected(lambda: check_gaps(run(executable, "A"), expected_gaps["A"], 8, 14), "omit gap seven") + expect_rejected(lambda: check_catalogue(catalogue_raw.splitlines()[0], low, paths), "truncated catalogue") + expect_rejected(lambda: check_gaps(b"\0", expected_gaps["A"], 8, 14), "truncated gap stream") + expect_rejected(lambda: replace_once(source + "\n++stats.compositions;", "++stats.compositions;", ""), "ambiguous source anchor") + print("PASS_DOMAIN_CONTROLS compiled_mutants=4 truncations=2 correspondence=1") + collisions = {key: words for key, words in paths.items() if len(words) > 1} + example_key = min(collisions) + return {"source_sha256": SOURCE_SHA, "low_words": {"AB"[k]: v[1] for k, v in low.items()}, + "high_paths": {"literal_paths": sum(map(len, paths.values())), "quotient_classes": len(paths), + "translated_replacement_controls": replacements, + "class_size_histogram": dict(sorted(Counter(map(len, paths.values())).items())), + "quotient_keys_sha256": digest(sorted(paths)), + "collision_example": {"key": example_key, "words": collisions[example_key]}}, + "native_catalogue": catalogue, "gaps": gap_receipts, + "scope": "Complete representation domains for the pinned simple A/B contract; no full census or kappa claim."} + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--emit", action="store_true", help="print receipt without overwriting evidence") + parser.add_argument("--controls", action="store_true", help="also compile four semantic mutants") + args = parser.parse_args() + result = audit(args.controls) + if args.emit: + print(json.dumps(result, indent=2, sort_keys=True)) + else: + require(json.loads(json.dumps(result)) == json.loads((HERE / "RESULT.json").read_text()), + "committed receipt mismatch") + print("PASS_CONNECTOR_DOMAIN_COMPLETENESS low_orbits=82 path_classes=106 initial_domains=256 no_full_census") + + +if __name__ == "__main__": + main()