algo/applications/collatz/collatz_k_scripts/collatz_iterate_palier_protocol.py
ncantu bd529682bf collatz: add palier2p15/p16 artefacts and Sm refinement tooling
**Motivations:**
- Publish new Collatz palier runs and associated artefacts (C3 local descent, universal clauses, iteration protocol).
- Extend the scripts toolbox to generate/verify clauses and build refinement certificates over S_m.

**Root causes:**
- Universal clause witnesses were lifted to 2^(A+1) even when the witness is already fixed modulo the domain palier, leading to unstable or unnecessarily weak/ambiguous modulus choices.
- CSV palier inference in scission could mis-detect short column names (e.g. "m") by substring matching.

**Correctifs:**
- Lift D_exact/F witnesses to m_stable := max(m, A+1) in universal clause extraction and run reports.
- Make scission palier/m column detection exact-match to avoid false positives.
- Update C3 local descent verification/reporting to use strict fusion witness selection prioritizing lower modular stability and refreshed D/F metrics.
- Add a dedicated run report profile for per-palier universal clauses.

**Evolutions:**
- Add scripts for terminal clauses and minorated descent clauses over S_m, their deterministic verification, and multi-level refinement certificate building.
- Add modular tooling for register_K and incremental comparison of D_minor families.
- Add/update feature documentation for the new pipelines and generated reports.

**Pages affectées:**
- applications/collatz/collatz_k_scripts/README.md
- applications/collatz/collatz_k_scripts/collatz_extract_universal_clauses.py
- applications/collatz/collatz_k_scripts/collatz_generate_run_report.py
- applications/collatz/collatz_k_scripts/collatz_iterate_palier_protocol.py
- applications/collatz/collatz_k_scripts/collatz_scission.py
- applications/collatz/collatz_k_scripts/collatz_verify_c3_local_descent.py
- applications/collatz/collatz_k_scripts/collatz_verify_universal_clauses.py
- applications/collatz/collatz_k_scripts/*refinement*over_Sm*.py
- applications/collatz/collatz_k_scripts/collatz_generate_*clauses_over_Sm.py
- applications/collatz/collatz_k_scripts/collatz_verify_minorated_descent_clauses_over_Sm.py
- applications/collatz/collatz_k_scripts/collatz_build_register_K_modular.py
- applications/collatz/collatz_k_scripts/collatz_compare_dminor_families_incremental.py
- applications/collatz/*.md
- docs/features/*.md
- docs/artefacts/collatz/**
- docs/collatz_run_report_2026-03-09_*.md
2026-03-09 23:29:59 +01:00

242 lines
9.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
collatz_iterate_palier_protocol.py
Deterministic "next palier" protocol generator for the hybrid chain C1→C2→C3.
It does NOT run expensive computations. It inspects existing versioned artefacts
and writes a checklist (JSON + MD) describing:
- current certified palier for C3 (from verification JSON)
- current max C2 completion transition (from verification JSON)
- availability of local H6 directories at a chosen target palier
- commands to generate / verify / report the next iteration (2^m → 2^(m+1))
Outputs are intended to be versioned under `docs/artefacts/`.
"""
from __future__ import annotations
import argparse
import json
from dataclasses import dataclass
from pathlib import Path
def _read_json(path: Path) -> object:
return json.loads(path.read_text(encoding="utf-8", errors="strict"))
def _req_int(d: dict[str, object], key: str) -> int:
v = d.get(key)
if not isinstance(v, int):
raise ValueError(f"Expected int for {key}")
return v
def _write_json(path: Path, obj: object) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(obj, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
def _write_md(path: Path, lines: list[str]) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("\n".join(lines) + "\n", encoding="utf-8")
def _discover_local_h6_state_dirs(root: Path, palier: int) -> list[Path]:
return sorted([p for p in root.glob(f"local_E*_palier2p{palier}") if p.is_dir()])
@dataclass(frozen=True)
class ProtocolState:
c3_palier: int
c2_max_child_palier: int
target_palier: int
local_h6_states_found: int
local_h6_missing_state_ids: list[int]
def _load_c3_palier(c3_verification_json: Path) -> int:
obj = _read_json(c3_verification_json)
if not isinstance(obj, dict):
raise ValueError("Invalid C3 verification JSON: expected object")
domain = obj.get("domain")
if not isinstance(domain, dict):
raise ValueError("Invalid C3 verification JSON: missing domain")
return _req_int(domain, "palier")
def _load_c2_max_child_palier(c2_verification_json: Path) -> int:
obj = _read_json(c2_verification_json)
if not isinstance(obj, dict):
raise ValueError("Invalid C2 verification JSON: expected object")
transitions = obj.get("transitions")
if not isinstance(transitions, list) or not all(isinstance(x, dict) for x in transitions):
raise ValueError("Invalid C2 verification JSON: missing transitions")
child_paliers = [_req_int(t, "palier_child") for t in transitions]
if not child_paliers:
raise ValueError("Invalid C2 verification JSON: empty transitions")
return max(child_paliers)
def _infer_state_id_from_dirname(dirname: str) -> int:
# expected: local_E{sid}_palier2p{m}
parts = dirname.split("_")
for p in parts:
if p.startswith("E") and p[1:].isdigit():
return int(p[1:])
raise ValueError(f"Cannot infer state id from {dirname}")
def run(
*,
local_h6_root: Path,
c2_verification_json: Path,
c3_verification_json: Path,
output_dir: Path,
target_palier: int | None,
) -> None:
c3_palier = _load_c3_palier(c3_verification_json)
c2_max_child = _load_c2_max_child_palier(c2_verification_json)
tgt = (c3_palier + 1) if target_palier is None else int(target_palier)
if tgt < 13:
raise ValueError("target_palier must be >= 13")
found_dirs = _discover_local_h6_state_dirs(local_h6_root, tgt)
found_ids = sorted({_infer_state_id_from_dirname(p.name) for p in found_dirs})
missing_ids = [sid for sid in range(1, 61) if sid not in found_ids]
state = ProtocolState(
c3_palier=c3_palier,
c2_max_child_palier=c2_max_child,
target_palier=tgt,
local_h6_states_found=len(found_ids),
local_h6_missing_state_ids=missing_ids,
)
commands = {
"C1_local_H6_generate": (
"python3 applications/collatz/collatz_k_scripts/collatz_generate_local_h6_artefacts.py "
f"--docs-dir docs --output-root docs/artefacts/collatz --state-ids all "
f"--palier-start {tgt} --palier-max {tgt} "
"--t-min 9 --t-max 120 --write-index --index-path docs/artefacts/collatz/local_H6_index.md"
),
"C1_local_H6_run_reports": (
"python3 applications/collatz/collatz_k_scripts/collatz_generate_local_h6_run_reports.py "
"--out-dir applications/collatz/out --docs-dir docs --local-h6-root docs/artefacts/collatz "
f"--palier {tgt} --index-path docs/artefacts/collatz/local_H6_index.md"
),
"C3_verify_local_descent": (
"python3 applications/collatz/collatz_k_scripts/collatz_verify_c3_local_descent.py "
"--local-h6-root docs/artefacts/collatz "
"--output-dir docs/artefacts/collatz/c3_local_descent "
f"--palier {tgt}"
),
"C3_run_report_palier": (
"python3 applications/collatz/collatz_k_scripts/collatz_generate_run_report.py "
"--profile c3_local_descent_palier "
"--c3-artefacts-dir docs/artefacts/collatz/c3_local_descent "
f"--c3-palier {tgt} "
"--out-dir applications/collatz/out --docs-dir docs"
),
"Universal_clauses_extract": (
"python3 applications/collatz/collatz_k_scripts/collatz_extract_universal_clauses.py "
f"--verification-json docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p{tgt}.json "
f"--output-dir docs/artefacts/collatz/universal_clauses/palier2p{tgt}"
),
"Universal_clauses_verify": (
"python3 applications/collatz/collatz_k_scripts/collatz_verify_universal_clauses.py "
f"--verification-json docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p{tgt}.json "
f"--clauses-json docs/artefacts/collatz/universal_clauses/palier2p{tgt}/clauses_universelles.json "
f"--output-dir docs/artefacts/collatz/universal_clauses/palier2p{tgt}"
),
"Universal_clauses_run_report_palier": (
"python3 applications/collatz/collatz_k_scripts/collatz_generate_run_report.py "
"--profile universal_clauses_palier "
f"--universal-clauses-artefacts-dir docs/artefacts/collatz/universal_clauses/palier2p{tgt} "
"--out-dir applications/collatz/out --docs-dir docs"
),
"C2_verify_projective": (
"python3 applications/collatz/collatz_k_scripts/collatz_verify_c2_projective.py "
"--repo-root /home/ncantu/code/algo --output-dir docs/artefacts/collatz/c2_projective"
),
}
out_obj = {
"inputs": {
"local_h6_root": str(local_h6_root),
"c2_verification_json": str(c2_verification_json),
"c3_verification_json": str(c3_verification_json),
},
"state": {
"c3_palier": state.c3_palier,
"c2_max_child_palier": state.c2_max_child_palier,
"target_palier": state.target_palier,
"local_h6_states_found": state.local_h6_states_found,
"local_h6_missing_state_ids": state.local_h6_missing_state_ids,
},
"commands": commands,
}
output_dir.mkdir(parents=True, exist_ok=True)
out_json = output_dir / "iteration_protocol.json"
out_md = output_dir / "iteration_protocol.md"
_write_json(out_json, out_obj)
md: list[str] = []
md.append("**Auteur** : Équipe 4NK")
md.append("")
md.append("# Protocole déterministe — itération de palier (C1→C2→C3)")
md.append("")
md.append("## État courant (artefacts)")
md.append("")
md.append(f"- C3 palier certifié : 2^{state.c3_palier} (daprès `{c3_verification_json}`)")
md.append(f"- C2 transition max auditée : palier enfant 2^{state.c2_max_child_palier} (daprès `{c2_verification_json}`)")
md.append("")
md.append("## Palier cible")
md.append("")
md.append(f"- palier cible : 2^{state.target_palier}")
md.append(f"- H6 locale présente (états) : {state.local_h6_states_found}/60")
if state.local_h6_missing_state_ids:
md.append(f"- états manquants : {state.local_h6_missing_state_ids}")
md.append("")
md.append("## Étapes (commandes reproductibles)")
md.append("")
for k, cmd in commands.items():
md.append(f"- **{k}** :")
md.append("")
md.append("```bash")
md.append(cmd)
md.append("```")
md.append("")
md.append("## Notes")
md.append("")
md.append("- Pour `C3_verify_local_descent` : si `palier != 13`, les sorties attendues sont suffixées `..._palier2p<m>.{json,md}`.")
md.append("- Les rapports C3 par palier sont générés via le profil `c3_local_descent_palier` (nom de fichier déterministe).")
_write_md(out_md, md)
def main() -> None:
ap = argparse.ArgumentParser(description="Generate a deterministic next-palier protocol for C1→C2→C3")
ap.add_argument("--local-h6-root", default="docs/artefacts/collatz", help="Root containing local_E*_palier2p<m>/ dirs")
ap.add_argument("--c2-verification-json", default="docs/artefacts/collatz/c2_projective/verification_c2_projective.json")
ap.add_argument("--c3-verification-json", default="docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent.json")
ap.add_argument("--output-dir", default="docs/artefacts/collatz/iteration_protocol")
ap.add_argument("--target-palier", default="", help="Override target palier m (defaults to c3_palier+1)")
args = ap.parse_args()
tgt = int(args.target_palier) if args.target_palier.strip() else None
run(
local_h6_root=Path(args.local_h6_root).resolve(),
c2_verification_json=Path(args.c2_verification_json).resolve(),
c3_verification_json=Path(args.c3_verification_json).resolve(),
output_dir=Path(args.output_dir).resolve(),
target_palier=tgt,
)
if __name__ == "__main__":
main()