**Motivations:** - Implémenter le workflow complet de démonstration Collatz (commandes.md) - Permettre la reprise après interruption au palier D20 **Evolutions:** - Scripts 01-12 et run-full-workflow alignés sur commandes.md sections 1-10 - collatz_recover_noyau.py : recréation de noyau_post_D20 à partir du CSV candidats - Option --resume-from D20 dans collatz_k_pipeline pour reprendre sans recalculer D18-D19-F15 - Détection automatique : si candidats_D20 existe sans noyau_post_D20, récupération puis poursuite - Filtres --cible=critique et --modulo dans collatz_fusion_pipeline - ROOT par défaut = collatz_k_scripts (plus data/source vide) **Pages affectées:** - .gitignore (__pycache__, out/) - applications/collatz/collatz_k_scripts/*.py - applications/collatz/scripts/*.sh - applications/collatz/scripts/README.md
66 lines
2.1 KiB
Python
66 lines
2.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
collatz_compute_survival_rate.py
|
|
|
|
Compute survival rate (coefficient of contraction) for a noyau.
|
|
Outputs |B_m| and q = |B_m| / (2 * |R_{m-1}|) when previous noyau is available.
|
|
|
|
Usage: python collatz_compute_survival_rate.py --noyau PATH [--previous PATH]
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
|
|
|
|
def load_noyau(path: str) -> tuple[list[int], int]:
|
|
"""Load noyau from JSON, return (residues, palier)."""
|
|
data = json.loads(Path(path).read_text(encoding="utf-8"))
|
|
if isinstance(data, list):
|
|
residues = [int(x) for x in data]
|
|
palier = max(n.bit_length() for n in residues) if residues else 0
|
|
return residues, palier
|
|
if isinstance(data, dict):
|
|
for key in ("noyau", "residues", "uncovered"):
|
|
if key in data and isinstance(data[key], list):
|
|
residues = [int(x) for x in data[key]]
|
|
palier = data.get("palier", max(n.bit_length() for n in residues) if residues else 0)
|
|
return residues, palier
|
|
raise ValueError(f"Cannot load noyau from {path}")
|
|
|
|
|
|
def main() -> None:
|
|
ap = argparse.ArgumentParser(description="Compute survival rate of noyau")
|
|
ap.add_argument("--noyau", required=True, help="Path to noyau JSON")
|
|
ap.add_argument("--previous", help="Path to previous noyau (for q = |B_m| / 2|R_{m-1}|)")
|
|
args = ap.parse_args()
|
|
|
|
residues, palier = load_noyau(args.noyau)
|
|
size = len(residues)
|
|
|
|
lines = [
|
|
f"# Survival rate: {Path(args.noyau).name}",
|
|
"",
|
|
f"- |B_{{m}}| = {size}",
|
|
f"- palier m ≈ {palier}",
|
|
"",
|
|
]
|
|
|
|
if args.previous and Path(args.previous).exists():
|
|
prev_residues, prev_palier = load_noyau(args.previous)
|
|
prev_size = len(prev_residues)
|
|
denom = 2 * prev_size
|
|
q = size / denom if denom else 0
|
|
lines.extend([
|
|
f"- |R_{{m-1}}| = {prev_size}",
|
|
f"- q = |B_m| / (2|R_{{m-1}}|) = {q:.6f}",
|
|
"",
|
|
])
|
|
|
|
print("\n".join(lines))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|