diff --git a/applications/collatz/collatz_k_scripts/collatz_verify_c2_projective.py b/applications/collatz/collatz_k_scripts/collatz_verify_c2_projective.py index 30bebfa..a5d2014 100644 --- a/applications/collatz/collatz_k_scripts/collatz_verify_c2_projective.py +++ b/applications/collatz/collatz_k_scripts/collatz_verify_c2_projective.py @@ -110,6 +110,44 @@ def _display_path(path: Path, repo_root: Path) -> str: return str(path) +def _discover_both_parent_blocks(md: str) -> dict[int, list[int]]: + """ + Discover "Parents « both » au palier 2^m" blocks in a completion markdown file. + Returns m -> residues list. + """ + out: dict[int, list[int]] = {} + for m in re.findall(r"^###\s+Parents\s+«\s+both\s+»\s+au\s+palier\s+2\^(\d+)\b", md, flags=re.M): + mm = int(m) + out[mm] = _parse_list_under_heading( + md, rf"^###\s+Parents\s+«\s+both\s+»\s+au\s+palier\s+2\^{mm}\b" + ) + return out + + +def _discover_listed_residual_after_completion(md: str, child_palier: int) -> list[int] | None: + """ + Optional: "Résidu restant au palier 2^(m+1) après complétion « one » (...)". + """ + pattern = rf"^###\s+Résidu\s+restant\s+au\s+palier\s+2\^{child_palier}\s+après\s+complétion\s+«\s+one\s+»" + try: + return _parse_list_under_heading(md, pattern) + except ValueError: + return None + + +def _discover_declared_residual_size(md: str, child_palier: int) -> int | None: + """ + Optional: parse a declared residual size like "|R_16^comp| = 2202". + """ + matches = re.findall(rf"\|R_{child_palier}\^comp\|\s*=\s*([^\n]+)", md) + if not matches: + return None + # Extract the last integer on the matched RHS (e.g. "2*|both| = 2202" -> 2202). + rhs = matches[-1] + ints = re.findall(r"\b(\d+)\b", rhs) + return int(ints[-1]) if ints else None + + def verify_c2( *, noyau_both_base_4096_md: Path, @@ -156,17 +194,47 @@ def verify_c2( children16 = _lift_children(both15, 15) _assert_all_odd(children16, "Computed children at m=16") - # This completion file does not necessarily list the full residual after completion, so we only check the count. + listed_r16 = _discover_listed_residual_after_completion(c1516_md, 16) + declared_r16_size = _discover_declared_residual_size(c1516_md, 16) + if listed_r16 is not None: + _assert_all_odd(listed_r16, "Listed residual at m=16") + if set(listed_r16) != set(children16): + raise ValueError("Listed residual at m=16 does not match computed children of both(m=15)") + if declared_r16_size is not None and declared_r16_size != len(children16): + raise ValueError(f"Declared |R_16^comp|={declared_r16_size} does not match computed {len(children16)}") + + # This completion file may omit the full residual after completion. c1516 = C2CheckResult( palier_parent=15, palier_child=16, both_parent_count=len(both15), computed_children_count=len(children16), - listed_residual_count=None, - children_equals_listed_residual=None, + listed_residual_count=len(listed_r16) if listed_r16 is not None else declared_r16_size, + children_equals_listed_residual=(set(children16) == set(listed_r16)) if listed_r16 is not None else None, projection_mod_4096_equals_b12=(_project_mod_4096(both15) == set(b12)), ) + transitions: list[dict[str, object]] = [] + for src_name, md in (("completion_m14_to_m15", c1415_md), ("completion_m15_to_m16", c1516_md)): + both_blocks = _discover_both_parent_blocks(md) + for m_parent, both in sorted(both_blocks.items()): + child_palier = m_parent + 1 + children = _lift_children(both, m_parent) + listed = _discover_listed_residual_after_completion(md, child_palier) + declared = _discover_declared_residual_size(md, child_palier) + transitions.append( + { + "source": src_name, + "palier_parent": m_parent, + "palier_child": child_palier, + "both_parent_count": len(both), + "computed_children_count": len(children), + "listed_residual_count": len(listed) if listed is not None else declared, + "children_equals_listed_residual": (set(children) == set(listed)) if listed is not None else None, + "projection_mod_4096_equals_b12": (_project_mod_4096(both) == set(b12)), + } + ) + summary = { "inputs": { "noyau_both_base_4096_md": _display_path(noyau_both_base_4096_md, repo_root), @@ -174,6 +242,7 @@ def verify_c2( "completion_m15_to_m16_md": _display_path(completion_m15_to_m16_md, repo_root), }, "B12": {"count": len(b12), "min": min(b12), "max": max(b12)}, + "transitions": transitions, "checks": { "m14_to_m15": c1415.__dict__, "m15_to_m16": c1516.__dict__, @@ -216,6 +285,8 @@ def verify_c2( lines.append("") lines.append(f"- |both parents (m=15)| = {c1516.both_parent_count}") lines.append(f"- |computed children (m=16)| = {c1516.computed_children_count} (attendu 2*|both|)") + if c1516.listed_residual_count is not None: + lines.append(f"- |listed residual (m=16)| : {c1516.listed_residual_count}") lines.append(f"- projection both(m=15) mod 4096 == B12 : {c1516.projection_mod_4096_equals_b12}") lines.append("") lines.append("## Sorties") diff --git a/docs/artefacts/collatz/c2_projective/verification_c2_projective.json b/docs/artefacts/collatz/c2_projective/verification_c2_projective.json index 2b3d5ad..e9abbd4 100644 --- a/docs/artefacts/collatz/c2_projective/verification_c2_projective.json +++ b/docs/artefacts/collatz/c2_projective/verification_c2_projective.json @@ -9,6 +9,28 @@ "min": 27, "max": 4095 }, + "transitions": [ + { + "source": "completion_m14_to_m15", + "palier_parent": 14, + "palier_child": 15, + "both_parent_count": 593, + "computed_children_count": 1186, + "listed_residual_count": 1186, + "children_equals_listed_residual": true, + "projection_mod_4096_equals_b12": true + }, + { + "source": "completion_m15_to_m16", + "palier_parent": 15, + "palier_child": 16, + "both_parent_count": 1101, + "computed_children_count": 2202, + "listed_residual_count": 2202, + "children_equals_listed_residual": null, + "projection_mod_4096_equals_b12": true + } + ], "checks": { "m14_to_m15": { "palier_parent": 14, @@ -24,7 +46,7 @@ "palier_child": 16, "both_parent_count": 1101, "computed_children_count": 2202, - "listed_residual_count": null, + "listed_residual_count": 2202, "children_equals_listed_residual": null, "projection_mod_4096_equals_b12": true } diff --git a/docs/artefacts/collatz/c2_projective/verification_c2_projective.md b/docs/artefacts/collatz/c2_projective/verification_c2_projective.md index 41b5fae..ccd555e 100644 --- a/docs/artefacts/collatz/c2_projective/verification_c2_projective.md +++ b/docs/artefacts/collatz/c2_projective/verification_c2_projective.md @@ -25,6 +25,7 @@ - |both parents (m=15)| = 1101 - |computed children (m=16)| = 2202 (attendu 2*|both|) +- |listed residual (m=16)| : 2202 - projection both(m=15) mod 4096 == B12 : True ## Sorties diff --git a/docs/collatz_run_report_2026-03-09_c2_projective.md b/docs/collatz_run_report_2026-03-09_c2_projective.md index 18088fb..45de231 100644 --- a/docs/collatz_run_report_2026-03-09_c2_projective.md +++ b/docs/collatz_run_report_2026-03-09_c2_projective.md @@ -9,7 +9,7 @@ ## Code et reproductibilité -- **Commit Git** : `e12c544e7bf8d7a6f9518cdd4959d0da07bccc07` +- **Commit Git** : `e3e68fe39c8ad466e5741e87d20311ca93b2456e` - **Commande** : ```bash @@ -19,7 +19,7 @@ python3 applications/collatz/collatz_k_scripts/collatz_generate_run_report.py -- ## Empreintes sha256 (scripts, artefacts) - `/home/ncantu/code/algo/applications/collatz/collatz_k_scripts/collatz_verify_c2_projective.py` - - sha256: `4f515d649c44c4ffe55349b07c72e9e766f591f7596e1bcdf0f9447e6b94950d` + - sha256: `bad3ddd4288af4a8b7bcc4fa30c1f5350db16f352b6eaf29918e8c1e1428a5b0` - `/home/ncantu/code/algo/applications/collatz/collatz_k_scripts/noyau_both_base_4096.md` - sha256: `d0abffeca9ce2356d13b31ee4325b68fd85cf061670a8524b8e60fd15aba881b` - `/home/ncantu/code/algo/applications/collatz/collatz_k_scripts/complétion_minorée_m14_vers_m15.md` @@ -27,9 +27,9 @@ python3 applications/collatz/collatz_k_scripts/collatz_generate_run_report.py -- - `/home/ncantu/code/algo/applications/collatz/collatz_k_scripts/complétion_minorée_m15_vers_m16.md` - sha256: `956f8fd19570b7614705384995b52b6bf81399ca8dc36c3ea33bcbad3e4aff50` - `/home/ncantu/code/algo/docs/artefacts/collatz/c2_projective/verification_c2_projective.json` - - sha256: `b1b9ab9d5d4f9d4ee60e7efd43b853ac29d3d51a19c2d71bdac45c4340d01bf0` + - sha256: `259901a9e4e307dae238672cc3e2e1e016800f034cdd98efe929e69bc1e4068a` - `/home/ncantu/code/algo/docs/artefacts/collatz/c2_projective/verification_c2_projective.md` - - sha256: `8bd84cb2149d297487e0e0ff03ebe96ff27b07a5ab677407cb4b9a17a339c2ba` + - sha256: `dc5562fea53f62e88acc08bcd29c89c53e9ad6e5fc4d41351642e7942cc49bdc` ## Compteurs et métriques