khtst-rust / scripts /48_suite_som.py
PowerMachine's picture
v0.5.0: suíte SOM-4D + suíte JEPA (12) + tecnologia Pensamento + telemetria Theil–Sen — 29/29 gates verdes (provas r-18..r-22)
e26f4cc verified
Raw History Blame Contribute Delete
5.35 kB
#!/usr/bin/env python3
"""48_suite_som.py — Suíte SOM v0.5.0: 4D-SOM, T-SOM, GNG, H-SOM.
Demos com estrutura topológica CONHECIDA (critérios de falsificação das
provas r-19):
- 4D-SOM: 4 aglomerados em 4D — EQ deve cair, TE deve cair (Teos S4-1/S4-2)
- T-SOM: deriva linear — EQ temporal estabiliza (Teo T-1, rastreio)
- GNG: 3 aglomerados — crescimento + componentes conexas (Teo G-1)
- H-SOM: decomposição — cota do Teo H-1 respeitada E QE_hier ≤ QE_grosso
Saída: resultados/suite_som_v050.json
"""
import json, os, random, sys, time
def main():
import khtst_rust.nucleo_rust as nr
pasta = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
res = {"versao": "0.5.0", "modulo": nr.versao(), "suites": {}}
# ---------------------------------------------------------------- 4D-SOM
print("=== 4D-SOM (grade neuronal 4D) ===", flush=True)
rng = random.Random(7)
dados = []
for _ in range(240):
bloco = rng.randrange(4)
c = [[-3, -3, -3, -3], [3, -3, 3, -3], [-3, 3, -3, 3], [3, 3, 3, 3]][bloco]
dados.append([v + rng.gauss(0, 0.4) for v in c])
t0 = time.time()
som = nr.treinar_som4d(dados, json.dumps({
"nx": 4, "ny": 4, "nz": 2, "nt": 2, "epocas": 150,
"sigma0": 1.2, "sigma1": 0.4, "eta0": 0.6, "eta1": 0.1,
"espalhada": True,
}))
dt = time.time() - t0
queda_eq = 100.0 * (1 - som["eq_final"] / som["eq_inicial"])
print(f" EQ: {som['eq_inicial']:.4f} -> {som['eq_final']:.4f} (-{queda_eq:.1f}%) | TE: {som['te_final']:.4f} | {dt:.1f}s")
res["suites"]["som4d"] = {
**{k: som[k] for k in ("eq_inicial", "eq_final", "te_final", "celulas", "grade", "massa_soma")},
"queda_eq_pct": queda_eq, "tempo_s": dt,
"gate_eq_cai": som["eq_final"] < som["eq_inicial"],
"gate_te_baixo": som["te_final"] < 0.3,
"gate_massa_valida": abs(som["massa_soma"] - 1.0) < 1e-6,
}
# ---------------------------------------------------------------- T-SOM
print("=== T-SOM (Time SOM 4D com esquecimento) ===", flush=True)
rng = random.Random(11)
iniciais = [[rng.gauss(0, 0.5) for _ in range(3)] for _ in range(96)]
tsom = nr.demo_tsom(iniciais, [[rng.gauss(0, 0.5) for _ in range(3)] for _ in range(32)], 25, 0.9)
hist = tsom["eq_temporal_historico"]
# com deriva simulada DENTRO da janela (recência pondera mais), o EQ
# temporal fica limitado — o filtro acompanha (Teo T-1)
print(f" EQ temporal: inicio {hist[0]:.4f} | fim {hist[-1]:.4f} | max {max(hist):.4f}")
res["suites"]["tsom"] = {
"gamma": tsom["gamma"],
"eq_temporal_historico": hist,
"gate_rastreio_limitado": max(hist) < 2.0 and hist[-1] < hist[0] * 1.5 + 0.5,
}
# ---------------------------------------------------------------- GNG
print("=== GNG (Growing Neural Gas) ===", flush=True)
rng = random.Random(3)
dados_gng = []
for c in [[-5, 0, 0, 0], [5, 0, 0, 0], [0, 5, 0, 0]]:
for _ in range(70):
dados_gng.append([v + rng.gauss(0, 0.3) for v in c])
t0 = time.time()
gng = nr.treinar_gng(dados_gng, json.dumps({"passos": 8000, "max_vertices": 45, "lambda": 60}))
dt = time.time() - t0
print(f" vertices: {gng['vertices']} | arestas: {gng['arestas']} | EQ medio: {gng['eq_medio']:.4f} | {dt:.1f}s")
res["suites"]["gng"] = {
**{k: gng[k] for k in ("vertices", "arestas", "componentes_conexas", "insercoes", "eq_medio")},
"tempo_s": dt,
"gate_cresceu": gng["vertices"] >= 10,
"gate_eq_baixo": gng["eq_medio"] < 0.8,
}
# ---------------------------------------------------------------- H-SOM
print("=== H-SOM (hierárquico) ===", flush=True)
rng = random.Random(21)
dados_h = []
for c in [[-2, -2, 0], [2, -2, 0], [-2, 2, 0], [2, 2, 0]]:
for _ in range(60):
dados_h.append([v + rng.gauss(0, 0.5) for v in c])
t0 = time.time()
hsom = nr.treinar_hsom(dados_h, json.dumps({"celulas_finas": 9, "epocas_finas": 20}))
dt = time.time() - t0
print(f" QE hier: {hsom['eq_hierarquico']:.4f} | QE grosso: {hsom['eq_grosso']:.4f} | R_fino: {hsom['r_fino']:.4f} | {dt:.1f}s")
res["suites"]["hsom"] = {
**{k: hsom[k] for k in ("eq_hierarquico", "eq_grosso", "r_fino", "cota_teo_h1", "cota_respeitada")},
"tempo_s": dt,
"gate_hier_melhora": hsom["eq_hierarquico"] <= hsom["eq_grosso"] + 1e-9,
}
# ---------------------------------------------------------------- resumo
gates = []
for nome, s in res["suites"].items():
gates += [(f"{nome}.{g[5:]}", v) for g, v in s.items() if g.startswith("gate_")]
ok = sum(1 for _, v in gates if v)
res["resumo"] = {"gates_totais": len(gates), "gates_ok": ok,
"todos_verdes": ok == len(gates)}
print(f"\n=== RESUMO: {ok}/{len(gates)} gates verdes ===")
for g, v in gates:
print(f" {'OK ' if v else 'FALHOU'} {g}")
os.makedirs(os.path.join(pasta, "resultados"), exist_ok=True)
with open(os.path.join(pasta, "resultados", "suite_som_v050.json"), "w") as f:
json.dump(res, f, indent=1, ensure_ascii=False)
print("salvo: resultados/suite_som_v050.json")
if not res["resumo"]["todos_verdes"]:
sys.exit(1)
if __name__ == "__main__":
main()