khtst-rust / scripts /62_suite_fnh.py
PowerMachine's picture
v0.7.0: FNH gate de punição + árvore de pesos indexada (arestas duplas) + quebra-cabeça do Pensamento + NLP/NLG + decodificador especulativo + auto-ajuste SOM limitado + correções v070-1/2/3 — 73/73 gates, 84/84 cargo, provas r-28..r-32
4dbc907 verified
Raw History Blame Contribute Delete
3.43 kB
#!/usr/bin/env python3
"""62_suite_fnh.py — v0.7.0: gates da FNH + ablação rotação/ortogonalidade
EM TREINO (r-29 §3; requisitos: "construir em rust fnh_layer quando a
punição estiver alta" + "testar e verificar uso de rotação e
ortogonalidade em treinamento").
Gates:
F1 rotação SO(n) exata (δ_ort ≤ 1e-6) — cargo test f1;
F2 nascimento neutro bit-a-bit — cargo test f2;
F3 gate zona morta exata + monotonia — cargo test f3;
F4 homeostase (gradiente a θ estrangulado com g=0) — cargo test f4;
F6 migração compensada identidade — cargo f6;
F7 balanço AM-GM — cargo f7;
A1 ablação: π alta ⇒ θ aprende; π baixa ⇒ θ congelado (demo_fnh);
A2 δ_ort do codebook da fase A mantido (rotação no treino real).
"""
import json, os, sys
def main():
pasta = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, pasta)
import khtst_rust as K
rel = {"versao": "fnh-suite-0.7.0", "gates": {}}
# ablação sintética controlada (mecanismo)
fnh = K.demo_fnh()
alta, baixa = fnh["resumo"]["punicao_alta"], fnh["resumo"]["punicao_baixa"]
rel["gates"]["f1_so_n_exato"] = alta["delta_ort"] < 1e-6
rel["gates"]["f3_gate_zona_morta"] = baixa["gate_final"] == 0.0
rel["gates"]["f3_gate_abre"] = alta["gate_final"] > 0.5
rel["gates"]["f4_homeostase_theta_congelado"] = baixa["theta_norma"] == 0.0
rel["gates"]["f4_rotacao_aprende_com_punicao"] = alta["theta_norma"] > 0.0
rel["ablaton"] = {"alta": alta, "baixa": baixa}
# treino real: δ_ort do CODEBOOK TREINADO (medido pelo 63 no checkpoint
# da fase A — rotação Stiefel EM treino real) + punição da fase C
t70 = os.path.join(pasta, "resultados", "treino_v070.json")
aq = os.path.join(pasta, "resultados", "arvore_quebra_v070.json")
d_ort = None
if os.path.exists(aq):
with open(aq) as f:
d_ort = json.load(f).get("quebra_cabeca_real", {}).get("delta_ort_codebook")
if d_ort is None:
# mede direto (o 63 roda depois se preciso — aqui executa a medição)
ck_tok = os.path.join(pasta, "resultados", "tokenizador_conceitos.json")
ck_ger = os.path.join(pasta, "resultados", "gerador_conceitos.json")
if os.path.exists(ck_tok) and os.path.exists(ck_ger):
cfg = K.Config(os.path.join(pasta, "configs", "base_rust.json"))
qc = K.quebra_cabeca_real(cfg, ck_tok, ck_ger, n_pecas=2,
n_rodadas=1, tau_c=1.1, nivel=0, seed=1)
d_ort = qc.get("delta_ort_codebook")
if d_ort is not None:
rel["gates"]["a2_delta_ort_treino_real"] = d_ort < 1e-5
rel["treino_real"] = {"delta_ort_codebook": d_ort}
if os.path.exists(t70):
with open(t70) as f:
tr = json.load(f)
pun = tr.get("fnh", {}).get("punicao_normalizada_fase_c", 0.0)
rel["gates"]["a3_punicao_real_medida"] = 0.0 <= pun <= 1.0
# veredito
n_ok = sum(1 for v in rel["gates"].values() if v)
rel["veredito"] = f"{n_ok}/{len(rel['gates'])}"
saida = os.path.join(pasta, "resultados", "suite_fnh_v070.json")
with open(saida, "w") as f:
json.dump(rel, f, indent=1, ensure_ascii=False)
print(json.dumps(rel["gates"], indent=1))
print("VEREDITO FNH:", rel["veredito"])
assert n_ok == len(rel["gates"]), "gate FNH falhou"
if __name__ == "__main__":
main()