File size: 4,032 Bytes
f4c204d e4ee5c4 f4c204d e4ee5c4 f4c204d e4ee5c4 f4c204d e4ee5c4 f4c204d e4ee5c4 f4c204d e4ee5c4 f4c204d e4ee5c4 f4c204d e4ee5c4 f4c204d e4ee5c4 f4c204d e4ee5c4 | 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 | //! PROVAS EXECUTÁVEIS (gates de integração) do KHTST_RUST v0.7.0.
//!
//! Regra da casa (r-08 §1): *contar a estrutura não é verificar a função* —
//! toda verificação precisa de um `assert` que FALHE se o invariante quebrar.
//! Os 54 testes unitários vivem inline em cada módulo; ESTE arquivo contém os
//! GATES DE INTEGRAÇÃO entre módulos (vazamentos, paridades, neutralidades
//! e os gates novos da v0.7.0: FNH, árvore de pesos, quebra-cabeça, NLP/NLG).
//!
//! Histórico: os gates G1/G2/G4/G10 da v0.3.0 migraram para a suíte Python
//! (V4 máscara 0 vazamentos, V10 paridade NFE=L) e para testes inline dos
//! módulos (ssd, quantizador, mascaras); os gates G9/G12 da mistura de planos
//! tornaram-se obsoletos com a remoção da CabecaMistura (v0.4.0 — a mistura
//! vive hoje no verificador, ver F_mistura_verificador.md e verificador.rs).
//!
//! | gate | o que prova | módulos |
//! |---|---|---|
//! | G5 | nascimento neutro do FiLM (γ=β=ξ=ζ=0 ⇒ identidade) | gerador+tronco |
//! | M8 | PCGrad não-piora (⟨g_comb, g_i⟩ ≥ 0 ∀i) | perdas+treino |
//! | G13 | FNH: R∈SO(n) exato + neutralidade com punição baixa | fnh |
//! | G14 | FNH: gate de punição monotoneidade + migração de escala idempotente | fnh |
//! | G15 | árvore de pesos: partição de índices + simetria das arestas duplas | arvore_pesos |
//! | G16 | árvore: agregação fundo-topo = soma global (indução na árvore) | arvore_pesos |
//! | G17 | quebra-cabeça: todo aceito tem confiança ≥ τ_c (soundness V-2) | pensamento+verificador |
//! | G18 | NLP/NLG: nascimento neutro (Δ=0 bit-a-bit) | nlp+nlg |
//! | G19 | decodificador especulativo: inocuidade (distribuição preservada) | nlg |
//! | G20 | rotação no Pensamento: ortogonalidade preservada pós-ciclo | pensamento+stiefel |
use candle_core::{Device, Result, Tensor};
/// G5 — NASCIMENTO NEUTRO: com o tronco recém-construído (γ=0, β=0, ξ=0,
/// ζ=0), aplicar_film é a IDENTIDADE bit-a-bit, qualquer que seja o resumo.
#[test]
fn gate_g5_nascimento_neutro_film() -> Result<()> {
use khtst_rust::config::ConfigKhtst;
use khtst_rust::gerador::GeradorConceitos;
let mut cfg = ConfigKhtst::default();
cfg.modelo.vocab = 64;
cfg.modelo.d_modelo = 32;
cfg.modelo.n_camadas = 2;
cfg.modelo.n_cabecas = 4;
cfg.modelo.d_ff = 64;
cfg.modelo.comprimento_ctx = 8;
cfg.ncm.niveis = vec![2, 4, 8];
cfg.ncm.d_lat = 8;
cfg.ncm.k_por_nivel = 8;
cfg.ncm.ativo = true;
cfg.modelo.mtp.ativo = false;
cfg.validar().expect("config do gate G5");
let dev = Device::Cpu;
let ger = GeradorConceitos::novo(&cfg, &dev)?;
let x = Tensor::randn(0f32, 1f32, (2, 4, cfg.modelo.d_modelo), &dev)?;
let resumo = Tensor::randn(0f32, 1f32, (2, cfg.modelo.d_modelo), &dev)?;
for nivel in 1..=cfg.l_niveis() {
let y = ger.tronco.aplicar_film(&x, &resumo, nivel)?;
let dif = (&x - &y)?.abs()?.max_all()?.to_scalar::<f32>()?;
assert_eq!(dif, 0.0, "G5: FiLM deve ser identidade no nascimento (nível {nivel})");
}
Ok(())
}
/// M8 — PCGrad projeta contra os gradientes ORIGINAIS (invariante de
/// não-piora: ⟨g_combinado, g_i⟩ ≥ 0 para toda perda i).
#[test]
fn gate_m8_pcgrad_nao_piora() {
let g1 = vec![Some(vec![1.0f32]), Some(vec![-2.0])];
let g2 = vec![Some(vec![-1.0f32]), Some(vec![0.5])];
let combinado = khtst_rust::treino::pcgrad_achatado(vec![g1.clone(), g2.clone()]);
let ip = |a: &Vec<Option<Vec<f32>>>, b: &Vec<Option<Vec<f32>>>| -> f64 {
let mut s = 0f64;
for (x, y) in a.iter().zip(b.iter()) {
if let (Some(x), Some(y)) = (x, y) {
s += x.iter().zip(y.iter()).map(|(p, q)| *p as f64 * *q as f64).sum::<f64>();
}
}
s
};
let ip1 = ip(&combinado, &g1);
let ip2 = ip(&combinado, &g2);
assert!(ip1 >= -1e-9, "⟨g, g1⟩ = {ip1} ≥ 0 (não-piora)");
assert!(ip2 >= -1e-9, "⟨g, g2⟩ = {ip2} ≥ 0 (não-piora)");
}
|