File size: 4,964 Bytes
bb2363d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/env python3
"""55_verificador_ncm.py — v0.6.0: o validador do Pensamento passa a ser a
PRÓPRIA CONFIANÇA DO NCM, calibrada (r-21 §3.1 fechado; provas r-23).

Demos:
  1. calibração de temperatura em dados retidos (V-1): T*, ECE antes/depois;
  2. soundness sem oráculo (V-2): P(erro|aceito) ≤ 1−τ_c+ECE+folga;
  3. τ_c por quantil DKW (V-3);
  4. ciclo d do Pensamento com o verificador NCM (produção, sem oráculo)
     — ganho de confiança vs 1 rede isolada;
  5. escalonamento com N sob o verificador NCM.

Saída: resultados/verificador_ncm_v060.json
"""
import json, os, time

def main():
    import khtst_rust.nucleo_rust as nr

    pasta = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    res = {"versao": "0.6.0", "modulo": nr.versao(), "demos": {}}

    # -------------------------------------------- 1-3: calibração + soundness
    print("=== Verificador NCM: calibração (V-1) + soundness (V-2) + DKW (V-3) ===", flush=True)
    t0 = time.time()
    v = nr.demo_verificador_ncm(n=3000, k=24, semente=42)
    dt = time.time() - t0
    print(f"  temperatura calibrada T*: {v['temperatura_calibrada']:.4f}")
    print(f"  ECE: {v['ece_antes']:.4f} -> {v['ece_depois']:.4f} (NLL {v['nll_antes']:.4f} -> {v['nll_depois']:.4f})")
    print(f"  tau_c (DKW, eps=0.25): {v['tau_c_dkw']:.4f}")
    print(f"  P(erro|aceito) = {v['p_erro_aceito']:.4f} <= cota {v['cota_soundness']:.4f} -> {v['soundness_ok']}")
    print(f"  (referência: acerto do ORÁCULO no mesmo problema = {v['acerto_oraculo_referencia']:.4f} — inacessível em produção)")
    res["demos"]["calibracao_soundness"] = {**v, "tempo_s": dt}

    # -------------------------------------------- 4: ciclo d SEM oráculo
    print("\n=== Ciclo d com verificador NCM (sem oráculo) ===", flush=True)
    t0 = time.time()
    d = nr.demo_pensamento_ncm(
        d_cond=12, d_saida=6, n_tentativas=5,
        passos_treino=220, limiar_conf=0.92, orcamento=6, semente=42,
    )
    dt = time.time() - t0
    print(f"  treino cooperativo: {d['perda_treino_inicial']:.4f} -> {d['perda_treino_final']:.4f} (aprendeu: {d['treino_aprendeu']})")
    print(f"  ECE do verificador: {d['ece_verificador_antes']:.4f} -> {d['ece_verificador_depois']:.4f} (T*={d['temperatura_calibrada']:.3f})")
    print(f"  ciclo d: {d['iteracoes_ciclo_d_media']:.1f} iterações médias | conf base 1 rede: {d['confianca_base_1_rede']:.4f}")
    print(f"  conf Pensamento (N=5, verificador NCM): {d['confianca_pensamento']:.4f} (ganho {d['ganho_confianca']:+.4f})")
    print(f"  OOD honesto: base {d['confianca_ood_base']:.4f} -> pensamento {d['confianca_ood_pensamento']:.4f} (iterações {d['iteracoes_ood']})")
    res["demos"]["ciclo_d_sem_oraculo"] = {
        **d, "tempo_s": dt,
        "gate_aprendeu": d["treino_aprendeu"],
        "gate_terminou": d["iteracoes_ciclo_d_media"] <= 6,
        "gate_sem_oraculo": True,
    }

    # -------------------------------------------- 5: escalonamento com N
    print("\n=== Escalonamento com N (verificador NCM, consultas retidas) ===", flush=True)
    escal = []
    for n in (1, 2, 4, 8):
        r = nr.demo_pensamento_ncm(
            d_cond=12, d_saida=6, n_tentativas=n,
            passos_treino=180, limiar_conf=0.95, orcamento=8, semente=100 + n,
        )
        escal.append({
            "n": n,
            "conf_base": r["confianca_base_1_rede"],
            "conf_pensamento": r["confianca_pensamento"],
            "ganho": r["ganho_confianca"],
            "iteracoes": r["iteracoes_ciclo_d_media"],
        })
        print(f"  N={n}: base {r['confianca_base_1_rede']:.4f} -> pensamento {r['confianca_pensamento']:.4f} (ganho {r['ganho_confianca']:+.4f})")
    n1, nn = escal[0]["conf_pensamento"], escal[-1]["conf_pensamento"]
    res["demos"]["escalonamento_n"] = {
        "serie": escal, "confianca_n1": n1, "confianca_n_max": nn,
        "gate_tp2_ncm": nn >= n1 - 0.05,
    }

    # ------------------------------------------------------------------ resumo
    gates = []
    for nome, s in res["demos"].items():
        gates += [(f"{nome}.{g[5:]}", val) for g, val in s.items() if g.startswith("gate_")]
        # gates aninhados do Rust (honestidade: conta TODOS)
        if isinstance(s.get("gates"), dict):
            gates += [(f"{nome}.{g[5:]}", val) for g, val in s["gates"].items() if g.startswith("gate_")]
    ok = sum(1 for _, val in gates if val)
    res["resumo"] = {"gates_totais": len(gates), "gates_ok": ok, "todos_verdes": ok == len(gates)}
    print(f"\n=== RESUMO: {ok}/{len(gates)} gates verdes ===")

    os.makedirs(os.path.join(pasta, "resultados"), exist_ok=True)
    with open(os.path.join(pasta, "resultados", "verificador_ncm_v060.json"), "w") as f:
        json.dump(res, f, indent=1, ensure_ascii=False)
    print("salvo: resultados/verificador_ncm_v060.json")
    if not res["resumo"]["todos_verdes"]:
        raise SystemExit(1)

if __name__ == "__main__":
    main()