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
This commit is contained in:
parent
40fa3808a7
commit
bd529682bf
@ -6,6 +6,8 @@ Scripts Python nécessaires pour reproduire les calculs et audits produits jusqu
|
||||
- génération des paquets D_k (au moins la branche "après fusion" pour D16 et D17)
|
||||
- génération et audit des clauses de fusion (F)
|
||||
- production systématique des listes exhaustives en Markdown (bloc CSV)
|
||||
- génération et vérification de clauses terminales sur \(S_M\) (exactes et minorées)
|
||||
- certificats de raffinement (sur \(L\) et sur \(S_M\))
|
||||
|
||||
## Entrées
|
||||
|
||||
@ -27,3 +29,11 @@ python collatz_k_pipeline.py \
|
||||
Orchestrateur:
|
||||
|
||||
python reproduce_all_audits.py --root /chemin/fichiers_source --out /chemin/sorties
|
||||
|
||||
## Compléments (scripts unitaires)
|
||||
|
||||
- `collatz_generate_terminal_clauses_over_Sm.py` : clauses terminales (D/F) directement décidables sur \(S_M\).
|
||||
- `collatz_generate_minorated_descent_clauses_over_Sm.py` : clauses de descente minorées (D_minor) sur \(S_M\).
|
||||
- `collatz_verify_minorated_descent_clauses_over_Sm.py` : vérification déterministe des clauses D_minor.
|
||||
- `collatz_build_refinement_certificate_over_Sm_multilevel.py` : audit de fermeture par raffinement (multi-niveaux) sur \(S_M\).
|
||||
- `collatz_compare_dminor_families_incremental.py` : tableau d’impact incrémental (Δopen_roots, Δq_m, Δparents_one_child, quantiles lb) par ajout de familles D_minor groupées par \(k\).
|
||||
|
||||
@ -0,0 +1,544 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
collatz_analyze_open_roots_refinement.py
|
||||
|
||||
Targeted analysis of open roots in S_M after a multilevel refinement closure attempt.
|
||||
|
||||
Goal:
|
||||
- For each open root r in S_M, compute obstruction diagnostics on its two children at level M+1.
|
||||
- Estimate a lower-bound "first possible closure depth" by searching for the minimal contractive
|
||||
terminal clause (D or F) for each child residue, in terms of required m >= A+1.
|
||||
|
||||
This analysis is deterministic, versionable, and intended to decide whether open roots are
|
||||
"structurally late" (require m >> M_max) or might be treated early by a grammar change.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any, Literal
|
||||
|
||||
from collatz_k_core import prefix_data, delta_D, fusion_choice_a, delta_F
|
||||
|
||||
|
||||
Kind = Literal["D_exact", "F"]
|
||||
|
||||
|
||||
def _read_json(path: Path) -> object:
|
||||
return json.loads(path.read_text(encoding="utf-8", errors="strict"))
|
||||
|
||||
|
||||
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 _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
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class BestClause:
|
||||
kind: Kind
|
||||
k_or_t: int
|
||||
A: int
|
||||
required_m: int
|
||||
extra: dict[str, int]
|
||||
|
||||
def to_json(self) -> dict[str, object]:
|
||||
return {
|
||||
"kind": self.kind,
|
||||
"k_or_t": self.k_or_t,
|
||||
"A": self.A,
|
||||
"required_m": self.required_m,
|
||||
"extra": self.extra,
|
||||
}
|
||||
|
||||
|
||||
def _best_contractive_D(*, residue: int, k_max: int, max_required_m: int) -> BestClause | None:
|
||||
best: BestClause | None = None
|
||||
best_key: tuple[int, int, int] | None = None
|
||||
for k in range(1, k_max + 1):
|
||||
pref = prefix_data(residue, k)
|
||||
req_m = pref.A + 1
|
||||
if req_m > max_required_m:
|
||||
break
|
||||
if delta_D(pref.A, k) <= 0:
|
||||
continue
|
||||
key = (req_m, pref.A, k)
|
||||
if best_key is None or key < best_key:
|
||||
best_key = key
|
||||
best = BestClause(kind="D_exact", k_or_t=k, A=pref.A, required_m=req_m, extra={"k": k})
|
||||
return best
|
||||
|
||||
|
||||
def _best_contractive_F(*, residue: int, t_max: int, max_required_m: int) -> BestClause | None:
|
||||
best: BestClause | None = None
|
||||
best_key: tuple[int, int, int] | None = None
|
||||
for t in range(1, t_max + 1):
|
||||
pref = prefix_data(residue, t)
|
||||
req_m = pref.A + 1
|
||||
if req_m > max_required_m:
|
||||
break
|
||||
a = fusion_choice_a(pref.y)
|
||||
if a is None:
|
||||
continue
|
||||
if delta_F(pref.A, t, a) <= 0:
|
||||
continue
|
||||
key = (req_m, pref.A, t)
|
||||
if best_key is None or key < best_key:
|
||||
best_key = key
|
||||
best = BestClause(kind="F", k_or_t=t, A=pref.A, required_m=req_m, extra={"t": t, "a": a})
|
||||
return best
|
||||
|
||||
|
||||
def _analyze_child(*, child_residue: int, k_max: int, t_max: int, max_required_m: int) -> dict[str, object]:
|
||||
best_D = _best_contractive_D(residue=child_residue, k_max=k_max, max_required_m=max_required_m)
|
||||
best_F = _best_contractive_F(residue=child_residue, t_max=t_max, max_required_m=max_required_m)
|
||||
|
||||
# obstruction markers at small depths (<=32)
|
||||
any_deltaD_pos = False
|
||||
first_k_deltaD_pos: int | None = None
|
||||
for k in range(1, min(k_max, 32) + 1):
|
||||
pref = prefix_data(child_residue, k)
|
||||
if delta_D(pref.A, k) > 0:
|
||||
any_deltaD_pos = True
|
||||
first_k_deltaD_pos = k
|
||||
break
|
||||
|
||||
any_y_mod3_nonzero = False
|
||||
y_mod3_zero_count = 0
|
||||
any_deltaF_pos = False
|
||||
first_t_deltaF_pos: int | None = None
|
||||
first_t_y_mod3_nonzero: int | None = None
|
||||
for t in range(1, min(t_max, 32) + 1):
|
||||
pref = prefix_data(child_residue, t)
|
||||
a = fusion_choice_a(pref.y)
|
||||
if a is None:
|
||||
y_mod3_zero_count += 1
|
||||
continue
|
||||
any_y_mod3_nonzero = True
|
||||
if first_t_y_mod3_nonzero is None:
|
||||
first_t_y_mod3_nonzero = t
|
||||
if delta_F(pref.A, t, a) > 0:
|
||||
any_deltaF_pos = True
|
||||
first_t_deltaF_pos = t
|
||||
break
|
||||
|
||||
def req_m(b: BestClause | None) -> int | None:
|
||||
return b.required_m if b is not None else None
|
||||
|
||||
req_D = req_m(best_D)
|
||||
req_F = req_m(best_F)
|
||||
req_any = min([x for x in [req_D, req_F] if x is not None], default=None)
|
||||
|
||||
return {
|
||||
"child_residue_mod_2p": child_residue,
|
||||
"best_D": (best_D.to_json() if best_D is not None else None),
|
||||
"best_F": (best_F.to_json() if best_F is not None else None),
|
||||
"required_m": {"D": req_D, "F": req_F, "any": req_any},
|
||||
"obstructions": {
|
||||
"any_contracting_D_found_up_to32": any_deltaD_pos,
|
||||
"first_k_contracting_D_up_to32": first_k_deltaD_pos,
|
||||
"any_y_mod3_nonzero_up_to32": any_y_mod3_nonzero,
|
||||
"y_mod3_zero_count_up_to32": y_mod3_zero_count,
|
||||
"first_t_y_mod3_nonzero_up_to32": first_t_y_mod3_nonzero,
|
||||
"any_contracting_F_found_up_to32": any_deltaF_pos,
|
||||
"first_t_contracting_F_up_to32": first_t_deltaF_pos,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def run(
|
||||
*,
|
||||
root_palier: int,
|
||||
max_palier: int,
|
||||
multilevel_json: Path,
|
||||
output_dir: Path,
|
||||
k_max: int,
|
||||
t_max: int,
|
||||
search_max_required_m: int,
|
||||
) -> None:
|
||||
obj = _read_json(multilevel_json)
|
||||
if not isinstance(obj, dict):
|
||||
raise ValueError("Invalid multilevel certificate JSON: expected object")
|
||||
domain = obj.get("domain")
|
||||
closure = obj.get("closure")
|
||||
if not isinstance(domain, dict) or not isinstance(closure, dict):
|
||||
raise ValueError("Invalid multilevel certificate JSON: missing domain/closure")
|
||||
if _req_int(domain, "root_palier") != root_palier or _req_int(domain, "max_palier") != max_palier:
|
||||
raise ValueError("multilevel certificate domain mismatch")
|
||||
|
||||
still_open_sample = closure.get("still_open_roots_sample")
|
||||
if not isinstance(still_open_sample, list) or not all(isinstance(x, int) for x in still_open_sample):
|
||||
raise ValueError("Invalid multilevel certificate JSON: missing still_open_roots_sample")
|
||||
|
||||
# The full open set is not stored by default; we recompute it from closed sample is insufficient.
|
||||
# We therefore require the corresponding MD to list the open roots sample only, and analyze the full set by reconstruction.
|
||||
# Reconstruction: scan all roots and check if they appear in first_close mapping.
|
||||
first_close = obj.get("first_close_palier_by_root")
|
||||
if not isinstance(first_close, dict):
|
||||
raise ValueError("Invalid multilevel certificate JSON: missing first_close_palier_by_root")
|
||||
|
||||
open_roots: list[int] = []
|
||||
for r0 in range(1, 1 << root_palier, 2):
|
||||
if str(r0) not in first_close:
|
||||
open_roots.append(r0)
|
||||
|
||||
rows: list[dict[str, object]] = []
|
||||
bucket_any: dict[int, int] = {}
|
||||
bucket_D: dict[int, int] = {}
|
||||
bucket_F: dict[int, int] = {}
|
||||
|
||||
motif_counts: dict[str, int] = {}
|
||||
hist_first_k_D: dict[int, int] = {}
|
||||
hist_first_t_F: dict[int, int] = {}
|
||||
hist_first_t_y_nonzero: dict[int, int] = {}
|
||||
hist_y_mod3_zero_count: dict[int, int] = {}
|
||||
hist_first_k_D_low: dict[int, int] = {}
|
||||
hist_first_k_D_high: dict[int, int] = {}
|
||||
hist_first_t_F_low: dict[int, int] = {}
|
||||
hist_first_t_F_high: dict[int, int] = {}
|
||||
hist_y_mod3_zero_count_low: dict[int, int] = {}
|
||||
hist_y_mod3_zero_count_high: dict[int, int] = {}
|
||||
hist_lbD_minus_lbF: dict[int, int] = {}
|
||||
hist_lbAny_minus_lbD: dict[int, int] = {}
|
||||
hist_lbAny_minus_lbF: dict[int, int] = {}
|
||||
|
||||
lb_any_values: list[int] = []
|
||||
lb_D_values: list[int] = []
|
||||
lb_F_values: list[int] = []
|
||||
|
||||
def bump(hist: dict[int, int], key: int | None) -> None:
|
||||
if key is None:
|
||||
return
|
||||
hist[key] = hist.get(key, 0) + 1
|
||||
|
||||
for r0 in open_roots:
|
||||
c0 = r0
|
||||
c1 = r0 + (1 << root_palier)
|
||||
a0 = _analyze_child(child_residue=c0, k_max=k_max, t_max=t_max, max_required_m=search_max_required_m)
|
||||
a1 = _analyze_child(child_residue=c1, k_max=k_max, t_max=t_max, max_required_m=search_max_required_m)
|
||||
|
||||
def req_kind(x: dict[str, object], k: str) -> int | None:
|
||||
req = x.get("required_m")
|
||||
if not isinstance(req, dict):
|
||||
return None
|
||||
v = req.get(k)
|
||||
return int(v) if isinstance(v, int) else None
|
||||
|
||||
req0_any = req_kind(a0, "any")
|
||||
req1_any = req_kind(a1, "any")
|
||||
lb_any = max([x for x in [req0_any, req1_any] if x is not None], default=0) or None
|
||||
if lb_any is not None:
|
||||
bucket_any[lb_any] = bucket_any.get(lb_any, 0) + 1
|
||||
lb_any_values.append(int(lb_any))
|
||||
|
||||
req0_D = req_kind(a0, "D")
|
||||
req1_D = req_kind(a1, "D")
|
||||
lb_D = max([x for x in [req0_D, req1_D] if x is not None], default=0) or None
|
||||
if lb_D is not None:
|
||||
bucket_D[lb_D] = bucket_D.get(lb_D, 0) + 1
|
||||
lb_D_values.append(int(lb_D))
|
||||
|
||||
req0_F = req_kind(a0, "F")
|
||||
req1_F = req_kind(a1, "F")
|
||||
lb_F = max([x for x in [req0_F, req1_F] if x is not None], default=0) or None
|
||||
if lb_F is not None:
|
||||
bucket_F[lb_F] = bucket_F.get(lb_F, 0) + 1
|
||||
lb_F_values.append(int(lb_F))
|
||||
|
||||
# motifs (dominant obstructions at small depths)
|
||||
o0 = a0.get("obstructions")
|
||||
o1 = a1.get("obstructions")
|
||||
if isinstance(o0, dict) and isinstance(o1, dict):
|
||||
both_no_D32 = (o0.get("any_contracting_D_found_up_to32") is False) and (o1.get("any_contracting_D_found_up_to32") is False)
|
||||
both_no_F32 = (o0.get("any_contracting_F_found_up_to32") is False) and (o1.get("any_contracting_F_found_up_to32") is False)
|
||||
both_y3_nonzero = (o0.get("any_y_mod3_nonzero_up_to32") is True) and (o1.get("any_y_mod3_nonzero_up_to32") is True)
|
||||
if both_no_D32:
|
||||
motif_counts["both_children_no_contracting_D_up_to32"] = motif_counts.get("both_children_no_contracting_D_up_to32", 0) + 1
|
||||
if both_no_F32:
|
||||
motif_counts["both_children_no_contracting_F_up_to32"] = motif_counts.get("both_children_no_contracting_F_up_to32", 0) + 1
|
||||
if both_no_F32 and both_y3_nonzero:
|
||||
motif_counts["both_children_F_blocked_by_deltaF_up_to32"] = motif_counts.get("both_children_F_blocked_by_deltaF_up_to32", 0) + 1
|
||||
if both_no_F32 and (not both_y3_nonzero):
|
||||
motif_counts["some_child_y_mod3_zero_always_up_to32"] = motif_counts.get("some_child_y_mod3_zero_always_up_to32", 0) + 1
|
||||
|
||||
bump(hist_first_k_D, o0.get("first_k_contracting_D_up_to32") if isinstance(o0.get("first_k_contracting_D_up_to32"), int) else None)
|
||||
bump(hist_first_k_D, o1.get("first_k_contracting_D_up_to32") if isinstance(o1.get("first_k_contracting_D_up_to32"), int) else None)
|
||||
bump(hist_first_k_D_low, o0.get("first_k_contracting_D_up_to32") if isinstance(o0.get("first_k_contracting_D_up_to32"), int) else None)
|
||||
bump(hist_first_k_D_high, o1.get("first_k_contracting_D_up_to32") if isinstance(o1.get("first_k_contracting_D_up_to32"), int) else None)
|
||||
bump(hist_first_t_F, o0.get("first_t_contracting_F_up_to32") if isinstance(o0.get("first_t_contracting_F_up_to32"), int) else None)
|
||||
bump(hist_first_t_F, o1.get("first_t_contracting_F_up_to32") if isinstance(o1.get("first_t_contracting_F_up_to32"), int) else None)
|
||||
bump(hist_first_t_F_low, o0.get("first_t_contracting_F_up_to32") if isinstance(o0.get("first_t_contracting_F_up_to32"), int) else None)
|
||||
bump(hist_first_t_F_high, o1.get("first_t_contracting_F_up_to32") if isinstance(o1.get("first_t_contracting_F_up_to32"), int) else None)
|
||||
bump(hist_first_t_y_nonzero, o0.get("first_t_y_mod3_nonzero_up_to32") if isinstance(o0.get("first_t_y_mod3_nonzero_up_to32"), int) else None)
|
||||
bump(hist_first_t_y_nonzero, o1.get("first_t_y_mod3_nonzero_up_to32") if isinstance(o1.get("first_t_y_mod3_nonzero_up_to32"), int) else None)
|
||||
bump(hist_y_mod3_zero_count, o0.get("y_mod3_zero_count_up_to32") if isinstance(o0.get("y_mod3_zero_count_up_to32"), int) else None)
|
||||
bump(hist_y_mod3_zero_count, o1.get("y_mod3_zero_count_up_to32") if isinstance(o1.get("y_mod3_zero_count_up_to32"), int) else None)
|
||||
bump(hist_y_mod3_zero_count_low, o0.get("y_mod3_zero_count_up_to32") if isinstance(o0.get("y_mod3_zero_count_up_to32"), int) else None)
|
||||
bump(hist_y_mod3_zero_count_high, o1.get("y_mod3_zero_count_up_to32") if isinstance(o1.get("y_mod3_zero_count_up_to32"), int) else None)
|
||||
|
||||
# Correlations based on lower bounds for this root
|
||||
if lb_D is not None and lb_F is not None:
|
||||
diff = int(lb_D) - int(lb_F)
|
||||
hist_lbD_minus_lbF[diff] = hist_lbD_minus_lbF.get(diff, 0) + 1
|
||||
if lb_any is not None and lb_D is not None:
|
||||
diff = int(lb_any) - int(lb_D)
|
||||
hist_lbAny_minus_lbD[diff] = hist_lbAny_minus_lbD.get(diff, 0) + 1
|
||||
if lb_any is not None and lb_F is not None:
|
||||
diff = int(lb_any) - int(lb_F)
|
||||
hist_lbAny_minus_lbF[diff] = hist_lbAny_minus_lbF.get(diff, 0) + 1
|
||||
|
||||
rows.append(
|
||||
{
|
||||
"root_residue_mod_2p": r0,
|
||||
"children_mod_2p16": [c0, c1],
|
||||
"child0": a0,
|
||||
"child1": a1,
|
||||
"lower_bound_required_m_to_close_root": {"any": lb_any, "D": lb_D, "F": lb_F},
|
||||
}
|
||||
)
|
||||
|
||||
out_json = output_dir / f"open_roots_obstruction_profile_mod2p{root_palier}_to2p{max_palier}.json"
|
||||
out_md = output_dir / f"open_roots_obstruction_profile_mod2p{root_palier}_to2p{max_palier}.md"
|
||||
|
||||
def quantiles(values: list[int]) -> dict[str, int]:
|
||||
if not values:
|
||||
return {}
|
||||
s = sorted(values)
|
||||
n = len(s)
|
||||
def at(p: float) -> int:
|
||||
idx = int((n - 1) * p)
|
||||
return int(s[idx])
|
||||
return {
|
||||
"p50": at(0.50),
|
||||
"p75": at(0.75),
|
||||
"p90": at(0.90),
|
||||
"p95": at(0.95),
|
||||
"p99": at(0.99),
|
||||
"max": int(s[-1]),
|
||||
}
|
||||
|
||||
summary = {
|
||||
"domain": {
|
||||
"root_palier": root_palier,
|
||||
"max_palier": max_palier,
|
||||
"open_roots_count": len(open_roots),
|
||||
},
|
||||
"search": {
|
||||
"k_max": k_max,
|
||||
"t_max": t_max,
|
||||
"search_max_required_m": search_max_required_m,
|
||||
},
|
||||
"lower_bound_required_m_bucket": {
|
||||
"any": {str(k): v for k, v in sorted(bucket_any.items())},
|
||||
"D": {str(k): v for k, v in sorted(bucket_D.items())},
|
||||
"F": {str(k): v for k, v in sorted(bucket_F.items())},
|
||||
},
|
||||
"motifs_up_to32": motif_counts,
|
||||
"histograms_up_to32": {
|
||||
"first_k_contracting_D": {str(k): v for k, v in sorted(hist_first_k_D.items())},
|
||||
"first_k_contracting_D_low": {str(k): v for k, v in sorted(hist_first_k_D_low.items())},
|
||||
"first_k_contracting_D_high": {str(k): v for k, v in sorted(hist_first_k_D_high.items())},
|
||||
"first_t_contracting_F": {str(k): v for k, v in sorted(hist_first_t_F.items())},
|
||||
"first_t_contracting_F_low": {str(k): v for k, v in sorted(hist_first_t_F_low.items())},
|
||||
"first_t_contracting_F_high": {str(k): v for k, v in sorted(hist_first_t_F_high.items())},
|
||||
"first_t_y_mod3_nonzero": {str(k): v for k, v in sorted(hist_first_t_y_nonzero.items())},
|
||||
"y_mod3_zero_count": {str(k): v for k, v in sorted(hist_y_mod3_zero_count.items())},
|
||||
"y_mod3_zero_count_low": {str(k): v for k, v in sorted(hist_y_mod3_zero_count_low.items())},
|
||||
"y_mod3_zero_count_high": {str(k): v for k, v in sorted(hist_y_mod3_zero_count_high.items())},
|
||||
},
|
||||
"correlations": {
|
||||
"lb_D_minus_lb_F": {str(k): v for k, v in sorted(hist_lbD_minus_lbF.items())},
|
||||
"lb_any_minus_lb_D": {str(k): v for k, v in sorted(hist_lbAny_minus_lbD.items())},
|
||||
"lb_any_minus_lb_F": {str(k): v for k, v in sorted(hist_lbAny_minus_lbF.items())},
|
||||
},
|
||||
"quantiles": {
|
||||
"lb_any": quantiles(lb_any_values),
|
||||
"lb_D": quantiles(lb_D_values),
|
||||
"lb_F": quantiles(lb_F_values),
|
||||
},
|
||||
"rows": rows,
|
||||
}
|
||||
_write_json(out_json, summary)
|
||||
|
||||
md: list[str] = []
|
||||
md.append("**Auteur** : Équipe 4NK")
|
||||
md.append("")
|
||||
md.append(f"# Profil d’obstruction — racines ouvertes sur S_{root_palier} (raffinement jusqu’à 2^{max_palier})")
|
||||
md.append("")
|
||||
md.append("## Domaine")
|
||||
md.append("")
|
||||
md.append(f"- racine : 2^{root_palier}")
|
||||
md.append(f"- max : 2^{max_palier}")
|
||||
md.append(f"- open_roots : {len(open_roots)}")
|
||||
md.append("")
|
||||
md.append("## Recherche (borne inférieure de profondeur)")
|
||||
md.append("")
|
||||
md.append(f"- k_max : {k_max}")
|
||||
md.append(f"- t_max : {t_max}")
|
||||
md.append(f"- max_required_m (pruning) : {search_max_required_m}")
|
||||
md.append("")
|
||||
md.append("### Buckets — lower_bound_required_m_to_close_root")
|
||||
md.append("")
|
||||
md.append("Buckets (any):")
|
||||
for k, v in sorted(bucket_any.items()):
|
||||
md.append(f"- required_m={k} : {v}")
|
||||
md.append("")
|
||||
md.append("Buckets (D only):")
|
||||
for k, v in sorted(bucket_D.items()):
|
||||
md.append(f"- required_m={k} : {v}")
|
||||
md.append("")
|
||||
md.append("Buckets (F only):")
|
||||
for k, v in sorted(bucket_F.items()):
|
||||
md.append(f"- required_m={k} : {v}")
|
||||
md.append("")
|
||||
md.append("## Motifs dominants (<=32)")
|
||||
md.append("")
|
||||
for k, v in sorted(motif_counts.items(), key=lambda x: (-x[1], x[0])):
|
||||
md.append(f"- {k} : {v}")
|
||||
md.append("")
|
||||
md.append("## Histogrammes (<=32, agrégés sur les deux enfants)")
|
||||
md.append("")
|
||||
md.append("### first_k_contracting_D_up_to32")
|
||||
for k, v in sorted(hist_first_k_D.items()):
|
||||
md.append(f"- k={k} : {v}")
|
||||
md.append("")
|
||||
md.append("### first_k_contracting_D_up_to32 (low child)")
|
||||
for k, v in sorted(hist_first_k_D_low.items()):
|
||||
md.append(f"- k={k} : {v}")
|
||||
md.append("")
|
||||
md.append("### first_k_contracting_D_up_to32 (high child)")
|
||||
for k, v in sorted(hist_first_k_D_high.items()):
|
||||
md.append(f"- k={k} : {v}")
|
||||
md.append("")
|
||||
md.append("### first_t_contracting_F_up_to32")
|
||||
for k, v in sorted(hist_first_t_F.items()):
|
||||
md.append(f"- t={k} : {v}")
|
||||
md.append("")
|
||||
md.append("### first_t_y_mod3_nonzero_up_to32")
|
||||
for k, v in sorted(hist_first_t_y_nonzero.items()):
|
||||
md.append(f"- t={k} : {v}")
|
||||
md.append("")
|
||||
md.append("### y_mod3_zero_count_up_to32")
|
||||
for k, v in sorted(hist_y_mod3_zero_count.items()):
|
||||
md.append(f"- count={k} : {v}")
|
||||
md.append("")
|
||||
md.append("### y_mod3_zero_count_up_to32 (low child)")
|
||||
for k, v in sorted(hist_y_mod3_zero_count_low.items()):
|
||||
md.append(f"- count={k} : {v}")
|
||||
md.append("")
|
||||
md.append("### y_mod3_zero_count_up_to32 (high child)")
|
||||
for k, v in sorted(hist_y_mod3_zero_count_high.items()):
|
||||
md.append(f"- count={k} : {v}")
|
||||
md.append("")
|
||||
md.append("## Corrélations (borne inférieure)")
|
||||
md.append("")
|
||||
md.append("### lb_D - lb_F")
|
||||
for k, v in sorted(hist_lbD_minus_lbF.items()):
|
||||
md.append(f"- diff={k} : {v}")
|
||||
md.append("")
|
||||
md.append("### lb_any - lb_D")
|
||||
for k, v in sorted(hist_lbAny_minus_lbD.items()):
|
||||
md.append(f"- diff={k} : {v}")
|
||||
md.append("")
|
||||
md.append("### lb_any - lb_F")
|
||||
for k, v in sorted(hist_lbAny_minus_lbF.items()):
|
||||
md.append(f"- diff={k} : {v}")
|
||||
md.append("")
|
||||
md.append("## Quantiles (borne inférieure)")
|
||||
md.append("")
|
||||
q_any = quantiles(lb_any_values)
|
||||
q_D = quantiles(lb_D_values)
|
||||
q_F = quantiles(lb_F_values)
|
||||
md.append("| metric | p50 | p75 | p90 | p95 | p99 | max |")
|
||||
md.append("| --- | --- | --- | --- | --- | --- | --- |")
|
||||
if q_any:
|
||||
md.append(f"| lb_any | {q_any['p50']} | {q_any['p75']} | {q_any['p90']} | {q_any['p95']} | {q_any['p99']} | {q_any['max']} |")
|
||||
if q_D:
|
||||
md.append(f"| lb_D | {q_D['p50']} | {q_D['p75']} | {q_D['p90']} | {q_D['p95']} | {q_D['p99']} | {q_D['max']} |")
|
||||
if q_F:
|
||||
md.append(f"| lb_F | {q_F['p50']} | {q_F['p75']} | {q_F['p90']} | {q_F['p95']} | {q_F['p99']} | {q_F['max']} |")
|
||||
md.append("")
|
||||
md.append("## Exemples (premières lignes)")
|
||||
md.append("")
|
||||
md.append("| r | child0 | child1 | lb_any | lb_D | lb_F |")
|
||||
md.append("| --- | --- | --- | --- | --- | --- |")
|
||||
for row in rows[:40]:
|
||||
r0 = int(row["root_residue_mod_2p"]) # type: ignore[arg-type]
|
||||
c0 = int(row["children_mod_2p16"][0]) # type: ignore[index]
|
||||
c1 = int(row["children_mod_2p16"][1]) # type: ignore[index]
|
||||
lb = row.get("lower_bound_required_m_to_close_root")
|
||||
lb_any2 = ""
|
||||
lb_D2 = ""
|
||||
lb_F2 = ""
|
||||
if isinstance(lb, dict):
|
||||
lb_any2 = "" if lb.get("any") is None else str(lb.get("any"))
|
||||
lb_D2 = "" if lb.get("D") is None else str(lb.get("D"))
|
||||
lb_F2 = "" if lb.get("F") is None else str(lb.get("F"))
|
||||
md.append(f"| {r0} | {c0} | {c1} | {lb_any2} | {lb_D2} | {lb_F2} |")
|
||||
md.append("")
|
||||
md.append("## Sorties")
|
||||
md.append("")
|
||||
md.append(f"- JSON : `{out_json}`")
|
||||
md.append(f"- Markdown : `{out_md}`")
|
||||
md.append("")
|
||||
_write_md(out_md, md)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ap = argparse.ArgumentParser(description="Analyze open roots after multilevel refinement closure")
|
||||
ap.add_argument("--root-palier", type=int, default=15)
|
||||
ap.add_argument("--max-palier", type=int, default=18)
|
||||
ap.add_argument("--multilevel-json", default="", help="Path to refinement_certificate_Sm_multilevel JSON")
|
||||
ap.add_argument("--output-dir", default="", help="Output directory (defaults under docs/artefacts/...)")
|
||||
ap.add_argument("--k-max", type=int, default=128)
|
||||
ap.add_argument("--t-max", type=int, default=128)
|
||||
ap.add_argument("--search-max-required-m", type=int, default=128)
|
||||
args = ap.parse_args()
|
||||
|
||||
root_palier = int(args.root_palier)
|
||||
max_palier = int(args.max_palier)
|
||||
if args.multilevel_json.strip():
|
||||
multilevel_json = Path(args.multilevel_json).resolve()
|
||||
else:
|
||||
multilevel_json = (
|
||||
Path("docs")
|
||||
/ "artefacts"
|
||||
/ "collatz"
|
||||
/ "refinement_K"
|
||||
/ f"palier2p{root_palier}"
|
||||
/ f"refinement_certificate_Sm_multilevel_mod2p{root_palier}_to2p{max_palier}.json"
|
||||
).resolve()
|
||||
if args.output_dir.strip():
|
||||
output_dir = Path(args.output_dir).resolve()
|
||||
else:
|
||||
output_dir = (Path("docs") / "artefacts" / "collatz" / "refinement_K" / f"palier2p{root_palier}").resolve()
|
||||
|
||||
run(
|
||||
root_palier=root_palier,
|
||||
max_palier=max_palier,
|
||||
multilevel_json=multilevel_json,
|
||||
output_dir=output_dir,
|
||||
k_max=int(args.k_max),
|
||||
t_max=int(args.t_max),
|
||||
search_max_required_m=int(args.search_max_required_m),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@ -0,0 +1,338 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
collatz_build_refinement_certificate_modular.py
|
||||
|
||||
Build a deterministic refinement certificate at palier 2^M on the instrumented domain L.
|
||||
|
||||
This is an alternative to the "direct decidability" constraint m(c) <= M used in the modular register K_M.
|
||||
Here, leaf clauses may live at modulus 2^m with m > M; a finite refinement path is recorded from the
|
||||
root residue (mod 2^M) to the leaf residue (mod 2^m).
|
||||
|
||||
Scope (by design):
|
||||
- The certificate is defined and audited on the finite C3 domain L (record n values), not on S_M.
|
||||
|
||||
Inputs:
|
||||
- clauses_universelles.json (Option A) at the chosen palier
|
||||
- the referenced C3 verification JSON (from clauses JSON inputs)
|
||||
|
||||
Outputs:
|
||||
- refinement_certificate_mod2p<M>.{json,md}
|
||||
- audit_refinement_certificate_mod2p<M>.{json,md}
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any, Literal
|
||||
|
||||
from collatz_build_register_K_modular import _display_path, _generated_at_utc_from_mtime, _sha256_file
|
||||
|
||||
|
||||
ClauseKind = Literal["D_exact", "F", "D_brother_local"]
|
||||
|
||||
|
||||
def _read_json(path: Path) -> object:
|
||||
return json.loads(path.read_text(encoding="utf-8", errors="strict"))
|
||||
|
||||
|
||||
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 _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 _opt_int(d: dict[str, object], key: str) -> int | None:
|
||||
v = d.get(key)
|
||||
if v is None:
|
||||
return None
|
||||
if not isinstance(v, int):
|
||||
raise ValueError(f"Expected int|null for {key}")
|
||||
return v
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RefinementEntry:
|
||||
n: int
|
||||
kind: ClauseKind
|
||||
root_modulus_power: int
|
||||
root_residue_mod_2p: int
|
||||
leaf_modulus_power: int
|
||||
leaf_residue_mod_2p: int
|
||||
# one decision per level m in [M..leaf_m-1]
|
||||
decisions: tuple[int, ...]
|
||||
# terminal clause info (minimal for auditing / traceability)
|
||||
k_or_t: int | None
|
||||
A: int | None
|
||||
threshold: int | None
|
||||
|
||||
def to_json(self) -> dict[str, object]:
|
||||
return {
|
||||
"n": self.n,
|
||||
"kind": self.kind,
|
||||
"root_modulus_power": self.root_modulus_power,
|
||||
"root_residue_mod_2p": self.root_residue_mod_2p,
|
||||
"leaf_modulus_power": self.leaf_modulus_power,
|
||||
"leaf_residue_mod_2p": self.leaf_residue_mod_2p,
|
||||
"decisions": list(self.decisions),
|
||||
"k_or_t": self.k_or_t,
|
||||
"A": self.A,
|
||||
"threshold": self.threshold,
|
||||
}
|
||||
|
||||
|
||||
def _infer_default_clauses_json(*, repo_root: Path, palier: int) -> Path:
|
||||
base = repo_root / "docs" / "artefacts" / "collatz" / "universal_clauses"
|
||||
if palier == 13:
|
||||
return base / "clauses_universelles.json"
|
||||
return base / f"palier2p{palier}" / "clauses_universelles.json"
|
||||
|
||||
|
||||
def _infer_default_output_dir(*, repo_root: Path, palier: int) -> Path:
|
||||
return repo_root / "docs" / "artefacts" / "collatz" / "refinement_K" / f"palier2p{palier}"
|
||||
|
||||
|
||||
def _load_c3_verification_path_from_clauses(*, clauses_obj: dict[str, object], repo_root: Path) -> Path:
|
||||
inputs = clauses_obj.get("inputs")
|
||||
if not isinstance(inputs, dict):
|
||||
raise ValueError("Invalid clauses JSON: missing inputs")
|
||||
p = inputs.get("verification_c3_local_descent_json")
|
||||
if not isinstance(p, str) or not p.strip():
|
||||
raise ValueError("Invalid clauses JSON: missing inputs.verification_c3_local_descent_json")
|
||||
path = Path(p)
|
||||
if not path.is_absolute():
|
||||
path = repo_root / path
|
||||
return path.resolve()
|
||||
|
||||
|
||||
def _refinement_decisions(*, root_residue: int, root_m: int, leaf_residue: int, leaf_m: int) -> tuple[int, ...]:
|
||||
if leaf_m < root_m:
|
||||
raise ValueError("leaf_m must be >= root_m")
|
||||
if (leaf_residue % (1 << root_m)) != (root_residue % (1 << root_m)):
|
||||
raise ValueError("leaf_residue must extend root_residue")
|
||||
res = root_residue
|
||||
out: list[int] = []
|
||||
for m in range(root_m, leaf_m):
|
||||
target_mod = 1 << (m + 1)
|
||||
target = leaf_residue % target_mod
|
||||
if target == res:
|
||||
out.append(0)
|
||||
continue
|
||||
if target == res + (1 << m):
|
||||
res = res + (1 << m)
|
||||
out.append(1)
|
||||
continue
|
||||
raise ValueError(f"Inconsistent refinement at level m={m}: root={root_residue}, leaf={leaf_residue}, res={res}")
|
||||
if res != leaf_residue:
|
||||
raise ValueError("Refinement reconstruction failed")
|
||||
return tuple(out)
|
||||
|
||||
|
||||
def run(*, palier: int, clauses_json: Path, output_dir: Path, repo_root: Path) -> None:
|
||||
cobj = _read_json(clauses_json)
|
||||
if not isinstance(cobj, dict):
|
||||
raise ValueError("Invalid clauses JSON: expected object")
|
||||
domain = cobj.get("domain")
|
||||
if not isinstance(domain, dict):
|
||||
raise ValueError("Invalid clauses JSON: missing domain")
|
||||
domain_palier = _req_int(domain, "palier")
|
||||
if domain_palier != palier:
|
||||
raise ValueError(f"Clauses domain palier mismatch: {domain_palier} != {palier}")
|
||||
clauses = cobj.get("clauses")
|
||||
if not isinstance(clauses, list) or not all(isinstance(x, dict) for x in clauses):
|
||||
raise ValueError("Invalid clauses JSON: missing clauses list")
|
||||
|
||||
c3_verification_json = _load_c3_verification_path_from_clauses(clauses_obj=cobj, repo_root=repo_root)
|
||||
vobj = _read_json(c3_verification_json)
|
||||
if not isinstance(vobj, dict):
|
||||
raise ValueError("Invalid C3 verification JSON: expected object")
|
||||
vdomain = vobj.get("domain")
|
||||
vrecords = vobj.get("records")
|
||||
if not isinstance(vdomain, dict) or not isinstance(vrecords, list):
|
||||
raise ValueError("Invalid C3 verification JSON: missing domain/records")
|
||||
if _req_int(vdomain, "palier") != palier:
|
||||
raise ValueError("C3 domain palier mismatch")
|
||||
if not all(isinstance(r, dict) for r in vrecords):
|
||||
raise ValueError("Invalid C3 records")
|
||||
|
||||
# Map by source_n for a direct, deterministic join
|
||||
clause_by_source_n: dict[int, dict[str, object]] = {}
|
||||
for c in clauses:
|
||||
sn = c.get("source_n")
|
||||
if isinstance(sn, int):
|
||||
clause_by_source_n[sn] = c
|
||||
|
||||
entries: list[RefinementEntry] = []
|
||||
missing: list[int] = []
|
||||
for rec in vrecords:
|
||||
n = rec.get("n")
|
||||
if not isinstance(n, int):
|
||||
raise ValueError("Invalid C3 record: missing n")
|
||||
c = clause_by_source_n.get(n)
|
||||
if c is None:
|
||||
missing.append(n)
|
||||
continue
|
||||
|
||||
kind = c.get("kind")
|
||||
if not isinstance(kind, str) or kind not in ("D_exact", "F", "D_brother_local"):
|
||||
raise ValueError(f"Invalid clause kind for source_n={n}")
|
||||
stable_m = _opt_int(c, "stable_modulus_power")
|
||||
stable_r = _opt_int(c, "stable_residue_mod_2p")
|
||||
if stable_m is None or stable_r is None:
|
||||
raise ValueError(f"Missing stable modulus/residue for source_n={n}")
|
||||
|
||||
root_r = n % (1 << palier)
|
||||
decisions = _refinement_decisions(root_residue=root_r, root_m=palier, leaf_residue=stable_r, leaf_m=stable_m)
|
||||
|
||||
thr = _opt_int(c, "N0") if kind == "D_exact" else _opt_int(c, "Nf") if kind == "F" else None
|
||||
entries.append(
|
||||
RefinementEntry(
|
||||
n=n,
|
||||
kind=kind, # type: ignore[arg-type]
|
||||
root_modulus_power=palier,
|
||||
root_residue_mod_2p=root_r,
|
||||
leaf_modulus_power=stable_m,
|
||||
leaf_residue_mod_2p=stable_r,
|
||||
decisions=decisions,
|
||||
k_or_t=_opt_int(c, "k_or_t"),
|
||||
A=_opt_int(c, "A"),
|
||||
threshold=thr,
|
||||
)
|
||||
)
|
||||
|
||||
if missing:
|
||||
raise ValueError(f"Missing extracted clauses for {len(missing)} C3 residues (e.g. {missing[:20]})")
|
||||
|
||||
generated_at = _generated_at_utc_from_mtime([clauses_json, c3_verification_json])
|
||||
sha = {
|
||||
_display_path(clauses_json, repo_root): _sha256_file(clauses_json),
|
||||
_display_path(c3_verification_json, repo_root): _sha256_file(c3_verification_json),
|
||||
}
|
||||
|
||||
depths = [e.leaf_modulus_power - palier for e in entries]
|
||||
max_depth = max(depths, default=0)
|
||||
direct = sum(1 for d in depths if d == 0)
|
||||
refined = len(depths) - direct
|
||||
|
||||
depth_buckets: dict[int, int] = {}
|
||||
for d in depths:
|
||||
depth_buckets[d] = depth_buckets.get(d, 0) + 1
|
||||
|
||||
out_json = output_dir / f"refinement_certificate_mod2p{palier}.json"
|
||||
out_md = output_dir / f"refinement_certificate_mod2p{palier}.md"
|
||||
audit_json = output_dir / f"audit_refinement_certificate_mod2p{palier}.json"
|
||||
audit_md = output_dir / f"audit_refinement_certificate_mod2p{palier}.md"
|
||||
|
||||
cert_obj: dict[str, object] = {
|
||||
"inputs": {
|
||||
"clauses_json": _display_path(clauses_json, repo_root),
|
||||
"verification_c3_local_descent_json": _display_path(c3_verification_json, repo_root),
|
||||
},
|
||||
"domain": {
|
||||
"palier": palier,
|
||||
"L_size": len(entries),
|
||||
},
|
||||
"generated_at": generated_at,
|
||||
"sha256": sha,
|
||||
"entries": [e.to_json() for e in sorted(entries, key=lambda x: x.n)],
|
||||
}
|
||||
_write_json(out_json, cert_obj)
|
||||
|
||||
audit_obj: dict[str, object] = {
|
||||
"domain": {
|
||||
"palier": palier,
|
||||
"L_size": len(entries),
|
||||
},
|
||||
"decidability": {
|
||||
"direct_leaf_count": direct,
|
||||
"refined_leaf_count": refined,
|
||||
"max_refinement_depth": max_depth,
|
||||
"depth_buckets": {str(k): v for k, v in sorted(depth_buckets.items())},
|
||||
},
|
||||
"generated_at": generated_at,
|
||||
"sha256": {
|
||||
"outputs": {
|
||||
_display_path(out_json, repo_root): _sha256_file(out_json),
|
||||
}
|
||||
},
|
||||
}
|
||||
_write_json(audit_json, audit_obj)
|
||||
|
||||
md: list[str] = []
|
||||
md.append("**Auteur** : Équipe 4NK")
|
||||
md.append("")
|
||||
md.append(f"# Certificat de raffinement — décidabilité depuis 2^{palier} (domaine L)")
|
||||
md.append("")
|
||||
md.append("## Entrées")
|
||||
md.append("")
|
||||
md.append(f"- clauses : `{_display_path(clauses_json, repo_root)}`")
|
||||
md.append(f"- C3 : `{_display_path(c3_verification_json, repo_root)}`")
|
||||
md.append("")
|
||||
md.append("## Domaine")
|
||||
md.append("")
|
||||
md.append(f"- palier : 2^{palier}")
|
||||
md.append(f"- |L| : {len(entries)}")
|
||||
md.append(f"- generated_at : {generated_at}")
|
||||
md.append("")
|
||||
md.append("## Décidabilité (sur L)")
|
||||
md.append("")
|
||||
md.append(f"- feuilles directes (m_leaf = {palier}) : {direct}")
|
||||
md.append(f"- feuilles raffinées (m_leaf > {palier}) : {refined}")
|
||||
md.append(f"- profondeur max : {max_depth}")
|
||||
md.append("")
|
||||
md.append("### Buckets (profondeur = m_leaf - M)")
|
||||
md.append("")
|
||||
for d, cnt in sorted(depth_buckets.items()):
|
||||
md.append(f"- depth={d} : {cnt}")
|
||||
md.append("")
|
||||
md.append("## Sorties")
|
||||
md.append("")
|
||||
md.append(f"- JSON : `{_display_path(out_json, repo_root)}`")
|
||||
md.append(f"- Audit JSON : `{_display_path(audit_json, repo_root)}`")
|
||||
_write_md(out_md, md)
|
||||
|
||||
amd: list[str] = []
|
||||
amd.append("**Auteur** : Équipe 4NK")
|
||||
amd.append("")
|
||||
amd.append(f"# Audit — certificat de raffinement (2^{palier}, domaine L)")
|
||||
amd.append("")
|
||||
amd.append(f"- direct : {direct}")
|
||||
amd.append(f"- refined : {refined}")
|
||||
amd.append(f"- max_depth : {max_depth}")
|
||||
amd.append("")
|
||||
_write_md(audit_md, amd)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ap = argparse.ArgumentParser(description="Build a deterministic refinement certificate at palier 2^M on domain L")
|
||||
ap.add_argument("--repo-root", default=".", help="Repository root (defaults to current working directory)")
|
||||
ap.add_argument("--palier", type=int, default=15, help="Root palier M for the refinement certificate")
|
||||
ap.add_argument("--clauses-json", default="", help="Path to clauses_universelles.json (Option A)")
|
||||
ap.add_argument("--output-dir", default="", help="Output directory for refinement artefacts")
|
||||
args = ap.parse_args()
|
||||
|
||||
repo_root = Path(args.repo_root).resolve()
|
||||
palier = int(args.palier)
|
||||
clauses_json = Path(args.clauses_json).resolve() if args.clauses_json.strip() else _infer_default_clauses_json(repo_root=repo_root, palier=palier)
|
||||
output_dir = Path(args.output_dir).resolve() if args.output_dir.strip() else _infer_default_output_dir(repo_root=repo_root, palier=palier)
|
||||
|
||||
run(palier=palier, clauses_json=clauses_json, output_dir=output_dir, repo_root=repo_root)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@ -0,0 +1,414 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
collatz_build_refinement_certificate_over_Sm.py
|
||||
|
||||
Build a deterministic refinement certificate over the full odd residue space S_M
|
||||
(all odd residues modulo 2^M), using a finite set of terminal clauses (Option A).
|
||||
|
||||
Interpretation (H2' style, "decidable by finite refinement"):
|
||||
- A root residue r in S_M is considered *closed* if the full binary refinement tree
|
||||
rooted at (M,r) can be finitely closed by terminal clauses D/F (at varying moduli).
|
||||
- A node (m, r_m) is closed if:
|
||||
- it has a terminal clause at modulus 2^m with residue r_m, OR
|
||||
- both children (m+1, r_m) and (m+1, r_m + 2^m) are closed.
|
||||
|
||||
Scope:
|
||||
- This construction uses only the finite clause set; it does not claim closure for
|
||||
residues whose refinement subtrees are not fully covered by these clauses.
|
||||
|
||||
Inputs:
|
||||
- clauses_universelles.json (Option A) at palier M
|
||||
|
||||
Outputs:
|
||||
- refinement_certificate_Sm_mod2p<M>.{json,md}
|
||||
- audit_refinement_certificate_Sm_mod2p<M>.{json,md}
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any, Literal
|
||||
|
||||
from collatz_build_register_K_modular import _display_path, _generated_at_utc_from_mtime, _sha256_file
|
||||
|
||||
|
||||
ClauseKind = Literal["D_exact", "F"]
|
||||
|
||||
|
||||
def _read_json(path: Path) -> object:
|
||||
return json.loads(path.read_text(encoding="utf-8", errors="strict"))
|
||||
|
||||
|
||||
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 _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 _opt_int(d: dict[str, object], key: str) -> int | None:
|
||||
v = d.get(key)
|
||||
if v is None:
|
||||
return None
|
||||
if not isinstance(v, int):
|
||||
raise ValueError(f"Expected int|null for {key}")
|
||||
return v
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TerminalClause:
|
||||
kind: ClauseKind
|
||||
modulus_power: int
|
||||
residue_mod_2p: int
|
||||
threshold: int
|
||||
source_n: int
|
||||
k_or_t: int | None
|
||||
A: int | None
|
||||
|
||||
def to_json(self) -> dict[str, object]:
|
||||
return {
|
||||
"kind": self.kind,
|
||||
"modulus_power": self.modulus_power,
|
||||
"residue_mod_2p": self.residue_mod_2p,
|
||||
"threshold": self.threshold,
|
||||
"source_n": self.source_n,
|
||||
"k_or_t": self.k_or_t,
|
||||
"A": self.A,
|
||||
}
|
||||
|
||||
|
||||
def _infer_default_clauses_json(*, repo_root: Path, palier: int) -> Path:
|
||||
base = repo_root / "docs" / "artefacts" / "collatz" / "universal_clauses"
|
||||
if palier == 13:
|
||||
return base / "clauses_universelles.json"
|
||||
return base / f"palier2p{palier}" / "clauses_universelles.json"
|
||||
|
||||
|
||||
def _infer_default_terminal_over_sm_json(*, repo_root: Path, palier: int) -> Path:
|
||||
return (
|
||||
repo_root
|
||||
/ "docs"
|
||||
/ "artefacts"
|
||||
/ "collatz"
|
||||
/ "terminal_clauses_over_Sm"
|
||||
/ f"palier2p{palier}"
|
||||
/ f"clauses_terminal_over_Sm_mod2p{palier}.json"
|
||||
)
|
||||
|
||||
|
||||
def _infer_default_output_dir(*, repo_root: Path, palier: int) -> Path:
|
||||
return repo_root / "docs" / "artefacts" / "collatz" / "refinement_K" / f"palier2p{palier}"
|
||||
|
||||
|
||||
def _load_terminal_clauses_from_option_a(*, clauses_obj: dict[str, object], palier: int) -> list[TerminalClause]:
|
||||
domain = clauses_obj.get("domain")
|
||||
if not isinstance(domain, dict):
|
||||
raise ValueError("Invalid clauses JSON: missing domain")
|
||||
if _req_int(domain, "palier") != palier:
|
||||
raise ValueError("Clauses domain palier mismatch")
|
||||
|
||||
clauses = clauses_obj.get("clauses")
|
||||
if not isinstance(clauses, list) or not all(isinstance(x, dict) for x in clauses):
|
||||
raise ValueError("Invalid clauses JSON: missing clauses list")
|
||||
|
||||
out: list[TerminalClause] = []
|
||||
for c in clauses:
|
||||
kind = c.get("kind")
|
||||
if kind not in ("D_exact", "F"):
|
||||
continue
|
||||
stable_m = _opt_int(c, "stable_modulus_power")
|
||||
stable_r = _opt_int(c, "stable_residue_mod_2p")
|
||||
if stable_m is None or stable_r is None:
|
||||
continue
|
||||
thr = _opt_int(c, "N0") if kind == "D_exact" else _opt_int(c, "Nf")
|
||||
if thr is None:
|
||||
raise ValueError(f"Missing threshold for clause kind={kind}")
|
||||
sn = _opt_int(c, "source_n")
|
||||
if sn is None:
|
||||
raise ValueError("Missing source_n")
|
||||
out.append(
|
||||
TerminalClause(
|
||||
kind=kind,
|
||||
modulus_power=stable_m,
|
||||
residue_mod_2p=stable_r,
|
||||
threshold=thr,
|
||||
source_n=sn,
|
||||
k_or_t=_opt_int(c, "k_or_t"),
|
||||
A=_opt_int(c, "A"),
|
||||
)
|
||||
)
|
||||
return out
|
||||
|
||||
|
||||
def _load_terminal_clauses_from_over_sm(*, obj: dict[str, object], palier: int) -> list[TerminalClause]:
|
||||
domain = obj.get("domain")
|
||||
if not isinstance(domain, dict):
|
||||
raise ValueError("Invalid terminal clauses JSON: missing domain")
|
||||
if _req_int(domain, "palier") != palier:
|
||||
raise ValueError("Terminal clauses domain palier mismatch")
|
||||
clauses = obj.get("clauses")
|
||||
if not isinstance(clauses, list) or not all(isinstance(x, dict) for x in clauses):
|
||||
raise ValueError("Invalid terminal clauses JSON: missing clauses list")
|
||||
out: list[TerminalClause] = []
|
||||
for c in clauses:
|
||||
kind = c.get("kind")
|
||||
if kind not in ("D_exact", "F"):
|
||||
continue
|
||||
m = _opt_int(c, "modulus_power")
|
||||
r = _opt_int(c, "residue_mod_2p")
|
||||
thr = _opt_int(c, "threshold")
|
||||
if m is None or r is None or thr is None:
|
||||
raise ValueError("Invalid terminal clause entry: missing modulus/residue/threshold")
|
||||
out.append(
|
||||
TerminalClause(
|
||||
kind=kind,
|
||||
modulus_power=m,
|
||||
residue_mod_2p=r,
|
||||
threshold=thr,
|
||||
source_n=_opt_int(c, "residue_mod_2p") or 0,
|
||||
k_or_t=_opt_int(c, "k_or_t"),
|
||||
A=_opt_int(c, "A"),
|
||||
)
|
||||
)
|
||||
return out
|
||||
|
||||
|
||||
def _parent_residue(*, r: int, m: int) -> int:
|
||||
return r % (1 << m)
|
||||
|
||||
|
||||
def _child_residues(*, r: int, m: int) -> tuple[int, int]:
|
||||
return (r, r + (1 << m))
|
||||
|
||||
|
||||
def run(*, palier: int, clauses_json: Path, output_dir: Path, repo_root: Path, source: str) -> None:
|
||||
cobj = _read_json(clauses_json)
|
||||
if not isinstance(cobj, dict):
|
||||
raise ValueError("Invalid clauses JSON: expected object")
|
||||
if source == "optionA":
|
||||
terminal = _load_terminal_clauses_from_option_a(clauses_obj=cobj, palier=palier)
|
||||
elif source == "overSm":
|
||||
terminal = _load_terminal_clauses_from_over_sm(obj=cobj, palier=palier)
|
||||
else:
|
||||
raise ValueError("Invalid source (expected optionA or overSm)")
|
||||
if not terminal:
|
||||
raise ValueError("No terminal clauses found (D_exact/F with stable modulus)")
|
||||
|
||||
# De-duplicate terminal clauses by exact node (m,r), keep minimal threshold for determinism.
|
||||
by_node: dict[tuple[int, int], TerminalClause] = {}
|
||||
for c in terminal:
|
||||
key = (c.modulus_power, c.residue_mod_2p)
|
||||
prev = by_node.get(key)
|
||||
if prev is None:
|
||||
by_node[key] = c
|
||||
continue
|
||||
if (c.threshold, c.kind, c.source_n) < (prev.threshold, prev.kind, prev.source_n):
|
||||
by_node[key] = c
|
||||
|
||||
max_m = max(m for (m, _) in by_node.keys())
|
||||
if max_m < palier:
|
||||
raise ValueError("Invalid clause set: max modulus < palier")
|
||||
|
||||
# Sparse node set: include all ancestors of terminal nodes down to palier.
|
||||
nodes_by_level: dict[int, set[int]] = {m: set() for m in range(palier, max_m + 1)}
|
||||
for (m, r) in by_node.keys():
|
||||
cur_r = r
|
||||
for mm in range(m, palier - 1, -1):
|
||||
nodes_by_level[mm].add(_parent_residue(r=cur_r, m=mm))
|
||||
cur_r = _parent_residue(r=cur_r, m=mm - 1) if mm - 1 >= palier else cur_r
|
||||
|
||||
# Bottom-up closure.
|
||||
closed_by_level: dict[int, set[int]] = {m: set() for m in range(palier, max_m + 1)}
|
||||
for m in range(max_m, palier - 1, -1):
|
||||
for r in sorted(nodes_by_level[m]):
|
||||
if (m, r) in by_node:
|
||||
closed_by_level[m].add(r)
|
||||
continue
|
||||
if m == max_m:
|
||||
continue
|
||||
c0, c1 = _child_residues(r=r, m=m)
|
||||
if (c0 in closed_by_level[m + 1]) and (c1 in closed_by_level[m + 1]):
|
||||
closed_by_level[m].add(r)
|
||||
|
||||
closed_roots = sorted(closed_by_level[palier])
|
||||
total_roots = 1 << (palier - 1) # odd residues modulo 2^M
|
||||
|
||||
# Collect leaves per closed root (clauses that close its refinement tree).
|
||||
memo_leaves: dict[tuple[int, int], list[tuple[int, int]]] = {}
|
||||
|
||||
def leaves(m: int, r: int) -> list[tuple[int, int]]:
|
||||
key = (m, r)
|
||||
cached = memo_leaves.get(key)
|
||||
if cached is not None:
|
||||
return cached
|
||||
if (m, r) in by_node:
|
||||
res = [(m, r)]
|
||||
memo_leaves[key] = res
|
||||
return res
|
||||
if m >= max_m:
|
||||
raise ValueError("Closed node expected to have descendants")
|
||||
c0, c1 = _child_residues(r=r, m=m)
|
||||
if (c0 not in closed_by_level[m + 1]) or (c1 not in closed_by_level[m + 1]):
|
||||
raise ValueError("Closed node has non-closed child")
|
||||
res = leaves(m + 1, c0) + leaves(m + 1, c1)
|
||||
memo_leaves[key] = res
|
||||
return res
|
||||
|
||||
closed_entries: list[dict[str, object]] = []
|
||||
for r0 in closed_roots:
|
||||
lf = leaves(palier, r0)
|
||||
lf_clauses = [by_node[(m, r)].to_json() for (m, r) in sorted(lf)]
|
||||
max_leaf_m = max(m for (m, _) in lf)
|
||||
closed_entries.append(
|
||||
{
|
||||
"root_residue_mod_2p": r0,
|
||||
"root_modulus_power": palier,
|
||||
"leaf_count": len(lf),
|
||||
"max_leaf_modulus_power": max_leaf_m,
|
||||
"max_refinement_depth": max_leaf_m - palier,
|
||||
"leaves": lf_clauses,
|
||||
}
|
||||
)
|
||||
|
||||
generated_at = _generated_at_utc_from_mtime([clauses_json])
|
||||
sha = {_display_path(clauses_json, repo_root): _sha256_file(clauses_json)}
|
||||
|
||||
out_json = output_dir / f"refinement_certificate_Sm_mod2p{palier}.json"
|
||||
out_md = output_dir / f"refinement_certificate_Sm_mod2p{palier}.md"
|
||||
audit_json = output_dir / f"audit_refinement_certificate_Sm_mod2p{palier}.json"
|
||||
audit_md = output_dir / f"audit_refinement_certificate_Sm_mod2p{palier}.md"
|
||||
|
||||
cert_obj: dict[str, object] = {
|
||||
"inputs": {
|
||||
"clauses_json": _display_path(clauses_json, repo_root),
|
||||
"source": source,
|
||||
},
|
||||
"domain": {
|
||||
"palier": palier,
|
||||
"S_M_size": total_roots,
|
||||
"candidate_roots_with_descendant_clauses": len(nodes_by_level[palier]),
|
||||
},
|
||||
"generated_at": generated_at,
|
||||
"sha256": sha,
|
||||
"closed_roots": {
|
||||
"count": len(closed_roots),
|
||||
"rows": closed_entries,
|
||||
},
|
||||
}
|
||||
_write_json(out_json, cert_obj)
|
||||
|
||||
open_count = total_roots - len(closed_roots)
|
||||
audit_obj: dict[str, object] = {
|
||||
"domain": {
|
||||
"palier": palier,
|
||||
"S_M_size": total_roots,
|
||||
},
|
||||
"closure": {
|
||||
"closed_roots": len(closed_roots),
|
||||
"open_roots": open_count,
|
||||
"closed_ratio": (len(closed_roots) / total_roots) if total_roots else 0.0,
|
||||
},
|
||||
"generated_at": generated_at,
|
||||
"sha256": {
|
||||
"inputs": sha,
|
||||
"outputs": {
|
||||
_display_path(out_json, repo_root): _sha256_file(out_json),
|
||||
},
|
||||
},
|
||||
}
|
||||
_write_json(audit_json, audit_obj)
|
||||
|
||||
md: list[str] = []
|
||||
md.append("**Auteur** : Équipe 4NK")
|
||||
md.append("")
|
||||
md.append(f"# Certificat de raffinement sur S_M — palier 2^{palier}")
|
||||
md.append("")
|
||||
md.append("## Entrée")
|
||||
md.append("")
|
||||
md.append(f"- clauses : `{_display_path(clauses_json, repo_root)}`")
|
||||
md.append("")
|
||||
md.append("## Domaine")
|
||||
md.append("")
|
||||
md.append(f"- palier : 2^{palier}")
|
||||
md.append(f"- |S_M| (impairs) : {total_roots}")
|
||||
md.append(f"- racines candidates (au moins une clause descendante) : {len(nodes_by_level[palier])}")
|
||||
md.append(f"- generated_at : {generated_at}")
|
||||
md.append("")
|
||||
md.append("## Fermeture (sur S_M)")
|
||||
md.append("")
|
||||
md.append(f"- racines fermées : {len(closed_roots)}")
|
||||
md.append(f"- racines ouvertes : {open_count}")
|
||||
md.append("")
|
||||
md.append("### Racines fermées (extrait)")
|
||||
md.append("")
|
||||
for row in closed_entries[:20]:
|
||||
md.append(
|
||||
f"- r={row['root_residue_mod_2p']} leaves={row['leaf_count']} max_depth={row['max_refinement_depth']}"
|
||||
)
|
||||
if len(closed_entries) > 20:
|
||||
md.append(f"- ... ({len(closed_entries)-20} more)")
|
||||
md.append("")
|
||||
md.append("## Sorties")
|
||||
md.append("")
|
||||
md.append(f"- JSON : `{_display_path(out_json, repo_root)}`")
|
||||
md.append(f"- Audit JSON : `{_display_path(audit_json, repo_root)}`")
|
||||
_write_md(out_md, md)
|
||||
|
||||
amd: list[str] = []
|
||||
amd.append("**Auteur** : Équipe 4NK")
|
||||
amd.append("")
|
||||
amd.append(f"# Audit — certificat de raffinement sur S_M (2^{palier})")
|
||||
amd.append("")
|
||||
amd.append(f"- closed_roots : {len(closed_roots)}")
|
||||
amd.append(f"- open_roots : {open_count}")
|
||||
amd.append(f"- closed_ratio : {(len(closed_roots) / total_roots) if total_roots else 0.0}")
|
||||
amd.append("")
|
||||
_write_md(audit_md, amd)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ap = argparse.ArgumentParser(description="Build refinement certificate over the full S_M (odd residues modulo 2^M)")
|
||||
ap.add_argument("--repo-root", default=".", help="Repository root (defaults to current working directory)")
|
||||
ap.add_argument("--palier", type=int, default=15, help="Palier M for S_M")
|
||||
ap.add_argument(
|
||||
"--source",
|
||||
default="optionA",
|
||||
choices=["optionA", "overSm"],
|
||||
help="Clause source: optionA (clauses_universelles.json) or overSm (directly decidable terminal clauses over S_M)",
|
||||
)
|
||||
ap.add_argument("--clauses-json", default="", help="Path to clauses JSON (source-dependent)")
|
||||
ap.add_argument("--output-dir", default="", help="Output directory for refinement artefacts")
|
||||
args = ap.parse_args()
|
||||
|
||||
repo_root = Path(args.repo_root).resolve()
|
||||
palier = int(args.palier)
|
||||
if args.clauses_json.strip():
|
||||
clauses_json = Path(args.clauses_json).resolve()
|
||||
else:
|
||||
clauses_json = (
|
||||
_infer_default_clauses_json(repo_root=repo_root, palier=palier)
|
||||
if args.source == "optionA"
|
||||
else _infer_default_terminal_over_sm_json(repo_root=repo_root, palier=palier)
|
||||
)
|
||||
output_dir = Path(args.output_dir).resolve() if args.output_dir.strip() else _infer_default_output_dir(repo_root=repo_root, palier=palier)
|
||||
|
||||
run(palier=palier, clauses_json=clauses_json, output_dir=output_dir, repo_root=repo_root, source=str(args.source))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@ -0,0 +1,364 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
collatz_build_refinement_certificate_over_Sm_multilevel.py
|
||||
|
||||
Build a deterministic refinement-closure audit for roots in S_M using terminal leaves
|
||||
provided at multiple modulus levels (e.g. direct decidability at 2^16 to close roots at 2^15).
|
||||
|
||||
Given a root palier M and a max palier M_max>=M, we consider the full refinement tree
|
||||
of odd residues from level M to level M_max. A node (m,r) is closed if:
|
||||
- it is a leaf: there exists a terminal clause provided at that exact level m and residue r, OR
|
||||
- both children (m+1,r) and (m+1,r+2^m) are closed.
|
||||
|
||||
This artefact is purely structural ("closure by refinement") and does not claim global
|
||||
termination beyond the validity of the terminal clauses used as leaves.
|
||||
|
||||
Inputs:
|
||||
- one or more JSON files produced by collatz_generate_terminal_clauses_over_Sm.py
|
||||
(clauses_terminal_over_Sm_mod2p<m>.json), each providing leaves at its palier.
|
||||
|
||||
Outputs:
|
||||
- docs/artefacts/collatz/refinement_K/palier2p<M>/refinement_certificate_Sm_multilevel_mod2p<M>_to2p<M_max>.{json,md}
|
||||
- docs/artefacts/collatz/refinement_K/palier2p<M>/audit_refinement_certificate_Sm_multilevel_mod2p<M>_to2p<M_max>.{json,md}
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def _read_json(path: Path) -> object:
|
||||
return json.loads(path.read_text(encoding="utf-8", errors="strict"))
|
||||
|
||||
|
||||
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 _sha256_file(path: Path, chunk_size: int = 16 * 1024 * 1024) -> str:
|
||||
h = hashlib.sha256()
|
||||
with path.open("rb") as f:
|
||||
while True:
|
||||
chunk = f.read(chunk_size)
|
||||
if not chunk:
|
||||
break
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def _utc_now_iso() -> str:
|
||||
return datetime.now(tz=timezone.utc).isoformat().replace("+00:00", "Z")
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class LeafSet:
|
||||
palier: int
|
||||
residues: set[int]
|
||||
source_json: str
|
||||
|
||||
|
||||
def _load_leaf_set(path: Path) -> LeafSet:
|
||||
obj = _read_json(path)
|
||||
if not isinstance(obj, dict):
|
||||
raise ValueError(f"Invalid leaf JSON: expected object: {path}")
|
||||
domain = obj.get("domain")
|
||||
if not isinstance(domain, dict):
|
||||
raise ValueError(f"Invalid leaf JSON: missing domain: {path}")
|
||||
palier = _req_int(domain, "palier")
|
||||
clauses = obj.get("clauses")
|
||||
if not isinstance(clauses, list) or not all(isinstance(x, dict) for x in clauses):
|
||||
raise ValueError(f"Invalid leaf JSON: missing clauses list: {path}")
|
||||
residues: set[int] = set()
|
||||
for c in clauses:
|
||||
m = c.get("modulus_power")
|
||||
r = c.get("residue_mod_2p")
|
||||
if m != palier:
|
||||
raise ValueError(f"Invalid clause entry: modulus_power mismatch vs file palier: got {m}, expected {palier}")
|
||||
if not isinstance(r, int):
|
||||
raise ValueError("Invalid clause entry: missing residue_mod_2p")
|
||||
residues.add(r)
|
||||
return LeafSet(palier=palier, residues=residues, source_json=str(path))
|
||||
|
||||
|
||||
def run(*, root_palier: int, max_palier: int, leaf_json_paths: list[Path], output_dir: Path, repo_root: Path) -> None:
|
||||
if max_palier < root_palier:
|
||||
raise ValueError("max_palier must be >= root_palier")
|
||||
if not leaf_json_paths:
|
||||
raise ValueError("At least one leaf JSON must be provided")
|
||||
|
||||
leaf_sets = [_load_leaf_set(p) for p in leaf_json_paths]
|
||||
leaves_by_m: dict[int, set[int]] = {}
|
||||
for ls in leaf_sets:
|
||||
leaves_by_m.setdefault(ls.palier, set()).update(ls.residues)
|
||||
for m in range(root_palier, max_palier + 1):
|
||||
leaves_by_m.setdefault(m, set())
|
||||
|
||||
def compute_closed_by_level(*, target_max: int) -> dict[int, set[int]]:
|
||||
closed: dict[int, set[int]] = {m: set() for m in range(root_palier, target_max + 1)}
|
||||
for m in range(root_palier, target_max + 1):
|
||||
closed[m] |= leaves_by_m[m]
|
||||
for m in range(target_max - 1, root_palier - 1, -1):
|
||||
step = 1 << m
|
||||
for r in range(1, 1 << m, 2):
|
||||
if r in closed[m]:
|
||||
continue
|
||||
if (r in closed[m + 1]) and ((r + step) in closed[m + 1]):
|
||||
closed[m].add(r)
|
||||
return closed
|
||||
|
||||
def compute_closed_roots(*, target_max: int) -> set[int]:
|
||||
closed = compute_closed_by_level(target_max=target_max)
|
||||
return closed[root_palier]
|
||||
|
||||
total_roots = 1 << (root_palier - 1)
|
||||
|
||||
closed_roots_by_max: dict[int, set[int]] = {}
|
||||
for target in range(root_palier, max_palier + 1):
|
||||
closed_roots_by_max[target] = compute_closed_roots(target_max=target)
|
||||
|
||||
closed_roots = sorted(closed_roots_by_max[max_palier])
|
||||
open_roots = total_roots - len(closed_roots)
|
||||
|
||||
closed_by_level_final = compute_closed_by_level(target_max=max_palier)
|
||||
open_count_by_m: dict[int, int] = {}
|
||||
q_by_m: dict[int, float] = {}
|
||||
parents_one_child_by_m: dict[int, int] = {}
|
||||
for m in range(root_palier, max_palier + 1):
|
||||
total_nodes_m = 1 << (m - 1)
|
||||
open_count_by_m[m] = total_nodes_m - len(closed_by_level_final[m])
|
||||
for m in range(root_palier, max_palier):
|
||||
denom = 2 * open_count_by_m[m]
|
||||
q_by_m[m] = (open_count_by_m[m + 1] / denom) if denom else 0.0
|
||||
step = 1 << m
|
||||
parents_one_child = 0
|
||||
for r in range(1, 1 << m, 2):
|
||||
if r in closed_by_level_final[m]:
|
||||
continue
|
||||
child0_closed = r in closed_by_level_final[m + 1]
|
||||
child1_closed = (r + step) in closed_by_level_final[m + 1]
|
||||
# parent is open; count it if exactly one child is open
|
||||
if child0_closed != child1_closed:
|
||||
parents_one_child += 1
|
||||
parents_one_child_by_m[m] = parents_one_child
|
||||
|
||||
# first closure depth per root (minimal target max palier where it becomes closed), if any
|
||||
first_close: dict[int, int] = {}
|
||||
for r0 in range(1, 1 << root_palier, 2):
|
||||
for target in range(root_palier, max_palier + 1):
|
||||
if r0 in closed_roots_by_max[target]:
|
||||
first_close[r0] = target
|
||||
break
|
||||
|
||||
newly_closed_by_target: dict[int, list[int]] = {}
|
||||
prev_closed: set[int] = set()
|
||||
for target in range(root_palier, max_palier + 1):
|
||||
cur_closed = closed_roots_by_max[target]
|
||||
newly = sorted([r for r in cur_closed if r not in prev_closed])
|
||||
newly_closed_by_target[target] = newly
|
||||
prev_closed = set(cur_closed)
|
||||
|
||||
still_open = sorted([r for r in range(1, 1 << root_palier, 2) if r not in closed_roots_by_max[max_palier]])
|
||||
|
||||
inputs_sha: dict[str, str] = {}
|
||||
for p in leaf_json_paths:
|
||||
rel = str(p.resolve().relative_to(repo_root.resolve())) if p.is_absolute() else str(p)
|
||||
inputs_sha[rel] = _sha256_file(p)
|
||||
|
||||
cert_json = output_dir / f"refinement_certificate_Sm_multilevel_mod2p{root_palier}_to2p{max_palier}.json"
|
||||
cert_md = output_dir / f"refinement_certificate_Sm_multilevel_mod2p{root_palier}_to2p{max_palier}.md"
|
||||
audit_json = output_dir / f"audit_refinement_certificate_Sm_multilevel_mod2p{root_palier}_to2p{max_palier}.json"
|
||||
audit_md = output_dir / f"audit_refinement_certificate_Sm_multilevel_mod2p{root_palier}_to2p{max_palier}.md"
|
||||
|
||||
generated_at = _utc_now_iso()
|
||||
|
||||
cert_obj: dict[str, object] = {
|
||||
"domain": {
|
||||
"root_palier": root_palier,
|
||||
"max_palier": max_palier,
|
||||
"S_root_size": total_roots,
|
||||
},
|
||||
"inputs": {
|
||||
"leaf_sources": [str(p) for p in leaf_json_paths],
|
||||
},
|
||||
"generated_at": generated_at,
|
||||
"sha256": {"inputs": inputs_sha},
|
||||
"closure": {
|
||||
"closed_roots": len(closed_roots),
|
||||
"open_roots": open_roots,
|
||||
"closed_ratio": (len(closed_roots) / total_roots) if total_roots else 0.0,
|
||||
"closed_roots_sample": closed_roots[:200],
|
||||
"still_open_roots_sample": still_open[:200],
|
||||
},
|
||||
"residue_audit": {
|
||||
"open_count_by_palier": {str(k): v for k, v in open_count_by_m.items()},
|
||||
"q_by_palier": {str(k): v for k, v in q_by_m.items()},
|
||||
"parents_one_child_by_palier": {str(k): v for k, v in parents_one_child_by_m.items()},
|
||||
},
|
||||
"timeline": [
|
||||
{
|
||||
"target_max_palier": target,
|
||||
"closed_roots": len(closed_roots_by_max[target]),
|
||||
"open_roots": total_roots - len(closed_roots_by_max[target]),
|
||||
"newly_closed_at_target": len(newly_closed_by_target[target]),
|
||||
}
|
||||
for target in range(root_palier, max_palier + 1)
|
||||
],
|
||||
"newly_closed_roots_by_target": {str(k): v for k, v in newly_closed_by_target.items()},
|
||||
"first_close_palier_by_root": {str(k): v for k, v in first_close.items()},
|
||||
}
|
||||
_write_json(cert_json, cert_obj)
|
||||
|
||||
audit_obj: dict[str, object] = {
|
||||
"domain": cert_obj["domain"],
|
||||
"closure": cert_obj["closure"],
|
||||
"generated_at": generated_at,
|
||||
"sha256": {
|
||||
"inputs": inputs_sha,
|
||||
"outputs": {str(cert_json.relative_to(repo_root)): _sha256_file(cert_json)} if cert_json.is_absolute() else {},
|
||||
},
|
||||
}
|
||||
_write_json(audit_json, audit_obj)
|
||||
|
||||
md: list[str] = []
|
||||
md.append("**Auteur** : Équipe 4NK")
|
||||
md.append("")
|
||||
md.append(f"# Certificat de raffinement multi-niveaux sur S_M — racine 2^{root_palier} vers 2^{max_palier}")
|
||||
md.append("")
|
||||
md.append("## Domaine")
|
||||
md.append("")
|
||||
md.append(f"- racine : 2^{root_palier}")
|
||||
md.append(f"- profondeur max : 2^{max_palier}")
|
||||
md.append(f"- |S_{root_palier}| (impairs) : {total_roots}")
|
||||
md.append("")
|
||||
md.append("## Entrées (feuilles terminales)")
|
||||
md.append("")
|
||||
for p in leaf_json_paths:
|
||||
md.append(f"- `{p}`")
|
||||
md.append("")
|
||||
md.append("## Fermeture (sur S_M)")
|
||||
md.append("")
|
||||
md.append(f"- closed_roots : {len(closed_roots)}")
|
||||
md.append(f"- open_roots : {open_roots}")
|
||||
md.append(f"- closed_ratio : {(len(closed_roots) / total_roots) if total_roots else 0.0}")
|
||||
md.append("")
|
||||
md.append("## Timeline (première profondeur de fermeture)")
|
||||
md.append("")
|
||||
md.append("| cible | newly_closed | closed | open | closed_ratio |")
|
||||
md.append("| --- | --- | --- | --- | --- |")
|
||||
for row in cert_obj["timeline"]: # type: ignore[assignment]
|
||||
target = int(row["target_max_palier"]) # type: ignore[index]
|
||||
newly = int(row["newly_closed_at_target"]) # type: ignore[index]
|
||||
closed_cnt = int(row["closed_roots"]) # type: ignore[index]
|
||||
open_cnt = int(row["open_roots"]) # type: ignore[index]
|
||||
ratio = closed_cnt / total_roots if total_roots else 0.0
|
||||
md.append(f"| {target} | {newly} | {closed_cnt} | {open_cnt} | {ratio:.6f} |")
|
||||
md.append("")
|
||||
md.append("## Audit du résidu (comptes, q_m, parents à un enfant)")
|
||||
md.append("")
|
||||
md.append("| m | open_count | q_m | parents_one_child |")
|
||||
md.append("| --- | --- | --- | --- |")
|
||||
for m in range(root_palier, max_palier):
|
||||
md.append(
|
||||
f"| {m} | {open_count_by_m[m]} | {q_by_m[m]:.12f} | {parents_one_child_by_m[m]} |"
|
||||
)
|
||||
md.append(f"| {max_palier} | {open_count_by_m[max_palier]} | | |")
|
||||
md.append("")
|
||||
md.append("### Racines encore ouvertes (extrait)")
|
||||
md.append("")
|
||||
for r in still_open[:40]:
|
||||
md.append(f"- r={r}")
|
||||
if len(still_open) > 40:
|
||||
md.append(f"- ... ({len(still_open)-40} more)")
|
||||
md.append("")
|
||||
md.append("### Racines fermées (extrait)")
|
||||
md.append("")
|
||||
for r in closed_roots[:40]:
|
||||
md.append(f"- r={r}")
|
||||
if len(closed_roots) > 40:
|
||||
md.append(f"- ... ({len(closed_roots)-40} more)")
|
||||
md.append("")
|
||||
md.append("## Sorties")
|
||||
md.append("")
|
||||
md.append(f"- JSON : `{cert_json}`")
|
||||
md.append(f"- Audit JSON : `{audit_json}`")
|
||||
md.append("")
|
||||
_write_md(cert_md, md)
|
||||
|
||||
amd: list[str] = []
|
||||
amd.append("**Auteur** : Équipe 4NK")
|
||||
amd.append("")
|
||||
amd.append(f"# Audit — raffinement multi-niveaux sur S_M (2^{root_palier}→2^{max_palier})")
|
||||
amd.append("")
|
||||
amd.append(f"- closed_roots : {len(closed_roots)}")
|
||||
amd.append(f"- open_roots : {open_roots}")
|
||||
amd.append(f"- closed_ratio : {(len(closed_roots) / total_roots) if total_roots else 0.0}")
|
||||
amd.append("")
|
||||
_write_md(audit_md, amd)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ap = argparse.ArgumentParser(description="Build a multilevel refinement closure audit over S_M")
|
||||
ap.add_argument("--repo-root", default=".", help="Repository root")
|
||||
ap.add_argument("--root-palier", type=int, default=15, help="Root palier M")
|
||||
ap.add_argument("--max-palier", type=int, default=16, help="Max palier for refinement")
|
||||
ap.add_argument(
|
||||
"--leaf-json",
|
||||
action="append",
|
||||
default=[],
|
||||
help="Leaf JSON path (can be repeated). If omitted, uses terminal_clauses_over_Sm for root and max levels.",
|
||||
)
|
||||
ap.add_argument("--output-dir", default="", help="Output directory (defaults under docs/artefacts/...)")
|
||||
args = ap.parse_args()
|
||||
|
||||
repo_root = Path(args.repo_root).resolve()
|
||||
root_palier = int(args.root_palier)
|
||||
max_palier = int(args.max_palier)
|
||||
|
||||
default_leafs: list[Path] = []
|
||||
for m in range(root_palier, max_palier + 1):
|
||||
default_leafs.append(
|
||||
repo_root
|
||||
/ "docs"
|
||||
/ "artefacts"
|
||||
/ "collatz"
|
||||
/ "terminal_clauses_over_Sm"
|
||||
/ f"palier2p{m}"
|
||||
/ f"clauses_terminal_over_Sm_mod2p{m}.json"
|
||||
)
|
||||
|
||||
leaf_paths = [Path(p).resolve() for p in args.leaf_json] if args.leaf_json else default_leafs
|
||||
output_dir = Path(args.output_dir).resolve() if args.output_dir.strip() else (
|
||||
repo_root / "docs" / "artefacts" / "collatz" / "refinement_K" / f"palier2p{root_palier}"
|
||||
)
|
||||
|
||||
run(
|
||||
root_palier=root_palier,
|
||||
max_palier=max_palier,
|
||||
leaf_json_paths=leaf_paths,
|
||||
output_dir=output_dir,
|
||||
repo_root=repo_root,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@ -0,0 +1,990 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
collatz_build_register_K_modular.py
|
||||
|
||||
Build a deterministic, versionable modular register K_M and a finite coverage audit
|
||||
from Option A artefacts.
|
||||
|
||||
Inputs:
|
||||
- universal clauses artefact produced by `collatz_extract_universal_clauses.py`
|
||||
(clauses_universelles.json)
|
||||
- C3 verification JSON referenced by the clauses artefact, or provided explicitly
|
||||
|
||||
Outputs (versionable, no transcripts):
|
||||
- register_K_mod2p<M>.{json,md}
|
||||
- audit_register_K_mod2p<M>.{json,md}
|
||||
- non_eligible_clauses_mod2p<M>.{json,md}
|
||||
- manifest_register_K_mod2p<M>.{json,md}
|
||||
|
||||
Scope:
|
||||
- K_M contains only clauses with modulus power m(c) <= M (decidable at palier 2^M).
|
||||
- The coverage audit is performed on the finite C3 domain L (the record n's), not on S_M.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any, Literal
|
||||
|
||||
|
||||
ClauseKind = Literal["D_exact", "F", "D_brother_local"]
|
||||
|
||||
|
||||
def _read_json(path: Path) -> object:
|
||||
return json.loads(path.read_text(encoding="utf-8", errors="strict"))
|
||||
|
||||
|
||||
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 _sha256_file(path: Path, chunk_size: int = 16 * 1024 * 1024) -> str:
|
||||
h = hashlib.sha256()
|
||||
with path.open("rb") as f:
|
||||
while True:
|
||||
chunk = f.read(chunk_size)
|
||||
if not chunk:
|
||||
break
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def _file_size_bytes(path: Path) -> int:
|
||||
if not path.exists():
|
||||
raise FileNotFoundError(str(path))
|
||||
return path.stat().st_size
|
||||
|
||||
|
||||
def _file_mtime_utc_iso(path: Path) -> str:
|
||||
if not path.exists():
|
||||
raise FileNotFoundError(str(path))
|
||||
ts = path.stat().st_mtime
|
||||
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
|
||||
return dt.isoformat().replace("+00:00", "Z")
|
||||
|
||||
|
||||
def _file_mtime_epoch_seconds(path: Path) -> float:
|
||||
if not path.exists():
|
||||
raise FileNotFoundError(str(path))
|
||||
return float(path.stat().st_mtime)
|
||||
|
||||
|
||||
def _float_equal(a: float, b: float, eps: float = 1e-6) -> bool:
|
||||
return abs(a - b) <= eps
|
||||
|
||||
|
||||
class CheckMismatchError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def _generated_at_utc_from_mtime(paths: list[Path]) -> str:
|
||||
mtimes = [p.stat().st_mtime for p in paths if p.exists()]
|
||||
if not mtimes:
|
||||
raise ValueError("Cannot infer generated_at: no existing input paths")
|
||||
ts = max(mtimes)
|
||||
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
|
||||
return dt.isoformat().replace("+00:00", "Z")
|
||||
|
||||
|
||||
def _display_path(path: Path, repo_root: Path) -> str:
|
||||
try:
|
||||
rel = path.resolve().relative_to(repo_root.resolve())
|
||||
return str(rel)
|
||||
except ValueError:
|
||||
return str(path)
|
||||
|
||||
|
||||
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 _opt_int(d: dict[str, object], key: str) -> int | None:
|
||||
v = d.get(key)
|
||||
if v is None:
|
||||
return None
|
||||
if not isinstance(v, int):
|
||||
raise ValueError(f"Expected int|null for {key}")
|
||||
return v
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class EligibleClause:
|
||||
kind: ClauseKind
|
||||
modulus_power: int
|
||||
residue_mod_2p: int
|
||||
threshold: int
|
||||
source_n: int
|
||||
# optional payload for traceability
|
||||
k_or_t: int | None
|
||||
A: int | None
|
||||
C: int | None
|
||||
a: int | None
|
||||
y: int | None
|
||||
preimage_m: int | None
|
||||
DeltaF: int | None
|
||||
|
||||
def to_json(self) -> dict[str, object]:
|
||||
return {
|
||||
"kind": self.kind,
|
||||
"modulus_power": self.modulus_power,
|
||||
"residue_mod_2p": self.residue_mod_2p,
|
||||
"threshold": self.threshold,
|
||||
"source_n": self.source_n,
|
||||
"k_or_t": self.k_or_t,
|
||||
"A": self.A,
|
||||
"C": self.C,
|
||||
"a": self.a,
|
||||
"y": self.y,
|
||||
"preimage_m": self.preimage_m,
|
||||
"DeltaF": self.DeltaF,
|
||||
}
|
||||
|
||||
|
||||
def _infer_default_clauses_json(*, repo_root: Path, palier: int) -> Path:
|
||||
base = repo_root / "docs" / "artefacts" / "collatz" / "universal_clauses"
|
||||
if palier == 13:
|
||||
return base / "clauses_universelles.json"
|
||||
return base / f"palier2p{palier}" / "clauses_universelles.json"
|
||||
|
||||
|
||||
def _infer_default_output_dir(*, repo_root: Path, palier: int) -> Path:
|
||||
return repo_root / "docs" / "artefacts" / "collatz" / "register_K" / f"palier2p{palier}"
|
||||
|
||||
|
||||
def _load_c3_verification_path_from_clauses(*, clauses_obj: dict[str, object], repo_root: Path) -> Path:
|
||||
inputs = clauses_obj.get("inputs")
|
||||
if not isinstance(inputs, dict):
|
||||
raise ValueError("Invalid clauses JSON: missing inputs")
|
||||
p = inputs.get("verification_c3_local_descent_json")
|
||||
if not isinstance(p, str) or not p.strip():
|
||||
raise ValueError("Invalid clauses JSON: missing inputs.verification_c3_local_descent_json")
|
||||
path = Path(p)
|
||||
if not path.is_absolute():
|
||||
path = repo_root / path
|
||||
return path.resolve()
|
||||
|
||||
|
||||
def _eligible_clause_from_extracted(obj: dict[str, object]) -> EligibleClause | None:
|
||||
kind = obj.get("kind")
|
||||
if not isinstance(kind, str):
|
||||
raise ValueError("Invalid clause entry: missing kind")
|
||||
if kind not in ("D_exact", "F", "D_brother_local"):
|
||||
raise ValueError(f"Invalid clause entry: unknown kind {kind}")
|
||||
stable_m = _opt_int(obj, "stable_modulus_power")
|
||||
stable_r = _opt_int(obj, "stable_residue_mod_2p")
|
||||
if stable_m is None or stable_r is None:
|
||||
return None
|
||||
|
||||
source_n = _req_int(obj, "source_n")
|
||||
k_or_t = _opt_int(obj, "k_or_t")
|
||||
A = _opt_int(obj, "A")
|
||||
C = _opt_int(obj, "C")
|
||||
a = _opt_int(obj, "a")
|
||||
y = _opt_int(obj, "y")
|
||||
pre = _opt_int(obj, "preimage_m")
|
||||
dF = _opt_int(obj, "DeltaF")
|
||||
|
||||
if kind == "D_exact":
|
||||
thr = _opt_int(obj, "N0")
|
||||
if thr is None:
|
||||
raise ValueError("Invalid D_exact clause entry: missing N0")
|
||||
return EligibleClause(
|
||||
kind="D_exact",
|
||||
modulus_power=stable_m,
|
||||
residue_mod_2p=stable_r,
|
||||
threshold=thr,
|
||||
source_n=source_n,
|
||||
k_or_t=k_or_t,
|
||||
A=A,
|
||||
C=C,
|
||||
a=None,
|
||||
y=None,
|
||||
preimage_m=None,
|
||||
DeltaF=None,
|
||||
)
|
||||
|
||||
if kind == "F":
|
||||
thr = _opt_int(obj, "Nf")
|
||||
if thr is None:
|
||||
raise ValueError("Invalid F clause entry: missing Nf")
|
||||
return EligibleClause(
|
||||
kind="F",
|
||||
modulus_power=stable_m,
|
||||
residue_mod_2p=stable_r,
|
||||
threshold=thr,
|
||||
source_n=source_n,
|
||||
k_or_t=k_or_t,
|
||||
A=A,
|
||||
C=C,
|
||||
a=a,
|
||||
y=y,
|
||||
preimage_m=pre,
|
||||
DeltaF=dF,
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def _build_brother_local_entries(*, clauses: list[dict[str, object]], palier: int) -> list[EligibleClause]:
|
||||
"""
|
||||
Convert D_brother_local extracted entries into register entries that are decidable at the domain palier.
|
||||
|
||||
These entries are LOCAL to the instrumented domain L and are included only for traceability/piloting.
|
||||
They are not claimed as standalone universal clauses on S_M.
|
||||
"""
|
||||
by_source_n: dict[int, dict[str, object]] = {}
|
||||
for c in clauses:
|
||||
sn = c.get("source_n")
|
||||
if isinstance(sn, int):
|
||||
by_source_n[sn] = c
|
||||
|
||||
out: list[EligibleClause] = []
|
||||
for c in clauses:
|
||||
if c.get("kind") != "D_brother_local":
|
||||
continue
|
||||
sn = c.get("source_n")
|
||||
mate = c.get("mate_exact")
|
||||
if not isinstance(sn, int) or not isinstance(mate, int):
|
||||
raise ValueError("Invalid D_brother_local entry: missing source_n/mate_exact")
|
||||
mate_obj = by_source_n.get(mate)
|
||||
if mate_obj is None or mate_obj.get("kind") != "D_exact":
|
||||
raise ValueError(f"Invalid D_brother_local entry: mate_exact is not a D_exact clause: source_n={sn} mate={mate}")
|
||||
thr = _opt_int(mate_obj, "N0")
|
||||
if thr is None:
|
||||
raise ValueError(f"Invalid mate D_exact entry: missing N0: mate={mate}")
|
||||
out.append(
|
||||
EligibleClause(
|
||||
kind="D_brother_local",
|
||||
modulus_power=palier,
|
||||
residue_mod_2p=sn,
|
||||
threshold=thr,
|
||||
source_n=sn,
|
||||
k_or_t=_opt_int(mate_obj, "k_or_t"),
|
||||
A=_opt_int(mate_obj, "A"),
|
||||
C=_opt_int(mate_obj, "C"),
|
||||
a=None,
|
||||
y=None,
|
||||
preimage_m=None,
|
||||
DeltaF=None,
|
||||
)
|
||||
)
|
||||
return out
|
||||
|
||||
|
||||
def _compute_required_m_stable(*, domain_palier: int, record: dict[str, Any]) -> int | None:
|
||||
kind = record.get("kind")
|
||||
if kind == "D_exact":
|
||||
A = record.get("A_k")
|
||||
if not isinstance(A, int):
|
||||
raise ValueError("Invalid D_exact record: missing A_k")
|
||||
return max(domain_palier, A + 1)
|
||||
if kind == "F":
|
||||
A = record.get("A_t")
|
||||
if not isinstance(A, int):
|
||||
raise ValueError("Invalid F record: missing A_t")
|
||||
return max(domain_palier, A + 1)
|
||||
if kind == "D_brother":
|
||||
return None
|
||||
raise ValueError(f"Unknown C3 record kind: {kind}")
|
||||
|
||||
|
||||
def _check_manual_edits_from_manifest(*, manifest_json: Path, repo_root: Path) -> None:
|
||||
obj = _read_json(manifest_json)
|
||||
if not isinstance(obj, dict):
|
||||
raise ValueError("Invalid manifest JSON: expected object")
|
||||
mtimes = obj.get("mtimes")
|
||||
sizes = obj.get("sizes_bytes")
|
||||
if not isinstance(mtimes, dict) or not isinstance(sizes, dict):
|
||||
raise ValueError("Invalid manifest JSON: missing mtimes/sizes_bytes")
|
||||
outs_mtimes = mtimes.get("outputs")
|
||||
outs_sizes = sizes.get("outputs")
|
||||
if not isinstance(outs_mtimes, dict) or not isinstance(outs_sizes, dict):
|
||||
raise ValueError("Invalid manifest JSON: missing mtimes.outputs / sizes_bytes.outputs")
|
||||
|
||||
changed: list[str] = []
|
||||
for rel_path, meta in outs_mtimes.items():
|
||||
if not isinstance(rel_path, str) or not isinstance(meta, dict):
|
||||
raise ValueError("Invalid manifest JSON: mtimes.outputs must be object of objects")
|
||||
recorded_epoch = meta.get("mtime_epoch_seconds")
|
||||
recorded_iso = meta.get("mtime_utc_iso")
|
||||
if not isinstance(recorded_epoch, (int, float)) or not isinstance(recorded_iso, str):
|
||||
raise ValueError(f"Invalid manifest JSON: bad mtime meta for {rel_path}")
|
||||
rec_size = outs_sizes.get(rel_path)
|
||||
if not isinstance(rec_size, int):
|
||||
raise ValueError(f"Invalid manifest JSON: missing sizes_bytes.outputs for {rel_path}")
|
||||
|
||||
p = Path(rel_path)
|
||||
abs_p = p if p.is_absolute() else (repo_root / p)
|
||||
if not abs_p.exists():
|
||||
changed.append(f"{rel_path}: missing (recorded mtime={recorded_iso}, size={rec_size})")
|
||||
continue
|
||||
cur_epoch = _file_mtime_epoch_seconds(abs_p)
|
||||
cur_iso = _file_mtime_utc_iso(abs_p)
|
||||
cur_size = _file_size_bytes(abs_p)
|
||||
if (not _float_equal(cur_epoch, float(recorded_epoch))) or (cur_size != rec_size):
|
||||
changed.append(
|
||||
f"{rel_path}: recorded {recorded_iso} ({recorded_epoch}), size={rec_size}; current {cur_iso} ({cur_epoch}), size={cur_size}"
|
||||
)
|
||||
|
||||
if changed:
|
||||
details = "\n".join(changed[:60])
|
||||
more = "" if len(changed) <= 60 else f"\n... ({len(changed)-60} more)"
|
||||
raise CheckMismatchError(f"Detected output modifications since manifest:\n{details}{more}")
|
||||
|
||||
|
||||
def _check_sha256_from_manifest(*, manifest_json: Path, repo_root: Path) -> None:
|
||||
obj = _read_json(manifest_json)
|
||||
if not isinstance(obj, dict):
|
||||
raise ValueError("Invalid manifest JSON: expected object")
|
||||
sha = obj.get("sha256")
|
||||
if not isinstance(sha, dict):
|
||||
raise ValueError("Invalid manifest JSON: missing sha256")
|
||||
outs_sha = sha.get("outputs")
|
||||
if not isinstance(outs_sha, dict):
|
||||
raise ValueError("Invalid manifest JSON: missing sha256.outputs")
|
||||
|
||||
mismatches: list[str] = []
|
||||
for rel_path, recorded in outs_sha.items():
|
||||
if not isinstance(rel_path, str) or not isinstance(recorded, str):
|
||||
raise ValueError("Invalid manifest JSON: sha256.outputs must be object of strings")
|
||||
p = Path(rel_path)
|
||||
abs_p = p if p.is_absolute() else (repo_root / p)
|
||||
if not abs_p.exists():
|
||||
mismatches.append(f"{rel_path}: missing (recorded sha256={recorded})")
|
||||
continue
|
||||
cur = _sha256_file(abs_p)
|
||||
if cur != recorded:
|
||||
mismatches.append(f"{rel_path}: recorded {recorded}, current {cur}")
|
||||
|
||||
if mismatches:
|
||||
details = "\n".join(mismatches[:60])
|
||||
more = "" if len(mismatches) <= 60 else f"\n... ({len(mismatches)-60} more)"
|
||||
raise CheckMismatchError(f"Detected sha256 mismatches vs manifest:\n{details}{more}")
|
||||
|
||||
|
||||
def _check_inputs_sha256_from_manifest(*, manifest_json: Path, repo_root: Path) -> None:
|
||||
obj = _read_json(manifest_json)
|
||||
if not isinstance(obj, dict):
|
||||
raise ValueError("Invalid manifest JSON: expected object")
|
||||
sha = obj.get("sha256")
|
||||
if not isinstance(sha, dict):
|
||||
raise ValueError("Invalid manifest JSON: missing sha256")
|
||||
ins_sha = sha.get("inputs")
|
||||
if not isinstance(ins_sha, dict):
|
||||
raise ValueError("Invalid manifest JSON: missing sha256.inputs")
|
||||
|
||||
mismatches: list[str] = []
|
||||
for rel_path, recorded in ins_sha.items():
|
||||
if not isinstance(rel_path, str) or not isinstance(recorded, str):
|
||||
raise ValueError("Invalid manifest JSON: sha256.inputs must be object of strings")
|
||||
p = Path(rel_path)
|
||||
abs_p = p if p.is_absolute() else (repo_root / p)
|
||||
if not abs_p.exists():
|
||||
mismatches.append(f"{rel_path}: missing (recorded sha256={recorded})")
|
||||
continue
|
||||
cur = _sha256_file(abs_p)
|
||||
if cur != recorded:
|
||||
mismatches.append(f"{rel_path}: recorded {recorded}, current {cur}")
|
||||
|
||||
if mismatches:
|
||||
details = "\n".join(mismatches[:60])
|
||||
more = "" if len(mismatches) <= 60 else f"\n... ({len(mismatches)-60} more)"
|
||||
raise CheckMismatchError(f"Detected input sha256 mismatches vs manifest:\n{details}{more}")
|
||||
|
||||
|
||||
def run(*, palier: int, horizon_k: int, clauses_json: Path, c3_verification_json: Path, output_dir: Path, repo_root: Path) -> None:
|
||||
if palier < 1:
|
||||
raise ValueError("palier must be >= 1")
|
||||
if horizon_k < 1:
|
||||
raise ValueError("horizon_k must be >= 1")
|
||||
|
||||
cobj = _read_json(clauses_json)
|
||||
if not isinstance(cobj, dict):
|
||||
raise ValueError("Invalid clauses JSON: expected object")
|
||||
domain = cobj.get("domain")
|
||||
if not isinstance(domain, dict):
|
||||
raise ValueError("Invalid clauses JSON: missing domain")
|
||||
domain_palier = _req_int(domain, "palier")
|
||||
if domain_palier != palier:
|
||||
raise ValueError(f"Clauses domain palier mismatch: {domain_palier} != {palier}")
|
||||
clauses = cobj.get("clauses")
|
||||
if not isinstance(clauses, list) or not all(isinstance(x, dict) for x in clauses):
|
||||
raise ValueError("Invalid clauses JSON: missing clauses list")
|
||||
|
||||
eligible_raw: list[EligibleClause] = []
|
||||
for c in clauses:
|
||||
ec = _eligible_clause_from_extracted(c)
|
||||
if ec is None:
|
||||
continue
|
||||
if ec.modulus_power <= palier:
|
||||
eligible_raw.append(ec)
|
||||
|
||||
# Optional local entries: D_brother_local (decidable at domain palier, not universal on S_M)
|
||||
eligible_raw.extend(_build_brother_local_entries(clauses=clauses, palier=palier))
|
||||
|
||||
# de-duplicate by (kind, modulus, residue)
|
||||
seen: set[tuple[str, int, int]] = set()
|
||||
eligible: list[EligibleClause] = []
|
||||
for c in sorted(eligible_raw, key=lambda x: (x.kind, x.modulus_power, x.residue_mod_2p, x.threshold, x.source_n)):
|
||||
key = (c.kind, c.modulus_power, c.residue_mod_2p)
|
||||
if key in seen:
|
||||
continue
|
||||
seen.add(key)
|
||||
eligible.append(c)
|
||||
|
||||
n_star = max([c.threshold for c in eligible], default=0)
|
||||
|
||||
# coverage audit on L = {record.n} from C3 verification
|
||||
vobj = _read_json(c3_verification_json)
|
||||
if not isinstance(vobj, dict):
|
||||
raise ValueError("Invalid C3 verification JSON: expected object")
|
||||
vdomain = vobj.get("domain")
|
||||
vrecords = vobj.get("records")
|
||||
if not isinstance(vdomain, dict) or not isinstance(vrecords, list):
|
||||
raise ValueError("Invalid C3 verification JSON: missing domain/records")
|
||||
vpal = _req_int(vdomain, "palier")
|
||||
if vpal != palier:
|
||||
raise ValueError(f"C3 domain palier mismatch: {vpal} != {palier}")
|
||||
if not all(isinstance(r, dict) for r in vrecords):
|
||||
raise ValueError("Invalid C3 verification JSON: records must be objects")
|
||||
|
||||
L: list[int] = []
|
||||
by_n: dict[int, dict[str, Any]] = {}
|
||||
for r in vrecords:
|
||||
n = r.get("n")
|
||||
if not isinstance(n, int):
|
||||
raise ValueError("Invalid C3 record: missing n")
|
||||
if n in by_n:
|
||||
raise ValueError(f"Duplicate n in C3 records: {n}")
|
||||
by_n[n] = r # type: ignore[assignment]
|
||||
L.append(n)
|
||||
L_sorted = sorted(L)
|
||||
|
||||
covered: set[int] = set()
|
||||
for n in L_sorted:
|
||||
for c in eligible:
|
||||
mod = 1 << c.modulus_power
|
||||
if (n % mod) == c.residue_mod_2p:
|
||||
covered.add(n)
|
||||
break
|
||||
|
||||
uncovered = [n for n in L_sorted if n not in covered]
|
||||
uncovered_diagnostics: list[dict[str, object]] = []
|
||||
for n in uncovered[:500]:
|
||||
rec = by_n[n]
|
||||
required = _compute_required_m_stable(domain_palier=palier, record=rec)
|
||||
uncovered_diagnostics.append(
|
||||
{
|
||||
"n": n,
|
||||
"kind": rec.get("kind"),
|
||||
"required_m_stable": required,
|
||||
}
|
||||
)
|
||||
|
||||
# Non-eligible table (piloting): n in L whose required_m_stable > M, sorted by required_m_stable
|
||||
non_eligible: list[dict[str, object]] = []
|
||||
for n in L_sorted:
|
||||
rec = by_n[n]
|
||||
required = _compute_required_m_stable(domain_palier=palier, record=rec)
|
||||
if required is None:
|
||||
continue
|
||||
if required <= palier:
|
||||
continue
|
||||
delta_to_next = required - palier
|
||||
non_eligible.append(
|
||||
{
|
||||
"n": n,
|
||||
"kind": rec.get("kind"),
|
||||
"required_m_stable": required,
|
||||
"delta_to_next": delta_to_next,
|
||||
}
|
||||
)
|
||||
non_eligible_sorted = sorted(non_eligible, key=lambda x: (int(x["required_m_stable"]), int(x["n"]))) # type: ignore[arg-type]
|
||||
|
||||
buckets: dict[int, int] = {}
|
||||
for x in non_eligible_sorted:
|
||||
mreq = int(x["required_m_stable"]) # type: ignore[arg-type]
|
||||
buckets[mreq] = buckets.get(mreq, 0) + 1
|
||||
m_next = palier + 1
|
||||
gains_next = buckets.get(m_next, 0)
|
||||
max_required = max(buckets.keys(), default=palier)
|
||||
cum_rows: list[dict[str, object]] = []
|
||||
cum = 0
|
||||
for target in range(palier + 1, max_required + 1):
|
||||
newly = buckets.get(target, 0)
|
||||
cum += newly
|
||||
cum_rows.append(
|
||||
{
|
||||
"target_M": target,
|
||||
"k": target - palier,
|
||||
"newly_eligible_at_target": newly,
|
||||
"cumulative_newly_eligible_up_to_target": cum,
|
||||
"eligible_count_at_target": len(covered) + cum,
|
||||
}
|
||||
)
|
||||
|
||||
sha = {
|
||||
_display_path(clauses_json, repo_root): _sha256_file(clauses_json),
|
||||
_display_path(c3_verification_json, repo_root): _sha256_file(c3_verification_json),
|
||||
}
|
||||
generated_at = _generated_at_utc_from_mtime([clauses_json, c3_verification_json])
|
||||
|
||||
register_obj: dict[str, object] = {
|
||||
"inputs": {
|
||||
"clauses_universelles_json": _display_path(clauses_json, repo_root),
|
||||
"verification_c3_local_descent_json": _display_path(c3_verification_json, repo_root),
|
||||
},
|
||||
"sha256": sha,
|
||||
"domain": {
|
||||
"palier": palier,
|
||||
},
|
||||
"generation": {
|
||||
"horizon_k": horizon_k,
|
||||
"generated_at": generated_at,
|
||||
},
|
||||
"register": {
|
||||
"M": palier,
|
||||
"n_star": n_star,
|
||||
"clauses_total": len(eligible),
|
||||
"clauses": [c.to_json() for c in eligible],
|
||||
},
|
||||
}
|
||||
|
||||
audit_obj: dict[str, object] = {
|
||||
"inputs": register_obj["inputs"],
|
||||
"sha256": sha,
|
||||
"domain": {
|
||||
"palier": palier,
|
||||
"L_size": len(L_sorted),
|
||||
"L_min_n": min(L_sorted) if L_sorted else None,
|
||||
"L_max_n": max(L_sorted) if L_sorted else None,
|
||||
},
|
||||
"generation": {
|
||||
"horizon_k": horizon_k,
|
||||
"generated_at": generated_at,
|
||||
},
|
||||
"register": {
|
||||
"M": palier,
|
||||
"clauses_total": len(eligible),
|
||||
"n_star": n_star,
|
||||
},
|
||||
"coverage": {
|
||||
"covered_count": len(covered),
|
||||
"uncovered_count": len(uncovered),
|
||||
"uncovered_sample_limit": 500,
|
||||
"uncovered_sample": uncovered_diagnostics,
|
||||
},
|
||||
"ok_full_coverage_on_L": len(uncovered) == 0,
|
||||
}
|
||||
|
||||
non_eligible_obj: dict[str, object] = {
|
||||
"inputs": register_obj["inputs"],
|
||||
"sha256": sha,
|
||||
"domain": {
|
||||
"palier": palier,
|
||||
"L_size": len(L_sorted),
|
||||
},
|
||||
"non_eligible": {
|
||||
"criterion": "required_m_stable > M",
|
||||
"M": palier,
|
||||
"horizon_k": horizon_k,
|
||||
"generated_at": generated_at,
|
||||
"total": len(non_eligible_sorted),
|
||||
"gains_expected_at_M_plus_1": {
|
||||
"M_plus_1": m_next,
|
||||
"newly_eligible_count": gains_next,
|
||||
"eligible_count_at_M": len(covered),
|
||||
"eligible_count_at_M_plus_1": len(covered) + gains_next,
|
||||
},
|
||||
"cumulative_gains_expected": {
|
||||
"max_required_m_stable": max_required,
|
||||
"rows": cum_rows,
|
||||
},
|
||||
"buckets_by_required_m_stable": {str(k): v for k, v in sorted(buckets.items())},
|
||||
"rows": non_eligible_sorted,
|
||||
},
|
||||
}
|
||||
|
||||
out_json = output_dir / f"register_K_mod2p{palier}.json"
|
||||
out_md = output_dir / f"register_K_mod2p{palier}.md"
|
||||
audit_json = output_dir / f"audit_register_K_mod2p{palier}.json"
|
||||
audit_md = output_dir / f"audit_register_K_mod2p{palier}.md"
|
||||
non_eligible_json = output_dir / f"non_eligible_clauses_mod2p{palier}.json"
|
||||
non_eligible_md = output_dir / f"non_eligible_clauses_mod2p{palier}.md"
|
||||
manifest_json = output_dir / f"manifest_register_K_mod2p{palier}.json"
|
||||
manifest_md = output_dir / f"manifest_register_K_mod2p{palier}.md"
|
||||
|
||||
_write_json(out_json, register_obj)
|
||||
_write_json(audit_json, audit_obj)
|
||||
_write_json(non_eligible_json, non_eligible_obj)
|
||||
|
||||
md: list[str] = []
|
||||
md.append("**Auteur** : Équipe 4NK")
|
||||
md.append("")
|
||||
md.append(f"# Registre modulaire — K_{palier} (palier 2^{palier})")
|
||||
md.append("")
|
||||
md.append("## Entrées")
|
||||
md.append("")
|
||||
md.append(f"- clauses : `{register_obj['inputs']['clauses_universelles_json']}`")
|
||||
md.append(f"- C3 vérification : `{register_obj['inputs']['verification_c3_local_descent_json']}`")
|
||||
md.append("")
|
||||
md.append("## Paramètres")
|
||||
md.append("")
|
||||
md.append(f"- M : {palier}")
|
||||
md.append(f"- generated_at : {generated_at}")
|
||||
md.append(f"- N* (max seuils) : {n_star}")
|
||||
md.append(f"- clauses retenues (m(c) <= M) : {len(eligible)}")
|
||||
md.append("")
|
||||
md.append("## Empreintes sha256")
|
||||
md.append("")
|
||||
for k in sorted(sha.keys()):
|
||||
md.append(f"- `{k}` : `{sha[k]}`")
|
||||
md.append("")
|
||||
md.append("## Table (extrait)")
|
||||
md.append("")
|
||||
header = ["kind", "m", "residue", "threshold", "k/t", "A", "source_n"]
|
||||
md.append("| " + " | ".join(header) + " |")
|
||||
md.append("| " + " | ".join(["---"] * len(header)) + " |")
|
||||
for c in eligible[:40]:
|
||||
md.append(f"| {c.kind} | {c.modulus_power} | {c.residue_mod_2p} | {c.threshold} | {c.k_or_t or ''} | {c.A or ''} | {c.source_n} |")
|
||||
if len(eligible) > 40:
|
||||
md.append("| ... | ... | ... | ... | ... | ... | ... |")
|
||||
_write_md(out_md, md)
|
||||
|
||||
amd: list[str] = []
|
||||
amd.append("**Auteur** : Équipe 4NK")
|
||||
amd.append("")
|
||||
amd.append(f"# Audit — couverture modulaire de K_{palier} sur le domaine L (C3)")
|
||||
amd.append("")
|
||||
amd.append("## Domaine")
|
||||
amd.append("")
|
||||
amd.append(f"- palier : 2^{palier}")
|
||||
amd.append(f"- |L| : {len(L_sorted)}")
|
||||
amd.append(f"- generated_at : {generated_at}")
|
||||
amd.append("")
|
||||
amd.append("## Registre")
|
||||
amd.append("")
|
||||
amd.append(f"- clauses : {len(eligible)} (m(c) <= {palier})")
|
||||
amd.append(f"- N* : {n_star}")
|
||||
amd.append("")
|
||||
amd.append("## Couverture sur L")
|
||||
amd.append("")
|
||||
amd.append(f"- covered : {len(covered)}")
|
||||
amd.append(f"- uncovered : {len(uncovered)}")
|
||||
amd.append(f"- ok_full_coverage_on_L : {len(uncovered) == 0}")
|
||||
amd.append("")
|
||||
if uncovered:
|
||||
amd.append("### Uncovered (extrait)")
|
||||
amd.append("")
|
||||
for u in uncovered_diagnostics[:40]:
|
||||
amd.append(f"- n={u['n']} kind={u['kind']} required_m_stable={u['required_m_stable']}")
|
||||
if len(uncovered_diagnostics) > 40:
|
||||
amd.append("- ...")
|
||||
amd.append("")
|
||||
amd.append("### Interprétation (indexée)")
|
||||
amd.append("")
|
||||
amd.append(f"- Pour les `F` avec required_m_stable > {palier}, la clause candidate exige un module > 2^{palier} et n’est donc pas décidable au niveau des classes modulo 2^{palier}.")
|
||||
amd.append("")
|
||||
amd.append("## Planification — gains cumulés à horizon fixe")
|
||||
amd.append("")
|
||||
amd.append(f"Vue cumulée à horizon (M+k) avec k <= {horizon_k} (sur les témoins non éligibles, groupés par `required_m_stable`).")
|
||||
amd.append("")
|
||||
amd.append("| cible | k | newly | cumulative | eligible@cible | eligible@cible / |L| |")
|
||||
amd.append("| --- | --- | --- | --- | --- | --- |")
|
||||
if cum_rows:
|
||||
fixed = [row for row in cum_rows if int(row["k"]) <= horizon_k]
|
||||
for row in fixed:
|
||||
eligible_at_target = int(row["eligible_count_at_target"])
|
||||
pct = (eligible_at_target / len(L_sorted) * 100.0) if L_sorted else 0.0
|
||||
amd.append(
|
||||
f"| {row['target_M']} | {row['k']} | {row['newly_eligible_at_target']} | "
|
||||
f"{row['cumulative_newly_eligible_up_to_target']} | {row['eligible_count_at_target']} | {pct:.2f}% |"
|
||||
)
|
||||
if len(fixed) < horizon_k:
|
||||
amd.append("| ... | ... | ... | ... | ... | ... |")
|
||||
amd.append("")
|
||||
last_fixed = fixed[-1]
|
||||
eligible_m_plus_5 = int(last_fixed["eligible_count_at_target"])
|
||||
pct_m_plus_5 = (eligible_m_plus_5 / len(L_sorted) * 100.0) if L_sorted else 0.0
|
||||
amd.append("Vue parallèle (comparaison inter-paliers).")
|
||||
amd.append("")
|
||||
amd.append(f"- eligible@M : {len(covered)}/{len(L_sorted)} ({(len(covered)/len(L_sorted)*100.0) if L_sorted else 0.0:.2f}%)")
|
||||
amd.append(f"- eligible@M+{horizon_k} : {eligible_m_plus_5}/{len(L_sorted)} ({pct_m_plus_5:.2f}%)")
|
||||
amd.append("")
|
||||
else:
|
||||
pct = (len(covered) / len(L_sorted) * 100.0) if L_sorted else 0.0
|
||||
amd.append(f"| {palier+1} | 1 | 0 | 0 | {len(covered)} | {pct:.2f}% |")
|
||||
amd.append("")
|
||||
_write_md(audit_md, amd)
|
||||
|
||||
nmd: list[str] = []
|
||||
nmd.append("**Auteur** : Équipe 4NK")
|
||||
nmd.append("")
|
||||
nmd.append(f"# Table — clauses non éligibles à 2^{palier} (triées par required_m_stable)")
|
||||
nmd.append("")
|
||||
nmd.append("## Critère")
|
||||
nmd.append("")
|
||||
nmd.append(f"- palier M : {palier}")
|
||||
nmd.append("- non-éligible : `required_m_stable > M` (au sens m_stable=max(m_dom, A+1))")
|
||||
nmd.append("")
|
||||
nmd.append("## Buckets")
|
||||
nmd.append("")
|
||||
for k, v in sorted(buckets.items()):
|
||||
nmd.append(f"- required_m_stable={k} : {v}")
|
||||
nmd.append("")
|
||||
nmd.append("## Gains attendus au palier suivant")
|
||||
nmd.append("")
|
||||
nmd.append(f"- M+1 : {m_next}")
|
||||
nmd.append(f"- newly_eligible_count : {gains_next}")
|
||||
nmd.append(f"- eligible_count_at_M : {len(covered)}")
|
||||
nmd.append(f"- eligible_count_at_M_plus_1 : {len(covered) + gains_next}")
|
||||
nmd.append(f"- eligible_count_at_M / |L| : {((len(covered) / len(L_sorted) * 100.0) if L_sorted else 0.0):.2f}%")
|
||||
nmd.append(
|
||||
f"- eligible_count_at_M_plus_1 / |L| : {(((len(covered) + gains_next) / len(L_sorted) * 100.0) if L_sorted else 0.0):.2f}%"
|
||||
)
|
||||
nmd.append("")
|
||||
nmd.append("## Gains cumulés attendus (horizon fixe)")
|
||||
nmd.append("")
|
||||
if cum_rows:
|
||||
fixed_rows = [row for row in cum_rows if int(row["k"]) <= horizon_k]
|
||||
nmd.append("| cible | k | newly | cumulative | eligible@cible | eligible@cible / |L| |")
|
||||
nmd.append("| --- | --- | --- | --- | --- | --- |")
|
||||
for row in fixed_rows:
|
||||
eligible_at_target = int(row["eligible_count_at_target"])
|
||||
pct = (eligible_at_target / len(L_sorted) * 100.0) if L_sorted else 0.0
|
||||
nmd.append(
|
||||
f"| {row['target_M']} | {row['k']} | {row['newly_eligible_at_target']} | "
|
||||
f"{row['cumulative_newly_eligible_up_to_target']} | {row['eligible_count_at_target']} | {pct:.2f}% |"
|
||||
)
|
||||
if len(fixed_rows) < horizon_k:
|
||||
nmd.append("| ... | ... | ... | ... | ... | ... |")
|
||||
nmd.append("")
|
||||
|
||||
nmd.append("## Gains cumulés attendus (planification complète)")
|
||||
nmd.append("")
|
||||
if cum_rows:
|
||||
nmd.append("| cible | k | newly | cumulative | eligible@cible | eligible@cible / |L| |")
|
||||
nmd.append("| --- | --- | --- | --- | --- | --- |")
|
||||
for row in cum_rows[:12]:
|
||||
eligible_at_target = int(row["eligible_count_at_target"])
|
||||
pct = (eligible_at_target / len(L_sorted) * 100.0) if L_sorted else 0.0
|
||||
nmd.append(
|
||||
f"| {row['target_M']} | {row['k']} | {row['newly_eligible_at_target']} | "
|
||||
f"{row['cumulative_newly_eligible_up_to_target']} | {row['eligible_count_at_target']} | {pct:.2f}% |"
|
||||
)
|
||||
if len(cum_rows) > 12:
|
||||
last = cum_rows[-1]
|
||||
eligible_last = int(last["eligible_count_at_target"])
|
||||
pct_last = (eligible_last / len(L_sorted) * 100.0) if L_sorted else 0.0
|
||||
nmd.append("| ... | ... | ... | ... | ... | ... |")
|
||||
nmd.append(
|
||||
f"| {last['target_M']} | {last['k']} | {last['newly_eligible_at_target']} | "
|
||||
f"{last['cumulative_newly_eligible_up_to_target']} | {last['eligible_count_at_target']} | {pct_last:.2f}% |"
|
||||
)
|
||||
nmd.append("")
|
||||
nmd.append("## Table (extrait)")
|
||||
nmd.append("")
|
||||
header2 = ["n", "kind", "required_m_stable", "delta_to_next"]
|
||||
nmd.append("| " + " | ".join(header2) + " |")
|
||||
nmd.append("| " + " | ".join(["---"] * len(header2)) + " |")
|
||||
for row in non_eligible_sorted[:60]:
|
||||
nmd.append(f"| {row['n']} | {row['kind']} | {row['required_m_stable']} | {row['delta_to_next']} |")
|
||||
if len(non_eligible_sorted) > 60:
|
||||
nmd.append("| ... | ... | ... | ... |")
|
||||
_write_md(non_eligible_md, nmd)
|
||||
|
||||
outputs = [
|
||||
out_json,
|
||||
out_md,
|
||||
audit_json,
|
||||
audit_md,
|
||||
non_eligible_json,
|
||||
non_eligible_md,
|
||||
]
|
||||
outputs_sha = { _display_path(p, repo_root): _sha256_file(p) for p in outputs }
|
||||
outputs_size = { _display_path(p, repo_root): _file_size_bytes(p) for p in outputs }
|
||||
outputs_mtime = {
|
||||
_display_path(p, repo_root): {
|
||||
"mtime_epoch_seconds": _file_mtime_epoch_seconds(p),
|
||||
"mtime_utc_iso": _file_mtime_utc_iso(p),
|
||||
}
|
||||
for p in outputs
|
||||
}
|
||||
inputs_size = {
|
||||
_display_path(clauses_json, repo_root): _file_size_bytes(clauses_json),
|
||||
_display_path(c3_verification_json, repo_root): _file_size_bytes(c3_verification_json),
|
||||
}
|
||||
inputs_mtime = {
|
||||
_display_path(clauses_json, repo_root): {
|
||||
"mtime_epoch_seconds": _file_mtime_epoch_seconds(clauses_json),
|
||||
"mtime_utc_iso": _file_mtime_utc_iso(clauses_json),
|
||||
},
|
||||
_display_path(c3_verification_json, repo_root): {
|
||||
"mtime_epoch_seconds": _file_mtime_epoch_seconds(c3_verification_json),
|
||||
"mtime_utc_iso": _file_mtime_utc_iso(c3_verification_json),
|
||||
},
|
||||
}
|
||||
manifest_obj: dict[str, object] = {
|
||||
"domain": {
|
||||
"palier": palier,
|
||||
},
|
||||
"generation": {
|
||||
"horizon_k": horizon_k,
|
||||
"generated_at": generated_at,
|
||||
},
|
||||
"inputs": {
|
||||
"clauses_universelles_json": _display_path(clauses_json, repo_root),
|
||||
"verification_c3_local_descent_json": _display_path(c3_verification_json, repo_root),
|
||||
},
|
||||
"sha256": {"inputs": sha, "outputs": outputs_sha},
|
||||
"sizes_bytes": {"inputs": inputs_size, "outputs": outputs_size},
|
||||
"mtimes": {"inputs": inputs_mtime, "outputs": outputs_mtime},
|
||||
}
|
||||
_write_json(manifest_json, manifest_obj)
|
||||
|
||||
mmd: list[str] = []
|
||||
mmd.append("**Auteur** : Équipe 4NK")
|
||||
mmd.append("")
|
||||
mmd.append(f"# Manifest — register_K_mod2p{palier}")
|
||||
mmd.append("")
|
||||
mmd.append("## Generation")
|
||||
mmd.append("")
|
||||
mmd.append(f"- palier : 2^{palier}")
|
||||
mmd.append(f"- horizon_k : {horizon_k}")
|
||||
mmd.append(f"- generated_at : {generated_at}")
|
||||
mmd.append("")
|
||||
mmd.append("## Inputs (sha256)")
|
||||
mmd.append("")
|
||||
for k in sorted(sha.keys()):
|
||||
mmd.append(f"- `{k}` : `{sha[k]}`")
|
||||
mmd.append("")
|
||||
mmd.append("## Inputs (size bytes)")
|
||||
mmd.append("")
|
||||
for k in sorted(inputs_size.keys()):
|
||||
mmd.append(f"- `{k}` : {inputs_size[k]}")
|
||||
mmd.append("")
|
||||
mmd.append("## Inputs (mtime)")
|
||||
mmd.append("")
|
||||
for k in sorted(inputs_mtime.keys()):
|
||||
v = inputs_mtime[k]
|
||||
mmd.append(f"- `{k}` : {v['mtime_utc_iso']} ({v['mtime_epoch_seconds']})")
|
||||
mmd.append("")
|
||||
mmd.append("## Outputs (sha256)")
|
||||
mmd.append("")
|
||||
for k in sorted(outputs_sha.keys()):
|
||||
mmd.append(f"- `{k}` : `{outputs_sha[k]}`")
|
||||
mmd.append("")
|
||||
mmd.append("## Outputs (size bytes)")
|
||||
mmd.append("")
|
||||
for k in sorted(outputs_size.keys()):
|
||||
mmd.append(f"- `{k}` : {outputs_size[k]}")
|
||||
mmd.append("")
|
||||
mmd.append("## Outputs (mtime)")
|
||||
mmd.append("")
|
||||
for k in sorted(outputs_mtime.keys()):
|
||||
v = outputs_mtime[k]
|
||||
mmd.append(f"- `{k}` : {v['mtime_utc_iso']} ({v['mtime_epoch_seconds']})")
|
||||
mmd.append("")
|
||||
_write_md(manifest_md, mmd)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ap = argparse.ArgumentParser(description="Build a modular register K_M and a finite coverage audit from Option A artefacts")
|
||||
ap.add_argument("--palier", type=int, required=True, help="Target palier M (power of 2 exponent)")
|
||||
ap.add_argument("--horizon-k", type=int, default=5, help="Fixed horizon for the cumulative planning view in audit markdown (default 5)")
|
||||
ap.add_argument(
|
||||
"--check-manual-edits",
|
||||
action="store_true",
|
||||
help="Verify outputs match the last manifest (mtime + size) and exit without regenerating",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--check-sha256",
|
||||
action="store_true",
|
||||
help="Verify sha256 of outputs vs the manifest and exit without regenerating",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--check-inputs-sha256",
|
||||
action="store_true",
|
||||
help="Verify sha256 of inputs vs the manifest and exit without regenerating",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--check-all",
|
||||
action="store_true",
|
||||
help="Run all checks (outputs mtime+size, outputs sha256, inputs sha256) and exit without regenerating",
|
||||
)
|
||||
ap.add_argument("--clauses-json", default="", help="Path to clauses_universelles.json (defaults to the standard palier location)")
|
||||
ap.add_argument("--c3-verification-json", default="", help="Override path to C3 verification JSON (defaults to clauses inputs)")
|
||||
ap.add_argument("--output-dir", default="", help="Output directory (defaults to docs/artefacts/collatz/register_K/palier2pM)")
|
||||
ap.add_argument("--repo-root", default="", help="Repository root for relative paths and defaults (defaults to cwd)")
|
||||
args = ap.parse_args()
|
||||
|
||||
repo_root = Path(args.repo_root).resolve() if args.repo_root.strip() else Path.cwd().resolve()
|
||||
palier = int(args.palier)
|
||||
|
||||
clauses_json = Path(args.clauses_json).resolve() if args.clauses_json.strip() else _infer_default_clauses_json(repo_root=repo_root, palier=palier)
|
||||
clauses_obj = _read_json(clauses_json)
|
||||
if not isinstance(clauses_obj, dict):
|
||||
raise ValueError("Invalid clauses JSON: expected object")
|
||||
c3_json = (
|
||||
Path(args.c3_verification_json).resolve()
|
||||
if args.c3_verification_json.strip()
|
||||
else _load_c3_verification_path_from_clauses(clauses_obj=clauses_obj, repo_root=repo_root)
|
||||
)
|
||||
output_dir = Path(args.output_dir).resolve() if args.output_dir.strip() else _infer_default_output_dir(repo_root=repo_root, palier=palier)
|
||||
|
||||
check_manual = args.check_manual_edits or args.check_all
|
||||
check_sha = args.check_sha256 or args.check_all
|
||||
check_inputs_sha = args.check_inputs_sha256 or args.check_all
|
||||
|
||||
if check_manual or check_sha or check_inputs_sha:
|
||||
manifest_json = output_dir / f"manifest_register_K_mod2p{palier}.json"
|
||||
try:
|
||||
if check_manual:
|
||||
_check_manual_edits_from_manifest(manifest_json=manifest_json, repo_root=repo_root)
|
||||
if check_sha:
|
||||
_check_sha256_from_manifest(manifest_json=manifest_json, repo_root=repo_root)
|
||||
if check_inputs_sha:
|
||||
_check_inputs_sha256_from_manifest(manifest_json=manifest_json, repo_root=repo_root)
|
||||
except CheckMismatchError as e:
|
||||
print(f"MISMATCH {str(e)}", file=sys.stderr)
|
||||
raise SystemExit(2) from e
|
||||
checks: list[str] = []
|
||||
if check_manual:
|
||||
checks.append("manual-edits")
|
||||
if check_sha:
|
||||
checks.append("sha256-outputs")
|
||||
if check_inputs_sha:
|
||||
checks.append("sha256-inputs")
|
||||
checks_str = ",".join(checks) if checks else "(none)"
|
||||
print(f"OK checks={checks_str} palier=2^{palier} manifest={manifest_json}")
|
||||
return
|
||||
|
||||
run(
|
||||
palier=palier,
|
||||
horizon_k=int(args.horizon_k),
|
||||
clauses_json=clauses_json,
|
||||
c3_verification_json=c3_json,
|
||||
output_dir=output_dir,
|
||||
repo_root=repo_root,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@ -0,0 +1,620 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
collatz_compare_dminor_families_incremental.py
|
||||
|
||||
Build an automated, deterministic comparison table for incremental addition of D_minor families (grouped by k)
|
||||
to the multilevel refinement closure over S_M.
|
||||
|
||||
Per step, the script:
|
||||
- runs collatz_build_refinement_certificate_over_Sm_multilevel.py into a dedicated output directory,
|
||||
- runs collatz_analyze_open_roots_refinement.py on the produced certificate (to extract lb quantiles),
|
||||
- extracts metrics and computes deltas.
|
||||
|
||||
Selection strategy (aligned with "dette d’observabilité"):
|
||||
- greedy: at each step, pick the k-family that best improves the "late extremes" objective
|
||||
(by default: global lb_any max, then lb_any p99, then open_roots, then q_root, then parents_one_child_root).
|
||||
- optional "target extremes" mode: track the baseline top-N open roots by lb_any, and score improvements
|
||||
on this tracked subset first (tracked lb_any max/p99, then tracked open count, then global metrics).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
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 _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 _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 _req_float(d: dict[str, object], key: str) -> float:
|
||||
v = d.get(key)
|
||||
if not isinstance(v, (int, float)):
|
||||
raise ValueError(f"Expected float for {key}")
|
||||
return float(v)
|
||||
|
||||
|
||||
def _run(cmd: list[str]) -> None:
|
||||
subprocess.run(cmd, check=True)
|
||||
|
||||
|
||||
_DMINOR_RE = re.compile(r"clauses_D_minor_over_Sm_mod2p(?P<m>\d+)_k(?P<k>\d+)_u(?P<u>\d+)\.json$")
|
||||
|
||||
|
||||
def _discover_dminor_families(*, repo_root: Path, root_palier: int, max_palier: int) -> dict[int, list[Path]]:
|
||||
base = repo_root / "docs" / "artefacts" / "collatz" / "minorated_clauses_over_Sm"
|
||||
families: dict[int, list[Path]] = {}
|
||||
for m in range(root_palier, max_palier + 1):
|
||||
d = base / f"palier2p{m}"
|
||||
if not d.exists():
|
||||
continue
|
||||
for p in sorted(d.glob("clauses_D_minor_over_Sm_mod2p*_k*_u*.json")):
|
||||
m2 = _DMINOR_RE.search(p.name)
|
||||
if m2 is None:
|
||||
continue
|
||||
k = int(m2.group("k"))
|
||||
families.setdefault(k, []).append(p)
|
||||
return {k: v for k, v in sorted(families.items())}
|
||||
|
||||
|
||||
def _default_terminal_leafs(*, repo_root: Path, root_palier: int, max_palier: int) -> list[Path]:
|
||||
out: list[Path] = []
|
||||
for m in range(root_palier, max_palier + 1):
|
||||
out.append(
|
||||
repo_root
|
||||
/ "docs"
|
||||
/ "artefacts"
|
||||
/ "collatz"
|
||||
/ "terminal_clauses_over_Sm"
|
||||
/ f"palier2p{m}"
|
||||
/ f"clauses_terminal_over_Sm_mod2p{m}.json"
|
||||
)
|
||||
return out
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class StepMetrics:
|
||||
step_id: str
|
||||
added_k: int | None
|
||||
open_roots: int
|
||||
q_root: float
|
||||
parents_one_child_root: int
|
||||
lb_any_p99: int
|
||||
lb_any_max: int
|
||||
tracked: dict[str, int] | None
|
||||
|
||||
def to_json(self) -> dict[str, object]:
|
||||
out: dict[str, object] = {
|
||||
"step_id": self.step_id,
|
||||
"added_k": self.added_k,
|
||||
"open_roots": self.open_roots,
|
||||
"q_root": self.q_root,
|
||||
"parents_one_child_root": self.parents_one_child_root,
|
||||
"lb_any": {"p99": self.lb_any_p99, "max": self.lb_any_max},
|
||||
}
|
||||
if self.tracked is not None:
|
||||
out["tracked"] = self.tracked
|
||||
return out
|
||||
|
||||
|
||||
def _extract_step_metrics(
|
||||
*,
|
||||
root_palier: int,
|
||||
cert_json: Path,
|
||||
obstruction_json: Path,
|
||||
step_id: str,
|
||||
added_k: int | None,
|
||||
tracked_roots: set[int] | None,
|
||||
) -> StepMetrics:
|
||||
cert = _read_json(cert_json)
|
||||
if not isinstance(cert, dict):
|
||||
raise ValueError("Invalid certificate JSON")
|
||||
closure = cert.get("closure")
|
||||
if not isinstance(closure, dict):
|
||||
raise ValueError("Invalid certificate JSON: missing closure")
|
||||
residue_audit = cert.get("residue_audit")
|
||||
if not isinstance(residue_audit, dict):
|
||||
raise ValueError("Invalid certificate JSON: missing residue_audit")
|
||||
open_roots = _req_int(closure, "open_roots")
|
||||
q_by = residue_audit.get("q_by_palier")
|
||||
p1c_by = residue_audit.get("parents_one_child_by_palier")
|
||||
if not isinstance(q_by, dict) or not isinstance(p1c_by, dict):
|
||||
raise ValueError("Invalid residue_audit structure")
|
||||
q_root = float(q_by.get(str(root_palier), 0.0))
|
||||
parents_one_child_root = int(p1c_by.get(str(root_palier), 0))
|
||||
|
||||
obs = _read_json(obstruction_json)
|
||||
if not isinstance(obs, dict):
|
||||
raise ValueError("Invalid obstruction JSON")
|
||||
quantiles = obs.get("quantiles")
|
||||
if not isinstance(quantiles, dict):
|
||||
raise ValueError("Invalid obstruction JSON: missing quantiles")
|
||||
q_any = quantiles.get("lb_any")
|
||||
if not isinstance(q_any, dict):
|
||||
raise ValueError("Invalid obstruction JSON: missing quantiles.lb_any")
|
||||
lb_any_p99 = _req_int(q_any, "p99")
|
||||
lb_any_max = _req_int(q_any, "max")
|
||||
|
||||
tracked: dict[str, int] | None = None
|
||||
if tracked_roots is not None:
|
||||
rows = obs.get("rows")
|
||||
if not isinstance(rows, list) or not all(isinstance(x, dict) for x in rows):
|
||||
raise ValueError("Invalid obstruction JSON: missing rows")
|
||||
tracked_any_values: list[int] = []
|
||||
tracked_still_open = 0
|
||||
for row in rows:
|
||||
r0 = row.get("root_residue_mod_2p")
|
||||
if not isinstance(r0, int) or r0 not in tracked_roots:
|
||||
continue
|
||||
lb = row.get("lower_bound_required_m_to_close_root")
|
||||
if not isinstance(lb, dict):
|
||||
continue
|
||||
lb_any = lb.get("any")
|
||||
if not isinstance(lb_any, int):
|
||||
continue
|
||||
tracked_any_values.append(lb_any)
|
||||
tracked_still_open += 1
|
||||
if tracked_any_values:
|
||||
s = sorted(tracked_any_values)
|
||||
idx = int((len(s) - 1) * 0.99)
|
||||
tracked = {
|
||||
"tracked_top_n": len(tracked_roots),
|
||||
"tracked_still_open": tracked_still_open,
|
||||
"tracked_closed": len(tracked_roots) - tracked_still_open,
|
||||
"tracked_lb_any_p99": int(s[idx]),
|
||||
"tracked_lb_any_max": int(s[-1]),
|
||||
}
|
||||
else:
|
||||
tracked = {
|
||||
"tracked_top_n": len(tracked_roots),
|
||||
"tracked_still_open": 0,
|
||||
"tracked_closed": len(tracked_roots),
|
||||
"tracked_lb_any_p99": 0,
|
||||
"tracked_lb_any_max": 0,
|
||||
}
|
||||
return StepMetrics(
|
||||
step_id=step_id,
|
||||
added_k=added_k,
|
||||
open_roots=open_roots,
|
||||
q_root=q_root,
|
||||
parents_one_child_root=parents_one_child_root,
|
||||
lb_any_p99=lb_any_p99,
|
||||
lb_any_max=lb_any_max,
|
||||
tracked=tracked,
|
||||
)
|
||||
|
||||
|
||||
def _score_for_extremes(m: StepMetrics) -> tuple[int, int, int, float, int]:
|
||||
return (m.lb_any_max, m.lb_any_p99, m.open_roots, m.q_root, m.parents_one_child_root)
|
||||
|
||||
|
||||
def _score_for_targeted_extremes(m: StepMetrics) -> tuple[int, int, int, int, int, float, int]:
|
||||
if m.tracked is None:
|
||||
return (m.lb_any_max, m.lb_any_p99, m.open_roots, 0, 0, m.q_root, m.parents_one_child_root)
|
||||
return (
|
||||
int(m.tracked["tracked_lb_any_max"]),
|
||||
int(m.tracked["tracked_lb_any_p99"]),
|
||||
int(m.tracked["tracked_still_open"]),
|
||||
m.lb_any_max,
|
||||
m.lb_any_p99,
|
||||
m.q_root,
|
||||
m.parents_one_child_root,
|
||||
)
|
||||
|
||||
|
||||
def _baseline_top_roots_by_lb_any(*, obstruction_json: Path, top_n: int) -> list[int]:
|
||||
obs = _read_json(obstruction_json)
|
||||
if not isinstance(obs, dict):
|
||||
raise ValueError("Invalid obstruction JSON")
|
||||
rows = obs.get("rows")
|
||||
if not isinstance(rows, list) or not all(isinstance(x, dict) for x in rows):
|
||||
raise ValueError("Invalid obstruction JSON: missing rows")
|
||||
entries: list[tuple[int, int]] = []
|
||||
for row in rows:
|
||||
r0 = row.get("root_residue_mod_2p")
|
||||
if not isinstance(r0, int):
|
||||
continue
|
||||
lb = row.get("lower_bound_required_m_to_close_root")
|
||||
if not isinstance(lb, dict):
|
||||
continue
|
||||
lb_any = lb.get("any")
|
||||
if not isinstance(lb_any, int):
|
||||
continue
|
||||
entries.append((lb_any, r0))
|
||||
entries.sort(key=lambda x: (-x[0], x[1]))
|
||||
return [r for _, r in entries[:top_n]]
|
||||
|
||||
|
||||
def _read_tracked_roots_file(path: Path) -> list[int]:
|
||||
if not path.exists():
|
||||
raise ValueError(f"tracked roots file not found: {path}")
|
||||
roots: list[int] = []
|
||||
seen: set[int] = set()
|
||||
for line in path.read_text(encoding="utf-8", errors="strict").splitlines():
|
||||
s = line.strip()
|
||||
if not s or s.startswith("#"):
|
||||
continue
|
||||
if "#" in s:
|
||||
s = s.split("#", 1)[0].strip()
|
||||
if not s:
|
||||
continue
|
||||
try:
|
||||
r = int(s, 10)
|
||||
except ValueError as e:
|
||||
raise ValueError(f"Invalid tracked root value in {path}: {line!r}") from e
|
||||
if r <= 0 or (r % 2) == 0:
|
||||
raise ValueError(f"Invalid tracked root (must be positive odd integer): {r}")
|
||||
if r not in seen:
|
||||
roots.append(r)
|
||||
seen.add(r)
|
||||
return roots
|
||||
|
||||
|
||||
def _write_tracked_roots_file(path: Path, roots: list[int]) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text("\n".join(str(r) for r in roots) + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def run(
|
||||
*,
|
||||
repo_root: Path,
|
||||
root_palier: int,
|
||||
max_palier: int,
|
||||
k_max: int,
|
||||
t_max: int,
|
||||
search_max_required_m: int,
|
||||
out_dir: Path,
|
||||
target_extremes_top_n: int,
|
||||
tracked_roots_file: Path | None,
|
||||
export_tracked_roots_file: Path | None,
|
||||
) -> None:
|
||||
families_by_k = _discover_dminor_families(repo_root=repo_root, root_palier=root_palier, max_palier=max_palier)
|
||||
if not families_by_k:
|
||||
raise ValueError("No D_minor families found. Generate them under docs/artefacts/.../minorated_clauses_over_Sm/ first.")
|
||||
|
||||
terminal_leafs = _default_terminal_leafs(repo_root=repo_root, root_palier=root_palier, max_palier=max_palier)
|
||||
multilevel_script = repo_root / "applications" / "collatz" / "collatz_k_scripts" / "collatz_build_refinement_certificate_over_Sm_multilevel.py"
|
||||
obstruction_script = repo_root / "applications" / "collatz" / "collatz_k_scripts" / "collatz_analyze_open_roots_refinement.py"
|
||||
|
||||
steps: list[StepMetrics] = []
|
||||
selected_ks: list[int] = []
|
||||
remaining_ks = list(families_by_k.keys())
|
||||
tracked_roots: set[int] | None = None
|
||||
tracked_roots_source: dict[str, object] | None = None
|
||||
tracked_list: list[int] = []
|
||||
|
||||
def evaluate_step(*, step_id: str, added_k: int | None, ks: list[int]) -> StepMetrics:
|
||||
step_dir = out_dir / step_id
|
||||
leaf_args: list[str] = []
|
||||
for p in terminal_leafs:
|
||||
leaf_args.extend(["--leaf-json", str(p)])
|
||||
for k in ks:
|
||||
for p in families_by_k[k]:
|
||||
leaf_args.extend(["--leaf-json", str(p)])
|
||||
|
||||
_run(
|
||||
[
|
||||
"python3",
|
||||
str(multilevel_script),
|
||||
"--repo-root",
|
||||
str(repo_root),
|
||||
"--root-palier",
|
||||
str(root_palier),
|
||||
"--max-palier",
|
||||
str(max_palier),
|
||||
"--output-dir",
|
||||
str(step_dir),
|
||||
*leaf_args,
|
||||
]
|
||||
)
|
||||
|
||||
cert_json = step_dir / f"refinement_certificate_Sm_multilevel_mod2p{root_palier}_to2p{max_palier}.json"
|
||||
_run(
|
||||
[
|
||||
"python3",
|
||||
str(obstruction_script),
|
||||
"--root-palier",
|
||||
str(root_palier),
|
||||
"--max-palier",
|
||||
str(max_palier),
|
||||
"--multilevel-json",
|
||||
str(cert_json),
|
||||
"--output-dir",
|
||||
str(step_dir),
|
||||
"--k-max",
|
||||
str(k_max),
|
||||
"--t-max",
|
||||
str(t_max),
|
||||
"--search-max-required-m",
|
||||
str(search_max_required_m),
|
||||
]
|
||||
)
|
||||
obstruction_json = step_dir / f"open_roots_obstruction_profile_mod2p{root_palier}_to2p{max_palier}.json"
|
||||
return _extract_step_metrics(
|
||||
root_palier=root_palier,
|
||||
cert_json=cert_json,
|
||||
obstruction_json=obstruction_json,
|
||||
step_id=step_id,
|
||||
added_k=added_k,
|
||||
tracked_roots=tracked_roots,
|
||||
)
|
||||
|
||||
baseline = evaluate_step(step_id="step00_baseline_terminal_only", added_k=None, ks=[])
|
||||
steps.append(baseline)
|
||||
if tracked_roots_file is not None and target_extremes_top_n > 0:
|
||||
raise ValueError("Use either --tracked-roots-file or --target-extremes-top-n, not both")
|
||||
if tracked_roots_file is not None:
|
||||
tracked_list = _read_tracked_roots_file(tracked_roots_file)
|
||||
tracked_roots = set(tracked_list)
|
||||
tracked_roots_source = {"kind": "file", "path": str(tracked_roots_file), "count": len(tracked_list)}
|
||||
baseline = evaluate_step(step_id="step00_baseline_terminal_only", added_k=None, ks=[])
|
||||
steps = [baseline]
|
||||
elif target_extremes_top_n > 0:
|
||||
baseline_dir = out_dir / "step00_baseline_terminal_only"
|
||||
baseline_obstruction_json = baseline_dir / f"open_roots_obstruction_profile_mod2p{root_palier}_to2p{max_palier}.json"
|
||||
tracked_list = _baseline_top_roots_by_lb_any(obstruction_json=baseline_obstruction_json, top_n=target_extremes_top_n)
|
||||
tracked_roots = set(tracked_list)
|
||||
tracked_roots_source = {"kind": "baseline_top_n", "top_n": target_extremes_top_n, "count": len(tracked_list)}
|
||||
# Re-evaluate baseline to populate tracked metrics
|
||||
baseline = evaluate_step(step_id="step00_baseline_terminal_only", added_k=None, ks=[])
|
||||
steps = [baseline]
|
||||
|
||||
if export_tracked_roots_file is not None and tracked_list:
|
||||
_write_tracked_roots_file(export_tracked_roots_file, tracked_list)
|
||||
|
||||
while remaining_ks:
|
||||
best_k: int | None = None
|
||||
best_metrics: StepMetrics | None = None
|
||||
best_key: tuple[int, ...] | None = None
|
||||
for k in remaining_ks:
|
||||
ks2 = [*selected_ks, k]
|
||||
step_id = f"step{len(steps):02d}_add_k{k}"
|
||||
m = evaluate_step(step_id=step_id, added_k=k, ks=ks2)
|
||||
key = _score_for_targeted_extremes(m) if tracked_roots is not None else _score_for_extremes(m)
|
||||
if best_key is None or key < best_key:
|
||||
best_key = key
|
||||
best_k = k
|
||||
best_metrics = m
|
||||
if best_k is None or best_metrics is None:
|
||||
raise ValueError("Internal error: greedy selection failed")
|
||||
selected_ks.append(best_k)
|
||||
remaining_ks = [k for k in remaining_ks if k != best_k]
|
||||
steps.append(best_metrics)
|
||||
|
||||
# Build deltas table vs baseline and vs previous step
|
||||
base = steps[0]
|
||||
rows: list[dict[str, object]] = []
|
||||
prev = base
|
||||
for m in steps:
|
||||
row: dict[str, object] = m.to_json()
|
||||
row["delta_vs_baseline"] = {
|
||||
"open_roots": m.open_roots - base.open_roots,
|
||||
"q_root": m.q_root - base.q_root,
|
||||
"parents_one_child_root": m.parents_one_child_root - base.parents_one_child_root,
|
||||
"lb_any_p99": m.lb_any_p99 - base.lb_any_p99,
|
||||
"lb_any_max": m.lb_any_max - base.lb_any_max,
|
||||
}
|
||||
row["delta_vs_prev"] = {
|
||||
"open_roots": m.open_roots - prev.open_roots,
|
||||
"q_root": m.q_root - prev.q_root,
|
||||
"parents_one_child_root": m.parents_one_child_root - prev.parents_one_child_root,
|
||||
"lb_any_p99": m.lb_any_p99 - prev.lb_any_p99,
|
||||
"lb_any_max": m.lb_any_max - prev.lb_any_max,
|
||||
}
|
||||
rows.append(row)
|
||||
prev = m
|
||||
|
||||
out_json = out_dir / f"impact_table_D_minor_incremental_mod2p{root_palier}_to2p{max_palier}.json"
|
||||
out_md = out_dir / f"impact_table_D_minor_incremental_mod2p{root_palier}_to2p{max_palier}.md"
|
||||
obj = {
|
||||
"domain": {"root_palier": root_palier, "max_palier": max_palier},
|
||||
"params": {"k_max": k_max, "t_max": t_max, "search_max_required_m": search_max_required_m},
|
||||
"target_extremes_top_n": target_extremes_top_n,
|
||||
"tracked_roots_source": tracked_roots_source,
|
||||
"tracked_roots_by_baseline_lb_any": sorted(list(tracked_roots)) if tracked_roots is not None else [],
|
||||
"families_by_k": {str(k): [str(p) for p in v] for k, v in families_by_k.items()},
|
||||
"selected_order_by_k": selected_ks,
|
||||
"baseline": base.to_json(),
|
||||
"rows": rows,
|
||||
}
|
||||
_write_json(out_json, obj)
|
||||
|
||||
md: list[str] = []
|
||||
md.append("**Auteur** : Équipe 4NK")
|
||||
md.append("")
|
||||
md.append(f"# Impact incrémental des familles D_minor (par k) — S_{root_palier}→2^{max_palier}")
|
||||
md.append("")
|
||||
md.append("## Stratégie de sélection")
|
||||
md.append("")
|
||||
if tracked_roots is not None:
|
||||
if tracked_roots_file is not None:
|
||||
md.append(f"Mode “ciblage extrêmes” activé (liste fixe via fichier : `{tracked_roots_file}`).")
|
||||
else:
|
||||
md.append(f"Mode “ciblage extrêmes” activé (top-N baseline, N={target_extremes_top_n}).")
|
||||
md.append("Sélection gloutonne, objectif “extrêmes tardifs” (lexicographique) :")
|
||||
md.append("- minimiser `tracked.tracked_lb_any_max`")
|
||||
md.append("- puis minimiser `tracked.tracked_lb_any_p99`")
|
||||
md.append("- puis minimiser `tracked.tracked_still_open`")
|
||||
md.append("- puis minimiser `lb_any.max` (global)")
|
||||
md.append("- puis minimiser `lb_any.p99` (global)")
|
||||
md.append("- puis minimiser `q_root`")
|
||||
md.append("- puis minimiser `parents_one_child_root`")
|
||||
else:
|
||||
md.append("Sélection gloutonne, objectif “extrêmes tardifs” (global, lexicographique) :")
|
||||
md.append("- minimiser `lb_any.max`")
|
||||
md.append("- puis minimiser `lb_any.p99`")
|
||||
md.append("- puis minimiser `open_roots`")
|
||||
md.append("- puis minimiser `q_root`")
|
||||
md.append("- puis minimiser `parents_one_child_root`")
|
||||
md.append("")
|
||||
md.append(f"Ordre sélectionné (k) : {', '.join(str(k) for k in selected_ks)}")
|
||||
md.append("")
|
||||
md.append("## Table (deltas vs baseline)")
|
||||
md.append("")
|
||||
if tracked_roots is not None:
|
||||
md.append("| step | added_k | tracked.open | tracked.max | tracked.p99 | open_roots | Δopen | q_root | Δq | parents_one_child_root | Δparents | lb_any.p99 | Δp99 | lb_any.max | Δmax |")
|
||||
md.append("| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |")
|
||||
else:
|
||||
md.append("| step | added_k | open_roots | Δopen | q_root | Δq | parents_one_child_root | Δparents | lb_any.p99 | Δp99 | lb_any.max | Δmax |")
|
||||
md.append("| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |")
|
||||
for r in rows:
|
||||
m = r
|
||||
dvb = m["delta_vs_baseline"] # type: ignore[index]
|
||||
lb_any = m["lb_any"] # type: ignore[index]
|
||||
if tracked_roots is not None:
|
||||
tr = m.get("tracked") # type: ignore[assignment]
|
||||
tr_open = ""
|
||||
tr_max = ""
|
||||
tr_p99 = ""
|
||||
if isinstance(tr, dict):
|
||||
tr_open = str(tr.get("tracked_still_open", ""))
|
||||
tr_max = str(tr.get("tracked_lb_any_max", ""))
|
||||
tr_p99 = str(tr.get("tracked_lb_any_p99", ""))
|
||||
md.append(
|
||||
"| "
|
||||
+ str(m["step_id"])
|
||||
+ " | "
|
||||
+ ("" if m["added_k"] is None else str(m["added_k"]))
|
||||
+ " | "
|
||||
+ tr_open
|
||||
+ " | "
|
||||
+ tr_max
|
||||
+ " | "
|
||||
+ tr_p99
|
||||
+ " | "
|
||||
+ str(m["open_roots"])
|
||||
+ " | "
|
||||
+ str(dvb["open_roots"])
|
||||
+ " | "
|
||||
+ f"{float(m['q_root']):.12f}"
|
||||
+ " | "
|
||||
+ f"{float(dvb['q_root']):+.12f}"
|
||||
+ " | "
|
||||
+ str(m["parents_one_child_root"])
|
||||
+ " | "
|
||||
+ str(dvb["parents_one_child_root"])
|
||||
+ " | "
|
||||
+ str(lb_any["p99"])
|
||||
+ " | "
|
||||
+ str(dvb["lb_any_p99"])
|
||||
+ " | "
|
||||
+ str(lb_any["max"])
|
||||
+ " | "
|
||||
+ str(dvb["lb_any_max"])
|
||||
+ " |"
|
||||
)
|
||||
else:
|
||||
md.append(
|
||||
"| "
|
||||
+ str(m["step_id"])
|
||||
+ " | "
|
||||
+ ("" if m["added_k"] is None else str(m["added_k"]))
|
||||
+ " | "
|
||||
+ str(m["open_roots"])
|
||||
+ " | "
|
||||
+ str(dvb["open_roots"])
|
||||
+ " | "
|
||||
+ f"{float(m['q_root']):.12f}"
|
||||
+ " | "
|
||||
+ f"{float(dvb['q_root']):+.12f}"
|
||||
+ " | "
|
||||
+ str(m["parents_one_child_root"])
|
||||
+ " | "
|
||||
+ str(dvb["parents_one_child_root"])
|
||||
+ " | "
|
||||
+ str(lb_any["p99"])
|
||||
+ " | "
|
||||
+ str(dvb["lb_any_p99"])
|
||||
+ " | "
|
||||
+ str(lb_any["max"])
|
||||
+ " | "
|
||||
+ str(dvb["lb_any_max"])
|
||||
+ " |"
|
||||
)
|
||||
md.append("")
|
||||
md.append("## Sorties")
|
||||
md.append("")
|
||||
md.append(f"- JSON : `{out_json}`")
|
||||
md.append(f"- Markdown : `{out_md}`")
|
||||
md.append("")
|
||||
_write_md(out_md, md)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ap = argparse.ArgumentParser(description="Incremental impact table for D_minor families (grouped by k)")
|
||||
ap.add_argument("--repo-root", default=".", help="Repository root")
|
||||
ap.add_argument("--root-palier", type=int, default=15)
|
||||
ap.add_argument("--max-palier", type=int, default=18)
|
||||
ap.add_argument("--k-max", type=int, default=256)
|
||||
ap.add_argument("--t-max", type=int, default=256)
|
||||
ap.add_argument("--search-max-required-m", type=int, default=256)
|
||||
ap.add_argument(
|
||||
"--target-extremes-top-n",
|
||||
type=int,
|
||||
default=0,
|
||||
help="If >0, track baseline top-N open roots by lb_any, and score families primarily on this subset",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--tracked-roots-file",
|
||||
default="",
|
||||
help="If set, read a fixed list of roots (one odd integer per line) to track across runs (overrides --target-extremes-top-n)",
|
||||
)
|
||||
ap.add_argument(
|
||||
"--export-tracked-roots-file",
|
||||
default="",
|
||||
help="If set, export the tracked roots list (after resolution) to this file",
|
||||
)
|
||||
ap.add_argument("--out-dir", default="", help="Output directory (defaults under docs/artefacts/...)")
|
||||
args = ap.parse_args()
|
||||
|
||||
repo_root = Path(args.repo_root).resolve()
|
||||
root_palier = int(args.root_palier)
|
||||
max_palier = int(args.max_palier)
|
||||
out_dir = Path(args.out_dir).resolve() if args.out_dir.strip() else (
|
||||
repo_root / "docs" / "artefacts" / "collatz" / "refinement_K" / f"palier2p{root_palier}" / "incremental_D_minor"
|
||||
)
|
||||
|
||||
tracked_roots_file = Path(args.tracked_roots_file).resolve() if args.tracked_roots_file.strip() else None
|
||||
export_tracked_roots_file = (
|
||||
Path(args.export_tracked_roots_file).resolve() if args.export_tracked_roots_file.strip() else None
|
||||
)
|
||||
|
||||
run(
|
||||
repo_root=repo_root,
|
||||
root_palier=root_palier,
|
||||
max_palier=max_palier,
|
||||
k_max=int(args.k_max),
|
||||
t_max=int(args.t_max),
|
||||
search_max_required_m=int(args.search_max_required_m),
|
||||
out_dir=out_dir,
|
||||
target_extremes_top_n=int(args.target_extremes_top_n),
|
||||
tracked_roots_file=tracked_roots_file,
|
||||
export_tracked_roots_file=export_tracked_roots_file,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@ -15,7 +15,8 @@ Outputs (versionable, no transcripts):
|
||||
- docs/artefacts/collatz/universal_clauses/clauses_universelles.md
|
||||
|
||||
Notes:
|
||||
- D_exact and F witnesses are lifted to modulus 2^(A+1) where A is the prefix sum.
|
||||
- D_exact and F witnesses are lifted to modulus 2^m_stable, where
|
||||
m_stable := max(domain_palier, A+1), because the witness is already fixed modulo 2^domain_palier.
|
||||
- D_brother witnesses are preserved as *local* dependencies (mate_exact) at the
|
||||
domain palier; they are not asserted as standalone universal reductions here.
|
||||
"""
|
||||
@ -167,7 +168,7 @@ def run(*, verification_json: Path, output_dir: Path, repo_root: Path) -> None:
|
||||
pref = prefix_data(n, k)
|
||||
if pref.A != A_k or pref.C != C_k:
|
||||
raise ValueError(f"D_exact mismatch for n={n}: prefix_data differs from record")
|
||||
m_stab = A_k + 1
|
||||
m_stab = max(palier, A_k + 1)
|
||||
r_stab = _lift_to_stable_residue(
|
||||
n0=n,
|
||||
base_palier=palier,
|
||||
@ -218,7 +219,7 @@ def run(*, verification_json: Path, output_dir: Path, repo_root: Path) -> None:
|
||||
pref = prefix_data(n, t)
|
||||
if pref.A != A_t or pref.C != C_t or pref.y != y:
|
||||
raise ValueError(f"F mismatch for n={n}: prefix_data differs from record")
|
||||
m_stab = A_t + 1
|
||||
m_stab = max(palier, A_t + 1)
|
||||
r_stab = _lift_to_stable_residue(
|
||||
n0=n,
|
||||
base_palier=palier,
|
||||
@ -354,7 +355,10 @@ def run(*, verification_json: Path, output_dir: Path, repo_root: Path) -> None:
|
||||
lines.append("")
|
||||
lines.append("## Notes")
|
||||
lines.append("")
|
||||
lines.append("- `D_exact` et `F` sont relevées au module minimal \\(2^{A+1}\\) qui fige le mot de valuations du témoin.")
|
||||
lines.append(
|
||||
"- `D_exact` et `F` sont relevées au module \\(2^{m_{stable}}\\) avec "
|
||||
"\\(m_{stable}=\\max(m, A+1)\\), où \\(m\\) est le palier du domaine, afin de figer le mot de valuations du témoin."
|
||||
)
|
||||
lines.append("- `D_brother_local` encode une dépendance locale (palier du domaine) vers un `mate_exact` ; elle n’est pas utilisée ici comme clause universelle autonome.")
|
||||
lines.append("")
|
||||
out_md.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
||||
|
||||
@ -0,0 +1,205 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
collatz_generate_minorated_descent_clauses_over_Sm.py
|
||||
|
||||
Generate deterministic "minorated" descent clauses (D_minor) over the full odd residue space S_m
|
||||
(odd residues modulo 2^m).
|
||||
|
||||
Grammar (aligned with conjoncture_collatz.md, "clauses de descente par minoration"):
|
||||
- Fix an horizon k.
|
||||
- Require that the prefix word of length k-1 is stable at palier 2^m (so A_{k-1}, C_{k-1} are fixed).
|
||||
- Let B_k := 3*C_{k-1} + 2^{A_{k-1}} so that 3*U^{(k-1)}(n)+1 = (3^k n + B_k)/2^{A_{k-1}}.
|
||||
- Replace the exact last valuation by a lower bound: v2(3^k n + B_k) >= underlineA.
|
||||
- Then A(n) >= underlineA implies U^k(n) <= (3^k n + B_k)/2^{underlineA}, and a standard threshold
|
||||
yields a universal strict descent for n >= N0.
|
||||
|
||||
Outputs:
|
||||
- docs/artefacts/collatz/minorated_clauses_over_Sm/palier2p<m>/clauses_D_minor_over_Sm_mod2p<m>.{json,md}
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
from collatz_k_core import prefix_data
|
||||
|
||||
|
||||
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 _sha256_file(path: Path, chunk_size: int = 16 * 1024 * 1024) -> str:
|
||||
h = hashlib.sha256()
|
||||
with path.open("rb") as f:
|
||||
while True:
|
||||
chunk = f.read(chunk_size)
|
||||
if not chunk:
|
||||
break
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def _utc_now_iso() -> str:
|
||||
return datetime.now(tz=timezone.utc).isoformat().replace("+00:00", "Z")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class DMinorClause:
|
||||
modulus_power: int
|
||||
residue_mod_2p: int
|
||||
k: int
|
||||
underlineA: int
|
||||
numerator_B_k: int
|
||||
prefix_word_len_km1: tuple[int, ...] # word of length k-1
|
||||
A_km1: int
|
||||
C_km1: int
|
||||
N0: int
|
||||
delta_min: int
|
||||
|
||||
def to_json(self) -> dict[str, object]:
|
||||
return {
|
||||
"kind": "D_minor",
|
||||
"modulus_power": self.modulus_power,
|
||||
"residue_mod_2p": self.residue_mod_2p,
|
||||
"k": self.k,
|
||||
"underlineA": self.underlineA,
|
||||
"numerator_B_k": self.numerator_B_k,
|
||||
"prefix_word_len_km1": list(self.prefix_word_len_km1),
|
||||
"A_km1": self.A_km1,
|
||||
"C_km1": self.C_km1,
|
||||
"delta_min": self.delta_min,
|
||||
"N0": self.N0,
|
||||
}
|
||||
|
||||
|
||||
def run(*, palier: int, k: int, underlineA: int, output_dir: Path, repo_root: Path) -> None:
|
||||
if palier < 2:
|
||||
raise ValueError("palier must be >= 2")
|
||||
if k < 2:
|
||||
raise ValueError("k must be >= 2 (needs k-1 prefix)")
|
||||
if underlineA < 1:
|
||||
raise ValueError("underlineA must be >= 1")
|
||||
if underlineA > palier:
|
||||
raise ValueError("underlineA must be <= palier (decidable at 2^palier)")
|
||||
|
||||
alpha = 3**k
|
||||
mod = 1 << palier
|
||||
pow2u = 1 << underlineA
|
||||
delta_min = (1 << underlineA) - alpha
|
||||
if delta_min <= 0:
|
||||
raise ValueError("delta_min <= 0: no structural contraction for this (k, underlineA)")
|
||||
|
||||
clauses: list[DMinorClause] = []
|
||||
rejected_prefix_not_stable = 0
|
||||
rejected_divisibility = 0
|
||||
|
||||
for r in range(1, mod, 2):
|
||||
pref = prefix_data(r, k - 1)
|
||||
w_prefix = tuple(int(x) for x in pref.word)
|
||||
A_km1 = int(pref.A)
|
||||
C_km1 = int(pref.C)
|
||||
if A_km1 + 1 > palier:
|
||||
rejected_prefix_not_stable += 1
|
||||
continue
|
||||
numerator_B_k = 3 * C_km1 + (1 << A_km1)
|
||||
|
||||
if ((alpha * r + numerator_B_k) % pow2u) != 0:
|
||||
rejected_divisibility += 1
|
||||
continue
|
||||
|
||||
N0 = (numerator_B_k // delta_min) + 1
|
||||
clauses.append(
|
||||
DMinorClause(
|
||||
modulus_power=palier,
|
||||
residue_mod_2p=r,
|
||||
k=k,
|
||||
underlineA=underlineA,
|
||||
numerator_B_k=numerator_B_k,
|
||||
prefix_word_len_km1=w_prefix,
|
||||
A_km1=A_km1,
|
||||
C_km1=C_km1,
|
||||
N0=N0,
|
||||
delta_min=delta_min,
|
||||
)
|
||||
)
|
||||
|
||||
out_json = output_dir / f"clauses_D_minor_over_Sm_mod2p{palier}_k{k}_u{underlineA}.json"
|
||||
out_md = output_dir / f"clauses_D_minor_over_Sm_mod2p{palier}_k{k}_u{underlineA}.md"
|
||||
|
||||
generated_at = _utc_now_iso()
|
||||
core_path = repo_root / "applications" / "collatz" / "collatz_k_scripts" / "collatz_k_core.py"
|
||||
sha_inputs = {}
|
||||
if core_path.exists():
|
||||
sha_inputs[str(core_path.relative_to(repo_root))] = _sha256_file(core_path)
|
||||
|
||||
obj: dict[str, object] = {
|
||||
"domain": {"palier": palier, "S_M_size": (1 << (palier - 1))},
|
||||
"params": {"k": k, "underlineA": underlineA},
|
||||
"generated_at": generated_at,
|
||||
"sha256": {"inputs": sha_inputs},
|
||||
"counts": {
|
||||
"clauses": len(clauses),
|
||||
"rejected_prefix_not_stable": rejected_prefix_not_stable,
|
||||
"rejected_divisibility": rejected_divisibility,
|
||||
},
|
||||
"clauses": [c.to_json() for c in clauses],
|
||||
}
|
||||
_write_json(out_json, obj)
|
||||
|
||||
md: list[str] = []
|
||||
md.append("**Auteur** : Équipe 4NK")
|
||||
md.append("")
|
||||
md.append(f"# Clauses D minorées sur S_M — palier 2^{palier}")
|
||||
md.append("")
|
||||
md.append("## Paramètres")
|
||||
md.append("")
|
||||
md.append(f"- k : {k}")
|
||||
md.append(f"- underlineA : {underlineA}")
|
||||
md.append(f"- delta_min = 2^underlineA - 3^k : {delta_min}")
|
||||
md.append("")
|
||||
md.append("## Compteurs")
|
||||
md.append("")
|
||||
md.append(f"- clauses : {len(clauses)}")
|
||||
md.append(f"- rejected_prefix_not_stable : {rejected_prefix_not_stable}")
|
||||
md.append(f"- rejected_divisibility : {rejected_divisibility}")
|
||||
md.append("")
|
||||
md.append("## Sorties")
|
||||
md.append("")
|
||||
md.append(f"- JSON : `{out_json}`")
|
||||
md.append(f"- Markdown : `{out_md}`")
|
||||
md.append("")
|
||||
_write_md(out_md, md)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ap = argparse.ArgumentParser(description="Generate minorated descent clauses over S_M (odd residues modulo 2^M)")
|
||||
ap.add_argument("--repo-root", default=".", help="Repository root")
|
||||
ap.add_argument("--palier", type=int, default=15)
|
||||
ap.add_argument("--k", type=int, default=8)
|
||||
ap.add_argument("--underlineA", type=int, default=13)
|
||||
ap.add_argument("--output-dir", default="", help="Output directory (defaults under docs/artefacts/...)")
|
||||
args = ap.parse_args()
|
||||
|
||||
repo_root = Path(args.repo_root).resolve()
|
||||
palier = int(args.palier)
|
||||
output_dir = Path(args.output_dir).resolve() if args.output_dir.strip() else (
|
||||
repo_root / "docs" / "artefacts" / "collatz" / "minorated_clauses_over_Sm" / f"palier2p{palier}"
|
||||
)
|
||||
run(palier=palier, k=int(args.k), underlineA=int(args.underlineA), output_dir=output_dir, repo_root=repo_root)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@ -61,6 +61,14 @@ def read_text(path: Path) -> str:
|
||||
return path.read_text(encoding="utf-8", errors="strict")
|
||||
|
||||
|
||||
def display_path(path: Path, repo_root: Path) -> str:
|
||||
try:
|
||||
rel = path.resolve().relative_to(repo_root.resolve())
|
||||
return str(rel)
|
||||
except ValueError:
|
||||
return str(path)
|
||||
|
||||
|
||||
def parse_last_extend_run_date(pipeline_extend_log: str) -> str:
|
||||
"""
|
||||
Return YYYY-MM-DD for the last extend run that reached completion.
|
||||
@ -148,10 +156,12 @@ class C2ProjectiveMetrics:
|
||||
class C3LocalDescentMetrics:
|
||||
palier: int
|
||||
lifted_domain_size: int
|
||||
d8_nodes: int
|
||||
d8_exact_nodes: int
|
||||
d8_brother_nodes: int
|
||||
fusion_nodes: int
|
||||
d_nodes: int
|
||||
d_base_cases: int
|
||||
d_descent_witnesses: int
|
||||
f_nodes: int
|
||||
f_base_cases: int
|
||||
f_descent_witnesses: int
|
||||
n_star: int
|
||||
base_checked_up_to: int
|
||||
|
||||
@ -276,10 +286,12 @@ def parse_c3_local_descent_metrics(verification_json: str) -> C3LocalDescentMetr
|
||||
return C3LocalDescentMetrics(
|
||||
palier=req_int(domain, "palier"),
|
||||
lifted_domain_size=req_int(domain, "lifted_domain_size"),
|
||||
d8_nodes=req_int(elim, "d8_nodes"),
|
||||
d8_exact_nodes=req_int(elim, "d8_exact_nodes"),
|
||||
d8_brother_nodes=req_int(elim, "d8_brother_nodes"),
|
||||
fusion_nodes=req_int(elim, "fusion_nodes"),
|
||||
d_nodes=req_int(elim, "d_nodes"),
|
||||
d_base_cases=req_int(elim, "d_base_cases"),
|
||||
d_descent_witnesses=req_int(elim, "d_descent_witnesses"),
|
||||
f_nodes=req_int(elim, "f_nodes"),
|
||||
f_base_cases=req_int(elim, "f_base_cases"),
|
||||
f_descent_witnesses=req_int(elim, "f_descent_witnesses"),
|
||||
n_star=req_int(elim, "N_star"),
|
||||
base_checked_up_to=req_int(base, "checked_up_to"),
|
||||
)
|
||||
@ -450,8 +462,12 @@ def write_c3_local_descent_run_report(
|
||||
lines.append("")
|
||||
lines.append(f"- palier : 2^{metrics.palier}")
|
||||
lines.append(f"- |Lift(B12)| : {metrics.lifted_domain_size}")
|
||||
lines.append(f"- D8 : {metrics.d8_nodes} (exact={metrics.d8_exact_nodes}, brothers={metrics.d8_brother_nodes})")
|
||||
lines.append(f"- Fusion : {metrics.fusion_nodes}")
|
||||
lines.append(
|
||||
f"- D : {metrics.d_nodes} (descente={metrics.d_descent_witnesses}, base_cases={metrics.d_base_cases})"
|
||||
)
|
||||
lines.append(
|
||||
f"- Fusion : {metrics.f_nodes} (descente={metrics.f_descent_witnesses}, base_cases={metrics.f_base_cases})"
|
||||
)
|
||||
lines.append(f"- N* (max seuils N0/Nf calculés) : {metrics.n_star}")
|
||||
lines.append(f"- base validation checked up to : {metrics.base_checked_up_to}")
|
||||
lines.append("")
|
||||
@ -481,7 +497,10 @@ def write_universal_clauses_run_report(
|
||||
lines.append("## Contexte")
|
||||
lines.append("")
|
||||
lines.append("- **But du run** : extraire des clauses universelles candidates (Option A : Lift(B12)) depuis l’artefact C3 local, et vérifier leur cohérence déterministe.")
|
||||
lines.append("- **Assertion vérifiée** : cohérence arithmétique des clauses extraites et cohérence des relèvements au module minimal \\(2^{A+1}\\).")
|
||||
lines.append(
|
||||
"- **Assertion vérifiée** : cohérence arithmétique des clauses extraites et cohérence des relèvements "
|
||||
"au module \\(2^{m_{stable}}\\) avec \\(m_{stable}=\\max(m, A+1)\\)."
|
||||
)
|
||||
lines.append("")
|
||||
lines.append("## Code et reproductibilité")
|
||||
lines.append("")
|
||||
@ -1119,6 +1138,7 @@ def main() -> None:
|
||||
"c3_local_descent",
|
||||
"c3_local_descent_palier",
|
||||
"universal_clauses",
|
||||
"universal_clauses_palier",
|
||||
],
|
||||
help="Report profile",
|
||||
)
|
||||
@ -1503,18 +1523,21 @@ def main() -> None:
|
||||
return
|
||||
|
||||
if args.profile == "universal_clauses":
|
||||
command = (
|
||||
args.command.strip()
|
||||
if args.command.strip()
|
||||
else "--profile universal_clauses --scope universal_clauses "
|
||||
"--universal-clauses-artefacts-dir docs/artefacts/collatz/universal_clauses "
|
||||
"--out-dir applications/collatz/out --docs-dir docs"
|
||||
)
|
||||
artefacts_dir = (
|
||||
Path(args.universal_clauses_artefacts_dir).resolve()
|
||||
if args.universal_clauses_artefacts_dir.strip()
|
||||
else (docs_dir / "artefacts" / "collatz" / "universal_clauses")
|
||||
)
|
||||
command = args.command.strip()
|
||||
if not command:
|
||||
artefacts_display = display_path(artefacts_dir, repo_root)
|
||||
command = (
|
||||
"python3 applications/collatz/collatz_k_scripts/collatz_generate_run_report.py "
|
||||
"--profile universal_clauses "
|
||||
f"--scope {args.scope} "
|
||||
"--out-dir applications/collatz/out --docs-dir docs "
|
||||
f"--universal-clauses-artefacts-dir {artefacts_display}"
|
||||
)
|
||||
clauses_json = artefacts_dir / "clauses_universelles.json"
|
||||
clauses_md = artefacts_dir / "clauses_universelles.md"
|
||||
verification_json = artefacts_dir / "verification_universal_clauses.json"
|
||||
@ -1550,6 +1573,57 @@ def main() -> None:
|
||||
print(f"Wrote: {output_path}")
|
||||
return
|
||||
|
||||
if args.profile == "universal_clauses_palier":
|
||||
artefacts_dir = (
|
||||
Path(args.universal_clauses_artefacts_dir).resolve()
|
||||
if args.universal_clauses_artefacts_dir.strip()
|
||||
else (docs_dir / "artefacts" / "collatz" / "universal_clauses")
|
||||
)
|
||||
command = args.command.strip()
|
||||
if not command:
|
||||
artefacts_display = display_path(artefacts_dir, repo_root)
|
||||
command = (
|
||||
"python3 applications/collatz/collatz_k_scripts/collatz_generate_run_report.py "
|
||||
"--profile universal_clauses_palier "
|
||||
"--out-dir applications/collatz/out --docs-dir docs "
|
||||
f"--universal-clauses-artefacts-dir {artefacts_display}"
|
||||
)
|
||||
clauses_json = artefacts_dir / "clauses_universelles.json"
|
||||
clauses_md = artefacts_dir / "clauses_universelles.md"
|
||||
verification_json = artefacts_dir / "verification_universal_clauses.json"
|
||||
verification_md = artefacts_dir / "verification_universal_clauses.md"
|
||||
metrics = parse_universal_clauses_metrics(
|
||||
clauses_json_path=clauses_json,
|
||||
verification_json_path=verification_json,
|
||||
)
|
||||
date_str = pick_report_date_from_mtime([clauses_json, clauses_md, verification_json, verification_md])
|
||||
|
||||
c3_input_json = _extract_universal_clauses_c3_input_path(clauses_json_path=clauses_json, repo_root=repo_root)
|
||||
sha_paths: list[Path] = [
|
||||
repo_root / "applications" / "collatz" / "collatz_k_scripts" / "collatz_generate_run_report.py",
|
||||
repo_root / "applications" / "collatz" / "collatz_k_scripts" / "collatz_extract_universal_clauses.py",
|
||||
repo_root / "applications" / "collatz" / "collatz_k_scripts" / "collatz_verify_universal_clauses.py",
|
||||
c3_input_json,
|
||||
clauses_json,
|
||||
clauses_md,
|
||||
verification_json,
|
||||
verification_md,
|
||||
]
|
||||
sha_entries = compute_sha256_entries(sha_paths)
|
||||
m = metrics.domain_palier
|
||||
output_path = docs_dir / f"collatz_run_report_{date_str}_universal_clauses_palier2p{m}.md"
|
||||
write_universal_clauses_run_report(
|
||||
output_path=output_path,
|
||||
report_title=f"Rapport d’exécution — universal_clauses_palier2p{m}",
|
||||
command=command,
|
||||
git_commit=commit_hash,
|
||||
sha_entries=sha_entries,
|
||||
metrics=metrics,
|
||||
artefacts_dir=artefacts_dir,
|
||||
)
|
||||
print(f"Wrote: {output_path}")
|
||||
return
|
||||
|
||||
raise ValueError(f"Unknown profile: {args.profile}")
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,237 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
collatz_generate_terminal_clauses_over_Sm.py
|
||||
|
||||
Generate a deterministic set of terminal D/F clauses for the full odd residue space S_m
|
||||
(odd residues modulo 2^m), optionally restricted to clauses *directly decidable* at 2^m
|
||||
in the sense A+1 <= m (so stable_modulus_power == m).
|
||||
|
||||
This script is intended as an "Option A (expanded domain)" source of terminal clauses
|
||||
to support refinement-closure audits over S_M.
|
||||
|
||||
Inputs:
|
||||
- None (pure computation at a chosen modulus power), except the code of collatz_k_core.
|
||||
|
||||
Outputs:
|
||||
- docs/artefacts/collatz/terminal_clauses_over_Sm/palier2p<m>/clauses_terminal_over_Sm_mod2p<m>.{json,md}
|
||||
|
||||
Notes:
|
||||
- Clauses are generated from prefix_data and standard threshold formulas (N0_D, Nf_F).
|
||||
- No claim of global correctness is made beyond the arithmetic validation of the clause parameters.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Literal
|
||||
|
||||
from collatz_k_core import prefix_data, N0_D, fusion_choice_a, delta_F, Nf_F
|
||||
|
||||
|
||||
ClauseKind = Literal["D_exact", "F"]
|
||||
|
||||
|
||||
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 _sha256_file(path: Path, chunk_size: int = 16 * 1024 * 1024) -> str:
|
||||
h = hashlib.sha256()
|
||||
with path.open("rb") as f:
|
||||
while True:
|
||||
chunk = f.read(chunk_size)
|
||||
if not chunk:
|
||||
break
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def _utc_now_iso() -> str:
|
||||
return datetime.now(tz=timezone.utc).isoformat().replace("+00:00", "Z")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TerminalClause:
|
||||
kind: ClauseKind
|
||||
modulus_power: int
|
||||
residue_mod_2p: int
|
||||
threshold: int
|
||||
k_or_t: int
|
||||
A: int
|
||||
C: int
|
||||
|
||||
def to_json(self) -> dict[str, object]:
|
||||
return {
|
||||
"kind": self.kind,
|
||||
"modulus_power": self.modulus_power,
|
||||
"residue_mod_2p": self.residue_mod_2p,
|
||||
"threshold": self.threshold,
|
||||
"k_or_t": self.k_or_t,
|
||||
"A": self.A,
|
||||
"C": self.C,
|
||||
}
|
||||
|
||||
|
||||
def _best_direct_clause_for_residue(*, r: int, m: int, k_max: int, t_max: int) -> TerminalClause | None:
|
||||
"""
|
||||
Return a clause with A+1 <= m (directly decidable at 2^m), preferring smaller A.
|
||||
Deterministic tie-breakers: kind, k/t, threshold.
|
||||
"""
|
||||
best: TerminalClause | None = None
|
||||
best_key: tuple[int, str, int, int] | None = None
|
||||
|
||||
for k in range(1, k_max + 1):
|
||||
pref = prefix_data(r, k)
|
||||
if pref.A + 1 > m:
|
||||
break
|
||||
try:
|
||||
N0 = N0_D(pref.C, pref.A, k)
|
||||
except ValueError:
|
||||
continue
|
||||
cand = TerminalClause(kind="D_exact", modulus_power=m, residue_mod_2p=r, threshold=N0, k_or_t=k, A=pref.A, C=pref.C)
|
||||
key = (cand.A, cand.kind, cand.k_or_t, cand.threshold)
|
||||
if best_key is None or key < best_key:
|
||||
best_key = key
|
||||
best = cand
|
||||
|
||||
for t in range(1, t_max + 1):
|
||||
pref = prefix_data(r, t)
|
||||
if pref.A + 1 > m:
|
||||
break
|
||||
a = fusion_choice_a(pref.y)
|
||||
if a is None:
|
||||
continue
|
||||
if delta_F(pref.A, t, a) <= 0:
|
||||
continue
|
||||
try:
|
||||
Nf = Nf_F(pref.C, pref.A, t, a)
|
||||
except ValueError:
|
||||
continue
|
||||
cand = TerminalClause(kind="F", modulus_power=m, residue_mod_2p=r, threshold=Nf, k_or_t=t, A=pref.A, C=pref.C)
|
||||
key = (cand.A, cand.kind, cand.k_or_t, cand.threshold)
|
||||
if best_key is None or key < best_key:
|
||||
best_key = key
|
||||
best = cand
|
||||
|
||||
return best
|
||||
|
||||
|
||||
def run(*, palier: int, k_max: int, t_max: int, output_dir: Path, repo_root: Path) -> None:
|
||||
if palier < 2:
|
||||
raise ValueError("palier must be >= 2")
|
||||
if k_max < 1 or t_max < 1:
|
||||
raise ValueError("k_max and t_max must be >= 1")
|
||||
|
||||
mod = 1 << palier
|
||||
residues = list(range(1, mod, 2))
|
||||
|
||||
clauses: list[TerminalClause] = []
|
||||
missing: list[int] = []
|
||||
for r in residues:
|
||||
c = _best_direct_clause_for_residue(r=r, m=palier, k_max=k_max, t_max=t_max)
|
||||
if c is None:
|
||||
missing.append(r)
|
||||
continue
|
||||
clauses.append(c)
|
||||
|
||||
out_json = output_dir / f"clauses_terminal_over_Sm_mod2p{palier}.json"
|
||||
out_md = output_dir / f"clauses_terminal_over_Sm_mod2p{palier}.md"
|
||||
|
||||
generated_at = _utc_now_iso()
|
||||
core_path = repo_root / "applications" / "collatz" / "collatz_k_scripts" / "collatz_k_core.py"
|
||||
sha_inputs = {}
|
||||
if core_path.exists():
|
||||
sha_inputs[str(core_path.relative_to(repo_root))] = _sha256_file(core_path)
|
||||
|
||||
obj: dict[str, object] = {
|
||||
"domain": {
|
||||
"palier": palier,
|
||||
"S_M_size": len(residues),
|
||||
},
|
||||
"params": {
|
||||
"k_max": k_max,
|
||||
"t_max": t_max,
|
||||
"direct_decidability": "A+1 <= M (stable_modulus_power == M)",
|
||||
},
|
||||
"generated_at": generated_at,
|
||||
"sha256": {"inputs": sha_inputs},
|
||||
"counts": {
|
||||
"total_roots": len(residues),
|
||||
"clauses": len(clauses),
|
||||
"missing": len(missing),
|
||||
"D_exact": sum(1 for c in clauses if c.kind == "D_exact"),
|
||||
"F": sum(1 for c in clauses if c.kind == "F"),
|
||||
},
|
||||
"missing_sample": missing[:64],
|
||||
"clauses": [c.to_json() for c in clauses],
|
||||
}
|
||||
_write_json(out_json, obj)
|
||||
|
||||
md: list[str] = []
|
||||
md.append("**Auteur** : Équipe 4NK")
|
||||
md.append("")
|
||||
md.append(f"# Clauses terminales sur S_M — décidables directement à 2^{palier}")
|
||||
md.append("")
|
||||
md.append("## Domaine")
|
||||
md.append("")
|
||||
md.append(f"- palier : 2^{palier}")
|
||||
md.append(f"- |S_M| (impairs) : {len(residues)}")
|
||||
md.append("")
|
||||
md.append("## Paramètres")
|
||||
md.append("")
|
||||
md.append(f"- k_max : {k_max}")
|
||||
md.append(f"- t_max : {t_max}")
|
||||
md.append("- critère : A+1 <= M (stable_modulus_power == M)")
|
||||
md.append("")
|
||||
md.append("## Compteurs")
|
||||
md.append("")
|
||||
md.append(f"- clauses : {len(clauses)}")
|
||||
md.append(f"- missing : {len(missing)}")
|
||||
md.append(f"- D_exact : {sum(1 for c in clauses if c.kind == 'D_exact')}")
|
||||
md.append(f"- F : {sum(1 for c in clauses if c.kind == 'F')}")
|
||||
md.append("")
|
||||
if missing:
|
||||
md.append("### Missing (extrait)")
|
||||
md.append("")
|
||||
md.append(", ".join(map(str, missing[:64])) + (" …" if len(missing) > 64 else ""))
|
||||
md.append("")
|
||||
md.append("## Sorties")
|
||||
md.append("")
|
||||
md.append(f"- JSON : `{out_json}`")
|
||||
md.append(f"- Markdown : `{out_md}`")
|
||||
md.append("")
|
||||
_write_md(out_md, md)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ap = argparse.ArgumentParser(description="Generate terminal clauses over S_M (directly decidable at 2^M)")
|
||||
ap.add_argument("--repo-root", default=".", help="Repository root (defaults to current working directory)")
|
||||
ap.add_argument("--palier", type=int, default=16, help="Palier M for S_M")
|
||||
ap.add_argument("--k-max", type=int, default=14, help="Max k to search for D clauses")
|
||||
ap.add_argument("--t-max", type=int, default=14, help="Max t to search for F clauses")
|
||||
ap.add_argument("--output-dir", default="", help="Output directory (defaults under docs/artefacts/...)")
|
||||
args = ap.parse_args()
|
||||
|
||||
repo_root = Path(args.repo_root).resolve()
|
||||
palier = int(args.palier)
|
||||
output_dir = Path(args.output_dir).resolve() if args.output_dir.strip() else (
|
||||
repo_root / "docs" / "artefacts" / "collatz" / "terminal_clauses_over_Sm" / f"palier2p{palier}"
|
||||
)
|
||||
run(palier=palier, k_max=int(args.k_max), t_max=int(args.t_max), output_dir=output_dir, repo_root=repo_root)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@ -151,6 +151,12 @@ def run(
|
||||
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"
|
||||
|
||||
@ -26,6 +26,22 @@ def _find_column(row: dict, *candidates: str) -> str | None:
|
||||
return None
|
||||
|
||||
|
||||
def _find_column_exact(row: dict, *candidates: str) -> str | None:
|
||||
"""
|
||||
Return the first column whose normalized key equals one of the candidates.
|
||||
|
||||
Use this for short keys like 'm' where substring matching is unsafe
|
||||
(e.g. 'classe_mod_2^m' contains 'm' but is not an exponent column).
|
||||
"""
|
||||
keys = set(row.keys())
|
||||
normalized: dict[str, str] = {k.replace(" ", "").lower(): k for k in keys}
|
||||
for c in candidates:
|
||||
ck = c.replace(" ", "").lower()
|
||||
if ck in normalized:
|
||||
return normalized[ck]
|
||||
return None
|
||||
|
||||
|
||||
def _try_parse_int(value: object) -> int | None:
|
||||
if value is None:
|
||||
return None
|
||||
@ -53,12 +69,12 @@ def infer_palier(rows: list[dict], classe_col: str | None, csv_path: Path | None
|
||||
- fallback heuristic from max class value (legacy; not reliable when values are sparse)
|
||||
"""
|
||||
if rows:
|
||||
pal_col = _find_column(rows[0], "palier")
|
||||
pal_col = _find_column_exact(rows[0], "palier")
|
||||
if pal_col:
|
||||
v = _try_parse_int(rows[0].get(pal_col))
|
||||
if v is not None and v > 0:
|
||||
return v
|
||||
m_col = _find_column(rows[0], "m", "modulus_power")
|
||||
m_col = _find_column_exact(rows[0], "m", "modulus_power")
|
||||
if m_col:
|
||||
v = _try_parse_int(rows[0].get(m_col))
|
||||
if v is not None and v > 0:
|
||||
|
||||
@ -33,7 +33,7 @@ import re
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
from collatz_k_core import U_step, prefix_data, N0_D, fusion_choice_a, delta_F, Nf_F
|
||||
from collatz_k_core import U_step, prefix_data, N0_D, fusion_choice_a, delta_F, Nf_F, preimage_m
|
||||
|
||||
|
||||
def _read_json(path: Path) -> object:
|
||||
@ -47,16 +47,6 @@ def _discover_state_dirs(root: Path, palier: int) -> list[Path]:
|
||||
return dirs
|
||||
|
||||
|
||||
def _load_covered_from_cert(cert_path: Path) -> set[int]:
|
||||
obj = _read_json(cert_path)
|
||||
if not isinstance(obj, dict) or "covered" not in obj:
|
||||
raise ValueError(f"Invalid certificate JSON (missing covered): {cert_path}")
|
||||
cov = obj["covered"]
|
||||
if not isinstance(cov, list) or not all(isinstance(x, int) for x in cov):
|
||||
raise ValueError(f"Invalid certificate JSON covered list: {cert_path}")
|
||||
return set(cov)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FusionWitness:
|
||||
n: int
|
||||
@ -126,18 +116,30 @@ def _collatz_terminates(n: int) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
def _pick_best_witness(witnesses: list[FusionWitness]) -> dict[int, FusionWitness]:
|
||||
def _pick_best_strict_witness(*, witnesses: list[FusionWitness], palier: int) -> dict[int, FusionWitness]:
|
||||
"""
|
||||
For each n, choose a canonical witness: minimal t, then minimal preimage_m,
|
||||
then lexical source_csv (for determinism).
|
||||
For each n, choose a canonical STRICT fusion witness that prioritizes lower modular stability.
|
||||
|
||||
Objective:
|
||||
- minimize required_m_stable := max(palier, A_t+1), where A_t is computed from prefix_data(n,t)
|
||||
(this increases the fraction of witnesses that can be turned into clauses decidable at 2^palier).
|
||||
|
||||
Tie-breakers (deterministic):
|
||||
- minimal A_t
|
||||
- minimal t
|
||||
- minimal preimage_m
|
||||
- lexical source_csv
|
||||
"""
|
||||
out: dict[int, FusionWitness] = {}
|
||||
key_by_n: dict[int, tuple[int, int, int, int, str]] = {}
|
||||
for w in witnesses:
|
||||
prev = out.get(w.n)
|
||||
if prev is None:
|
||||
out[w.n] = w
|
||||
continue
|
||||
if (w.t, w.preimage_m, w.source_csv) < (prev.t, prev.preimage_m, prev.source_csv):
|
||||
pref = prefix_data(w.n, w.t)
|
||||
A_t = pref.A
|
||||
required_m_stable = max(palier, A_t + 1)
|
||||
key = (required_m_stable, A_t, w.t, w.preimage_m, w.source_csv)
|
||||
prev_key = key_by_n.get(w.n)
|
||||
if prev_key is None or key < prev_key:
|
||||
key_by_n[w.n] = key
|
||||
out[w.n] = w
|
||||
return out
|
||||
|
||||
@ -159,7 +161,6 @@ def run(
|
||||
|
||||
# Domain L as union of per-state lifted noyaux
|
||||
L: set[int] = set()
|
||||
d8_covered: set[int] = set()
|
||||
fusion_witnesses_all: list[FusionWitness] = []
|
||||
|
||||
for sd in state_dirs:
|
||||
@ -175,140 +176,159 @@ def run(
|
||||
raise ValueError(f"Invalid lift noyau list: {lift_candidates[0]}")
|
||||
L |= set(lift_list)
|
||||
|
||||
cert_d8 = sd / "certificats" / f"certificat_D8_E{sid}_palier2p{palier}.json"
|
||||
if cert_d8.exists():
|
||||
d8_covered |= _load_covered_from_cert(cert_d8)
|
||||
|
||||
fusion_witnesses_all.extend(_load_fusion_witnesses(sd, palier))
|
||||
|
||||
if not L:
|
||||
raise ValueError("Empty domain L")
|
||||
|
||||
fusion_by_n = _pick_best_witness(fusion_witnesses_all)
|
||||
|
||||
d8_nodes = sorted([n for n in L if n in d8_covered])
|
||||
f_nodes = sorted([n for n in L if n not in d8_covered])
|
||||
|
||||
missing_f = [n for n in f_nodes if n not in fusion_by_n]
|
||||
if missing_f:
|
||||
raise ValueError(f"Missing fusion witness for {len(missing_f)} residues (e.g. {missing_f[:20]})")
|
||||
strict_fusion_by_n = _pick_best_strict_witness(witnesses=fusion_witnesses_all, palier=palier)
|
||||
|
||||
records: list[dict[str, object]] = []
|
||||
next_values: list[int] = []
|
||||
thresholds: list[int] = []
|
||||
d8_exact_nodes = 0
|
||||
d8_brother_nodes = 0
|
||||
d8_exact_base_cases = 0
|
||||
d8_exact_descent_witnesses = 0
|
||||
|
||||
shift = 1 << (palier - 1)
|
||||
d8_exact_set: set[int] = set()
|
||||
d8_brother_set: set[int] = set()
|
||||
for n in d8_nodes:
|
||||
pref = prefix_data(n, 8)
|
||||
if pref.A == 13:
|
||||
d8_exact_set.add(n)
|
||||
else:
|
||||
d8_brother_set.add(n)
|
||||
d_nodes = 0
|
||||
d_base_cases = 0
|
||||
d_descent_witnesses = 0
|
||||
f_nodes = 0
|
||||
f_base_cases = 0
|
||||
f_descent_witnesses = 0
|
||||
t_search_max = 14 # A_t <= 14 is required for m_stable <= 15 at palier 2^15
|
||||
|
||||
for n in sorted(L):
|
||||
if n in d8_covered:
|
||||
pref = prefix_data(n, 8)
|
||||
if n in d8_exact_set:
|
||||
d8_exact_nodes += 1
|
||||
N0 = N0_D(pref.C, pref.A, 8)
|
||||
thresholds.append(N0)
|
||||
|
||||
if n >= N0:
|
||||
y = pref.y
|
||||
if y >= n:
|
||||
raise ValueError(f"D8 descent check failed for n={n}: U^8(n)={y} not < n (N0={N0})")
|
||||
next_values.append(y)
|
||||
d8_exact_descent_witnesses += 1
|
||||
records.append(
|
||||
{
|
||||
"n": n,
|
||||
"kind": "D_exact",
|
||||
"k": 8,
|
||||
"A_k": pref.A,
|
||||
"C_k": pref.C,
|
||||
"N0": N0,
|
||||
"next": y,
|
||||
"base_case": False,
|
||||
}
|
||||
)
|
||||
else:
|
||||
d8_exact_base_cases += 1
|
||||
records.append(
|
||||
{
|
||||
"n": n,
|
||||
"kind": "D_exact",
|
||||
"k": 8,
|
||||
"A_k": pref.A,
|
||||
"C_k": pref.C,
|
||||
"N0": N0,
|
||||
"next": None,
|
||||
"base_case": True,
|
||||
}
|
||||
)
|
||||
# Try to produce a D_k witness with A_k <= 14 (so m_stable <= 15 at palier 2^15).
|
||||
best_d: dict[str, object] | None = None
|
||||
best_d_key: tuple[int, int, int, int, int] | None = None
|
||||
for k in range(1, t_search_max + 1):
|
||||
pref = prefix_data(n, k)
|
||||
if pref.A > 14:
|
||||
break
|
||||
try:
|
||||
N0 = N0_D(pref.C, pref.A, k)
|
||||
except ValueError:
|
||||
continue
|
||||
base_case = n < N0
|
||||
if not base_case and pref.y >= n:
|
||||
continue
|
||||
key = (max(palier, pref.A + 1), 1 if base_case else 0, pref.A, k, N0)
|
||||
if best_d_key is None or key < best_d_key:
|
||||
best_d_key = key
|
||||
best_d = {
|
||||
"n": n,
|
||||
"kind": "D_exact",
|
||||
"k": k,
|
||||
"A_k": pref.A,
|
||||
"C_k": pref.C,
|
||||
"N0": N0,
|
||||
"next": (None if base_case else pref.y),
|
||||
"base_case": base_case,
|
||||
}
|
||||
if best_d is not None:
|
||||
d_nodes += 1
|
||||
N0v = int(best_d["N0"]) # type: ignore[arg-type]
|
||||
thresholds.append(N0v)
|
||||
if bool(best_d["base_case"]):
|
||||
d_base_cases += 1
|
||||
else:
|
||||
d8_brother_nodes += 1
|
||||
mate = n ^ shift
|
||||
if mate not in d8_exact_set:
|
||||
raise ValueError(
|
||||
f"D8 brother check failed for n={n}: expected mate={mate} to be an exact D8 candidate (A8=13)"
|
||||
)
|
||||
records.append(
|
||||
{
|
||||
"n": n,
|
||||
"kind": "D_brother",
|
||||
"k": 8,
|
||||
"A_k": pref.A,
|
||||
"C_k": pref.C,
|
||||
"mate_exact": mate,
|
||||
}
|
||||
)
|
||||
else:
|
||||
w = fusion_by_n[n]
|
||||
pref = prefix_data(n, w.t)
|
||||
y = pref.y
|
||||
if y != w.y:
|
||||
raise ValueError(f"Fusion witness y mismatch for n={n}: computed U^{w.t}(n)={y}, row y={w.y}")
|
||||
m = w.preimage_m
|
||||
if m >= n:
|
||||
raise ValueError(f"Fusion witness preimage not smaller for n={n}: m={m} >= n")
|
||||
y2, _ = U_step(m)
|
||||
if y2 != y:
|
||||
raise ValueError(f"Fusion witness invalid: U(m) != U^t(n) for n={n}: U({m})={y2}, U^{w.t}({n})={y}")
|
||||
a = fusion_choice_a(y)
|
||||
d_descent_witnesses += 1
|
||||
next_values.append(int(best_d["next"])) # type: ignore[arg-type]
|
||||
records.append(best_d)
|
||||
continue
|
||||
|
||||
# Try to produce a short fusion witness (t<=14, A_t<=14). Allow base-case if n < Nf.
|
||||
best_f: dict[str, object] | None = None
|
||||
best_f_key: tuple[int, int, int, int, int, int] | None = None
|
||||
for t in range(1, t_search_max + 1):
|
||||
pref = prefix_data(n, t)
|
||||
if pref.A > 14:
|
||||
break
|
||||
a = fusion_choice_a(pref.y)
|
||||
if a is None:
|
||||
raise ValueError(f"Fusion witness invalid: y mod 3 == 0 for n={n}, y={y}")
|
||||
if a != w.a:
|
||||
raise ValueError(f"Fusion witness a mismatch for n={n}: computed a={a}, row a={w.a}")
|
||||
dF = delta_F(pref.A, w.t, a)
|
||||
continue
|
||||
dF = delta_F(pref.A, t, a)
|
||||
if dF <= 0:
|
||||
raise ValueError(f"Fusion witness invalid: DeltaF<=0 for n={n}: DeltaF={dF}")
|
||||
Nf = Nf_F(pref.C, pref.A, w.t, a)
|
||||
thresholds.append(Nf)
|
||||
if n < Nf:
|
||||
raise ValueError(f"Fusion witness invalid: n < Nf for n={n}: Nf={Nf}")
|
||||
records.append(
|
||||
{
|
||||
continue
|
||||
Nf = Nf_F(pref.C, pref.A, t, a)
|
||||
m = preimage_m(pref.y, a)
|
||||
base_case = (n < Nf) or (m >= n)
|
||||
key = (max(palier, pref.A + 1), 1 if base_case else 0, pref.A, t, Nf, m)
|
||||
if best_f_key is None or key < best_f_key:
|
||||
best_f_key = key
|
||||
best_f = {
|
||||
"n": n,
|
||||
"kind": "F",
|
||||
"t": w.t,
|
||||
"t": t,
|
||||
"a": a,
|
||||
"y": y,
|
||||
"y": pref.y,
|
||||
"preimage_m": m,
|
||||
"A_t": pref.A,
|
||||
"C_t": pref.C,
|
||||
"DeltaF": dF,
|
||||
"Nf": Nf,
|
||||
"source_csv": w.source_csv,
|
||||
"next": m,
|
||||
"source_csv": "computed:short_fusion_search",
|
||||
"next": (None if base_case else m),
|
||||
"base_case": base_case,
|
||||
}
|
||||
)
|
||||
next_values.append(m)
|
||||
if best_f is not None:
|
||||
f_nodes += 1
|
||||
if bool(best_f["base_case"]):
|
||||
f_base_cases += 1
|
||||
else:
|
||||
f_descent_witnesses += 1
|
||||
thresholds.append(int(best_f["Nf"])) # type: ignore[arg-type]
|
||||
next_values.append(int(best_f["next"])) # type: ignore[arg-type]
|
||||
# Always verify U(m)=U^t(n) at the recorded y (even in base-case mode).
|
||||
y2, _ = U_step(int(best_f["preimage_m"])) # type: ignore[arg-type]
|
||||
if y2 != int(best_f["y"]): # type: ignore[arg-type]
|
||||
raise ValueError(f"Computed fusion witness invalid for n={n}: U(m) != y")
|
||||
records.append(best_f)
|
||||
continue
|
||||
|
||||
# Fallback: strict fusion witness from local H6 artefacts (guarantees m<n for the representative).
|
||||
w = strict_fusion_by_n.get(n)
|
||||
if w is None:
|
||||
raise ValueError(f"Missing strict fusion witness for n={n}")
|
||||
pref = prefix_data(n, w.t)
|
||||
y = pref.y
|
||||
if y != w.y:
|
||||
raise ValueError(f"Fusion witness y mismatch for n={n}: computed U^{w.t}(n)={y}, row y={w.y}")
|
||||
m = w.preimage_m
|
||||
y2, _ = U_step(m)
|
||||
if y2 != y:
|
||||
raise ValueError(f"Fusion witness invalid: U(m) != U^t(n) for n={n}: U({m})={y2}, U^{w.t}({n})={y}")
|
||||
a = fusion_choice_a(y)
|
||||
if a is None:
|
||||
raise ValueError(f"Fusion witness invalid: y mod 3 == 0 for n={n}, y={y}")
|
||||
if a != w.a:
|
||||
raise ValueError(f"Fusion witness a mismatch for n={n}: computed a={a}, row a={w.a}")
|
||||
dF = delta_F(pref.A, w.t, a)
|
||||
if dF <= 0:
|
||||
raise ValueError(f"Fusion witness invalid: DeltaF<=0 for n={n}: DeltaF={dF}")
|
||||
Nf = Nf_F(pref.C, pref.A, w.t, a)
|
||||
if n < Nf:
|
||||
raise ValueError(f"Fusion witness invalid: n < Nf for n={n}: Nf={Nf}")
|
||||
if m >= n:
|
||||
raise ValueError(f"Fusion witness preimage not smaller for n={n}: m={m} >= n")
|
||||
f_nodes += 1
|
||||
f_descent_witnesses += 1
|
||||
thresholds.append(Nf)
|
||||
records.append(
|
||||
{
|
||||
"n": n,
|
||||
"kind": "F",
|
||||
"t": w.t,
|
||||
"a": a,
|
||||
"y": y,
|
||||
"preimage_m": m,
|
||||
"A_t": pref.A,
|
||||
"C_t": pref.C,
|
||||
"DeltaF": dF,
|
||||
"Nf": Nf,
|
||||
"source_csv": w.source_csv,
|
||||
"next": m,
|
||||
"base_case": False,
|
||||
}
|
||||
)
|
||||
next_values.append(m)
|
||||
|
||||
max_n = max(L)
|
||||
max_next = max(next_values) if next_values else 0
|
||||
@ -337,12 +357,12 @@ def run(
|
||||
"max_n": max_n,
|
||||
},
|
||||
"elimination": {
|
||||
"d8_nodes": len(d8_nodes),
|
||||
"d8_exact_nodes": d8_exact_nodes,
|
||||
"d8_exact_descent_witnesses": d8_exact_descent_witnesses,
|
||||
"d8_exact_base_cases": d8_exact_base_cases,
|
||||
"d8_brother_nodes": d8_brother_nodes,
|
||||
"fusion_nodes": len(f_nodes),
|
||||
"d_nodes": d_nodes,
|
||||
"d_base_cases": d_base_cases,
|
||||
"d_descent_witnesses": d_descent_witnesses,
|
||||
"f_nodes": f_nodes,
|
||||
"f_base_cases": f_base_cases,
|
||||
"f_descent_witnesses": f_descent_witnesses,
|
||||
"max_next": max_next,
|
||||
"N_star": N_star,
|
||||
},
|
||||
@ -380,12 +400,11 @@ def run(
|
||||
lines.append("## Élimination (témoins)")
|
||||
lines.append("")
|
||||
lines.append(
|
||||
f"- D8 : {len(d8_nodes)} (exact A8=13 : {d8_exact_nodes}, "
|
||||
f"descente vérifiée pour n>=N0 : {d8_exact_descent_witnesses}, "
|
||||
f"cas de base n<N0 : {d8_exact_base_cases}, "
|
||||
f"frères (mate exact requis) : {d8_brother_nodes})"
|
||||
f"- D : {d_nodes} (k variable, A_k<=14 ; descente vérifiée : {d_descent_witnesses}, cas de base : {d_base_cases})"
|
||||
)
|
||||
lines.append(
|
||||
f"- Fusion : {f_nodes} (descente vérifiée : {f_descent_witnesses}, cas de base : {f_base_cases})"
|
||||
)
|
||||
lines.append(f"- Fusion : {len(f_nodes)} (m<n, U(m)=U^t(n) vérifié)")
|
||||
lines.append(f"- max(next) : {max_next}")
|
||||
lines.append(f"- N* (max des seuils N0/Nf calculés) : {N_star}")
|
||||
lines.append("")
|
||||
|
||||
@ -0,0 +1,151 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
collatz_verify_minorated_descent_clauses_over_Sm.py
|
||||
|
||||
Deterministic verification of D_minor clauses produced by
|
||||
collatz_generate_minorated_descent_clauses_over_Sm.py.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from collatz_k_core import prefix_data
|
||||
|
||||
|
||||
def _read_json(path: Path) -> object:
|
||||
return json.loads(path.read_text(encoding="utf-8", errors="strict"))
|
||||
|
||||
|
||||
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 _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 run(*, clauses_json: Path, output_dir: Path) -> None:
|
||||
obj = _read_json(clauses_json)
|
||||
if not isinstance(obj, dict):
|
||||
raise ValueError("Invalid D_minor clauses JSON: expected object")
|
||||
domain = obj.get("domain")
|
||||
params = obj.get("params")
|
||||
clauses = obj.get("clauses")
|
||||
if not isinstance(domain, dict) or not isinstance(params, dict) or not isinstance(clauses, list):
|
||||
raise ValueError("Invalid D_minor clauses JSON: missing domain/params/clauses")
|
||||
palier = _req_int(domain, "palier")
|
||||
k = _req_int(params, "k")
|
||||
underlineA = _req_int(params, "underlineA")
|
||||
|
||||
alpha = 3**k
|
||||
pow2u = 1 << underlineA
|
||||
delta_min = (1 << underlineA) - alpha
|
||||
if delta_min <= 0:
|
||||
raise ValueError("delta_min <= 0")
|
||||
|
||||
ok = 0
|
||||
errors: list[str] = []
|
||||
for c in clauses:
|
||||
if not isinstance(c, dict):
|
||||
raise ValueError("Invalid clause entry: expected object")
|
||||
if c.get("kind") != "D_minor":
|
||||
raise ValueError("Invalid clause entry: kind must be D_minor")
|
||||
m = _req_int(c, "modulus_power")
|
||||
r = _req_int(c, "residue_mod_2p")
|
||||
kk = _req_int(c, "k")
|
||||
uA = _req_int(c, "underlineA")
|
||||
numerator_B_k = _req_int(c, "numerator_B_k")
|
||||
A_km1 = _req_int(c, "A_km1")
|
||||
C_km1 = _req_int(c, "C_km1")
|
||||
N0 = _req_int(c, "N0")
|
||||
w_prefix_raw = c.get("prefix_word_len_km1")
|
||||
if not isinstance(w_prefix_raw, list) or not all(isinstance(x, int) for x in w_prefix_raw):
|
||||
raise ValueError("Invalid prefix_word_len_km1")
|
||||
if m != palier or kk != k or uA != underlineA:
|
||||
raise ValueError("Clause params mismatch vs header")
|
||||
if underlineA > palier:
|
||||
raise ValueError("underlineA must be <= palier")
|
||||
if A_km1 + 1 > palier:
|
||||
raise ValueError("Prefix stability condition violated: A_km1+1 > palier")
|
||||
if ((alpha * r + numerator_B_k) % pow2u) != 0:
|
||||
errors.append(f"divisibility failed for r={r}")
|
||||
continue
|
||||
|
||||
pref = prefix_data(r, k - 1)
|
||||
w_prefix = [int(x) for x in pref.word]
|
||||
if w_prefix != w_prefix_raw:
|
||||
errors.append(f"prefix word mismatch for r={r}")
|
||||
continue
|
||||
if int(pref.A) != A_km1:
|
||||
errors.append(f"A_km1 mismatch for r={r}")
|
||||
continue
|
||||
if int(pref.C) != C_km1:
|
||||
errors.append(f"C_km1 mismatch for r={r}")
|
||||
continue
|
||||
expected_B_k = 3 * C_km1 + (1 << A_km1)
|
||||
if expected_B_k != numerator_B_k:
|
||||
errors.append(f"numerator_B_k mismatch for r={r}")
|
||||
continue
|
||||
expected_N0 = (numerator_B_k // delta_min) + 1
|
||||
if expected_N0 != N0:
|
||||
errors.append(f"N0 mismatch for r={r}: got {N0}, expected {expected_N0}")
|
||||
continue
|
||||
ok += 1
|
||||
|
||||
out_json = output_dir / f"verification_D_minor_over_Sm_mod2p{palier}_k{k}_u{underlineA}.json"
|
||||
out_md = output_dir / f"verification_D_minor_over_Sm_mod2p{palier}_k{k}_u{underlineA}.md"
|
||||
out = {
|
||||
"domain": {"palier": palier},
|
||||
"params": {"k": k, "underlineA": underlineA},
|
||||
"counts": {"total": len(clauses), "ok": ok, "errors": len(errors)},
|
||||
"ok": (ok == len(clauses)),
|
||||
"errors_sample": errors[:50],
|
||||
}
|
||||
_write_json(out_json, out)
|
||||
|
||||
md: list[str] = []
|
||||
md.append("**Auteur** : Équipe 4NK")
|
||||
md.append("")
|
||||
md.append(f"# Vérification — clauses D minorées sur S_M (2^{palier})")
|
||||
md.append("")
|
||||
md.append(f"- total : {len(clauses)}")
|
||||
md.append(f"- ok : {ok}")
|
||||
md.append(f"- errors : {len(errors)}")
|
||||
md.append(f"- ok_all : {out['ok']}")
|
||||
md.append("")
|
||||
if errors:
|
||||
md.append("## Erreurs (extrait)")
|
||||
md.append("")
|
||||
for e in errors[:30]:
|
||||
md.append(f"- {e}")
|
||||
md.append("")
|
||||
_write_md(out_md, md)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ap = argparse.ArgumentParser(description="Verify D_minor clauses over S_M")
|
||||
ap.add_argument("--clauses-json", required=True, help="Path to clauses_D_minor_over_Sm_mod2pM.json")
|
||||
ap.add_argument("--output-dir", default="", help="Output directory (defaults to same directory as input)")
|
||||
args = ap.parse_args()
|
||||
|
||||
clauses_json = Path(args.clauses_json).resolve()
|
||||
output_dir = Path(args.output_dir).resolve() if args.output_dir.strip() else clauses_json.parent
|
||||
run(clauses_json=clauses_json, output_dir=output_dir)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@ -168,8 +168,9 @@ def run(
|
||||
raise ValueError(f"D_exact clause params mismatch for n={n}")
|
||||
if m_stab is None or r_stab is None or word is None:
|
||||
raise ValueError(f"D_exact clause missing stability fields for n={n}")
|
||||
if m_stab != A_k + 1:
|
||||
raise ValueError(f"D_exact stable modulus mismatch for n={n}: {m_stab} != {A_k+1}")
|
||||
m_expected = max(palier, A_k + 1)
|
||||
if m_stab != m_expected:
|
||||
raise ValueError(f"D_exact stable modulus mismatch for n={n}: {m_stab} != {m_expected}")
|
||||
pref = prefix_data(n, k)
|
||||
if pref.word != word or pref.A != A_k or pref.C != C_k:
|
||||
raise ValueError(f"D_exact prefix mismatch for n={n}")
|
||||
@ -211,8 +212,9 @@ def run(
|
||||
raise ValueError(f"F clause params mismatch for n={n}")
|
||||
if m_stab is None or r_stab is None or word is None:
|
||||
raise ValueError(f"F clause missing stability fields for n={n}")
|
||||
if m_stab != A_t + 1:
|
||||
raise ValueError(f"F stable modulus mismatch for n={n}: {m_stab} != {A_t+1}")
|
||||
m_expected = max(palier, A_t + 1)
|
||||
if m_stab != m_expected:
|
||||
raise ValueError(f"F stable modulus mismatch for n={n}: {m_stab} != {m_expected}")
|
||||
|
||||
pref = prefix_data(n, t)
|
||||
if pref.word != word or pref.A != A_t or pref.C != C_t or pref.y != y:
|
||||
|
||||
@ -190,13 +190,13 @@ On fixe un palier de relèvement \(m\ge 13\) et on partitionne explicitement les
|
||||
Pour rendre cette complétude locale *citable* (et alignée avec la notion “certifié D/F”), l’artefact attendu est un CSV+certificat construit sur un domaine fini explicitement défini :
|
||||
|
||||
- domaine \(L\) : la liste explicite des relèvements impairs de \(B_{12}(E_1)\) au palier \(m\) (pour un premier essai : \(m=13\), donc \(L\) a cardinal \(2^{m-12}\cdot 16 = 32\)) ;
|
||||
- certificats produits : `certificat_D8_palier2p13.json` et/ou `certificat_Ft_palier2p13.json` (selon les horizons retenus), obtenus par les scripts existants `collatz_k_pipeline.py` (pour D) et `collatz_fusion_pipeline.py` + `collatz_scission.py` (pour F) appliqués à \(L\) ;
|
||||
- certificats produits : `certificat_D8_palier2p<m>.json` et/ou `certificat_Ft*_palier2p<m>.json` (selon les horizons retenus), obtenus par les scripts existants `collatz_k_pipeline.py` (pour D) et `collatz_fusion_pipeline.py` + `collatz_scission.py` (pour F) appliqués à \(L\) ;
|
||||
- assertion (H6) : l’union des ensembles `covered` de ces certificats recouvre exactement \(L\).
|
||||
|
||||
Note (versionnement, flux standard).
|
||||
Les artefacts locaux produits pour H6(E1) ne peuvent pas être versionnés dans `applications/collatz/out/` car ce répertoire est ignoré par Git. Une copie canonique (versionnée) est donc placée dans :
|
||||
|
||||
- `docs/artefacts/collatz/local_E1_palier2p13/`
|
||||
- `docs/artefacts/collatz/local_E1_palier2p<m>/` (par exemple `.../local_E1_palier2p15/`)
|
||||
|
||||
et sert de base pour les rapports d’exécution générés.
|
||||
|
||||
@ -205,12 +205,11 @@ Un index versionné agrège \(\Delta m(E)\) et les horizons minimaux observés p
|
||||
|
||||
- `docs/artefacts/collatz/local_H6_index.md`
|
||||
|
||||
Constats (à partir de l’index, palier cible \(2^{13}\)).
|
||||
Constats (à partir de l’index, palier cible \(2^{15}\)).
|
||||
Les artefacts versionnés montrent, pour les 60 états \(E\) de \(B_{12}\) :
|
||||
|
||||
- \(\Delta m(E)=1\) (donc relèvement \(12\to 13\)) ;
|
||||
- l’horizon maximal observé pour la complétude par fusion est \(t_{\max}=51\) (états \(E9\) et \(E25\)) ;
|
||||
- certains états sont complets par D8 seul (pas de clause de fusion observée sur le complément après D8 : \(E56\), \(E57\), \(E58\)).
|
||||
- \(\Delta m(E)=3\) (donc relèvement \(12\to 15\)) ;
|
||||
- l’horizon maximal observé pour la complétude par fusion est \(t_{\max,\mathrm{used}}=64\).
|
||||
|
||||
Ces constats sont des assertions d’audit (égalité d’ensembles sur artefacts) et ne remplacent pas la preuve des hypothèses (H4)–(H5).
|
||||
|
||||
|
||||
@ -73,7 +73,7 @@ Cette trajectoire isole une chaîne de vérifications citable (sans transcript)
|
||||
|
||||
- C1 (complétude locale H6(E) sur les états de \(B_{12}\)) :
|
||||
- index : `docs/artefacts/collatz/local_H6_index.md`
|
||||
- rapports : `docs/collatz_run_report_2026-03-09_local_H6_E*_palier2p13.md`, `docs/collatz_run_report_2026-03-09_local_H6_E*_palier2p14.md`
|
||||
- rapports : `docs/collatz_run_report_2026-03-09_local_H6_E*_palier2p13.md`, `docs/collatz_run_report_2026-03-09_local_H6_E*_palier2p14.md`, `docs/collatz_run_report_2026-03-09_local_H6_E*_palier2p15.md`
|
||||
|
||||
- C2 (réduction projective par complétion “one” et stabilité \(B_m\bmod 2^{12}=B_{12}\)) :
|
||||
- script : `applications/collatz/collatz_k_scripts/collatz_verify_c2_projective.py`
|
||||
@ -84,15 +84,16 @@ Cette trajectoire isole une chaîne de vérifications citable (sans transcript)
|
||||
- `applications/collatz/collatz_k_scripts/complétion_minorée_m15_vers_m16.md`
|
||||
- `applications/collatz/collatz_k_scripts/complétion_minorée_m16_vers_m17.md`
|
||||
|
||||
- C3 (instance locale au palier \(2^{13}\) sur \(L=\mathrm{Lift}_{12\to 13}(B_{12})\)) :
|
||||
- C3 (instance locale au palier \(2^{m}\) sur \(L=\mathrm{Lift}_{12\to m}(B_{12})\), \(m\ge 13\)) :
|
||||
- script : `applications/collatz/collatz_k_scripts/collatz_verify_c3_local_descent.py`
|
||||
- sorties : `docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent.{json,md}` et `..._palier2p<m>.{json,md}`
|
||||
- rapports : `docs/collatz_run_report_2026-03-09_c3_local_descent.md`, `docs/collatz_run_report_2026-03-09_c3_local_descent_palier2p14.md`
|
||||
- rapports : `docs/collatz_run_report_2026-03-09_c3_local_descent.md`, `docs/collatz_run_report_2026-03-09_c3_local_descent_palier2p14.md`, `docs/collatz_run_report_2026-03-09_c3_local_descent_palier2p15.md`
|
||||
|
||||
- Extraction de clauses universelles candidates (Option A : Lift(\(B_{12}\))) :
|
||||
- scripts : `applications/collatz/collatz_k_scripts/{collatz_extract_universal_clauses.py,collatz_verify_universal_clauses.py}`
|
||||
- sorties : `docs/artefacts/collatz/universal_clauses/{clauses_universelles,verification_universal_clauses}.{json,md}` et `docs/artefacts/collatz/universal_clauses/palier2p14/*`
|
||||
- rapports : `docs/collatz_run_report_2026-03-09_universal_clauses.md`, `docs/collatz_run_report_2026-03-09_universal_clauses_palier2p14.md`
|
||||
- stabilisation : pour un témoin au palier \(m\) avec somme \(A\), la clause candidate est indexée par \(m_{stable}=\max(m,A+1)\)
|
||||
- sorties : `docs/artefacts/collatz/universal_clauses/{clauses_universelles,verification_universal_clauses}.{json,md}` et `docs/artefacts/collatz/universal_clauses/palier2p14/*`, `docs/artefacts/collatz/universal_clauses/palier2p15/*`
|
||||
- rapports : `docs/collatz_run_report_2026-03-09_universal_clauses.md`, `docs/collatz_run_report_2026-03-09_universal_clauses_palier2p14.md`, `docs/collatz_run_report_2026-03-09_universal_clauses_palier2p15.md`
|
||||
|
||||
Le verrou restant est la transformation des témoins observés en clauses universelles valides “pour tout \(n\) dans une classe modulo \(2^m\), pour tout \(n\ge N\)”, et l’itération du schéma \(C1+C2\to C3\) à paliers arbitraires. La formalisation minimale visée est donnée dans :
|
||||
- `applications/collatz/collatz_k_scripts/plan_lemmes_manquants_et_programme_de_preuve.md`.
|
||||
@ -175,6 +176,47 @@ on a \(m<n\) dès que \(n\ge N_F\).
|
||||
|
||||
La congruence \(y\equiv 2 \pmod 3\) assure l'intégralité de \((2y-1)/3\). Ensuite \(U(m)=y\) par construction de la branche impaire avec une seule division par 2. La borne \(m<n\) se réduit à une inégalité affine en \(n\), équivalente à \(\Delta_F n > 2C_k+1\). \(\square\)
|
||||
|
||||
### Lemme 4 (Stabilité d’un préfixe au module \(2^{m_{stable}}\))
|
||||
|
||||
**Hypothèses.**
|
||||
|
||||
- \(n_0\) impair, \(k\ge 1\);
|
||||
- on fixe un mot \(w=(a_0,\dots,a_{k-1})\) et l’on suppose que \(n_0\) réalise ce préfixe, c’est-à-dire
|
||||
\[
|
||||
\forall i\in\{0,\dots,k-1\},\quad a_i=v_2(3n_i+1)\ \text{avec}\ n_{i+1}=U(n_i);
|
||||
\]
|
||||
- on note \(A:=\sum_{i=0}^{k-1} a_i\) et \(C_k\) la constante affine associée à \(w\) (lemme 1);
|
||||
- on fixe un palier de domaine \(m_{\mathrm{dom}}\ge 1\) tel que \(n_0\) est interprété comme une classe modulo \(2^{m_{\mathrm{dom}}}\);
|
||||
- on pose
|
||||
\[
|
||||
m_{stable}:=\max(m_{\mathrm{dom}},A+1).
|
||||
\]
|
||||
|
||||
**Énoncé.**
|
||||
|
||||
Il existe un résidu unique \(r\in S_{m_{stable}}\) tel que \(r\equiv n_0\pmod{2^{m_{\mathrm{dom}}}}\) et tel que, pour tout impair \(n\) vérifiant \(n\equiv r\pmod{2^{m_{stable}}}\), on a :
|
||||
|
||||
1) le préfixe de valuations est constant et vaut \(w\) :
|
||||
\[
|
||||
\forall i\in\{0,\dots,k-1\},\quad v_2(3n_i+1)=a_i;
|
||||
\]
|
||||
|
||||
2) les constantes affines sont identiques :
|
||||
\[
|
||||
U^{(k)}(n)=\frac{3^k n + C_k}{2^A},
|
||||
\]
|
||||
et \(A_k(n)=A\), \(C_k(n)=C_k\).
|
||||
|
||||
**Preuve.**
|
||||
|
||||
Pour chaque \(i\), la condition \(v_2(3n_i+1)=a_i\) est équivalente à une conjonction de congruences modulo des puissances de 2 ne dépassant pas \(2^{A+1}\) :
|
||||
\[
|
||||
3n_i+1\equiv 0\pmod{2^{a_i}}\quad\text{et}\quad 3n_i+1\not\equiv 0\pmod{2^{a_i+1}}.
|
||||
\]
|
||||
En réécrivant \(n_i\) sous la forme affine en fonction de \(n\) (lemme 1 appliqué aux préfixes \(<i\)), ces conditions deviennent des contraintes congruentielles sur \(n\) modulo une puissance de 2 d’exposant \(\le A+1\). Ainsi, l’ensemble des impairs réalisant le préfixe \(w\) est une classe modulo \(2^{A+1}\). En imposant en outre la contrainte de domaine \(n\equiv n_0\pmod{2^{m_{\mathrm{dom}}}}\) et en prenant \(m_{stable}=\max(m_{\mathrm{dom}},A+1)\), on obtient une classe modulo \(2^{m_{stable}}\) qui fixe simultanément les \(m_{\mathrm{dom}}\) premiers bits et le préfixe \(w\). L’unicité du résidu \(r\) est immédiate.
|
||||
|
||||
Les égalités sur \(A_k\), \(C_k\) et \(U^{(k)}\) résultent alors du fait que \(w\) fixe \(A\) et \(C_k\) (lemme 1). \(\square\)
|
||||
|
||||
## Théorème-cadre conditionnel
|
||||
|
||||
### Théorème 1 (Certificat fini \((K)\Rightarrow\) terminaison globale)
|
||||
@ -186,6 +228,84 @@ La congruence \(y\equiv 2 \pmod 3\) assure l'intégralité de \((2y-1)/3\). Ensu
|
||||
- (H3) chaque clause applicable produit une réduction stricte: soit \(U^{(k)}(n)<n\), soit \(U^{(k)}(n)=U(m)\) avec \(m<n\);
|
||||
- (H4) pour tout \(1\le n\le N^\ast\), la trajectoire atteint \(1\).
|
||||
|
||||
**Formalisation de (H2) : couverture modulaire au palier \(2^M\).**
|
||||
|
||||
On note \(\mathcal{K}\) un ensemble fini de clauses universelles de type \(D/F\). Chaque clause \(c\in\mathcal{K}\) est indexée par un module \(2^{m(c)}\), un résidu \(r(c)\in S_{m(c)}\) et un seuil \(N(c)\), et elle s’applique à tout impair \(n\) vérifiant :
|
||||
\[
|
||||
n\equiv r(c)\pmod{2^{m(c)}}\quad\text{et}\quad n\ge N(c).
|
||||
\]
|
||||
|
||||
On dit que \(\mathcal{K}\) **couvre modulo** \(2^M\) (au-delà d’un seuil \(N^\ast\)) si :
|
||||
\[
|
||||
\forall n\in 2\mathbb{N}+1,\quad n>N^\ast\ \Longrightarrow\ \exists c\in\mathcal{K},\ \bigl(n\equiv r(c)\!\!\!\pmod{2^{m(c)}}\ \wedge\ n\ge N(c)\bigr),
|
||||
\]
|
||||
avec la contrainte \(m(c)\le M\) pour que l’applicabilité soit décidée par la classe modulo \(2^M\).
|
||||
|
||||
Dans l’instrumentation par témoins (C3 \(\to\) clauses candidates), le module \(2^{m(c)}\) est pris égal à \(2^{m_{stable}}\) où \(m_{stable}=\max(m_{\mathrm{dom}},A+1)\) (lemme 4). L’obligation de preuve associée à (H2) devient alors :
|
||||
- exhiber un \(M\) et une famille finie \(\mathcal{K}\) telle que \(m(c)\le M\) pour tout \(c\in\mathcal{K}\),
|
||||
- établir l’égalité d’ensembles au niveau des classes modulo \(2^M\) (au-delà des seuils) entre les impairs et l’union des classes définies par les clauses de \(\mathcal{K}\).
|
||||
|
||||
**Version indexée par artefacts (registre + audit fini).**
|
||||
Une matérialisation déterministe de \(\mathcal{K}_M\) et de l’audit fini de couverture sur le domaine instrumenté \(L\) est produite par :
|
||||
- script : `applications/collatz/collatz_k_scripts/collatz_build_register_K_modular.py --palier M`
|
||||
- sorties : `docs/artefacts/collatz/register_K/palier2pM/{register_K_mod2pM,audit_register_K_mod2pM,non_eligible_clauses_mod2pM,manifest_register_K_mod2pM}.{json,md}`.
|
||||
- exemple concret (palier \(2^{15}\)) :
|
||||
- `docs/artefacts/collatz/register_K/palier2p15/register_K_mod2p15.{json,md}`
|
||||
- `docs/artefacts/collatz/register_K/palier2p15/audit_register_K_mod2p15.{json,md}`
|
||||
- `docs/artefacts/collatz/register_K/palier2p15/non_eligible_clauses_mod2p15.{json,md}`
|
||||
- `docs/artefacts/collatz/register_K/palier2p15/manifest_register_K_mod2p15.{json,md}`
|
||||
|
||||
**Variante (H2′) : couverture décidée par raffinement fini de l’observabilité.**
|
||||
On fixe la projection \(\pi_M:2\mathbb{N}+1\to S_M\), \(\pi_M(n)=n\bmod 2^M\). La contrainte \(m(c)\le M\) impose une décidabilité “directe” à la granularité \(2^M\). Lorsque les clauses extraites ont typiquement \(m(c)>M\) (par exemple \(m(c)=m_{stable}=\max(M,A+1)\) avec \(A\) grand), une alternative consiste à décider l’applicabilité par un **raffinement fini** de la classe \(\pi_M(n)\) vers un module plus fin, puis appliquer une clause terminale \(D/F\).
|
||||
|
||||
### Définition 6 (Arbre de raffinement modulo \(2^M\) — domaine instrumenté)
|
||||
|
||||
**Hypothèses.**
|
||||
- \(M\ge 1\) et \(L\subset 2\mathbb{N}+1\) est un domaine fini (par exemple \(L=\mathrm{Lift}_{12\to M}(B_{12})\) dans (C3));
|
||||
- \(\mathcal{K}\) est une famille finie de clauses terminales \(D/F\), chacune indexée par \((m(c),r(c),N(c))\) comme ci-dessus, sans contrainte a priori \(m(c)\le M\).
|
||||
|
||||
**Énoncé.**
|
||||
Un **arbre de raffinement** pour une classe \(r\in S_M\) est un arbre binaire fini \(T(r)\) tel que :
|
||||
1) chaque nœud interne est étiqueté par une paire \((m,r_m)\) avec \(m\ge M\) et \(r_m\in S_m\), et a exactement deux enfants correspondant aux deux relèvements \(r_m\) et \(r_m+2^m\) dans \(S_{m+1}\);
|
||||
2) chaque feuille est étiquetée par une clause \(c\in\mathcal{K}\) telle que \(m(c)=m_\ell\) et \(r(c)=r_{m_\ell}\) (la feuille “ferme” la branche);
|
||||
3) la racine est \((M,r)\).
|
||||
|
||||
On dit qu’un tel arbre **certifie** la classe \(r\) (au-delà d’un seuil \(N^\*\)) si \(N^\*\ge \max_{\ell\in\mathrm{Leaves}(T(r))} N(c_\ell)\).
|
||||
|
||||
### Proposition 2 (Décidabilité par raffinement fini, version instrumentée)
|
||||
|
||||
**Hypothèses.**
|
||||
- hypothèses de la définition 6;
|
||||
- pour chaque \(n\in L\), il existe un arbre \(T(\pi_M(n))\) dont la branche suivie par les bits 2‑adiques de \(n\) aboutit à une feuille \(c_n\in\mathcal{K}\);
|
||||
- \(N^\*\) majore les seuils des feuilles comme ci-dessus.
|
||||
|
||||
**Énoncé.**
|
||||
Pour tout \(n\in L\) vérifiant \(n\ge N^\*\), la procédure déterministe “raffiner \(\pi_M(n)\) jusqu’à la feuille, puis appliquer la clause terminale” produit une réduction stricte au sens de (H3).
|
||||
|
||||
**Preuve.**
|
||||
Le raffinement ne fait qu’expliciter la congruence \(n\bmod 2^{m(c_n)}=r(c_n)\) le long de la branche. Comme \(n\ge N^\*\ge N(c_n)\), la clause terminale est applicable et fournit une réduction stricte (lemme 2 ou lemme 3 selon le type). \(\square\)
|
||||
|
||||
**Version indexée par artefacts (raffinement sur \(L\) au palier \(2^{15}\)).**
|
||||
Une matérialisation déterministe de chemins de raffinement (depuis \(\pi_{15}(n)\) jusqu’au module \(2^{m_{stable}}\) de la clause terminale) sur le domaine instrumenté \(L\) est produite par :
|
||||
- script : `applications/collatz/collatz_k_scripts/collatz_build_refinement_certificate_modular.py --palier 15`
|
||||
- sorties : `docs/artefacts/collatz/refinement_K/palier2p15/{refinement_certificate_mod2p15,audit_refinement_certificate_mod2p15}.{json,md}`.
|
||||
|
||||
**Version indexée par artefacts (raffinement sur \(S_M\), \(M=15\)).**
|
||||
Une matérialisation déterministe de la fermeture (ou non‑fermeture) de classes racines \(r\in S_{15}\) par raffinement fini (avec feuilles \(D/F\) extraites) est produite par :
|
||||
- script : `applications/collatz/collatz_k_scripts/collatz_build_refinement_certificate_over_Sm.py --palier 15`
|
||||
- sorties : `docs/artefacts/collatz/refinement_K/palier2p15/{refinement_certificate_Sm_mod2p15,audit_refinement_certificate_Sm_mod2p15}.{json,md}`.
|
||||
|
||||
**Version indexée par artefacts (raffinement multi‑niveaux sur \(S_{15}\to S_{16}\)).**
|
||||
Une matérialisation déterministe de la fermeture de \(S_{15}\) par raffinement sur un niveau supplémentaire (feuilles directement décidables à \(2^{15}\) et \(2^{16}\)) est produite par :
|
||||
- script : `applications/collatz/collatz_k_scripts/collatz_generate_terminal_clauses_over_Sm.py --palier 15` et `... --palier 16`
|
||||
- script : `applications/collatz/collatz_k_scripts/collatz_build_refinement_certificate_over_Sm_multilevel.py --root-palier 15 --max-palier 16`
|
||||
- sorties : `docs/artefacts/collatz/refinement_K/palier2p15/{refinement_certificate_Sm_multilevel_mod2p15_to2p16,audit_refinement_certificate_Sm_multilevel_mod2p15_to2p16}.{json,md}`.
|
||||
|
||||
**Analyse ciblée (racines ouvertes).**
|
||||
Un profil d’obstruction des racines encore ouvertes après raffinement jusqu’à \(2^{M_{\max}}\) (avec borne inférieure “première profondeur possible”) est produit par :
|
||||
- script : `applications/collatz/collatz_k_scripts/collatz_analyze_open_roots_refinement.py --root-palier 15 --max-palier M_max`
|
||||
- sorties : `docs/artefacts/collatz/refinement_K/palier2p15/open_roots_obstruction_profile_mod2p15_to2pM_max.{json,md}`.
|
||||
|
||||
**Énoncé.**
|
||||
|
||||
La conjecture de Collatz est vraie.
|
||||
@ -2327,6 +2447,32 @@ et la clause universelle est :
|
||||
\forall n,\ C(n)\ \wedge\ n\ge N_0 \Rightarrow U^{(k)}(n)<n.
|
||||
]
|
||||
|
||||
### Lemme (validité d’une clause (D) minorée, version congruentielle)
|
||||
|
||||
**Hypothèses.**
|
||||
- Un horizon \(k\ge 2\) et un palier \(2^m\).
|
||||
- Une condition \(C(n)\) de la forme :
|
||||
1) *préfixe stabilisé*: \(n \equiv r \pmod{2^m}\) impose un mot de valuations fixé de longueur \(k-1\), donc fixe \(A_{k-1}\) et \(C_{k-1}\) (par la stabilité du préfixe) ;
|
||||
2) on pose \(B_k=3C_{k-1}+2^{A_{k-1}}\), de sorte que \(3U^{(k-1)}(n)+1=(3^k n + B_k)/2^{A_{k-1}}\) ;
|
||||
3) *divisibilité*: \(n \equiv r \pmod{2^m}\) implique \(v_2(3^k n + B_k)\ge \underline A\), avec \(\underline A\le m\).
|
||||
|
||||
**Conclusion.**
|
||||
Si \(2^{\underline A}>3^k\), en posant
|
||||
\[
|
||||
N_0=\left\lfloor \frac{B_k}{2^{\underline A}-3^k}\right\rfloor +1,
|
||||
\]
|
||||
on a
|
||||
\[
|
||||
\forall n,\ C(n)\ \wedge\ n\ge N_0 \Rightarrow U^{(k)}(n)<n.
|
||||
\]
|
||||
|
||||
**Preuve.**
|
||||
Sous \(C(n)\), on a \(A(n)\ge \underline A\) et \(v_2(3^k n + B_k)\ge \underline A\), donc l’expression affine \(3^k n + B_k\) est divisible par \(2^{\underline A}\) et
|
||||
\[
|
||||
U^{(k)}(n)=\frac{3^k n + B_k}{2^{A(n)}} \le \frac{3^k n + B_k}{2^{\underline A}}.
|
||||
\]
|
||||
Si \(n\ge N_0\), alors \(B_k < (2^{\underline A}-3^k)n\), donc \((3^k n + B_k)/2^{\underline A}<n\), d’où \(U^{(k)}(n)<n\).
|
||||
|
||||
Point conceptuel
|
||||
Cette clause n’exige pas que la dernière valuation soit figée “au bit près”. Une minoration suffit. C’est précisément le mécanisme qui ferme plus tôt les sommets.
|
||||
|
||||
|
||||
@ -128,18 +128,23 @@ Pour chaque état \(E\) (mot de valuations sur \(B_{12}\) à horizon fixé), ét
|
||||
|
||||
Artefacts (H6 locale).
|
||||
- index agrégé : `docs/artefacts/collatz/local_H6_index.md`
|
||||
- répertoires par état : `docs/artefacts/collatz/local_E*_palier2p13/`, `docs/artefacts/collatz/local_E*_palier2p14/`
|
||||
- rapports d’exécution : `docs/collatz_run_report_2026-03-09_local_H6_E*_palier2p13.md`, `docs/collatz_run_report_2026-03-09_local_H6_E*_palier2p14.md`
|
||||
- répertoires par état : `docs/artefacts/collatz/local_E*_palier2p13/`, `docs/artefacts/collatz/local_E*_palier2p14/`, `docs/artefacts/collatz/local_E*_palier2p15/`
|
||||
- rapports d’exécution : `docs/collatz_run_report_2026-03-09_local_H6_E*_palier2p13.md`, `docs/collatz_run_report_2026-03-09_local_H6_E*_palier2p14.md`, `docs/collatz_run_report_2026-03-09_local_H6_E*_palier2p15.md`
|
||||
|
||||
6.3. C3 (instance locale : clôture sur Lift(\(B_{12}\)) au palier \(2^{13}\))
|
||||
Constats d’audit (index agrégé, palier \(2^{15}\)).
|
||||
Les artefacts versionnés indiquent :
|
||||
- \(\Delta m(E)=3\) pour les 60 états \(E\) (relèvement \(12\to 15\)) ;
|
||||
- \(\max_E\ t_{\max,\mathrm{used}}(E)=64\) dans la complétude par fusion.
|
||||
|
||||
6.3. C3 (instance locale : clôture sur Lift(\(B_{12}\)) au palier \(2^{m}\))
|
||||
|
||||
But.
|
||||
Sur le domaine \(L=\mathrm{Lift}_{12\to 13}(B_{12})\), exhiber pour chaque classe un témoin \(D\) (descente exacte ou frère) ou \(F\) (fusion vers un impair strictement plus petit) et fermer l’instance par validation de base finie.
|
||||
Sur le domaine \(L=\mathrm{Lift}_{12\to m}(B_{12})\) (pour un palier \(m\ge 13\)), exhiber pour chaque classe un témoin \(D\) (descente exacte ou frère) ou \(F\) (fusion vers un impair strictement plus petit) et fermer l’instance par validation de base finie.
|
||||
|
||||
Artefact déterministe (C3 local).
|
||||
- script : `applications/collatz/collatz_k_scripts/collatz_verify_c3_local_descent.py`
|
||||
- sorties versionnées : `docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent.{json,md}` et `..._palier2p<m>.{json,md}`
|
||||
- rapports d’exécution : `docs/collatz_run_report_2026-03-09_c3_local_descent.md`, `docs/collatz_run_report_2026-03-09_c3_local_descent_palier2p14.md`
|
||||
- rapports d’exécution : `docs/collatz_run_report_2026-03-09_c3_local_descent.md`, `docs/collatz_run_report_2026-03-09_c3_local_descent_palier2p14.md`, `docs/collatz_run_report_2026-03-09_c3_local_descent_palier2p15.md`
|
||||
|
||||
6.4. Verrou formel restant (au-delà de \(2^{13}\))
|
||||
|
||||
@ -150,20 +155,52 @@ La formalisation minimale de ces clauses universelles (formes D/F, seuils \(N_0/
|
||||
|
||||
6.5. Extraction déterministe de clauses universelles candidates (Option A : Lift(\(B_{12}\)))
|
||||
|
||||
À partir de l’artefact déterministe C3 (témoins locaux sur \(L=\mathrm{Lift}_{12\to 13}(B_{12})\)), une procédure de relèvement transforme chaque témoin \(D\) exact ou \(F\) en une clause candidate stabilisée au module minimal \(2^{A+1}\) où le préfixe de valuations est figé.
|
||||
À partir de l’artefact déterministe C3 (témoins locaux sur un domaine \(L=\mathrm{Lift}_{12\to m}(B_{12})\)), une procédure de relèvement transforme chaque témoin \(D\) exact ou \(F\) en une clause candidate stabilisée au module \(2^{m_{stable}}\), avec \(m_{stable}=\max(m,A+1)\), où le préfixe de valuations est figé.
|
||||
|
||||
Artefacts déterministes :
|
||||
- extraction : `applications/collatz/collatz_k_scripts/collatz_extract_universal_clauses.py`
|
||||
- vérification : `applications/collatz/collatz_k_scripts/collatz_verify_universal_clauses.py`
|
||||
- sorties versionnées : `docs/artefacts/collatz/universal_clauses/{clauses_universelles,verification_universal_clauses}.{json,md}` et `docs/artefacts/collatz/universal_clauses/palier2p14/*`
|
||||
- rapports d’exécution : `docs/collatz_run_report_2026-03-09_universal_clauses.md`, `docs/collatz_run_report_2026-03-09_universal_clauses_palier2p14.md`
|
||||
- sorties versionnées : `docs/artefacts/collatz/universal_clauses/{clauses_universelles,verification_universal_clauses}.{json,md}` et `docs/artefacts/collatz/universal_clauses/palier2p14/*`, `docs/artefacts/collatz/universal_clauses/palier2p15/*`
|
||||
- rapports d’exécution : `docs/collatz_run_report_2026-03-09_universal_clauses.md`, `docs/collatz_run_report_2026-03-09_universal_clauses_palier2p14.md`, `docs/collatz_run_report_2026-03-09_universal_clauses_palier2p15.md`
|
||||
|
||||
6.6. Protocole déterministe d’itération de palier (au-delà de \(2^{13}\))
|
||||
|
||||
Pour organiser l’itération \(2^m\to 2^{m+1}\) (C1→C2→C3) à partir des artefacts versionnés, un protocole déterministe produit un état courant (paliers certifiés, transitions C2 disponibles) et une checklist de commandes reproductibles pour un palier cible.
|
||||
|
||||
- script : `applications/collatz/collatz_k_scripts/collatz_iterate_palier_protocol.py`
|
||||
- sorties : `docs/artefacts/collatz/iteration_protocol/{iteration_protocol.json,iteration_protocol.md}`
|
||||
- sorties : `docs/artefacts/collatz/iteration_protocol/palier2p<m>/{iteration_protocol.json,iteration_protocol.md}`
|
||||
|
||||
Le vérificateur C3 est paramétrable en palier :
|
||||
- `applications/collatz/collatz_k_scripts/collatz_verify_c3_local_descent.py --palier m`
|
||||
|
||||
6.7. Clauses universelles (formes D/F) et compatibilité avec l’induction bien fondée
|
||||
|
||||
Objectif.
|
||||
Rendre explicite la forme “universelle” attendue des clauses, et l’interface minimale requise pour les utiliser dans une preuve par descente bien fondée sur \(\mathbb{N}\).
|
||||
|
||||
Clause universelle D (descente exacte).
|
||||
Une clause universelle D est indexée par \((m,k,A,C,N_0,r)\) et affirme :
|
||||
\[
|
||||
\forall n\in 2\mathbb{N}+1,\quad \bigl(n\equiv r \!\!\!\pmod{2^m}\ \wedge\ n\ge N_0\bigr)\ \Longrightarrow\ U^{(k)}(n)<n.
|
||||
\]
|
||||
Dans l’instrumentation (Option A), le paramètre \(m\) est pris égal à \(m_{stable}=\max(m_{\mathrm{domaine}},A+1)\) et le résidu \(r\) est un représentant canonique relevé au palier \(m_{stable}\) ; l’assertion à établir est que, sur la classe modulo \(2^{m_{stable}}\), le préfixe de valuations de longueur \(k\) est constant et égale le mot observé sur le témoin. Cette assertion est formalisée par le **lemme 4** de `applications/collatz/conjoncture_collatz.md`.
|
||||
|
||||
Clause universelle F (fusion).
|
||||
Une clause universelle F est indexée par \((m,t,A,C,a,y,N_F,r)\) et affirme :
|
||||
\[
|
||||
\forall n\in 2\mathbb{N}+1,\quad \bigl(n\equiv r \!\!\!\pmod{2^m}\ \wedge\ n\ge N_F\bigr)\ \Longrightarrow\ \exists m'<n,\ U(m')=U^{(t)}(n),
|
||||
\]
|
||||
où \(m'\) est une préimage courte calculable à partir de \(y:=U^{(t)}(n)\) (dans les artefacts actuels : \(a=1\) et \(m'=(2y-1)/3\)). Ici aussi, \(m=m_{stable}=\max(m_{\mathrm{domaine}},A+1)\) est choisi pour figer le préfixe de valuations d’horizon \(t\). La stabilité du préfixe au module \(2^{m_{stable}}\) est formalisée par le **lemme 4** de `applications/collatz/conjoncture_collatz.md`.
|
||||
|
||||
Compatibilité avec l’induction bien fondée.
|
||||
Une famille finie de clauses universelles \(\mathcal{K}\) est compatible avec une preuve par bon ordre si elle satisfait :
|
||||
- (I1) **Couverture** : il existe \(M\) et \(N^\ast\) tels que tout impair \(n>N^\ast\) satisfait la prémisse d’au moins une clause de \(\mathcal{K}\) via sa classe modulo \(2^M\) ;
|
||||
- (I2) **Réduction stricte** : toute clause applicable produit un entier impair strictement plus petit (descente D) ou un impair \(m'<n\) fusionné vers le même successeur accéléré (fusion F) ;
|
||||
- (I3) **Base finie** : pour tout impair \(1\le n\le N^\ast\), la trajectoire atteint \(1\).
|
||||
|
||||
Statut (au regard des artefacts).
|
||||
Les scripts d’extraction/vérification produisent des clauses candidates et vérifient la cohérence arithmétique (constantes affines, seuils, relèvements) sur le domaine instrumenté, mais (I1)–(I3) restent des obligations de preuve pour conclure globalement.
|
||||
|
||||
Point de passage “instance locale \(\to\) couverture modulo \(2^M\)”.
|
||||
La formalisation opérationnelle de (I1) (couverture modulaire au palier \(2^M\)) et la contrainte \(m(c)\le M\) pour les clauses applicables par classes modulo \(2^M\) sont précisées dans la **formalisation de (H2)** sous le Théorème 1 de `applications/collatz/conjoncture_collatz.md`.
|
||||
Une matérialisation déterministe (registre \(\mathcal{K}_M\) + audit fini de couverture sur le domaine \(L\) + table non‑éligibles + manifeste) est produite par `applications/collatz/collatz_k_scripts/collatz_build_register_K_modular.py`.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,31 @@
|
||||
**Auteur** : Équipe 4NK
|
||||
|
||||
# Vérification déterministe — C3 (clôture locale par descente/fusion)
|
||||
|
||||
## Entrées
|
||||
|
||||
- ARTEFACTS ROOT : `docs/artefacts/collatz`
|
||||
|
||||
## Domaine
|
||||
|
||||
- palier : 2^15
|
||||
- |L| (Lift(B12) à 2^15) : 1536
|
||||
- min(L) : 27, max(L) : 32767
|
||||
|
||||
## Élimination (témoins)
|
||||
|
||||
- D : 180 (k variable, A_k<=14 ; descente vérifiée : 180, cas de base : 0)
|
||||
- Fusion : 1356 (descente vérifiée : 1356, cas de base : 0)
|
||||
- max(next) : 31959
|
||||
- N* (max des seuils N0/Nf calculés) : 138
|
||||
|
||||
## Validation de base (finie)
|
||||
|
||||
- Trajectoires vérifiées jusqu’à : 32767
|
||||
- Résultat : True (toutes atteignent 1)
|
||||
|
||||
## Sorties
|
||||
|
||||
- JSON : `docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p15.json`
|
||||
- Markdown : `docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p15.md`
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,31 @@
|
||||
**Auteur** : Équipe 4NK
|
||||
|
||||
# Vérification déterministe — C3 (clôture locale par descente/fusion)
|
||||
|
||||
## Entrées
|
||||
|
||||
- ARTEFACTS ROOT : `docs/artefacts/collatz`
|
||||
|
||||
## Domaine
|
||||
|
||||
- palier : 2^16
|
||||
- |L| (Lift(B12) à 2^16) : 3072
|
||||
- min(L) : 27, max(L) : 65535
|
||||
|
||||
## Élimination (témoins)
|
||||
|
||||
- D : 360 (k variable, A_k<=14 ; descente vérifiée : 360, cas de base : 0)
|
||||
- Fusion : 2712 (descente vérifiée : 2712, cas de base : 0)
|
||||
- max(next) : 63543
|
||||
- N* (max des seuils N0/Nf calculés) : 217
|
||||
|
||||
## Validation de base (finie)
|
||||
|
||||
- Trajectoires vérifiées jusqu’à : 65535
|
||||
- Résultat : True (toutes atteignent 1)
|
||||
|
||||
## Sorties
|
||||
|
||||
- JSON : `docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p16.json`
|
||||
- Markdown : `docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p16.md`
|
||||
|
||||
@ -78,6 +78,7 @@
|
||||
"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 --c3-palier 15 --out-dir applications/collatz/out --docs-dir docs",
|
||||
"Universal_clauses_extract": "python3 applications/collatz/collatz_k_scripts/collatz_extract_universal_clauses.py --verification-json docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p15.json --output-dir docs/artefacts/collatz/universal_clauses/palier2p15",
|
||||
"Universal_clauses_verify": "python3 applications/collatz/collatz_k_scripts/collatz_verify_universal_clauses.py --verification-json docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p15.json --clauses-json docs/artefacts/collatz/universal_clauses/palier2p15/clauses_universelles.json --output-dir docs/artefacts/collatz/universal_clauses/palier2p15",
|
||||
"Universal_clauses_run_report_palier": "python3 applications/collatz/collatz_k_scripts/collatz_generate_run_report.py --profile universal_clauses_palier --universal-clauses-artefacts-dir docs/artefacts/collatz/universal_clauses/palier2p15 --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"
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,6 +51,12 @@ python3 applications/collatz/collatz_k_scripts/collatz_extract_universal_clauses
|
||||
python3 applications/collatz/collatz_k_scripts/collatz_verify_universal_clauses.py --verification-json docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p15.json --clauses-json docs/artefacts/collatz/universal_clauses/palier2p15/clauses_universelles.json --output-dir docs/artefacts/collatz/universal_clauses/palier2p15
|
||||
```
|
||||
|
||||
- **Universal_clauses_run_report_palier** :
|
||||
|
||||
```bash
|
||||
python3 applications/collatz/collatz_k_scripts/collatz_generate_run_report.py --profile universal_clauses_palier --universal-clauses-artefacts-dir docs/artefacts/collatz/universal_clauses/palier2p15 --out-dir applications/collatz/out --docs-dir docs
|
||||
```
|
||||
|
||||
- **C2_verify_projective** :
|
||||
|
||||
```bash
|
||||
|
||||
@ -0,0 +1,84 @@
|
||||
{
|
||||
"inputs": {
|
||||
"local_h6_root": "/home/ncantu/code/algo/docs/artefacts/collatz",
|
||||
"c2_verification_json": "/home/ncantu/code/algo/docs/artefacts/collatz/c2_projective/verification_c2_projective.json",
|
||||
"c3_verification_json": "/home/ncantu/code/algo/docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p15.json"
|
||||
},
|
||||
"state": {
|
||||
"c3_palier": 15,
|
||||
"c2_max_child_palier": 17,
|
||||
"target_palier": 16,
|
||||
"local_h6_states_found": 1,
|
||||
"local_h6_missing_state_ids": [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
27,
|
||||
28,
|
||||
29,
|
||||
30,
|
||||
31,
|
||||
32,
|
||||
33,
|
||||
34,
|
||||
35,
|
||||
36,
|
||||
37,
|
||||
38,
|
||||
39,
|
||||
40,
|
||||
41,
|
||||
42,
|
||||
43,
|
||||
44,
|
||||
45,
|
||||
46,
|
||||
47,
|
||||
48,
|
||||
49,
|
||||
50,
|
||||
51,
|
||||
52,
|
||||
53,
|
||||
54,
|
||||
55,
|
||||
56,
|
||||
57,
|
||||
58,
|
||||
59,
|
||||
60
|
||||
]
|
||||
},
|
||||
"commands": {
|
||||
"C1_local_H6_generate": "python3 applications/collatz/collatz_k_scripts/collatz_generate_local_h6_artefacts.py --docs-dir docs --output-root docs/artefacts/collatz --state-ids all --palier-start 16 --palier-max 16 --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 --palier 16 --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 --palier 16",
|
||||
"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 --c3-palier 16 --out-dir applications/collatz/out --docs-dir docs",
|
||||
"Universal_clauses_extract": "python3 applications/collatz/collatz_k_scripts/collatz_extract_universal_clauses.py --verification-json docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p16.json --output-dir docs/artefacts/collatz/universal_clauses/palier2p16",
|
||||
"Universal_clauses_verify": "python3 applications/collatz/collatz_k_scripts/collatz_verify_universal_clauses.py --verification-json docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p16.json --clauses-json docs/artefacts/collatz/universal_clauses/palier2p16/clauses_universelles.json --output-dir docs/artefacts/collatz/universal_clauses/palier2p16",
|
||||
"Universal_clauses_run_report_palier": "python3 applications/collatz/collatz_k_scripts/collatz_generate_run_report.py --profile universal_clauses_palier --universal-clauses-artefacts-dir docs/artefacts/collatz/universal_clauses/palier2p16 --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"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
**Auteur** : Équipe 4NK
|
||||
|
||||
# Protocole déterministe — itération de palier (C1→C2→C3)
|
||||
|
||||
## État courant (artefacts)
|
||||
|
||||
- C3 palier certifié : 2^15 (d’après `/home/ncantu/code/algo/docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p15.json`)
|
||||
- C2 transition max auditée : palier enfant 2^17 (d’après `/home/ncantu/code/algo/docs/artefacts/collatz/c2_projective/verification_c2_projective.json`)
|
||||
|
||||
## Palier cible
|
||||
|
||||
- palier cible : 2^16
|
||||
- H6 locale présente (états) : 1/60
|
||||
- états manquants : [1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]
|
||||
|
||||
## Étapes (commandes reproductibles)
|
||||
|
||||
- **C1_local_H6_generate** :
|
||||
|
||||
```bash
|
||||
python3 applications/collatz/collatz_k_scripts/collatz_generate_local_h6_artefacts.py --docs-dir docs --output-root docs/artefacts/collatz --state-ids all --palier-start 16 --palier-max 16 --t-min 9 --t-max 120 --write-index --index-path docs/artefacts/collatz/local_H6_index.md
|
||||
```
|
||||
|
||||
- **C1_local_H6_run_reports** :
|
||||
|
||||
```bash
|
||||
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 --palier 16 --index-path docs/artefacts/collatz/local_H6_index.md
|
||||
```
|
||||
|
||||
- **C3_verify_local_descent** :
|
||||
|
||||
```bash
|
||||
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 --palier 16
|
||||
```
|
||||
|
||||
- **C3_run_report_palier** :
|
||||
|
||||
```bash
|
||||
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 --c3-palier 16 --out-dir applications/collatz/out --docs-dir docs
|
||||
```
|
||||
|
||||
- **Universal_clauses_extract** :
|
||||
|
||||
```bash
|
||||
python3 applications/collatz/collatz_k_scripts/collatz_extract_universal_clauses.py --verification-json docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p16.json --output-dir docs/artefacts/collatz/universal_clauses/palier2p16
|
||||
```
|
||||
|
||||
- **Universal_clauses_verify** :
|
||||
|
||||
```bash
|
||||
python3 applications/collatz/collatz_k_scripts/collatz_verify_universal_clauses.py --verification-json docs/artefacts/collatz/c3_local_descent/verification_c3_local_descent_palier2p16.json --clauses-json docs/artefacts/collatz/universal_clauses/palier2p16/clauses_universelles.json --output-dir docs/artefacts/collatz/universal_clauses/palier2p16
|
||||
```
|
||||
|
||||
- **Universal_clauses_run_report_palier** :
|
||||
|
||||
```bash
|
||||
python3 applications/collatz/collatz_k_scripts/collatz_generate_run_report.py --profile universal_clauses_palier --universal-clauses-artefacts-dir docs/artefacts/collatz/universal_clauses/palier2p16 --out-dir applications/collatz/out --docs-dir docs
|
||||
```
|
||||
|
||||
- **C2_verify_projective** :
|
||||
|
||||
```bash
|
||||
python3 applications/collatz/collatz_k_scripts/collatz_verify_c2_projective.py --repo-root /home/ncantu/code/algo --output-dir docs/artefacts/collatz/c2_projective
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Pour `C3_verify_local_descent` : si `palier != 13`, les sorties attendues sont suffixées `..._palier2p<m>.{json,md}`.
|
||||
- Les rapports C3 par palier sont générés via le profil `c3_local_descent_palier` (nom de fichier déterministe).
|
||||
@ -0,0 +1,27 @@
|
||||
**Auteur** : Équipe 4NK
|
||||
|
||||
# Vérification H6(E10) — couverture des relèvements au palier \(2^{15}\)
|
||||
|
||||
## Objet
|
||||
|
||||
Vérifier, au sens “certifié D/F” (appartenance aux ensembles `covered` de certificats), que l’union des certificats locaux couvre le domaine des relèvements impairs.
|
||||
|
||||
## Domaine
|
||||
|
||||
- base : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p15/noyaux/noyau_E10_B12.json`
|
||||
- relevé : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p15/noyaux/noyau_Lift_E10_palier2p15.json`
|
||||
- taille : 32
|
||||
|
||||
## Certificats utilisés (local)
|
||||
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p15/certificats/certificat_D8_E10_palier2p15.json`
|
||||
- covered : 2 classes
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p15/certificats/certificat_F9to32_E10_palier2p15.json`
|
||||
- covered : 30 classes
|
||||
|
||||
## Résultat
|
||||
|
||||
- |L| = 32
|
||||
- |U| = 32
|
||||
- |L \ U| = 0
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
classe_mod_2^m,sœur,A8,palier
|
||||
5439,21823,13,15
|
||||
21823,5439,13,15
|
||||
|
@ -0,0 +1,31 @@
|
||||
horizon_t,classe_mod_2^m,m,t,a,A_t,mot_a0..,C_t,y,y_mod_3,DeltaF,Nf,preimage_m,etat_id,base_mod_4096
|
||||
9,7487,15,9,1,16,1 1 1 1 1 3 1 2 5,23843,2249,2,157242,1,1499,10,3391
|
||||
9,13631,15,9,1,15,1 1 1 1 1 3 1 5 1,38179,8189,2,58938,1,5459,10,1343
|
||||
9,17727,15,9,1,15,1 1 1 1 1 3 1 3 3,25891,10649,2,58938,1,7099,10,1343
|
||||
9,18751,15,9,1,25,1 1 1 1 1 3 1 1 15,22819,11,2,100623930,1,7,10,2367
|
||||
9,23871,15,9,1,14,1 1 1 1 1 3 1 2 3,23843,28679,2,9786,4,19119,10,3391
|
||||
9,30015,15,9,1,19,1 1 1 1 1 3 1 7 3,87331,1127,2,1533498,1,751,10,1343
|
||||
10,2367,15,10,1,17,1 1 1 1 1 3 1 1 4 3,84841,1067,2,275118,1,711,10,2367
|
||||
10,10559,15,10,1,16,1 1 1 1 1 3 1 1 3 3,76649,9515,2,78510,2,6343,10,2367
|
||||
11,20799,15,11,1,21,1 1 1 1 1 3 1 1 1 1 9,215611,1757,2,5937162,1,1171,10,319
|
||||
11,22847,15,11,1,22,1 1 1 1 1 3 1 1 2 1 9,225851,965,2,12228618,1,643,10,2367
|
||||
11,26943,15,11,1,23,1 1 1 1 1 3 1 1 3 1 9,246331,569,2,24811530,1,379,10,2367
|
||||
11,32063,15,11,1,20,1 1 1 1 1 3 1 2 2 2 5,271931,5417,2,2791434,1,3611,10,3391
|
||||
13,319,15,13,2,23,1 1 1 1 1 3 1 1 1 4 2 2 4,3116051,61,1,18788532,1,81,10,319
|
||||
13,11583,15,13,1,21,1 1 1 1 1 3 1 2 1 1 3 2 3,2574355,8807,2,3102810,1,5871,10,3391
|
||||
13,15679,15,13,1,21,1 1 1 1 1 3 1 2 2 1 2 2 3,2758675,11921,2,3102810,2,7947,10,3391
|
||||
14,1343,15,14,1,23,1 1 1 1 1 3 1 3 2 1 1 1 3 3,10534969,767,2,15599886,1,511,10,1343
|
||||
14,6463,15,14,2,24,1 1 1 1 1 3 1 1 2 1 1 4 2 4,8080441,1843,1,31199772,1,2457,10,2367
|
||||
14,9535,15,14,2,24,1 1 1 1 1 3 1 3 1 2 2 2 1 4,11640889,2719,1,31199772,1,3625,10,1343
|
||||
14,12607,15,14,2,23,1 1 1 1 1 3 1 1 1 1 1 4 2 4,6812729,7189,1,6033948,4,9585,10,319
|
||||
14,14655,15,14,1,23,1 1 1 1 1 3 1 1 2 3 1 2 2 3,9186361,8357,2,15599886,1,5571,10,2367
|
||||
14,16703,15,14,1,22,1 1 1 1 1 3 1 1 1 3 1 2 2 3,7365689,19049,2,3016974,4,12699,10,319
|
||||
17,4415,15,17,2,28,1 1 1 1 1 3 1 1 1 1 2 4 2 1 2 1 4,271524355,2125,1,288745716,3,2833,10,319
|
||||
18,3391,15,18,2,29,1 1 1 1 1 3 1 2 1 3 2 2 1 1 1 2 1 4,1053985289,2449,1,60930780,61,3265,10,3391
|
||||
18,8511,15,18,1,28,1 1 1 1 1 3 1 1 1 2 3 2 2 1 1 1 4 1,930665993,12287,2,30465390,53,8191,10,319
|
||||
19,25919,15,19,2,31,1 1 1 1 1 3 1 3 1 1 1 2 2 1 1 2 1 1 6,2393134619,14029,1,1793405076,5,18705,10,1343
|
||||
22,27967,15,22,2,38,1 1 1 1 1 3 1 2 1 1 1 1 1 1 1 1 3 1 2 4 3 6,51062787289,3193,1,699109482396,1,4257,10,3391
|
||||
26,24895,15,26,2,42,1 1 1 1 1 3 1 1 1 2 1 1 1 1 1 1 1 3 1 1 3 3 2 2 1 6,3741452025001,14389,1,3026676219996,4,19185,10,319
|
||||
27,19775,15,27,1,44,1 1 1 1 1 3 1 2 1 2 1 2 2 1 2 2 1 1 3 1 1 1 1 1 3 4 3,21620693160443,8573,2,37525363163274,1,5715,10,3391
|
||||
31,28991,15,31,1,49,1 1 1 1 1 3 1 1 1 1 1 1 2 1 2 1 1 1 1 1 1 3 1 1 3 3 3 4 1 2 3,1031536617448555,31811,2,453503067696042,4,21207,10,319
|
||||
32,31039,15,32,2,54,1 1 1 1 1 3 1 1 2 2 1 1 1 1 1 1 1 3 5 1 1 1 1 1 1 2 1 1 2 4 3 6,4080799003682113,3193,1,46631114773038588,1,4257,10,2367
|
||||
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"clauses": [
|
||||
5439,
|
||||
21823
|
||||
],
|
||||
"covered": [
|
||||
5439,
|
||||
21823
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
{
|
||||
"clauses": [
|
||||
319,
|
||||
1343,
|
||||
2367,
|
||||
3391,
|
||||
4415,
|
||||
6463,
|
||||
7487,
|
||||
8511,
|
||||
9535,
|
||||
10559,
|
||||
11583,
|
||||
12607,
|
||||
13631,
|
||||
14655,
|
||||
15679,
|
||||
16703,
|
||||
17727,
|
||||
18751,
|
||||
19775,
|
||||
20799,
|
||||
22847,
|
||||
23871,
|
||||
24895,
|
||||
25919,
|
||||
26943,
|
||||
27967,
|
||||
28991,
|
||||
30015,
|
||||
31039,
|
||||
32063
|
||||
],
|
||||
"covered": [
|
||||
319,
|
||||
1343,
|
||||
2367,
|
||||
3391,
|
||||
4415,
|
||||
6463,
|
||||
7487,
|
||||
8511,
|
||||
9535,
|
||||
10559,
|
||||
11583,
|
||||
12607,
|
||||
13631,
|
||||
14655,
|
||||
15679,
|
||||
16703,
|
||||
17727,
|
||||
18751,
|
||||
19775,
|
||||
20799,
|
||||
22847,
|
||||
23871,
|
||||
24895,
|
||||
25919,
|
||||
26943,
|
||||
27967,
|
||||
28991,
|
||||
30015,
|
||||
31039,
|
||||
32063
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
25
docs/artefacts/collatz/local_E10_palier2p15/metadata.json
Normal file
25
docs/artefacts/collatz/local_E10_palier2p15/metadata.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"state_id": 10,
|
||||
"base_palier": 12,
|
||||
"target_palier": 15,
|
||||
"delta_m": 3,
|
||||
"lift_size": 32,
|
||||
"d8": {
|
||||
"k": 8,
|
||||
"threshold_Ak": 13,
|
||||
"candidates": 2,
|
||||
"covered": 2,
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p15/certificats/certificat_D8_E10_palier2p15.json"
|
||||
},
|
||||
"fusion": {
|
||||
"t_min": 9,
|
||||
"t_max_search": 120,
|
||||
"t_max_used": 32,
|
||||
"merged_csv": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p15/candidats/candidats_F9to32_E10_palier2p15.csv",
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p15/certificats/certificat_F9to32_E10_palier2p15.json",
|
||||
"clauses": 30,
|
||||
"covered": 30
|
||||
},
|
||||
"verification_md": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p15/audits/verification_H6_E10_palier2p15.md",
|
||||
"success": true
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"noyau": [
|
||||
319,
|
||||
1343,
|
||||
2367,
|
||||
3391
|
||||
],
|
||||
"palier": 12
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
{
|
||||
"noyau": [
|
||||
319,
|
||||
1343,
|
||||
2367,
|
||||
3391,
|
||||
4415,
|
||||
5439,
|
||||
6463,
|
||||
7487,
|
||||
8511,
|
||||
9535,
|
||||
10559,
|
||||
11583,
|
||||
12607,
|
||||
13631,
|
||||
14655,
|
||||
15679,
|
||||
16703,
|
||||
17727,
|
||||
18751,
|
||||
19775,
|
||||
20799,
|
||||
21823,
|
||||
22847,
|
||||
23871,
|
||||
24895,
|
||||
25919,
|
||||
26943,
|
||||
27967,
|
||||
28991,
|
||||
30015,
|
||||
31039,
|
||||
32063
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
{
|
||||
"noyau": [
|
||||
319,
|
||||
1343,
|
||||
2367,
|
||||
3391,
|
||||
4415,
|
||||
6463,
|
||||
7487,
|
||||
8511,
|
||||
9535,
|
||||
10559,
|
||||
11583,
|
||||
12607,
|
||||
13631,
|
||||
14655,
|
||||
15679,
|
||||
16703,
|
||||
17727,
|
||||
18751,
|
||||
19775,
|
||||
20799,
|
||||
22847,
|
||||
23871,
|
||||
24895,
|
||||
25919,
|
||||
26943,
|
||||
27967,
|
||||
28991,
|
||||
30015,
|
||||
31039,
|
||||
32063
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
**Auteur** : Équipe 4NK
|
||||
|
||||
# Vérification H6(E10) — couverture des relèvements au palier \(2^{16}\)
|
||||
|
||||
## Objet
|
||||
|
||||
Vérifier, au sens “certifié D/F” (appartenance aux ensembles `covered` de certificats), que l’union des certificats locaux couvre le domaine des relèvements impairs.
|
||||
|
||||
## Domaine
|
||||
|
||||
- base : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p16/noyaux/noyau_E10_B12.json`
|
||||
- relevé : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p16/noyaux/noyau_Lift_E10_palier2p16.json`
|
||||
- taille : 64
|
||||
|
||||
## Certificats utilisés (local)
|
||||
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p16/certificats/certificat_D8_E10_palier2p16.json`
|
||||
- covered : 4 classes
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p16/certificats/certificat_F9to33_E10_palier2p16.json`
|
||||
- covered : 60 classes
|
||||
|
||||
## Résultat
|
||||
|
||||
- |L| = 64
|
||||
- |U| = 64
|
||||
- |L \ U| = 0
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
classe_mod_2^m,sœur,A8,palier
|
||||
5439,38207,13,16
|
||||
21823,54591,13,16
|
||||
38207,5439,13,16
|
||||
54591,21823,13,16
|
||||
|
@ -0,0 +1,61 @@
|
||||
horizon_t,classe_mod_2^m,m,t,a,A_t,mot_a0..,C_t,y,y_mod_3,DeltaF,Nf,preimage_m,etat_id,base_mod_4096
|
||||
9,7487,16,9,1,16,1 1 1 1 1 3 1 2 5,23843,2249,2,157242,1,1499,10,3391
|
||||
9,13631,16,9,1,15,1 1 1 1 1 3 1 5 1,38179,8189,2,58938,1,5459,10,1343
|
||||
9,17727,16,9,1,15,1 1 1 1 1 3 1 3 3,25891,10649,2,58938,1,7099,10,1343
|
||||
9,18751,16,9,1,25,1 1 1 1 1 3 1 1 15,22819,11,2,100623930,1,7,10,2367
|
||||
9,23871,16,9,1,14,1 1 1 1 1 3 1 2 3,23843,28679,2,9786,4,19119,10,3391
|
||||
9,30015,16,9,1,19,1 1 1 1 1 3 1 7 3,87331,1127,2,1533498,1,751,10,1343
|
||||
9,40255,16,9,2,15,1 1 1 1 1 3 1 2 4,23843,24181,1,19572,4,32241,10,3391
|
||||
9,46399,16,9,2,20,1 1 1 1 1 3 1 5 6,38179,871,1,3066996,1,1161,10,1343
|
||||
9,50495,16,9,1,17,1 1 1 1 1 3 1 3 5,25891,7583,2,353850,1,5055,10,1343
|
||||
9,51519,16,9,1,15,1 1 1 1 1 3 1 1 5,22819,30947,2,58938,1,20631,10,2367
|
||||
9,56639,16,9,1,14,1 1 1 1 1 3 1 2 3,23843,68045,2,9786,4,45363,10,3391
|
||||
9,62783,16,9,1,16,1 1 1 1 1 3 1 6 1,54563,18857,2,157242,1,12571,10,1343
|
||||
10,2367,16,10,1,17,1 1 1 1 1 3 1 1 4 3,84841,1067,2,275118,1,711,10,2367
|
||||
10,10559,16,10,1,16,1 1 1 1 1 3 1 1 3 3,76649,9515,2,78510,2,6343,10,2367
|
||||
10,33087,16,10,1,16,1 1 1 1 1 3 1 1 1 5,70505,29813,2,78510,1,19875,10,319
|
||||
10,34111,16,10,2,20,1 1 1 1 1 3 1 3 2 6,94057,1921,1,2909532,1,2561,10,1343
|
||||
10,42303,16,10,1,16,1 1 1 1 1 3 1 3 1 3,85865,38117,2,78510,2,25411,10,1343
|
||||
10,47423,16,10,1,17,1 1 1 1 1 3 1 1 2 5,72553,21365,2,275118,1,14243,10,2367
|
||||
10,64831,16,10,1,16,1 1 1 1 1 3 1 2 2 3,79721,58415,2,78510,2,38943,10,3391
|
||||
11,20799,16,11,1,21,1 1 1 1 1 3 1 1 1 1 9,215611,1757,2,5937162,1,1171,10,319
|
||||
11,22847,16,11,1,22,1 1 1 1 1 3 1 1 2 1 9,225851,965,2,12228618,1,643,10,2367
|
||||
11,26943,16,11,1,23,1 1 1 1 1 3 1 1 3 1 9,246331,569,2,24811530,1,379,10,2367
|
||||
11,32063,16,11,1,20,1 1 1 1 1 3 1 2 2 2 5,271931,5417,2,2791434,1,3611,10,3391
|
||||
11,35135,16,11,1,24,1 1 1 1 1 3 1 1 4 1 9,287291,371,2,49977354,1,247,10,2367
|
||||
11,36159,16,11,2,20,1 1 1 1 1 3 1 2 1 4 4,292411,6109,1,2437140,1,8145,10,3391
|
||||
11,49471,16,11,1,17,1 1 1 1 1 3 1 1 1 3 3,227899,66863,2,38922,9,44575,10,319
|
||||
11,52543,16,11,1,17,1 1 1 1 1 3 1 2 1 2 3,243259,71015,2,38922,10,47343,10,3391
|
||||
11,58687,16,11,1,17,1 1 1 1 1 3 1 3 1 1 3,273979,79319,2,38922,11,52879,10,1343
|
||||
12,57663,16,12,1,19,1 1 1 1 1 3 1 1 1 2 1 5,675505,58451,2,509982,2,38967,10,319
|
||||
12,60735,16,12,1,19,1 1 1 1 1 3 1 2 1 1 1 5,721585,61565,2,509982,2,41043,10,3391
|
||||
12,63807,16,12,1,19,1 1 1 1 1 3 1 1 2 2 2 3,767665,64679,2,509982,2,43119,10,2367
|
||||
13,319,16,13,2,23,1 1 1 1 1 3 1 1 1 4 2 2 4,3116051,61,1,18788532,1,81,10,319
|
||||
13,11583,16,13,1,21,1 1 1 1 1 3 1 2 1 1 3 2 3,2574355,8807,2,3102810,1,5871,10,3391
|
||||
13,15679,16,13,1,21,1 1 1 1 1 3 1 2 2 1 2 2 3,2758675,11921,2,3102810,2,7947,10,3391
|
||||
14,1343,16,14,1,23,1 1 1 1 1 3 1 3 2 1 1 1 3 3,10534969,767,2,15599886,1,511,10,1343
|
||||
14,6463,16,14,2,24,1 1 1 1 1 3 1 1 2 1 1 4 2 4,8080441,1843,1,31199772,1,2457,10,2367
|
||||
14,9535,16,14,2,24,1 1 1 1 1 3 1 3 1 2 2 2 1 4,11640889,2719,1,31199772,1,3625,10,1343
|
||||
14,12607,16,14,2,23,1 1 1 1 1 3 1 1 1 1 1 4 2 4,6812729,7189,1,6033948,4,9585,10,319
|
||||
14,14655,16,14,1,23,1 1 1 1 1 3 1 1 2 3 1 2 2 3,9186361,8357,2,15599886,1,5571,10,2367
|
||||
14,16703,16,14,1,22,1 1 1 1 1 3 1 1 1 3 1 2 2 3,7365689,19049,2,3016974,4,12699,10,319
|
||||
15,53567,16,15,1,24,1 1 1 1 1 3 1 1 1 1 3 1 2 1 5,20249771,45815,2,21633834,2,30543,10,319
|
||||
16,44351,16,16,1,27,1 1 1 1 1 3 1 2 1 1 2 3 1 2 1 5,82057729,14225,2,316559742,1,9483,10,3391
|
||||
16,45375,16,16,2,26,1 1 1 1 1 3 1 1 1 1 1 2 5 2 2 2,92739073,29107,1,29139708,11,38809,10,319
|
||||
16,55615,16,16,1,26,1 1 1 1 1 3 1 1 2 1 2 1 2 1 2 5,65334785,35675,2,115233150,1,23783,10,2367
|
||||
17,4415,16,17,2,28,1 1 1 1 1 3 1 1 1 1 2 4 2 1 2 1 4,271524355,2125,1,288745716,3,2833,10,319
|
||||
18,3391,16,18,2,29,1 1 1 1 1 3 1 2 1 3 2 2 1 1 1 2 1 4,1053985289,2449,1,60930780,61,3265,10,3391
|
||||
18,8511,16,18,1,28,1 1 1 1 1 3 1 1 1 2 3 2 2 1 1 1 4 1,930665993,12287,2,30465390,53,8191,10,319
|
||||
19,25919,16,19,2,31,1 1 1 1 1 3 1 3 1 1 1 2 2 1 1 2 1 1 6,2393134619,14029,1,1793405076,5,18705,10,1343
|
||||
19,43327,16,19,1,30,1 1 1 1 1 3 1 1 3 2 1 1 1 1 1 1 1 5 3,2262706715,46901,2,896702538,4,31267,10,2367
|
||||
19,48447,16,19,2,32,1 1 1 1 1 3 1 2 2 1 1 3 1 2 2 2 1 2 4,3234926107,13111,1,8235856020,2,17481,10,3391
|
||||
22,27967,16,22,2,38,1 1 1 1 1 3 1 2 1 1 1 1 1 1 1 1 3 1 2 4 3 6,51062787289,3193,1,699109482396,1,4257,10,3391
|
||||
23,37183,16,23,2,37,1 1 1 1 1 3 1 1 1 1 2 1 2 1 2 4 1 1 1 2 3 1 4,181765560971,25471,1,35744145108,17,33961,10,319
|
||||
26,24895,16,26,2,42,1 1 1 1 1 3 1 1 1 2 1 1 1 1 1 1 1 3 1 1 3 3 2 2 1 6,3741452025001,14389,1,3026676219996,4,19185,10,319
|
||||
26,59711,16,26,1,41,1 1 1 1 1 3 1 1 3 1 1 1 2 1 2 1 1 1 2 1 1 3 1 4 4 1,5831692612777,69023,2,1513338109998,7,46015,10,2367
|
||||
27,19775,16,27,1,44,1 1 1 1 1 3 1 2 1 2 1 2 2 1 2 2 1 1 3 1 1 1 1 1 3 4 3,21620693160443,8573,2,37525363163274,1,5715,10,3391
|
||||
27,39231,16,27,2,45,1 1 1 1 1 3 1 1 2 1 1 1 2 1 2 1 1 1 1 2 4 2 1 2 1 3 6,12900937813499,8503,1,75050726326548,1,11337,10,2367
|
||||
29,41279,16,29,2,47,1 1 1 1 1 3 1 1 1 2 2 3 1 1 2 1 1 2 1 2 2 1 1 3 3 1 1 2 4,193030836102611,20131,1,147690955606452,5,26841,10,319
|
||||
31,28991,16,31,1,49,1 1 1 1 1 3 1 1 1 1 1 1 2 1 2 1 1 1 1 1 1 3 1 1 3 3 3 4 1 2 3,1031536617448555,31811,2,453503067696042,4,21207,10,319
|
||||
32,31039,16,32,2,54,1 1 1 1 1 3 1 1 2 2 1 1 1 1 1 1 1 3 5 1 1 1 1 1 1 2 1 1 2 4 3 6,4080799003682113,3193,1,46631114773038588,1,4257,10,2367
|
||||
33,61759,16,33,1,52,1 1 1 1 1 3 1 1 1 1 1 1 1 2 1 1 2 5 1 1 1 1 1 2 4 1 1 2 2 1 1 4 3,9896062687217603,76235,2,2392677749000442,7,50823,10,319
|
||||
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"clauses": [
|
||||
5439,
|
||||
21823,
|
||||
38207,
|
||||
54591
|
||||
],
|
||||
"covered": [
|
||||
5439,
|
||||
21823,
|
||||
38207,
|
||||
54591
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
@ -0,0 +1,127 @@
|
||||
{
|
||||
"clauses": [
|
||||
319,
|
||||
1343,
|
||||
2367,
|
||||
3391,
|
||||
4415,
|
||||
6463,
|
||||
7487,
|
||||
8511,
|
||||
9535,
|
||||
10559,
|
||||
11583,
|
||||
12607,
|
||||
13631,
|
||||
14655,
|
||||
15679,
|
||||
16703,
|
||||
17727,
|
||||
18751,
|
||||
19775,
|
||||
20799,
|
||||
22847,
|
||||
23871,
|
||||
24895,
|
||||
25919,
|
||||
26943,
|
||||
27967,
|
||||
28991,
|
||||
30015,
|
||||
31039,
|
||||
32063,
|
||||
33087,
|
||||
34111,
|
||||
35135,
|
||||
36159,
|
||||
37183,
|
||||
39231,
|
||||
40255,
|
||||
41279,
|
||||
42303,
|
||||
43327,
|
||||
44351,
|
||||
45375,
|
||||
46399,
|
||||
47423,
|
||||
48447,
|
||||
49471,
|
||||
50495,
|
||||
51519,
|
||||
52543,
|
||||
53567,
|
||||
55615,
|
||||
56639,
|
||||
57663,
|
||||
58687,
|
||||
59711,
|
||||
60735,
|
||||
61759,
|
||||
62783,
|
||||
63807,
|
||||
64831
|
||||
],
|
||||
"covered": [
|
||||
319,
|
||||
1343,
|
||||
2367,
|
||||
3391,
|
||||
4415,
|
||||
6463,
|
||||
7487,
|
||||
8511,
|
||||
9535,
|
||||
10559,
|
||||
11583,
|
||||
12607,
|
||||
13631,
|
||||
14655,
|
||||
15679,
|
||||
16703,
|
||||
17727,
|
||||
18751,
|
||||
19775,
|
||||
20799,
|
||||
22847,
|
||||
23871,
|
||||
24895,
|
||||
25919,
|
||||
26943,
|
||||
27967,
|
||||
28991,
|
||||
30015,
|
||||
31039,
|
||||
32063,
|
||||
33087,
|
||||
34111,
|
||||
35135,
|
||||
36159,
|
||||
37183,
|
||||
39231,
|
||||
40255,
|
||||
41279,
|
||||
42303,
|
||||
43327,
|
||||
44351,
|
||||
45375,
|
||||
46399,
|
||||
47423,
|
||||
48447,
|
||||
49471,
|
||||
50495,
|
||||
51519,
|
||||
52543,
|
||||
53567,
|
||||
55615,
|
||||
56639,
|
||||
57663,
|
||||
58687,
|
||||
59711,
|
||||
60735,
|
||||
61759,
|
||||
62783,
|
||||
63807,
|
||||
64831
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
25
docs/artefacts/collatz/local_E10_palier2p16/metadata.json
Normal file
25
docs/artefacts/collatz/local_E10_palier2p16/metadata.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"state_id": 10,
|
||||
"base_palier": 12,
|
||||
"target_palier": 16,
|
||||
"delta_m": 4,
|
||||
"lift_size": 64,
|
||||
"d8": {
|
||||
"k": 8,
|
||||
"threshold_Ak": 13,
|
||||
"candidates": 4,
|
||||
"covered": 4,
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p16/certificats/certificat_D8_E10_palier2p16.json"
|
||||
},
|
||||
"fusion": {
|
||||
"t_min": 9,
|
||||
"t_max_search": 128,
|
||||
"t_max_used": 33,
|
||||
"merged_csv": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p16/candidats/candidats_F9to33_E10_palier2p16.csv",
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p16/certificats/certificat_F9to33_E10_palier2p16.json",
|
||||
"clauses": 60,
|
||||
"covered": 60
|
||||
},
|
||||
"verification_md": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E10_palier2p16/audits/verification_H6_E10_palier2p16.md",
|
||||
"success": true
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"noyau": [
|
||||
319,
|
||||
1343,
|
||||
2367,
|
||||
3391
|
||||
],
|
||||
"palier": 12
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
{
|
||||
"noyau": [
|
||||
319,
|
||||
1343,
|
||||
2367,
|
||||
3391,
|
||||
4415,
|
||||
5439,
|
||||
6463,
|
||||
7487,
|
||||
8511,
|
||||
9535,
|
||||
10559,
|
||||
11583,
|
||||
12607,
|
||||
13631,
|
||||
14655,
|
||||
15679,
|
||||
16703,
|
||||
17727,
|
||||
18751,
|
||||
19775,
|
||||
20799,
|
||||
21823,
|
||||
22847,
|
||||
23871,
|
||||
24895,
|
||||
25919,
|
||||
26943,
|
||||
27967,
|
||||
28991,
|
||||
30015,
|
||||
31039,
|
||||
32063,
|
||||
33087,
|
||||
34111,
|
||||
35135,
|
||||
36159,
|
||||
37183,
|
||||
38207,
|
||||
39231,
|
||||
40255,
|
||||
41279,
|
||||
42303,
|
||||
43327,
|
||||
44351,
|
||||
45375,
|
||||
46399,
|
||||
47423,
|
||||
48447,
|
||||
49471,
|
||||
50495,
|
||||
51519,
|
||||
52543,
|
||||
53567,
|
||||
54591,
|
||||
55615,
|
||||
56639,
|
||||
57663,
|
||||
58687,
|
||||
59711,
|
||||
60735,
|
||||
61759,
|
||||
62783,
|
||||
63807,
|
||||
64831
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
{
|
||||
"noyau": [
|
||||
319,
|
||||
1343,
|
||||
2367,
|
||||
3391,
|
||||
4415,
|
||||
6463,
|
||||
7487,
|
||||
8511,
|
||||
9535,
|
||||
10559,
|
||||
11583,
|
||||
12607,
|
||||
13631,
|
||||
14655,
|
||||
15679,
|
||||
16703,
|
||||
17727,
|
||||
18751,
|
||||
19775,
|
||||
20799,
|
||||
22847,
|
||||
23871,
|
||||
24895,
|
||||
25919,
|
||||
26943,
|
||||
27967,
|
||||
28991,
|
||||
30015,
|
||||
31039,
|
||||
32063,
|
||||
33087,
|
||||
34111,
|
||||
35135,
|
||||
36159,
|
||||
37183,
|
||||
39231,
|
||||
40255,
|
||||
41279,
|
||||
42303,
|
||||
43327,
|
||||
44351,
|
||||
45375,
|
||||
46399,
|
||||
47423,
|
||||
48447,
|
||||
49471,
|
||||
50495,
|
||||
51519,
|
||||
52543,
|
||||
53567,
|
||||
55615,
|
||||
56639,
|
||||
57663,
|
||||
58687,
|
||||
59711,
|
||||
60735,
|
||||
61759,
|
||||
62783,
|
||||
63807,
|
||||
64831
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
**Auteur** : Équipe 4NK
|
||||
|
||||
# Vérification H6(E11) — couverture des relèvements au palier \(2^{15}\)
|
||||
|
||||
## Objet
|
||||
|
||||
Vérifier, au sens “certifié D/F” (appartenance aux ensembles `covered` de certificats), que l’union des certificats locaux couvre le domaine des relèvements impairs.
|
||||
|
||||
## Domaine
|
||||
|
||||
- base : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p15/noyaux/noyau_E11_B12.json`
|
||||
- relevé : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p15/noyaux/noyau_Lift_E11_palier2p15.json`
|
||||
- taille : 32
|
||||
|
||||
## Certificats utilisés (local)
|
||||
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p15/certificats/certificat_D8_E11_palier2p15.json`
|
||||
- covered : 2 classes
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p15/certificats/certificat_F9to45_E11_palier2p15.json`
|
||||
- covered : 30 classes
|
||||
|
||||
## Résultat
|
||||
|
||||
- |L| = 32
|
||||
- |U| = 32
|
||||
- |L \ U| = 0
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
classe_mod_2^m,sœur,A8,palier
|
||||
14751,31135,13,15
|
||||
31135,14751,13,15
|
||||
|
@ -0,0 +1,31 @@
|
||||
horizon_t,classe_mod_2^m,m,t,a,A_t,mot_a0..,C_t,y,y_mod_3,DeltaF,Nf,preimage_m,etat_id,base_mod_4096
|
||||
9,415,15,9,1,16,1 1 1 1 2 1 2 2 5,23555,125,2,157242,1,83,11,415
|
||||
9,6559,15,9,1,15,1 1 1 1 2 1 2 5 1,37891,3941,2,58938,1,2627,11,2463
|
||||
9,10655,15,9,1,15,1 1 1 1 2 1 2 3 3,25603,6401,2,58938,1,4267,11,2463
|
||||
9,11679,15,9,2,18,1 1 1 1 2 1 2 1 8,22531,877,1,707700,1,1169,11,3487
|
||||
9,16799,15,9,1,14,1 1 1 1 2 1 2 2 3,23555,20183,2,9786,4,13455,11,415
|
||||
9,22943,15,9,2,18,1 1 1 1 2 1 2 7 2,87043,1723,1,707700,1,2297,11,2463
|
||||
10,3487,15,10,1,16,1 1 1 1 2 1 2 1 3 3,75785,3143,2,78510,2,2095,11,3487
|
||||
10,26015,15,10,1,16,1 1 1 1 2 1 2 1 1 5,69641,23441,2,78510,1,15627,11,1439
|
||||
10,27039,15,10,2,18,1 1 1 1 2 1 2 3 2 4,93193,6091,1,550236,1,8121,11,2463
|
||||
11,13727,15,11,2,18,1 1 1 1 2 1 2 1 1 1 6,213019,9277,1,77844,8,12369,11,1439
|
||||
11,15775,15,11,1,18,1 1 1 1 2 1 2 1 2 1 5,223259,10661,2,432138,1,7107,11,3487
|
||||
11,19871,15,11,2,18,1 1 1 1 2 1 2 1 3 1 4,243739,13429,1,77844,10,17905,11,3487
|
||||
11,24991,15,11,1,18,1 1 1 1 2 1 2 2 2 2 3,269339,16889,2,432138,1,11259,11,415
|
||||
11,28063,15,11,1,18,1 1 1 1 2 1 2 1 4 1 3,284699,18965,2,432138,1,12643,11,3487
|
||||
11,29087,15,11,2,18,1 1 1 1 2 1 2 2 1 4 2,289819,19657,1,77844,12,26209,11,415
|
||||
12,1439,15,12,1,21,1 1 1 1 2 1 2 1 1 2 3 5,716881,365,2,5228574,1,243,11,1439
|
||||
12,4511,15,12,2,20,1 1 1 1 2 1 2 2 1 1 3 4,762961,2287,1,1019964,2,3049,11,415
|
||||
12,7583,15,12,2,22,1 1 1 1 2 1 2 1 2 3 1 6,809041,961,1,10457148,1,1281,11,3487
|
||||
12,8607,15,12,2,20,1 1 1 1 2 1 2 2 2 1 2 4,824401,4363,1,1019964,3,5817,11,415
|
||||
13,2463,15,13,2,22,1 1 1 1 2 1 2 3 1 2 2 1 4,3245299,937,1,6205620,2,1249,11,2463
|
||||
14,32159,15,14,2,23,1 1 1 1 2 1 2 1 2 1 1 1 2 6,6404825,18337,1,6033948,3,24449,11,3487
|
||||
15,30111,15,15,2,25,1 1 1 1 2 1 2 1 1 1 2 1 2 4 4,20482187,12877,1,43267668,2,17169,11,1439
|
||||
16,23967,15,16,1,25,1 1 1 1 2 1 2 1 2 2 1 1 1 2 1 5,64467361,30749,2,14569854,7,20499,11,3487
|
||||
17,5535,15,17,1,27,1 1 1 1 2 1 2 1 1 1 1 4 1 1 1 2 5,187034851,5327,2,144372858,2,3551,11,1439
|
||||
17,18847,15,17,1,30,1 1 1 1 2 1 2 3 1 1 1 2 1 1 2 4 5,268062947,2267,2,2962945146,1,1511,11,2463
|
||||
18,21919,15,18,1,28,1 1 1 1 2 1 2 1 1 1 1 1 2 1 1 1 8 1,622823081,31637,2,30465390,33,21091,11,1439
|
||||
19,9631,15,19,1,30,1 1 1 1 2 1 2 1 1 3 1 2 1 1 1 4 1 2 3,2165810171,10427,2,896702538,4,6951,11,1439
|
||||
23,17823,15,23,1,36,1 1 1 1 2 1 2 1 1 2 1 1 1 1 3 1 1 2 2 3 1 3 3,147026182763,24419,2,17872072554,13,16279,11,1439
|
||||
43,12703,15,43,1,70,1 1 1 1 2 1 2 2 1 2 1 2 1 1 3 1 1 2 2 2 2 1 1 1 1 3 2 1 2 1 1 1 1 2 1 2 2 3 3 1 2 1 5,1181939181809637901211,3533,2,2885260927363159755018,1,2355,11,415
|
||||
45,20895,15,45,1,72,1 1 1 1 2 1 2 2 1 1 1 1 1 1 4 1 1 1 1 1 1 2 1 1 1 1 1 3 2 2 1 1 1 1 2 1 1 5 2 2 2 3 3 1 5,5133027175201745502323,13073,2,8258474035507268243802,1,8715,11,415
|
||||
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"clauses": [
|
||||
14751,
|
||||
31135
|
||||
],
|
||||
"covered": [
|
||||
14751,
|
||||
31135
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
{
|
||||
"clauses": [
|
||||
415,
|
||||
1439,
|
||||
2463,
|
||||
3487,
|
||||
4511,
|
||||
5535,
|
||||
6559,
|
||||
7583,
|
||||
8607,
|
||||
9631,
|
||||
10655,
|
||||
11679,
|
||||
12703,
|
||||
13727,
|
||||
15775,
|
||||
16799,
|
||||
17823,
|
||||
18847,
|
||||
19871,
|
||||
20895,
|
||||
21919,
|
||||
22943,
|
||||
23967,
|
||||
24991,
|
||||
26015,
|
||||
27039,
|
||||
28063,
|
||||
29087,
|
||||
30111,
|
||||
32159
|
||||
],
|
||||
"covered": [
|
||||
415,
|
||||
1439,
|
||||
2463,
|
||||
3487,
|
||||
4511,
|
||||
5535,
|
||||
6559,
|
||||
7583,
|
||||
8607,
|
||||
9631,
|
||||
10655,
|
||||
11679,
|
||||
12703,
|
||||
13727,
|
||||
15775,
|
||||
16799,
|
||||
17823,
|
||||
18847,
|
||||
19871,
|
||||
20895,
|
||||
21919,
|
||||
22943,
|
||||
23967,
|
||||
24991,
|
||||
26015,
|
||||
27039,
|
||||
28063,
|
||||
29087,
|
||||
30111,
|
||||
32159
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
25
docs/artefacts/collatz/local_E11_palier2p15/metadata.json
Normal file
25
docs/artefacts/collatz/local_E11_palier2p15/metadata.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"state_id": 11,
|
||||
"base_palier": 12,
|
||||
"target_palier": 15,
|
||||
"delta_m": 3,
|
||||
"lift_size": 32,
|
||||
"d8": {
|
||||
"k": 8,
|
||||
"threshold_Ak": 13,
|
||||
"candidates": 2,
|
||||
"covered": 2,
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p15/certificats/certificat_D8_E11_palier2p15.json"
|
||||
},
|
||||
"fusion": {
|
||||
"t_min": 9,
|
||||
"t_max_search": 120,
|
||||
"t_max_used": 45,
|
||||
"merged_csv": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p15/candidats/candidats_F9to45_E11_palier2p15.csv",
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p15/certificats/certificat_F9to45_E11_palier2p15.json",
|
||||
"clauses": 30,
|
||||
"covered": 30
|
||||
},
|
||||
"verification_md": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p15/audits/verification_H6_E11_palier2p15.md",
|
||||
"success": true
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"noyau": [
|
||||
415,
|
||||
1439,
|
||||
2463,
|
||||
3487
|
||||
],
|
||||
"palier": 12
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
{
|
||||
"noyau": [
|
||||
415,
|
||||
1439,
|
||||
2463,
|
||||
3487,
|
||||
4511,
|
||||
5535,
|
||||
6559,
|
||||
7583,
|
||||
8607,
|
||||
9631,
|
||||
10655,
|
||||
11679,
|
||||
12703,
|
||||
13727,
|
||||
14751,
|
||||
15775,
|
||||
16799,
|
||||
17823,
|
||||
18847,
|
||||
19871,
|
||||
20895,
|
||||
21919,
|
||||
22943,
|
||||
23967,
|
||||
24991,
|
||||
26015,
|
||||
27039,
|
||||
28063,
|
||||
29087,
|
||||
30111,
|
||||
31135,
|
||||
32159
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
{
|
||||
"noyau": [
|
||||
415,
|
||||
1439,
|
||||
2463,
|
||||
3487,
|
||||
4511,
|
||||
5535,
|
||||
6559,
|
||||
7583,
|
||||
8607,
|
||||
9631,
|
||||
10655,
|
||||
11679,
|
||||
12703,
|
||||
13727,
|
||||
15775,
|
||||
16799,
|
||||
17823,
|
||||
18847,
|
||||
19871,
|
||||
20895,
|
||||
21919,
|
||||
22943,
|
||||
23967,
|
||||
24991,
|
||||
26015,
|
||||
27039,
|
||||
28063,
|
||||
29087,
|
||||
30111,
|
||||
32159
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
**Auteur** : Équipe 4NK
|
||||
|
||||
# Vérification H6(E11) — couverture des relèvements au palier \(2^{16}\)
|
||||
|
||||
## Objet
|
||||
|
||||
Vérifier, au sens “certifié D/F” (appartenance aux ensembles `covered` de certificats), que l’union des certificats locaux couvre le domaine des relèvements impairs.
|
||||
|
||||
## Domaine
|
||||
|
||||
- base : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p16/noyaux/noyau_E11_B12.json`
|
||||
- relevé : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p16/noyaux/noyau_Lift_E11_palier2p16.json`
|
||||
- taille : 64
|
||||
|
||||
## Certificats utilisés (local)
|
||||
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p16/certificats/certificat_D8_E11_palier2p16.json`
|
||||
- covered : 4 classes
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p16/certificats/certificat_F9to45_E11_palier2p16.json`
|
||||
- covered : 60 classes
|
||||
|
||||
## Résultat
|
||||
|
||||
- |L| = 64
|
||||
- |U| = 64
|
||||
- |L \ U| = 0
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
classe_mod_2^m,sœur,A8,palier
|
||||
14751,47519,13,16
|
||||
31135,63903,13,16
|
||||
47519,14751,13,16
|
||||
63903,31135,13,16
|
||||
|
@ -0,0 +1,61 @@
|
||||
horizon_t,classe_mod_2^m,m,t,a,A_t,mot_a0..,C_t,y,y_mod_3,DeltaF,Nf,preimage_m,etat_id,base_mod_4096
|
||||
9,415,16,9,1,16,1 1 1 1 2 1 2 2 5,23555,125,2,157242,1,83,11,415
|
||||
9,6559,16,9,1,15,1 1 1 1 2 1 2 5 1,37891,3941,2,58938,1,2627,11,2463
|
||||
9,10655,16,9,1,15,1 1 1 1 2 1 2 3 3,25603,6401,2,58938,1,4267,11,2463
|
||||
9,11679,16,9,2,18,1 1 1 1 2 1 2 1 8,22531,877,1,707700,1,1169,11,3487
|
||||
9,16799,16,9,1,14,1 1 1 1 2 1 2 2 3,23555,20183,2,9786,4,13455,11,415
|
||||
9,22943,16,9,2,18,1 1 1 1 2 1 2 7 2,87043,1723,1,707700,1,2297,11,2463
|
||||
9,33183,16,9,2,15,1 1 1 1 2 1 2 2 4,23555,19933,1,19572,4,26577,11,415
|
||||
9,39327,16,9,2,18,1 1 1 1 2 1 2 5 4,37891,2953,1,707700,1,3937,11,2463
|
||||
9,43423,16,9,1,17,1 1 1 1 2 1 2 3 5,25603,6521,2,353850,1,4347,11,2463
|
||||
9,44447,16,9,1,15,1 1 1 1 2 1 2 1 5,22531,26699,2,58938,1,17799,11,3487
|
||||
9,49567,16,9,1,14,1 1 1 1 2 1 2 2 3,23555,59549,2,9786,4,39699,11,415
|
||||
9,55711,16,9,1,16,1 1 1 1 2 1 2 6 1,54275,16733,2,157242,1,11155,11,2463
|
||||
10,3487,16,10,1,16,1 1 1 1 2 1 2 1 3 3,75785,3143,2,78510,2,2095,11,3487
|
||||
10,26015,16,10,1,16,1 1 1 1 2 1 2 1 1 5,69641,23441,2,78510,1,15627,11,1439
|
||||
10,27039,16,10,2,18,1 1 1 1 2 1 2 3 2 4,93193,6091,1,550236,1,8121,11,2463
|
||||
10,35231,16,10,1,16,1 1 1 1 2 1 2 3 1 3,85001,31745,2,78510,2,21163,11,2463
|
||||
10,40351,16,10,1,17,1 1 1 1 2 1 2 1 2 5,71689,18179,2,275118,1,12119,11,3487
|
||||
10,57759,16,10,1,16,1 1 1 1 2 1 2 2 2 3,78857,52043,2,78510,2,34695,11,415
|
||||
11,13727,16,11,2,18,1 1 1 1 2 1 2 1 1 1 6,213019,9277,1,77844,8,12369,11,1439
|
||||
11,15775,16,11,1,18,1 1 1 1 2 1 2 1 2 1 5,223259,10661,2,432138,1,7107,11,3487
|
||||
11,19871,16,11,2,18,1 1 1 1 2 1 2 1 3 1 4,243739,13429,1,77844,10,17905,11,3487
|
||||
11,24991,16,11,1,18,1 1 1 1 2 1 2 2 2 2 3,269339,16889,2,432138,1,11259,11,415
|
||||
11,28063,16,11,1,18,1 1 1 1 2 1 2 1 4 1 3,284699,18965,2,432138,1,12643,11,3487
|
||||
11,29087,16,11,2,18,1 1 1 1 2 1 2 2 1 4 2,289819,19657,1,77844,12,26209,11,415
|
||||
11,42399,16,11,1,17,1 1 1 1 2 1 2 1 1 3 3,225307,57305,2,38922,9,38203,11,1439
|
||||
11,45471,16,11,1,17,1 1 1 1 2 1 2 2 1 2 3,240667,61457,2,38922,9,40971,11,415
|
||||
11,51615,16,11,1,17,1 1 1 1 2 1 2 3 1 1 3,271387,69761,2,38922,11,46507,11,2463
|
||||
11,60831,16,11,1,17,1 1 1 1 2 1 2 1 4 2 1,317467,82217,2,38922,13,54811,11,3487
|
||||
12,1439,16,12,1,21,1 1 1 1 2 1 2 1 1 2 3 5,716881,365,2,5228574,1,243,11,1439
|
||||
12,4511,16,12,2,20,1 1 1 1 2 1 2 2 1 1 3 4,762961,2287,1,1019964,2,3049,11,415
|
||||
12,7583,16,12,2,22,1 1 1 1 2 1 2 1 2 3 1 6,809041,961,1,10457148,1,1281,11,3487
|
||||
12,8607,16,12,2,20,1 1 1 1 2 1 2 2 2 1 2 4,824401,4363,1,1019964,3,5817,11,415
|
||||
13,2463,16,13,2,22,1 1 1 1 2 1 2 3 1 2 2 1 4,3245299,937,1,6205620,2,1249,11,2463
|
||||
13,37279,16,13,1,22,1 1 1 1 2 1 2 2 1 1 2 4 3,2714867,14171,2,9394266,1,9447,11,415
|
||||
13,41375,16,13,1,26,1 1 1 1 2 1 2 2 2 1 1 4 7,2899187,983,2,198137946,1,655,11,415
|
||||
13,46495,16,13,1,23,1 1 1 1 2 1 2 1 1 1 3 1 7,2081011,8837,2,21977178,1,5891,11,1439
|
||||
13,48543,16,13,1,21,1 1 1 1 2 1 2 1 2 1 2 1 5,2173171,36905,2,3102810,1,24603,11,3487
|
||||
13,50591,16,13,2,22,1 1 1 1 2 1 2 1 1 2 1 4 4,2265331,19231,1,6205620,1,25641,11,1439
|
||||
13,52639,16,13,1,21,1 1 1 1 2 1 2 1 3 1 1 1 5,2357491,40019,2,3102810,1,26679,11,3487
|
||||
13,56735,16,13,1,21,1 1 1 1 2 1 2 1 2 2 2 2 3,2541811,43133,2,3102810,1,28755,11,3487
|
||||
13,58783,16,13,2,22,1 1 1 1 2 1 2 1 1 4 1 2 4,2633971,22345,1,6205620,2,29793,11,1439
|
||||
14,32159,16,14,2,23,1 1 1 1 2 1 2 1 2 1 1 1 2 6,6404825,18337,1,6033948,3,24449,11,3487
|
||||
14,34207,16,14,1,23,1 1 1 1 2 1 2 1 1 2 2 4 1 3,8778457,19505,2,15599886,1,13003,11,1439
|
||||
14,59807,16,14,1,24,1 1 1 1 2 1 2 3 2 1 2 2 2 3,13283033,17051,2,40765710,1,11367,11,2463
|
||||
15,30111,16,15,2,25,1 1 1 1 2 1 2 1 1 1 2 1 2 4 4,20482187,12877,1,43267668,2,17169,11,1439
|
||||
15,61855,16,15,2,27,1 1 1 1 2 1 2 2 1 3 1 2 2 1 6,30192779,6613,1,345257556,1,8817,11,415
|
||||
16,23967,16,16,1,25,1 1 1 1 2 1 2 1 2 2 1 1 1 2 1 5,64467361,30749,2,14569854,7,20499,11,3487
|
||||
16,36255,16,16,2,26,1 1 1 1 2 1 2 1 3 2 1 1 3 1 1 4,91980193,23257,1,29139708,11,31009,11,3487
|
||||
16,62879,16,16,1,25,1 1 1 1 2 1 2 1 1 1 2 2 2 3 1 3,67705249,80669,2,14569854,7,53779,11,1439
|
||||
16,64927,16,16,1,25,1 1 1 1 2 1 2 1 2 1 1 2 2 4 2 1,89067937,83297,2,14569854,10,55531,11,3487
|
||||
17,5535,16,17,1,27,1 1 1 1 2 1 2 1 1 1 1 4 1 1 1 2 5,187034851,5327,2,144372858,2,3551,11,1439
|
||||
17,18847,16,17,1,30,1 1 1 1 2 1 2 3 1 1 1 2 1 1 2 4 5,268062947,2267,2,2962945146,1,1511,11,2463
|
||||
17,53663,16,17,1,27,1 1 1 1 2 1 2 2 1 1 1 4 2 1 2 1 3,283818211,51635,2,144372858,4,34423,11,415
|
||||
18,21919,16,18,1,28,1 1 1 1 2 1 2 1 1 1 1 1 2 1 1 1 8 1,622823081,31637,2,30465390,33,21091,11,1439
|
||||
19,9631,16,19,1,30,1 1 1 1 2 1 2 1 1 3 1 2 1 1 1 4 1 2 3,2165810171,10427,2,896702538,4,6951,11,1439
|
||||
20,54687,16,20,1,33,1 1 1 1 2 1 2 1 1 1 1 1 1 2 5 1 3 1 1 5,6179470321,22199,2,18796234974,1,14799,11,1439
|
||||
23,17823,16,23,1,36,1 1 1 1 2 1 2 1 1 2 1 1 1 1 3 1 1 2 2 3 1 3 3,147026182763,24419,2,17872072554,13,16279,11,1439
|
||||
41,38303,16,41,1,66,1 1 1 1 2 1 2 1 1 1 1 2 3 2 2 2 2 1 1 1 2 1 1 4 1 2 1 2 2 1 1 1 1 3 1 2 1 1 1 1 7,131215907988807801731,18935,2,148414936130173046586,2,12623,11,1439
|
||||
43,12703,16,43,1,70,1 1 1 1 2 1 2 2 1 2 1 2 1 1 3 1 1 2 2 2 2 1 1 1 1 3 2 1 2 1 1 1 1 2 1 2 2 3 3 1 2 1 5,1181939181809637901211,3533,2,2885260927363159755018,1,2355,11,415
|
||||
45,20895,16,45,1,72,1 1 1 1 2 1 2 2 1 1 1 1 1 1 4 1 1 1 1 1 1 2 1 1 1 1 1 3 2 2 1 1 1 1 2 1 1 5 2 2 2 3 3 1 5,5133027175201745502323,13073,2,8258474035507268243802,1,8715,11,415
|
||||
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"clauses": [
|
||||
14751,
|
||||
31135,
|
||||
47519,
|
||||
63903
|
||||
],
|
||||
"covered": [
|
||||
14751,
|
||||
31135,
|
||||
47519,
|
||||
63903
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
@ -0,0 +1,127 @@
|
||||
{
|
||||
"clauses": [
|
||||
415,
|
||||
1439,
|
||||
2463,
|
||||
3487,
|
||||
4511,
|
||||
5535,
|
||||
6559,
|
||||
7583,
|
||||
8607,
|
||||
9631,
|
||||
10655,
|
||||
11679,
|
||||
12703,
|
||||
13727,
|
||||
15775,
|
||||
16799,
|
||||
17823,
|
||||
18847,
|
||||
19871,
|
||||
20895,
|
||||
21919,
|
||||
22943,
|
||||
23967,
|
||||
24991,
|
||||
26015,
|
||||
27039,
|
||||
28063,
|
||||
29087,
|
||||
30111,
|
||||
32159,
|
||||
33183,
|
||||
34207,
|
||||
35231,
|
||||
36255,
|
||||
37279,
|
||||
38303,
|
||||
39327,
|
||||
40351,
|
||||
41375,
|
||||
42399,
|
||||
43423,
|
||||
44447,
|
||||
45471,
|
||||
46495,
|
||||
48543,
|
||||
49567,
|
||||
50591,
|
||||
51615,
|
||||
52639,
|
||||
53663,
|
||||
54687,
|
||||
55711,
|
||||
56735,
|
||||
57759,
|
||||
58783,
|
||||
59807,
|
||||
60831,
|
||||
61855,
|
||||
62879,
|
||||
64927
|
||||
],
|
||||
"covered": [
|
||||
415,
|
||||
1439,
|
||||
2463,
|
||||
3487,
|
||||
4511,
|
||||
5535,
|
||||
6559,
|
||||
7583,
|
||||
8607,
|
||||
9631,
|
||||
10655,
|
||||
11679,
|
||||
12703,
|
||||
13727,
|
||||
15775,
|
||||
16799,
|
||||
17823,
|
||||
18847,
|
||||
19871,
|
||||
20895,
|
||||
21919,
|
||||
22943,
|
||||
23967,
|
||||
24991,
|
||||
26015,
|
||||
27039,
|
||||
28063,
|
||||
29087,
|
||||
30111,
|
||||
32159,
|
||||
33183,
|
||||
34207,
|
||||
35231,
|
||||
36255,
|
||||
37279,
|
||||
38303,
|
||||
39327,
|
||||
40351,
|
||||
41375,
|
||||
42399,
|
||||
43423,
|
||||
44447,
|
||||
45471,
|
||||
46495,
|
||||
48543,
|
||||
49567,
|
||||
50591,
|
||||
51615,
|
||||
52639,
|
||||
53663,
|
||||
54687,
|
||||
55711,
|
||||
56735,
|
||||
57759,
|
||||
58783,
|
||||
59807,
|
||||
60831,
|
||||
61855,
|
||||
62879,
|
||||
64927
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
25
docs/artefacts/collatz/local_E11_palier2p16/metadata.json
Normal file
25
docs/artefacts/collatz/local_E11_palier2p16/metadata.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"state_id": 11,
|
||||
"base_palier": 12,
|
||||
"target_palier": 16,
|
||||
"delta_m": 4,
|
||||
"lift_size": 64,
|
||||
"d8": {
|
||||
"k": 8,
|
||||
"threshold_Ak": 13,
|
||||
"candidates": 4,
|
||||
"covered": 4,
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p16/certificats/certificat_D8_E11_palier2p16.json"
|
||||
},
|
||||
"fusion": {
|
||||
"t_min": 9,
|
||||
"t_max_search": 128,
|
||||
"t_max_used": 45,
|
||||
"merged_csv": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p16/candidats/candidats_F9to45_E11_palier2p16.csv",
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p16/certificats/certificat_F9to45_E11_palier2p16.json",
|
||||
"clauses": 60,
|
||||
"covered": 60
|
||||
},
|
||||
"verification_md": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E11_palier2p16/audits/verification_H6_E11_palier2p16.md",
|
||||
"success": true
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"noyau": [
|
||||
415,
|
||||
1439,
|
||||
2463,
|
||||
3487
|
||||
],
|
||||
"palier": 12
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
{
|
||||
"noyau": [
|
||||
415,
|
||||
1439,
|
||||
2463,
|
||||
3487,
|
||||
4511,
|
||||
5535,
|
||||
6559,
|
||||
7583,
|
||||
8607,
|
||||
9631,
|
||||
10655,
|
||||
11679,
|
||||
12703,
|
||||
13727,
|
||||
14751,
|
||||
15775,
|
||||
16799,
|
||||
17823,
|
||||
18847,
|
||||
19871,
|
||||
20895,
|
||||
21919,
|
||||
22943,
|
||||
23967,
|
||||
24991,
|
||||
26015,
|
||||
27039,
|
||||
28063,
|
||||
29087,
|
||||
30111,
|
||||
31135,
|
||||
32159,
|
||||
33183,
|
||||
34207,
|
||||
35231,
|
||||
36255,
|
||||
37279,
|
||||
38303,
|
||||
39327,
|
||||
40351,
|
||||
41375,
|
||||
42399,
|
||||
43423,
|
||||
44447,
|
||||
45471,
|
||||
46495,
|
||||
47519,
|
||||
48543,
|
||||
49567,
|
||||
50591,
|
||||
51615,
|
||||
52639,
|
||||
53663,
|
||||
54687,
|
||||
55711,
|
||||
56735,
|
||||
57759,
|
||||
58783,
|
||||
59807,
|
||||
60831,
|
||||
61855,
|
||||
62879,
|
||||
63903,
|
||||
64927
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
{
|
||||
"noyau": [
|
||||
415,
|
||||
1439,
|
||||
2463,
|
||||
3487,
|
||||
4511,
|
||||
5535,
|
||||
6559,
|
||||
7583,
|
||||
8607,
|
||||
9631,
|
||||
10655,
|
||||
11679,
|
||||
12703,
|
||||
13727,
|
||||
15775,
|
||||
16799,
|
||||
17823,
|
||||
18847,
|
||||
19871,
|
||||
20895,
|
||||
21919,
|
||||
22943,
|
||||
23967,
|
||||
24991,
|
||||
26015,
|
||||
27039,
|
||||
28063,
|
||||
29087,
|
||||
30111,
|
||||
32159,
|
||||
33183,
|
||||
34207,
|
||||
35231,
|
||||
36255,
|
||||
37279,
|
||||
38303,
|
||||
39327,
|
||||
40351,
|
||||
41375,
|
||||
42399,
|
||||
43423,
|
||||
44447,
|
||||
45471,
|
||||
46495,
|
||||
48543,
|
||||
49567,
|
||||
50591,
|
||||
51615,
|
||||
52639,
|
||||
53663,
|
||||
54687,
|
||||
55711,
|
||||
56735,
|
||||
57759,
|
||||
58783,
|
||||
59807,
|
||||
60831,
|
||||
61855,
|
||||
62879,
|
||||
64927
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
**Auteur** : Équipe 4NK
|
||||
|
||||
# Vérification H6(E12) — couverture des relèvements au palier \(2^{15}\)
|
||||
|
||||
## Objet
|
||||
|
||||
Vérifier, au sens “certifié D/F” (appartenance aux ensembles `covered` de certificats), que l’union des certificats locaux couvre le domaine des relèvements impairs.
|
||||
|
||||
## Domaine
|
||||
|
||||
- base : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p15/noyaux/noyau_E12_B12.json`
|
||||
- relevé : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p15/noyaux/noyau_Lift_E12_palier2p15.json`
|
||||
- taille : 32
|
||||
|
||||
## Certificats utilisés (local)
|
||||
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p15/certificats/certificat_D8_E12_palier2p15.json`
|
||||
- covered : 2 classes
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p15/certificats/certificat_F9to51_E12_palier2p15.json`
|
||||
- covered : 30 classes
|
||||
|
||||
## Résultat
|
||||
|
||||
- |L| = 32
|
||||
- |U| = 32
|
||||
- |L \ U| = 0
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
classe_mod_2^m,sœur,A8,palier
|
||||
10271,26655,13,15
|
||||
26655,10271,13,15
|
||||
|
@ -0,0 +1,31 @@
|
||||
horizon_t,classe_mod_2^m,m,t,a,A_t,mot_a0..,C_t,y,y_mod_3,DeltaF,Nf,preimage_m,etat_id,base_mod_4096
|
||||
9,2079,15,9,2,16,1 1 1 1 2 2 1 5 2,39043,625,1,117876,1,833,12,2079
|
||||
9,6175,15,9,2,16,1 1 1 1 2 2 1 3 4,26755,1855,1,117876,1,2473,12,2079
|
||||
9,7199,15,9,1,15,1 1 1 1 2 2 1 1 5,23683,4325,2,58938,1,2883,12,3103
|
||||
9,12319,15,9,1,14,1 1 1 1 2 2 1 2 3,24707,14801,2,9786,4,9867,12,31
|
||||
9,18463,15,9,2,17,1 1 1 1 2 2 1 6 2,55427,2773,1,314484,1,3697,12,2079
|
||||
9,28703,15,9,1,16,1 1 1 1 2 2 1 2 5,24707,8621,2,157242,1,5747,12,31
|
||||
10,20511,15,10,2,17,1 1 1 1 2 2 1 2 2 4,82313,9241,1,157020,2,12321,12,31
|
||||
10,23583,15,10,1,17,1 1 1 1 2 2 1 1 4 3,87433,10625,2,275118,1,7083,12,3103
|
||||
10,31775,15,10,1,16,1 1 1 1 2 2 1 1 3 3,79241,28631,2,78510,2,19087,12,3103
|
||||
11,3103,15,11,1,19,1 1 1 1 2 2 1 1 2 4 3,290971,1049,2,1218570,1,699,12,3103
|
||||
11,19487,15,11,1,17,1 1 1 1 2 2 1 1 2 2 3,241819,26339,2,38922,10,17559,12,3103
|
||||
12,25631,15,12,2,20,1 1 1 1 2 2 1 1 1 1 2 6,686545,12991,1,1019964,2,17321,12,1055
|
||||
12,27679,15,12,2,20,1 1 1 1 2 2 1 1 2 1 1 6,717265,14029,1,1019964,2,18705,12,3103
|
||||
12,29727,15,12,2,20,1 1 1 1 2 2 1 1 1 2 3 4,747985,15067,1,1019964,2,20089,12,1055
|
||||
13,9247,15,13,1,21,1 1 1 1 2 2 1 1 1 1 3 3 3,2370931,7031,2,3102810,1,4687,12,1055
|
||||
13,11295,15,13,1,23,1 1 1 1 2 2 1 1 2 1 2 3 5,2463091,2147,2,21977178,1,1431,12,3103
|
||||
13,15391,15,13,2,22,1 1 1 1 2 2 1 1 3 1 1 3 4,2647411,5851,1,6205620,2,7801,12,3103
|
||||
13,21535,15,13,1,21,1 1 1 1 2 2 1 1 1 4 2 1 3,2923891,16373,2,3102810,2,10915,12,1055
|
||||
16,8223,15,16,1,28,1 1 1 1 2 2 1 2 1 2 2 1 1 4 1 5,93179681,1319,2,719212926,1,879,12,31
|
||||
16,13343,15,16,2,30,1 1 1 1 2 2 1 1 1 2 1 2 1 3 4 6,79477537,535,1,3049038588,1,713,12,1055
|
||||
16,14367,15,16,2,26,1 1 1 1 2 2 1 3 1 1 2 1 1 3 1 4,90158881,9217,1,29139708,11,12289,12,2079
|
||||
17,16415,15,17,2,29,1 1 1 1 2 2 1 2 1 1 1 2 1 4 2 2 4,267455843,3949,1,1094052084,1,5265,12,31
|
||||
21,5151,15,21,1,33,1 1 1 1 2 2 1 1 1 3 2 1 1 2 1 1 1 3 1 3 3,20560216147,6275,2,4849097370,7,4183,12,1055
|
||||
21,17439,15,21,1,34,1 1 1 1 2 2 1 1 1 1 1 1 1 1 2 2 2 2 3 2 5,14931357779,10619,2,30618901146,1,7079,12,1055
|
||||
21,30751,15,21,1,33,1 1 1 1 2 2 1 3 1 2 2 1 2 1 1 2 1 2 1 4 1,35319059539,37451,2,4849097370,13,24967,12,2079
|
||||
25,24607,15,25,1,40,1 1 1 1 2 2 1 2 1 3 2 1 2 2 1 1 1 1 2 1 2 1 4 1 3,3007208207939,18965,2,1603957664442,4,12643,12,31
|
||||
26,4127,15,26,1,42,1 1 1 1 2 2 1 2 2 1 1 1 1 1 2 2 4 2 1 1 2 2 1 1 3 3,7856748491465,2387,2,8110407876654,2,1591,12,31
|
||||
35,31,15,35,1,56,1 1 1 1 2 2 1 2 1 1 2 1 1 1 2 3 1 1 2 1 2 1 1 1 1 1 3 1 1 1 4 2 2 4 3,106346764803351611,23,2,116109691915784394,2,15,12,31
|
||||
50,1055,15,50,2,82,1 1 1 1 2 2 1 1 1 1 1 2 1 2 2 1 1 3 4 1 1 1 2 1 1 1 1 2 1 1 2 1 1 3 2 3 1 1 2 1 1 1 5 1 1 1 1 4 2 6,1823037703082640562865833,157,1,11635517884608139741393116,1,209,12,1055
|
||||
51,22559,15,51,1,82,1 1 1 1 2 2 1 3 2 1 1 1 1 3 1 1 1 1 1 1 1 4 3 2 1 2 1 1 1 1 1 2 1 2 2 1 2 1 1 1 1 1 1 4 4 2 1 3 1 1 5,8800132208126656285308923,10049,2,10199721909224434563852618,2,6699,12,2079
|
||||
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"clauses": [
|
||||
10271,
|
||||
26655
|
||||
],
|
||||
"covered": [
|
||||
10271,
|
||||
26655
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
{
|
||||
"clauses": [
|
||||
31,
|
||||
1055,
|
||||
2079,
|
||||
3103,
|
||||
4127,
|
||||
5151,
|
||||
6175,
|
||||
7199,
|
||||
8223,
|
||||
9247,
|
||||
11295,
|
||||
12319,
|
||||
13343,
|
||||
14367,
|
||||
15391,
|
||||
16415,
|
||||
17439,
|
||||
18463,
|
||||
19487,
|
||||
20511,
|
||||
21535,
|
||||
22559,
|
||||
23583,
|
||||
24607,
|
||||
25631,
|
||||
27679,
|
||||
28703,
|
||||
29727,
|
||||
30751,
|
||||
31775
|
||||
],
|
||||
"covered": [
|
||||
31,
|
||||
1055,
|
||||
2079,
|
||||
3103,
|
||||
4127,
|
||||
5151,
|
||||
6175,
|
||||
7199,
|
||||
8223,
|
||||
9247,
|
||||
11295,
|
||||
12319,
|
||||
13343,
|
||||
14367,
|
||||
15391,
|
||||
16415,
|
||||
17439,
|
||||
18463,
|
||||
19487,
|
||||
20511,
|
||||
21535,
|
||||
22559,
|
||||
23583,
|
||||
24607,
|
||||
25631,
|
||||
27679,
|
||||
28703,
|
||||
29727,
|
||||
30751,
|
||||
31775
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
25
docs/artefacts/collatz/local_E12_palier2p15/metadata.json
Normal file
25
docs/artefacts/collatz/local_E12_palier2p15/metadata.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"state_id": 12,
|
||||
"base_palier": 12,
|
||||
"target_palier": 15,
|
||||
"delta_m": 3,
|
||||
"lift_size": 32,
|
||||
"d8": {
|
||||
"k": 8,
|
||||
"threshold_Ak": 13,
|
||||
"candidates": 2,
|
||||
"covered": 2,
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p15/certificats/certificat_D8_E12_palier2p15.json"
|
||||
},
|
||||
"fusion": {
|
||||
"t_min": 9,
|
||||
"t_max_search": 120,
|
||||
"t_max_used": 51,
|
||||
"merged_csv": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p15/candidats/candidats_F9to51_E12_palier2p15.csv",
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p15/certificats/certificat_F9to51_E12_palier2p15.json",
|
||||
"clauses": 30,
|
||||
"covered": 30
|
||||
},
|
||||
"verification_md": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p15/audits/verification_H6_E12_palier2p15.md",
|
||||
"success": true
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"noyau": [
|
||||
31,
|
||||
1055,
|
||||
2079,
|
||||
3103
|
||||
],
|
||||
"palier": 12
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
{
|
||||
"noyau": [
|
||||
31,
|
||||
1055,
|
||||
2079,
|
||||
3103,
|
||||
4127,
|
||||
5151,
|
||||
6175,
|
||||
7199,
|
||||
8223,
|
||||
9247,
|
||||
10271,
|
||||
11295,
|
||||
12319,
|
||||
13343,
|
||||
14367,
|
||||
15391,
|
||||
16415,
|
||||
17439,
|
||||
18463,
|
||||
19487,
|
||||
20511,
|
||||
21535,
|
||||
22559,
|
||||
23583,
|
||||
24607,
|
||||
25631,
|
||||
26655,
|
||||
27679,
|
||||
28703,
|
||||
29727,
|
||||
30751,
|
||||
31775
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
{
|
||||
"noyau": [
|
||||
31,
|
||||
1055,
|
||||
2079,
|
||||
3103,
|
||||
4127,
|
||||
5151,
|
||||
6175,
|
||||
7199,
|
||||
8223,
|
||||
9247,
|
||||
11295,
|
||||
12319,
|
||||
13343,
|
||||
14367,
|
||||
15391,
|
||||
16415,
|
||||
17439,
|
||||
18463,
|
||||
19487,
|
||||
20511,
|
||||
21535,
|
||||
22559,
|
||||
23583,
|
||||
24607,
|
||||
25631,
|
||||
27679,
|
||||
28703,
|
||||
29727,
|
||||
30751,
|
||||
31775
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
**Auteur** : Équipe 4NK
|
||||
|
||||
# Vérification H6(E12) — couverture des relèvements au palier \(2^{16}\)
|
||||
|
||||
## Objet
|
||||
|
||||
Vérifier, au sens “certifié D/F” (appartenance aux ensembles `covered` de certificats), que l’union des certificats locaux couvre le domaine des relèvements impairs.
|
||||
|
||||
## Domaine
|
||||
|
||||
- base : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p16/noyaux/noyau_E12_B12.json`
|
||||
- relevé : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p16/noyaux/noyau_Lift_E12_palier2p16.json`
|
||||
- taille : 64
|
||||
|
||||
## Certificats utilisés (local)
|
||||
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p16/certificats/certificat_D8_E12_palier2p16.json`
|
||||
- covered : 4 classes
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p16/certificats/certificat_F9to51_E12_palier2p16.json`
|
||||
- covered : 60 classes
|
||||
|
||||
## Résultat
|
||||
|
||||
- |L| = 64
|
||||
- |U| = 64
|
||||
- |L \ U| = 0
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
classe_mod_2^m,sœur,A8,palier
|
||||
10271,43039,13,16
|
||||
26655,59423,13,16
|
||||
43039,10271,13,16
|
||||
59423,26655,13,16
|
||||
|
@ -0,0 +1,61 @@
|
||||
horizon_t,classe_mod_2^m,m,t,a,A_t,mot_a0..,C_t,y,y_mod_3,DeltaF,Nf,preimage_m,etat_id,base_mod_4096
|
||||
9,2079,16,9,2,16,1 1 1 1 2 2 1 5 2,39043,625,1,117876,1,833,12,2079
|
||||
9,6175,16,9,2,16,1 1 1 1 2 2 1 3 4,26755,1855,1,117876,1,2473,12,2079
|
||||
9,7199,16,9,1,15,1 1 1 1 2 2 1 1 5,23683,4325,2,58938,1,2883,12,3103
|
||||
9,12319,16,9,1,14,1 1 1 1 2 2 1 2 3,24707,14801,2,9786,4,9867,12,31
|
||||
9,18463,16,9,2,17,1 1 1 1 2 2 1 6 2,55427,2773,1,314484,1,3697,12,2079
|
||||
9,28703,16,9,1,16,1 1 1 1 2 2 1 2 5,24707,8621,2,157242,1,5747,12,31
|
||||
9,34847,16,9,1,15,1 1 1 1 2 2 1 5 1,39043,20933,2,58938,1,13955,12,2079
|
||||
9,38943,16,9,1,15,1 1 1 1 2 2 1 3 3,26755,23393,2,58938,1,15595,12,2079
|
||||
9,39967,16,9,2,18,1 1 1 1 2 2 1 1 8,23683,3001,1,707700,1,4001,12,3103
|
||||
9,45087,16,9,1,14,1 1 1 1 2 2 1 2 3,24707,54167,2,9786,4,36111,12,31
|
||||
9,51231,16,9,2,18,1 1 1 1 2 2 1 7 2,88195,3847,1,707700,1,5129,12,2079
|
||||
9,61471,16,9,2,15,1 1 1 1 2 2 1 2 4,24707,36925,1,19572,4,49233,12,31
|
||||
10,20511,16,10,2,17,1 1 1 1 2 2 1 2 2 4,82313,9241,1,157020,2,12321,12,31
|
||||
10,23583,16,10,1,17,1 1 1 1 2 2 1 1 4 3,87433,10625,2,275118,1,7083,12,3103
|
||||
10,31775,16,10,1,16,1 1 1 1 2 2 1 1 3 3,79241,28631,2,78510,2,19087,12,3103
|
||||
10,54303,16,10,1,16,1 1 1 1 2 2 1 1 1 5,73097,48929,2,78510,2,32619,12,1055
|
||||
10,55327,16,10,2,18,1 1 1 1 2 2 1 3 2 4,96649,12463,1,550236,1,16617,12,2079
|
||||
10,63519,16,10,1,16,1 1 1 1 2 2 1 3 1 3,88457,57233,2,78510,2,38155,12,2079
|
||||
11,3103,16,11,1,19,1 1 1 1 2 2 1 1 2 4 3,290971,1049,2,1218570,1,699,12,3103
|
||||
11,19487,16,11,1,17,1 1 1 1 2 2 1 1 2 2 3,241819,26339,2,38922,10,17559,12,3103
|
||||
11,42015,16,11,2,18,1 1 1 1 2 2 1 1 1 1 6,223387,28393,1,77844,9,37857,12,1055
|
||||
11,44063,16,11,1,18,1 1 1 1 2 2 1 1 2 1 5,233627,29777,2,432138,1,19851,12,3103
|
||||
11,48159,16,11,2,18,1 1 1 1 2 2 1 1 3 1 4,254107,32545,1,77844,10,43393,12,3103
|
||||
11,53279,16,11,1,18,1 1 1 1 2 2 1 2 2 2 3,279707,36005,2,432138,1,24003,12,31
|
||||
11,56351,16,11,1,18,1 1 1 1 2 2 1 1 4 1 3,295067,38081,2,432138,1,25387,12,3103
|
||||
11,57375,16,11,2,18,1 1 1 1 2 2 1 2 1 4 2,300187,38773,1,77844,13,51697,12,31
|
||||
12,25631,16,12,2,20,1 1 1 1 2 2 1 1 1 1 2 6,686545,12991,1,1019964,2,17321,12,1055
|
||||
12,27679,16,12,2,20,1 1 1 1 2 2 1 1 2 1 1 6,717265,14029,1,1019964,2,18705,12,3103
|
||||
12,29727,16,12,2,20,1 1 1 1 2 2 1 1 1 2 3 4,747985,15067,1,1019964,2,20089,12,1055
|
||||
12,32799,16,12,2,24,1 1 1 1 2 2 1 2 1 1 3 8,794065,1039,1,48205884,1,1385,12,31
|
||||
12,35871,16,12,2,20,1 1 1 1 2 2 1 1 2 3 1 4,840145,18181,1,1019964,3,24241,12,3103
|
||||
12,36895,16,12,2,22,1 1 1 1 2 2 1 2 2 1 2 6,855505,4675,1,10457148,1,6233,12,31
|
||||
13,9247,16,13,1,21,1 1 1 1 2 2 1 1 1 1 3 3 3,2370931,7031,2,3102810,1,4687,12,1055
|
||||
13,11295,16,13,1,23,1 1 1 1 2 2 1 1 2 1 2 3 5,2463091,2147,2,21977178,1,1431,12,3103
|
||||
13,15391,16,13,2,22,1 1 1 1 2 2 1 1 3 1 1 3 4,2647411,5851,1,6205620,2,7801,12,3103
|
||||
13,21535,16,13,1,21,1 1 1 1 2 2 1 1 1 4 2 1 3,2923891,16373,2,3102810,2,10915,12,1055
|
||||
13,62495,16,13,1,24,1 1 1 1 2 2 1 1 1 2 2 4 5,2669939,5939,2,47143002,1,3959,12,1055
|
||||
14,64543,16,14,1,24,1 1 1 1 2 2 1 1 3 2 1 1 4 3,10383449,18401,2,40765710,1,12267,12,3103
|
||||
15,37919,16,15,1,28,1 1 1 1 2 2 1 1 1 3 1 2 1 1 9,22464779,2027,2,776608554,1,1351,12,1055
|
||||
15,52255,16,15,1,24,1 1 1 1 2 2 1 1 2 2 1 1 1 2 5,21979403,44693,2,21633834,2,29795,12,3103
|
||||
16,8223,16,16,1,28,1 1 1 1 2 2 1 2 1 2 2 1 1 4 1 5,93179681,1319,2,719212926,1,879,12,31
|
||||
16,13343,16,16,2,30,1 1 1 1 2 2 1 1 1 2 1 2 1 3 4 6,79477537,535,1,3049038588,1,713,12,1055
|
||||
16,14367,16,16,2,26,1 1 1 1 2 2 1 3 1 1 2 1 1 3 1 4,90158881,9217,1,29139708,11,12289,12,2079
|
||||
16,60447,16,16,1,25,1 1 1 1 2 2 1 1 2 1 1 1 2 3 2 3,67502881,77549,2,14569854,7,51699,12,3103
|
||||
17,16415,16,17,2,29,1 1 1 1 2 2 1 2 1 1 1 2 1 4 2 2 4,267455843,3949,1,1094052084,1,5265,12,31
|
||||
17,46111,16,17,2,31,1 1 1 1 2 2 1 1 1 2 1 1 1 1 4 2 8,190099811,2773,1,5925890292,1,3697,12,1055
|
||||
18,33823,16,18,2,29,1 1 1 1 2 2 1 1 1 1 1 4 1 1 3 1 4 2,758891561,24409,1,60930780,42,32545,12,1055
|
||||
18,58399,16,18,1,28,1 1 1 1 2 2 1 1 1 1 2 1 2 3 1 3 1 3,650142761,84287,2,30465390,34,56191,12,1055
|
||||
21,5151,16,21,1,33,1 1 1 1 2 2 1 1 1 3 2 1 1 2 1 1 1 3 1 3 3,20560216147,6275,2,4849097370,7,4183,12,1055
|
||||
21,17439,16,21,1,34,1 1 1 1 2 2 1 1 1 1 1 1 1 1 2 2 2 2 3 2 5,14931357779,10619,2,30618901146,1,7079,12,1055
|
||||
21,30751,16,21,1,33,1 1 1 1 2 2 1 3 1 2 2 1 2 1 1 2 1 2 1 4 1,35319059539,37451,2,4849097370,13,24967,12,2079
|
||||
24,49183,16,24,1,41,1 1 1 1 2 2 1 2 1 1 1 1 1 1 3 2 1 3 1 1 2 1 3 7,498012576961,6317,2,6032210693694,1,4211,12,31
|
||||
25,24607,16,25,1,40,1 1 1 1 2 2 1 2 1 3 2 1 2 2 1 1 1 1 2 1 2 1 4 1 3,3007208207939,18965,2,1603957664442,4,12643,12,31
|
||||
26,4127,16,26,1,42,1 1 1 1 2 2 1 2 2 1 1 1 1 1 2 2 4 2 1 1 2 2 1 1 3 3,7856748491465,2387,2,8110407876654,2,1591,12,31
|
||||
27,47135,16,27,1,43,1 1 1 1 2 2 1 3 1 1 1 2 1 1 1 4 1 1 1 2 1 2 1 1 4 2 3,19803897667675,40865,2,11137084096650,3,27243,12,2079
|
||||
32,40991,16,32,2,52,1 1 1 1 2 2 1 2 1 2 1 2 1 1 1 1 1 3 1 1 4 1 2 1 2 1 2 2 3 2 1 4,5064353632341601,16867,1,6098718126704124,3,22489,12,31
|
||||
35,31,16,35,1,56,1 1 1 1 2 2 1 2 1 1 2 1 1 1 2 3 1 1 2 1 2 1 1 1 1 1 3 1 1 1 4 2 2 4 3,106346764803351611,23,2,116109691915784394,2,15,12,31
|
||||
36,50207,16,36,1,59,1 1 1 1 2 2 1 1 1 1 1 1 2 1 1 1 1 1 3 2 2 1 1 1 1 2 1 1 5 2 2 2 3 3 1 5,270060506220390577,13073,2,1429192986316272222,1,8715,12,1055
|
||||
50,1055,16,50,2,82,1 1 1 1 2 2 1 1 1 1 1 2 1 2 2 1 1 3 4 1 1 1 2 1 1 1 1 2 1 1 2 1 1 3 2 3 1 1 2 1 1 1 5 1 1 1 1 4 2 6,1823037703082640562865833,157,1,11635517884608139741393116,1,209,12,1055
|
||||
51,22559,16,51,1,82,1 1 1 1 2 2 1 3 2 1 1 1 1 3 1 1 1 1 1 1 1 4 3 2 1 2 1 1 1 1 1 2 1 2 2 1 2 1 1 1 1 1 1 4 4 2 1 3 1 1 5,8800132208126656285308923,10049,2,10199721909224434563852618,2,6699,12,2079
|
||||
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"clauses": [
|
||||
10271,
|
||||
26655,
|
||||
43039,
|
||||
59423
|
||||
],
|
||||
"covered": [
|
||||
10271,
|
||||
26655,
|
||||
43039,
|
||||
59423
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
@ -0,0 +1,127 @@
|
||||
{
|
||||
"clauses": [
|
||||
31,
|
||||
1055,
|
||||
2079,
|
||||
3103,
|
||||
4127,
|
||||
5151,
|
||||
6175,
|
||||
7199,
|
||||
8223,
|
||||
9247,
|
||||
11295,
|
||||
12319,
|
||||
13343,
|
||||
14367,
|
||||
15391,
|
||||
16415,
|
||||
17439,
|
||||
18463,
|
||||
19487,
|
||||
20511,
|
||||
21535,
|
||||
22559,
|
||||
23583,
|
||||
24607,
|
||||
25631,
|
||||
27679,
|
||||
28703,
|
||||
29727,
|
||||
30751,
|
||||
31775,
|
||||
32799,
|
||||
33823,
|
||||
34847,
|
||||
35871,
|
||||
36895,
|
||||
37919,
|
||||
38943,
|
||||
39967,
|
||||
40991,
|
||||
42015,
|
||||
44063,
|
||||
45087,
|
||||
46111,
|
||||
47135,
|
||||
48159,
|
||||
49183,
|
||||
50207,
|
||||
51231,
|
||||
52255,
|
||||
53279,
|
||||
54303,
|
||||
55327,
|
||||
56351,
|
||||
57375,
|
||||
58399,
|
||||
60447,
|
||||
61471,
|
||||
62495,
|
||||
63519,
|
||||
64543
|
||||
],
|
||||
"covered": [
|
||||
31,
|
||||
1055,
|
||||
2079,
|
||||
3103,
|
||||
4127,
|
||||
5151,
|
||||
6175,
|
||||
7199,
|
||||
8223,
|
||||
9247,
|
||||
11295,
|
||||
12319,
|
||||
13343,
|
||||
14367,
|
||||
15391,
|
||||
16415,
|
||||
17439,
|
||||
18463,
|
||||
19487,
|
||||
20511,
|
||||
21535,
|
||||
22559,
|
||||
23583,
|
||||
24607,
|
||||
25631,
|
||||
27679,
|
||||
28703,
|
||||
29727,
|
||||
30751,
|
||||
31775,
|
||||
32799,
|
||||
33823,
|
||||
34847,
|
||||
35871,
|
||||
36895,
|
||||
37919,
|
||||
38943,
|
||||
39967,
|
||||
40991,
|
||||
42015,
|
||||
44063,
|
||||
45087,
|
||||
46111,
|
||||
47135,
|
||||
48159,
|
||||
49183,
|
||||
50207,
|
||||
51231,
|
||||
52255,
|
||||
53279,
|
||||
54303,
|
||||
55327,
|
||||
56351,
|
||||
57375,
|
||||
58399,
|
||||
60447,
|
||||
61471,
|
||||
62495,
|
||||
63519,
|
||||
64543
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
25
docs/artefacts/collatz/local_E12_palier2p16/metadata.json
Normal file
25
docs/artefacts/collatz/local_E12_palier2p16/metadata.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"state_id": 12,
|
||||
"base_palier": 12,
|
||||
"target_palier": 16,
|
||||
"delta_m": 4,
|
||||
"lift_size": 64,
|
||||
"d8": {
|
||||
"k": 8,
|
||||
"threshold_Ak": 13,
|
||||
"candidates": 4,
|
||||
"covered": 4,
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p16/certificats/certificat_D8_E12_palier2p16.json"
|
||||
},
|
||||
"fusion": {
|
||||
"t_min": 9,
|
||||
"t_max_search": 128,
|
||||
"t_max_used": 51,
|
||||
"merged_csv": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p16/candidats/candidats_F9to51_E12_palier2p16.csv",
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p16/certificats/certificat_F9to51_E12_palier2p16.json",
|
||||
"clauses": 60,
|
||||
"covered": 60
|
||||
},
|
||||
"verification_md": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E12_palier2p16/audits/verification_H6_E12_palier2p16.md",
|
||||
"success": true
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"noyau": [
|
||||
31,
|
||||
1055,
|
||||
2079,
|
||||
3103
|
||||
],
|
||||
"palier": 12
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
{
|
||||
"noyau": [
|
||||
31,
|
||||
1055,
|
||||
2079,
|
||||
3103,
|
||||
4127,
|
||||
5151,
|
||||
6175,
|
||||
7199,
|
||||
8223,
|
||||
9247,
|
||||
10271,
|
||||
11295,
|
||||
12319,
|
||||
13343,
|
||||
14367,
|
||||
15391,
|
||||
16415,
|
||||
17439,
|
||||
18463,
|
||||
19487,
|
||||
20511,
|
||||
21535,
|
||||
22559,
|
||||
23583,
|
||||
24607,
|
||||
25631,
|
||||
26655,
|
||||
27679,
|
||||
28703,
|
||||
29727,
|
||||
30751,
|
||||
31775,
|
||||
32799,
|
||||
33823,
|
||||
34847,
|
||||
35871,
|
||||
36895,
|
||||
37919,
|
||||
38943,
|
||||
39967,
|
||||
40991,
|
||||
42015,
|
||||
43039,
|
||||
44063,
|
||||
45087,
|
||||
46111,
|
||||
47135,
|
||||
48159,
|
||||
49183,
|
||||
50207,
|
||||
51231,
|
||||
52255,
|
||||
53279,
|
||||
54303,
|
||||
55327,
|
||||
56351,
|
||||
57375,
|
||||
58399,
|
||||
59423,
|
||||
60447,
|
||||
61471,
|
||||
62495,
|
||||
63519,
|
||||
64543
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
{
|
||||
"noyau": [
|
||||
31,
|
||||
1055,
|
||||
2079,
|
||||
3103,
|
||||
4127,
|
||||
5151,
|
||||
6175,
|
||||
7199,
|
||||
8223,
|
||||
9247,
|
||||
11295,
|
||||
12319,
|
||||
13343,
|
||||
14367,
|
||||
15391,
|
||||
16415,
|
||||
17439,
|
||||
18463,
|
||||
19487,
|
||||
20511,
|
||||
21535,
|
||||
22559,
|
||||
23583,
|
||||
24607,
|
||||
25631,
|
||||
27679,
|
||||
28703,
|
||||
29727,
|
||||
30751,
|
||||
31775,
|
||||
32799,
|
||||
33823,
|
||||
34847,
|
||||
35871,
|
||||
36895,
|
||||
37919,
|
||||
38943,
|
||||
39967,
|
||||
40991,
|
||||
42015,
|
||||
44063,
|
||||
45087,
|
||||
46111,
|
||||
47135,
|
||||
48159,
|
||||
49183,
|
||||
50207,
|
||||
51231,
|
||||
52255,
|
||||
53279,
|
||||
54303,
|
||||
55327,
|
||||
56351,
|
||||
57375,
|
||||
58399,
|
||||
60447,
|
||||
61471,
|
||||
62495,
|
||||
63519,
|
||||
64543
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
**Auteur** : Équipe 4NK
|
||||
|
||||
# Vérification H6(E13) — couverture des relèvements au palier \(2^{15}\)
|
||||
|
||||
## Objet
|
||||
|
||||
Vérifier, au sens “certifié D/F” (appartenance aux ensembles `covered` de certificats), que l’union des certificats locaux couvre le domaine des relèvements impairs.
|
||||
|
||||
## Domaine
|
||||
|
||||
- base : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p15/noyaux/noyau_E13_B12.json`
|
||||
- relevé : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p15/noyaux/noyau_Lift_E13_palier2p15.json`
|
||||
- taille : 32
|
||||
|
||||
## Certificats utilisés (local)
|
||||
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p15/certificats/certificat_D8_E13_palier2p15.json`
|
||||
- covered : 2 classes
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p15/certificats/certificat_F9to42_E13_palier2p15.json`
|
||||
- covered : 30 classes
|
||||
|
||||
## Résultat
|
||||
|
||||
- |L| = 32
|
||||
- |U| = 32
|
||||
- |L \ U| = 0
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
classe_mod_2^m,sœur,A8,palier
|
||||
3551,19935,13,15
|
||||
19935,3551,13,15
|
||||
|
@ -0,0 +1,31 @@
|
||||
horizon_t,classe_mod_2^m,m,t,a,A_t,mot_a0..,C_t,y,y_mod_3,DeltaF,Nf,preimage_m,etat_id,base_mod_4096
|
||||
9,5599,15,9,2,17,1 1 1 1 3 1 1 2 6,26435,841,1,314484,1,1121,13,1503
|
||||
9,11743,15,9,1,15,1 1 1 1 3 1 1 5 1,40771,7055,2,58938,1,4703,13,3551
|
||||
9,15839,15,9,1,15,1 1 1 1 3 1 1 3 3,28483,9515,2,58938,1,6343,13,3551
|
||||
9,16863,15,9,2,16,1 1 1 1 3 1 1 1 6,25411,5065,1,117876,1,6753,13,479
|
||||
9,21983,15,9,1,14,1 1 1 1 3 1 1 2 3,26435,26411,2,9786,4,17607,13,1503
|
||||
9,28127,15,9,1,25,1 1 1 1 3 1 1 15 1,16801603,17,2,100623930,1,11,13,3551
|
||||
10,8671,15,10,2,17,1 1 1 1 3 1 1 1 3 4,84425,3907,1,157020,2,5209,13,479
|
||||
10,31199,15,10,1,20,1 1 1 1 3 1 1 1 1 9,78281,1757,2,3027630,1,1171,13,2527
|
||||
11,479,15,11,2,18,1 1 1 1 3 1 1 1 4 2 2,343387,325,1,77844,15,433,13,479
|
||||
11,13791,15,11,1,17,1 1 1 1 3 1 1 2 2 1 3,278875,18641,2,38922,11,12427,13,1503
|
||||
11,32223,15,11,1,17,1 1 1 1 3 1 1 3 2 2 1,371035,43553,2,38922,16,29035,13,3551
|
||||
13,1503,15,13,1,24,1 1 1 1 3 1 1 2 1 3 1 1 7,2874419,143,2,47143002,1,95,13,1503
|
||||
13,9695,15,13,2,23,1 1 1 1 3 1 1 2 1 1 4 2 4,3243059,1843,1,18788532,1,2457,13,1503
|
||||
13,10719,15,13,2,22,1 1 1 1 3 1 1 1 1 1 1 3 6,2240563,4075,1,6205620,1,5433,13,2527
|
||||
13,14815,15,13,1,31,1 1 1 1 3 1 1 1 1 3 1 1 15,2424883,11,2,6439262298,1,7,13,2527
|
||||
13,18911,15,13,2,22,1 1 1 1 3 1 1 1 1 1 4 2 4,2609203,7189,1,6205620,2,9585,13,2527
|
||||
13,20959,15,13,1,21,1 1 1 1 3 1 1 1 2 1 3 2 3,2701363,15935,2,3102810,2,10623,13,479
|
||||
13,25055,15,13,1,21,1 1 1 1 3 1 1 1 3 1 2 2 3,2885683,19049,2,3102810,2,12699,13,479
|
||||
14,7647,15,14,1,22,1 1 1 1 3 1 1 3 1 2 1 1 4 1,11549849,8723,2,3016974,7,5815,13,3551
|
||||
14,24031,15,14,1,23,1 1 1 1 3 1 1 3 1 1 1 1 4 3,9567385,13703,2,15599886,1,9135,13,3551
|
||||
14,26079,15,14,1,22,1 1 1 1 3 1 1 2 1 1 1 1 4 3,7746713,29741,2,3016974,4,19827,13,1503
|
||||
16,2527,15,16,2,27,1 1 1 1 3 1 1 1 1 1 2 2 1 1 5 4,71513441,811,1,230466300,1,1081,13,2527
|
||||
16,6623,15,16,2,27,1 1 1 1 3 1 1 1 1 2 4 2 1 2 1 4,114238817,2125,1,230466300,2,2833,13,2527
|
||||
16,12767,15,16,2,26,1 1 1 1 3 1 1 1 2 3 2 2 1 1 1 4,111218017,8191,1,29139708,13,10921,13,479
|
||||
16,29151,15,16,2,28,1 1 1 1 3 1 1 1 2 2 1 2 2 1 2 6,80792929,4675,1,633119484,1,6233,13,479
|
||||
17,30175,15,17,1,29,1 1 1 1 3 1 1 2 2 2 1 2 2 1 2 1 5,341531683,7259,2,1352332410,1,4839,13,1503
|
||||
19,17887,15,19,1,32,1 1 1 1 3 1 1 2 1 2 1 1 4 1 1 1 1 1 7,2565819707,4841,2,10560378954,1,3227,13,1503
|
||||
24,4575,15,24,1,38,1 1 1 1 3 1 1 1 2 1 1 2 1 1 3 2 3 1 1 2 1 1 1 5,635666957057,4703,2,259774647870,4,3135,13,479
|
||||
26,23007,15,26,1,41,1 1 1 1 3 1 1 1 1 2 1 1 4 1 1 1 3 2 1 1 1 2 1 3 4 1,6714415551241,26597,2,1513338109998,8,17731,13,2527
|
||||
42,27103,15,42,1,68,1 1 1 1 3 1 1 1 1 1 1 1 4 3 2 1 2 1 1 1 1 1 2 1 2 2 1 2 1 1 1 1 1 1 4 4 2 1 3 1 1 5,358436715937075385417,10049,2,666605737275033759150,1,6699,13,2527
|
||||
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"clauses": [
|
||||
3551,
|
||||
19935
|
||||
],
|
||||
"covered": [
|
||||
3551,
|
||||
19935
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
{
|
||||
"clauses": [
|
||||
479,
|
||||
1503,
|
||||
2527,
|
||||
4575,
|
||||
5599,
|
||||
6623,
|
||||
7647,
|
||||
8671,
|
||||
9695,
|
||||
10719,
|
||||
11743,
|
||||
12767,
|
||||
13791,
|
||||
14815,
|
||||
15839,
|
||||
16863,
|
||||
17887,
|
||||
18911,
|
||||
20959,
|
||||
21983,
|
||||
23007,
|
||||
24031,
|
||||
25055,
|
||||
26079,
|
||||
27103,
|
||||
28127,
|
||||
29151,
|
||||
30175,
|
||||
31199,
|
||||
32223
|
||||
],
|
||||
"covered": [
|
||||
479,
|
||||
1503,
|
||||
2527,
|
||||
4575,
|
||||
5599,
|
||||
6623,
|
||||
7647,
|
||||
8671,
|
||||
9695,
|
||||
10719,
|
||||
11743,
|
||||
12767,
|
||||
13791,
|
||||
14815,
|
||||
15839,
|
||||
16863,
|
||||
17887,
|
||||
18911,
|
||||
20959,
|
||||
21983,
|
||||
23007,
|
||||
24031,
|
||||
25055,
|
||||
26079,
|
||||
27103,
|
||||
28127,
|
||||
29151,
|
||||
30175,
|
||||
31199,
|
||||
32223
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
25
docs/artefacts/collatz/local_E13_palier2p15/metadata.json
Normal file
25
docs/artefacts/collatz/local_E13_palier2p15/metadata.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"state_id": 13,
|
||||
"base_palier": 12,
|
||||
"target_palier": 15,
|
||||
"delta_m": 3,
|
||||
"lift_size": 32,
|
||||
"d8": {
|
||||
"k": 8,
|
||||
"threshold_Ak": 13,
|
||||
"candidates": 2,
|
||||
"covered": 2,
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p15/certificats/certificat_D8_E13_palier2p15.json"
|
||||
},
|
||||
"fusion": {
|
||||
"t_min": 9,
|
||||
"t_max_search": 120,
|
||||
"t_max_used": 42,
|
||||
"merged_csv": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p15/candidats/candidats_F9to42_E13_palier2p15.csv",
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p15/certificats/certificat_F9to42_E13_palier2p15.json",
|
||||
"clauses": 30,
|
||||
"covered": 30
|
||||
},
|
||||
"verification_md": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p15/audits/verification_H6_E13_palier2p15.md",
|
||||
"success": true
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"noyau": [
|
||||
479,
|
||||
1503,
|
||||
2527,
|
||||
3551
|
||||
],
|
||||
"palier": 12
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
{
|
||||
"noyau": [
|
||||
479,
|
||||
1503,
|
||||
2527,
|
||||
3551,
|
||||
4575,
|
||||
5599,
|
||||
6623,
|
||||
7647,
|
||||
8671,
|
||||
9695,
|
||||
10719,
|
||||
11743,
|
||||
12767,
|
||||
13791,
|
||||
14815,
|
||||
15839,
|
||||
16863,
|
||||
17887,
|
||||
18911,
|
||||
19935,
|
||||
20959,
|
||||
21983,
|
||||
23007,
|
||||
24031,
|
||||
25055,
|
||||
26079,
|
||||
27103,
|
||||
28127,
|
||||
29151,
|
||||
30175,
|
||||
31199,
|
||||
32223
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
{
|
||||
"noyau": [
|
||||
479,
|
||||
1503,
|
||||
2527,
|
||||
4575,
|
||||
5599,
|
||||
6623,
|
||||
7647,
|
||||
8671,
|
||||
9695,
|
||||
10719,
|
||||
11743,
|
||||
12767,
|
||||
13791,
|
||||
14815,
|
||||
15839,
|
||||
16863,
|
||||
17887,
|
||||
18911,
|
||||
20959,
|
||||
21983,
|
||||
23007,
|
||||
24031,
|
||||
25055,
|
||||
26079,
|
||||
27103,
|
||||
28127,
|
||||
29151,
|
||||
30175,
|
||||
31199,
|
||||
32223
|
||||
],
|
||||
"palier": 15
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
**Auteur** : Équipe 4NK
|
||||
|
||||
# Vérification H6(E13) — couverture des relèvements au palier \(2^{16}\)
|
||||
|
||||
## Objet
|
||||
|
||||
Vérifier, au sens “certifié D/F” (appartenance aux ensembles `covered` de certificats), que l’union des certificats locaux couvre le domaine des relèvements impairs.
|
||||
|
||||
## Domaine
|
||||
|
||||
- base : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p16/noyaux/noyau_E13_B12.json`
|
||||
- relevé : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p16/noyaux/noyau_Lift_E13_palier2p16.json`
|
||||
- taille : 64
|
||||
|
||||
## Certificats utilisés (local)
|
||||
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p16/certificats/certificat_D8_E13_palier2p16.json`
|
||||
- covered : 4 classes
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p16/certificats/certificat_F9to44_E13_palier2p16.json`
|
||||
- covered : 60 classes
|
||||
|
||||
## Résultat
|
||||
|
||||
- |L| = 64
|
||||
- |U| = 64
|
||||
- |L \ U| = 0
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
classe_mod_2^m,sœur,A8,palier
|
||||
3551,36319,13,16
|
||||
19935,52703,13,16
|
||||
36319,3551,13,16
|
||||
52703,19935,13,16
|
||||
|
@ -0,0 +1,61 @@
|
||||
horizon_t,classe_mod_2^m,m,t,a,A_t,mot_a0..,C_t,y,y_mod_3,DeltaF,Nf,preimage_m,etat_id,base_mod_4096
|
||||
9,5599,16,9,2,17,1 1 1 1 3 1 1 2 6,26435,841,1,314484,1,1121,13,1503
|
||||
9,11743,16,9,1,15,1 1 1 1 3 1 1 5 1,40771,7055,2,58938,1,4703,13,3551
|
||||
9,15839,16,9,1,15,1 1 1 1 3 1 1 3 3,28483,9515,2,58938,1,6343,13,3551
|
||||
9,16863,16,9,2,16,1 1 1 1 3 1 1 1 6,25411,5065,1,117876,1,6753,13,479
|
||||
9,21983,16,9,1,14,1 1 1 1 3 1 1 2 3,26435,26411,2,9786,4,17607,13,1503
|
||||
9,28127,16,9,1,25,1 1 1 1 3 1 1 15 1,16801603,17,2,100623930,1,11,13,3551
|
||||
9,38367,16,9,2,15,1 1 1 1 3 1 1 2 4,26435,23047,1,19572,4,30729,13,1503
|
||||
9,44511,16,9,2,16,1 1 1 1 3 1 1 5 2,40771,13369,1,117876,1,17825,13,3551
|
||||
9,48607,16,9,2,16,1 1 1 1 3 1 1 3 4,28483,14599,1,117876,1,19465,13,3551
|
||||
9,49631,16,9,1,15,1 1 1 1 3 1 1 1 5,25411,29813,2,58938,1,19875,13,479
|
||||
9,54751,16,9,1,14,1 1 1 1 3 1 1 2 3,26435,65777,2,9786,4,43851,13,1503
|
||||
9,60895,16,9,2,17,1 1 1 1 3 1 1 6 2,57155,9145,1,314484,1,12193,13,3551
|
||||
10,8671,16,10,2,17,1 1 1 1 3 1 1 1 3 4,84425,3907,1,157020,2,5209,13,479
|
||||
10,31199,16,10,1,20,1 1 1 1 3 1 1 1 1 9,78281,1757,2,3027630,1,1171,13,2527
|
||||
10,34271,16,10,1,21,1 1 1 1 3 1 1 2 1 9,83401,965,2,6173358,1,643,13,1503
|
||||
10,40415,16,10,1,22,1 1 1 1 3 1 1 3 1 9,93641,569,2,12464814,1,379,13,3551
|
||||
10,62943,16,10,2,17,1 1 1 1 3 1 1 2 2 4,87497,28357,1,157020,2,37809,13,1503
|
||||
11,479,16,11,2,18,1 1 1 1 3 1 1 1 4 2 2,343387,325,1,77844,15,433,13,479
|
||||
11,13791,16,11,1,17,1 1 1 1 3 1 1 2 2 1 3,278875,18641,2,38922,11,12427,13,1503
|
||||
11,32223,16,11,1,17,1 1 1 1 3 1 1 3 2 2 1,371035,43553,2,38922,16,29035,13,3551
|
||||
11,41439,16,11,1,20,1 1 1 1 3 1 1 1 3 2 5,286043,7001,2,2791434,1,4667,13,479
|
||||
11,45535,16,11,2,20,1 1 1 1 3 1 1 1 2 4 4,306523,7693,1,2437140,1,10257,13,479
|
||||
11,61919,16,11,1,17,1 1 1 1 3 1 1 1 2 2 3,257371,83687,2,38922,10,55791,13,479
|
||||
13,1503,16,13,1,24,1 1 1 1 3 1 1 2 1 3 1 1 7,2874419,143,2,47143002,1,95,13,1503
|
||||
13,9695,16,13,2,23,1 1 1 1 3 1 1 2 1 1 4 2 4,3243059,1843,1,18788532,1,2457,13,1503
|
||||
13,10719,16,13,2,22,1 1 1 1 3 1 1 1 1 1 1 3 6,2240563,4075,1,6205620,1,5433,13,2527
|
||||
13,14815,16,13,1,31,1 1 1 1 3 1 1 1 1 3 1 1 15,2424883,11,2,6439262298,1,7,13,2527
|
||||
13,18911,16,13,2,22,1 1 1 1 3 1 1 1 1 1 4 2 4,2609203,7189,1,6205620,2,9585,13,2527
|
||||
13,20959,16,13,1,21,1 1 1 1 3 1 1 1 2 1 3 2 3,2701363,15935,2,3102810,2,10623,13,479
|
||||
13,25055,16,13,1,21,1 1 1 1 3 1 1 1 3 1 2 2 3,2885683,19049,2,3102810,2,12699,13,479
|
||||
13,33247,16,13,1,21,1 1 1 1 3 1 1 1 4 1 1 2 3,3254323,25277,2,3102810,2,16851,13,479
|
||||
14,7647,16,14,1,22,1 1 1 1 3 1 1 3 1 2 1 1 4 1,11549849,8723,2,3016974,7,5815,13,3551
|
||||
14,24031,16,14,1,23,1 1 1 1 3 1 1 3 1 1 1 1 4 3,9567385,13703,2,15599886,1,9135,13,3551
|
||||
14,26079,16,14,1,22,1 1 1 1 3 1 1 2 1 1 1 1 4 3,7746713,29741,2,3016974,4,19827,13,1503
|
||||
14,51679,16,14,2,23,1 1 1 1 3 1 1 1 1 1 3 3 1 4,8056985,29467,1,6033948,4,39289,13,2527
|
||||
14,63967,16,14,1,22,1 1 1 1 3 1 1 1 1 4 2 1 1 3,9715865,72947,2,3016974,6,48631,13,2527
|
||||
16,2527,16,16,2,27,1 1 1 1 3 1 1 1 1 1 2 2 1 1 5 4,71513441,811,1,230466300,1,1081,13,2527
|
||||
16,6623,16,16,2,27,1 1 1 1 3 1 1 1 1 2 4 2 1 2 1 4,114238817,2125,1,230466300,2,2833,13,2527
|
||||
16,12767,16,16,2,26,1 1 1 1 3 1 1 1 2 3 2 2 1 1 1 4,111218017,8191,1,29139708,13,10921,13,479
|
||||
16,29151,16,16,2,28,1 1 1 1 3 1 1 1 2 2 1 2 2 1 2 6,80792929,4675,1,633119484,1,6233,13,479
|
||||
17,30175,16,17,1,29,1 1 1 1 3 1 1 2 2 2 1 2 2 1 2 1 5,341531683,7259,2,1352332410,1,4839,13,1503
|
||||
18,46559,16,18,1,28,1 1 1 1 3 1 1 2 2 1 1 1 1 1 1 1 3 5,683660393,67199,2,30465390,37,44799,13,1503
|
||||
18,64991,16,18,1,29,1 1 1 1 3 1 1 3 2 1 1 1 1 1 1 1 5 3,937643113,46901,2,835771758,2,31267,13,3551
|
||||
19,17887,16,19,1,32,1 1 1 1 3 1 1 2 1 2 1 1 4 1 1 1 1 1 7,2565819707,4841,2,10560378954,1,3227,13,1503
|
||||
19,47583,16,19,2,32,1 1 1 1 3 1 1 1 1 3 2 1 1 1 2 1 2 4 4,2406486331,12877,1,8235856020,1,17169,13,2527
|
||||
21,50655,16,21,2,36,1 1 1 1 3 1 1 2 1 2 2 1 1 1 1 3 3 2 1 1 6,26693613331,7711,1,164317017396,1,10281,13,1503
|
||||
22,39391,16,22,2,36,1 1 1 1 3 1 1 1 1 2 2 1 1 1 1 3 1 4 1 2 2 4,63347945785,17989,1,80634191772,3,23985,13,2527
|
||||
22,55775,16,22,2,36,1 1 1 1 3 1 1 1 1 2 1 2 1 2 4 1 1 1 2 3 1 4,75192250681,25471,1,80634191772,3,33961,13,2527
|
||||
23,57823,16,23,1,38,1 1 1 1 3 1 1 1 3 1 1 3 1 2 2 1 1 1 1 4 2 2 3,315917712299,19805,2,636347363178,1,13203,13,479
|
||||
24,4575,16,24,1,38,1 1 1 1 3 1 1 1 2 1 1 2 1 1 3 2 3 1 1 2 1 1 1 5,635666957057,4703,2,259774647870,4,3135,13,479
|
||||
25,37343,16,25,2,41,1 1 1 1 3 1 1 1 2 1 1 1 1 1 1 1 3 1 1 3 3 2 2 1 6,1447081707779,14389,1,3207915328884,2,19185,13,479
|
||||
25,53727,16,25,1,40,1 1 1 1 3 1 1 1 2 1 2 3 1 2 1 2 2 2 2 1 1 1 2 2 3,3003828521219,41405,2,1603957664442,4,27603,13,479
|
||||
26,23007,16,26,1,41,1 1 1 1 3 1 1 1 1 2 1 1 4 1 1 1 3 2 1 1 1 2 1 3 4 1,6714415551241,26597,2,1513338109998,8,17731,13,2527
|
||||
26,58847,16,26,2,44,1 1 1 1 3 1 1 2 1 1 1 2 1 2 1 1 1 1 2 4 2 1 2 1 3 6,5179535992585,8503,1,42609094819932,1,11337,13,1503
|
||||
30,43487,16,30,1,48,1 1 1 1 3 1 1 1 1 1 1 2 1 2 1 1 1 1 1 1 3 1 1 3 3 3 4 1 2 3,412822742676953,31811,2,432642665942670,2,21207,13,2527
|
||||
33,56799,16,33,1,53,1 1 1 1 3 1 1 3 1 1 2 1 1 1 1 1 2 1 4 1 1 1 2 3 1 1 2 1 1 4 1 3 3,16303153667805667,35057,2,15903476631111930,2,23371,13,3551
|
||||
35,59871,16,35,2,58,1 1 1 1 3 1 1 1 1 1 1 1 1 1 2 1 5 1 2 1 4 1 2 1 1 1 3 1 1 2 3 1 2 1 6,139662722528697595,10393,1,664564948059136404,1,13857,13,2527
|
||||
41,35295,16,41,1,65,1 1 1 1 3 1 1 1 1 1 2 1 1 1 1 1 2 2 1 1 3 1 4 1 1 5 1 1 1 1 1 2 2 2 1 1 2 1 3 3 3,83861771946701186755,34895,2,37734471687915736890,4,23263,13,2527
|
||||
42,27103,16,42,1,68,1 1 1 1 3 1 1 1 1 1 1 1 4 3 2 1 2 1 1 1 1 1 2 1 2 2 1 2 1 1 1 1 1 1 4 4 2 1 3 1 1 5,358436715937075385417,10049,2,666605737275033759150,1,6699,13,2527
|
||||
44,42463,16,44,1,71,1 1 1 1 3 1 1 2 1 1 2 1 1 1 1 1 2 4 3 1 2 1 1 1 1 1 1 1 1 1 3 1 2 2 4 1 1 2 1 1 1 1 3 7,2589569629459408059025,17711,2,5114007919937245354782,1,11807,13,1503
|
||||
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"clauses": [
|
||||
3551,
|
||||
19935,
|
||||
36319,
|
||||
52703
|
||||
],
|
||||
"covered": [
|
||||
3551,
|
||||
19935,
|
||||
36319,
|
||||
52703
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
@ -0,0 +1,127 @@
|
||||
{
|
||||
"clauses": [
|
||||
479,
|
||||
1503,
|
||||
2527,
|
||||
4575,
|
||||
5599,
|
||||
6623,
|
||||
7647,
|
||||
8671,
|
||||
9695,
|
||||
10719,
|
||||
11743,
|
||||
12767,
|
||||
13791,
|
||||
14815,
|
||||
15839,
|
||||
16863,
|
||||
17887,
|
||||
18911,
|
||||
20959,
|
||||
21983,
|
||||
23007,
|
||||
24031,
|
||||
25055,
|
||||
26079,
|
||||
27103,
|
||||
28127,
|
||||
29151,
|
||||
30175,
|
||||
31199,
|
||||
32223,
|
||||
33247,
|
||||
34271,
|
||||
35295,
|
||||
37343,
|
||||
38367,
|
||||
39391,
|
||||
40415,
|
||||
41439,
|
||||
42463,
|
||||
43487,
|
||||
44511,
|
||||
45535,
|
||||
46559,
|
||||
47583,
|
||||
48607,
|
||||
49631,
|
||||
50655,
|
||||
51679,
|
||||
53727,
|
||||
54751,
|
||||
55775,
|
||||
56799,
|
||||
57823,
|
||||
58847,
|
||||
59871,
|
||||
60895,
|
||||
61919,
|
||||
62943,
|
||||
63967,
|
||||
64991
|
||||
],
|
||||
"covered": [
|
||||
479,
|
||||
1503,
|
||||
2527,
|
||||
4575,
|
||||
5599,
|
||||
6623,
|
||||
7647,
|
||||
8671,
|
||||
9695,
|
||||
10719,
|
||||
11743,
|
||||
12767,
|
||||
13791,
|
||||
14815,
|
||||
15839,
|
||||
16863,
|
||||
17887,
|
||||
18911,
|
||||
20959,
|
||||
21983,
|
||||
23007,
|
||||
24031,
|
||||
25055,
|
||||
26079,
|
||||
27103,
|
||||
28127,
|
||||
29151,
|
||||
30175,
|
||||
31199,
|
||||
32223,
|
||||
33247,
|
||||
34271,
|
||||
35295,
|
||||
37343,
|
||||
38367,
|
||||
39391,
|
||||
40415,
|
||||
41439,
|
||||
42463,
|
||||
43487,
|
||||
44511,
|
||||
45535,
|
||||
46559,
|
||||
47583,
|
||||
48607,
|
||||
49631,
|
||||
50655,
|
||||
51679,
|
||||
53727,
|
||||
54751,
|
||||
55775,
|
||||
56799,
|
||||
57823,
|
||||
58847,
|
||||
59871,
|
||||
60895,
|
||||
61919,
|
||||
62943,
|
||||
63967,
|
||||
64991
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
25
docs/artefacts/collatz/local_E13_palier2p16/metadata.json
Normal file
25
docs/artefacts/collatz/local_E13_palier2p16/metadata.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"state_id": 13,
|
||||
"base_palier": 12,
|
||||
"target_palier": 16,
|
||||
"delta_m": 4,
|
||||
"lift_size": 64,
|
||||
"d8": {
|
||||
"k": 8,
|
||||
"threshold_Ak": 13,
|
||||
"candidates": 4,
|
||||
"covered": 4,
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p16/certificats/certificat_D8_E13_palier2p16.json"
|
||||
},
|
||||
"fusion": {
|
||||
"t_min": 9,
|
||||
"t_max_search": 128,
|
||||
"t_max_used": 44,
|
||||
"merged_csv": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p16/candidats/candidats_F9to44_E13_palier2p16.csv",
|
||||
"certificate": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p16/certificats/certificat_F9to44_E13_palier2p16.json",
|
||||
"clauses": 60,
|
||||
"covered": 60
|
||||
},
|
||||
"verification_md": "/home/ncantu/code/algo/docs/artefacts/collatz/local_E13_palier2p16/audits/verification_H6_E13_palier2p16.md",
|
||||
"success": true
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"noyau": [
|
||||
479,
|
||||
1503,
|
||||
2527,
|
||||
3551
|
||||
],
|
||||
"palier": 12
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
{
|
||||
"noyau": [
|
||||
479,
|
||||
1503,
|
||||
2527,
|
||||
3551,
|
||||
4575,
|
||||
5599,
|
||||
6623,
|
||||
7647,
|
||||
8671,
|
||||
9695,
|
||||
10719,
|
||||
11743,
|
||||
12767,
|
||||
13791,
|
||||
14815,
|
||||
15839,
|
||||
16863,
|
||||
17887,
|
||||
18911,
|
||||
19935,
|
||||
20959,
|
||||
21983,
|
||||
23007,
|
||||
24031,
|
||||
25055,
|
||||
26079,
|
||||
27103,
|
||||
28127,
|
||||
29151,
|
||||
30175,
|
||||
31199,
|
||||
32223,
|
||||
33247,
|
||||
34271,
|
||||
35295,
|
||||
36319,
|
||||
37343,
|
||||
38367,
|
||||
39391,
|
||||
40415,
|
||||
41439,
|
||||
42463,
|
||||
43487,
|
||||
44511,
|
||||
45535,
|
||||
46559,
|
||||
47583,
|
||||
48607,
|
||||
49631,
|
||||
50655,
|
||||
51679,
|
||||
52703,
|
||||
53727,
|
||||
54751,
|
||||
55775,
|
||||
56799,
|
||||
57823,
|
||||
58847,
|
||||
59871,
|
||||
60895,
|
||||
61919,
|
||||
62943,
|
||||
63967,
|
||||
64991
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
{
|
||||
"noyau": [
|
||||
479,
|
||||
1503,
|
||||
2527,
|
||||
4575,
|
||||
5599,
|
||||
6623,
|
||||
7647,
|
||||
8671,
|
||||
9695,
|
||||
10719,
|
||||
11743,
|
||||
12767,
|
||||
13791,
|
||||
14815,
|
||||
15839,
|
||||
16863,
|
||||
17887,
|
||||
18911,
|
||||
20959,
|
||||
21983,
|
||||
23007,
|
||||
24031,
|
||||
25055,
|
||||
26079,
|
||||
27103,
|
||||
28127,
|
||||
29151,
|
||||
30175,
|
||||
31199,
|
||||
32223,
|
||||
33247,
|
||||
34271,
|
||||
35295,
|
||||
37343,
|
||||
38367,
|
||||
39391,
|
||||
40415,
|
||||
41439,
|
||||
42463,
|
||||
43487,
|
||||
44511,
|
||||
45535,
|
||||
46559,
|
||||
47583,
|
||||
48607,
|
||||
49631,
|
||||
50655,
|
||||
51679,
|
||||
53727,
|
||||
54751,
|
||||
55775,
|
||||
56799,
|
||||
57823,
|
||||
58847,
|
||||
59871,
|
||||
60895,
|
||||
61919,
|
||||
62943,
|
||||
63967,
|
||||
64991
|
||||
],
|
||||
"palier": 16
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
**Auteur** : Équipe 4NK
|
||||
|
||||
# Vérification H6(E14) — couverture des relèvements au palier \(2^{15}\)
|
||||
|
||||
## Objet
|
||||
|
||||
Vérifier, au sens “certifié D/F” (appartenance aux ensembles `covered` de certificats), que l’union des certificats locaux couvre le domaine des relèvements impairs.
|
||||
|
||||
## Domaine
|
||||
|
||||
- base : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E14_palier2p15/noyaux/noyau_E14_B12.json`
|
||||
- relevé : `/home/ncantu/code/algo/docs/artefacts/collatz/local_E14_palier2p15/noyaux/noyau_Lift_E14_palier2p15.json`
|
||||
- taille : 32
|
||||
|
||||
## Certificats utilisés (local)
|
||||
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E14_palier2p15/certificats/certificat_D8_E14_palier2p15.json`
|
||||
- covered : 2 classes
|
||||
- `/home/ncantu/code/algo/docs/artefacts/collatz/local_E14_palier2p15/certificats/certificat_F9to41_E14_palier2p15.json`
|
||||
- covered : 30 classes
|
||||
|
||||
## Résultat
|
||||
|
||||
- |L| = 32
|
||||
- |U| = 32
|
||||
- |L \ U| = 0
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user