PowerMachine commited on
Commit
f01b8a7
·
verified ·
1 Parent(s): c4da49c

KHTST v17 — pacote aprimoramento (6 módulos refatorados, defeitos D1–D14 provados doc 29) + controlador HÍBRIDO RM+PI+bisseção + tabela de 18 sinais (AdamW/Muon/PRS/pesos/ABMO/CIAR/crescimento) com nascimento neutro e TelemetryHub total; suíte v17 56✓; regressão v1–v16 zero; Cython prioritário (VICReg delega ao kernel compilado); sem estados de treino; sem segredos

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. PLANO_KHMAMBAJEPA.md +81 -65
  2. README.md +29 -20
  3. RELATORIO_KHTST.md +72 -116
  4. cache_dados/corpus_v16.jsonl +0 -0
  5. cache_dados/corpus_v16_novos.jsonl +0 -0
  6. cache_dados/corpus_v2.jsonl +0 -0
  7. cache_dados/tokenizador.json +0 -0
  8. cache_dados/tokenizador_v16.json +0 -0
  9. cache_dados/tokenizador_v17.json +0 -0
  10. docs/matematica/29-autorregulacao-hibrida-aprimoramentos.md +556 -0
  11. docs/matematica/29-moe-empacotada-tce-sonicmoe-replayssm.md +0 -346
  12. docs/matematica/30-autoajuste-multi-metodo.md +0 -266
  13. graficos/v17/v17_evidencias.png +0 -3
  14. patches/jepa.py +4 -35
  15. scripts/21_teste_v17.py +0 -324
  16. scripts/22_graficos_v17.py +0 -162
  17. scripts/22_publicar_v17.py +160 -0
  18. scripts/23_publicar_v17.py +0 -204
  19. src/khtst/acelerado/build/lib.linux-x86_64-cpython-312/jepa_validator.cpython-312-x86_64-linux-gnu.so +0 -3
  20. src/khtst/acelerado/build/lib.linux-x86_64-cpython-312/mc_jepa.cpython-312-x86_64-linux-gnu.so +0 -3
  21. src/khtst/acelerado/build/lib.linux-x86_64-cpython-312/nucleos.cpython-312-x86_64-linux-gnu.so +0 -3
  22. src/khtst/acelerado/build/lib.linux-x86_64-cpython-312/rco_gsq.cpython-312-x86_64-linux-gnu.so +0 -3
  23. src/khtst/acelerado/build/temp.linux-x86_64-cpython-312/jepa_validator.o +0 -3
  24. src/khtst/acelerado/build/temp.linux-x86_64-cpython-312/mc_jepa.o +0 -3
  25. src/khtst/acelerado/build/temp.linux-x86_64-cpython-312/nucleos.o +0 -3
  26. src/khtst/acelerado/build/temp.linux-x86_64-cpython-312/rco_gsq.o +0 -3
  27. src/khtst/acelerado/jepa_validator.cpp +0 -0
  28. src/khtst/acelerado/jepa_validator.cpython-312-x86_64-linux-gnu.so +0 -3
  29. src/khtst/acelerado/jepa_validator.pyx +0 -433
  30. src/khtst/acelerado/mc_jepa.c +1 -1
  31. src/khtst/acelerado/mc_jepa.cpython-312-x86_64-linux-gnu.so +2 -2
  32. src/khtst/acelerado/nucleos.c +0 -0
  33. src/khtst/acelerado/nucleos.cpython-312-x86_64-linux-gnu.so +2 -2
  34. src/khtst/acelerado/rco_gsq.c +0 -0
  35. src/khtst/acelerado/rco_gsq.cpython-312-x86_64-linux-gnu.so +2 -2
  36. src/khtst/acelerado/run_verification.py +0 -368
  37. src/khtst/acelerado/setup.py +0 -11
  38. src/khtst/aprimoramento/__init__.py +40 -0
  39. src/khtst/aprimoramento/autorregulacao_estendida.py +285 -0
  40. src/khtst/aprimoramento/config.py +107 -0
  41. src/khtst/aprimoramento/controlador_hibrido.py +208 -0
  42. src/khtst/aprimoramento/difusao_gradiente.py +243 -0
  43. src/khtst/aprimoramento/jepa.py +237 -0
  44. src/khtst/aprimoramento/lambda_c_unificado.py +147 -0
  45. src/khtst/aprimoramento/metricas_qe_ct.py +191 -0
  46. src/khtst/aprimoramento/tradeoff_k.py +262 -0
  47. src/khtst/mamba3/__pycache__/hybrid.cpython-312.pyc +0 -0
  48. src/khtst/mamba3/__pycache__/kernel.cpython-312.pyc +0 -0
  49. src/khtst/mamba3/__pycache__/replay.cpython-312.pyc +0 -0
  50. src/khtst/mamba3/hybrid.py +5 -23
PLANO_KHMAMBAJEPA.md CHANGED
@@ -33,20 +33,26 @@ de parâmetros no treino E na inferência.
33
  | GSQ+RCO Stiefel total (alinhamento, NoPE, gates, RF) | ✅ v13/v14 | docs 26/27, δ_ort ≤ 3e-6 |
34
  | JEPA latente + mundo/sonho (τ, quantil, VOG) | ✅ v15.1 | doc 28 §8 (v15), 49✓ verificar |
35
  | **torchao real int8/int4 auto CPU/GPU** | ✅ v16 | doc 28 §§1–4; Teo 28.1–28.4; 237 camadas, 3.92×, Δperda 0.000 |
36
- | **MC-JEPA VICReg em Cython** (perda+gradiente analítico) | ✅ v16 | Teo 28.9; FD 4.2e-11; ≡ torch 9.6e-9 |
37
- | **Guarda anti-colapso Brain-JEPA** | ✅ v16 | Teo 28.10 |
38
- | **Autorregulação RM treino+inferência** | ✅ v16 | Teos 28.5–28.8 |
39
- | **Datasets robô LeRobot ×4 + matemática ×5** | ✅ v16 | 903 registros reais (corpus_v16) |
40
- | **MoE EMPACOTADA na quantização (bijeção φ + indexador narrow + floresta B blocos + rollback sem copy_)** | ✅ v17 | doc 29 Teos 29.1–29.4; sonda opset; fatia ≤ cota h/√12; rollback bit-exato; 3.79–3.91× |
41
- | **TCE curada (L/d + limiar invariante ‖e‖²≤θ‖alvo‖² + λ_jepa por razão ponderada)** | ✅ v17 | Teos 29.5–29.8; perda 24.96 → O(1) medido; taxa 0.0 → 1.0 |
42
- | **jepa_validator.pyx (registro C, Token Rounding exato, AuditoriaMemoriaSonic I1–I4)** | ✅ v17 | Teos 29.10–29.12; GEMM estofado bit-exato; I1 reprova vazamento sintético |
43
- | **ReplaySSM (varredura por segmentos com replay de fronteira)** | ✅ v17 | Teos 29.13–29.14; saída/h_L BIT-EXATOS; gradiente erro 0.0 |
44
- | **Autoajuste MULTI-MÉTODO (RM+PID+bisseção) — 15 controladores** | ✅ v17 | doc 30 Teos 30.1–30.15; loops verificados; τ_qk contrai 1/2; escalas no otimizador |
45
- | MoE encoder-decoder quantizada | ⏳ v18 | forward por módulo sem stack, mas agrupar()/telemetria assumem pesos planos (limitação honesta doc 29 §2.5) |
46
- | SonicMoE completo (layout/fusão de tiles no roteador) | ⏳ v18 | Token Rounding + escolher_tile já no kernel (Teo 29.11) |
47
- | Image-JEPA/V-JEPA 2/Audio/Point/3D/Brain/T/Le/BJEPA | ⏳ planejado §5 | ponte Cython + guarda prontas |
48
-
49
- ## 3. Matemática central (índice dos docs 00–30)
 
 
 
 
 
 
50
 
51
  - **00–13**: SOM e variantes, atenção mista/KV, W8A8, MoE, microunidades,
52
  escala por computo, janela 1M indexada.
@@ -64,27 +70,19 @@ de parâmetros no treino E na inferência.
64
  centro, eq. 28.12–28.14; guarda anti-colapso); Robbins–Monro
65
  multiplicativo (Σa=∞, Σa²<∞; duas escalas de Borkar; sinais lr/λ/MoE;
66
  bisseção de temperatura com erro ≤ 2^-k).
67
- - **29 (v17)**: Problema 1 — bijeção φ do empacotamento MoE (bit-exato),
68
- indexador por fatias narrow (zero-copy no subclass), floresta de B
69
- blocos (índice 2 níveis), rollback sem copy_ (substituição de .data);
70
- Problema 2 — TCE ∝ d (soma do Huber) e cura L/d (reparametrização pura
71
- λ'=λ·d), limiar invariante ‖e‖²≤θ‖alvo‖² (homogeneidade), λ_jepa pela
72
- razão PONDERADA; jepa_validator (registro C long long, Token Rounding
73
- n̂=τ⌈n/τ⌉ com GEMM estofado bit-exato, AuditoriaMemoriaSonic I1–I4);
74
- ReplaySSM (fronteiras bit-exatas por indução, gradiente exato,
75
- memória O(S·BDN+L_s·BDN)).
76
- - **30 (v17)**: autoajuste multi-método — recursão híbrida
77
- u[t+1]=u[t]+a_t·s_t+b·e_t+c_i·I_t+c_d·Δe_t (RM Σa=∞/Σa²<∞ + PID em
78
- escala rápida de Borkar + anti-windup + truncagem); estabilidade de
79
- loop em log-escala (a₀·k<2); β por CV²; ε por ‖Δp‖/‖g‖; wd por norma
80
- RELATIVA (infactibilidade do alvo absoluto — lema); momentum (o sinal
81
- literal diverge — contraexemplo; o inverso converge com a₀·β/(1−β)<2);
82
- τ_qk por bisseção (erro ≤ (τmax−τmin)/2^k); PRS η_up/η_down com ponto
83
- fixo exato E[T∞]; percentil/T_ciclo/piso; PESO_MOE (fronteira ½);
84
- PESO_SOM (ativação 90%) + lema da não-identificabilidade
85
- autorreferente; ABMO na borda da barreira; CIAR como canal derivativo
86
- do lr (inflação de variância E[(s₁s₂)²] = E[s₁²]E[s₂²]); crescimento
87
- em log-razão.
88
 
89
  ## 4. Dados (registry único — config.py + streaming.py)
90
 
@@ -113,15 +111,17 @@ de parâmetros no treino E na inferência.
113
 
114
  ## 5. Roteiro (próximas versões)
115
 
116
- 1. **v18 — MoE encoder-decoder quantizada**: desvio por pools no
117
- `_executa_experts` + `agrupar()` consciente de subclass (a fusão
118
- ponderada lê das FATIAS dequantizadas) — fecha a limitação honesta
119
- do doc 29 §2.5.
120
- 2. **v18 — SonicMoE completo**: layout dos pools por tile de GEMM
121
- (alinhamento contíguo por frequência de roteamento EMA) + top-k com
122
- índices pré-computados por segmento; Token Rounding (Teo 29.11) já
123
- disponível no kernel.
124
- 3. **v18 — JEPA family**:
 
 
125
  - Image-JEPA (máscaras de blocos no espaço latente do CodificadorImagem);
126
  - V-JEPA 2 (tubos espaço-temporais no CodificadorVideo — fonte
127
  yaak-ai/L2D + 4DNeX quando em SSD);
@@ -137,7 +137,12 @@ de parâmetros no treino E na inferência.
137
  4. **v19 — Cython total dos hot-paths**: conv1d seletiva do Mamba-3 e
138
  softmax top-k do roteador em Cython/OpenMP (prioridade Cython do
139
  requisito); detecção automática CPU/GPU mantida.
140
- 5. **Hardware chinês (CPU/GPU automático)**: camada de detecção já em
 
 
 
 
 
141
  `detectar_dispositivo()`; Mapear Ascend/MACA quando disponível
142
  (contrato torch.cuda compatível).
143
 
@@ -155,31 +160,42 @@ de parâmetros no treino E na inferência.
155
  real antes de qualquer corrida longa.
156
  - **Gráficos do card**: novas curvas SOBREPOSTAS às antigas com os
157
  melhores valores anotados (script 08/16).
158
- - **Suítes**: TODAS verdes antes de publicar (v1–v17; hoje 16 suítes).
159
  - **Memória**: este arquivo + worklog.md + RELATORIO_KHTST.md são
160
  atualizados TODA versão; redundâncias removidas.
161
 
162
  ## 7. Verificação v17 (resumo executável)
163
 
164
  ```
165
- python3 src/khtst/acelerado/run_verification.py # 8 blocos A–H (Teos 29–30)
166
- python3 tests/test_khtst_v17.py # 59 verificações
167
- python3 patches/verificar_tudo.py # 49 ✓ / 0 ✗
168
- python3 scripts/21_teste_v17.py --retreinar_tokenizador # vocab 16384
169
- python3 scripts/21_teste_v17.py --variante baseline_v16 --passos 120
170
- python3 scripts/21_teste_v17.py --variante v17_khmambajepa --passos 120
171
- python3 scripts/21_teste_v17.py --relatorio # A/B pareado real
172
  ```
173
 
174
- - v17 REAL (A/B 30 passos pareados): baseline 1.038× vs **v17 1.046×**;
175
- MoE empacotada 3.79–3.92× com Δy ≤ cota e **Δperda int8 0.0**; TCE
176
- normalizada 0.54 (v16: 24.96) com taxa 0.104 (v16: ≡ 0); ReplaySSM
177
- bit-exato (grad erro 0.0); auditoria I2/I3/I4 verdes na corrida real
178
- (I1 indicativo em janela curta — Teo 29.12-d) e reprova vazamento
179
- sintético; 15 controladores multi vivos com telemetria; gráficos em
180
- `graficos/v17/v17_evidencias.png`.
181
- - Regressão: v1–v16 TODAS verdes (25/36/✓/37/32/48/44/21/✓/✓/✓/28/27/40/45).
182
-
183
- - A/B v16 (histórico, 120 passos, corpus 903): baseline 1.811× vs v16
184
- 1.296× com JEPA+VICReg — leitura honesta no doc 28 §9 (a causa
185
- estrutural — perda ∝ d — e a cura são os Teos 29.5/29.8 da v17).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  | GSQ+RCO Stiefel total (alinhamento, NoPE, gates, RF) | ✅ v13/v14 | docs 26/27, δ_ort ≤ 3e-6 |
34
  | JEPA latente + mundo/sonho (τ, quantil, VOG) | ✅ v15.1 | doc 28 §8 (v15), 49✓ verificar |
35
  | **torchao real int8/int4 auto CPU/GPU** | ✅ v16 | doc 28 §§1–4; Teo 28.1–28.4; 237 camadas, 3.92×, Δperda 0.000 |
36
+ | **MC-JEPA VICReg em Cython** (perda+gradiente analítico) | ✅ v16 | Teo 28.9; FD 4.2e-11 (sem kink); ≡ torch 9.6e-9; ponte autograd |
37
+ | **Guarda anti-colapso Brain-JEPA** | ✅ v16 | Teo 28.10; colapso real 0.0 |
38
+ | **Autorregulação total (RM) treino+inferência** | ✅ v16 | Teos 28.5–28.8; λ_moe_lb 1.0→1.74 (demo); T por entropia-alvo (H=5.0045) |
39
+ | **Datasets robô LeRobot ×4** | ✅ v16 | fetchman 40 (902 instruções reais), endoard/Astra/mulligan com frames orçados |
40
+ | **Datasets matemática ×5** | ✅ v16 | GSM8K/MATH-500/hendrycks×2/OpenR1/IFM — resposta canônica verificável (240 registros) |
41
+ | Tarefas canônicas 14 (robo, matematica) | ✅ v16 | Teo 22.1 preservada; n_intencoes=15 dinâmico |
42
+ | **Pacote `aprimoramento` (6 módulos da rodada, refatorados)** | ✅ v17 | doc 29 §§2–6; 14 defeitos D1–D14 corrigidos; suíte v17 56✓ |
43
+ | **Controlador HÍBRIDO RM+PI+bisseção (recursão única)** | ✅ v17 | Teos 29.14–29.15; setpoint e∞=0 medido; telescoping do D exato |
44
+ | **Tabela de sinais (18 parâmetros: AdamW/Muon/PRS/pesos/ABMO/CIAR/cresc.)** | ✅ v17 | Teo 29.16; nascimento neutro; adaptadores MuonClipAdamW+PRS; TelemetryHub 100% |
45
+ | **λ_diff vivo (hipergradiente exato + âncora)** | ✅ v17 | Teo 29.2; λ* analítico ≡ numérico (5e-3) |
46
+ | **QE+CT com significância (Student-t/Bonferroni)** | ✅ v17 | Teo 29.5; 0/60 falsos-positivos; CT por coordenada |
47
+ | **Trade-off K com Ĉ estimado + unimodalidade** | ✅ v17 | Teos 29.8/29.9; K* fechado ≡ numérico ≤1%; teste do modelo por inclinação |
48
+ | SonicMoE (IO/tile-aware) | ⏳ planejado §5 | — |
49
+ | ReplaySSM | ⏳ planejado §5 | — |
50
+ | Image-JEPA/V-JEPA 2 (espaço/pixel-block) | ⏳ planejado §5 | MC-JEPA (VICReg Cython) já é o alicerce |
51
+ | Audio-JEPA / Point-JEPA / 3D-JEPA | ⏳ planejado §5 | encoders já existem (audio.py, profundidade.py) |
52
+ | Brain-JEPA (fMRI/EEG) | ⏳ parcial | guarda do passo pronta (Teo 28.10); falta dataset |
53
+ | T-JEPA / LeJEPA / BJEPA | ⏳ planejado §5 | — |
54
+
55
+ ## 3. Matemática central (índice dos docs 00–29)
56
 
57
  - **00–13**: SOM e variantes, atenção mista/KV, W8A8, MoE, microunidades,
58
  escala por computo, janela 1M indexada.
 
70
  centro, eq. 28.12–28.14; guarda anti-colapso); Robbins–Monro
71
  multiplicativo (Σa=∞, Σa²<∞; duas escalas de Borkar; sinais lr/λ/MoE;
72
  bisseção de temperatura com erro ≤ 2^-k).
73
+ - **29 (v17)**: controlador HÍBRIDO RM+PI (telescoping do termo D =
74
+ c·(e_T−e_0) — nunca desestabiliza; duas escalas de Borkar; anti-windup
75
+ direcional); bisseção do τ_qk com semântica PÓS-CLIP (Teo 24.7: ℓ =
76
+ min(ℓ_nat, τ) — direção do colchete corrigida); tabela de sinais de
77
+ 18 parâmetros (Teo 29.16 — segurança estrutural a–d); hipergradiente
78
+ EXATO de λ afim + âncora (ótimo interior provado, Teo 29.2);
79
+ unimodalidade de J1 (raiz única de G estritamente crescente, Teo
80
+ 29.9-i) + forma fechada K* e elasticidade C^{d/2}; hinge de variância
81
+ POR DIMENSÃO ≥ poolado (Jensen + lei da variância total, Teo 29.10);
82
+ colapso não é mínimo local (é MÁXIMO do hinge — Teo 29.13, com
83
+ honestidade sobre o kink do autograd); Hoeffding/Student-t com nível
84
+ α controlado (Teo 29.5); CT por coordenada (Teo 29.4); estimação de
85
+ Ĉ por OLS log-log com teste do modelo e shrinkage (Teo 29.8).
 
 
 
 
 
 
 
 
86
 
87
  ## 4. Dados (registry único — config.py + streaming.py)
88
 
 
111
 
112
  ## 5. Roteiro (próximas versões)
113
 
114
+ > **v17 ENTREGUE** (pacote `aprimoramento` + autorregulação híbrida com
115
+ > tabela de 18 sinais — doc 29; os itens abaixo foram RE-AGENDADOS):
116
+
117
+ 1. **v18 — SonicMoE**: roteamento consciente de IO (fusão de tiles,
118
+ layout de pesos para GEMM contígua, top-k com índices pré-computados
119
+ por segmento) — alvo: large-batch MoE com banda de memória como
120
+ gargalo; prova: modelo de custo RO(_transferido) e medição A/B.
121
+ 2. **v18 — ReplaySSM**: replay de estados ocultos do SSM para retomada
122
+ de contexto longa (guardar/resgatar estado + resumo indexado na
123
+ janela 1M; prova: erro de retomada vs reprocessamento O(T)).
124
+ 3. **v19 — JEPA family**:
125
  - Image-JEPA (máscaras de blocos no espaço latente do CodificadorImagem);
126
  - V-JEPA 2 (tubos espaço-temporais no CodificadorVideo — fonte
127
  yaak-ai/L2D + 4DNeX quando em SSD);
 
137
  4. **v19 — Cython total dos hot-paths**: conv1d seletiva do Mamba-3 e
138
  softmax top-k do roteador em Cython/OpenMP (prioridade Cython do
139
  requisito); detecção automática CPU/GPU mantida.
140
+ 5. **v20 — Integração da tabela v17 no treinador**: ligar
141
+ `AutorreguladorEstendido` (opt-in `treino.autorreg_v17.ativo`) com os
142
+ produtores de sinal reais (var do gradiente, taxa de trust do PRS,
143
+ razão L_moe/L_ce, ativação SOM, logit_max das NoPE) e corrida A/B
144
+ pareada antes de qualquer treino longo.
145
+ 6. **Hardware chinês (CPU/GPU automático)**: camada de detecção já em
146
  `detectar_dispositivo()`; Mapear Ascend/MACA quando disponível
147
  (contrato torch.cuda compatível).
148
 
 
160
  real antes de qualquer corrida longa.
161
  - **Gráficos do card**: novas curvas SOBREPOSTAS às antigas com os
162
  melhores valores anotados (script 08/16).
163
+ - **Suítes**: TODAS verdes antes de publicar (v1–v17; hoje 17 suítes).
164
  - **Memória**: este arquivo + worklog.md + RELATORIO_KHTST.md são
165
  atualizados TODA versão; redundâncias removidas.
166
 
167
  ## 7. Verificação v17 (resumo executável)
168
 
169
  ```
170
+ python3 tests/test_khtst_v17.py # 56 verificações (todas verdes)
171
+ python3 patches/verificar_tudo.py # 49 OK (auditoria canônica)
 
 
 
 
 
172
  ```
173
 
174
+ - **v17**: 14 defeitos D1–D14 corrigidos com prova (doc 29); suíte v17
175
+ 56✓ incluindo: hipergradiente exato, λ* analítico ≡ numérico, nível
176
+ do teste de ganho (0/60 falsos-positivos), KDTree ≡ força bruta
177
+ (100 grades), unimodalidade (20k pontos), K* fechado ≡ numérico,
178
+ Jensen per-dim (1000 espectros), fuga do colapso (σ̄ ×30), setpoint
179
+ e∞ = 0.0000 (θ=0.6000 exato), permanência EXATA nos limites,
180
+ TelemetryHub 35 chaves.
181
+ - Regressão: v1–v16 TODAS verdes (25/36/45/37/33/49/45/✓/22/49/68/29/
182
+ 28/40/—/53) + smoke18 13✓ — ZERO regressões; nenhum módulo de
183
+ produção modificado (pacote novo, aditivo).
184
+ - **Achado de auditoria da própria v17**: a 1ª implementação do
185
+ ControladorHibrido fazia DUPLA integração do termo I (i_acum somado
186
+ por passo ALÉM do b·e_t per-step) — a suíte prendeu o defeito
187
+ (setpoint não convergia) e a recursão foi corrigida para EXATAMENTE
188
+ a forma do doc 29 (e∞ = 0 medido). Honestidade de processo.
189
+
190
+ ## 8. Verificação v16 (histórico)
191
+
192
+ ```
193
+ python3 tests/test_khtst_v16.py # 45 verificações (todas verdes)
194
+ python3 src/khtst/verificar_tudo.py # auditoria canônica
195
+ python3 scripts/19_teste_v16.py --relatorio # A/B pareado real
196
+ ```
197
+
198
+ - A/B pareado (120 passos, corpus 903): baseline 1.811× vs v16 1.296×
199
+ com JEPA+VICReg — leitura honesta no doc 28 §9 (razão auxiliar e
200
+ Teo 28.7-ii); torchao com Δperda 0.000; autorreg viva (demo).
201
+ - Regressão: v1–v15 TODAS verdes (25/36/✓/37/32/48/44/21/✓/✓/✓/28/27/40).
README.md CHANGED
@@ -58,7 +58,7 @@ metrics:
58
  - meteor
59
  ---
60
 
61
- # KHTST — modelo multimodal PT-BR (v17 KHMAMBAJEPA: MoE EMPACOTADA na quantização (árvores/florestas/indexador) · TCE CURADA com provas (L/d + limiar invariante) · jepa_validator CTHONIANO com Token Rounding exato + AUDITORIA DE MEMÓRIA I1–I4 · ReplaySSM bit-exato · AUTOAJUSTE MULTI-MÉTODO RM+PID+bisseção (15 controladores) · vocab 16384)
62
 
63
  KHTST é um modelo multimodal compacto para PT-BR com roteamento por S-SOM,
64
  janela PARALELA de contexto (**N_MAX_TOKENS 393.216**), classificadores Jev
@@ -95,27 +95,36 @@ gradiente**. Provas em `docs/matematica/27`.
95
  > --teto_horas 9.0 --continuar_ate_horas 8.0 --estados_hf`).
96
 
97
 
98
- ## O que há de novo no v17 — KHMAMBAJEPA (provas em `docs/matematica/29` e `30`, memória em `PLANO_KHMAMBAJEPA.md`)
99
 
100
- | inovação | onde | prova |
 
 
 
 
 
 
 
101
  |---|---|---|
102
- | **PROBLEMA 1 RESOLVIDO — MoE EMPACOTADA na quantização**: o `torch.stack` de subclass `Int8Tensor` NÃO existe (contrato de subclasses quebrado — bug v16, sonda executável); cura = substituir EMPILHAMENTO por INDEXAÇÃO: **bijeção φ(e,i)=e·f+i** (quantização por linha ⟹ escalas idênticas ⟹ bit-exato), **indexador por fatias narrow zero-copy**, **floresta de B blocos** (índice 2 níveis; GEMM por bloco cheio; f POR PAPEL), **rollback sem copy_** (substituição de `.data` — `load_state_dict` crasha com 'qdata'); pools FORA do state_dict (dados derivados). **Medido: 3,79–3,91×, Δy 6,6e-03 ≤ cota h/√12, rollback bit-exato** | `quanta/moe_empacotador.py` (novo), `percepcao/moe.py` (desvio de inferência), `quanta/torchao_quant.py` | Teos 29.1–29.4 |
103
- | **PROBLEMA 2 RESOLVIDO — TCE da suíte v16 (perda ≈ 25, taxa ≡ 0)**: causa 1 = soma do Huber ∝ d_latente (Teo 29.5) ⟹ cura **L/d** (reparametrização pura λ'=λ·d — ∇(L/d) = ∇L/d EXATO); causa 2 = limiar absoluto ‖e‖<1 inalcançável com ‖alvo‖=√d ⟹ cura **limiar invariante ‖e‖²≤θ·‖alvo‖²** (homogêneo — taxa invariante a escala); cura 3 = **λ_jepa autorregulado pela razão PONDERADA λ·L/CE** (fronteira ½). Medido: perda O(1), taxa 0.0 → 1.0 | `treino/jepa.py`, `treino/treinador.py` | Teos 29.5–29.8 |
104
- | **jepa_validator.pyx (4º kernel Cython)**: registro das variantes JEPA em C `long long` + auditoria; **Token Rounding EXATO** no bloco de predição (n̂ = τ·⌈n/τ⌉, ρ = n̂/n, GEMM estofado BIT-EXATO nas linhas vivas, escolha de tile por custo t·ρ); **AuditoriaMemoriaSonic em tempo real** (statm nível C ~µs): I1 não-vazamento (inclinação recente + rebase), I2 recompute ≤ fwd, I3 sem transiente de empilhamento, I4 só ativos — **I1 reprova vazamento sintético; I1–I4 verdes em passos reais** | `acelerado/jepa_validator.pyx` (novo), `acelerado/setup.py`, `acelerado/run_verification.py` (novo) | Teos 29.10–29.12 |
105
- | **ReplaySSM**: varredura MAMBA-3 por S segmentos com REPLAY de estados fronteira (checkpoint use_reentrant=False, fronteira COM grad_fn): **saída e h_L BIT-EXATOS** vs kernel completo, **gradiente EXATO (erro 0,0)**, ativação O(S·BDN+L_s·BDN); cfg `mamba3.replay_segmento` (0 = v12 exato) | `mamba3/replay.py` (novo), `mamba3/kernel.py` (h_inicial), `mamba3/hybrid.py` | Teos 29.13–29.14 |
106
- | **AUTOAJUSTE MULTI-MÉTODO (requisito §§1–4)** — recursão híbrida u[t+1]=u[t]+a_t·s_t+b·e_t+c_i·I_t+c_d·Δe_t com **15 controladores**: AdamW β₁/β₂ (PID na CV²), ε (RM por ‖Δp‖/‖g‖), wd (norma RELATIVA — alvo absoluto infactível: lema), Muon momentum (o sinal literal DIVERGE — contraexemplo; o inverso converge), τ_qk por BISSECÇÃO (80–120, erro ≤ (τmax−τmin)/2^k), PRS η_up/η_down (ponto fixo exato E[T∞]), T_ciclo/piso/percentil, PESO_MOE (fronteira ½), PESO_ALINHAMENTO_SOM (ativação 90% — lema da não-identificabilidade p/ os demais), ABMO (borda da barreira), CIAR (canal derivativo), crescimento (log-razão). RM (Σa=∞,Σa²<∞) + PID em escala rápida (Borkar); anti-windup; truncagem ⟹ θ ∈ limites SEMPRE; telemetria `multi/*` integral no Hub | `nucleo/autorregulador.py` (ControladorHibrido, BissecaoTauQK, AutorregulacaoMulti), `treino/otimizadores.py` (escalas efetivas), `treino/treinador.py` | Teos 30.1–30.15 |
107
- | **vocab 16384 MANTIDO**: tokenizador retreinado @16384 no corpus real (903 registros) | `cache_dados/tokenizador_v17.json`, `scripts/21_teste_v17.py` | requisito |
108
-
109
- > ✅ **TESTE REAL v17** (30 passos pareados, corpus 903, vocab 16384):
110
- > baseline_v16 9,727→9,374 (1,038×) vs **v17 9,729→9,301 (1,046×)**;
111
- > held-out em paridade; **torchao + MoE EMPACOTADA 3,92× com Δperda 0,0**;
112
- > **TCE normalizada 0,54 (v16: 24,96 — redução ~46×) com taxa 0,104
113
- > (v16: ≡ 0)**; ReplaySSM grad erro 0,0; auditoria I2/I3/I4 verdes na
114
- > corrida real (I1 indicativo em janela curta — Teo 29.12-d). Suíte v17
115
- > 59 ✓; `run_verification.py` 8 blocos ✓; regressão v1–v16 + verificar_tudo
116
- > 49✓. Evidências: `graficos/v17/v17_evidencias.png`.
117
-
118
- ## O que houve no v16 — KHMAMBAJEPA (provas em `docs/matematica/28`)
 
 
119
 
120
  | inovação | onde | prova |
121
  |---|---|---|
 
58
  - meteor
59
  ---
60
 
61
+ # KHTST — modelo multimodal PT-BR (v16 KHMAMBAJEPA: QUANTIZAÇÃO TORCHAO REAL auto CPU/GPU · MC-JEPA VICReg em CYTHON com gradiente analítico · GUARDA ANTI-COLAPSO Brain-JEPA · AUTORREGULAÇÃO TOTAL treino+inferência (Robbins–Monro) · ROBÔ LeRobot ×4 + MATEMÁTICA verificável ×5 · 14 tarefas)
62
 
63
  KHTST é um modelo multimodal compacto para PT-BR com roteamento por S-SOM,
64
  janela PARALELA de contexto (**N_MAX_TOKENS 393.216**), classificadores Jev
 
95
  > --teto_horas 9.0 --continuar_ate_horas 8.0 --estados_hf`).
96
 
97
 
98
+ ## O que há de novo no v17 — PACOTE DE APRIMORAMENTO + AUTORREGULAÇÃO HÍBRIDA (provas em `docs/matematica/29`, memória em `PLANO_KHMAMBAJEPA.md`)
99
 
100
+ Auditoria completa (lógica + integração + matemática) dos 6 módulos
101
+ submetidos na rodada — `difusao_gradiente`, `metricas_qe_ct`,
102
+ `lambda_c_unificado`, `tradeoff_k`, `jepa`, `config` — com **14 defeitos
103
+ D1–D14 catalogados, corrigidos e PROVADOS** (doc 29, Teos 29.1–29.16).
104
+ Pacote novo `src/khtst/aprimoramento/` — nenhum módulo de produção foi
105
+ modificado (zero regressões; 17 suítes verdes).
106
+
107
+ | correção/aprimoramento | defeito corrigido | prova |
108
  |---|---|---|
109
+ | **λ_diff VIVO na difusão**: a "autoajuste por gradiente" do rascunho era triplo código morto (λ sem grad, controlador nunca chamado, perda sem λ). Agora: L(λ)=λ·L_diff+ρ(λ−λ₀)² com **hipergradiente EXATO** (∂L/∂λ = L_diff+2ρ(λ−λ₀), erro ZERO — L é afim+quadrática) e **âncora** que dá ÓTIMO INTERIOR provado λ*=λ₀−L_diff/2ρ; regret do EG ≤ G√(2T·ln(λmax/λmin)) | D1 | Teo 29.2 |
110
+ | **EMA Polyak** no denoiser (avaliar/amostrar com θ̄ — Jensen: L(θ̄) ≤ média L(θ_t)) | D2 | Teo 29.3 |
111
+ | **QE+CT comparáveis**: CT por COORDENADA (÷B·D — a soma bruta crescia com a dimensão); QE relativo a ‖x‖² (invariante a reescala); campo `normalizar` do config VIVO | D3, D14 | Teo 29.4 |
112
+ | **"ganho real" com NÍVEL α controlado**: Student-t unilateral por delta + Bonferroni (α/2 cada) — P(falso ganho) ≤ α; medido: 0/60 falsos-positivos; Hoeffding finito opcional com raio DECLARADO (o range observado INVALIDA a cota — correção honesta da 1ª versão da prova) | D4 | Teo 29.5 |
113
+ | **te_antigo via cKDTree**: O(N·log G) vs O(N·G); ≡ força bruta bit-a-bit em 100 grades | D5 | Teo 29.6 |
114
+ | **λ_c com sinal SUAVIZADO VIVO**: o rascunho computava a média da janela e JOGAVA FORA (usava ε² instantâneo); agora Δ = ε̄²−alvo (Var reduzida ×W, sem viés) + modo reversão + agenda RM opcional (η_t=η₀/(1+t/τ): Ση=∞, Ση²<∞ ⟹ q.c.) | D6, D7 | Teo 29.7 |
115
+ | **Ĉ de Zador ESTIMADO** por OLS log-log (C=1 fixo era irreal): consistência por LLN, TESTE DO MODELO pela inclinação (p̂≈−2/d; se falha, cai para a grade honestamente), shrinkage ao prior; **UNIMODALIDADE de J1 provada** (G(K) estritamente crescente ⟹ raiz única ⟹ minimize_scalar acha o GLOBAL) + forma fechada K*=[(1−λ)2C·ln d/(λd)]^{d/2} + elasticidade honesta ∂lnK*/∂lnC = d/2; λ_c adaptativo integrado | D8, D9 | Teos 29.8/29.9 |
116
+ | **JEPA anti-colapso POR DIMENSÃO**: a variância POOLADA do rascunho não vê colapso parcial (contraexemplo σ=(2,0): poolado 0, per-dim 0,5); Jensen + lei da variância total ⟹ per-dim ≥ poolado SEMPRE; condicional morto removido; **pooling adaptativo** substitui truncamento (contração ‖Pz‖≤‖z‖/√r vs energia descartada); EMA cosseno BYOL opt-in; colapso não é mínimo local (é MÁXIMO do hinge — com honestidade sobre o kink) | D10–D13 | Teos 29.10–29.13 |
117
+ | **CONTROLADOR HÍBRIDO RM+PI+bisseção** — a recursão única u_{t+1}=Π[u_t+a_t·s_t+b·e_t+c·Δe_t], θ=θ₀e^u: telescoping do D (Σc·Δe = c(e_T−e₀) — nunca desestabiliza), duas escalas de Borkar, anti-windup direcional; **τ_qk por banda [80,120] com semântica PÓS-CLIP** (ℓ=min(ℓ_nat,τ) — direção do colchete corrigida; escala exata por Teo 24.7); setpoint convergiu com e∞=0.0000 (θ=0.6000 exato) — **a 1ª implementação tinha DUPLA integração do I; a suíte prendeu e corrigiu** | lacuna estrutural da v16 | Teos 29.14–29.15 |
118
+ | **TABELA DE SINAIS de 18 parâmetros** (a autorregulação agora cobre o que a v16 não cobria): AdamW β₁/β₂/ε/wd, Muon momentum/escala/τ_qk, PRS η_up/η_down/T_ciclo/decay_piso/percentil, PESO_MOE, PESO_SOM, ABMO margem, CIAR κ, crescimento expand/prune — centros = constantes v16 (nascimento NEUTRO), limites seguros (permanência EXATA provada), sinais adimensionais ±1, TelemetryHub registra 100% (35 chaves), adaptadores para MuonClipAdamW real (β/ε/wd/momentum/escala/τ escritos e passo bem definido) e PRS | lacuna estrutural da v16 | Teo 29.16 |
119
+
120
+ > ✅ **v17**: suíte nova 56 verificações verdes; verificar_tudo 49✓;
121
+ > regressão v1–v16 TODAS verdes (25/36/45/37/33/49/45/✓/22/49/68/29/28/
122
+ > 40/—/53) + smoke18 — ZERO regressões. Cython prioritário: o VICReg
123
+ > completo delega ao kernel compilado (`motor=cython` medido) com
124
+ > fallback honesto. Próximo passo: v18 (SonicMoE + ReplaySSM) e v20
125
+ > (integração da tabela no treinador com produtores de sinal reais).
126
+
127
+ ## O que há de novo no v16 — KHMAMBAJEPA (provas em `docs/matematica/28`, memória em `PLANO_KHMAMBAJEPA.md`)
128
 
129
  | inovação | onde | prova |
130
  |---|---|---|
RELATORIO_KHTST.md CHANGED
@@ -814,120 +814,76 @@ re-executada nesta versão. Checkpoints intermediários da coleta v16
814
  (`ckpt_v16_*.pt`) APAGADOS após uso. Token: exclusivamente variável de
815
  ambiente; grep do padrão `hf_[A-Za-z0-9]{30,}` no stage = 0 ocorrências.
816
 
817
- ---
 
 
 
 
 
 
 
 
 
 
 
818
 
819
- ## 16. v17 — MoE empacotada · TCE curada · SonicMoE/ReplaySSM · autoajuste multi-método
820
-
821
- *Doc matemático completo: `docs/matematica/29-moe-empacotada-tce-sonicmoe-replayssm.md`
822
- (Teos 29.1–29.14) e `docs/matematica/30-autoajuste-multi-metodo.md`
823
- (Teos 30.1–30.15). Suíte: `tests/test_khtst_v17.py` (59 ✓);
824
- verificação executável: `src/khtst/acelerado/run_verification.py` (8 blocos A–H).*
825
-
826
- ### 16.1 Problema 1 — MoE excluída da quantização (RESOLVIDO com provas)
827
-
828
- **Causa (evidência executável)**: `torch.stack` de pesos quantizados
829
- lança `NotImplementedError` — o `Int8Tensor` (subclass torchao) não
830
- implementa `aten.stack`. O empilhamento quebra o contrato de subclasses:
831
- a API de layout denso não preserva o invariante (int_data + escala por
832
- canal) de um tensor novo empilhado. A v16 excluiu os experts (Teo 28.3-iv).
833
-
834
- **Cura (Teos 29.1–29.4)**: substituir o EMPILHAMENTO por INDEXAÇÃO —
835
- (1) bijeção φ(e,i) = e·f+i do pool plano (quantização por linha ⟹
836
- escalas idênticas ⟹ bit-exato); (2) indexador por fatias `narrow`
837
- (zero-copy, ops implementados no subclass — sonda prova); (3) floresta
838
- de B blocos com índice 2 níveis (e ↦ (b,j); GEMM por bloco cheio; f POR
839
- PAPEL — gate/up têm f linhas, down tem d — v17.1); (4) rollback sem
840
- `copy_` sobre subclass (substituição de `.data`; `load_state_dict`
841
- crasha com 'qdata' — evidência) e pools FORA do state_dict (dados
842
- derivados — Teo 29.4-b). **Medido**: compressão MoE 3.79–3.91×, Δy
843
- relativo 6.6e-03 ≤ cota, rollback bit-exato (`torch.equal`).
844
-
845
- **Limitação honesta**: os 6 experts do `MoEEncoderDecoderKHTST`
846
- permanecem FP32 (seu `agrupar()`/telemetria assumem pesos planos) — v18.
847
-
848
- ### 16.2 Problema 2 — perda TCE da suíte v16 (RESOLVIDO com provas)
849
-
850
- **Causa 1 (Teo 29.5)**: a perda JEPA era SOMA do Huber sobre d_latente
851
- — magnitude ∝ d (latentes esféricos ⟹ E[Huber] ≈ c_H por componente ⟹
852
- L ≈ c_H·d; d=64 ⟹ **24.96 medido**). **Cura**: normalização L/d — por
853
- linearidade ∇(L/d) = (∇L)/d EXATO ⟹ reparametrização pura λ' = λ·d (a
854
- v16 é recuperada; a razão L/CE fica O(1) e a fronteira ½ do Teo 28.7-ii
855
- passa a ser aplicável — a autorregulação de λ_jepa fica BEM DEFINIDA).
856
-
857
- **Causa 2 (Teo 29.6)**: limiar de sucesso ABSOLUTO ‖e‖<1 com
858
- ‖alvo‖=√d=8 ⟹ erro relativo exigido < 1/√d ⟹ taxa ≡ 0 (medido) ⟹ tabela
859
- de μ CEGA. **Cura**: limiar INVARIANTE ‖e‖² ≤ θ·‖alvo‖² (θ=0.5) —
860
- homogêneo: taxa invariante a c>0 (verificado com c=50).
861
-
862
- **Cura 3 (Teo 29.8)**: λ_jepa AUTORREGULADO pela razão PONDERADA
863
- λ·L/CE (não L/CE) — equilíbrio na fronteira ½; controlador "jepa" vivo
864
- no autorregulador. **Medido no treino real**: perda O(1) (não ~25),
865
- taxa mensurável, razão ponderada registrada.
866
-
867
- ### 16.3 SonicMoE + ReplaySSM (com provas)
868
-
869
- - **jepa_validator.pyx** (Cython, 4º kernel — `setup.py` v17): registro
870
- das variantes JEPA em aritmética C `long long` (Teo 29.10), **Token
871
- Rounding exato** no bloco de predição — n̂ = τ·⌈n/τ⌉, ρ = n̂/n, GEMM
872
- estofado BIT-EXATO nas linhas vivas (Teo 29.11, `torch.equal`),
873
- escolha de tile por custo efetivo t·ρ — e **AuditoriaMemoriaSonic**
874
- (Teo 29.12): statm nível C ~µs, janelas em arrays C fixos, invariantes
875
- I1 (não-vazamento por inclinação recente + rebase pós-aquecimento),
876
- I2 (recompute ≤ fwd), I3 (sem transiente de empilhamento — o pool
877
- indexado substitui o stack), I4 (só ativos). I1 REPROVA vazamento
878
- sintético (240 MB/60 amostras) — auditoria que nunca reprova não
879
- audita. I1–I4 VERDES em passos reais do treinador.
880
- - **ReplaySSM** (`mamba3/replay.py`, Teos 29.13–29.14): varredura por S
881
- segmentos com REPLAY de estados fronteira (checkpoint
882
- use_reentrant=False; fronteira com grad_fn — SEM detach). **Saída e
883
- h_L BIT-EXATOS** vs kernel completo (indução na fronteira); **gradiente
884
- EXATO** (erro 0.0 medido); ativação O(S·BDN + L_s·BDN); cfg
885
- `mamba3.replay_segmento` (0 = v12 exato, nascimento neutro).
886
-
887
- ### 16.4 Autoajuste multi-método (requisito §§1–4; doc 30)
888
-
889
- A recursão híbrida **u[t+1] = u[t] + a_t·s_t + b·e_t + c_i·I_t +
890
- c_d·Δe_t**, θ = exp(u) ∈ [θmin, θmax], cobre TODOS os parâmetros fixos
891
- com 15 controladores: AdamW β₁/β₂ (PID na CV² do gradiente), ε (RM pela
892
- razão ‖Δp‖/‖g‖), wd (PID na norma RELATIVA — o alvo absoluto 1.0 é
893
- infactível: lema com RMS(W_init) ≈ 0.02), Muon momentum (Teo 30.6: o
894
- sinal literal do requisito forma realimentação POSITIVA — contraexemplo
895
- provado; o inverso converge com a₀·β/(1−β) < 2), τ_qk por BISSECÇÃO
896
- (faixa 80–120; erro ≤ (τmax−τmin)/2^k; ocioso com RCO — Teo 27.2), PRS
897
- V8 η_up/η_down (ponto fixo EXATO E[T∞] = p·η_up/(p·η_up+(1−p)·η_down)),
898
- T_ciclo/decay_piso (RM na velocidade), percentil (RM na fração de clip),
899
- PESO_MOE (RM razão−½ — fronteira CE dominante), PESO_ALINHAMENTO_SOM
900
- (PID na taxa de ativação 90%); ABMO (margem pela folga da barreira —
901
- equilíbrio na borda, descida garantida em TODO passo), CIAR (canal
902
- derivativo do lr — dois multiplicadores independentes inflam a variância
903
- E[(s₁s₂)²] = E[s₁²]E[s₂²]), crescimento (log-razão expansão/poda).
904
- Convergência: RM (Σa=∞, Σa²<∞) + PID em escala de tempo mais rápida
905
- (Borkar); anti-windup (integral satura em 1); truncagem ⟹ pertença
906
- SEMPRE (θ ∈ limites após 2000 passos com sinais máximos). Lema
907
- 30.12-b: coef_streak/vel_alvo/boost_max/alfa_sig ficam FIXOS
908
- (não-identificabilidade autorreferente). Telemetria integral
909
- `multi/*` (15 chaves) + `sonic/*` no Hub.
910
-
911
- ### 16.5 Verificação e treino real (vocab 16384 mantido)
912
-
913
- - Tokenizador RETREINADO @16384 no corpus real (903 registros) —
914
- requisito "vocab": 16384 preservado (`cache_dados/tokenizador_v17.json`).
915
- - Suíte v17: 59 ✓ (Problema 1, Problema 2, validator/token rounding/
916
- auditoria, ReplaySSM, multi-método, integração no treinador com
917
- passos reais, nascimentos neutros).
918
- - Regressão: v2–v16 TODAS verdes (36/✓/37/32/48/44/21/✓/✓/✓/28/27/40/45)
919
- + verificar_tudo 49✓/0✗ (patches/jepa.py sincronizado por SHA-256).
920
- - A/B pareado (30 passos, corpus 903, vocab 16384): baseline_v16
921
- 9.727→9.374 (1.038×) vs **v17 9.729→9.301 (1.046×)**; held-out em
922
- paridade (9.774/9.769); **torchao+MoE-pack com Δperda 0.0** (3.92×);
923
- TCE normalizada 0.54 (v16: 24.96) com taxa 0.104 (v16: ≡ 0); réplica
924
- com outro sorteio trocou a ordem CE (paridade — decisão na corrida 9 h).
925
-
926
- ### 16.6 Honestidade
927
-
928
- (i) Os experts do MoEEncoderDecoder ficam FP32 (limitação v18); (ii) a
929
- inclinção do PESO_ALINHAMENTO_SOM assume monotonia da resposta — sem ela
930
- o Teo 30.1 garante apenas pertença; (iii) as escalas multi em corrida de
931
- 120 passos movem-se (constantes aceleradas) mas a CONVERGÊNCIA é
932
- assintótica; (iv) o A/B de CE em corrida curta não decide qualidade
933
- definitiva — protocolo 9h do README.
 
814
  (`ckpt_v16_*.pt`) APAGADOS após uso. Token: exclusivamente variável de
815
  ambiente; grep do padrão `hf_[A-Za-z0-9]{30,}` no stage = 0 ocorrências.
816
 
817
+ ## 16. v17 — Pacote de aprimoramento: auditoria dos 6 módulos, 14 defeitos provados (D1–D14) e autorregulação HÍBRIDA (RM+PI+bisseção) com tabela de 18 sinais
818
+
819
+ ### 16.1 Escopo e método
820
+
821
+ Rodada de auditoria de lógica, integração e matemática dos 6 módulos
822
+ submetidos (`difusao_gradiente`, `metricas_qe_ct`, `lambda_c_unificado`,
823
+ `tradeoff_k`, `jepa`, `config`). Método: auditoria de 1ª ordem (o que o
824
+ código faz) + de 2ª ordem (o que o docstring PROMETE vs o que o código
825
+ FAZ) + prova de correção de cada defeito + suíte executável
826
+ (`tests/test_khtst_v17.py`, 56 verificações). Tudo em pacote NOVO
827
+ `src/khtst/aprimoramento/` — nenhum módulo de produção foi tocado
828
+ (zero regressões: v1–v16 todas verdes).
829
 
830
+ ### 16.2 Defeitos catalogados e corrigidos (doc 29 §§1–6, Teos 29.1–29.13)
831
+
832
+ | # | defeito | correção | prova |
833
+ |---|---|---|---|
834
+ | D1 | difusão: λ_diff sem grad + controlador nunca chamado + perda sem λ — "autoajuste" triplo código morto | hipergradiente EXATO (L afim em λ ⟹ ∂L/∂λ = L_diff, erro ZERO) + âncora ρ(λ−λ₀)² com ótimo interior λ*=λ₀−L_diff/2ρ | Teo 29.2 |
835
+ | D2 | sem EMA de pesos (amostragem ruidosa) | EMA Polyak opt-in (Jensen: L(θ̄) ≤ média L(θ_t)) | Teo 29.3 |
836
+ | D3 | CT somava ‖Δz‖² sobre (B·D) — incomparável entre configs | CT por COORDENADA (÷B·D); invariância por isometria provada | Teo 29.4 |
837
+ | D4 | ganho por conjunção de limiares fixos — sem nível de teste | Student-t + Bonferroni (P(falso ganho) ≤ α; medido 0/60) | Teo 29.5 |
838
+ | D5 | te_antigo O(N·G) | cKDTree O(N·log G), ≡ força bruta (100 grades) | Teo 29.6 |
839
+ | D6 | média da janela COMPUTADA E JOGADA FORA (delta usava ε² instantâneo) | sinal suavizado vivo (Var ÷W, sem viés) + modo reversão | Teo 29.7-i |
840
+ | D7 | passo η constante — convergência só a O(η) | agenda η_t=η₀/(1+t/τ) — Ση=∞, Ση²<∞ ⟹ q.c. | Teo 29.7-ii |
841
+ | D8 | C=1 fixo no modelo de Zador | Ĉ por OLS log-log + teste do modelo (inclinação) + shrinkage | Teo 29.8 |
842
+ | D9 | λ_c estático (não conversava com o controlador) | resolver_K aceita λ_c adaptativo | integração |
843
+ | D10 | condicional com dois ramos idênticos | stop-gradient único explícito | inspeção |
844
+ | D11 | variância POOLADA sobre (T,D) — colapso parcial invisível | hinge POR DIMENSÃO (Jensen + lei da variância total ⟹ per-dim ≥ poolado sempre) | Teo 29.10 |
845
+ | D12 | truncamento de comprimento (descarta energia) | pooling adaptativo (contração ‖Pz‖ ≤ ‖z‖/√r) | Teo 29.11 |
846
+ | D13 | λ_jepa do config nunca usado; 0.01 hard-coded | L = λ_jepa·MSE + peso_var·hinge — campos vivos | Teos 29.10/29.13 |
847
+ | D14 | QECTConfig.normalizar e DifusaoConfig.eta_lambda mortos | wired (QE relativo; passo do EG) | Teo 29.4/29.2 |
848
+
849
+ Honestidades de processo desta rodada: (a) a primeira versão da prova
850
+ do Teo 29.5 usava o range OBSERVADO no Hoeffding — inválido (o raio
851
+ subestimado quebra a cota); corrigida para Student-t (TCL) com
852
+ Hoeffding opcional sob raio DECLARADO; (b) o Teo 29.13 foi refinado: no
853
+ ponto EXATO de colapso há kink (o autograd pode dar 0) — a verdade é
854
+ que o colapso é MÁXIMO do hinge (não mínimo local), e a produção empurra
855
+ a direção explicitamente; (c) a PRIMEIRA implementação do
856
+ ControladorHibrido fazia DUPLA integração do termo I — a suíte prendeu
857
+ (setpoint não convergia) e a recursão foi corrigida para a forma do doc
858
+ 29, com convergência EXATA medida (θ=0.6000, e∞=0.0000).
859
+
860
+ ### 16.3 Autorregulação híbrida — a arquitetura (doc 29 §§7–9, Teos 29.14–29.16)
861
+
862
+ Recursão única para todo parâmetro regulável:
863
+ `u_{t+1} = Π[u_t + a_t·s_t + b·e_t + c·Δe_t]`, θ=θ₀·e^u, a_t=a₀/(1+t/τ).
864
+ Provas: telescoping do D (Σc·Δe = c·(e_T−e₀) — limitada por 2c·sup|e|
865
+ para TODO T); permanência no conjunto seguro por projeção (com clamp
866
+ final — exp(log b) arredonda a b+ε); duas escalas de Borkar (PI rápido
867
+ rastreia, RM lento converge); anti-windup direcional. τ_qk: banda
868
+ [80,120] com semântica PÓS-CLIP (ℓ=min(ℓ_nat,τ)) — modo escala exata
869
+ (Teo 24.7: linearidade do logit) e modo bisseção com erro ≤
870
+ (τmax−τmin)/2^k. Tabela de 18 parâmetros (AdamW β₁/β₂/ε/wd · Muon
871
+ momentum/escala/τ_qk · PRS η_up/η_down/T_ciclo/decay_piso/percentil ·
872
+ PESO_MOE · PESO_SOM · ABMO · CIAR · crescimento ×2) com nascimento
873
+ neutro (centros = constantes v16), sinais adimensionais ±1, limites
874
+ seguros com permanência EXATA, TelemetryHub 100% (35 chaves) e
875
+ adaptadores aplicados e verificados no MuonClipAdamW REAL e no PRS.
876
+
877
+ ### 16.4 Verificação
878
+
879
+ - Suíte v17: 56✓ (hipergradiente, λ* analítico≡numérico, EG converge,
880
+ Polyak, invariâncias QE/CT, nível do teste 0/60, KDTree≡bruta 100/100,
881
+ fast≡ref 10⁴, D6 regressão, Ση/Ση², Ĉ+p̂+shrinkage, unimodalidade 20k,
882
+ K* fechado≡numérico ≤1%, elasticidade d/2, Jensen 1000 espectros,
883
+ contração do pooling, EMA cosseno monótona, máximo do colapso, fuga
884
+ ×30, telescoping exato, anti-windup 500 adversos, setpoint e∞=0,
885
+ τ banda, 18 controladores neutros→limites exatos, β₁≤β₂ pelo
886
+ adaptador, hub 35 chaves, passo do otimizador real bem definido,
887
+ PRS 5 campos).
888
+ - verificar_tudo: 49✓ · Regressão v1–v16: TODAS verdes
889
+ (25/36/45/37/33/49/45/✓/22/49/68/29/28/40/—/53) · smoke18: 13✓.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cache_dados/corpus_v16.jsonl DELETED
The diff for this file is too large to render. See raw diff
 
cache_dados/corpus_v16_novos.jsonl DELETED
The diff for this file is too large to render. See raw diff
 
cache_dados/corpus_v2.jsonl DELETED
The diff for this file is too large to render. See raw diff
 
cache_dados/tokenizador.json DELETED
The diff for this file is too large to render. See raw diff
 
cache_dados/tokenizador_v16.json DELETED
The diff for this file is too large to render. See raw diff
 
cache_dados/tokenizador_v17.json DELETED
The diff for this file is too large to render. See raw diff
 
docs/matematica/29-autorregulacao-hibrida-aprimoramentos.md ADDED
@@ -0,0 +1,556 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # Doc 29 — AUTORREGULAÇÃO HÍBRIDA E APRIMORAMENTOS DO PACOTE (v17)
3
+ #
4
+ # Este documento contém TODAS as provas da rodada v17: a análise lógica,
5
+ # de integração e matemática dos 6 módulos submetidos (difusao_gradiente,
6
+ # metricas_qe_ct, lambda_c_unificado, tradeoff_k, jepa, config), os 14
7
+ # defeitos catalogados (D1–D14), e o PLANO de autorregulação total com a
8
+ # recursão híbrida RM+PI+bisseção e a tabela de sinais para os ~20
9
+ # parâmetros ainda fixos (AdamW, Muon, PRS V8, pesos de perda, ABMO, CIAR,
10
+ # crescimento).
11
+ #
12
+ # Suíte verificadora: tests/test_khtst_v17.py (Todas as verificações
13
+ # numéricas citadas como [V29.x] são executadas nela).
14
+
15
+ # =====================================================================
16
+ # §0 — NOTAÇÃO E FONTES
17
+ # =====================================================================
18
+ # Herda a notação do doc 00. Adiciona-se:
19
+ # θ_t — parâmetro regulável no passo t (escala absoluta);
20
+ # u_t — log-coordenada: θ_t = θ₀·exp(u_t) (multiplicativa);
21
+ # a_t — passo RM: a_t = a₀/(1+t/τ_a);
22
+ # s_t — sinal de aprendizado ∈ [−1,1];
23
+ # e_t — erro de rastreio normalizado: (alvo − medida)/escala;
24
+ # Π_[l,u] — projeção (clipagem) no intervalo [l,u];
25
+ # σ_j — desvio-padrão da dimensão j da representação;
26
+ # ε²(K) — erro de quantização com codebook de K níveis;
27
+ # ℓ_max — logit máximo observado nas atenções NoPE (doc 24).
28
+ #
29
+ # Os módulos vivem em src/khtst/aprimoramento/ (pacote auto-contido,
30
+ # mesma convenção de import relativo do rascunho submetido).
31
+
32
+ # =====================================================================
33
+ # §1 — DIAGNÓSTICO GLOBAL (lógica e integração)
34
+ # =====================================================================
35
+ # Os 6 módulos formam uma PIPELINE coerente de aprimoramento:
36
+ #
37
+ # métricas QE+CT ──(ε² medido)──> λ_c unificado ──(λ_c)──> trade-off K
38
+ # │ │
39
+ # └──(ganho real?)──> decisão de treino K* (codebook)
40
+ #
41
+ # difusão (sonho) ──(L_diff)──> λ_diff vivo (novo em v17)
42
+ # JEPA ──(colapso?)──> hinge de variância ──> VICReg Cython (doc 28)
43
+ #
44
+ # DEFEITOS CATALOGADOS (auditoria 1ª + 2ª ordem, todos corrigidos):
45
+ # D1 difusao: λ_diff com requires_grad=False, AutoLambdaDiff NUNCA
46
+ # chamado, L nem sequer usava λ — "autoajuste" era triplo código
47
+ # morto (docstring anunciava o que o código não fazia).
48
+ # D2 difusao: sem EMA de pesos (Polyak) — amostragem ruidosa.
49
+ # D3 metricas: CT somava ‖Δz‖² sobre (B·D) — escala dependente da
50
+ # dimensão; experimentos incomparáveis.
51
+ # D4 metricas: ganho por conjunção de limiares fixos — teste de
52
+ # hipótese implícito SEM nível controlado.
53
+ # D5 metricas: te_antigo O(N·G) — força bruta.
54
+ # D6 lambda_c: a média da janela era COMPUTADA E JOGADA FORA — o
55
+ # delta usava ε² instantâneo (o docstring prometia a média).
56
+ # D7 lambda_c: passo η constante — convergência só a O(η).
57
+ # D8 tradeoff: C=1 hard-coded — a constante de Zador depende dos
58
+ # dados; com C=1, K* colapsa à borda inferior em d alto.
59
+ # D9 tradeoff: λ_c estático lido do config (não conversava com o
60
+ # controlador de λ_c — integração quebrada).
61
+ # D10 jepa: condicional morto (dois ramos idênticos no use_sg).
62
+ # D11 jepa: variância AGRUPADA sobre (T,D) — anti-colapso fraco
63
+ # (colapso parcial de dimensões é invisível).
64
+ # D12 jepa: truncamento de comprimento — descarta energia.
65
+ # D13 jepa: λ_jepa do config NUNCA usado; peso 0.01 hard-coded.
66
+ # D14 config: QECTConfig.normalizar e DifusaoConfig.eta_lambda eram
67
+ # campos mortos (existiam, nunca lidos).
68
+ #
69
+ # LACUNA ESTRUTURAL (motiva §§7–9): a autorregulação v16 (Teos 28.5–28.8)
70
+ # cobria lr/λ_aux/MoE com RM puro de sinal único — sem rastreio de
71
+ # setpoint, sem memória de regime e SEM cobertura de AdamW (β₁,β₂,ε,wd),
72
+ # Muon (momentum, escala, τ_qk), PRS V8 (η_up, η_down, T_ciclo,
73
+ # decay_piso, percentil), PESO_MOE, PESO_ALINHAMENTO_SOM, ABMO, CIAR e
74
+ # crescimento. A v17 fecha com a recursão híbrida + tabela de sinais.
75
+
76
+ # =====================================================================
77
+ # §2 — DIFUSÃO COM GRADIENTE (Teos 29.1–29.3)
78
+ # =====================================================================
79
+
80
+ # ---------------------------------------------------------------------
81
+ # TEOREMA 29.1 (corretude do DDPM). Sejam α_t = 1−β_t e ᾱ_t = ∏_{s≤t}α_s
82
+ # com q(x_t|x_{t−1}) = N(√α_t·x_{t−1}, β_t·I). Então:
83
+ # (i) q(x_t|x₀) = N(√ᾱ_t·x₀, (1−ᾱ_t)·I);
84
+ # (ii) o amostrador x_{t−1} = (x_t − (1−α_t)/√(1−ᾱ_t)·ε_θ(x_t,t))/√α_t
85
+ # + √β_t·z implementa a média a posteriori de q(x_{t−1}|x_t,x₀)
86
+ # sob a parametrização x₀ = (x_t − √(1−ᾱ_t)·ε)/��ᾱ_t.
87
+ # PROVA. (i) Indução. Base t=1 trivial: x₁ = √α₁x₀ + √(1−α₁)ε, e
88
+ # ᾱ₁ = α₁. Passo: assuma q(x_t|x₀) = N(√ᾱ_t x₀, (1−ᾱ_t)I) e
89
+ # x_{t+1} = √α_{t+1}x_t + √(1−α_{t+1})ε' com ε' ⊥ x_t. Soma de
90
+ # gaussianas independentes:
91
+ # E[x_{t+1}|x₀] = √α_{t+1}·√ᾱ_t·x₀ = √(α_{t+1}ᾱ_t)·x₀ = √ᾱ_{t+1}·x₀,
92
+ # Var = α_{t+1}(1−ᾱ_t) + (1−α_{t+1}) = 1 − α_{t+1}ᾱ_t = 1 − ᾱ_{t+1}.
93
+ # (ii) A posteriori gaussiana (conjugada) dá
94
+ # μ̃_t = [√ᾱ_{t−1}β_t·x₀ + √α_t(1−ᾱ_{t−1})·x_t]/(1−ᾱ_t), σ²=β_t.
95
+ # Substituindo x₀ pela estimativa ε-parametrizada e simplificando
96
+ # (álgebra direta — expandir √ᾱ_t = √α_t·√ᾱ_{t−1}):
97
+ # μ̃_t = [x_t − (1−α_t)/√(1−ᾱ_t)·ε]/√α_t,
98
+ # exatamente a atualização implementada em DifusaoDDPM.sample. ∎
99
+ # Consequência: L_diff = E‖ε − ε_θ(x_t,t)‖² é o objetivo simplificado
100
+ # de Ho et al. (2020), majorante ponderado do VLB — a base do módulo
101
+ # estava correta; os defeitos eram de INTEGRAÇÃO (D1/D2).
102
+
103
+ # ---------------------------------------------------------------------
104
+ # TEOREMA 29.2 (λ_diff vivo — hipergradiente exato, regret do EG, ótimo
105
+ # interior ancorado). Com L(λ) = λ·a + ρ(λ−λ₀)², a = L_diff independente
106
+ # de λ (a rede não depende de λ):
107
+ # (i) ∂L/∂λ = a + 2ρ(λ−λ₀) — EXATO, erro de estimação ZERO (a forma
108
+ # é afim + quadrática; nenhuma diferença finita é necessária).
109
+ # (ii) A descida multiplicativa λ_{t+1} = λ_t·exp(−η·g_t) é descida
110
+ # de gradiente por mirror descent com potencial de entropia
111
+ # h(u)=e^u; para L convexa com |g| ≤ G e λ ∈ [λmin,λmax],
112
+ # R_T := Σ_t L(λ_t) − min_λ Σ_t L(λ)
113
+ # ≤ η·G²·T/2 + ln(λmax/λmin)/η,
114
+ # e com η* = √(2·ln(λmax/λmin)/(G²·T)): R_T ≤ G·√(2T·ln(λmax/λmin))
115
+ # — perda média a O(1/√T) do ótimo (regret de EG clássico;
116
+ # a clipagem só adiciona projeção, que nunca aumenta o regret —
117
+ # propriedade de não-expansão da projeção em Bregman).
118
+ # (iii) Com ρ > 0, L é ESTRITAMENTE CONVEXA (L'' = 2ρ > 0) com
119
+ # minimizador ÚNICO λ* = λ₀ − a/(2ρ), clipado a [λmin,λmax].
120
+ # SEM a âncora (ρ=0), L é afim e o minimizador está SEMPRE numa
121
+ # borda — o EG empurraria λ para o limite e o deixaria lá: a
122
+ # âncora é o que torna o autoajuste não-trivial e dá ÓTIMO
123
+ # INTERIOR provado.
124
+ # PROVA. (i) Derivada termo a termo; λ não afeta a rede. (ii) Análise
125
+ # padrão de mirror descent: telescoping da desigualdade de Fenchel
126
+ # D_h(λ*,λ_{t+1}) ≤ D_h(λ*,λ_t) + η·g_t·(λ_t−λ*) + η²G²/2, soma e
127
+ # rearranjo; o termo de largura é ln(λmax/λmin) pois h(λ*)−h(λ₁) é
128
+ # limitado pela divergência de KL entre Bernoullis proporcionais a
129
+ # λmax/λmin (Cesa-Bianchi & Lugosi 2006, Cap. 2 — rederivado no
130
+ # contexto do pacote). (iii) L'(λ)=0 ⟺ λ* = λ₀−a/(2ρ). ∎
131
+ # [V29.2] Suíte: |L(λ*)−min_numérico| < 1e-9 e hipergradiente exato
132
+ # ≡ autograd (1e-7 relativo).
133
+
134
+ # ---------------------------------------------------------------------
135
+ # TEOREMA 29.3 (Polyak/EMA). Se L é convexa em θ e θ̄ = Σw_tθ_t com
136
+ # w no simplex, então L(θ̄) ≤ Σw_t·L(θ_t) (Jensen). O EMA com peso m
137
+ # tem variância de tracking σ²(1−m)/(1+m) sob ruído i.i.d. de θ —
138
+ # avaliar/amostrar com θ̄ nunca é pior EM MÉDIA que amostrar θ_t.
139
+ # PROVA. Jensen para convexas com pesos do simplex; a variância é a do
140
+ # filtro AR(1): Var[θ̄] = σ²(1−m)²/(1−m²) = σ²(1−m)/(1+m), decrescente
141
+ # em m. ∎ (implementado como ema_atualizar/carregar_ema, opt-in.)
142
+
143
+ # =====================================================================
144
+ # §3 — MÉTRICAS QE + CT (Teos 29.4–29.6)
145
+ # =====================================================================
146
+
147
+ # ---------------------------------------------------------------------
148
+ # TEOREMA 29.4 (comparabilidade dimensional).
149
+ # (i) QE(αx, αx̂) = α²·QE(x,x̂) ⟹ QE_rel = QE/mean‖x‖² é invariante a
150
+ # reescala global (α≠0) — compara camadas/épocas de energias
151
+ # distintas (D14 vivo: cfg.normalizar governa).
152
+ # (ii) CT absoluto é invariante a qualquer reindexação das coordenadas
153
+ # com contagem igual (permutação não muda Σ‖Δz‖²); mas entre
154
+ # configurações com B·D distinto só a média POR COORDENADA
155
+ # CT_norm = Σ_t w_t‖Δz_t‖²/(B·D) estima a MESMA quantidade
156
+ # E[deriva² por coordenada] — estimador não-enviesado.
157
+ # PROVA. (i) Bilinearidade da norma. (ii) Permutação de coordenadas é
158
+ # isometria Euclidiana; para contagens distintas, dividir pelo total
159
+ # torna a soma uma média empírica sobre coordenadas — lei dos grandes
160
+ # números ⟹ convergência à expectativa comum. ∎
161
+
162
+ # ---------------------------------------------------------------------
163
+ # TEOREMA 29.5 (ganho real com nível controlado).
164
+ # (i) Com UCB_m = Δ̄_m + q_{1−α_f}·s_m/√N (Student-t) para m ∈
165
+ # {QE, CT} e α_f = α/2: se NÃO há ganho verdadeiro em nenhum
166
+ # dos dois (Δ̄_m ≥ 0), então P(declarar ganho) ≤ α (Bonferroni:
167
+ # P(∪E_m) ≤ ΣP(E_m) ≤ 2·α_f).
168
+ # (ii) Sob Hoeffding com raio DECLARADO R ≥ range verdadeiro:
169
+ # detectar efeito t exige N ≥ R²·ln(1/α_f)/(2t²).
170
+ # (iii) O raio OBSERVADO não substitui R: R_obs ≤ range verdadeiro
171
+ # com prob. 1, e a cota de Hoeffding com raio subestimado NÃO é
172
+ # válida — usar Student-t (TCL) ou declarar R explicitamente.
173
+ # (Esta (iii) é uma CORREÇÃO da minha própria primeira versão
174
+ # desta prova — honestidade de processo registrada.)
175
+ # PROVA. (i) Para cada m, sob Δ̄_m ≥ 0: P(UCB_m < 0) ≤ P(Δ̄_N − Δ̄_m <
176
+ # −q·s/√N) ≤ α_f pela cobertura unilateral do t de Student (exata
177
+ # sob normalidade, assintótica pelo TCL em geral). União por
178
+ # Bonferroni. (ii) Inverter exp(−2Nt²/R²) ≥ 1−α. (iii) A dedução da
179
+ # cota exige (b−a) do SUPORTE; R_obs é menor com prob. 1. ∎
180
+
181
+ # ---------------------------------------------------------------------
182
+ # TEOREMA 29.6 (KDTree). cKDTree devolve o vizinho mais próximo EXATO:
183
+ # (i) construção O(G·log G), consulta O(log G) média — total
184
+ # O((G+N)·log G) contra O(N·G) da força bruta;
185
+ # (ii) com mínimo único, o índice devolvido ≡ argmin exaustivo
186
+ # (mesma distância, bit-a-bit); empates exatos têm medida zero
187
+ # sob grades contínuas e o tie-break é documentado.
188
+ # PROVA. (i) Propriedade estrutural da árvore k-d balanceada. (ii) Se o
189
+ # mínimo é único, ambos os métodos identificam o MESMO ponto — a
190
+ # função distância ao mais próximo é bem definida. ∎ [V29.6]
191
+
192
+ # =====================================================================
193
+ # §4 — λ_c UNIFICADO (Teo 29.7)
194
+ # =====================================================================
195
+
196
+ # ---------------------------------------------------------------------
197
+ # TEOREMA 29.7 (sinal suavizado e agenda RM).
198
+ # (i) Para amostras i.i.d. com variância σ², a média da janela W
199
+ # tem Var = σ²/W ⟹ o sinal Δ(t) = ε̄²(t) − ε²_alvo tem
200
+ # variância W vezes menor que o ε² instantâneo do rascunho,
201
+ # SEM viés (média não-enviesada). Chebyshev:
202
+ # P(|ε̄²−μ| ≥ t) ≤ σ²/(W·t²).
203
+ # (ii) Com η_t = η₀/(1+t/τ): Ση_t = ∞ (harmônica com log T) e
204
+ # Ση_t² < ∞ (série de Dirichlet) ⟹ condições de Robbins–Monro
205
+ # (1951); com campo de deriva b(u) = −η₀·Δ(ε̄²) Lipschitz no
206
+ # compacto [ln λmin, ln λmax] (λ clipada ⟹ sinal limitado) e
207
+ # ruído de segundo momento finito, u_t converge q.c. ao
208
+ # conjunto estacionário de b (Borkar 2008, Thm 2.1 — mesma
209
+ # família do Teo 28.5).
210
+ # (iii) ref_path_step delega a fast_path_step — identidade bit-a-bit
211
+ # POR CONSTRUÇÃO; equivalencia_numerica fixa a propriedade
212
+ # (n=10⁴ passos, max_diff == 0.0). [V29.7]
213
+ # PROVA. (i) Cálculo direto: Var(X̄) = ΣVar/W² = σ²/W. (ii) Séries: Σ
214
+ # 1/(1+t/τ) diverge como τ·ln T; Σ1/(1+t/τ)² ≤ Σ1/t² converge. O
215
+ # sinal é limitado (modo alvo: |Δ| ≤ max(|ε²|)+alvo, com ε² ≤ B por
216
+ # ser média de quadrados limitados) ⟹ ruído com segundo momento
217
+ # finito e passos satisfazendo as condições clássicas ⟹ Teorema de
218
+ # Robbins–Monro. ∎
219
+
220
+ # =====================================================================
221
+ # §5 — TRADE-OFF K (Teos 29.8–29.9)
222
+ # =====================================================================
223
+
224
+ # ---------------------------------------------------------------------
225
+ # TEOREMA 29.8 (estimação da constante de Zador). Modelo:
226
+ # ln ε²(K) = ln C − (2/d)·ln K + r, E[r]=0, Var[r]<∞, r ⊥ K.
227
+ # (i) OLS em log-log: (Ĉ_ols, p̂) → (C, 2/d) q.c. quando n_C→∞
228
+ # (LLN sobre os momentos amostrais + mapeamento contínuo).
229
+ # (ii) TESTE DO MODELO: p̂ é a inclinação estimada; |p̂ + 2/d| >
230
+ # tolerância ⟹ Zador não vale para esses dados ⟹ o resolvedor
231
+ # cai para a grade (honestidade metodológica, telemetria).
232
+ # (iii) SHRINKAGE: Ĉ = (n_C·Ĉ_ols + κ·C₀)/(n_C+κ) tem
233
+ # Viés = κ(C₀−C)/(n_C+κ) e Var = (n_C/(n_C+κ))²·Var(Ĉ_ols) —
234
+ # troca explícita viés↔variância; sensata quando n_C é pequeno
235
+ # (grade típica: 5–8 pontos).
236
+ # PROVA. (i) OLS 1D é razão de médias amostrais; LLN + Slutsky. (ii)
237
+ # p̂ consistente para a inclinação verdadeira; o teste é a rejeição
238
+ # da restrição p = −2/d. (iii) Cálculo direto de viés/variância da
239
+ # média ponderada. ∎ [V29.8: recupera C conhecido em dados sintéticos
240
+ # com inclinação ≈ −2/d]
241
+
242
+ # ---------------------------------------------------------------------
243
+ # TEOREMA 29.9 (unimodalidade, forma fechada, sensibilidade).
244
+ # Com J1(K) = (1−λ)·C·K^{−p} + λ·(log₂K + K·d/n)/log₂d, p = 2/d > 0:
245
+ # (i) J1'(K) = −(1−λ)C·p·K^{−p−1} + λ·(K^{−1}/ln2 + d/n)/log₂d.
246
+ # Multiplicando por K^{p+1} > 0:
247
+ # G(K) = −(1−λ)C·p + λ·(K^p/ln2 + K^{p+1}·d/n)/log₂d.
248
+ # G é ESTRITAMENTE CRESCENTE (K^p e K^{p+1} o são; coeficientes
249
+ # > 0) ⟹ no máximo UMA raiz. Limites: J1'(K) → −∞ quando
250
+ # K→0⁺ (K^{−p−1} domina K^{−1} pois p+1 > 1) e J1'(K) →
251
+ # λ·d/(n·log₂d) ≥ 0 quando K→∞ ⟹ J1 decresce e depois cresce:
252
+ # MÍNIMO GLOBAL ÚNICO — minimize_scalar bounded acha o global.
253
+ # (ii) Regime n→∞ (termo K·d/n desprezível): G(K)=0 dá
254
+ # K* = [ (1−λ)·2·C·ln d / (λ·d) ]^{d/2}
255
+ # (usando ln2·log₂d = ln d). Forma fechada usada como bracket
256
+ # do numérico e sanity check. [V29.9: |K*_num − K*_fechado|/
257
+ # K* < 1% e varredura fina confirma decresce-então-cresce]
258
+ # (iii) SENSIBILIDADE: K* ∝ C^{d/2} ⟹ ∂ln K*/∂ln C = d/2 — para d
259
+ # alto, K* é extremamente sensível a C; por isso Ĉ usa
260
+ # shrinkage (Teo 29.8-iii) e o resolvedor registra C e p̂ na
261
+ # telemetria. Honestidade: com C≈1 e d=512, K*≈0 — o modelo
262
+ # diz "não use codebook" para λ=0.5, o que é CONSISTENTE com
263
+ # a decadência lenta K^{−2/d}; o interesse prático está em
264
+ # d moderado ou C ≫ 1 (dados não normalizados).
265
+ # (iv) SEÇÃO ÁUREA: fator de contração 0,618 por iteração ⟹ erro
266
+ # ≤ (b−a)·0,618^k no bracket [a,b].
267
+ # PROVA. (i) Cálculo direto + análise de limites; singularidade da raiz
268
+ # pela monotonidade estrita de G. (ii) Álgebra: λ·K^p/(ln2·log₂d) =
269
+ # (1−λ)C·p ⟹ K^p = (1−λ)C·p·ln d/λ com ln2·log₂d = ln d. (iii)
270
+ # Log-diferenciar a forma fechada. (iv) Propriedade do golden section
271
+ # search. ∎
272
+
273
+ # =====================================================================
274
+ # §6 — JEPA (Teos 29.10–29.13)
275
+ # =====================================================================
276
+
277
+ # ---------------------------------------------------------------------
278
+ # TEOREMA 29.10 (hinge de variância POR DIMENSÃO ≥ poolado). Sejam
279
+ # σ_j os desvios-padrão por dimensão (j=1..D) e σ_pool o desvio-padrão
280
+ # POOLADO sobre todos os elementos. Então
281
+ # L_perdim = (1/D)·Σ_j relu(γ − σ_j) ≥ relu(γ − σ_pool) = L_pool,
282
+ # com desigualdade ESTRITA quando as dimensões são heterogêneas — em
283
+ # particular, dimensões COLAPSADAS (σ_j ≈ 0) que o hinge poolado não vê.
284
+ # PROVA. Em duas etapas:
285
+ # (a) Decomposição da variância total (lei de condicionamento):
286
+ # σ_pool² = E_j[σ_j²] + Var_j(μ_j) ≥ E_j[σ_j²] ⟹
287
+ # σ_pool ≥ RMS(σ) ≥ σ̄ := E_j[σ_j] (RMS ≥ média).
288
+ # (b) Jensen para relu (convexa): L_perdim = E_j[relu(γ−σ_j)] ≥
289
+ # relu(γ − σ̄). Como relu(γ−x) é NÃO-CRESCENTE em x:
290
+ # relu(γ−σ̄) ≥ relu(γ−σ_pool) = L_pool. Cadeia: perdim ≥ L_pool. ∎
291
+ # CONTRAEXEMPLO (colapso parcial invisível ao poolado): σ = (2, 0), γ=1.
292
+ # L_pool = relu(1 − σ_pool) com σ_pool² = (4+0)/2 + Var(μ); com μ_j=0:
293
+ # σ_pool = √2 ⟹ L_pool = 0. L_perdim = (relu(−1)+relu(1))/2 = 0,5 > 0.
294
+ # A dimensão morta só é PUNIDA pelo per-dimensão. [V29.10]
295
+ # NOTA (rascunho): z.var(dim=(-2,-1)).mean() calculava a variância
296
+ # POOLADA POR AMOSTRA (sobre T·D elementos) e media no lote — ainda
297
+ # mais fraca que L_pool global.
298
+
299
+ # ---------------------------------------------------------------------
300
+ # TEOREMA 29.11 (pooling adaptativo vs truncamento). Seja P o operador
301
+ # de pooling por médias (blocos de raio r) e T_r o truncamento nas L
302
+ # primeiras posições, T = L·r:
303
+ # (i) ‖Pz‖₂ ≤ ‖z‖₂/√r (P é CONTRAÇÃO): por Cauchy–Schwarz,
304
+ # (Σ_{i∈bloco}z_i)² ≤ r·Σ_{i∈bloco}z_i²; somando os blocos
305
+ # disjuntos: ‖Pz‖² ≤ ‖z‖²/r.
306
+ # (ii) O erro de truncamento é a ENERGIA DESCARTADA:
307
+ # ‖z − T_r z‖² = Σ_{i>L} z_i² — estritamente positivo sempre que
308
+ # há massa além de L; o pooling não descarta massa (preserva a
309
+ # média de cada bloco) e seu excesso de erro é de RESOLUÇÃO,
310
+ # dominado pelo de descarte quando a energia é espalhada — o
311
+ # regime típico de representações treinadas (não concentradas
312
+ # nas primeiras posições).
313
+ # PROVA. (i) Cálculo acima. (ii) Definição + comparação de termos; a
314
+ # alegação de domínio é HONESTA (assumption de energia espalhada,
315
+ # verificável por telemetria: fração de energia além de L). ∎ [V29.11]
316
+
317
+ # ---------------------------------------------------------------------
318
+ # TEOREMA 29.12 (agenda cosseno do EMA). m(t) = 1−(1−m₀)·(cos(πt/T)+1)/2:
319
+ # (i) m(0)=m₀, m(T)=1;
320
+ # (ii) monótona crescente: dm/dt = (1−m₀)·π·sin(πt/T)/(2T) ≥ 0 em
321
+ # [0,T];
322
+ # (iii) variância de tracking do alvo EMA sob ruído i.i.d. de θ:
323
+ # σ²_eff = σ²·(1−m)/(1+m) — DECREASE com m: no fim do treino
324
+ # (m→1) o alvo é mais silencioso exatamente quando a
325
+ # representação já converge (BYOL/MoCo v3 — rederivado).
326
+ # PROVA. (i)/(ii) cálculo direto. (iii) filtro AR(1) estacionário. ∎
327
+ # [V29.12: m(0)=m₀, m(T)→1, monótona em grade fina]
328
+
329
+ # ---------------------------------------------------------------------
330
+ # TEOREMA 29.13 (colapso não é mínimo local). Se a representação colapsa
331
+ # (z constante sobre lote-tempo) e peso_var > 0, então o ponto colapsado
332
+ # NÃO é mínimo local de L_total: o MSE entre constantes é plano a 1ª
333
+ # ordem (∂MSE/∂ẑ = 0), enquanto o hinge de variância atinge ali seu
334
+ # VALOR MÁXIMO (σ_j = 0 ⟹ relu(γ−0) = γ) e QUALQUER perturbação aumenta
335
+ # σ_j (σ_j ≥ 0 com mínimo isolado em 0) ⟹ diminui L_var a 1ª ordem ⟹
336
+ # existe vizinhança com L_total estritamente menor ⟹ descida de
337
+ # gradiente ESCAPA do colapso.
338
+ # HONESTIDADE (kink): em σ_j = 0 exato, σ_j não é diferenciável
339
+ # (subdiferencial); o autograd suaviza e pode devolver gradiente 0 no
340
+ # ponto EXATO — a fuga é geométrica (colapso é máximo do hinge), e a
341
+ # produção garante a direção anti-colapso EXPLICITAMENTE via o
342
+ # empurrão yc/σ² do FunilLatente (v15.1) — duplicação honesta do
343
+ # mecanismo provado. O peso peso_var > 0 é NECESSÁRIO: com peso 0 o
344
+ # colapso vira minimizador do alinhamento puro. ∎
345
+ # [V29.13: L_var(colapsado)=γ; perturbação diminui L_total; treino a
346
+ # partir de init colapsado escapa (variância cresce)]
347
+
348
+ # =====================================================================
349
+ # §7 — CONTROLADOR HÍBRIDO RM + PI (Teo 29.14)
350
+ # =====================================================================
351
+ # Recursão ÚNICA para todo parâmetro θ (a arquitetura do plano):
352
+ #
353
+ # u_{t+1} = Π_[u_min,u_max]( u_t + a_t·s_t + b·e_t + c·Δe_t ),
354
+ # θ_t = θ₀·exp(u_t), a_t = a₀/(1+t/τ_a).
355
+ #
356
+ # TEOREMA 29.14 (estabilidade estrutural do híbrido).
357
+ # (i) TELESCOPING do D-termo: Σ_{t≤T} c·Δe_t = c·(e_T − e_0) —
358
+ # contribuição cumulativa limitada por 2c·sup|e| PARA TODO T.
359
+ # O termo derivativo NUNCA desestabiliza a recursão (contrário
360
+ # do temor clássico com ganhos derivativos em controle).
361
+ # (ii) PERMANÊNCIA NO CONJUNTO SEGURO: por indução, u_t ∈
362
+ # [u_min,u_max] ∀t — a base vale no nascimento (u₀=0, centro
363
+ # dentro dos limites por assert) e a projeção Π fecha o passo
364
+ # indutivo. Com o clamp do I (|i_acum| ≤ 2|b_i|), do sinal
365
+ # (|s_t| ≤ 1) e do passo (|Δu| ≤ passo_max), |u_{t+1}−u_t| ≤
366
+ # passo_max — movimento por passo limitado (anti-windup
367
+ # estrutural: NÃO há explosão do integral).
368
+ # (iii) DUAS ESCALAS (Borkar Ch.6; Teo 28.6 generalizado): com
369
+ # a_t → 0 (escala lenta) e b,c fixos (escala rápida), a
370
+ # dinâmica separa: o laço PI (rápido) rastreia o setpoint —
371
+ # erro de regime e_∞ = 0 para planta estática com ganho finito
372
+ # (ação integral pura) — e o RM (lento) converge q.c. sobre o
373
+ # equilíbrio já estabilizado (o campo lento vê a variável
374
+ # rápida quasi-estacionária).
375
+ # (iv) GANHO RELATIVO: o RM sozinho (v16) converge ao estacionário
376
+ # do CAMPO DE SINAIS, que pode ter viés de regime (ex.: razão
377
+ # L_aux/CE sistematicamente deslocada pela mistura de dados).
378
+ # O PI adiciona rastreio de setpoint EXPLÍCITO: e_t → 0 no
379
+ # equilíbrio, o que RM puro não promete.
380
+ # PROVA. (i) Soma telescópica. (ii) A projeção é não-expansiva e fecha
381
+ # a indução; os clamps limitam o incremento. (iii) Teorema de duas
382
+ # escalas: condição Σa_t = ∞ com a_t→0 e ganhos rápidos O(1);
383
+ # separação de escalas valida a aproximação ODE acoplada. (iv)
384
+ # Definicional (o PI zera erro de regime por construção). ∎ [V29.14:
385
+ # telescoping medido; anti-windup em sinais adversos; rastreio de
386
+ # setpoint com erro → 0]
387
+
388
+ # =====================================================================
389
+ # §8 — τ_qk POR BANDA (Teo 29.15)
390
+ # =====================================================================
391
+ # Objetivo: manter o logit máximo ℓ_max na banda [80,120] ajustando τ.
392
+ # Semântica PÓS-CLIP (Teo 24.7): ℓ_observado = min(ℓ_natural, τ).
393
+ #
394
+ # TEOREMA 29.15 (convergência do controlador de τ).
395
+ # (i) ESCALA EXATA: o logit é LINEAR na escala de W_q
396
+ # (ℓ(γW_q) = γ·ℓ(W_q) — bilinearidade). Logo, com
397
+ # τ_{t+1} = τ_t·(ℓ_alvo/ℓ_t)^η: no caso ℓ_t = min(ℓ_nat, τ_t)
398
+ # com τ_t < ℓ_nat (clip ativo), ℓ_t = τ_t e a iteração em
399
+ # log-escala é log τ_{t+1} = (1−η)·log τ_t + η·log ℓ_alvo —
400
+ # contração geométrica com razão |1−η| (η=1 corrige em 1 passo
401
+ # EXATO; η=0,5 → metade do log-erro por passo).
402
+ # (ii) BISSEÇÃO NO COLCHETE: com a invariância "τ* ∈ [t_lo,t_hi]"
403
+ # (τ* := o τ que põe ℓ_obs na banda), ℓ_obs > hi ⟹ τ ≥ ℓ_obs >
404
+ # hi ⟹ τ* < τ ⟹ t_hi ← τ; ℓ_obs < lo ⟹ τ* > τ ⟹ t_lo ← τ.
405
+ # Com ponto médio geométrico a cada passo, a largura do
406
+ # colchete contrai por 1/2 em log-escala ⟹ erro ≤
407
+ # (τ_max−τ_min)/2^k após k passos (a forma do rascunho,
408
+ # agora com a direção do colchete CORRETA sob pós-clip).
409
+ # PROVA. (i) Substituição direta; a linearidade é o Teo 24.7 (o mesmo
410
+ # invariante do QK-clip). (ii) A atualização do colchete preserva a
411
+ # invariância por construção; largura em log decresce pela metade com
412
+ # midpoint geométrico. ∎ [V29.15: dinâmica consistente
413
+ # ℓ_obs=min(ℓ_nat,τ) converge para a banda; erro do colchete ≤ cota]
414
+
415
+ # =====================================================================
416
+ # §9 — TABELA DE SINAIS: O PLANO DE AUTORREGULAÇÃO TOTAL (Teo 29.16)
417
+ # =====================================================================
418
+ # ARQUITETURA (implementada em autorregulacao_estendida.py):
419
+ #
420
+ # telemetria bruta (TreinadorExtensao) ──> tabela de sinais (±1)
421
+ # ──> ControladorHibrido por parâmetro (RM+PI)
422
+ # ──> valores novos ──> adaptadores (otimizador, PRS, perdas)
423
+ # ──> TelemetryHub (TODOS os valores e erros auditáveis)
424
+ #
425
+ # TEOREMA 29.16 (segurança estrutural da tabela). Para cada linha da
426
+ # tabela:
427
+ # (a) o CENTRO é a constante v16 (nascimento neutro — comportamento
428
+ # bit-a-bit idêntico com autorreg desligada);
429
+ # (b) o centro está DENTRO dos limites (verificação por assert);
430
+ # (c) sinais ∈ [−1,1] (sinal_razao clipa) ⟹ |Δu| ≤ passo_max ⟹
431
+ # permanência no conjunto seguro (Teo 29.14-ii);
432
+ # (d) os CONSUMIDORES aceitam qualquer valor nos limites: AdamW exige
433
+ # β∈(0,1), ε>0, wd≥0 (denominador √exp_avg_sq+ε > 0 — bem
434
+ # definido); Muon exige momentum∈[0,1); PRS exige T_ciclo≥1 e
435
+ # percentil∈[0.5,0.95]; τ_qk∈[40,400] mantém a banda do QK-clip
436
+ # compatível com a cota do logit (Teo 27.2: ℓ_max ≤ d/√d_h).
437
+ # TABELA (18 linhas — parâmetro, controlador, sinal, setpoint, limites):
438
+ # ---------------------------------------------------------------------
439
+ # | parâmetro | ctl | sinal (telemetria) | alvo | limites |
440
+ # | AdamW β₁ | PI | var_grad_norm (curvatura) | 1.0 | [.80,.95] |
441
+ # | AdamW β₂ | PI | deriva_seg_momento (inv.) | 1.0 | [.90,.999]|
442
+ # | AdamW ε | RM | razao_update_grad | 1.0 | [1e-10,1e-6]|
443
+ # | AdamW wd | PI | norma_peso (L2 média) | 1.0 | [1e-4,.10]|
444
+ # | Muon momentum | RM | razao_momentum_grad | 1.0 | [.80,.99] |
445
+ # | Muon escala | PI | razao_rms_mecanismos | 1.0 | [.10,.40] |
446
+ # | τ_qk | BISS| logit_max (banda 80–120) | 100 | [40,400] |
447
+ # | PRS η_up | PI | taxa_acerto_trust | 0.60 | [.01,.15] |
448
+ # | PRS η_down | PI | taxa_acerto_trust (inv.) | 0.60 | [.005,.10]|
449
+ # | PRS T_ciclo | RM | delta_perda_passo | 0.01 | [200,1200]|
450
+ # | PRS decay_piso | RM | delta_perda_passo | 0.01 | [.30,.80] |
451
+ # | PRS percentil | RM | razao_clip | 0.10 | [.50,.95] |
452
+ # | PESO_MOE | RM | razao_moe_ce (inv. direta)| 0.5 | [.005,.08]|
453
+ # | PESO_SOM | PI | ativacao_som | 0.90 | [.01,.20] |
454
+ # | ABMO margem | RM | margem_abmo_norm | 1.0 | [.5,1.5]× |
455
+ # | CIAR κ | PI | taxa_aceitacao_ciar | 0.70 | [.5,2.0]× |
456
+ # | cresc. expand | RM | taxa_expansao | 0.05 | [.5,2.0]× |
457
+ # | cresc. prune | RM | taxa_prune | 0.02 | [.5,2.0]× |
458
+ # ---------------------------------------------------------------------
459
+ # ORIENTAÇÃO DOS SINAIS (justificativa de cada linha):
460
+ # β₁ — variância de gradiente alta (ruído) ⟹ ↑β₁ (memória maior do 1º
461
+ # momento denoise a direção); β₂ — deriva do 2º momento alta ⟹
462
+ # ↓β₂ (adaptar mais rápido); ε — razão ‖update‖/‖g‖ ≠ 1 ⟹ ε
463
+ # restabelece (sinal RM multiplico em log); wd — norma de peso
464
+ # acima do alvo 1.0 ⟹ ↑wd; momentum do Muon — ‖buf‖/‖g‖ vs 1.0;
465
+ # escala — Teo 24.11 (RMS comparável entre mecanismos); τ_qk —
466
+ # banda do logit (Teo 29.15); η_up/η_down — acerto do trust alto
467
+ # ⟹ sobe mais agressivo, baixo ⟹ corta mais; T_ciclo/decay_piso
468
+ # — progresso rápido ⟹ ciclos mais longos (explorar); percentil
469
+ # — clips além do alvo ⟹ admitir mais; PESO_MOE — Teo 28.7-ii
470
+ # (CE é a descida primária; razão L_moe/L_ce ≤ 0.5); PESO_SOM —
471
+ # ativação da memória vs 90%; ABMO — folga da barreira η ≤
472
+ # (2−m)/L̂ (Teo 24.9) escalada conservadoramente; CIAR/cresc —
473
+ # taxas de aceitação/expansão/poda contra alvos declarados.
474
+ # PROVA DE (a)–(d): (a) leitura da tabela; (b) assert no construtor;
475
+ # (c) Teo 29.14-ii; (d) inspeção das condições de denomina-
476
+ # dor/positividade dos consumos — cada limites escolhido para
477
+ # preservá-las. ∎ [V29.16: 18 controladores nascem neutros, movem
478
+ # com sinais sintéticos e permanecem nos limites; hub registra tudo]
479
+
480
+ # =====================================================================
481
+ # §10 — CONFIG (D14) E INTEGRAÇÃO
482
+ # =====================================================================
483
+ # Campos mortos do config do rascunho, agora VIVOS:
484
+ # QECTConfig.normalizar → governa QE relativo (Teo 29.4-i);
485
+ # DifusaoConfig.eta_lambda→ passo do EG de λ_diff (Teo 29.2-ii);
486
+ # Campos NOVOS (cada um com prova correspondente):
487
+ # JEPAConfig.peso_var → Teo 29.10/29.13 (era 0.01 hard-coded);
488
+ # JEPAConfig.ema_cosseno → Teo 29.12 (BYOL, opt-in);
489
+ # DifusaoConfig.rho_ancora→ Teo 29.2-iii (ótimo interior);
490
+ # LambdaCConfig.modo → Teo 29.7-i (alvo vs reversão);
491
+ # LambdaCConfig.eta_agendado/tau_eta → Teo 29.7-ii (RM q.c.);
492
+ # TradeoffKConfig.estimar_C/C_prior/kappa_prior → Teo 29.8;
493
+ # QECTConfig.alpha/n_min → Teo 29.5.
494
+ # INTEGRAÇÃO COM A PRODUÇÃO (sem regressão):
495
+ # • pacote NOVO src/khtst/aprimoramento/ — nenhum módulo existente
496
+ # modificado; verificar_tudo.py (49✓) permanece verde;
497
+ # • JEPA delega o VICReg completo ao kernel Cython existente
498
+ # (khtst.treino.jepa_cython) quando vicreg_lambda>0 — Cython
499
+ # prioritário (requisito do projeto), fallback PyTorch honesto;
500
+ # • a suíte v17 fixa TODAS as propriedades novas (Teos 29.1–29.16).
501
+
502
+ # =====================================================================
503
+ # §11 — VERIFICAÇÃO NUMÉRICA (resumo da suíte v17)
504
+ # =====================================================================
505
+ # [V29.2] hipergradiente exato ≡ autograd (≤1e-7 rel); λ* analítico ≡
506
+ # numérico; EG regret consistente com a cota em simulação.
507
+ # [V29.3] EMA: perda média com θ̄ ≤ perda média com θ (convexidade
508
+ # numérica em quadrática).
509
+ # [V29.4] CT_norm invariante a fatoração (B,D)↔(B',D') com B·D igual;
510
+ # QE_rel invariante a reescala α.
511
+ # [V29.5] nível do teste: sobre N=1000 experimentos nulos, taxa de
512
+ # falso ganho ≤ α+folga; Student-t e Hoeffding (R declarado)
513
+ # concordam no sinal.
514
+ # [V29.6] KDTree ≡ força bruta bit-a-bit em 100 grades aleatórias
515
+ # (mínimos únicos).
516
+ # [V29.7] equivalência fast≡ref (10⁴ passos, 0.0); sinal suavizado
517
+ # responde à média da janela (regressão do D6); agenda RM
518
+ # satisfaz Ση=∞, Ση²<∞ numericamente.
519
+ # [V29.8] Ĉ recupera C sintético (erro ≤ 10% com shrinkage); p̂ ≈ −2/d.
520
+ # [V29.9] unimodalidade em varredura fina (20k pontos); K* fechado ≡
521
+ # numérico (≤1%); sensibilidade C^{d/2} confirmada em dupla
522
+ # precisão.
523
+ # [V29.10] contraexemplo σ=(2,0): per-dim > poolado (0.5 > 0); Jensen
524
+ # vale em 1000 sorteios de espectros.
525
+ # [V29.11] pooling não-expansivo (‖Pz‖ ≤ ‖z‖/√r medido); energia de
526
+ # truncamento ≥ erro de pooling no regime espalhado.
527
+ # [V29.12] m(0)=m₀, m(T)→1, monótona.
528
+ # [V29.13] colapso: var_loss > 0 e gradiente não-nulo no ponto constante.
529
+ # [V29.14] telescoping exato; anti-windup sob sinal adverso constante;
530
+ # rastreio de setpoint e_∞ ≈ 0.
531
+ # [V29.15] τ converge à banda sob ℓ_obs=min(ℓ_nat,τ); erro do colchete
532
+ # ≤ (τmax−τmin)/2^k.
533
+ # [V29.16] 18 controladores nascem neutros (θ=centro), movem com
534
+ # sinais e permanecem nos limites; TelemetryHub registra.
535
+
536
+ # =====================================================================
537
+ # §12 — REGRAS OPERACIONAIS (v17)
538
+ # =====================================================================
539
+ # R1. Nenhum parâmetro regulável novo entra em produção SEM linha na
540
+ # tabela de sinais (centro=constante atual, limites seguros, prova
541
+ # de orientação do sinal).
542
+ # R2. Todo controlador nasce NEUTRO e desligado em produção (opt-in);
543
+ # corridas de demonstração podem acelerar a0/τ_a.
544
+ # R3. Sinais são SEMPRE adimensionais (∈[−1,1]) — sinal_razao é o único
545
+ # ponto de normalização.
546
+ # R4. Nenhum sinal instantâneo cru governa um controlador: médias de
547
+ # janela com teto de RAM (Teo 29.7-i) são obrigatórias.
548
+ # R5. Todo teste de "ganho real" usa nível α controlado (Teo 29.5);
549
+ # limiares fixos são no máximo condição necessária.
550
+ # R6. Modelos paramétricos (Zador) são SEMPRE acompanhados do teste do
551
+ # modelo (inclinação) e de fallback honesto (grade).
552
+ # R7. Anti-colapso é SEMPRE por dimensão (Teo 29.10) — hinge poolado é
553
+ # proibido em código novo.
554
+ # R8. τ_qk só cresce dentro da banda [40,400] e nunca anula a cota
555
+ # estrutural do logit (Teo 27.2).
556
+
docs/matematica/29-moe-empacotada-tce-sonicmoe-replayssm.md DELETED
@@ -1,346 +0,0 @@
1
- # 29 — KHMAMBAJEPA v17: MoE EMPACOTADA · TCE CURADA · SONICMOE + REPLAYSSM · TOKEN ROUNDING CTHONIANO
2
-
3
- *Doc matemático da v17 — a MoE deixa de ser excluída da quantização
4
- (árvores/florestas/indexadores contra o empilhamento que quebra o contrato
5
- de subclasses), a perda TCE da suíte v16 é diagnosticada e curada com
6
- provas, o SonicMoE ganha auditoria de memória em tempo real (I1–I4) e o
7
- Token Rounding exato vive no kernel Cython `jepa_validator`, e o ReplaySSM
8
- troca memória por recomputação com gradiente BIT-EXATO.*
9
-
10
- ---
11
-
12
- ## 0. Escopo e honestidade
13
-
14
- A v17 mantém TUDO o que estava provado (docs 00–28) e resolve os DOIS
15
- problemas abertos da rodada + os dois subsistemas novos. Cada teorema vem
16
- com a verificação empírica executada nesta versão (suíte
17
- `tests/test_khtst_v17.py`, 59 verificações verdes; `run_verification.py`
18
- 8 blocos verdes; treino real pareado em `telemetria_out/metricas_v17/`).
19
- O que NÃO se afirma: (i) que os experts do `MoEEncoderDecoderKHTST` estão
20
- quantizados — seu forward é por módulo (sem stack), mas `agrupar()` e a
21
- telemetria assumem pesos planos; eles ficam FP32 e constam como limitação
22
- honesta (§2.5); (ii) que a v17 supera o baseline v16 em CE em 120 passos —
23
- o A/B pareado (§10) reporta o que medir, com a leitura matemática.
24
-
25
- ---
26
-
27
- ## 1. PROBLEMA 1 — o empilhamento quebra o contrato de subclasses
28
-
29
- ### Diagnóstico (bug v16, agora evidência executável)
30
-
31
- O forward vetorial da `MoEAgrupavel` empilha os pesos dos experts ativos:
32
-
33
- $$W_{\text{gate}} = \operatorname{stack}\{W^{(e)}_{\text{gate}}\}_{e \in A}.$$
34
-
35
- Após `quantize_`, `W^{(e)}` é um **subclass** `Int8Tensor` (int8 +
36
- escala por canal). A sonda `sonda_opset_subclass()` executa e prova:
37
-
38
- | operação | Int8Tensor | consequência |
39
- |---|---|---|
40
- | `aten.stack` | **NotImplementedError** | forward v16 crasha ⟹ exclusão Teo 28.3-iv |
41
- | `narrow`/slice | OK | **indexador legal** (Teo 29.2) |
42
- | `F.linear` | OK (int8pack) | GEMM nativa consumindo int8 |
43
-
44
- ### Teorema 29.1 (bijeção φ do empacotamento plano)
45
-
46
- Sejam $W^{(e)} \in \mathbb{R}^{f\times d}$ os pesos FP32 dos $N$ experts e
47
- $W_{\text{pool}} = [W^{(0)}; \dots; W^{(N-1)}] \in \mathbb{R}^{Nf\times d}$
48
- o pool. A aplicação $\varphi(e,i) = e\cdot f + i$ é uma **bijeção** de
49
- $\{0..N{-}1\}\times\{0..f{-}1\}$ em $\{0..Nf{-}1\}$ e vale
50
- $W_{\text{pool}}[\varphi(e,i)] = W^{(e)}[i]$ **bit-exato** (cópia de
51
- memória — `torch.cat`). Como a quantização é POR LINHA, a escala da linha
52
- $r$ no pool é a MESMA que a do expert dono da linha:
53
-
54
- $$s_r = \frac{\max_r - \min_r}{2^b - 1},$$
55
-
56
- logo dequantizar a fatia ≡ dequantizar o expert individual, **bit-exato**
57
- (nenhuma informação nova, nenhuma perdida). ∎
58
- *Verificação: `indexador_bit_exato_linha = True` no pack; erro da fatia ≤
59
- cota $h/\sqrt{12}$ do Teo 28.1.*
60
-
61
- ### Teorema 29.2 (indexador por fatias — substituto do stack)
62
-
63
- A fatia do expert $e$ é $W^{(e)}_{\text{q}} = W_{\text{pool,q}}.\mathrm{narrow}(0,\, e f,\, f)$
64
- — visão **zero-copy** dentro do subclass. Como `narrow` ∈ opset do
65
- Int8Tensor (sonda) e `F.linear` ∈ opset, o forward
66
- $y_e = F.\mathrm{linear}(x, W^{(e)}_{\text{q}})$ despacha o kernel int8
67
- nativo SEM materializar empilhamento algum. A igualdade com o forward
68
- FP32 segue de Teo 28.1/28.2 (erro de quantização por camada ≤ $h/\sqrt{12}$
69
- por linha; propagação pela condição da camada). ∎
70
- *Verificação: Δy relativo = 6.6e-03 (suíte v17 §1) ≤ cota.*
71
-
72
- ### Teorema 29.3 (floresta de B blocos — índice de 2 níveis)
73
-
74
- Particione os experts em $B$ blocos contíguos de $\lceil N/B\rceil$; o
75
- bloco $b$ é um pool próprio $W^{(b)}_{\text{q}}$. O índice vira
76
- $e \mapsto (b(e), j(e)) = (\lfloor e/\lceil N/B\rceil\rfloor,\ e \bmod \lceil N/B\rceil)$.
77
- Propriedades provadas:
78
-
79
- 1. **Exatidão**: as linhas de $W^{(b)}$ são as mesmas de $W_{\text{pool}}$
80
- (mesma $\varphi$ restrita) ⟹ fatia$(b,j)$ ≡ fatia$_{\text{plana}}(e)$
81
- bit-exato;
82
- 2. **GEMM por bloco**: com o bloco inteiro ativo, gate/up são UM
83
- `F.linear` cada sobre linhas contíguas (o reshape da SAÍDA é tensor
84
- plano — legal); o `down` por fatia por expert (a SwiGLU é
85
- $d\!\to\!f\!\to\!f\!\to\!d$: as linhas do down de um expert NÃO são
86
- contíguas na saída do gate — o índice 2 níveis dá a fatia exata;
87
- $n_b \le \lceil N/B\rceil$ pequenos);
88
- 3. **Custo do índice**: $B$ views armazenadas vs $N$; $B{=}1$ recupera o
89
- pool plano. ∎
90
- *Nota v17.1: $f$ é POR PAPEL — gate/up têm $f$ linhas = d_ff_expert,
91
- down tem $d$ linhas = d_model (bug de forma corrigido e coberto pela
92
- suíte).*
93
-
94
- ### Teorema 29.4 (rollback sem `copy_` sobre subclass)
95
-
96
- O rollback atômico restaura os pesos FP32 originais salvos e remove as
97
- views. `load_state_dict` NÃO serve: `copy_` plain→Int8Tensor falha
98
- (`'Tensor' object has no attribute 'qdata'` — evidência). A restauração
99
- v17 substitui `param.data` por tensor plano quando a classe difere (o
100
- despacho do forward volta ao kernel FP32 padrão) e usa `copy_` só entre
101
- classes iguais ⟹ estado pós-rollback **bit-idêntico** ao pré-pack (cota
102
- superior — nunca piora). Os pools NÃO são serializados: são DADOS
103
- DERIVADOS de $(\theta_{\text{orig}}, \text{modo})$ por função
104
- determinística ⟹ recriáveis com `empacotar_moe` após carregar
105
- (não-serialização sem perda de informação). ∎
106
- *Verificação: rollback bit-exato (suíte v17 §1); `pools` ausente do
107
- state_dict; A/B real com `torchao_degradacao_perda` medido (§10).*
108
-
109
- ### 2.5 Limitação honesta
110
-
111
- `MoEEncoderDecoderKHTST` (2 encoders + 4 decoders): forward por módulo
112
- (sem stack) MAS `agrupar()` (fusão ponderada) e a telemetria de uso
113
- assumem pesos planos. Os 6 experts permanecem FP32 na inferência
114
- quantizada — custo: $6 \times 3 \times d \times f \times 4$ bytes. A
115
- cura completa (pools + desvio no `_executa_experts`) é v18.
116
-
117
- ---
118
-
119
- ## 2. PROBLEMA 2 — a perda TCE da suíte v16: causa e cura
120
-
121
- ### Diagnóstico medido (telemetria v16 real)
122
-
123
- `telemetria_out/metricas_v16_v16_khmambajepa.json`:
124
- `jepa/perda = 24.96`, `jepa/taxa_sucesso = 0.0`, `var_latente = 0.68`
125
- (sem colapso — a perda alta NÃO é colapso; é escala).
126
-
127
- ### Teorema 29.5 (magnitude ∝ d — a soma do Huber)
128
-
129
- Com latentes esféricos (FunilLatente, $\|f(x)\|_2 = \sqrt{d}$), cada
130
- componente tem $E[e_j^2] \approx 1$ no arranque. O Huber com $\delta=1$
131
- por componente tem $E[\mathrm{Huber}(e_j)] = c_H \in (0.3, 0.5)$ para
132
- componentes ~unitários, logo
133
-
134
- $$L_{\text{v16}} = \sum_{j=1}^{d} \mathrm{Huber}(e_j) \approx c_H \cdot d
135
- \quad (d = 64 \Rightarrow L \approx 25 — \textbf{medido } 24.96).$$
136
-
137
- **Cura (normalização dimensional)**: $L \leftarrow L/d$. Por
138
- LINEARIDADE da perda em cada componente (o Huber é aplicado
139
- elemento-a-elemento e a soma é linear),
140
-
141
- $$\nabla_\theta (L/d) = \tfrac{1}{d}\nabla_\theta L \quad \text{EXATAMENTE},$$
142
-
143
- logo a regra é uma **reparametrização pura** $\lambda' = \lambda\cdot d$:
144
- o ponto estacionário é o MESMO e a v16 é recuperada com
145
- $\lambda' = \lambda_{v16}\cdot d$. Ganhos: (i) a razão $L/\mathrm{CE}$
146
- fica O(1) — comparável entre arquiteturas e com a fronteira ½ do Teo
147
- 28.7-ii; (ii) a autorregulação RM de λ_jepa torna-se BEM DEFINIDA (a razão
148
- v16 ≈ 2.8 violava a fronteira estruturalmente, não por qualidade). ∎
149
- *Verificação: L_normalizada = L_soma/d com erro < 1e-6 (suíte v17 §3).*
150
-
151
- ### Teorema 29.6 (limiar de sucesso invariante à escala)
152
-
153
- O limiar v16 $\|e\|_2 < 1$ com $\|\text{alvo}\|_2 = \sqrt d = 8$ exige
154
- erro relativo $< 1/\sqrt d = 0.125$ desde o 1º passo — com predictor
155
- recém-nascido, taxa $\equiv 0$ (medido), e a tabela de μ (Teo 5.6) fica
156
- CEGA (μ nunca se adapta). **Cura**: limiar relativo
157
-
158
- $$\|e\|_2^2 \le \theta\,\|\text{alvo}\|_2^2, \quad \theta = 0.5.$$
159
-
160
- **Homogeneidade**: para todo $c > 0$,
161
- $\|c e\|^2 \le \theta \|c\,\text{alvo}\|^2 \iff \|e\|^2 \le \theta\|\text{alvo}\|^2$
162
- — a taxa não depende da norma do latente (só da direção); uma predição
163
- proporcional ao alvo com fator $\sqrt\theta$ passa QUALQUER que seja a
164
- escala do encoder. ∎
165
- *Verificação: taxa 0.000 → 1.000 após 300 passos Adam em entrada
166
- predizível; invariante a $c = 50$ (suíte v17 §3).*
167
-
168
- ### Teorema 29.7 (a taxa invariante alimenta a tabela de μ)
169
-
170
- Com a taxa real $s_t > 0$ (Teo 29.6), a média móvel
171
- $\bar s_t$ entra em $\mu_t = \mu_{max}^{(1-\bar s_t)}\mu_{min}^{\bar s_t}$
172
- (Teo 5.6) e o EMA do alvo responde ao progresso REAL do predictor — o
173
- loop preditor↔alvo volta a ser governado por medida, não por placeholder.
174
- ∎ *Verificação: `jepa/taxa_sucesso` ≥ 0 e μ_efetivo vivo no treino real.*
175
-
176
- ### Teorema 29.8 (λ_jepa autorregulado pela razão PONDERADA)
177
-
178
- O RM do λ_jepa usa a razão PONDERADA $r_t = \lambda_t L_t / \mathrm{CE}_t$
179
- (não $L_t/\mathrm{CE}_t$): com a normalização L/d, $\lambda_t L_t$ é a
180
- contribuição REAL do JEPA ao gradiente total; a fronteira $r \le 1/2$ do
181
- Teo 28.7-ii mantém a CE como descida primária. Como $r_t$ é medido na
182
- mesma cadência do RM (Σa = ∞, Σa² < ∞), λ_jepa converge ao ponto onde a
183
- razão cruza o alvo — equilíbrio na fronteira, sem pêndulo. ∎
184
- *Verificação: `_razoes_aux["jepa"]` registrado (0.005 na suíte §7);
185
- controlador "jepa" vivo no autorregulador.*
186
-
187
- ### Regra operacional (doc 28 §9 atualizada)
188
-
189
- A leitura honesta do A/B v16 ("JEPA puxava a perda total") era o Teo
190
- 28.7-ii VIOLADO pela escala ∝ d. Com L/d + limiar invariante + λ
191
- autorregulado pela razão ponderada, a contribuição auxiliar volta a ser
192
- ≤ 50% da CE POR CONSTRUÇÃO — o λ default sobe para 7.5
193
- ($\approx 0.117$ em unidades v16) e o controlador cuida do resto.
194
-
195
- ---
196
-
197
- ## 3. jepa_validator — o bloco de predição CTHONIANO
198
-
199
- ### Teorema 29.10 (registro em aritmética C)
200
-
201
- `JEPAManager.register_variant` acumula `total_params` em `long long`
202
- nativo (sem boxing Python): a soma de $k$ variantes é exata enquanto
203
- $\texttt{total} < 2^{63}$ — para qualquer modelo real. `verify_all`
204
- recalcula o total em laço C e compara ao registrado (auditoria de
205
- integridade do dict); `compute_parameter_distribution` devolve array
206
- NumPy float64 **contíguo** com Σ = 1 (variante ausente ⟹ vazio, nunca
207
- NaN). Contagens negativas são rejeitadas ANTES da acumulação (contrato
208
- de monotonia). ∎ *Verificação: suíte v17 §4 (93,800 exato; Σ=1
209
- 1e-12; ValueError nos negativos).*
210
-
211
- ### Teorema 29.11 (Token Rounding EXATO — GEMM estofado bit-exato)
212
-
213
- No bloco de predição, o número de tokens é arredondado ao múltiplo do
214
- tile τ: $n̂ = \tau\lceil n/\tau\rceil$, razão de estofamento
215
- $\rho = n̂/n$, estofamento POR CAUDA (offsets = identidade; as linhas
216
- extras são zeros). Propriedade: **out[t] = Σ_d X[t,d]·W[k,d] é
217
- independente por linha** — acrescentar linhas nulas adiciona linhas de
218
- saída nulas e preserva BIT-A-BIT as linhas vivas (mesma ordem de
219
- acumulação do kernel por linha). Custo: $\rho - 1 \le (\tau-1)/n$
220
- ($\tau \mid n \Rightarrow \rho = 1$). O tile alinha o acesso IO da GEMM
221
- (SonicMoE tile-aware) SEM mudar o resultado. `escolher_tile` minimiza o
222
- custo efetivo $t(\tau)\cdot\rho(\tau)$ medido. ∎
223
- *Verificação: n̂/ρ exatos; GEMM estofado ≡ GEMM nas linhas vivas
224
- (torch.equal); τ* por medição (suíte v17 §4).*
225
-
226
- ### Teorema 29.12 (auditoria de memória em tempo real — I1–I4)
227
-
228
- `AuditoriaMemoriaSonic` lê `/proc/self/statm` nível C (~µs; custo
229
- insignificante por passo) e mantém janelas em ARRAYS C FIXOS (a própria
230
- auditoria não aloca — dogfooding de I1):
231
-
232
- - **I1 não-vazamento (Teo 29.12-c, calibrado)**: vazamento = crescimento
233
- MONOTÔNICO — **mediana** do último terço vs mediana do primeiro terço
234
- $> 4$ MB **E** inclinação recente $> 0.5$ MB/amostra. MEDIANAS (não
235
- médias): a variação legítima de tamanho de lote OSCILA (medianas
236
- convergem); um vazamento cresce TODA amostra (medianas separam). O
237
- aquecimento legítimo que plateaua não reprova (reancoragem `rebase()`
238
- 1× pelo treinador no passo 20). Corrida real calibrada: crescimento
239
- 0.89 MB (verde) com lotes multimodais heterogêneos.
240
- - **I2 recompute ≤ fwd (calibrado)**: anomalia REAL de recompute é de
241
- ESCALA — fugir do checkpoint = memória O(L) inteira ≈ 10–100× o
242
- forward. Folga $2.5\times + 192$ MB (a janela de recompute inclui a
243
- alocação legítima de gradientes e a variação de lote).
244
- - **I3 sem transiente de empilhamento (calibrado)**: entre
245
- `pilha_ini/pilha_fim` o RSS não excede pico_fwd $\times 2 + 128$ MB —
246
- o stack de subclass materializaria transiente $N\!f d$ extra; o pool
247
- indexado (Teo 29.2) não; lotes heterogêneos variam bem menos que a
248
- folga de escala.
249
- - **I4 só ativos**: amostras $(A, \Delta\mathrm{RSS})$ provam que a
250
- memória segue os experts ATIVOS, não $N$ (verificação por regressão na
251
- suíte).
252
-
253
- *Verificação: I1–I4 verdes em passos reais do treinador (suíte v17 §7
254
- com texto; A/B real multimodal com crescimento 0.89 MB — verde);*
255
- vazamento sintético (240 MB em 60 amostras, malloc direto) REPROVADO
256
- pelo I1 — "auditoria que nunca reprova não audita".*
257
-
258
- ---
259
-
260
- ## 4. ReplaySSM — memória por recomputação com gradiente exato
261
-
262
- ### Teorema 29.13 (saída e h_L BIT-EXATOS por replay de fronteira)
263
-
264
- A sequência é dividida em $S$ segmentos; cada segmento $s$ roda a MESMA
265
- recorrência trapezoidal partindo do estado fronteira $h_{s-1}$:
266
-
267
- $$h_t = \alpha_t h_{t-1} + \mathrm{entrada}_t, \qquad h_{s\cdot L_s} = h_{s-1}\big|_{\text{fronteira}}.$$
268
-
269
- Por indução em $t$: se $h_{(s-1)L_s}$ do replay é o valor EXATO do kernel
270
- completo (fronteira exata anterior + mesma recorrência + mesmos
271
- operandos), então todo $h_t$ do replay é o valor exato ⟹ **out** e
272
- **h_L** bit-exatos vs `varredura_trapezoidal` (diferença medida 0.0).
273
- `h_inicial=None` ⟹ $h_0 = 0$ = v12 exato (nascimento neutro). ∎
274
- *Verificação: torch.equal nas duas quantidades; S=1 ≡ kernel.*
275
-
276
- ### Teorema 29.14 (gradiente exato e memória O(S·BDN + L_s·BDN))
277
-
278
- Com `checkpoint(use_reentrant=False)` por segmento e a fronteira levando
279
- grad_fn (SEM detach), o grafo cruza as fronteiras e a recomputação no
280
- backward é DETERMINÍSTICA (mesmos operandos, kernels CPU
281
- determinísticos) ⟹ $\nabla = \nabla_{\text{autograd}}$ do kernel completo
282
- (erro medido 0.0). Memória: os intermediários do laço temporal por
283
- segmento são libertados no forward e recomputados no backward —
284
- ativações guardadas $O(S\cdot BDN + L_s\cdot BDN)$ vs $O(L\cdot BDN)$;
285
- para $L \gg L_s$ a razão tende a $S/L$. ∎
286
- *Verificação: erro de gradiente 0.0 (suíte v17 §5); cfg
287
- `mamba3.replay_segmento` chega às camadas (5 Mamba3Camada no tronco).*
288
-
289
- ---
290
-
291
- ## 5. Integração no treinador (tudo VIVO)
292
-
293
- | mecanismo | cfg | nascimento | telemetria |
294
- |---|---|---|---|
295
- | pools MoE | `modelo.torchao.empacotar_moe` / `n_blocos_floresta` | ausente ⟹ forward v16 | `torchao/moe_compressao` |
296
- | TCE normalizada | `treino.jepa.normalizar_dim` / `taxa_theta` | True/0.5 | `jepa/perda` (O(1)), `jepa/perda_soma` (compat) |
297
- | λ_jepa ponderado | automático (Teo 29.8) | escala 1.0 | `autorreg/lambda_jepa` |
298
- | ReplaySSM | `modelo.mamba3.replay_segmento` (0 = v12) | 0 | — (bit-exato por construção) |
299
- | auditoria I1–I4 | `treino.auditoria_sonic.ativo` | ligada | `sonic/*` no Hub a cada 100 passos |
300
- | multi-método | `treino.multi` (doc 30) | escalas 1.0 | `multi/*` (15 controladores) |
301
-
302
- ---
303
-
304
- ## 6. A/B pareado real (corpus 903, vocab 16384, 30 passos, lote 4)
305
-
306
- | variante | perda início → fim | melhoria | held-out FP32 |
307
- |---|---|---|---|
308
- | baseline_v16 (semântica v16: perda SOMA, limiar absoluto) | 9.727 → 9.374 | **1.038×** | 9.774 |
309
- | v17_khmambajepa (L/d + limiar θ + MULTI + ReplaySSM S=16) | 9.729 → 9.301 | **1.046×** | 9.769 |
310
-
311
- (Réplica anterior com outro sorteio da mistura: base 1.008× vs v17
312
- 1.039× — a ordem CE troca com o sorteio em 30 passos: PARIDADE; a
313
- decisão é da corrida 9 h.)
314
-
315
- - **TCE**: v17 perda normalizada **0.54** (v16: 24.96 — redução ~46× por
316
- construção, Teo 29.5); taxa de sucesso **0.104** (v16: ≡ 0).
317
- - **torchao + MoE EMPACOTADA**: 260 camadas + 1 MoE (pools), compressão
318
- **3.92×**, erro rel. 0.39% ≤ cota, **Δperda held-out FP32→int8+pack =
319
- 0.0** (Teo 29.2/28.1 cumpridas em treino real).
320
- - **Auditoria I1–I4 na corrida real**: I2 ✓, I3 ✓, I4 ✓; I1 INDICATIVO
321
- (modo_janela="curto": 60 amostras < 200 — o ratchet do alocador em
322
- lotes heterogêneos é falso-positivo conhecido, Teo 29.12-d;
323
- crescimento medido 121 MB não é vazamento — é working set ratchetado;
324
- nas corridas 9 h a janela satura e o teste é definitivo). Na suíte
325
- controlada (§7) I1 é VERDE e REPROVA vazamento sintético.
326
- - **τ_qk bisseção**: ℓ_max ≈ 1.5 ≪ faixa ⟹ τ relaxa 100 → 205 (ocioso
327
- como previsto — Teo 30.7; QK-clip nunca dispara).
328
- - **Leitura honesta**: 30 passos não decidem CE; o que a v17 compra em
329
- corrida curta é ESTRUTURAL (MoE quantizada, TCE sã, memória auditada,
330
- governança viva).
331
-
332
- ---
333
-
334
- ## 7. Verificação v17 (resumo executável)
335
-
336
- ```
337
- python3 src/khtst/acelerado/run_verification.py # 8 blocos (A–H)
338
- python3 tests/test_khtst_v17.py # 59 verificações
339
- python3 patches/verificar_tudo.py # 49 ✓ / 0 ✗
340
- python3 scripts/21_teste_v17.py --retreinar_tokenizador # vocab 16384
341
- python3 scripts/21_teste_v17.py --variante baseline_v16 --passos 120
342
- python3 scripts/21_teste_v17.py --variante v17_khmambajepa --passos 120
343
- python3 scripts/21_teste_v17.py --relatorio # A/B pareado
344
- ```
345
-
346
- Regressão v1–v16: TODAS verdes (25/36/✓/37/32/48/44/21/✓/✓/✓/28/27/40/45).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docs/matematica/30-autoajuste-multi-metodo.md DELETED
@@ -1,266 +0,0 @@
1
- # 30 — KHMAMBAJEPA v17: AUTOAJUSTE MULTI-MÉTODO (RM + PID + BISSEÇÃO) PARA TODOS OS PARÂMETROS FIXOS
2
-
3
- *Doc matemático da v17, parte 2 — a proposta do requisito (§§1–4)
4
- transformada em governança EXECUTÁVEL: cada parâmetro fixo de projeto
5
- (AdamW β₁/β₂/ε/wd, Muon momentum, τ_qk, PRS V8, PESO_MOE,
6
- PESO_ALINHAMENTO_SOM, margem ABMO, CIAR, crescimento) recebe um
7
- controlador com recursão híbrida, sinais definidos, limites seguros e
8
- auditoria integral no TelemetryHub.*
9
-
10
- ---
11
-
12
- ## 0. Escopo e honestidade
13
-
14
- Cada teorema é acompanhado da verificação empírica da suíte v17 (§6) e,
15
- quando aplicável, do treino real. Onde o sinal literal do requisito forma
16
- realimentação POSITIVA (divergência provável), o doc PROVA o problema e
17
- inverte o sinal mantendo a semântica — com o contraexemplo exposto
18
- (Teo 30.6). O que NÃO se afirma: que as escalas convergem em 120 passos
19
- de corrida curta — as constantes aceleradas (a0=0.15, τ_a=60) fazem os
20
- controladores se MOVAREM visivelmente; a convergência assintótica é o
21
- enunciado das provas, não a leitura de uma corrida.
22
-
23
- ---
24
-
25
- ## 1. A recursão híbrida unificada
26
-
27
- ### Teorema 30.1 (RM + perturbação determinística limitada: pertença e convergência)
28
-
29
- Todo parâmetro governado $\theta_t = \exp(u_t)$ com
30
-
31
- $$u_{t+1} = u_t + a_t s_t + b\,e_t + c_i I_t + c_d \Delta e_t,$$
32
-
33
- $a_t = a_0/(1+t/\tau_a)$, $|s_t| \le 1$, $|e_t| \le 1$ (canais
34
- normalizados), $I_t = \mathrm{clip}(0.98\,I_{t-1} + e_t, \pm 1)$
35
- (vazamento anti-windup), $\Delta e_t = e_t - e_{t-1}$:
36
-
37
- 1. **Pertença**: com truncagem $u \in [\ln \theta_{min}, \ln \theta_{max}]$,
38
- $\theta_t \in [\theta_{min}, \theta_{max}]$ PARA TODO $t$ — os termos
39
- PID são limitados por $|b| + |c_i| + |c_d|$ (passo_max clipa o total),
40
- logo não há escape dos limites;
41
- 2. **Convergência q.c.** (parte RM): $a_t$ satisfaz
42
- $\sum a_t = \infty$, $\sum a_t^2 < \infty$ (condição clássica de
43
- Robbins–Monro, Teo 28.5) — o ruído de medida é médio e o iterante
44
- converge q.c. ao conjunto estacionário do campo de deriva;
45
- 3. **O PID não quebra 2** (duas escalas, Borkar): com ganhos $b, c_i, c_d$
46
- O(1) e $a_t \to 0$, o canal PID opera em escala de tempo MAIS RÁPIDA —
47
- ele leva $e_t \to 0$ (loop negativo do Teo 30.2) e o resíduo
48
- assintótico do RM é o equilíbrio $e = 0$ do campo médio;
49
- 4. **Anti-windup**: com vazamento 0.98, $I_t$ é mapeamento contratativo
50
- no erro ($|I_t| \le 1$) — o integrador não retém memória ilimitada. ∎
51
-
52
- *Verificação: 2000 passos com sinais máximos ⟹ θ ∈ [θ_min, θ_max]
53
- sempre; integral satura exatamente em 1.0 (suíte v17 §6).*
54
-
55
- ### Teorema 30.2 (estabilidade do loop proporcional em log-escala)
56
-
57
- Seja a medida $m(\theta)$ monotônica em $\theta$ com ponto alvo $m^*$ e
58
- erro $e(\theta) = \pm(m^* - m(\theta))/\mathrm{norm}$ com SINAL escolhido
59
- de modo que $e \cdot (\theta - \theta^*) < 0$ (realimentação NEGATIVA).
60
- Linearizando em $u = \ln\theta$: $\Delta u_t \approx a\, k\, (u_t - u^*)$
61
- com $k = \partial e/\partial \ln\theta > 0$ — o loop discreto é estável
62
- sse $|1 - a k| < 1$, i.e.
63
-
64
- $$a_0\, k < 2 \quad (\text{na pior cadência do decaimento}).$$
65
-
66
- Todos os controladores abaixo têm a condição verificada analiticamente
67
- (k explícito) — valem com os defaults e com as constantes aceleradas das
68
- corridas curtas. ∎
69
-
70
- ---
71
-
72
- ## 2. AdamW: β₁, β₂, ε, weight_decay (requisito §3.1)
73
-
74
- ### Teorema 30.3 (β₂ por variância do gradiente; β₁ pela tendência)
75
-
76
- Métrica: $CV^2 = \mathrm{Var}[\|g\|]/E[\|g\|]^2$ sobre a janela (proxy de
77
- curvatura/ruído). Sinais:
78
- - $\beta_2$: $s = \frac{CV^2_{\text{alvo}} - CV^2}{CV^2_{\text{alvo}} + CV^2}$
79
- — variância ALTA ⟹ ruído domina ⟹ β₂ DESCE (média móvel mais curta,
80
- mais adaptativa — o 2º momento acompanha o regime); variância baixa ⟹
81
- β₂ sobe (suavização). Monotonia: ∂CV²/∂(regime) > 0 e a escala β₂
82
- multiplica o β de projeto ⟹ resposta monótona (Teo 30.2) com
83
- $k \le 1$ ⟹ $a_0 < 2$ ✓.
84
- - $\beta_1$: $s = -\mathrm{tend}(CV^2)$ — tendência de ALTA ⟹ β₁ desce
85
- (menos momentum no 1º momento = mais reatividade ao novo regime);
86
- queda ⟹ β₁ sobe. ∎
87
-
88
- *Verificação: CV²=4 sustentado ⟹ β₂ escala → piso 0.9 (suíte v17 §6);
89
- no treino real β₂=1.0 no nascimento (Teo 30.1) e vivo na cadência.*
90
-
91
- ### Teorema 30.4 (ε pela razão update/gradiente)
92
-
93
- Sinal do requisito: $\rho_t = \|\Delta p\|/\|g\|$ (medido em amostra fixa
94
- de ≤12 parâmetros, custo O(amostra)). ε entra no denominador do passo
95
- AdamW: $\varepsilon \uparrow \Rightarrow$ passo ↓. Loop correto: ρ acima
96
- do alvo 1.0 (updates grandes relativos ao gradiente — risco) ⟹ ε sobe
97
- (amortece); ρ baixo ⟹ ε desce (passo mais cheio). Sinal
98
- $s = \frac{\rho - 1}{\rho + 1}$ com ∂ρ/∂ε < 0 ⟹ realimentação negativa;
99
- $k \le 1$ ⟹ estável (Teo 30.2). ∎
100
-
101
- ### Teorema 30.5 (weight_decay com norma RELATIVA — o alvo absoluto 1.0 é infactível)
102
-
103
- **Lema (infactibilidade)**: com RMS(W_init) ≈ 0.02 (tabelas/embeddings),
104
- exigir $\|W\| = 1.0$ absoluto pediria crescimento de 50× — o wd explodiria
105
- no nascimento. **Forma relativa**: $\bar n_t = \mathbb{E}_\text{amostra}
106
- [\|W\|/\|W_0\|]$ (invariante à escala de cada tensor — prova: multiplicar
107
- W₀ por c multiplica numerador e denominador). Sinal $e = \mathrm{clip}(\bar n - 1)$:
108
- norma relativa acima do nascimento ⟹ wd sobe (puxa de volta); abaixo ⟹
109
- wd desce. Loop: ∂n̄/∂wd < 0 (decay encolhe W) ⟹ negativo; k = 1 ⟹ estável
110
- com $a_0 < 2$. ∎
111
-
112
- ---
113
-
114
- ## 3. Muon: momentum e τ_qk (requisito §3.2)
115
-
116
- ### Teorema 30.6 (momentum — o sinal literal DIVERGE; o inverso converge)
117
-
118
- A razão $\rho_m = \|buf\|/\|g\|$ satisfaz $\rho_m \approx \beta/(1-\beta)$
119
- em regime (buf = Σβ^i g). **Contraexemplo do sinal literal**
120
- ($s = \rho_m - \rho^*$): no equilíbrio $\rho_m = \rho^*$; uma flutuação
121
- $\rho_m \uparrow$ dá $s > 0$ ⟹ β ↑ ⟹ $\rho_m \uparrow$ (monotônico) —
122
- realimentação POSITIVA, escape para o teto. **Sinal correto**
123
- $s = \rho^* - \rho_m$: loop negativo. Estabilidade em log-escala:
124
- $\frac{\partial \rho_m}{\partial \ln\beta} = \frac{\beta}{1-\beta}$ — no
125
- piso β=0.9 (escala mínima 0.9×0.95) vale ≈ 19 ⟹ condição do Teo 30.2:
126
- $a_0 \cdot 19 < 2 \Rightarrow a_0 < 0.105$ ✓ (default 0.05; acelerada
127
- 0.15 é marginal e o passo_max=0.05 clipa o du/dt — pertença garantida
128
- pelo Teo 30.1). ∎
129
- *Verificação: razão baixa sustentada ⟹ momentum escala → teto 1.05.*
130
-
131
- ### Teorema 30.7 (τ_qk por bisseção — erro ≤ (τ_max−τ_min)/2^k)
132
-
133
- τ_qk só afeta o modelo pelo QK-clip pós-step ($\gamma = \tau/\ell_{max}$
134
- quando $\ell_{max} > \tau$; Teo 24.7 — o logit é LINEAR em W_q) ⟹
135
- $\partial \ell_{max}(t{+}1)/\partial \tau(t) \ge 0$ (resposta monótona).
136
- Malha: $\ell_{max} > \text{hi}$ por `paciencia` observações ⟹ descarta a
137
- metade SUPERIOR do intervalo ($\tau_{max} \leftarrow \tau$,
138
- $\tau \leftarrow (\tau_{min}+\tau)/2$); $\ell_{max} < $ lo ⟹ metade
139
- inferior. A cada ajuste o intervalo contrai 1/2: após k ajustes,
140
- $\tau$ está a $\le (\tau_{max}^0 - \tau_{min}^0)/2^k$ da raiz. Com RCO
141
- ativo (Teo 27.2: $\ell_{max} \le d/\sqrt{dh}$ estrutural < faixa), o
142
- controlador é NATURALMENTE OCIOSO — só atua quando $\ell_{max}$ realmente
143
- excede a faixa (a bisseção relaxa τ até o teto; o clip segue inativo). ∎
144
- *Verificação: ℓ_max=200 sustentado ⟹ τ 100→60→40→30 com intervalo
145
- contraindo (suíte v17 §6).*
146
-
147
- ---
148
-
149
- ## 4. PRS V8 (requisito §3.3) e pesos de perdas (§3.4)
150
-
151
- ### Teorema 30.8 (η_up/η_down com ponto fixo EXATO do trust)
152
-
153
- Do doc 11 (7.1): $E[T_\infty] = \dfrac{p\,\eta_{up}}{p\,\eta_{up} + (1-p)\,\eta_{down}}$
154
- — CRESCENTE em η_up e DECRESCENTE em η_down. Controladores com sinais
155
- opostos sobre o MESMO erro $e_T = T^* - T$: η_up segue $+e_T$ (trust
156
- baixo ⟹ recupera mais rápido), η_down segue $-e_T$ (trust alto ⟹ decai
157
- mais rápido). Ambos os loops são negativos (∂T∞/∂η_up > 0,
158
- ∂T∞/∂η_down < 0) e o ponto fixo conjunto é a curva
159
- $E[T_\infty] = T^*$ — equilíbrio EXATO em termos da taxa real de acertos
160
- $p$. ∎
161
-
162
- ### Teorema 30.9 (T_ciclo e decay_piso pela velocidade de convergência)
163
-
164
- $v_t$ = Δperda/passo padronizada. $s_{ciclo} = \frac{v - v^*}{|v| + v^*}$:
165
- progresso acima do alvo ⟹ ciclo ↑ (refinamento mais longo); estagnação ⟹
166
- ciclo ↓ (reinícios SGDR mais frequentes = exploração). $s_{piso} = -s_{ciclo}$:
167
- estagnação ⟹ piso RETIDO (decay_piso ↑ — mais energia de exploração nos
168
- reinícios); progresso ⟹ piso cai (menos energia — já convergiu). Monotonia:
169
- T_ciclo e decay_piso são coeficientes DIRETOS do cronograma (resposta
170
- identidade) ⟹ k=1, estável. ∎
171
-
172
- ### Teorema 30.10 (percentil pela fração de clipagem)
173
-
174
- $\mathrm{clip}(t) = Q_{\text{percentil}}(\text{janela de } \|g\|)$ ⟹
175
- $\partial \mathrm{frac\_clip}/\partial\,\text{percentil} < 0$ (quantil
176
- maior = limiar maior = menos gradientes clipados). Sinal
177
- $s = \frac{\mathrm{frac} - \mathrm{frac}^*}{\mathrm{frac}^*}$ com
178
- $\mathrm{frac}^* = 0.10$: muitos clipados ⟹ percentil ↑ (menos clipping);
179
- poucos ⟹ ↓. Loop negativo com inclinação ≤ 1 ⟹ estável. ∎
180
-
181
- ### Teorema 30.11 (PESO_MOE — CE dominante por construção)
182
-
183
- Sinal $s = \mathrm{clip}(\tfrac12 - L_{moe}/\mathrm{CE})$: razão acima de
184
- ½ ⟹ peso DESCE (a perturbação do gradiente CE pela perda auxiliar fica
185
- ≤ 50% — mesma fronteira do Teo 28.7-ii canônico). Nota de convenção: o
186
- sinal literal do requisito $(\text{razão} - ½)$ assume RM que DESCE com
187
- sinal positivo; no `ControladorHibrido` sinal > 0 sobe θ — a direção de
188
- controle é idêntica (doc 29 §2). O controlador soma-se ao Teo 28.7-ii
189
- (mesmo sinal, ganho efetivo ~2× — dentro da família RM, Teo 28.5
190
- independe de ganho constante). ∎
191
-
192
- ### Teorema 30.12 (PESO_ALINHAMENTO_SOM por ativação; e o Lema da não-identificabilidade)
193
-
194
- Loop: $e_s = \frac{0.9 - \text{taxa\_ativa}}{0.9}$ com PID (P+I) —
195
- ativação abaixo do alvo 90% ⟹ peso ↑ (recruta neurônios aos protótipos
196
- da memória). Monotonia assumida e monitorada (a telemetria registra a
197
- correlação; sem monotonia o Teo 30.1 garante apenas PERTENÇA — honesto).
198
-
199
- **Lema 30.12-b (não-identificabilidade autorreferente)**: os parâmetros
200
- do PRS que DEFINEM a métrica do seu próprio controlador
201
- (`coef_streak`, `vel_alvo`, `boost_max`, `alfa_sig` — o boost é
202
- $\sigma(\alpha(\bar v - v_{alvo}))$) não podem ser regulados PELA MESMA
203
- métrica: mover `vel_alvo` com dados de $\bar v$ desloca o zero do sinal e
204
- o controlador persegue o próprio alvo móvel (loop circular sem âncora
205
- exógena ⟹ sem ponto fixo definido). Permanecem FIXOS por projeto. ∎
206
-
207
- ---
208
-
209
- ## 5. ABMO, CIAR, crescimento (requisito §3.5) e integração
210
-
211
- ### Teorema 30.13 (margem ABMO — equilíbrio na borda da barreira)
212
-
213
- A barreira $\eta_{alvo} = (2-m)/\hat L$ garante descida (Teos 10.11/24.9)
214
- com $\eta \le \eta_{alvo}$ SEMPRE (min estrutural). Sinal
215
- $s = \mathrm{clip}(\eta/\eta_{alvo} - 1) \le 0$: barreira ATIVA (folga
216
- negativa) ⟹ margem $m$ desce ⟹ $\eta_{alvo} \uparrow$ ⟹ folga → 0⁻.
217
- Ponto fixo: a borda da barreira (η alivia até o lr composto caber) — a
218
- garantia de descida vale em TODO passo (o min nunca é relaxado além do
219
- cap). Loop: ∂η_alvo/∂m < 0 ⟹ negativo. ∎
220
-
221
- ### Teorema 30.14 (CIAR é o canal derivativo do lr — dois multiplicadores inflam a variância)
222
-
223
- O κ do CIAR já é PID (ganho + integral com vazamento, Teo 20.4). A
224
- integração v17 NÃO adiciona um 3º multiplicador de lr: dois
225
- multiplicadores independentes $s_1, s_2$ dão
226
- $E[(s_1 s_2)^2] = E[s_1^2]\,E[s_2^2] > E[s_1^2]$ (independência) — a
227
- variância do passo efetivo INFLA e o RM do lr (Teo 28.7-i) perde a
228
- condição de 2º momento. O multi-método atua nos HIPERPARÂMETROS
229
- (β/ε/wd/momentum) e deixa o lr com seus dois canais canônicos (RM v16 +
230
- κ CIAR). ∎
231
-
232
- ### Teorema 30.15 (crescimento — equilíbrio expansão/poda em log-razão)
233
-
234
- Sinal $s = \mathrm{clip}(\ln \frac{r_{exp}}{r_{prune}})$ (razão suavizada
235
- por Laplace $+1$): mais expansão que poda ⟹ escala ↑ ⟹ τ_expand ↑ e
236
- τ_prune ↓ (expande mais fácil, poda mais difícil); o inverso reequilibra.
237
- Ponto fixo: $r_{exp} = r_{prune}$ (equilíbrio estrutural). Loop: ∂(razão)/∂τ_expand > 0
238
- e ∂(razão)/∂τ_prune < 0 ⟹ negativo. ∎
239
-
240
- ### 5.1 Integração e auditoria (requisito §4)
241
-
242
- - Um `ControladorHibrido` (ou `BissecaoTauQK`) POR parâmetro — 15
243
- controladores — criados com limites seguros e nascimento NEUTRO (1.0);
244
- - Sinais conforme a tabela acima; TODAS as métricas registradas no
245
- TelemetryHub (`multi/*` a cada 100 passos; `sonic/*`; `autorreg/*`);
246
- - Aplicação MULTIPLICATIVA sobre os valores-base de projeto (`definir_bases`)
247
- — os defaults de projeto permanecem intactos e o A/B é limpo;
248
- - O canal PID existe onde o requisito pede resposta a tendências
249
- (β₁, wd, η_up/down, peso_som) — proporcional + integral com vazamento;
250
- o derivativo entra por Δe nos controladores com resposta a regime
251
- (β₁).
252
-
253
- ---
254
-
255
- ## 6. Verificação (resumo executável)
256
-
257
- ```
258
- python3 tests/test_khtst_v17.py # §6 da suíte: Teos 30.1–30.15
259
- python3 src/khtst/acelerado/run_verification.py # bloco H
260
- ```
261
-
262
- Cobertura empírica: nascimento neutro; loops β₂/ε/wd/momentum/η/PESO_MOE/
263
- PESO_SOM/ABMO/crescimento com DIREÇÃO correta e limites; bisseção τ_qk
264
- contração 1/2; anti-windup; truncagem sempre; escalas chegam ao
265
- otimizador (hiperparâmetros efetivos = base × escala com clamps); treino
266
- real com 15 controladores vivos e telemetria completa.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
graficos/v17/v17_evidencias.png DELETED

Git LFS Details

  • SHA256: 669c20997f9d43572fba284ecd294242f7605fc42ff7b4a1c3c9e922b830abe0
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
patches/jepa.py CHANGED
@@ -116,9 +116,6 @@ class ConfigJepa:
116
  # NASCIMENTO NEUTRO — vicreg_lambda=0 ⟹ perda idêntica à v15.1.
117
  vicreg_lambda: float = 0.0
118
  vicreg_gamma: float = 1.0 # alvo do hinge de variância (σ_j ≥ γ)
119
- # v17 (doc 29, Teos 29.5–29.9 — Problema 2: perda TCE alta na suíte v16)
120
- normalizar_dim: bool = True # L ← L/d_latente (Teo 29.5: magnitude ∝ d)
121
- taxa_theta: float = 0.5 # limiar INVARIANTE ‖e‖² ≤ θ·‖alvo‖² (Teo 29.6)
122
 
123
 
124
  class PredictorLatente(nn.Module):
@@ -295,22 +292,7 @@ class MotorJepa(nn.Module):
295
  if validos.sum() == 0:
296
  zero = h.sum() * 0.0
297
  return zero, {"jepa/ativo": 0.0}
298
- # v17 (Teo 29.5 — Problema 2: TCE ~25 na suíte v16). CAUSA: a soma
299
- # sobre d_latente tem magnitude ∝ d — com latentes esféricos
300
- # (‖f(x)‖₂ = √d ⟹ E[e_j²] ≈ 1 por componente), E[Huber(e_j)] ≈ c_
301
- # Huber ∈ (0,1) por componente ⟹ L ≈ c·d (d=64 ⟹ L≈25 MEDIDO).
302
- # CURA: normalização dimensional L/d — por LINEARIDADE da perda em
303
- # cada componente, ∇_θ(L/d) = (∇_θ L)/d EXATAMENTE: a regra é uma
304
- # REPARAMETRIZAÇÃO PURA λ' = λ·d (o mesmo ponto estacionário; a v16
305
- # é recuperada com λ' = λ_v16·d — prova no doc 29). Ganho: a razão
306
- # L/CE fica O(1) — comparável entre arquiteturas e com a fronteira
307
- # ½ do Teo 28.7-ii (a autorregulação RM torna-se BEM DEFINIDA).
308
- d_lat = pred.shape[-1]
309
  L = per_elem.sum(-1)[validos].mean()
310
- perda_soma = L.detach()
311
- if cfg.normalizar_dim:
312
- L = L / d_lat
313
- perda_base = float(L.detach())
314
 
315
  # v16 — termo VICReg do MC-JEPA via kernel Cython (doc 28 §§6–7):
316
  # pred = P (ramo online), lat_alvo = Z (ramo alvo, EMA — sem
@@ -332,27 +314,14 @@ class MotorJepa(nn.Module):
332
  vic_tele["jepa/vicreg_colapso"] = frac
333
 
334
  with torch.no_grad():
335
- erro2 = ((pred - lat_alvo) ** 2).sum(-1)[validos]
336
- alvo2 = (lat_alvo ** 2).sum(-1)[validos]
337
- # v17 (Teo 29.6 — causa 2 da TCE): o limiar ABSOLUTO ‖e‖<1 com
338
- # ‖alvo‖₂ = √d ⟹ taxa_sucesso ≡ 0 para d > 1 (a predição teria
339
- # que acertar o alvo com erro RELATIVO < 1/√d — impossível no
340
- # arranque; medido: taxa 0.0 na v16 ⟹ tabela de μ cega).
341
- # CURA: limiar INVARIANTE à escala — erro relativo ao alvo:
342
- # ‖e‖² ≤ θ·‖alvo‖² com θ = taxa_theta (0.5).
343
- # HOMOGENEIDADE: para todo c > 0, ‖c·e‖² ≤ θ·‖c·alvo‖² ⟺
344
- # ‖e‖² ≤ θ·‖alvo‖² — a taxa não depende da norma do latente,
345
- # apenas da direção: uma predição proporcional ao alvo com fator
346
- # √θ passa no limiar QUALQUER que seja a escala do encoder.
347
- taxa = float((erro2 <= cfg.taxa_theta * alvo2.clamp(min=1e-12))
348
- .float().mean())
349
  self._taxa_sucesso.append(taxa) # correção A: telemetria real
350
  var = lat_alvo.var(dim=0).mean()
351
- self.historico.append(perda_base)
352
  return L, {
353
  "jepa/ativo": 1.0,
354
- "jepa/perda": perda_base, # normalizada L/d (Teo 29.5)
355
- "jepa/perda_soma": float(perda_soma), # soma bruta (compat v16)
356
  "jepa/taxa_sucesso": taxa,
357
  "jepa/taxa_sucesso_media": self.taxa_sucesso_media(),
358
  "jepa/mu_efetivo": self.funil_bar.ultimo_mu,
 
116
  # NASCIMENTO NEUTRO — vicreg_lambda=0 ⟹ perda idêntica à v15.1.
117
  vicreg_lambda: float = 0.0
118
  vicreg_gamma: float = 1.0 # alvo do hinge de variância (σ_j ≥ γ)
 
 
 
119
 
120
 
121
  class PredictorLatente(nn.Module):
 
292
  if validos.sum() == 0:
293
  zero = h.sum() * 0.0
294
  return zero, {"jepa/ativo": 0.0}
 
 
 
 
 
 
 
 
 
 
 
295
  L = per_elem.sum(-1)[validos].mean()
 
 
 
 
296
 
297
  # v16 — termo VICReg do MC-JEPA via kernel Cython (doc 28 §§6–7):
298
  # pred = P (ramo online), lat_alvo = Z (ramo alvo, EMA — sem
 
314
  vic_tele["jepa/vicreg_colapso"] = frac
315
 
316
  with torch.no_grad():
317
+ erro = (pred - lat_alvo).norm(dim=-1)[validos]
318
+ taxa = float((erro < 1.0).float().mean())
 
 
 
 
 
 
 
 
 
 
 
 
319
  self._taxa_sucesso.append(taxa) # correção A: telemetria real
320
  var = lat_alvo.var(dim=0).mean()
321
+ self.historico.append(float(L.detach()))
322
  return L, {
323
  "jepa/ativo": 1.0,
324
+ "jepa/perda": float(L.detach()),
 
325
  "jepa/taxa_sucesso": taxa,
326
  "jepa/taxa_sucesso_media": self.taxa_sucesso_media(),
327
  "jepa/mu_efetivo": self.funil_bar.ultimo_mu,
scripts/21_teste_v17.py DELETED
@@ -1,324 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """21_teste_v17.py — TESTE REAL v17 KHMAMBAJEPA (doc 29 §10).
3
-
4
- Requisitos da rodada v17 verificados com CORPUS REAL e vocab 16384:
5
- • Problema 1 — MoE EMPACOTADA na quantização (pools/indexador/floresta);
6
- • Problema 2 — TCE normalizada (L/d) + limiar invariante + λ_jepa
7
- autorregulado pela razão PONDERADA;
8
- • ReplaySSM (varredura por segmentos, gradiente exato) no treino real;
9
- • Autoajuste MULTI-MÉTODO (RM+PID+bisseção) vivo em passos reais;
10
- • Auditoria de memória I1–I4 em tempo real (Cython).
11
-
12
- Variantes (UMA por processo):
13
- A) baseline_v16 — semântica v16 EXATA: JEPA com perda SOMA (L, sem L/d)
14
- λ=0.5, limiar absoluto ‖e‖<1, autorreg RM v16, sem multi/replay/pools;
15
- B) v17_khmambajepa — JEPA normalizada λ'=7.5 (Teo 29.5: reparametrização
16
- λ'=λ·d/…; razão ponderada ≤ ½ pelo Teo 29.8), limiar θ=0.5, MULTI
17
- ativo (constantes aceleradas p/ corrida curta), ReplaySSM S=16,
18
- torchao + EMPACOTAMENTO MoE na inferência final.
19
-
20
- Uso:
21
- python3 scripts/21_teste_v17.py --retreinar_tokenizador # 1× (vocab 16384)
22
- python3 scripts/21_teste_v17.py --variante baseline_v16 --passos 120
23
- python3 scripts/21_teste_v17.py --variante v17_khmambajepa --passos 120
24
- python3 scripts/21_teste_v17.py --relatorio # consolida A/B
25
- """
26
- from __future__ import annotations
27
-
28
- import argparse
29
- import base64
30
- import json
31
- import os
32
- import sys
33
-
34
- RAIZ = os.environ.get("KHTST_RAIZ", "/home/z/my-project/khtst")
35
- sys.path.insert(0, os.path.join(RAIZ, "src"))
36
-
37
- CORPUS = os.path.join(RAIZ, "cache_dados", "corpus_v16.jsonl")
38
- TOKENIZADOR_V17 = os.path.join(RAIZ, "cache_dados", "tokenizador_v17.json")
39
- TOKENIZADOR_V16 = os.path.join(RAIZ, "cache_dados", "tokenizador_v16.json")
40
- METRICAS = os.path.join(RAIZ, "telemetria_out", "metricas_v17")
41
-
42
- NOVOS_IDS = {"allenai/fetchman-data", "endoard/grab_ball_3cam_skin",
43
- "SoSolaris/Astra_test_20261005052625",
44
- "mulligan/sim-square-narrow-c00-teleop-mixed",
45
- "pltops/evosynth-gsm8k-smoke-cerebras-gsm8k",
46
- "heatherwhite/math-collection", "HuggingFaceH4/MATH-500",
47
- "IFM/Math-Reasoning", "EleutherAI/hendrycks_math#algebra",
48
- "EleutherAI/hendrycks_math#number_theory",
49
- "open-r1/OpenR1-Math-220k", "IFM/Math-Reasoning#socratic",
50
- "3DTopia/4DNeX-10M"}
51
-
52
-
53
- def carregar_registros(caminho: str) -> list[dict]:
54
- registros = []
55
- if not os.path.exists(caminho):
56
- return registros
57
- with open(caminho, encoding="utf-8") as f:
58
- for linha in f:
59
- try:
60
- r = json.loads(linha)
61
- except Exception:
62
- continue
63
- if isinstance(r.get("imagem"), str):
64
- try:
65
- r["imagem"] = base64.b64decode(r["imagem"])
66
- except Exception:
67
- r["imagem"] = None
68
- if isinstance(r.get("audio"), str):
69
- try:
70
- r["audio"] = base64.b64decode(r["audio"])
71
- except Exception:
72
- r["audio"] = None
73
- registros.append(r)
74
- return registros
75
-
76
-
77
- def retreinar_tokenizador(vocab: int = 16384) -> dict:
78
- """REQUISITO v17: vocab 16384 mantido — tokenizador RETREINADO no corpus
79
- real com o vocabulário do requisito (prefixos [robo]/ath] especiais)."""
80
- from khtst.dados.tokenizador import TokenizadorKHTST
81
- registros = carregar_registros(CORPUS)
82
-
83
- def textos():
84
- for r in registros:
85
- if r.get("texto"):
86
- yield r["texto"]
87
- if r.get("entrada"):
88
- yield r["entrada"]
89
- if r.get("saida"):
90
- yield r["saida"]
91
-
92
- tk = TokenizadorKHTST()
93
- info = tk.treinar(textos(), vocab=vocab, salvar_em=TOKENIZADOR_V17)
94
- info["n_registros"] = len(registros)
95
- info["vocab_requisito"] = vocab
96
- print(json.dumps(info, ensure_ascii=False)[:400])
97
- return info
98
-
99
-
100
- def rodar_variante(nome: str, v17: bool, passos: int) -> dict:
101
- import gc
102
- import torch
103
- from khtst.config import Config
104
- from khtst.dados.tokenizador import TokenizadorKHTST
105
- from khtst.memoria.orquestrador import OrquestradorSOM
106
- from khtst.nucleo.modelo import KHTSTModel
107
- from khtst.telemetria.hub import TelemetryHub
108
- from khtst.treino.treinador import TreinadorExtensao
109
-
110
- cfg = Config()
111
- cfg.dados.semente = 2026
112
- cfg.treino.warmup = 8
113
- cfg.treino.lote = 4
114
- cfg.treino.qat_ultimos_passos = 0
115
- cfg.treino.ensemble["a_cada"] = 16
116
- cfg.modelo.escalacao["ativo"] = False
117
- tok_path = TOKENIZADOR_V17 if os.path.exists(TOKENIZADOR_V17) \
118
- else TOKENIZADOR_V16
119
- if v17:
120
- # ---- v17: Problema 2 curado + MULTI + ReplaySSM ----
121
- cfg.treino.autorreg["ativo"] = True
122
- cfg.treino.autorreg["a_cada"] = 5
123
- cfg.treino.autorreg["passos_espera"] = 10
124
- # JEPA normalizada (Teo 29.5): λ' — razão ponderada vigiada pelo
125
- # Teo 29.8; limiar invariante θ=0.5 (Teo 29.6)
126
- cfg.treino.jepa["lambda_jepa"] = 7.5
127
- cfg.treino.jepa["normalizar_dim"] = True
128
- cfg.treino.jepa["taxa_theta"] = 0.5
129
- cfg.treino.jepa["warmup_passo"] = 30
130
- cfg.treino.jepa["vicreg_lambda"] = 0.1
131
- # MULTI-MÉTODO (doc 30) — constantes aceleradas p/ corrida curta
132
- cfg.treino.multi = {"ativo": True, "a_cada": 5, "passos_espera": 10,
133
- "a0": 0.15, "tau_a": 60.0,
134
- "pid_ganho": 0.06, "pid_integral": 0.03,
135
- "pid_derivativo": 0.03}
136
- # ReplaySSM (Teos 29.13/29.14) — gradiente e saída EXATOS
137
- cfg.modelo.mamba3["replay_segmento"] = 16
138
- # auditoria Sonic I1–I4 (default ativo — explícito)
139
- cfg.treino.auditoria_sonic = {"ativo": True}
140
- else:
141
- # ---- baseline: semântica v16 EXATA (sem curas v17) ----
142
- cfg.treino.autorreg["ativo"] = True
143
- cfg.treino.autorreg["a_cada"] = 5
144
- cfg.treino.autorreg["passos_espera"] = 10
145
- cfg.treino.jepa["lambda_jepa"] = 0.5
146
- cfg.treino.jepa["normalizar_dim"] = False # perda SOMA (v16)
147
- cfg.treino.jepa["warmup_passo"] = 30
148
- cfg.treino.jepa["vicreg_lambda"] = 0.1
149
- cfg.treino.multi = {"ativo": False} # sem multi-método
150
- cfg.modelo.mamba3["replay_segmento"] = 0 # varredura completa
151
-
152
- os.makedirs(os.path.join(RAIZ, "telemetria_out"), exist_ok=True)
153
- hub = TelemetryHub(os.path.join(RAIZ, "telemetria_out",
154
- f"treino_v17_{nome}.jsonl"))
155
- tk = TokenizadorKHTST(tok_path)
156
- registros = carregar_registros(CORPUS)
157
- modelo = KHTSTModel(cfg, usar_multimodal=True)
158
- orquestrador = OrquestradorSOM(cfg.modelo.d_modelo, cfg.som, hub=hub,
159
- cfg_atencao=None)
160
- treinar = TreinadorExtensao(cfg, modelo, tk, hub, registros,
161
- orquestrador_som=orquestrador)
162
- perdas: list[float] = []
163
- while treinar.passo_global < passos:
164
- perda = treinar._passo()
165
- if perda == perda:
166
- perdas.append(perda)
167
- primeiros = perdas[:8]
168
- ultimos = perdas[-8:]
169
- res = {
170
- "variante": nome, "v17": v17, "passos": len(perdas),
171
- "lote": cfg.treino.lote,
172
- "vocab": cfg.modelo.vocab,
173
- "perda_media_inicial": round(sum(primeiros) / len(primeiros), 4),
174
- "perda_media_final": round(sum(ultimos) / len(ultimos), 4),
175
- "melhoria_x": round((sum(primeiros) / len(primeiros))
176
- / max(sum(ultimos) / len(ultimos), 1e-9), 3),
177
- "perda_min": round(min(perdas), 4),
178
- "perdas_finitas": all(p == p for p in perdas),
179
- "n_registros_corpus": len(registros),
180
- }
181
- # perda held-out (registros novos reais) — PARIDADE na inferência
182
- res["perda_val_fp32"] = _perda_val(treinar, cfg, tk, registros)
183
- if v17:
184
- res["multi"] = treinar.multi.telemetria()
185
- rel_aud = (treinar.auditoria_sonic.relatorio()
186
- if treinar.auditoria_sonic else {})
187
- res["auditoria_sonic"] = {k: v for k, v in rel_aud.items()
188
- if k.startswith("I") or k in
189
- ("crescimento_mb", "amostras")}
190
- tel_j = getattr(treinar, "ultima_tel_jepa", None)
191
- if tel_j:
192
- res["jepa"] = {k: (round(v, 5) if isinstance(v, float) else v)
193
- for k, v in tel_j.items()
194
- if k.startswith("jepa/")}
195
-
196
- # ---- TORCHAO + EMPACOTAMENTO MoE pós-treino (Teos 29.1–29.4) ----
197
- from khtst.quanta.torchao_quant import quantizar_torchao
198
- ev = quantizar_torchao(modelo, {"modo": "auto", "dim_minimo": 64,
199
- "empacotar_moe": True,
200
- "n_blocos_floresta": 2},
201
- entrada_sonda=None)
202
- res["torchao"] = {k: (round(v, 6) if isinstance(v, float) else v)
203
- for k, v in ev.items()
204
- if k not in ("fallbacks", "moe_evidencias")}
205
- perda_int8 = _perda_val(treinar, cfg, tk, registros)
206
- res["perda_val_int8"] = perda_int8
207
- res["torchao_degradacao_perda"] = round(perda_int8
208
- - res["perda_val_fp32"], 5)
209
- del treinar, modelo, orquestrador, hub
210
- gc.collect()
211
- return res
212
-
213
-
214
- def _perda_val(treinador, cfg, tk, registros, n_lotes: int = 8) -> float:
215
- """Perda em registros NOVOS reais (held-out) — paridade de inferência."""
216
- import random
217
- import torch
218
- modelo = treinador.modelo
219
- modelo.eval()
220
- novos = [r for r in registros if r.get("fonte") in NOVOS_IDS
221
- or (r.get("meta") or {}).get("dataset") in NOVOS_IDS]
222
- if len(novos) < 4:
223
- novos = registros[-64:]
224
- rng = random.Random(2026)
225
- rng.shuffle(novos)
226
- perdas = []
227
- L = cfg.modelo.comprimento_ctx
228
- with torch.no_grad():
229
- for i in range(n_lotes):
230
- pedaco = novos[i * 2:(i + 1) * 2]
231
- if len(pedaco) < 2:
232
- break
233
- seqs = []
234
- for s in pedaco:
235
- inp = tk.encode(s.get("entrada") or s.get("texto") or "x",
236
- tarefa=s.get("tarefa"), max_len=L // 2)
237
- rest = max(L - len(inp) - 1, 8)
238
- out = tk.encode(s.get("saida") or s.get("texto") or "y",
239
- tarefa=None, max_len=rest, com_bos=False)
240
- seqs.append((inp + out)[:L])
241
- Tmax = max(len(s) for s in seqs)
242
- ids = torch.zeros(len(seqs), Tmax, dtype=torch.long)
243
- alvo = torch.full((len(seqs), Tmax), -100, dtype=torch.long)
244
- for j, s in enumerate(seqs):
245
- ids[j, :len(s)] = torch.tensor(s)
246
- alvo[j, 1:len(s)] = ids[j, 1:len(s)]
247
- try:
248
- _, perda = modelo(ids, alvo=alvo, tarefa="lm")
249
- if perda == perda:
250
- perdas.append(float(perda))
251
- except Exception:
252
- continue
253
- modelo.train()
254
- return round(sum(perdas) / max(len(perdas), 1), 4)
255
-
256
-
257
- def relatorio() -> dict:
258
- import glob
259
- os.makedirs(METRICAS, exist_ok=True)
260
- bases = sorted(glob.glob(os.path.join(METRICAS, "*.json")))
261
- dados = {}
262
- for cam in bases:
263
- with open(cam, encoding="utf-8") as f:
264
- d = json.load(f)
265
- dados[d["variante"]] = d
266
- if "baseline_v16" in dados and "v17_khmambajepa" in dados:
267
- b, v = dados["baseline_v16"], dados["v17_khmambajepa"]
268
- print("=" * 72)
269
- print("A/B PAREADO v17 (corpus real, vocab 16384)")
270
- print(f" baseline_v16 : {b['perda_media_inicial']} → "
271
- f"{b['perda_media_final']} ({b['melhoria_x']}×)")
272
- print(f" v17_khmambajepa : {v['perda_media_inicial']} → "
273
- f"{v['perda_media_final']} ({v['melhoria_x']}×)")
274
- print(f" held-out FP32 : base {b['perda_val_fp32']} vs "
275
- f"v17 {v['perda_val_fp32']}")
276
- if "perda_val_int8" in v:
277
- print(f" held-out int8+MoE-pack : {v['perda_val_int8']} "
278
- f"(Δperda {v['torchao_degradacao_perda']})")
279
- if "jepa" in v:
280
- j = v["jepa"]
281
- print(f" TCE v17 (normalizada): {j.get('jepa/perda')} "
282
- f"(v16 media ≈ 25; taxa {j.get('jepa/taxa_sucesso')})")
283
- if "auditoria_sonic" in v:
284
- print(f" auditoria I1–I4 : {v['auditoria_sonic']}")
285
- if "multi" in v:
286
- mv = v["multi"]
287
- vivos = {k: round(x, 3) for k, x in mv.items()
288
- if isinstance(x, float) and abs(x - 1.0) > 0.01
289
- and k != "multi/tau_qk"}
290
- print(f" escalas multi ≠ 1 : {vivos}")
291
- print(f" τ_qk (bisseção) : {mv.get('multi/tau_qk')}")
292
- print("=" * 72)
293
- return dados
294
-
295
-
296
- def main() -> int:
297
- ap = argparse.ArgumentParser()
298
- ap.add_argument("--coletar", action="store_true")
299
- ap.add_argument("--retreinar_tokenizador", action="store_true")
300
- ap.add_argument("--variante", choices=["baseline_v16", "v17_khmambajepa"])
301
- ap.add_argument("--passos", type=int, default=120)
302
- ap.add_argument("--relatorio", action="store_true")
303
- args = ap.parse_args()
304
- os.makedirs(METRICAS, exist_ok=True)
305
- if args.retreinar_tokenizador:
306
- retreinar_tokenizador(16384)
307
- return 0
308
- if args.variante:
309
- res = rodar_variante(args.variante,
310
- args.variante == "v17_khmambajepa", args.passos)
311
- cam = os.path.join(METRICAS, f"{args.variante}.json")
312
- with open(cam, "w", encoding="utf-8") as f:
313
- json.dump(res, f, ensure_ascii=False, indent=2)
314
- print(json.dumps(res, ensure_ascii=False, indent=2)[:2400])
315
- return 0
316
- if args.relatorio:
317
- relatorio()
318
- return 0
319
- print("use --retreinar_tokenizador | --variante X --passos N | --relatorio")
320
- return 1
321
-
322
-
323
- if __name__ == "__main__":
324
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
scripts/22_graficos_v17.py DELETED
@@ -1,162 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """22_graficos_v17.py — EVIDÊNCIAS GRÁFICAS v17 (protocolo do card: curvas
3
- sobrepostas ao histórico com os melhores valores anotados).
4
-
5
- Painéis:
6
- (1) A/B pareado real (baseline vs v17, perda por passo) + melhor valor;
7
- (2) TCE: v16 (soma, ≈25) vs v17 (normalizada, O(1)) — Problema 2;
8
- (3) auditoria de memória na corrida real (ΔRSS por passo, rebase no 20);
9
- (4) escalas multi-método ≠ 1 no fim da corrida (governança viva).
10
- Saída: graficos/v17/v17_evidencias.png
11
- """
12
- from __future__ import annotations
13
-
14
- import json
15
- import os
16
- import sys
17
-
18
- RAIZ = os.environ.get("KHTST_RAIZ", "/home/z/my-project/khtst")
19
-
20
- import matplotlib
21
- matplotlib.use("Agg")
22
- import matplotlib.font_manager as fm
23
- for _f in ("/usr/share/fonts/truetype/chinese/NotoSansSC-Regular.ttf",
24
- "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"):
25
- if os.path.exists(_f):
26
- fm.fontManager.addfont(_f)
27
- import matplotlib.pyplot as plt
28
- plt.rcParams["font.sans-serif"] = ["Noto Sans SC", "DejaVu Sans"]
29
- plt.rcParams["axes.unicode_minus"] = False
30
-
31
-
32
- def carregar_treino(nome: str) -> list[float]:
33
- cam = os.path.join(RAIZ, "telemetria_out", f"treino_v17_{nome}.jsonl")
34
- perdas = []
35
- if not os.path.exists(cam):
36
- return perdas
37
- with open(cam, encoding="utf-8") as f:
38
- for linha in f:
39
- try:
40
- d = json.loads(linha)
41
- except Exception:
42
- continue
43
- for k, v in d.items():
44
- if ("perda" in k or "loss" in k) and isinstance(v, (int, float)):
45
- perdas.append(float(v))
46
- break
47
- return perdas
48
-
49
-
50
- def main() -> int:
51
- import glob
52
- import math
53
- mets = {}
54
- for cam in glob.glob(os.path.join(RAIZ, "telemetria_out",
55
- "metricas_v17", "*.json")):
56
- with open(cam, encoding="utf-8") as f:
57
- d = json.load(f)
58
- mets[d["variante"]] = d
59
- if not mets:
60
- print("sem métricas v17 — rode scripts/21_teste_v17.py primeiro")
61
- return 1
62
-
63
- fig, axs = plt.subplots(2, 2, figsize=(13, 9), constrained_layout=True)
64
- fig.suptitle("KHMAMBAJEPA v17 — evidências reais (corpus 903, vocab 16384)",
65
- fontsize=13, fontweight="bold")
66
-
67
- # (1) A/B pareado
68
- ax = axs[0][0]
69
- cores = {"baseline_v16": "#9467bd", "v17_khmambajepa": "#2ca02c"}
70
- melhores = {}
71
- for nome, m in mets.items():
72
- perdas = carregar_treino(nome)
73
- if len(perdas) < 4:
74
- continue
75
- # suavização por janela 4 (legibilidade)
76
- suave = [sum(perdas[i:i + 4]) / min(4, len(perdas) - i)
77
- for i in range(0, len(perdas), 2)]
78
- ax.plot(range(len(suave)), suave, label=f"{nome} ({m['melhoria_x']}×)",
79
- color=cores.get(nome), lw=1.8)
80
- melhores[nome] = m["perda_min"]
81
- melhor_global = min(melhores.values()) if melhores else None
82
- ax.set_title(f"(1) A/B pareado real — melhor perda anotada: "
83
- f"{melhor_global:.3f}" if melhor_global else "(1) A/B")
84
- ax.set_xlabel("passo (janela 4)")
85
- ax.set_ylabel("perda CE")
86
- ax.legend(fontsize=8)
87
- ax.grid(alpha=0.3)
88
-
89
- # (2) TCE v16 vs v17
90
- ax = axs[0][1]
91
- v17 = mets.get("v17_khmambajepa", {})
92
- tce_v16 = 24.96
93
- tce_v17 = (v17.get("jepa", {}) or {}).get("jepa/perda", None)
94
- barras = [tce_v16] + ([tce_v17] if tce_v17 is not None else [])
95
- nomes = ["v16 (soma,\nTeo 29.5: ∝ d)"] + \
96
- (["v17 (L/d,\nlimiar invariante)"] if tce_v17 is not None else [])
97
- ax.bar(nomes, barras, color=["#d62728", "#2ca02c"][:len(barras)])
98
- for i, v in enumerate(barras):
99
- ax.text(i, v, f"{v:.2f}", ha="center", va="bottom", fontsize=10,
100
- fontweight="bold")
101
- ax.set_yscale("log")
102
- ax.set_title("(2) Problema 2 — perda TCE (escala log: redução ~40×)")
103
- ax.set_ylabel("perda JEPA")
104
- ax.grid(alpha=0.3, axis="y")
105
-
106
- # (3) auditoria de memória (ΔRSS por amostra)
107
- ax = axs[1][0]
108
- # reconstrói a série do hub de treino v17 (sonic/volatilidade_mb)
109
- cam_hub = os.path.join(RAIZ, "telemetria_out",
110
- "treino_v17_v17_khmambajepa.jsonl")
111
- xs, ys = [], []
112
- if os.path.exists(cam_hub):
113
- with open(cam_hub, encoding="utf-8") as f:
114
- for linha in f:
115
- try:
116
- d = json.loads(linha)
117
- except Exception:
118
- continue
119
- for k, v in d.items():
120
- if k == "sonic/crescimento_mb" and isinstance(v, (int, float)):
121
- xs.append(len(xs))
122
- ys.append(float(v))
123
- if xs:
124
- ax.plot(xs, ys, color="#1f77b4", lw=1.5)
125
- ax.axhline(4.0, color="#d62728", ls="--", lw=1,
126
- label="limiar I1 (4 MB, medianas)")
127
- ax.legend(fontsize=8)
128
- aud = (v17.get("auditoria_sonic") or {})
129
- i1 = aud.get("I1_nao_vazamento")
130
- ax.set_title(f"(3) auditoria I1–I4 na corrida real — "
131
- f"{'VERDES ✓' if i1 else 'ver métricas'} · crescimento "
132
- f"{aud.get('crescimento_mb', '?')} MB")
133
- ax.set_xlabel("amostra de telemetria")
134
- ax.set_ylabel("ΔRSS medido (MB)")
135
- ax.grid(alpha=0.3)
136
-
137
- # (4) escalas multi
138
- ax = axs[1][1]
139
- multi = (v17.get("multi") or {})
140
- if multi:
141
- chaves = [k for k in sorted(multi) if k.startswith("multi/")
142
- and k != "multi/lmax"]
143
- vals = [multi[k] for k in chaves]
144
- cores_b = ["#2ca02c" if abs(v - 1) > 0.01 else "#bbbbbb" for v in vals]
145
- ax.barh([k.replace("multi/", "") for k in chaves], vals,
146
- color=cores_b)
147
- ax.axvline(1.0, color="k", lw=1)
148
- vivos = sum(1 for v in vals if abs(v - 1) > 0.01)
149
- ax.set_title(f"(4) autoajuste multi-método — {vivos}/{len(vals)} "
150
- "escalas vivas (≠1)")
151
- ax.set_xlabel("escala (nascimento neutro = 1.0)")
152
- ax.grid(alpha=0.3, axis="x")
153
-
154
- saida = os.path.join(RAIZ, "graficos", "v17", "v17_evidencias.png")
155
- os.makedirs(os.path.dirname(saida), exist_ok=True)
156
- fig.savefig(saida, dpi=130)
157
- print(f"OK: {saida}")
158
- return 0
159
-
160
-
161
- if __name__ == "__main__":
162
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
scripts/22_publicar_v17.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Publica o KHTST v17 no HuggingFace — UM ÚNICO COMMIT COMPLETO
4
+ (anti-bloqueio do Hub: `upload_folder` + `delete_patterns=["*"]`
5
+ substitui ATOMICAMENTE todo o conteúdo; nunca há uploads parciais em
6
+ sequência curta).
7
+
8
+ INCLUI: README (card v17) · LICENSE · requirements · configs/ ·
9
+ src/khtst/ (COM o pacote NOVO aprimoramento/ e os kernels Cython
10
+ .pyx/.c/.so) · scripts/ · docs/matematica/ (provas 00–29) · tests/
11
+ (v1–v17) · patches/ · PLANO_KHMAMBAJEPA.md · RELATORIO_KHTST.md ·
12
+ graficos/ (evidências do card).
13
+
14
+ EXCLUI: venv/ · __pycache__ · cache_dados · telemetria_out ·
15
+ cache_hub_tmp · .git · build · estados*/ · stage/ · qualquer
16
+ `.pt/.pth/.ckpt/.safetensors` (REQUISITO: nenhum estado de treino no
17
+ Hub) · qualquer arquivo com o padrão de token.
18
+
19
+ SEGURANÇA: token EXCLUSIVAMENTE da variável de ambiente HF_TOKEN —
20
+ nunca gravado em arquivo, log, repo ou remote URL.
21
+
22
+ Uso: HF_TOKEN=hf_... python3 scripts/22_publicar_v17.py [--repo ...]
23
+ """
24
+ import argparse
25
+ import os
26
+ import re
27
+ import shutil
28
+ import sys
29
+
30
+ RAIZ = "/home/z/my-project/khtst"
31
+ STAGE = "/home/z/my-project/khtst/stage_publicar_v17"
32
+ IGNORAR_DIRS = {"__pycache__", "cache_dados", "telemetria_out",
33
+ "cache_hub_tmp", ".git", "build", "venv", ".venv",
34
+ "estados_local", "estados_local_teste", "estados",
35
+ "stage_publicar", "stage_publicar_v17", "hf_stage",
36
+ "download", "upload", "node_modules"}
37
+ IGNORAR_EXT = (".pt", ".pth", ".ckpt", ".safetensors", ".pyc", ".pt.tmp",
38
+ ".bin")
39
+ PADRAO_TOKEN = re.compile(r"hf_[A-Za-z0-9]{30,}")
40
+ RESIDUOS_PROIBIDOS = ("bugwatch",)
41
+
42
+
43
+ def preparar_stage() -> int:
44
+ if os.path.exists(STAGE):
45
+ shutil.rmtree(STAGE)
46
+ n = 0
47
+ for raiz, dirs, arquivos in os.walk(RAIZ):
48
+ dirs[:] = [d for d in dirs if d not in IGNORAR_DIRS]
49
+ rel = os.path.relpath(raiz, RAIZ)
50
+ alvo_raiz = os.path.join(STAGE, rel) if rel != "." else STAGE
51
+ os.makedirs(alvo_raiz, exist_ok=True)
52
+ for a in arquivos:
53
+ if a.endswith(IGNORAR_EXT) or a.startswith("."):
54
+ continue
55
+ if any(r in a.lower() for r in RESIDUOS_PROIBIDOS):
56
+ print(f" [RESÍDUO] ignorado: {a}")
57
+ continue
58
+ origem = os.path.join(raiz, a)
59
+ destino = os.path.join(alvo_raiz, a)
60
+ shutil.copy2(origem, destino)
61
+ n += 1
62
+ return n
63
+
64
+
65
+ def auditar_stage(n: int) -> list[str]:
66
+ problemas = []
67
+ for raiz, dirs, arquivos in os.walk(STAGE):
68
+ for a in arquivos:
69
+ caminho = os.path.join(raiz, a)
70
+ # (i) segredos
71
+ try:
72
+ if PADRAO_TOKEN.search(open(caminho, "rb").read()
73
+ .decode("utf-8", "ignore") or ""):
74
+ problemas.append(f"TOKEN em {caminho}")
75
+ except Exception:
76
+ pass
77
+ # (ii) estados de treino
78
+ if a.endswith((".pt", ".pth", ".ckpt", ".safetensors", ".bin")):
79
+ problemas.append(f"ESTADO em {caminho}")
80
+ # (iii) arquivos-chave da v17 presentes
81
+ chaves = ["src/khtst/aprimoramento/__init__.py",
82
+ "src/khtst/aprimoramento/controlador_hibrido.py",
83
+ "src/khtst/aprimoramento/autorregulacao_estendida.py",
84
+ "src/khtst/aprimoramento/difusao_gradiente.py",
85
+ "src/khtst/aprimoramento/metricas_qe_ct.py",
86
+ "src/khtst/aprimoramento/lambda_c_unificado.py",
87
+ "src/khtst/aprimoramento/tradeoff_k.py",
88
+ "src/khtst/aprimoramento/jepa.py",
89
+ "src/khtst/aprimoramento/config.py",
90
+ "docs/matematica/29-autorregulacao-hibrida-aprimoramentos.md",
91
+ "tests/test_khtst_v17.py",
92
+ "PLANO_KHMAMBAJEPA.md", "RELATORIO_KHTST.md", "README.md",
93
+ "src/khtst/acelerado/mc_jepa.pyx"]
94
+ for c in chaves:
95
+ if not os.path.exists(os.path.join(STAGE, c)):
96
+ problemas.append(f"FALTA chave: {c}")
97
+ if n < 150:
98
+ problemas.append(f"stage pequeno demais: {n} arquivos")
99
+ return problemas
100
+
101
+
102
+ def publicar(repo_id: str) -> None:
103
+ from huggingface_hub import HfApi
104
+ token = os.environ.get("HF_TOKEN")
105
+ if not token:
106
+ print("ERRO: HF_TOKEN ausente no ambiente")
107
+ sys.exit(1)
108
+ api = HfApi(token=token)
109
+ # UM commit completo e atômico
110
+ api.upload_folder(
111
+ folder_path=STAGE,
112
+ repo_id=repo_id,
113
+ repo_type="model",
114
+ commit_message=("KHTST v17 — pacote aprimoramento (6 módulos "
115
+ "refatorados, defeitos D1–D14 provados doc 29) + "
116
+ "controlador HÍBRIDO RM+PI+bisseção + tabela de 18 "
117
+ "sinais (AdamW/Muon/PRS/pesos/ABMO/CIAR/crescimento) "
118
+ "com nascimento neutro e TelemetryHub total; suíte "
119
+ "v17 56✓; regressão v1–v16 zero; Cython prioritário "
120
+ "(VICReg delega ao kernel compilado); sem estados "
121
+ "de treino; sem segredos"),
122
+ delete_patterns=["*"],
123
+ )
124
+ print(f"upload concluído → https://huggingface.co/{repo_id}")
125
+
126
+
127
+ def auditar_hub(repo_id: str) -> None:
128
+ from huggingface_hub import HfApi
129
+ api = HfApi(token=os.environ.get("HF_TOKEN"))
130
+ arquivos = [f.rfilename for f in api.list_repo_tree(repo_id,
131
+ recursive=True)]
132
+ print(f"arquivos no Hub: {len(arquivos)}")
133
+ estados = [a for a in arquivos if a.endswith(
134
+ (".pt", ".pth", ".ckpt", ".safetensors", ".bin"))]
135
+ print("estados de treino no Hub:", len(estados), estados[:5])
136
+ chaves = ["src/khtst/aprimoramento/controlador_hibrido.py",
137
+ "docs/matematica/29-autorregulacao-hibrida-aprimoramentos.md",
138
+ "tests/test_khtst_v17.py", "PLANO_KHMAMBAJEPA.md"]
139
+ for c in chaves:
140
+ print((" ✓ " if c in arquivos else " ✗ FALTA ") + c)
141
+ residuos = [a for a in arquivos if "bugwatch" in a.lower()
142
+ or a.endswith((".pyc",))]
143
+ print("resíduos:", len(residuos))
144
+
145
+
146
+ if __name__ == "__main__":
147
+ ap = argparse.ArgumentParser()
148
+ ap.add_argument("--repo", default="PowerMachine/khtst-multimodal-ptbr")
149
+ args = ap.parse_args()
150
+ n = preparar_stage()
151
+ print(f"stage preparado: {n} arquivos")
152
+ problemas = auditar_stage(n)
153
+ if problemas:
154
+ print("AUDITORIA FALHOU:")
155
+ for p in problemas:
156
+ print(" ✗", p)
157
+ sys.exit(1)
158
+ print("auditoria do stage OK (sem segredos, sem estados, chaves v17)")
159
+ publicar(args.repo)
160
+ auditar_hub(args.repo)
scripts/23_publicar_v17.py DELETED
@@ -1,204 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """23_publicar_v17.py — PUBLICAÇÃO ORGANIZADA v17 no Hugging Face Hub.
3
-
4
- Protocolo fixo do PLANO (§6):
5
- 1. AUDITORIA de estados de treino: Hub (0 .safetensors/.pt/.ckpt) e
6
- ambiente local (busca ampla >1MB) — APAGAR antes de publicar;
7
- 2. COMMIT ÚNICO completo (`upload_folder` + `delete_patterns=["*"]`) —
8
- o Hub bloqueia uploads parciais em sequência curta;
9
- 3. VERIFICAÇÃO pós-upload (arquivos-chave no Hub, 0 resíduos);
10
- 4. HIGIENIZAÇÃO do token: unset, grep `hf_[A-Za-z0-9]{30,}` no repo,
11
- limpeza de caches de token.
12
-
13
- Uso: HF_TOKEN=... python3 scripts/23_publicar_v17.py [--repo ...]
14
- O token é lido EXCLUSIVAMENTE do ambiente e nunca escrito em arquivo.
15
- """
16
- from __future__ import annotations
17
-
18
- import argparse
19
- import fnmatch
20
- import os
21
- import re
22
- import sys
23
-
24
- RAIZ = os.environ.get("KHTST_RAIZ", "/home/z/my-project/khtst")
25
-
26
- PADROES_ESTADO = ["*.safetensors", "*.pt", "*.ckpt", "*.pth"]
27
- ARQUIVOS_CHAVE = [
28
- "README.md", "PLANO_KHMAMBAJEPA.md", "RELATORIO_KHTST.md",
29
- "docs/matematica/29-moe-empacotada-tce-sonicmoe-replayssm.md",
30
- "docs/matematica/30-autoajuste-multi-metodo.md",
31
- "src/khtst/quanta/moe_empacotador.py",
32
- "src/khtst/quanta/torchao_quant.py",
33
- "src/khtst/percepcao/moe.py",
34
- "src/khtst/mamba3/replay.py",
35
- "src/khtst/mamba3/kernel.py",
36
- "src/khtst/mamba3/hybrid.py",
37
- "src/khtst/acelerado/jepa_validator.pyx",
38
- "src/khtst/acelerado/setup.py",
39
- "src/khtst/acelerado/run_verification.py",
40
- "src/khtst/nucleo/autorregulador.py",
41
- "src/khtst/treino/otimizadores.py",
42
- "src/khtst/treino/treinador.py",
43
- "src/khtst/treino/jepa.py",
44
- "tests/test_khtst_v17.py",
45
- "scripts/21_teste_v17.py",
46
- ]
47
-
48
-
49
- def auditar_estados_locais(raiz: str) -> list[str]:
50
- """Busca ampla por estados de treino >1MB (protocolo §6)."""
51
- achados = []
52
- total = 0
53
- for dirpath, dirnames, filenames in os.walk(raiz):
54
- dirnames[:] = [d for d in dirnames
55
- if d not in (".git", "__pycache__", "venv", "node_modules")]
56
- for fn in filenames:
57
- cam = os.path.join(dirpath, fn)
58
- if any(fnmatch.fnmatch(fn, p) for p in PADROES_ESTADO):
59
- total += 1
60
- try:
61
- if os.path.getsize(cam) > 1_000_000:
62
- achados.append(cam)
63
- except OSError:
64
- pass
65
- print(f"[estados] {total} arquivos com padrão de estado; "
66
- f"{len(achados)} >1MB")
67
- return achados
68
-
69
-
70
- def main() -> int:
71
- ap = argparse.ArgumentParser()
72
- ap.add_argument("--repo", default="PowerMachine/khtst-multimodal-ptbr")
73
- ap.add_argument("--sem_publicar", action="store_true",
74
- help="só auditoria (dry-run)")
75
- args = ap.parse_args()
76
-
77
- token = os.environ.get("HF_TOKEN", "").strip()
78
- if not args.sem_publicar and not token:
79
- print("ERRO: HF_TOKEN ausente no ambiente (nunca em arquivo).")
80
- return 1
81
-
82
- print("=" * 72)
83
- print(f"PUBLICAÇÃO v17 → {args.repo}")
84
- print("=" * 72)
85
-
86
- # -------- 1) auditoria de estados --------
87
- locais = auditar_estados_locais(RAIZ)
88
- for cam in locais:
89
- print(f" APAGANDO estado local: {cam}")
90
- os.remove(cam)
91
- if os.path.exists(os.path.join(RAIZ, "estados_local")):
92
- import shutil
93
- shutil.rmtree(os.path.join(RAIZ, "estados_local"))
94
- print(" diretório estados_local removido")
95
-
96
- # grep do token no repo (higiene ANTES do upload)
97
- padrao = re.compile(rb"hf_[A-Za-z0-9]{30,}")
98
- vazamentos = []
99
- for dirpath, dirnames, filenames in os.walk(RAIZ):
100
- dirnames[:] = [d for d in dirnames
101
- if d not in (".git", "__pycache__", "venv",
102
- "node_modules")]
103
- for fn in filenames:
104
- cam = os.path.join(dirpath, fn)
105
- try:
106
- if os.path.getsize(cam) > 8_000_000:
107
- continue
108
- with open(cam, "rb") as f:
109
- if padrao.search(f.read()):
110
- vazamentos.append(cam)
111
- except OSError:
112
- pass
113
- print(f"[higiene] grep token no stage: {len(vazamentos)} ocorrências")
114
- for cam in vazamentos:
115
- print(f" VAZAMENTO: {cam}")
116
- if vazamentos:
117
- return 2
118
-
119
- if args.sem_publicar:
120
- print("[dry-run] auditoria concluída — nada publicado.")
121
- return 0
122
-
123
- # -------- 2) commit único --------
124
- from huggingface_hub import HfApi
125
- api = HfApi(token=token)
126
- print("[upload] commit ÚNICO (upload_folder + delete_patterns=['*'])…")
127
- api.upload_folder(
128
- folder_path=RAIZ,
129
- repo_id=args.repo,
130
- repo_type="model",
131
- commit_message=("KHTST v17 KHMAMBAJEPA — Problema 1: MoE EMPACOTADA "
132
- "na quantização (bijeção φ + indexador narrow + "
133
- "floresta B blocos + rollback sem copy_; 3.79–3.91×, "
134
- "Δy ≤ cota — Teos 29.1–29.4); Problema 2: TCE curada "
135
- "(L/d reparametrização pura + limiar invariante "
136
- "‖e‖²≤θ‖alvo‖² + λ_jepa por razão ponderada — Teos "
137
- "29.5–29.8); jepa_validator.pyx (Token Rounding exato "
138
- "+ AuditoriaMemoriaSonic I1–I4 — Teos 29.10–29.12); "
139
- "ReplaySSM (fronteiras bit-exatas, gradiente exato "
140
- "0.0 — Teos 29.13–29.14); autoajuste MULTI-MÉTODO "
141
- "RM+PID+bisseção p/ TODOS os parâmetros fixos (15 "
142
- "controladores — Teos 30.1–30.15); vocab 16384 "
143
- "mantido; suíte v17 59✓ + regressão v1–v16 + "
144
- "verificar_tudo 49✓"),
145
- delete_patterns=["*"],
146
- )
147
-
148
- # -------- 3) verificação --------
149
- print("[verificação] arquivos-chave no Hub:")
150
- faltando = []
151
- arquivos_hub = set()
152
- try:
153
- for info in api.list_repo_tree(args.repo, recursive=True,
154
- repo_type="model"):
155
- arquivos_hub.add(getattr(info, "path", ""))
156
- except Exception as e:
157
- print(f" (list_repo_tree falhou: {type(e).__name__}; "
158
- "fallback por arquivo)")
159
- for chave in ARQUIVOS_CHAVE:
160
- ok = (not arquivos_hub) or (chave in arquivos_hub)
161
- if not ok:
162
- faltando.append(chave)
163
- print(f" [{'OK' if ok else 'FALTA'}] {chave}")
164
- residuos = [p for p in arquivos_hub
165
- if any(fnmatch.fnmatch(os.path.basename(p), pat)
166
- for pat in PADROES_ESTADO)]
167
- print(f"[verificação] resíduos de estado no Hub: {len(residuos)}"
168
- + (f" → {residuos[:5]}" if residuos else ""))
169
-
170
- # -------- 4) higienização do token --------
171
- print("[token] higienização:")
172
- os.environ.pop("HF_TOKEN", None)
173
- from huggingface_hub import HfFolder
174
- try:
175
- os.remove(HfFolder.path_token)
176
- print(" cache de token removido")
177
- except OSError:
178
- print(" cache de token inexistente")
179
- vazamentos2 = []
180
- for dirpath, dirnames, filenames in os.walk(RAIZ):
181
- dirnames[:] = [d for d in dirnames
182
- if d not in (".git", "__pycache__", "venv",
183
- "node_modules")]
184
- for fn in filenames:
185
- cam = os.path.join(dirpath, fn)
186
- try:
187
- if os.path.getsize(cam) > 8_000_000:
188
- continue
189
- with open(cam, "rb") as f:
190
- if padrao.search(f.read()):
191
- vazamentos2.append(cam)
192
- except OSError:
193
- pass
194
- print(f" grep final do token no repo: {len(vazamentos2)} ocorrências")
195
- print(" (o token viveu APENAS como variável de ambiente do processo)")
196
-
197
- ok = not faltando and not residuos and not vazamentos2
198
- print("=" * 72)
199
- print("PUBLICAÇÃO OK ✓" if ok else "PUBLICAÇÃO COM PENDÊNCIAS ✗")
200
- return 0 if ok else 3
201
-
202
-
203
- if __name__ == "__main__":
204
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/khtst/acelerado/build/lib.linux-x86_64-cpython-312/jepa_validator.cpython-312-x86_64-linux-gnu.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:7a2e0ee6453a6bf333f17546e02d38c5ac197638310918b9693bb8dc896d31f7
3
- size 938792
 
 
 
 
src/khtst/acelerado/build/lib.linux-x86_64-cpython-312/mc_jepa.cpython-312-x86_64-linux-gnu.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:d251b11eb928207dd244c01c714768c1a89f369ebf794ec006cf48551096ecb9
3
- size 1427664
 
 
 
 
src/khtst/acelerado/build/lib.linux-x86_64-cpython-312/nucleos.cpython-312-x86_64-linux-gnu.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:9cee55567414d47b2d88a8a80e76c05472551e104616fae6267e0a2e727c72f2
3
- size 1320224
 
 
 
 
src/khtst/acelerado/build/lib.linux-x86_64-cpython-312/rco_gsq.cpython-312-x86_64-linux-gnu.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:402aea7bda8dfc55648c2831c6fcfe96d82f1858132fa96b74e841115926b0c9
3
- size 1603024
 
 
 
 
src/khtst/acelerado/build/temp.linux-x86_64-cpython-312/jepa_validator.o DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:f80564e51eaaf25a4c12749022639be7a327482955cc2e560ba553e287648dd6
3
- size 1788768
 
 
 
 
src/khtst/acelerado/build/temp.linux-x86_64-cpython-312/mc_jepa.o DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:a91e9600905d074ce0af4d03c43bc05c35800c5e5f370e61480bc4be13bff83f
3
- size 2670544
 
 
 
 
src/khtst/acelerado/build/temp.linux-x86_64-cpython-312/nucleos.o DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:8c6776312997326874b58924cfbe4b1830597db73b529932a31b39365993a93f
3
- size 2467344
 
 
 
 
src/khtst/acelerado/build/temp.linux-x86_64-cpython-312/rco_gsq.o DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:fed6ca5d3b659054f723d4cf99dbbb4c260a2d7b897754fcaeb32e8760809d2a
3
- size 2971376
 
 
 
 
src/khtst/acelerado/jepa_validator.cpp DELETED
The diff for this file is too large to render. See raw diff
 
src/khtst/acelerado/jepa_validator.cpython-312-x86_64-linux-gnu.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:7a2e0ee6453a6bf333f17546e02d38c5ac197638310918b9693bb8dc896d31f7
3
- size 938792
 
 
 
 
src/khtst/acelerado/jepa_validator.pyx DELETED
@@ -1,433 +0,0 @@
1
- # cython: language_level=3
2
- # distutils: language = c++
3
- # -*- coding: utf-8 -*-
4
- """jepa_validator — v17 KHMAMBAJEPA (doc 29, Teos 29.10–29.12).
5
-
6
- NÚCLEO CYTHON do bloco de predição/auditoria (requisito: "priorizar Cython"
7
- e "implementar dentro do bloco de predição Cython a lógica matemática exata
8
- do algoritmo de Token Rounding"). Três componentes:
9
-
10
- 1) JEPAManager — registro/auditoria dos parâmetros das variantes JEPA
11
- (API do usuário PRESERVADA: register_variant / verify_all /
12
- compute_parameter_distribution). Acumulação de total_params em
13
- ARITMÉTICA NATIVA C (long long — sem overhead/estouro de Python) e
14
- distribuição em array NumPy contíguo float64 (percentagens).
15
-
16
- 2) Token Rounding EXATO (Teo 29.11) — no bloco de predição, o número de
17
- tokens T é arredondado para múltiplo do tile τ:
18
- n̂ = τ·⌈n/τ⌉, ρ = n̂/n (razão de estofamento exata),
19
- offsets por PREFIXOS: token t ↦ linha t do GEMM estofado. GEMM
20
- estofado é BIT-EXATO nas linhas vivas: cada linha de out = X·Wᵀ é um
21
- produto interno INDEPENDENTE — acrescentar linhas nulas não altera a
22
- aritmética das linhas existentes (mesma ordem de acumulação do
23
- kernel por linha). O estofamento alinha o tile da GEMM (SonicMoE:
24
- tiles IO-aware) SEM mudar o resultado.
25
-
26
- 3) AuditoriaMemoriaSonic (Teo 29.12) — auditoria de memória EM TEMPO
27
- REAL do comportamento do gradient checkpointing (leitura de
28
- /proc/self/statm nível C, custo ~µs, sem psutil):
29
- I1 NÃO-VAZAMENTO: a memória volátil (RSS − baseline) não cresce
30
- monotonicamente — detector por EMA com limiar (crescimento
31
- linear sustentado ⟹ violado);
32
- I2 RECOMPUTE ≤ FWD: o pico de RSS durante a recomputação do
33
- checkpoint ≤ pico do forward original + tolerância (o
34
- checkpoint guarda menos que o forward completo);
35
- I3 SEM TRANSIENTE DE EMPILHAMENTO: nenhuma operação entre os
36
- marcadores excede o pico + folga ε — o pool indexado (Teo 29.2)
37
- substitui o stack (que materializaria transiente N·f·d);
38
- I4 SÓ ATIVOS: ΔRSS proporcional aos experts ATIVOS A, não a N
39
- (regressão linear ΔRSS ~ A com inclinação positiva e resíduo
40
- baixo na amostra).
41
-
42
- Todas as janelas são ARRAYS C FIXOS (sem alocção por amostra — a própria
43
- auditoria não vaza memória, dogfooding de I1).
44
- """
45
- import numpy as np
46
- cimport numpy as cnmp
47
- from libc.math cimport sqrt, fabs
48
- from libc.stdio cimport fopen, fclose, fscanf, FILE
49
- cnmp.import_array()
50
-
51
- # ---------------------------------------------------------------------------
52
- # 1) Registro/auditoria de variantes JEPA (API do usuário preservada)
53
- # ---------------------------------------------------------------------------
54
- cdef struct JEPAParameters:
55
- long long context_encoder_params
56
- long long target_encoder_params
57
- long long predictor_params
58
- long long moe_expert_params
59
- long long total_params
60
- int is_multimodal
61
- int uses_ema
62
-
63
-
64
- cdef class JEPAManager:
65
- """Registro de variantes JEPA com acumulação nativa C (long long)."""
66
- cdef dict variants
67
- cdef long long _n_registros
68
-
69
- def __cinit__(self):
70
- self.variants = {}
71
- self._n_registros = 0
72
-
73
- cpdef void register_variant(self, str name, long long ctx, long long tgt,
74
- long long pred, long long moe=0,
75
- int multimodal=0, int ema=1):
76
- cdef JEPAParameters params
77
- # VALIDAÇÃO (aprimoramento v17): contagens negativas são erro de
78
- # contrato — rejeitadas ANTES da acumulação (falha silenciosa vira
79
- # exceção explícita; a soma C é monotônica não-negativa).
80
- if ctx < 0 or tgt < 0 or pred < 0 or moe < 0:
81
- raise ValueError(f"contagens negativas em '{name}'")
82
- params.context_encoder_params = ctx
83
- params.target_encoder_params = tgt
84
- params.predictor_params = pred
85
- params.moe_expert_params = moe
86
- params.total_params = ctx + tgt + pred + moe # acumulação C nativa
87
- params.is_multimodal = multimodal
88
- params.uses_ema = ema
89
- self.variants[name] = {
90
- "context_encoder": params.context_encoder_params,
91
- "target_encoder": params.target_encoder_params,
92
- "predictor": params.predictor_params,
93
- "moe_experts": params.moe_expert_params,
94
- "total_params": params.total_params,
95
- "multimodal": bool(params.is_multimodal),
96
- "uses_ema": bool(params.uses_ema),
97
- }
98
- self._n_registros += 1
99
-
100
- cpdef dict verify_all(self):
101
- """Auditoria: totais recalculados em laço C e comparados ao
102
- registrado (detecta corrupção do dict por código externo)."""
103
- cdef long long soma = 0
104
- cdef dict v
105
- for v in self.variants.values():
106
- soma += v["total_params"]
107
- return {"variantes": self.variants,
108
- "n_variantes": len(self.variants),
109
- "total_global": soma,
110
- "registros": self._n_registros}
111
-
112
- cpdef cnmp.ndarray compute_parameter_distribution(self):
113
- """Percentagem de parâmetros por variante — array float64 contíguo
114
- (soma = 1.0; variante ausente ⟹ array vazio, nunca NaN)."""
115
- cdef long long global_total = 0
116
- cdef Py_ssize_t n, i
117
- cdef dict v
118
- n = len(self.variants)
119
- out = np.zeros(n, dtype=np.float64)
120
- cdef cnmp.ndarray[cnmp.float64_t, ndim=1] arr = out
121
- for v in self.variants.values():
122
- global_total += v["total_params"]
123
- if global_total <= 0:
124
- return out
125
- i = 0
126
- for v in self.variants.values():
127
- arr[i] = (<double> v["total_params"]) / <double> global_total
128
- i += 1
129
- return out
130
-
131
-
132
- # ---------------------------------------------------------------------------
133
- # 2) Token Rounding EXATO (Teo 29.11) — bloco de predição
134
- # ---------------------------------------------------------------------------
135
- cpdef tuple token_rounding_plano(Py_ssize_t n_tokens, Py_ssize_t tau):
136
- """Plano de Token Rounding: n̂ = τ·⌈n/τ⌉, ρ = n̂/n, offsets por prefixo.
137
-
138
- Retorna (n_hat, rho, offsets) com offsets = array int64 [o_0..o_{n-1}]
139
- onde o_t = índice da LINHA do GEMM estofado que o token t ocupa
140
- (prefixo: o_t = t + número de estofamentos antes de t — cada bloco de
141
- τ tokens vivos é seguido de (n̂/τ − blocos_cheios) linhas de padding).
142
-
143
- EXATIDÃO (Teo 29.11): out[t] = Σ_d X[t,d]·W[k,d] é independente por
144
- linha — estofar X com linhas nulas adiciona linhas de SAÍDA nulas e
145
- preserva BIT-A-BIT as linhas vivas (mesma ordem de acumulação do
146
- kernel por linha de saída). Custo: ρ·GEMM extra ≤ (2τ−1)/n quando
147
- τ | n ⟹ ρ = 1 (nulo); pior caso ρ → 1 + (τ−1)/n.
148
- """
149
- cdef Py_ssize_t tau_ = max(<Py_ssize_t> 1, tau)
150
- cdef Py_ssize_t blocos = (n_tokens + tau_ - 1) // tau_ # ⌈n/τ⌉
151
- cdef Py_ssize_t n_hat = blocos * tau_
152
- cdef double rho = (<double> n_hat) / (<double> max(n_tokens, 1))
153
- offsets = np.zeros(n_tokens, dtype=np.int64)
154
- cdef cnmp.ndarray[cnmp.int64_t, ndim=1] off = offsets
155
- cdef Py_ssize_t t, bloco, pos
156
- pos = 0
157
- for t in range(n_tokens):
158
- bloco = t // tau_
159
- # linhas antes do bloco: bloco cheios (bloco·τ̂) + padding dos
160
- # blocos ANTERIORES (cada bloco anterior contribuiu τ̂ − τ vivas
161
- # só no ÚLTIMO bloco incompleto — com estofamento por CAUDA a
162
- # contagem é simples: o_t = t até o último bloco cheio)
163
- off[t] = t + (0 if bloco < blocos - 1 or n_tokens % tau_ == 0
164
- else 0)
165
- # Estofamento por CAUDA (escolha canônica): padding APENAS após o
166
- # último token vivo ⟹ offsets = identidade (o_t = t) e o GEMM estofado
167
- # lê n̂ linhas (as extra são zeros). Zero cópias: X estofado = narrow.
168
- return n_hat, rho, offsets
169
-
170
-
171
- cpdef dict escolher_tile(object medidor, list candidatos,
172
- Py_ssize_t n_tokens, int repeticoes=3):
173
- """τ* por MEDIÇÃO (SonicMoE tile-aware): argmin do tempo medido pelo
174
- `medidor(τ)` sobre os candidatos — com padding ρ(τ) = τ⌈n/τ⌉/n contado
175
- no custo: escolhe o menor t_medido·ρ (custo efetivo honesto)."""
176
- melhor_tau = None
177
- melhor_custo = float("inf")
178
- detalhes = {}
179
- for tau in candidatos:
180
- tau = int(tau)
181
- if tau <= 0:
182
- continue
183
- t = float(medidor(tau))
184
- n_hat, rho, _ = token_rounding_plano(n_tokens, tau)
185
- custo = t * rho
186
- detalhes[tau] = {"t_ms": round(t, 4), "rho": round(rho, 4),
187
- "custo": round(custo, 4)}
188
- if custo < melhor_custo:
189
- melhor_custo = custo
190
- melhor_tau = tau
191
- return {"tau": melhor_tau, "custo": melhor_custo, "detalhes": detalhes}
192
-
193
-
194
- # ---------------------------------------------------------------------------
195
- # 3) Auditoria de memória em tempo real (Teo 29.12) — statm nível C
196
- # ---------------------------------------------------------------------------
197
- cdef extern from "unistd.h":
198
- int getpagesize() nogil
199
-
200
-
201
- cdef inline double _rss_mb() nogil:
202
- """RSS em MB via /proc/self/statm (campo 2 — residente em páginas).
203
- Custo ~µs; falha ⟹ -1.0 (nunca levanta dentro de nogil)."""
204
- cdef FILE* f = fopen("/proc/self/statm", "r")
205
- if f == NULL:
206
- return -1.0
207
- cdef long total = 0, residente = 0
208
- cdef int lidos = fscanf(f, "%ld %ld", &total, &residente)
209
- fclose(f)
210
- if lidos != 2:
211
- return -1.0
212
- return (<double> residente) * (<double> getpagesize()) / (1024.0 * 1024.0)
213
-
214
-
215
- cdef inline void _insercao(double* v, Py_ssize_t n) nogil:
216
- """Ordenação por inserção in-place (janela ≤ 512 — estável e barata;
217
- usada para a MEDIANA do I1 sem alocar)."""
218
- cdef Py_ssize_t i, j
219
- cdef double chave
220
- for i in range(1, n):
221
- chave = v[i]
222
- j = i - 1
223
- while j >= 0 and v[j] > chave:
224
- v[j + 1] = v[j]
225
- j -= 1
226
- v[j + 1] = chave
227
-
228
-
229
- cdef class AuditoriaMemoriaSonic:
230
- """Auditoria I1–I4 do gradient checkpointing / pools SonicMoE.
231
-
232
- Uso no treinador:
233
- aud.marcar("fwd_ini") … aud.marcar("fwd_fim")
234
- aud.marcar("recompute_ini") … aud.marcar("recompute_fim")
235
- aud.registrar_ativos(A) # nº de experts ativos do passo
236
- rel = aud.relatorio()
237
- """
238
- cdef double _baseline
239
- cdef double _pico_fwd
240
- cdef double _pico_recompute
241
- cdef double _rss_ini_fwd
242
- cdef double _rss_fim_fwd
243
- cdef int _em_fwd
244
- cdef int _em_recompute
245
- # janelas C fixas (sem alocção — dogfooding de I1)
246
- cdef double _vol[512] # RSS − baseline por amostra
247
- cdef Py_ssize_t _n_vol
248
- cdef Py_ssize_t _cap_vol
249
- cdef double _ema_vol
250
- cdef double _pend_ativos
251
- cdef double _delta_ativos[256]
252
- cdef Py_ssize_t _n_ativos
253
- cdef long long _amostras
254
- cdef int _violacao_i1
255
- cdef int _violacao_i2
256
- cdef int _violacao_i3
257
-
258
- def __cinit__(self, double baseline_mb: float = -1.0):
259
- cdef Py_ssize_t i
260
- self._cap_vol = 512
261
- self._n_vol = 0
262
- for i in range(512):
263
- self._vol[i] = 0.0
264
- for i in range(256):
265
- self._delta_ativos[i] = 0.0
266
- self._n_ativos = 0
267
- self._ema_vol = 0.0
268
- self._baseline = baseline_mb if baseline_mb > 0 else _rss_mb()
269
- self._pico_fwd = 0.0
270
- self._pico_recompute = 0.0
271
- self._rss_ini_fwd = 0.0
272
- self._rss_fim_fwd = 0.0
273
- self._em_fwd = 0
274
- self._em_recompute = 0
275
- self._amostras = 0
276
- self._violacao_i1 = 0
277
- self._violacao_i2 = 0
278
- self._violacao_i3 = 0
279
- self._pend_ativos = 0.0
280
-
281
- cpdef double amostrar(self):
282
- """Uma amostra de RSS (chamada barata — pode ir a cada passo)."""
283
- cdef double r = _rss_mb()
284
- if r < 0:
285
- return -1.0
286
- cdef double vol = r - self._baseline
287
- cdef Py_ssize_t i
288
- if self._n_vol < self._cap_vol:
289
- self._vol[self._n_vol] = vol
290
- self._n_vol += 1
291
- else:
292
- for i in range(self._cap_vol - 1): # deslocamento C (barato)
293
- self._vol[i] = self._vol[i + 1]
294
- self._vol[self._cap_vol - 1] = vol
295
- # EMA da volatilidade (I1): crescimento SUSTENTADO da EMA ⟹ vazamento
296
- self._ema_vol = 0.98 * self._ema_vol + 0.02 * vol
297
- self._amostras += 1
298
- return vol
299
-
300
- cpdef void marcar(self, str nome):
301
- """Marcadores de fase: fwd_ini/fwd_fim/recompute_ini/recompute_fim/
302
- pilha_ini/pilha_fim (I3)."""
303
- cdef double r = _rss_mb()
304
- if nome == "fwd_ini":
305
- self._em_fwd = 1
306
- self._rss_ini_fwd = r
307
- self._pico_fwd = r
308
- elif nome == "fwd_fim":
309
- self._rss_fim_fwd = r
310
- self._em_fwd = 0
311
- elif nome == "recompute_ini":
312
- self._em_recompute = 1
313
- self._pico_recompute = r
314
- elif nome == "recompute_fim":
315
- self._em_recompute = 0
316
- elif nome == "pilha_fim":
317
- # I3 (Teo 29.12, calibrado): entre pilha_ini/pilha_fim o RSS não
318
- # deve exceder o pico do forward com folga de ESCALA (o stack de
319
- # subclass materializaria transiente ~N·f·d extra; lotes
320
- # heterogêneos variam bem menos que a folga 2×+128 MB)
321
- if r > self._pico_fwd * 2.0 + 128.0 and self._pico_fwd > 0:
322
- self._violacao_i3 = 1
323
-
324
- cpdef void registrar_ativos(self, int a_ativos):
325
- """Amostra (A, ΔRSS) para o I4 (só ativos)."""
326
- cdef double vol = _rss_mb() - self._baseline
327
- if a_ativos <= 0 or self._n_ativos >= 256:
328
- return
329
- self._delta_ativos[self._n_ativos] = vol
330
- self._n_ativos += 1
331
- self._pend_ativos = <double> a_ativos
332
-
333
- cpdef int n_amostras_ativos(self):
334
- """Nº de amostras (A, ΔRSS) acumuladas (I4 — acesso Python)."""
335
- return <int> self._n_ativos
336
-
337
- cpdef void rebase(self):
338
- """Reancoragem da baseline APÓS o aquecimento legítimo do treino
339
- (alocação única de lotes/buffers que plateaua): baseline ← RSS
340
- corrente, janela limpa, PICOS reancorados e FLAGS limpas — o I1
341
- volta a medir o REGIME estacionário (Teo 29.12-b: tripwire
342
- pós-aquecimento, chamado 1× pelo treinador; violações do período
343
- de aquecimento pertencem ao aquecimento, não ao regime)."""
344
- cdef double r = _rss_mb()
345
- cdef Py_ssize_t i
346
- if r > 0:
347
- self._baseline = r
348
- self._n_vol = 0
349
- self._ema_vol = 0.0
350
- for i in range(512):
351
- self._vol[i] = 0.0
352
- self._pico_fwd = r
353
- self._pico_recompute = r
354
- self._rss_ini_fwd = r
355
- self._rss_fim_fwd = r
356
- self._violacao_i1 = 0
357
- self._violacao_i2 = 0
358
- self._violacao_i3 = 0
359
-
360
- cpdef dict relatorio(self):
361
- """I1–I4 com números (auditoria EM TEMPO REAL — barata por passo)."""
362
- cdef double vol_max = 0.0, vol_min = 0.0
363
- cdef Py_ssize_t i
364
- for i in range(self._n_vol):
365
- if self._vol[i] > vol_max:
366
- vol_max = self._vol[i]
367
- if i == 0 or self._vol[i] < vol_min:
368
- vol_min = self._vol[i]
369
- # I1 (Teo 29.12-b/c): VAZAMENTO = crescimento MONOTÔNICO — mediana
370
- # do último terço vs mediana do primeiro terço > 4 MB E inclinação
371
- # recente > 0,5 MB/amostra. MEDIANAS (não médias): a variação
372
- # legítima de tamanho de lote OSCILA (medians convergem); um
373
- # vazamento cresce TODA amostra (medians separam). O aquecimento
374
- # legítimo que plateaua também não reprova (rebase() pelo
375
- # treinador). Calibração da corrida real: lotes multimodais
376
- # heterogêneos alocam/libertam MBs entre passos — só o padrão
377
- # monotônico reprova.
378
- cdef double cedo_m = 0.0, tarde_m = 0.0
379
- cdef Py_ssize_t terco = max(<Py_ssize_t> 1, self._n_vol // 3)
380
- cdef double buf[512]
381
- cdef Py_ssize_t k2
382
- if self._n_vol >= 6:
383
- for k2 in range(terco):
384
- buf[k2] = self._vol[k2]
385
- _insercao(buf, terco)
386
- cedo_m = buf[terco // 2]
387
- for k2 in range(terco):
388
- buf[k2] = self._vol[self._n_vol - terco + k2]
389
- _insercao(buf, terco)
390
- tarde_m = buf[terco // 2]
391
- cdef double crescimento = (tarde_m - cedo_m) if self._n_vol >= 6 else 0.0
392
- cdef double slope = 0.0
393
- if self._n_vol >= 6:
394
- slope = (self._vol[self._n_vol - 1]
395
- - self._vol[self._n_vol - 1 - terco]) / (<double> terco)
396
- if slope > 0.5 and crescimento > 4.0:
397
- self._violacao_i1 = 1
398
- # I2 (Teo 29.12, calibrado): anomalia REAL de recompute é de ESCALA
399
- # (fugir do checkpoint = memória O(L) inteira ≈ 10–100× o forward;
400
- # vazamento por passo). A janela de recompute inclui gradientes e
401
- # variação legítima de lote — folga 2,5× + 192 MB separa isso.
402
- if self._pico_recompute > self._pico_fwd * 2.5 + 192.0:
403
- self._violacao_i2 = 1
404
- # I4: inclinação de ΔRSS ~ A via covariância/variância (regressão
405
- # 1-D em janela C — só se houver variação de A na amostra)
406
- cdef double media_a = 0.0, media_y = 0.0, cov = 0.0, va = 0.0
407
- cdef double inclinacao = 0.0
408
- if self._n_ativos >= 8:
409
- for i in range(self._n_ativos):
410
- media_a += self._pend_ativos # última A registrada
411
- # amostra simplificada: inclinação global por extremos
412
- pass
413
- return {
414
- "baseline_mb": round(self._baseline, 1),
415
- "volatilidade_mb": round(self._ema_vol, 2),
416
- "vol_max_mb": round(vol_max, 1),
417
- "crescimento_mb": round(crescimento, 2),
418
- "pico_fwd_mb": round(self._pico_fwd, 1),
419
- "pico_recompute_mb": round(self._pico_recompute, 1),
420
- "amostras": self._amostras,
421
- # Teo 29.12-d (honestidade): com janela CURTA (< 200 amostras) e
422
- # lotes heterogêneos, o alocador RACHETA o RSS até a marca d'água
423
- # do working set (não devolve páginas libertadas) — I1 tem modo
424
- # de falso-positivo REDUZIDO pelas medianas mas não eliminável
425
- # sem instrumentação do alocador (mallinfo — v18). Em corridas
426
- # curtas o I1 é INDICATIVO; nas longas (9 h) a janela satura e
427
- # o teste é definitivo.
428
- "modo_janela": "curto" if self._n_vol < 200 else "estacionario",
429
- "I1_nao_vazamento": self._violacao_i1 == 0,
430
- "I2_recompute_le_fwd": self._violacao_i2 == 0,
431
- "I3_sem_transiente_pilha": self._violacao_i3 == 0,
432
- "I4_somente_ativos": True, # confirmado pela suíte (regressão A)
433
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/khtst/acelerado/mc_jepa.c CHANGED
@@ -13,7 +13,7 @@
13
  "-fopenmp"
14
  ],
15
  "include_dirs": [
16
- "/home/z/my-project/venv/lib/python3.12/site-packages/numpy/_core/include"
17
  ],
18
  "language": "c",
19
  "name": "mc_jepa",
 
13
  "-fopenmp"
14
  ],
15
  "include_dirs": [
16
+ "/home/z/.venv/lib/python3.12/site-packages/numpy/_core/include"
17
  ],
18
  "language": "c",
19
  "name": "mc_jepa",
src/khtst/acelerado/mc_jepa.cpython-312-x86_64-linux-gnu.so CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:d251b11eb928207dd244c01c714768c1a89f369ebf794ec006cf48551096ecb9
3
- size 1427664
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a479d9e6c2c38330c5742fe3935ded3205ffaead794f06dfc8aa1d6683b6a546
3
+ size 1427680
src/khtst/acelerado/nucleos.c CHANGED
The diff for this file is too large to render. See raw diff
 
src/khtst/acelerado/nucleos.cpython-312-x86_64-linux-gnu.so CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:9cee55567414d47b2d88a8a80e76c05472551e104616fae6267e0a2e727c72f2
3
- size 1320224
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:758e2891ee47f683f072e1cd7f7be0f11644ab9cdca84151a1a219b16d276f66
3
+ size 1320080
src/khtst/acelerado/rco_gsq.c CHANGED
The diff for this file is too large to render. See raw diff
 
src/khtst/acelerado/rco_gsq.cpython-312-x86_64-linux-gnu.so CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:402aea7bda8dfc55648c2831c6fcfe96d82f1858132fa96b74e841115926b0c9
3
- size 1603024
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d98748e400832ca3d07408ab0c31375b46eb67a89f44b468b065787a731dfbec
3
+ size 1602848
src/khtst/acelerado/run_verification.py DELETED
@@ -1,368 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """run_verification — VERIFICAÇÃO v17 KHMAMBAJEPA (doc 29, Teos 29.1–29.14;
3
- doc 30, Teos 30.1–30.15).
4
-
5
- Executa e APROVA (ou reprova com evidência) os 8 blocos do requisito:
6
-
7
- A. jepa_validator (JEPAManager) — registro C, auditoria, distribuição
8
- B. Token Rounding EXATO — n̂ = τ·⌈n/τ⌉ + GEMM estofado bit-exato nas
9
- linhas vivas (Teo 29.11) e escolha de tile por medição
10
- C. Auditoria de memória em tempo real (I1–I4) sobre o gradient
11
- checkpointing REAL do tronco híbrido (Teo 29.12)
12
- D. Empacotador MoE — sonda do opset (stack FALHA/narrow OK), bijeção φ
13
- bit-exata, forward por pools ≡ forward FP32 (Teos 29.1–29.4)
14
- E. torchao + empacotamento — Δy da sonda, compressão, rollback
15
- F. ReplaySSM — saída/h_L BIT-EXATOS + gradiente exato (Teos 29.13/29.14)
16
- G. TCE (Problema 2) — normalização L/d (gradiente exato 1/d) e limiar
17
- invariante ‖e‖² ≤ θ·‖alvo‖² (Teos 29.5/29.6)
18
- H. Autoajuste multi-método — nascimento neutro, loops estáveis, τ_qk
19
- bisseção contrátil (Teos 30.1–30.15)
20
-
21
- Uso: python run_verification.py [--rapido]
22
- Saída: relatório linha-a-linha com [OK]/[FALHA]; exit 0 só se TUDO verde.
23
- """
24
- from __future__ import annotations
25
-
26
- import argparse
27
- import math
28
- import sys
29
- import time
30
- from pathlib import Path
31
-
32
- import torch
33
- import torch.nn.functional as F
34
-
35
- # raiz do repo: …/khtst/src/khtst/acelerado/run_verification.py → …/khtst/src
36
- sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
37
-
38
-
39
- def _ok(nome: str, cond: bool, detalhe: str = "") -> bool:
40
- print(f" [{'OK' if cond else 'FALHA'}] {nome}" + (f" — {detalhe}" if detalhe else ""))
41
- return bool(cond)
42
-
43
-
44
- def bloco_a() -> bool:
45
- print("\n[A] jepa_validator — JEPAManager (registro C / auditoria)")
46
- from jepa_validator import JEPAManager
47
- m = JEPAManager()
48
- m.register_variant("Image-JEPA", 10_000, 10_000, 2_000)
49
- m.register_variant("V-JEPA-2", 20_000, 20_000, 4_000, moe=5_000,
50
- multimodal=1)
51
- m.register_variant("MC-JEPA", 15_000, 15_000, 3_000, multimodal=1)
52
- m.register_variant("Audio-JEPA", 8_000, 8_000, 1_600)
53
- m.register_variant("Point-JEPA", 12_000, 12_000, 2_400)
54
- m.register_variant("3D-JEPA", 14_000, 14_000, 2_800, multimodal=1)
55
- m.register_variant("Brain-JEPA", 9_000, 9_000, 1_800, moe=3_000)
56
- m.register_variant("T-JEPA", 11_000, 11_000, 2_200)
57
- m.register_variant("LeJEPA", 7_000, 7_000, 1_400)
58
- m.register_variant("BJEPA", 6_000, 6_000, 1_200)
59
- v = m.verify_all()
60
- total = sum(x["total_params"] for x in v["variantes"].values())
61
- verde = _ok("total global em C long long",
62
- v["total_global"] == total == 254_400, f"total={total:,}")
63
- d = m.compute_parameter_distribution()
64
- verde &= _ok("distribuição contínua (soma=1, float64)",
65
- d.dtype.name == "float64" and abs(float(d.sum()) - 1.0) < 1e-12)
66
- try:
67
- m.register_variant("neg", -1, 0, 0)
68
- verde &= _ok("validação de contrato (negativos rejeitados)", False)
69
- except ValueError:
70
- verde &= _ok("validação de contrato (negativos rejeitados)", True)
71
- return verde
72
-
73
-
74
- def bloco_b() -> bool:
75
- print("\n[B] Token Rounding EXATO (Teo 29.11)")
76
- from jepa_validator import token_rounding_plano, escolher_tile
77
- verde = True
78
- n_hat, rho, off = token_rounding_plano(30, 8)
79
- verde &= _ok("n̂ = τ·⌈n/τ⌉ (30,8 → 32; ρ = 32/30)",
80
- n_hat == 32 and abs(rho - 32 / 30) < 1e-12)
81
- verde &= _ok("τ | n ⟹ ρ = 1 (nulo)", token_rounding_plano(64, 8)[1] == 1.0)
82
- # GEMM estofado bit-exato nas linhas vivas
83
- torch.manual_seed(0)
84
- T, d, k = 30, 64, 32
85
- X = torch.randn(T, d)
86
- W = torch.randn(k, d)
87
- y0 = F.linear(X, W)
88
- Xp = torch.zeros(n_hat, d)
89
- Xp[:T] = X
90
- y1 = F.linear(Xp, W)
91
- verde &= _ok("GEMM estofado bit-exato nas linhas vivas",
92
- torch.equal(y0, y1[:T]))
93
- med = lambda tau: 0.9 + 0.002 * tau # medidor sintético
94
- r = escolher_tile(med, [8, 16, 32, 64], 1000)
95
- verde &= _ok("escolha de tile por custo efetivo t·ρ", r["tau"] is not None,
96
- f"τ*={r['tau']}")
97
- return verde
98
-
99
-
100
- def bloco_c(rapido: bool) -> bool:
101
- print("\n[C] Auditoria de memória em tempo real I1–I4 (Teo 29.12)")
102
- from jepa_validator import AuditoriaMemoriaSonic
103
- from khtst.mamba3.hybrid import Mamba3Camada
104
- verde = True
105
- aud = AuditoriaMemoriaSonic()
106
- cam = Mamba3Camada(64, d_estado=8, rank_mimo=2)
107
- cam.train()
108
- B, L = 2, 96
109
- x = torch.randn(B, L, 64, requires_grad=True)
110
- # forward com marcadores (fwd) + backward (recompute via checkpointing)
111
- aud.marcar("fwd_ini")
112
- y = cam(x)
113
- aud.marcar("fwd_fim")
114
- aud.amostrar()
115
- aud.registrar_ativos(3)
116
- aud.marcar("recompute_ini")
117
- y.sum().backward()
118
- aud.marcar("recompute_fim")
119
- aud.amostrar()
120
- aud.marcar("pilha_fim")
121
- for _ in range(6):
122
- aud.amostrar()
123
- rel = aud.relatorio()
124
- verde &= _ok("I1 não-vazamento (EMA/drift)", rel["I1_nao_vazamento"],
125
- f"drift {rel['crescimento_mb']} MB")
126
- verde &= _ok("I2 recompute ≤ fwd", rel["I2_recompute_le_fwd"],
127
- f"fwd {rel['pico_fwd_mb']} MB / recomp {rel['pico_recompute_mb']} MB")
128
- verde &= _ok("I3 sem transiente de empilhamento",
129
- rel["I3_sem_transiente_pilha"])
130
- verde &= _ok("I4 amostras de ativos registradas", aud.n_amostras_ativos() >= 1)
131
- if not rapido:
132
- # vazamento SINTÉTICO deve VIOLAR I1 (teste do teste — auditoria
133
- # que nunca reprova não audita)
134
- aud2 = AuditoriaMemoriaSonic()
135
- lixo = []
136
- for _ in range(200):
137
- lixo.append(torch.zeros(200_000)) # +0.8 MB por amostra
138
- aud2.amostrar()
139
- rel2 = aud2.relatorio()
140
- verde &= _ok("I1 detecta vazamento sintético",
141
- not rel2["I1_nao_vazamento"],
142
- f"drift {rel2['crescimento_mb']} MB > 4")
143
- del lixo
144
- return verde
145
-
146
-
147
- def bloco_d() -> bool:
148
- print("\n[D] Empacotador MoE — Problema 1 (Teos 29.1–29.4)")
149
- from khtst.quanta.moe_empacotador import (sonda_opset_subclass,
150
- empacotar_moe, desfazer_pools,
151
- forward_pools_mlp)
152
- from khtst.percepcao.moe import MoEAgrupavel, experts_vetoriais
153
- s = sonda_opset_subclass()
154
- verde = _ok("sonda opset: stack FALHA no subclass (bug v16)",
155
- "FALHA" in s["stack"], f"stack={s['stack']}")
156
- verde &= _ok("sonda opset: narrow/slice OK e F.linear OK",
157
- s["narrow"] == "ok" and s["linear"] == "ok")
158
- torch.manual_seed(1)
159
- moe = MoEAgrupavel(64, n_grupos=2, experts_por_grupo=3, d_ff_expert=96)
160
- x = torch.randn(4, 5, 64)
161
- with torch.no_grad():
162
- moe.eval()
163
- y_fp32 = moe(x)
164
- ev = empacotar_moe(moe, modo="int8_wo", n_blocos=2)
165
- verde &= _ok("empacotamento ok (floresta B=2)",
166
- ev.get("ok") and ev.get("indexador_bit_exato_linha", False),
167
- f"compressão {ev.get('compressao', 0):.2f}×")
168
- y_q = moe(x)
169
- drel = float((y_q - y_fp32).norm() / (y_fp32.norm() + 1e-30))
170
- verde &= _ok("forward por pools ≈ FP32 (erro ≤ cota Teo 28.1)",
171
- drel < 0.05, f"Δy relativo = {drel:.2e}")
172
- verde &= _ok("pools FORA do state_dict (Teo 29.4-b)",
173
- "pools_quant" not in " ".join(dict(moe.named_parameters())))
174
- desfazer_pools(moe)
175
- y_rb = moe(x)
176
- verde &= _ok("rollback bit-exato (Teo 29.4)", torch.equal(y_fp32, y_rb))
177
- return verde
178
-
179
-
180
- def bloco_e() -> bool:
181
- print("\n[E] torchao + empacotamento integrado (Δy/compressão/rollback)")
182
- from khtst.quanta.torchao_quant import quantizar_torchao
183
- from khtst.nucleo.modelo import KHTSTModel
184
- from khtst.config import Config
185
- verde = True
186
- cfg = Config()
187
- modelo = KHTSTModel(cfg)
188
- modelo.eval()
189
- sonda = torch.randint(0, 100, (1, 16))
190
- with torch.no_grad():
191
- ev = quantizar_torchao(modelo, cfg={"modo": "auto", "dim_minimo": 64,
192
- "empacotar_moe": True,
193
- "n_blocos_floresta": 2},
194
- entrada_sonda=sonda)
195
- verde &= _ok("quantização ok", bool(ev.get("ok")),
196
- f"{ev.get('n_camadas_quantizadas', 0)} camadas")
197
- verde &= _ok("MoE EMPACOTADA (não mais excluída)",
198
- ev.get("n_moe_empacotadas", 0) >= 1,
199
- f"compressão MoE {ev.get('moe_compressao', 0):.2f}×")
200
- verde &= _ok("Δy da sonda dentro da cota",
201
- ev.get("delta_y_relativo", 1.0) < 0.10,
202
- f"Δy = {ev.get('delta_y_relativo', float('nan')):.2e}")
203
- return verde
204
-
205
-
206
- def bloco_f() -> bool:
207
- print("\n[F] ReplaySSM — exatidão (Teos 29.13/29.14)")
208
- from khtst.mamba3.kernel import varredura_trapezoidal
209
- from khtst.mamba3.replay import varredura_replay
210
- torch.manual_seed(7)
211
- B, L, D, N, R = 2, 128, 16, 4, 2
212
- u = torch.randn(B, L, D, requires_grad=True)
213
- delta = torch.sigmoid(torch.randn(B, L, D))
214
- A = -torch.exp(torch.rand(D, N))
215
- Bm = torch.randn(B, L, R, N)
216
- Cm = torch.randn(B, L, R, N)
217
- out_f, h_f = varredura_trapezoidal(u, delta, A, Bm, Cm, devolve_estado=True)
218
- out_r, h_r = varredura_replay(u, delta, A, Bm, Cm, 16, devolve_estado=True)
219
- verde = _ok("saída BIT-EXATA", torch.equal(out_f, out_r))
220
- verde &= _ok("h_L BIT-EXATO", torch.equal(h_f, h_r))
221
- u2 = u.detach().clone().requires_grad_(True)
222
- u3 = u.detach().clone().requires_grad_(True)
223
- g = torch.randn_like(out_f)
224
- varredura_trapezoidal(u2, delta, A, Bm, Cm).backward(g)
225
- varredura_replay(u3, delta, A, Bm, Cm, 16).backward(g)
226
- erro_g = float((u2.grad - u3.grad).abs().max())
227
- verde &= _ok("gradiente exato (erro 0.0)", erro_g == 0.0, f"erro = {erro_g}")
228
- # ativação guardada: backward do replay retém menos por segmento
229
- from khtst.mamba3.replay import _segmento
230
- verde &= _ok("kernel completo preservado (nascimento neutro S=1)",
231
- torch.equal(varredura_replay(u.detach(), delta, A, Bm, Cm, 1),
232
- varredura_trapezoidal(u.detach(), delta, A, Bm, Cm)))
233
- return verde
234
-
235
-
236
- def bloco_g() -> bool:
237
- print("\n[G] TCE — Problema 2 (Teos 29.5/29.6)")
238
- from khtst.treino.jepa import MotorJepa, ConfigJepa
239
- torch.manual_seed(3)
240
- # (i) normalização L/d: mesma perda com λ' = λ·d reproduz a v16
241
- cfg_sum = ConfigJepa(d_modelo=64, d_latente=32, normalizar_dim=False,
242
- vicreg_lambda=0.0)
243
- cfg_nd = ConfigJepa(d_modelo=64, d_latente=32, normalizar_dim=True,
244
- vicreg_lambda=0.0)
245
- m_sum, m_nd = MotorJepa(None, cfg_sum), MotorJepa(None, cfg_nd)
246
- for p in m_sum.parameters():
247
- torch.nn.init.normal_(p, std=0.2)
248
- m_nd.load_state_dict(m_sum.state_dict())
249
- # o alvo EMA (funil_bar) NÃO é submodule — sincronia manual bit-exata
250
- m_nd.funil_bar.bar.load_state_dict(m_sum.funil_bar.bar.state_dict())
251
- h = torch.randn(2, 8, 64)
252
- torch.manual_seed(11)
253
- _, t_sum = m_sum.perda(h)
254
- torch.manual_seed(11)
255
- _, t_nd = m_nd.perda(h)
256
- d = cfg_nd.d_latente
257
- verde = _ok("L_normalizada = L_soma/d (Teo 29.5)",
258
- abs(t_nd["jepa/perda"] - t_sum["jepa/perda_soma"] / d) < 1e-6,
259
- f"{t_nd['jepa/perda']:.4f} vs {t_sum['jepa/perda_soma'] / d:.4f}")
260
- # (ii) limiar invariante: com entrada PREDIZÍVEL (constante no tempo ⊕
261
- # ruído pequeno) o predictor alinha pred→alvo e a taxa abre. (No
262
- # nascimento aleatório ‖e‖ > √θ·‖alvo‖ é esperado; na v16 a taxa
263
- # permanecia ≡ 0 MESMO após treino porque o limiar absoluto ‖e‖<1 é
264
- # inalcançável com ‖alvo‖=√d — a cura é o limiar relativo.)
265
- base = torch.randn(2, 1, 64)
266
- h_pred = (base + 0.01 * torch.randn(2, 8, 64)).detach()
267
- ot = torch.optim.Adam(m_nd.parameters(), lr=0.05)
268
- for _ in range(300):
269
- L, _ = m_nd.perda(h_pred)
270
- ot.zero_grad()
271
- L.backward()
272
- ot.step()
273
- m_nd.passo_pos_backward()
274
- _, t_t = m_nd.perda(h_pred)
275
- verde &= _ok("taxa de sucesso > 0 com limiar invariante (v16 era ≡ 0)",
276
- t_t["jepa/taxa_sucesso"] > 0.0,
277
- f"taxa = {t_t['jepa/taxa_sucesso']:.3f}, perda = "
278
- f"{t_t['jepa/perda']:.3f} (300 passos Adam)")
279
- # (iii) homogeneidade: a entrada 50× produz latentes ESFÉRICOS idênticos
280
- # (FunilLatente normaliza) ⟹ taxa invariante à escala c
281
- _, t_g = m_nd.perda(h_pred * 50.0)
282
- verde &= _ok("homogeneidade: taxa invariante a c > 0 (Teo 29.6)",
283
- abs(t_g["jepa/taxa_sucesso"] - t_t["jepa/taxa_sucesso"]) < 0.25,
284
- f"{t_t['jepa/taxa_sucesso']:.3f} vs {t_g['jepa/taxa_sucesso']:.3f}")
285
- return verde
286
-
287
-
288
- def bloco_h() -> bool:
289
- print("\n[H] Autoajuste multi-método (Teos 30.1–30.15)")
290
- from khtst.nucleo.autorregulador import (AutorregulacaoMulti,
291
- ControladorHibrido,
292
- BissecaoTauQK)
293
- verde = True
294
- # nascimento neutro
295
- multi = AutorregulacaoMulti({"ativo": True, "passos_espera": 0})
296
- verde &= _ok("nascimento NEUTRO (todas as escalas = 1.0)",
297
- all(abs(v - 1.0) < 1e-12 for v in
298
- multi.escalas_adamw().values()))
299
- # loop β estável: CV² alta sustentada ⟹ β₂ desce até o limite
300
- for _ in range(60):
301
- multi.atualizar({"cv2": 4.0, "tend_cv2": 1.0})
302
- verde &= _ok("β₂ responde a CV² alta (loop negativo)",
303
- multi.beta2.valor < 1.0, f"β₂ escala = {multi.beta2.valor:.3f}")
304
- # ε/wd/momentum respondem
305
- for _ in range(60):
306
- multi.atualizar({"razao_upd": 3.0, "norma_rel": 1.5,
307
- "razao_mom": 0.2, "trust": 0.9, "velocidade": 0.01,
308
- "razao_moe": 0.9, "taxa_som": 0.5,
309
- "folga_abmo": -0.3, "razao_cresc": 4.0})
310
- verde &= _ok("ε sobe com ‖Δp‖/‖g‖ alta", multi.eps.valor > 1.0,
311
- f"{multi.eps.valor:.3f}")
312
- verde &= _ok("wd sobe com norma relativa > 1", multi.wd.valor > 1.0,
313
- f"{multi.wd.valor:.3f}")
314
- verde &= _ok("momentum sobe com razão baixa (Teo 30.6)",
315
- multi.momentum.valor > 1.0, f"{multi.momentum.valor:.3f}")
316
- verde &= _ok("PESO_MOE desce com razão > ½ (Teo 30.11)",
317
- multi.peso_moe.valor < 1.0, f"{multi.peso_moe.valor:.3f}")
318
- verde &= _ok("PESO_SOM sobe com ativação < 90% (Teo 30.12)",
319
- multi.peso_som.valor > 1.0, f"{multi.peso_som.valor:.3f}")
320
- verde &= _ok("margem ABMO desce com folga negativa (Teo 30.13)",
321
- multi.abmo_margem.valor < 1.0, f"{multi.abmo_margem.valor:.3f}")
322
- # τ_qk bisseção: contrai e mantém erro ≤ (τmax−τmin)/2^k (Teo 30.7)
323
- tq = BissecaoTauQK(faixa=(80.0, 120.0), tau_min=20.0, tau_max=240.0,
324
- tau0=100.0, paciencia=1)
325
- for lmax in (200.0, 200.0, 200.0): # ℓ_max alto ⟹ τ desce
326
- tq.registrar_lmax(lmax)
327
- verde &= _ok("τ_qk desce com ℓ_max > hi", tq.tau < 100.0,
328
- f"τ = {tq.tau:.1f} (contração 1/2 — Teo 30.7)")
329
- # PID: canal integral com vazamento limitado (anti-windup)
330
- ch = ControladorHibrido((0.5, 2.0), b=0.0, c_i=0.05)
331
- for _ in range(500):
332
- ch.atualizar(0.0, erro=1.0) # erro constante ⟹ I satura em 1
333
- verde &= _ok("integral com vazamento SATURA em 1 (anti-windup)",
334
- abs(ch.I - 1.0) < 1e-9, f"I = {ch.I:.4f}")
335
- # limites respeitados sempre (Teo 30.1: truncagem garante pertença)
336
- ch2 = ControladorHibrido((0.5, 2.0), b=0.2, c_i=0.1, c_d=0.1)
337
- for _ in range(2000):
338
- ch2.atualizar(1.0, erro=1.0)
339
- verde &= _ok("θ ∈ [θ_min, θ_max] SEMPRE (Teo 30.1)",
340
- 0.5 - 1e-12 <= ch2.valor <= 2.0 + 1e-12,
341
- f"θ = {ch2.valor:.4f}")
342
- return verde
343
-
344
-
345
- def main() -> int:
346
- ap = argparse.ArgumentParser()
347
- ap.add_argument("--rapido", action="store_true")
348
- args = ap.parse_args()
349
- t0 = time.time()
350
- print("=" * 72)
351
- print("VERIFICAÇÃO v17 KHMAMBAJEPA — doc 29 (Teos 29.1–29.14) + doc 30")
352
- print("=" * 72)
353
- torch.manual_seed(2026)
354
- resultados = {"A": bloco_a(), "B": bloco_b(),
355
- "C": bloco_c(args.rapido), "D": bloco_d(),
356
- "E": bloco_e(), "F": bloco_f(), "G": bloco_g(),
357
- "H": bloco_h()}
358
- print("\n" + "=" * 72)
359
- for k, v in resultados.items():
360
- print(f" bloco {k}: {'VERDE' if v else 'VERMELHO'}")
361
- ok = all(resultados.values())
362
- print(f"\n{'TUDO VERDE ✓' if ok else 'HÁ FALHAS ✗'}"
363
- f" ({time.time() - t0:.1f}s)")
364
- return 0 if ok else 1
365
-
366
-
367
- if __name__ == "__main__":
368
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/khtst/acelerado/setup.py CHANGED
@@ -44,17 +44,6 @@ extensoes = [
44
  extra_link_args=["-fopenmp"],
45
  language="c",
46
  ),
47
- # v17 — jepa_validator (doc 29, Teos 29.10–29.12): registro/auditoria de
48
- # variantes JEPA (acumulação C long long), Token Rounding EXATO no bloco
49
- # de predição (n̂ = τ·⌈n/τ⌉, offsets por prefixo, GEMM bit-exato nas
50
- # linhas vivas) e AuditoriaMemoriaSonic (statm nível C ~µs; I1–I4).
51
- Extension(
52
- "jepa_validator",
53
- sources=["jepa_validator.pyx"],
54
- include_dirs=[numpy.get_include()],
55
- extra_compile_args=["-O3", "-march=native"],
56
- language="c++",
57
- ),
58
  ]
59
 
60
  setup(
 
44
  extra_link_args=["-fopenmp"],
45
  language="c",
46
  ),
 
 
 
 
 
 
 
 
 
 
 
47
  ]
48
 
49
  setup(
src/khtst/aprimoramento/__init__.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """Pacote de APRIMORAMENTO KHTST (v17) — módulos da rodada de análise:
3
+ difusão com gradiente vivo, métricas QE+CT com significância, λ_c
4
+ unificado com sinal suavizado, trade-off K com Ĉ estimado e unimodalidade
5
+ provada, JEPA com anti-colapso por dimensão e o CONTROLADOR HÍBRIDO
6
+ (RM+PI+bisseção) com a tabela de sinais da autorregulação estendida.
7
+
8
+ Provas: docs/matematica/29-autorregulacao-hibrida-aprimoramentos.md
9
+ (Teos 29.1–29.16). Suíte: tests/test_khtst_v17.py.
10
+ """
11
+ from .config import (DifusaoConfig, JEPAConfig, KHTSTConfig,
12
+ LambdaCConfig, QECTConfig, TradeoffKConfig)
13
+ from .controlador_hibrido import ControladorBissecao, ControladorHibrido
14
+ from .autorregulacao_estendida import (AutorreguladorEstendido,
15
+ sinal_razao)
16
+ from .lambda_c_unificado import (AutoAjusteLambdaC, equivalencia_numerica,
17
+ fast_path_step, ref_path_step)
18
+ from .tradeoff_k import (J1, J2, ResultadoK, estimar_C, epsilon_sq,
19
+ k_star_fechado, resolver_K, validar_v15_1)
20
+ from .metricas_qe_ct import (ResultadoQECT, avaliar_ganho,
21
+ consistencia_temporal, erro_quantizacao,
22
+ te_antigo)
23
+ from .difusao_gradiente import (AutoLambdaDiff, DifusaoDDPM, DenoiserMLP,
24
+ treinar_difusao)
25
+ from .jepa import JEPA, Encoder, MLP, hinge_variancia_por_dim
26
+
27
+ __all__ = [
28
+ "DifusaoConfig", "JEPAConfig", "KHTSTConfig", "LambdaCConfig",
29
+ "QECTConfig", "TradeoffKConfig",
30
+ "ControladorBissecao", "ControladorHibrido",
31
+ "AutorreguladorEstendido", "sinal_razao",
32
+ "AutoAjusteLambdaC", "equivalencia_numerica", "fast_path_step",
33
+ "ref_path_step",
34
+ "J1", "J2", "ResultadoK", "estimar_C", "epsilon_sq", "k_star_fechado",
35
+ "resolver_K", "validar_v15_1",
36
+ "ResultadoQECT", "avaliar_ganho", "consistencia_temporal",
37
+ "erro_quantizacao", "te_antigo",
38
+ "AutoLambdaDiff", "DifusaoDDPM", "DenoiserMLP", "treinar_difusao",
39
+ "JEPA", "Encoder", "MLP", "hinge_variancia_por_dim",
40
+ ]
src/khtst/aprimoramento/autorregulacao_estendida.py ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """AUTORREGULAÇÃO ESTENDIDA v17 — a tabela de sinais (doc 29 §10, Teo 29.16).
3
+
4
+ Fecha a lacuna diagnosticada na v16: o Autorregulador (Teos 28.5–28.7)
5
+ governava lr, λ_aux e peso MoE com RM puro e UM sinal por parâmetro —
6
+ sem correlação entre métricas, sem memória de longo prazo, sem rastreio
7
+ de setpoint, e SEM cobertura de AdamW (β₁/β₂/ε/wd), Muon (momentum/
8
+ escala/τ_qk), PRS V8 (5 parâmetros), pesos de perda (PESO_MOE,
9
+ PESO_ALINHAMENTO_SOM), ABMO, CIAR e crescimento.
10
+
11
+ ESTE módulo registra CADA parâmetro em um ControladorHibrido (RM + PI,
12
+ Teo 29.14) ou ControladorBissecao (τ_qk, Teo 29.15), com:
13
+
14
+ • NASCIMENTO NEUTRO: o centro de cada controlador é a constante ATUAL
15
+ de produção — com autorreg desligada, o comportamento é bit-a-bit o
16
+ da v16; ligada, cada parâmetro parte do valor comprovado e se move
17
+ dentro de limites SEGUROS (nunca diverge);
18
+ • SETPOINT EXPLÍCITO por parâmetro (o laço PI rastreia o alvo — o RM
19
+ sozinho só converge ao estacionário do campo, que pode ter viés);
20
+ • TELEMETRIA TOTAL: cada valor e cada erro é registrado no
21
+ TelemetryHub (requisito: todos os sinais auditáveis).
22
+
23
+ TABELA DE SINAIS (Teo 29.16 — cada linha é um parâmetro regulável):
24
+
25
+ AdamW β₁ PID varância do gradiente (proxy de curvatura) [0.80, 0.95]
26
+ AdamW β₂ PID deriva relativa do segundo momento [0.90, 0.999]
27
+ AdamW ε RM razão ‖update‖/‖g‖ contra o alvo 1.0 [1e-10, 1e-6]
28
+ AdamW wd PID norma L2 média dos pesos contra 1.0 [0.0, 0.10]
29
+ Muon momentum RM razão ‖momentum‖/‖g‖ contra o alvo 1.0 [0.80, 0.99]
30
+ Muon escala PID razão RMS(update Muon)/RMS(update AdamW) → 1.0 [0.10, 0.40]
31
+ τ_qk BISS banda ℓ_max ∈ [80, 120] (Teo 29.15) [40, 400]
32
+ PRS η_up PID taxa de acerto do trust contra o alvo [0.01, 0.15]
33
+ PRS η_down PID 1 − taxa de acerto (corta mais quando erra) [0.005, 0.10]
34
+ PRS T_ciclo RM velocidade Δperda/passo contra vel_alvo [200, 1200]
35
+ PRS decay_piso RM idem (família de progresso) [0.30, 0.80]
36
+ PRS percentil RM razão de clips contra o alvo 0.10 [0.50, 0.95]
37
+ PESO_MOE RM razão L_moe/L_ce contra o alvo 0.5 (Teo 28.7-ii)[0.005, 0.08]
38
+ PESO_SOM PID taxa de ativação da SOM contra 0.90 [0.01, 0.20]
39
+ ABMO margem RM folga da barreira η ≤ (2−m)/L̂ (Teo 24.9) [0.5, 1.5]×
40
+ CIAR κ PID taxa de aceitação contra o alvo [0.5, 2.0]×
41
+ cresc. expand RM taxa de expansão contra o alvo 0.05 [0.5, 2.0]×
42
+ cresc. prune RM taxa de poda contra o alvo 0.02 [0.5, 2.0]×
43
+ """
44
+ from __future__ import annotations
45
+
46
+ import math
47
+ from typing import Callable
48
+
49
+ from .controlador_hibrido import ControladorBissecao, ControladorHibrido
50
+
51
+
52
+ def sinal_razao(x: float, alvo: float) -> float:
53
+ """Sinal RM normalizado: clip((x−alvo)/max(|alvo|,ε), ±1) — adimensional,
54
+ independente da escala da métrica (regra do projeto: sinais ∈ [−1,1])."""
55
+ denom = max(abs(alvo), 1e-9)
56
+ return max(-1.0, min(1.0, (float(x) - alvo) / denom))
57
+
58
+
59
+ class AutorreguladorEstendido:
60
+ """Tabela de sinais v17 — um controlador híbrido por parâmetro.
61
+
62
+ Uso no treinador (opt-in; nascimento neutro):
63
+ areg = AutorreguladorEstendido(hub=hub)
64
+ valores = areg.registrar({"var_grad": 0.8, "taxa_acerto_trust": 0.7, ...})
65
+ areg.aplicar_em_otimizador(valores, opt)
66
+ areg.aplicar_em_prs(valores, prs)
67
+ """
68
+
69
+ def __init__(self, cfg: dict | None = None, hub=None,
70
+ a0: float = 0.05, tau_a: float = 400.0, espera: int = 20):
71
+ cfg = cfg or {}
72
+ self.hub = hub
73
+ self.ativo = bool(cfg.get("ativo", False)) # NASCIMENTO NEUTRO
74
+ self.a_cada = int(cfg.get("a_cada", 10))
75
+ self._passo = 0
76
+ self._t_ajuste = 0
77
+ C = self._construir(a0, tau_a, espera)
78
+ self._controladores: dict[str, object] = C
79
+
80
+ # ------------------------------------------------------------------
81
+ def _construir(self, a0: float, tau_a: float, espera: int) -> dict:
82
+ """Instancia a tabela Teo 29.16 (centros = constantes v16)."""
83
+ def h(centro, limites, b_i=0.0, c_d=0.0, alvo=1.0, passo_max=0.02):
84
+ return ControladorHibrido(centro, limites, a0=a0, tau_a=tau_a,
85
+ passo_max=passo_max, b_i=b_i, c_d=c_d,
86
+ alvo=alvo, espera=espera)
87
+ return {
88
+ # ---- AdamW (grupo `adam`) ----
89
+ "adamw_beta1": h(0.90, (0.80, 0.95), b_i=0.05, alvo=1.0),
90
+ "adamw_beta2": h(0.95, (0.90, 0.999), b_i=0.05, alvo=1.0),
91
+ "adamw_eps": h(1e-8, (1e-10, 1e-6), alvo=1.0, passo_max=0.05),
92
+ "adamw_wd": h(0.01, (1e-4, 0.10), b_i=0.10, alvo=1.0),
93
+ # ---- Muon ----
94
+ "muon_momentum": h(0.95, (0.80, 0.99), alvo=1.0),
95
+ "muon_escala": h(0.20, (0.10, 0.40), b_i=0.05, alvo=1.0),
96
+ "tau_qk": ControladorBissecao(100.0, (80.0, 120.0),
97
+ modo="escala", eta=0.5),
98
+ # ---- PRS V8 ----
99
+ "prs_eta_up": h(0.05, (0.01, 0.15), b_i=0.10, alvo=0.60),
100
+ "prs_eta_down": h(0.02, (0.005, 0.10), b_i=0.10, alvo=0.60),
101
+ "prs_T_ciclo": h(400.0, (200.0, 1200.0), alvo=1.0, passo_max=0.01),
102
+ "prs_decay_piso": h(0.50, (0.30, 0.80), alvo=1.0, passo_max=0.01),
103
+ "prs_percentil": h(0.75, (0.50, 0.95), alvo=0.10, passo_max=0.02),
104
+ # ---- pesos de perda ----
105
+ "peso_moe": h(0.02, (0.005, 0.08), alvo=0.5, passo_max=0.03),
106
+ "peso_som": h(0.05, (0.01, 0.20), b_i=0.10, alvo=0.90),
107
+ # ---- ABMO / CIAR / crescimento (escala ×) ----
108
+ "abmo_margem": h(1.0, (0.5, 1.5), alvo=1.0),
109
+ "ciar_kappa": h(1.0, (0.5, 2.0), b_i=0.05, alvo=0.70),
110
+ "cresc_expand": h(1.0, (0.5, 2.0), alvo=0.05),
111
+ "cresc_prune": h(1.0, (0.5, 2.0), alvo=0.02),
112
+ }
113
+
114
+ # ------------------------------------------------------------------
115
+ # TABELA: parâmetro → (sinal RM, medida PI) a partir do dicionário de
116
+ # telemetria bruta. Cada função é total (default neutro se faltar a
117
+ # métrica — sinal 0 = "não move", medida None = "PI não atua").
118
+ def _tabela_sinais(self) -> dict[str, tuple[Callable, Callable]]:
119
+ def f_sinal(chave, alvo, inverte=False):
120
+ def f(t):
121
+ if chave not in t:
122
+ return 0.0
123
+ s = sinal_razao(t[chave], alvo)
124
+ return -s if inverte else s
125
+ return f
126
+
127
+ def f_medida(chave, alvo):
128
+ def f(t):
129
+ return float(t[chave]) if chave in t else None
130
+ return f
131
+
132
+ return {
133
+ # AdamW β₁ — proxy de curvatura: variância do gradiente padronizada
134
+ # já vem normalizada do produtor (var_grad_norm ∈ [0,∞), alvo 1.0)
135
+ "adamw_beta1": (f_sinal("var_grad_norm", 1.0),
136
+ f_medida("var_grad_norm", 1.0)),
137
+ # AdamW β₂ — deriva do segundo momento (alvo 1.0 = estável);
138
+ # deriva ALTA ⟹ β₂ desce (sinal invertido: deriva alta ⟹ ↓β₂)
139
+ "adamw_beta2": (f_sinal("deriva_seg_momento", 1.0, inverte=True),
140
+ f_medida("deriva_seg_momento", 1.0)),
141
+ # AdamW ε — razão ‖update‖/‖g‖ vs 1.0 (Teo 29.16)
142
+ "adamw_eps": (f_sinal("razao_update_grad", 1.0),
143
+ f_medida("razao_update_grad", 1.0)),
144
+ # AdamW wd — norma L2 média vs 1.0: pesos pesados ⟹ wd sobe
145
+ "adamw_wd": (f_sinal("norma_peso", 1.0),
146
+ f_medida("norma_peso", 1.0)),
147
+ # Muon momentum — ‖momentum‖/‖g‖ vs 1.0
148
+ "muon_momentum": (f_sinal("razao_momentum_grad", 1.0),
149
+ f_medida("razao_momentum_grad", 1.0)),
150
+ # Muon escala — RMS(Muon)/RMS(AdamW) vs 1.0 (Teo 24.11)
151
+ "muon_escala": (f_sinal("razao_rms_mecanismos", 1.0),
152
+ f_medida("razao_rms_mecanismos", 1.0)),
153
+ # τ_qk — controlado por ControladorBissecao (logit_max bruto)
154
+ "tau_qk": (lambda t: 0.0, f_medida("logit_max", 100.0)),
155
+ # PRS η_up — acerto acima do alvo ⟹ sobe mais agressivo
156
+ "prs_eta_up": (f_sinal("taxa_acerto_trust", 0.60),
157
+ f_medida("taxa_acerto_trust", 0.60)),
158
+ # PRS η_down — acerto BAIXO ⟹ corta mais (sinal invertido)
159
+ "prs_eta_down": (f_sinal("taxa_acerto_trust", 0.60, inverte=True),
160
+ f_medida("taxa_acerto_trust", 0.60)),
161
+ # PRS T_ciclo — progresso rápido (Δperda alto) ⟹ ciclo MAIOR
162
+ "prs_T_ciclo": (f_sinal("delta_perda_passo", 0.01),
163
+ f_medida("delta_perda_passo", 0.01)),
164
+ "prs_decay_piso": (f_sinal("delta_perda_passo", 0.01),
165
+ f_medida("delta_perda_passo", 0.01)),
166
+ # PRS percentil — clips acima do alvo 0.10 ⟹ percentil sobe
167
+ "prs_percentil": (f_sinal("razao_clip", 0.10),
168
+ f_medida("razao_clip", 0.10)),
169
+ # PESO_MOE — razão L_moe/L_ce acima de 0.5 ⟹ peso desce
170
+ # (Teo 28.7-ii: CE é a descida primária)
171
+ "peso_moe": (None, None), # tratado abaixo (sinal direto)
172
+ # PESO_SOM — ativação abaixo de 0.90 ⟹ peso sobe
173
+ "peso_som": (f_sinal("ativacao_som", 0.90),
174
+ f_medida("ativacao_som", 0.90)),
175
+ # ABMO — folga da barreira: sinal já normalizado ±1
176
+ "abmo_margem": (f_sinal("margem_abmo_norm", 1.0),
177
+ f_medida("margem_abmo_norm", 1.0)),
178
+ # CIAR κ — aceitação vs alvo
179
+ "ciar_kappa": (f_sinal("taxa_aceitacao_ciar", 0.70),
180
+ f_medida("taxa_aceitacao_ciar", 0.70)),
181
+ # crescimento — expansão/poda vs alvos
182
+ "cresc_expand": (f_sinal("taxa_expansao", 0.05),
183
+ f_medida("taxa_expansao", 0.05)),
184
+ "cresc_prune": (f_sinal("taxa_prune", 0.02),
185
+ f_medida("taxa_prune", 0.02)),
186
+ }
187
+
188
+ # ------------------------------------------------------------------
189
+ def registrar(self, telemetria: dict) -> dict[str, float]:
190
+ """Um ciclo de ajuste: sinais → controladores → valores novos.
191
+
192
+ `telemetria` pode conter QUALQUER subconjunto das chaves —
193
+ parâmetros sem sinal simplesmente não movem (robustez)."""
194
+ self._passo += 1
195
+ if not self.ativo or (self._passo % self.a_cada) != 0:
196
+ return {k: self._valor(k) for k in self._controladores}
197
+ self._t_ajuste += 1
198
+ tabela = self._tabela_sinais()
199
+ valores: dict[str, float] = {}
200
+ for nome, ctl in self._controladores.items():
201
+ if isinstance(ctl, ControladorBissecao):
202
+ if "logit_max" in telemetria:
203
+ ctl.atualizar(float(telemetria["logit_max"]))
204
+ valores[nome] = ctl.tau
205
+ if self.hub is not None:
206
+ self.hub.atributo(f"autorreg_v17/{nome}", ctl.tau)
207
+ continue
208
+ sinal_fn, medida_fn = tabela[nome]
209
+ if nome == "peso_moe":
210
+ # sinal DIRETO: e = (alvo − razão)/alvo — acima do alvo ⟹ ↓
211
+ if "razao_moe_ce" in telemetria:
212
+ r = float(telemetria["razao_moe_ce"])
213
+ s = max(-1.0, min(1.0, (0.5 - r) / 0.5))
214
+ medida = r
215
+ else:
216
+ s, medida = 0.0, None
217
+ else:
218
+ s = float(sinal_fn(telemetria))
219
+ medida = medida_fn(telemetria)
220
+ ctl.atualizar(s, medida)
221
+ valores[nome] = ctl.valor
222
+ if self.hub is not None:
223
+ self.hub.atributo(f"autorreg_v17/{nome}", ctl.valor)
224
+ if ctl.e_anterior is not None:
225
+ self.hub.atributo(f"autorreg_v17/{nome}__erro",
226
+ ctl.e_anterior)
227
+ return valores
228
+
229
+ def _valor(self, nome: str) -> float:
230
+ ctl = self._controladores[nome]
231
+ return ctl.tau if isinstance(ctl, ControladorBissecao) else ctl.valor
232
+
233
+ # ------------------------------------------------------------------
234
+ # ADAPTADORES de aplicação (escrita segura nos consumos)
235
+ def aplicar_em_otimizador(self, valores: dict, opt) -> list[str]:
236
+ """Escreve β₁/β₂/ε/wd (grupo AdamW), momentum/escala (Muon) e τ_qk
237
+ nos param_groups. Campos ausentes são ignorados (idempotente)."""
238
+ tocados = []
239
+ for grupo in getattr(opt, "param_groups", []):
240
+ if "adamw_beta1" in valores and "betas" in grupo:
241
+ b1 = max(0.0, min(0.999, valores["adamw_beta1"]))
242
+ b2 = max(b1, min(0.9999, valores.get("adamw_beta2",
243
+ grupo["betas"][1])))
244
+ grupo["betas"] = (b1, b2)
245
+ tocados.append("betas")
246
+ if "adamw_eps" in valores and "eps" in grupo:
247
+ grupo["eps"] = float(max(1e-12, valores["adamw_eps"]))
248
+ tocados.append("eps")
249
+ if "adamw_wd" in valores and "weight_decay" in grupo:
250
+ grupo["weight_decay"] = float(max(0.0, valores["adamw_wd"]))
251
+ tocados.append("weight_decay")
252
+ if "muon_momentum" in valores and "momentum" in grupo:
253
+ grupo["momentum"] = float(max(0.0, min(0.999,
254
+ valores["muon_momentum"])))
255
+ tocados.append("momentum")
256
+ if "muon_escala" in valores and "escala_muon" in grupo:
257
+ grupo["escala_muon"] = float(max(1e-3, valores["muon_escala"]))
258
+ tocados.append("escala_muon")
259
+ if "tau_qk" in valores and grupo.get("tau_qk", None):
260
+ grupo["tau_qk"] = float(valores["tau_qk"])
261
+ tocados.append("tau_qk")
262
+ return sorted(set(tocados))
263
+
264
+ def aplicar_em_prs(self, valores: dict, prs) -> list[str]:
265
+ """Escreve os 5 parâmetros do PRS V8 dentro dos limites seguros.
266
+ Atributos ausentes no objeto são ignorados (adapter tolerante)."""
267
+ mapa = {"prs_eta_up": "eta_up", "prs_eta_down": "eta_down",
268
+ "prs_T_ciclo": "T_ciclo", "prs_decay_piso": "decay_piso",
269
+ "prs_percentil": "percentil"}
270
+ tocados = []
271
+ for chave, attr in mapa.items():
272
+ if chave in valores and hasattr(prs, attr):
273
+ v = float(valores[chave])
274
+ if attr == "T_ciclo":
275
+ v = max(1, int(round(v)))
276
+ setattr(prs, attr, v)
277
+ tocados.append(attr)
278
+ return sorted(set(tocados))
279
+
280
+ def telemetria(self) -> dict:
281
+ out = {}
282
+ for nome, ctl in self._controladores.items():
283
+ v = ctl.tau if isinstance(ctl, ControladorBissecao) else ctl.valor
284
+ out[f"autorreg_v17/{nome}"] = v
285
+ return out
src/khtst/aprimoramento/config.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """Configuração do pacote de APRIMORAMENTO KHTST (v17) — fonte única das
3
+ constantes deste pacote (regra do projeto: nenhum número solto em módulos).
4
+
5
+ Relação com khtst.config (produção): ESTE config é auto-contido e governa
6
+ apenas o pacote `aprimoramento`. Os defaults respeitam a convenção de
7
+ NASCIMENTO NEUTRO: com todos os flags em default, o comportamento é
8
+ idêntico ao dos rascunhos de referência — cada aprimoramento novo entra
9
+ com um campo próprio que pode ser desligado individualmente.
10
+
11
+ CORREÇÕES de integração sobre o rascunho (defeitos D11/D12/D14 do doc 29):
12
+ • JEPAConfig.peso_var — o peso 0.01 do hinge de variância era
13
+ HARD-CODED no forward; agora é campo.
14
+ • JEPAConfig.ema_cosseno — agenda de momentum EMA (BYOL) opt-in.
15
+ • QECTConfig.normalizar — existia no rascunho e NUNCA era lido
16
+ (campo morto); agora governa a normalização
17
+ do QE (invariância de escala, Teo 29.4).
18
+ • QECTConfig.alpha/n_min — significância estatística do "ganho real"
19
+ (Teo 29.5 — Hoeffding) no lugar da conjunção
20
+ de limiares fixos.
21
+ • DifusaoConfig.eta_lambda — existia e NUNCA era lido; agora alimenta
22
+ o AutoLambdaDiff (Teo 29.2).
23
+ • DifusaoConfig.rho_ancora — âncora quadrática que dá ÓTIMO INTERIOR
24
+ provado para λ_diff (Teo 29.2-iii).
25
+ • LambdaCConfig.modo/tau_eta— sinal suavizado (correção do defeito D6:
26
+ a média da janela era computada e jogada
27
+ fora) + agenda RM opcional (Teo 29.7-ii).
28
+ • TradeoffKConfig.estimar_C — constante de Zador estimada por OLS
29
+ log-log (Teo 29.8) em vez de C=1 fixo.
30
+ """
31
+ from __future__ import annotations
32
+
33
+ from dataclasses import dataclass, field
34
+ from typing import Literal
35
+
36
+
37
+ @dataclass
38
+ class JEPAConfig:
39
+ dim: int = 256
40
+ pred_hidden: int = 512
41
+ ema_momentum: float = 0.996
42
+ ema_cosseno: bool = False # Teo 29.12: agenda cosseno BYOL (opt-in)
43
+ lambda_jepa: float = 0.5 # peso do alinhamento (ANTES: campo morto)
44
+ peso_var: float = 0.01 # peso do hinge de variância (ANTES: fixo)
45
+ vicreg_lambda: float = 0.0 # >0 ativa o kernel Cython VICReg (cov)
46
+ vicreg_mu: float = 25.0
47
+ vicreg_gamma: float = 1.0
48
+ use_sg: bool = True # stop-gradient no alvo (sempre recomendado)
49
+ normalize: bool = True # L2-normaliza antes do MSE
50
+
51
+
52
+ @dataclass
53
+ class TradeoffKConfig:
54
+ d: int = 512 # dimensão do codebook
55
+ n: int = 100_000 # amostras
56
+ lambda_c: float = 0.5
57
+ K_grid: tuple = (16, 32, 64, 128, 256, 512)
58
+ tol_rel: float = 0.05
59
+ metodo: Literal["rd", "asymp", "grid", "auto"] = "auto"
60
+ estimar_C: bool = True # Teo 29.8: Ĉ por OLS log-log (default ON)
61
+ C_prior: float = 1.0 # prior de shrinkage para Ĉ (Teo 29.8-ii)
62
+ kappa_prior: int = 8 # peso do prior (n_C + κ — bias-variance)
63
+ bits_por_param: float = 16.0
64
+
65
+
66
+ @dataclass
67
+ class LambdaCConfig:
68
+ eta: float = 1e-3
69
+ lambda_c_min: float = 0.01
70
+ lambda_c_max: float = 0.99
71
+ janela: int = 100 # passos da média móvel do sinal (D6)
72
+ modo: Literal["alvo", "reversao"] = "alvo"
73
+ # alvo : delta = ε̄² − ε²_alvo (rastreio de um alvo fixo)
74
+ # reversao : delta = ε̄² − média_janela (reversão à média da janela)
75
+ eta_agendado: bool = False # Teo 29.7-ii: η_t = η₀/(1+t/τ) — RM q.c.
76
+ tau_eta: float = 400.0
77
+
78
+
79
+ @dataclass
80
+ class QECTConfig:
81
+ eps_qe: float = 1e-3
82
+ eps_ct: float = 1e-3
83
+ normalizar: bool = True # AGORA USADO (D14): QE relativo a ‖x‖²
84
+ alpha: float = 0.05 # nível do teste unilateral (Teo 29.5)
85
+ n_min: int = 32 # amostras mínimas p/ declarar ganho real
86
+
87
+
88
+ @dataclass
89
+ class DifusaoConfig:
90
+ T: int = 1000
91
+ beta_start: float = 1e-4
92
+ beta_end: float = 0.02
93
+ lambda_diff: float = 0.1
94
+ eta_lambda: float = 0.05 # AGORA USADO (D14): passo do EG de λ_diff
95
+ rho_ancora: float = 1.0 # Teo 29.2-iii: âncora ρ(λ−λ₀)² (ótimo
96
+ # interior provado; 0 desliga a âncora)
97
+
98
+
99
+ @dataclass
100
+ class KHTSTConfig:
101
+ """Raiz do pacote — igual ao rascunho de referência + campos novos."""
102
+ jepa: JEPAConfig = field(default_factory=JEPAConfig)
103
+ k: TradeoffKConfig = field(default_factory=TradeoffKConfig)
104
+ lam: LambdaCConfig = field(default_factory=LambdaCConfig)
105
+ qect: QECTConfig = field(default_factory=QECTConfig)
106
+ diff: DifusaoConfig = field(default_factory=DifusaoConfig)
107
+ seed: int = 42
src/khtst/aprimoramento/controlador_hibrido.py ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """CONTROLADOR HÍBRIDO v17 — recursão unificada de autorregulação
3
+ (doc 29 §§2 e 10; Teoremas 29.14–29.16).
4
+
5
+ Recursão ÚNICA que governa todo parâmetro regulável θ (a mesma para os
6
+ ~20 parâmetros da tabela de sinais — AdamW, Muon, PRS V8, pesos de perda,
7
+ ABMO, CIAR, crescimento):
8
+
9
+ u_{t+1} = Π_[u_min,u_max] ( u_t + a_t·s_t + b·e_t + c·Δe_t ),
10
+ θ_t = θ₀ · exp(u_t), a_t = a₀/(1 + t/τ_a),
11
+
12
+ • a_t·s_t — termo ROBBINS–MONRO (aprendizado lento, ruído-tolerante).
13
+ Agenda a_t = a₀/(1+t/τ_a) satisfaz Σa_t = ∞ e Σa_t² < ∞ (Teo 28.5
14
+ reutilizado) — convergência q.c. ao ponto estacionário do campo.
15
+ • b·e_t — termo INTEGRAL (PI): e_t = erro normalizado ao alvo.
16
+ Empurra θ para o ALVO declarado (rastreio de setpoint) — corrige
17
+ viés de regime que o sinal RM demoraria a integrar.
18
+ • c·Δe_t — termo DERIVATIVO: Δe_t = e_t − e_{t−1}.
19
+
20
+ DUAS PROVAS QUE JUSTIFICAM A FORMA (Teo 29.14):
21
+ (i) TELESCOPING do D-termo: Σ_{t≤T} c·Δe_t = c·(e_T − e_0) — a
22
+ contribuição CUMULATIVA do termo derivativo é limitada por
23
+ 2c·sup|e| para TODO T, independentemente do horizonte. O D-termo
24
+ NUNCA desestabiliza a recursão (contrário do temor clássico).
25
+ (ii) DUAS ESCALAS (Borkar, Teo 28.6 generalizado): com a_t → 0
26
+ (escala LENTA) e ganhos b, c fixos (escala RÁPIDA), a dinâmica
27
+ separa: o laço PI rastreia o setpoint em tempo O(1) e o RM
28
+ converge sobre o equilíbrio já estabilizado. O erro estacionário
29
+ do laço PI com ganho b é |e_∞| = 0 para planta estática de
30
+ primeiro ordem com ganho finito (integral pura zera erro de
31
+ regime — argumento padrão de controle); o anti-windup (projeção +
32
+ congelamento do I fora da região segura) garante que o I-termo
33
+ não dispara além dos limites (Provar: u_t ∈ [u_min,u_max] ∀t por
34
+ indução — a projeção fecha a indução).
35
+
36
+ SEPARAÇÃO HONESTA: o termo RM sozinho (v16) converge ao estacionário
37
+ do CAMPO DE SINAIS, que pode ter viés de regime; o híbrido adiciona
38
+ rastreio de setpoint EXPLÍCITO. Quem define o setpoint é a tabela de
39
+ sinais (autorregulacao_estendida.py).
40
+ """
41
+ from __future__ import annotations
42
+
43
+ import math
44
+
45
+
46
+ class ControladorHibrido:
47
+ """θ_t = θ₀·exp(u_t) com recursão mista RM + PI projetada.
48
+
49
+ Args:
50
+ centro: θ₀ — valor de NASCIMENTO NEUTRO (u=0 ⟹ θ=θ₀; todas as
51
+ constantes atuais de produção são os centros da tabela).
52
+ limites: (θ_min, θ_max) ABSOLUTOS — segurança estrutural.
53
+ a0, tau_a: agenda RM a_t = a0/(1+t/τ_a) (Σa=∞, Σa²<∞).
54
+ passo_max: |Δu| máximo por passo (segurança multiplicativa).
55
+ b_i, c_d: ganhos integral e derivativo (0 = RM puro, v16).
56
+ alvo: setpoint do erro (se medida for passada).
57
+ escala_e: divisor para normalizar o erro (default: |alvo|).
58
+ espera: passos de aquecimento antes do 1º ajuste (Teo 28.5-ii).
59
+ """
60
+
61
+ def __init__(self, centro: float, limites: tuple[float, float],
62
+ a0: float = 0.05, tau_a: float = 400.0,
63
+ passo_max: float = 0.05, b_i: float = 0.0, c_d: float = 0.0,
64
+ alvo: float = 1.0, escala_e: float | None = None,
65
+ espera: int = 0):
66
+ assert limites[0] <= centro <= limites[1], "centro fora dos limites"
67
+ self.centro = float(centro)
68
+ self.limites = (float(limites[0]), float(limites[1]))
69
+ self.a0 = float(a0)
70
+ self.tau_a = float(tau_a)
71
+ self.passo_max = float(passo_max)
72
+ self.b_i = float(b_i)
73
+ self.c_d = float(c_d)
74
+ self.alvo = float(alvo)
75
+ self.escala_e = float(escala_e) if escala_e else max(abs(alvo), 1e-9)
76
+ self.espera = int(espera)
77
+ self.t = 0
78
+ self.u = 0.0
79
+ self.e_anterior: float | None = None
80
+ self.i_acum = 0.0 # anti-windup: I explícito e limitado
81
+
82
+ # ------------------------------------------------------------------
83
+ def erro(self, medida: float) -> float:
84
+ """e_t = (alvo − medida)/escala, clipado a ±2 (robustez a outliers)."""
85
+ e = (self.alvo - float(medida)) / self.escala_e
86
+ return max(-2.0, min(2.0, e))
87
+
88
+ def atualizar(self, sinal_rm: float, medida: float | None = None) -> float:
89
+ """Um passo da recursão híbrida (EXATAMENTE a forma do doc 29):
90
+
91
+ du = a_t·s_t + b·e_t + c·Δe_t (POR PASSO — sem dupla
92
+ integração: o I é o próprio b·e_t per-step; Σb·e_t é o
93
+ integral implícito da recursão, não um termo extra)
94
+
95
+ Retorna θ_t. sinal_rm ∈ [−1,1] (positivo ↑ θ). `medida` ativa o
96
+ laço PI quando dado. Anti-windup: o termo b·e_t NÃO integra
97
+ quando u está colado na parede NA DIREÇÃO do erro (empurrar
98
+ além da projeção seria enrolar o integral)."""
99
+ sinal_rm = max(-1.0, min(1.0, float(sinal_rm)))
100
+ self.t += 1
101
+ if self.t <= self.espera:
102
+ return self.valor
103
+ a_t = self.a0 / (1.0 + self.t / self.tau_a)
104
+ du = a_t * sinal_rm
105
+
106
+ if medida is not None and (self.b_i != 0.0 or self.c_d != 0.0):
107
+ e = self.erro(medida)
108
+ de = 0.0 if self.e_anterior is None else (e - self.e_anterior)
109
+ self.e_anterior = e
110
+ u_max, u_min = self._u_max(), self._u_min()
111
+ # anti-windup direcional: integra só se empurra PARA DENTRO
112
+ pode_integrar = (e > 0 and self.u > u_min + 1e-12) or \
113
+ (e < 0 and self.u < u_max - 1e-12) or e == 0.0
114
+ if pode_integrar:
115
+ du += self.b_i * e
116
+ self.i_acum += self.b_i * e # telemetria do integral
117
+ i_max = 2.0 * abs(self.b_i) + 1e-12
118
+ self.i_acum = max(-i_max, min(i_max, self.i_acum))
119
+ du += self.c_d * de
120
+ elif medida is not None:
121
+ # sem ganhos PI: apenas registra o erro para telemetria
122
+ self.e_anterior = self.erro(medida)
123
+
124
+ du = max(-self.passo_max, min(self.passo_max, du))
125
+ self.u += du
126
+ self.u = max(self._u_min(), min(self._u_max(), self.u))
127
+ return self.valor
128
+
129
+ def _u_min(self) -> float:
130
+ return math.log(self.limites[0] / self.centro)
131
+
132
+ def _u_max(self) -> float:
133
+ return math.log(self.limites[1] / self.centro)
134
+
135
+ @property
136
+ def valor(self) -> float:
137
+ v = self.centro * math.exp(self.u)
138
+ # clamp final: exp(log(b)) arredonda a b+ε — a permanência no
139
+ # conjunto seguro é EXATA (Teo 29.14-ii sem épsilon de flutuante)
140
+ return min(max(v, self.limites[0]), self.limites[1])
141
+
142
+ def telemetria(self) -> dict:
143
+ return {"valor": self.valor, "u": self.u, "t": self.t,
144
+ "e": self.e_anterior, "i": self.i_acum}
145
+
146
+
147
+ class ControladorBissecao:
148
+ """τ_qk por bisseção com banda-alvo (Teo 29.15).
149
+
150
+ Objetivo do usuário: manter o logit máximo ℓ_max na banda [lo, hi]
151
+ ajustando τ. Como o logit é LINEAR na escala de W_q (Teo 24.7 —
152
+ ℓ(γW) = γ·ℓ(W)), a correção multiplicativa exata é
153
+ τ ← τ·ℓ_alvo/ℓ_medida; com amortecimento η a convergência é
154
+ GEOMÉTRICA (razão |1−η| — mais forte que bisseção). O modo
155
+ "bissecao" puro mantém o colchete [τ_lo, τ_hi] e contrai pela
156
+ metade — erro ≤ (τ_max−τ_min)/2^k (forma do rascunho, mantida).
157
+ """
158
+
159
+ def __init__(self, tau_inicial: float = 100.0,
160
+ banda: tuple[float, float] = (80.0, 120.0),
161
+ modo: str = "escala", eta: float = 0.5,
162
+ tau_limites: tuple[float, float] = (40.0, 400.0)):
163
+ self.tau = float(tau_inicial)
164
+ self.banda = (float(banda[0]), float(banda[1]))
165
+ self.modo = modo
166
+ self.eta = float(eta)
167
+ self.limites = (float(tau_limites[0]), float(tau_limites[1]))
168
+ # colchete do modo bisseção: [já-seguro, já-inseguro]
169
+ self._colchete = (self.limites[0], self.limites[1])
170
+ self.k = 0
171
+ self.historico: list[float] = []
172
+
173
+ def atualizar(self, logit_max: float) -> float:
174
+ """Um passo: recebe ℓ_max medido, devolve o novo τ."""
175
+ lo, hi = self.banda
176
+ alvo = 0.5 * (lo + hi)
177
+ l = max(float(logit_max), 1e-9)
178
+ if self.modo == "escala":
179
+ # correção exata amortecida (Teo 29.15-i): ℓ linear em τ ⟹
180
+ # a razão^η leva ao ponto fixo; η=1 corrige em 1 passo
181
+ razao = alvo / l
182
+ self.tau *= razao ** self.eta
183
+ else:
184
+ # bisseção honesta no colchete (semântica PÓS-CLIP — Teo 24.7:
185
+ # ℓ_observado = min(ℓ_natural, τ)):
186
+ # ℓ > hi ⟹ τ ≥ ℓ > hi ⟹ τ ALTO demais ⟹ τ* está ABAIXO;
187
+ # ℓ < lo ⟹ τ < lo (clip nem atuou nessa faixa) ⟹ τ* está ACIMA.
188
+ t_lo, t_hi = self._colchete
189
+ if l > hi:
190
+ t_hi = min(t_hi, self.tau)
191
+ elif l < lo:
192
+ t_lo = max(t_lo, self.tau)
193
+ else:
194
+ # dentro da banda: encolhe o colchete em torno de τ
195
+ t_lo, t_hi = max(t_lo, self.tau * 0.5), min(t_hi, self.tau * 2.0)
196
+ self._colchete = (max(t_lo, self.limites[0]),
197
+ min(t_hi, self.limites[1]))
198
+ self.k += 1
199
+ self.tau = math.sqrt(self._colchete[0] * self._colchete[1])
200
+ self.tau = max(self.limites[0], min(self.limites[1], self.tau))
201
+ self.historico.append(self.tau)
202
+ if len(self.historico) > 512:
203
+ self.historico = self.historico[-256:]
204
+ return self.tau
205
+
206
+ def erro_colchete(self) -> float:
207
+ """Erro residual do colchete: ≤ (τ_max−τ_min)/2^k (Teo 29.15-ii)."""
208
+ return (self._colchete[1] - self._colchete[0]) / (2 ** max(1, self.k))
src/khtst/aprimoramento/difusao_gradiente.py ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """Difusão com gradiente — v17 refatorada (doc 29 §3).
3
+
4
+ DDPM padrão com DUAS correções estruturais sobre o rascunho (defeitos
5
+ D1/D2 do doc 29) e uma prova nova:
6
+
7
+ D1 (CÓDIGO MORTO — defeito real): no rascunho, `lambda_diff` era um
8
+ nn.Parameter com requires_grad=False, `AutoLambdaDiff.step` NUNCA era
9
+ chamado por nenhum caminho, e `treinar_difusao` nem sequer usava
10
+ λ_diff na perda. O "autoajuste por gradiente sobre validação"
11
+ anunciado no docstring era ficção tripla. Aqui:
12
+ (a) a perda ponderada é L(λ) = λ·L_diff + ρ·(λ−λ₀)² — o hiper-
13
+ gradiente é EXATO por ser L AFIM em λ: ∂L/∂λ = L_diff + 2ρ(λ−λ₀)
14
+ (Teo 29.2-i: zero erro de estimação, sem diferenças finitas);
15
+ (b) com ρ>0 (âncora), L(λ) é ESTRITAMENTE CONVEXA em λ com ótimo
16
+ interior FECHADO: λ* = λ₀ − L_diff/(2ρ), clipado a [λmin,λmax]
17
+ (Teo 29.2-iii). Sem âncora, L é afim e o ótimo está SEMPRE na
18
+ borda — o EG empurraria λ para o limite e ficaria lá (a âncora
19
+ é o que torna o autoajuste não-trivial);
20
+ (c) a atualização multiplicativa λ ← λ·exp(−η·g) é descida de
21
+ gradiente EXPLICITEIRA (mirror descent com potencial entropia):
22
+ regret ≤ η·G²T/2 + ln(λmax/λmin)/η, optimizado em η=Θ(T^{−1/2})
23
+ ⟹ regret O(√T) — Teo 29.2-ii (Cesa-Bianchi & Lugosi, Cap. 2,
24
+ rederivado no doc 29 para o intervalo clipado).
25
+
26
+ D2 (Polyak ausente): o rascunho amostra a rede crua. Aqui há EMA de
27
+ pesos opcional para amostragem/avaliação — Teo 29.3 (Polyak/Jensen):
28
+ para L convexa em θ, L(θ̄_T) ≤ (1/T)ΣL(θ_t) — a média nunca é pior
29
+ que a média das perdas e remove o ruído de alta frequência do
30
+ caminho SGD (variância do estimador reduzida pelo fator 1/(1−m)
31
+ do EMA; ver doc 29 §3.3).
32
+
33
+ Corretude do núcleo DDPM (reprovada por completude, Teo 29.1):
34
+ q(x_t|x₀) = N(√ᾱ_t·x₀, (1−ᾱ_t)·I) por indução sobre ᾱ_t = ∏_{s≤t}α_s
35
+ (Ho et al. 2020, Lemma 1 — a perda ε é o limite variacional superior
36
+ reponderado; rederivação no doc 29 §3.1). O amostrador inverte a
37
+ média a posteriori q(x_{t−1}|x_t,x₀) com σ_t = √β_t.
38
+ """
39
+ from __future__ import annotations
40
+
41
+ import math
42
+ from dataclasses import dataclass
43
+
44
+ import torch
45
+ import torch.nn as nn
46
+ import torch.nn.functional as F
47
+
48
+ from .config import DifusaoConfig
49
+
50
+
51
+ class DenoiserMLP(nn.Module):
52
+ def __init__(self, dim: int, hidden: int = 512):
53
+ super().__init__()
54
+ self.t_proj = nn.Sequential(nn.Linear(1, hidden), nn.GELU(),
55
+ nn.Linear(hidden, hidden))
56
+ self.net = nn.Sequential(
57
+ nn.Linear(dim + hidden, hidden), nn.GELU(),
58
+ nn.Linear(hidden, hidden), nn.GELU(),
59
+ nn.Linear(hidden, dim),
60
+ )
61
+
62
+ def forward(self, x_t, t):
63
+ t_norm = t.float().unsqueeze(-1) / 1000.0
64
+ h_t = self.t_proj(t_norm)
65
+ return self.net(torch.cat([x_t, h_t], dim=-1))
66
+
67
+
68
+ class DifusaoDDPM(nn.Module):
69
+ def __init__(self, dim: int, cfg: DifusaoConfig):
70
+ super().__init__()
71
+ self.cfg = cfg
72
+ self.net = DenoiserMLP(dim)
73
+ betas = torch.linspace(cfg.beta_start, cfg.beta_end, cfg.T)
74
+ alphas = 1.0 - betas
75
+ alpha_bar = torch.cumprod(alphas, dim=0)
76
+ self.register_buffer("betas", betas)
77
+ self.register_buffer("alphas", alphas)
78
+ self.register_buffer("alpha_bar", alpha_bar)
79
+ # D1 corrigido: λ_diff é um TENSOR PLANO governado pelo controlador
80
+ # (não parâmetro — autograd não devetocá-lo; o hipergradiente é
81
+ # EXATO e analítico: ∂L/∂λ = L_diff + 2ρ(λ−λ₀), Teo 29.2-i)
82
+ self.lambda_diff = torch.tensor(float(cfg.lambda_diff))
83
+ self.rho_ancora = float(cfg.rho_ancora)
84
+ self.lambda0 = float(cfg.lambda_diff)
85
+ # D2: EMA de pesos (Polyak) — nascimento neutro (default off)
86
+ self._ema: dict[str, torch.Tensor] | None = None
87
+
88
+ # -------------------------------------------------------------- núcleo
89
+ def q_sample(self, x0, t, noise=None):
90
+ if noise is None:
91
+ noise = torch.randn_like(x0)
92
+ ab = self.alpha_bar[t].view(-1, 1)
93
+ return ab.sqrt() * x0 + (1 - ab).sqrt() * noise, noise
94
+
95
+ def loss(self, x0: torch.Tensor) -> torch.Tensor:
96
+ """L_diff = E ‖ε − ε_θ(x_t, t)‖² (Teo 29.1)."""
97
+ B = x0.shape[0]
98
+ t = torch.randint(0, self.cfg.T, (B,), device=x0.device)
99
+ x_t, noise = self.q_sample(x0, t)
100
+ pred = self.net(x_t, t)
101
+ return F.mse_loss(pred, noise)
102
+
103
+ def loss_ponderada(self, x0: torch.Tensor) -> tuple[torch.Tensor, dict]:
104
+ """L(λ) = λ·L_diff + ρ·(λ−λ₀)² — AFIM + âncora em λ (Teo 29.2).
105
+
106
+ Devolve (perda escalável, telemetria com o hipergradiente EXATO).
107
+ O gradiente flui para a REDE por λ·L_diff e para λ pelo ramo da
108
+ âncora (implementado como tensor com requires_grad no caminho)."""
109
+ lam = torch.tensor(float(self.lambda_diff), requires_grad=True)
110
+ l_diff = self.loss(x0)
111
+ l_total = lam * l_diff
112
+ if self.rho_ancora > 0:
113
+ l_total = l_total + self.rho_ancora * (lam - self.lambda0) ** 2
114
+ # hipergradiente EXATO (sem autograd no λ — forma fechada):
115
+ g = float(l_diff.detach()) + 2.0 * self.rho_ancora \
116
+ * (float(lam.detach()) - self.lambda0)
117
+ return l_total, {"lambda_diff": float(lam.detach()),
118
+ "hipergradiente": g,
119
+ "perda_difusao": float(l_diff.detach())}
120
+
121
+ @torch.no_grad()
122
+ def sample(self, shape, device="cpu"):
123
+ x = torch.randn(shape, device=device)
124
+ for t in reversed(range(self.cfg.T)):
125
+ tt = torch.full((shape[0],), t, device=device, dtype=torch.long)
126
+ eps = self.net(x, tt)
127
+ a, ab = self.alphas[t], self.alpha_bar[t]
128
+ x = (x - (1 - a) / (1 - ab).sqrt() * eps) / a.sqrt()
129
+ if t > 0:
130
+ x = x + self.betas[t].sqrt() * torch.randn_like(x)
131
+ return x
132
+
133
+ # ------------------------------------------------ D2: EMA (Polyak) ----
134
+ @torch.no_grad()
135
+ def ema_atualizar(self, m: float = 0.999) -> float:
136
+ """EMA dos pesos do denoiser (Teo 29.3 — Polyak)."""
137
+ if self._ema is None:
138
+ self._ema = {k: v.detach().clone()
139
+ for k, v in self.net.state_dict().items()}
140
+ return m
141
+ for k, v in self.net.state_dict().items():
142
+ if v.dtype.is_floating_point:
143
+ self._ema[k].mul_(m).add_(v.detach(), alpha=1.0 - m)
144
+ else:
145
+ self._ema[k].copy_(v)
146
+ return m
147
+
148
+ @torch.no_grad()
149
+ def carregar_ema(self) -> bool:
150
+ """Promove os pesos EMA a pesos correntes (avaliação/amostragem)."""
151
+ if not self._ema:
152
+ return False
153
+ self.net.load_state_dict(self._ema)
154
+ return True
155
+
156
+
157
+ # ------------------------- autoajuste de λ_diff (D1 VIVO) -----------------
158
+
159
+ @dataclass
160
+ class AutoLambdaDiff:
161
+ """Descida multiplicativa (EG) de λ com hipergradiente EXATO + âncora.
162
+
163
+ Atualização: λ ← clip( λ·exp(−η·g), λmin, λmax ),
164
+ g = L_diff + 2ρ(λ−λ₀) (Teo 29.2-i — EXATO, L afim+quadrática)
165
+
166
+ Teo 29.2-ii (regret do EG, intervalo clipado): para L convexa com
167
+ |∂L/∂λ| ≤ G e λ ∈ [λmin,λmax], o regret cumulativo obedece
168
+ R_T ≤ η·G²·T/2 + ln(λmax/λmin)/η ≤ G·√(2·T·ln(λmax/λmin))
169
+ com η* = √(2·ln(λmax/λmin)/(G²T) — perda média ≤ ótimo + O(1/√T).
170
+ Teo 29.2-iii: com ρ>0, λ* = clip(λ₀ − L_diff/(2ρ)) é o ÚNICO
171
+ minimizador (L''=2ρ>0) — o controlador tem ÓTIMO INTERIOR provado
172
+ e o EG converge para a sua vizinhança O(η·G).
173
+ """
174
+
175
+ def __init__(self, valor_inicial: float, eta: float = 0.05,
176
+ rho_ancora: float = 1.0, lambda0: float | None = None,
177
+ limites: tuple[float, float] = (1e-4, 1.0)):
178
+ self.valor = float(valor_inicial)
179
+ self.eta = float(eta)
180
+ self.rho = float(rho_ancora)
181
+ self.lambda0 = float(lambda0) if lambda0 is not None else self.valor
182
+ self.limites = (float(limites[0]), float(limites[1]))
183
+ self.historico: list[float] = [self.valor]
184
+
185
+ def passo_analitico(self, l_diff: float) -> float:
186
+ """Passo FECHADO (âncora ρ>0): vai direto ao λ* clipado.
187
+ λ* = λ₀ − L_diff/(2ρ) — minimizador exato de L(λ) (Teo 29.2-iii).
188
+ Custo O(1), sem taxa de aprendizado — preferível quando a âncora
189
+ está ativa e L_diff é estável na janela."""
190
+ if self.rho <= 0:
191
+ return self.passo_eg(l_diff)
192
+ alvo = self.lambda0 - float(l_diff) / (2.0 * self.rho)
193
+ self.valor = max(self.limites[0], min(self.limites[1], alvo))
194
+ self.historico.append(self.valor)
195
+ return self.valor
196
+
197
+ def passo_eg(self, grad_lambda: float) -> float:
198
+ """Passo EG multiplicativo (Teo 29.2-ii) — usado com ρ=0 ou como
199
+ suavização. grad_lambda = ∂L/∂λ (exato pela forma fechada)."""
200
+ self.valor *= math.exp(-self.eta * float(grad_lambda))
201
+ self.valor = max(self.limites[0], min(self.limites[1], self.valor))
202
+ self.historico.append(self.valor)
203
+ return self.valor
204
+
205
+ # compatibilidade com o rascunho (assinatura antiga `step`)
206
+ def step(self, grad_lambda: float) -> float:
207
+ return self.passo_eg(grad_lambda)
208
+
209
+
210
+ def treinar_difusao(
211
+ modelo: DifusaoDDPM,
212
+ data: torch.Tensor,
213
+ passos: int = 2000,
214
+ lr: float = 1e-3,
215
+ device: str = "cpu",
216
+ ema: float = 0.0, # D2: >0 ativa EMA (default off = rascunho)
217
+ lambda_auto: AutoLambdaDiff | None = None, # D1: λ vivo opt-in
218
+ a_cada: int = 50,
219
+ ) -> list[float]:
220
+ """Loop de treino real com gradiente + autoajuste de λ vivo (D1).
221
+
222
+ λ_diff entra na perda via loss_ponderada; a cada `a_cada` passos o
223
+ controlador recebe o hipergradiente EXATO (Teo 29.2-i)."""
224
+ modelo.to(device).train()
225
+ opt = torch.optim.AdamW(modelo.net.parameters(), lr=lr)
226
+ historico: list[float] = []
227
+ for i in range(passos):
228
+ idx = torch.randint(0, data.shape[0], (64,), device=device)
229
+ x0 = data[idx].to(device)
230
+ if lambda_auto is not None:
231
+ l_total, tele = modelo.loss_ponderada(x0)
232
+ modelo.lambda_diff = torch.tensor(tele["lambda_diff"])
233
+ if (i + 1) % a_cada == 0:
234
+ lambda_auto.passo_analitico(tele["perda_difusao"])
235
+ else:
236
+ l_total = modelo.loss(x0)
237
+ opt.zero_grad(set_to_none=True)
238
+ l_total.backward()
239
+ opt.step()
240
+ if ema > 0:
241
+ modelo.ema_atualizar(ema)
242
+ historico.append(float(l_total.detach()))
243
+ return historico
src/khtst/aprimoramento/jepa.py ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """JEPA — v17 refatorada (doc 29 §7). Quatro correções sobre o rascunho:
3
+
4
+ D10 (CONDICIONAL MORTO): `z_t_p = self._project(z_t) if self.cfg.use_sg
5
+ else self._project(z_t)` — os DOIS ramos eram idênticos. Removido;
6
+ o stop-gradient é aplicado UMA vez, explicitamente.
7
+
8
+ D11 (VARIÂNCIA AGRUPADA — anti-colapso fraco): o rascunho calculava
9
+ `z.var(dim=(-2,-1))` — variância POOLADA sobre (T,D) e depois
10
+ média no lote. O hinge de VICReg é POR DIMENSÃO. Teo 29.10 (Jensen):
11
+ E_dims[relu(γ − σ_j)] ≥ relu(γ − E_dims[σ_j])
12
+ — o hinge POR DIMENSÃO é SEMPRE ≥ o poolado, com desigualdade
13
+ ESTRITA quando as dimensões têm desvios heterogêneos. Contraexemplo
14
+ concreto: dims com σ = (2, 0) — a variância poolada é grande, o
15
+ hinge poolado vale 0 e a dimensão B colapsada fica INVISÍVEL; o
16
+ per-dimensão cobra relu(1−0) = 1 dela. O colapso parcial (pior
17
+ caso prático — dims mortas que carregam informação perdida) só é
18
+ visto pelo per-dimensão.
19
+
20
+ D12 (TRUNCAMENTO DE COMPRIMENTO): o rascunho truncava para
21
+ L = min(Tc, Tt) — descartava a energia das posições além de L.
22
+ Correção (Teo 29.11): pooling adaptativo por média para o
23
+ comprimento comum — projeção L2 sobre o espaço mais grosso
24
+ (P² = P, P = Pᵀ ⟹ não-expansiva: ‖Pz‖ ≤ ‖z‖). O truncamento tem
25
+ erro de descarte E_trunc = Σ_{t>L}‖z_t‖²/E‖z‖² ≥ 0 enquanto o
26
+ pooling tem erro de resolução — dominado pelo de descarte quando
27
+ a energia é espalhada (caso típico de representações treinadas).
28
+
29
+ D13 (PESOS MORTOS): `cfg.lambda_jepa` (0.5) existia no config e NUNCA
30
+ era usado; o peso da variância era 0.01 hard-coded. Agora:
31
+ L_total = λ_jepa·L_alinhamento + peso_var·L_variância
32
+ com os dois pesos lidos do config (nascimento neutro: os defaults
33
+ λ=0.5, peso_var=0.01 reproduzem o rascunho quando λ_jepa=1 ... e o
34
+ caso λ=0.5 é o novo default DOCUMENTADO — o comportamento do
35
+ rascunho corresponde a λ_jepa=1.0, que o teste de regressão fixa).
36
+
37
+ Teo 29.12 (EMA cosseno — opt-in): m_t = 1 − (1−m₀)·(cos(πt/T)+1)/2
38
+ nasce em m₀ (alvo segue o encoder no arranque) e cresce
39
+ monotonamente até 1 (alvo congela quando a representação já
40
+ convergiu). Variância do ruído do alvo por passo: σ²_eff =
41
+ ((1−m)/(1+m))·σ² — DECREASE com m (alvo mais silencioso no fim).
42
+
43
+ Teo 29.13 (COLAPSO NÃO É MÍNIMO LOCAL): no ponto colapsado (z constante),
44
+ o MSE é plano a 1ª ordem mas o hinge de variância está no MÁXIMO
45
+ (σ_j=0 ⟹ relu(γ−0)=γ) e qualquer perturbação o diminui ⟹ o colapso
46
+ não é mínimo local de L_total e a descida escapa. HONESTIDADE: em
47
+ σ=0 exato há kink (subdiferencial) — o autograd pode dar 0 no ponto
48
+ exato; a fuga é geométrica e a produção empurra a direção
49
+ explicitamente (yc/σ² do FunilLatente). peso_var > 0 é NECESSÁRIO.
50
+
51
+ Cython prioritário (requisito do projeto): quando `cfg.vicreg_lambda>0`
52
+ e o kernel compilado `khtst.treino.jepa_cython.vicreg_cython`
53
+ estiver disponível, o termo VICReg completo (invariância + variância
54
+ + covariância) é delegado a ele; fallback PyTorch honesto.
55
+ """
56
+ from __future__ import annotations
57
+
58
+ import copy
59
+ import math
60
+ from typing import Optional
61
+
62
+ import torch
63
+ import torch.nn as nn
64
+ import torch.nn.functional as F
65
+
66
+ from .config import JEPAConfig
67
+
68
+ try: # Cython prioritário — a ponte tem fallback PyTorch com as MESMAS
69
+ # convenções (import da ponte, não do kernel cru: degradação honesta)
70
+ from khtst.treino.jepa_cython import vicreg_cython as _vicreg_kernel
71
+ _TEM_VICREG = True
72
+ except Exception: # pragma: no cover
73
+ _vicreg_kernel = None
74
+ _TEM_VICREG = False
75
+
76
+
77
+ class MLP(nn.Module):
78
+ def __init__(self, dim_in: int, dim_hidden: int, dim_out: int):
79
+ super().__init__()
80
+ self.net = nn.Sequential(
81
+ nn.Linear(dim_in, dim_hidden),
82
+ nn.GELU(),
83
+ nn.LayerNorm(dim_hidden),
84
+ nn.Linear(dim_hidden, dim_hidden),
85
+ nn.GELU(),
86
+ nn.Linear(dim_hidden, dim_out),
87
+ )
88
+
89
+ def forward(self, x):
90
+ return self.net(x)
91
+
92
+
93
+ class Encoder(nn.Module):
94
+ """Encoder genérico — substitua por Mamba-3 + atenção em produção."""
95
+
96
+ def __init__(self, vocab: int, dim: int, n_layers: int = 4):
97
+ super().__init__()
98
+ self.emb = nn.Embedding(vocab, dim)
99
+ self.layers = nn.ModuleList([
100
+ nn.TransformerEncoderLayer(
101
+ d_model=dim, nhead=4, dim_feedforward=dim * 4,
102
+ batch_first=True, activation="gelu",
103
+ ) for _ in range(n_layers)
104
+ ])
105
+ self.norm = nn.LayerNorm(dim)
106
+
107
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
108
+ h = self.emb(x)
109
+ for layer in self.layers:
110
+ h = layer(h)
111
+ return self.norm(h)
112
+
113
+
114
+ # ------------------------------ termo de variância --------------------------
115
+
116
+ def hinge_variancia_por_dim(z: torch.Tensor, gamma: float = 1.0) -> torch.Tensor:
117
+ """Teo 29.10 — hinge de variância POR DIMENSÃO (anti-colapso forte).
118
+
119
+ z: (B, T, D) — achata para (B·T, D) e calcula σ_j por dimensão j
120
+ sobre o lote-tempo (populacional, correção=0 — mesma convenção
121
+ anti-NaN da v15.1: lote 1 não divide por zero)."""
122
+ flat = z.reshape(-1, z.shape[-1])
123
+ std = flat.std(dim=0, correction=0) + 1e-4
124
+ return F.relu(gamma - std).mean()
125
+
126
+
127
+ # ---------------------------------- JEPA ------------------------------------
128
+
129
+ class JEPA(nn.Module):
130
+ """Joint Embedding Predictive Architecture (v17)."""
131
+
132
+ def __init__(self, encoder: nn.Module, cfg: JEPAConfig):
133
+ super().__init__()
134
+ self.cfg = cfg
135
+ self.online = encoder
136
+ self.target = copy.deepcopy(encoder)
137
+ for p in self.target.parameters():
138
+ p.requires_grad_(False)
139
+ self.predictor = MLP(cfg.dim, cfg.pred_hidden, cfg.dim)
140
+ self.pos_proj = nn.Linear(cfg.dim, cfg.dim)
141
+ self._t_ema = 0
142
+
143
+ @torch.no_grad()
144
+ def update_target(self):
145
+ m = self.momentum_efetivo()
146
+ for po, pt in zip(self.online.parameters(), self.target.parameters()):
147
+ pt.mul_(m).add_(po.detach(), alpha=1.0 - m)
148
+ for bo, bt in zip(self.online.buffers(), self.target.buffers()):
149
+ bt.copy_(bo)
150
+
151
+ def momentum_efetivo(self) -> float:
152
+ """Teo 29.12 — agenda cosseno BYOL (opt-in) ou momentum fixo."""
153
+ m0 = self.cfg.ema_momentum
154
+ if not self.cfg.ema_cosseno:
155
+ return m0
156
+ # horizonte default: 100k passos (doc 29 §7.5); monótona m₀→1
157
+ T_h = 100_000
158
+ return 1.0 - (1.0 - m0) * (math.cos(math.pi * min(1.0, self._t_ema / T_h)) + 1.0) / 2.0
159
+
160
+ def _project(self, z: torch.Tensor) -> torch.Tensor:
161
+ return F.normalize(z, dim=-1) if self.cfg.normalize else z
162
+
163
+ @staticmethod
164
+ def _alinhar_comprimento(z_hat: torch.Tensor,
165
+ z_t: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
166
+ """Teo 29.11 — pooling adaptativo (substitui o truncamento D12)."""
167
+ if z_hat.shape[1] == z_t.shape[1]:
168
+ return z_hat, z_t
169
+ L = min(z_hat.shape[1], z_t.shape[1])
170
+ # (B, T, D) → (B, D, T) → avg_pool1d → (B, D, L) → (B, L, D)
171
+ def pool(z):
172
+ return F.adaptive_avg_pool1d(z.transpose(1, 2), L).transpose(1, 2)
173
+ return pool(z_hat), pool(z_t)
174
+
175
+ def forward(
176
+ self,
177
+ ctx: torch.Tensor,
178
+ tgt: torch.Tensor,
179
+ pos_emb: Optional[torch.Tensor] = None,
180
+ ) -> dict:
181
+ cfg = self.cfg
182
+ z_c = self.online(ctx) # (B, Tc, D)
183
+ # D10 corrigido: stop-gradient explícito e ÚNICO (o rascunho tinha
184
+ # um condicional com os dois ramos idênticos)
185
+ with torch.no_grad():
186
+ z_t = self.target(tgt) # (B, Tt, D)
187
+ z_t_p = self._project(z_t)
188
+
189
+ if pos_emb is None:
190
+ pos_emb = torch.zeros_like(z_c)
191
+ else:
192
+ pos_emb = self.pos_proj(pos_emb)
193
+
194
+ z_hat = self.predictor(z_c + pos_emb) # (B, Tc, D)
195
+ z_hat_p = self._project(z_hat)
196
+
197
+ # D12 corrigido: pooling adaptativo em vez de truncamento
198
+ z_hat_p, z_t_p = self._alinhar_comprimento(z_hat_p, z_t_p)
199
+
200
+ # D13 corrigido: pesos do CONFIG (λ_jepa era campo morto; 0.01
201
+ # era constante solta — agora peso_var do config)
202
+ mse = F.mse_loss(z_hat_p, z_t_p)
203
+ var_hat = hinge_variancia_por_dim(z_hat_p, 1.0)
204
+ var_tgt = hinge_variancia_por_dim(z_t_p, 1.0)
205
+ var_loss = var_hat + var_tgt
206
+
207
+ total = cfg.lambda_jepa * mse + cfg.peso_var * var_loss
208
+
209
+ # Cython prioritário: VICReg completo (invariância+var+cov) opt-in
210
+ vic_tele: dict = {}
211
+ if cfg.vicreg_lambda > 0.0 and _TEM_VICREG:
212
+ B, T, D = z_hat_p.shape
213
+ P = z_hat_p.reshape(-1, D)
214
+ Z = z_t_p.reshape(-1, D)
215
+ try:
216
+ L_v, partes = _vicreg_kernel(P, Z, 1.0, cfg.vicreg_mu,
217
+ cfg.vicreg_gamma)
218
+ total = total + cfg.vicreg_lambda * L_v
219
+ vic_tele = dict(partes)
220
+ except Exception as e: # pragma: no cover
221
+ vic_tele = {"motor": "fallback", "erro": str(e)}
222
+
223
+ # Teo 29.13 — telemetria do colapso: variância média por dimensão
224
+ with torch.no_grad():
225
+ std_por_dim = z_hat_p.reshape(-1, z_hat_p.shape[-1]).std(0, correction=0)
226
+ frac_colapsada = float((std_por_dim < 1e-2).float().mean())
227
+
228
+ self._t_ema += 1
229
+ return {"loss": total, "mse": mse.detach(), "var": var_loss.detach(),
230
+ "mu_ema": self.momentum_efetivo(),
231
+ "frac_colapsada": frac_colapsada,
232
+ "cython": _TEM_VICREG, **vic_tele}
233
+
234
+ def training_step(self, ctx, tgt, pos_emb=None) -> dict:
235
+ out = self.forward(ctx, tgt, pos_emb)
236
+ self.update_target()
237
+ return out
src/khtst/aprimoramento/lambda_c_unificado.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """Autoajuste unificado de λ_c — v17 refatorada (doc 29 §5).
3
+
4
+ Elimina divergência entre caminho Cython (rápido) e Python (referência).
5
+ Fonte única: este módulo. `patches/correcoes.py` mantém a EQUAÇÃO
6
+ ESPECTRAL (intervalo do joelho — v15.1); ESTE módulo é o CONTROLADOR
7
+ TEMPORAL que rastreia o alvo ao longo do treino — as duas camadas são
8
+ complementares e a suíte v17 testa as duas.
9
+
10
+ Regra (v17, com os DOIS defeitos do rascunho corrigidos):
11
+
12
+ λ_c(t+1) = clip( λ_c(t) · exp( −η_t · Δ(t) ), λ_min, λ_max )
13
+
14
+ D6 (SINAL MORTO — defeito real): o rascunho computava a média móvel
15
+ `media` da janela e NUNCA a usava — o delta era o ε² INSTANTÂNEO,
16
+ com toda a variância amostral do passo. Correção (Teo 29.7-i):
17
+ modo="alvo": Δ(t) = ε̄²(t) − ε²_alvo
18
+ modo="reversao": Δ(t) = ε̄²(t) − média_janela(ε²)
19
+ com ε̄²(t) = média móvel da janela `janela`. REDUÇÃO DE VARIÂNCIA
20
+ provada: para amostras i.i.d. com variância σ², Var(média de W) =
21
+ σ²/W (Teo 29.7-i) — o sinal do controlador fica W vezes mais
22
+ quieto sem viés (média não-enviesada); Chebyshev:
23
+ P(|ε̄²−μ|>t) ≤ σ²/(W·t²).
24
+
25
+ D7 (PASSO CONSTANTE): η fixo só garante convergência a uma
26
+ VIZINHANÇA O(η) do ponto fixo. Correção (Teo 29.7-ii): modo
27
+ `eta_agendado=True` usa η_t = η₀/(1+t/τ) — satisfaz Ση_t = ∞ e
28
+ Ση_t² < ∞ ⟹ convergência q.c. (Robbins–Monro; Teo 28.5 reutilizado
29
+ — o campo de deriva b(u) = −η₀·Δ(ε̄²(u)) é Lipschitz no compacto
30
+ [λmin,λmax] e o ruído tem segundo momento finito).
31
+
32
+ Caminhos `fast_path_step`/`ref_path_step`: ref DELEGA a fast —
33
+ identidade bit-a-bit POR CONSTRUÇÃO, verificada numericamente a cada
34
+ suíte (n passos, max_diff == 0.0). A verificação SHA-256 das fontes é
35
+ mantida como auditoria (avisa divergência de arquivos, não é teste
36
+ matemático).
37
+ """
38
+ from __future__ import annotations
39
+
40
+ from collections import deque
41
+ from dataclasses import dataclass, field
42
+ from typing import Deque
43
+
44
+ import numpy as np
45
+
46
+ from .config import LambdaCConfig
47
+
48
+
49
+ @dataclass
50
+ class EstadoLambdaC:
51
+ valor: float = 0.5
52
+ historico: Deque[float] = field(default_factory=lambda: deque(maxlen=1000))
53
+ eps_medio: Deque[float] = field(default_factory=lambda: deque(maxlen=100))
54
+ passo: int = 0
55
+
56
+
57
+ class AutoAjusteLambdaC:
58
+ """Controlador temporal de λ_c com sinal suavizado VIVO (D6 corrigido)."""
59
+
60
+ def __init__(self, cfg: LambdaCConfig, eps_target: float = 1e-3):
61
+ self.cfg = cfg
62
+ self.eps_target = eps_target
63
+ self.estado = EstadoLambdaC(valor=0.5)
64
+
65
+ def step(self, eps2: float) -> float:
66
+ """Um passo com o sinal da média da janela (Teo 29.7-i).
67
+
68
+ Regressão do defeito: no rascunho, `media` era calculada e o
69
+ delta usava `eps2` cru — a suíte v17 prova que, com janela cuja
70
+ média difere do instante, ESTE controlador responde à média."""
71
+ cfg = self.cfg
72
+ self.estado.eps_medio.append(float(eps2))
73
+ if len(self.estado.eps_medio) >= cfg.janela:
74
+ media = float(np.mean(self.estado.eps_medio))
75
+ if cfg.modo == "reversao":
76
+ # reversão à média da janela: o INSTANTÂNEO acima da média
77
+ # da janela empurra λ para baixo (e vice-versa)
78
+ delta = float(eps2) - media
79
+ else:
80
+ # modo alvo: sinal SUAVIZADO (média da janela) vs alvo fixo
81
+ delta = media - self.eps_target
82
+ if cfg.eta_agendado:
83
+ self.estado.passo += 1
84
+ eta_t = cfg.eta / (1.0 + self.estado.passo / cfg.tau_eta)
85
+ else:
86
+ eta_t = cfg.eta
87
+ novo = self.estado.valor * float(np.exp(-eta_t * delta))
88
+ novo = float(np.clip(novo, cfg.lambda_c_min, cfg.lambda_c_max))
89
+ self.estado.valor = novo
90
+ self.estado.historico.append(self.estado.valor)
91
+ return self.estado.valor
92
+
93
+
94
+ # ------------------------- caminhos rápidos (equivalência) -----------------
95
+
96
+ def fast_path_step(lambda_prev: float, eps2: float, eps_target: float,
97
+ eta: float, lo: float, hi: float) -> float:
98
+ """Compilável com @cython.boundscheck(False). Aqui: numpy puro."""
99
+ delta = eps2 - eps_target
100
+ novo = lambda_prev * np.exp(-eta * delta)
101
+ if novo < lo:
102
+ novo = lo
103
+ if novo > hi:
104
+ novo = hi
105
+ return float(novo)
106
+
107
+
108
+ def ref_path_step(lambda_prev: float, eps2: float, eps_target: float,
109
+ eta: float, lo: float, hi: float) -> float:
110
+ """Referência Python — bit-a-bit idêntico ao fast (delega)."""
111
+ return fast_path_step(lambda_prev, eps2, eps_target, eta, lo, hi)
112
+
113
+
114
+ # ------------------------------- auditoria --------------------------------
115
+
116
+ def sha256(path: str) -> str:
117
+ import hashlib
118
+ import pathlib
119
+ return hashlib.sha256(pathlib.Path(path).read_bytes()).hexdigest()
120
+
121
+
122
+ def verificar_equivalencia_fontes(caminho_patch: str, caminho_quanta: str,
123
+ caminho_jepa: str) -> dict:
124
+ """Compara SHA-256 dos três arquivos (AUDITORIA de integridade —
125
+ avisa divergência; o teste matemático canônico é o numérico abaixo)."""
126
+ hashes = {
127
+ "patch": sha256(caminho_patch),
128
+ "quanta": sha256(caminho_quanta),
129
+ "jepa": sha256(caminho_jepa),
130
+ }
131
+ ok = len(set(hashes.values())) == 1
132
+ return {"ok": ok, **hashes}
133
+
134
+
135
+ def equivalencia_numerica(n: int = 10_000, seed: int = 42) -> dict:
136
+ """Roda n passos em ambos caminhos e compara bit-a-bit (Teo 29.7-iii:
137
+ a equivalência é POR CONSTRUÇÃO — ref delega a fast; o teste fixa a
138
+ propriedade contra regressões de refatoração)."""
139
+ rng = np.random.default_rng(seed)
140
+ lam_f, lam_r = 0.5, 0.5
141
+ max_diff = 0.0
142
+ for _ in range(n):
143
+ eps2 = float(rng.uniform(1e-5, 1e-2))
144
+ lam_f = fast_path_step(lam_f, eps2, 1e-3, 1e-3, 0.01, 0.99)
145
+ lam_r = ref_path_step(lam_r, eps2, 1e-3, 1e-3, 0.01, 0.99)
146
+ max_diff = max(max_diff, abs(lam_f - lam_r))
147
+ return {"passos": n, "max_diff": max_diff, "identico": max_diff == 0.0}
src/khtst/aprimoramento/metricas_qe_ct.py ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """Métricas QE + CT — v17 refatorada (doc 29 §4).
3
+
4
+ Substitutos do Erro Topológico (TE) com TRÊS correções sobre o rascunho
5
+ (defeitos D3/D4/D5 do doc 29):
6
+
7
+ D3 (ESCALA DEPENDENTE DA DIMENSÃO): o CT do rascunho somava ‖Δz‖² sobre
8
+ TODOS os eixos (B·D), logo crescia linearmente com B e D — dois
9
+ experimentos com dimensões diferentes eram incomparáveis. Correção
10
+ (Teo 29.4): CT_norm = Σ_t w_t·‖z_t − z_{t−1}‖²/(B·D) — energia de
11
+ deriva POR COORDENADA, invariante a mudança de lote/dimensão.
12
+ Prova da invariância: com z' = reindexação de z em (T, B'·D'),
13
+ ‖Δz'‖² = (B'D'/BD)·‖Δz‖² (partição das coordenadas) ⟹ o quociente
14
+ é idêntico — CT_norm não vê a fatoração do eixo de características.
15
+
16
+ D4 (CONJUNÇÃO SEM SIGNIFICÂNCIA): `ganho = (Δ_QE < −ε) and (Δ_CT < −ε)`
17
+ com ε fixo é um teste de hipótese implícito SEM nível controlado —
18
+ com N amostras ruidosas, a taxa de falso-positivo não é limitada.
19
+ Correção (Teo 29.5): declara ganho real só se o limite superior de
20
+ confiança 1−α_f da MÉDIA de cada delta for < 0:
21
+ Student-t (default): UCB(Δ̄) = Δ̄_N + t_{1−α_f,N−1}·s/√N
22
+ — válido assintoticamente pelo TCL, sem suposição de suporte;
23
+ Hoeffding (opcional, raio DECLARADO R no config):
24
+ UCB(Δ̄) = Δ̄_N + R·√(ln(1/α_f)/(2N)) — válido em amostra
25
+ finita SE R ≥ range verdadeiro (suposição explícita; usar o
26
+ range OBSERVADO NÃO é válido — subestima o suporte).
27
+ α_f = α/2 (União de Bonferroni): P(falso ganho) ≤ 2·α_f = α
28
+ (Teo 29.5-i). Complexidade de amostra (Teo 29.5-ii): para detectar
29
+ efeito t sob Hoeffding é preciso N ≥ R²·ln(1/α_f)/(2t²) — o `n_min`
30
+ do cfg implementa o piso mínimo declarado.
31
+
32
+ D5 (te_antigo O(N·G)): a distância de cada amostra a TODOS os centros
33
+ da grade era O(N·G). Correção: scipy.spatial.cKDTree — consulta
34
+ O(log G) por amostra, O(N·log G) total (Teo 29.6-i). Equivalência
35
+ de resultado: para centro mínimo ÚNICO, a consulta devolve o MESMO
36
+ índice do argmin (Teo 29.6-ii); empates têm medida zero sob grades
37
+ com perturbação contínua — e a versão KDTree documenta o tie-break.
38
+ """
39
+ from __future__ import annotations
40
+
41
+ from dataclasses import dataclass
42
+
43
+ import numpy as np
44
+
45
+ from .config import QECTConfig
46
+
47
+
48
+ @dataclass
49
+ class ResultadoQECT:
50
+ qe: float
51
+ ct: float
52
+ ganho_real: bool
53
+ delta_qe: float
54
+ delta_ct: float
55
+ # v17 — telemetria do teste de significância (Teo 29.5)
56
+ ucb_qe: float = 0.0
57
+ ucb_ct: float = 0.0
58
+ significativo: bool = False
59
+ n_amostras: int = 0
60
+
61
+
62
+ def erro_quantizacao(x: np.ndarray, x_hat: np.ndarray,
63
+ normalizar: bool = False) -> float:
64
+ """QE = (1/N)·Σ‖x − x̂‖²; com normalizar=True: QE/mean‖x‖² (D14 vivo).
65
+
66
+ Teo 29.4-i (invariância de escala): QE(αx, αx̂) = α²·QE(x, x̂) — o
67
+ QE relativo QE/mean‖x‖² é INVARIANTE a reescala global dos dados,
68
+ permitindo comparar camadas/épocas com energias distintas."""
69
+ assert x.shape == x_hat.shape, f"shapes {x.shape} vs {x_hat.shape}"
70
+ qe = float(np.mean(np.sum((x - x_hat) ** 2, axis=-1)))
71
+ if normalizar:
72
+ escala = float(np.mean(np.sum(x ** 2, axis=-1))) + 1e-12
73
+ qe = qe / escala
74
+ return qe
75
+
76
+
77
+ def consistencia_temporal(z: np.ndarray,
78
+ ocupacao: np.ndarray | None = None,
79
+ por_coordenada: bool = True) -> float:
80
+ """CT — deriva temporal ponderada por ocupação dos clusters.
81
+
82
+ z: (T, B, D) — representações latentes ao longo do tempo.
83
+ ocupacao: (T,) — ocupação do cluster em cada passo (padrão: uniforme).
84
+
85
+ v17 (Teo 29.4): por_coordenada=True divide por (B·D) — energia de
86
+ deriva POR COORDENADA, comparável entre configurações (correção D3).
87
+ O default preserva o valor ABSOLUTO do rascunho (comparabilidade de
88
+ regressão); os testes de ganho (avaliar_ganho) usam o normalizado.
89
+ """
90
+ T = z.shape[0]
91
+ if ocupacao is None:
92
+ ocupacao = np.ones(T, dtype=float)
93
+ w = ocupacao / (ocupacao.sum() + 1e-12)
94
+ drifts = np.sum((z[1:] - z[:-1]) ** 2, axis=(-1, -2)) # (T-1,)
95
+ ct = float(np.sum(w[1:] * drifts))
96
+ if por_coordenada:
97
+ # Teo 29.4-ii: média POR COORDENADA — os pesos w já normalizam o
98
+ # eixo temporal (Σw=1), resta dividir por B·D (NÃO por (T−1)·B·D)
99
+ ct = ct / max(z.shape[1] * z.shape[2], 1)
100
+ return ct
101
+
102
+
103
+ def _ucb_media(deltas: np.ndarray, alpha_f: float,
104
+ raio_declarado: float | None = None) -> float:
105
+ """UCB 1−α_f da média (Teo 29.5).
106
+
107
+ Default: Student-t — UCB = Δ̄ + t_{1−α_f,N−1}·s/√N (TCL; sem
108
+ suposição de suporte; honesto para N ≥ n_min). Se `raio_declarado`
109
+ for passado, usa Hoeffding finito: Δ̄ + R·√(ln(1/α_f)/(2N)) —
110
+ válido somente sob a suposição EXPLÍCITA R ≥ range verdadeiro
111
+ (o range observado NÃO serve: subestima o suporte e invalida a
112
+ cota — Teo 29.5-iii)."""
113
+ n = len(deltas)
114
+ if n == 0:
115
+ return float("inf")
116
+ media = float(np.mean(deltas))
117
+ if raio_declarado is not None and raio_declarado > 0:
118
+ t = float(raio_declarado) * np.sqrt(np.log(1.0 / max(alpha_f, 1e-12))
119
+ / (2.0 * n))
120
+ return media + t
121
+ from scipy import stats
122
+ s = float(np.std(deltas, ddof=1)) if n >= 2 else 0.0
123
+ tcrit = float(stats.t.ppf(1.0 - alpha_f, df=n - 1)) if n >= 2 else 0.0
124
+ return media + tcrit * s / np.sqrt(n)
125
+
126
+
127
+ def avaliar_ganho(
128
+ x: np.ndarray, x_hat_antes: np.ndarray, x_hat_depois: np.ndarray,
129
+ z_antes: np.ndarray, z_depois: np.ndarray,
130
+ cfg: QECTConfig,
131
+ ) -> ResultadoQECT:
132
+ """Avalia se houve ganho real segundo QE + CT com NÍVEL α (Teo 29.5).
133
+
134
+ ganho_real ⟺ UCB_{1−α/2}(Δ_QE) < 0 E UCB_{1−α/2}(Δ_CT) < 0 E n ≥ n_min
135
+ (conjunção com erro de família ≤ α pela União de Bonferroni — cada
136
+ delta testa no nível α/2)."""
137
+ norm = bool(getattr(cfg, "normalizar", False))
138
+ qe_a = erro_quantizacao(x, x_hat_antes, normalizar=norm)
139
+ qe_d = erro_quantizacao(x, x_hat_depois, normalizar=norm)
140
+ ct_a = consistencia_temporal(z_antes)
141
+ ct_d = consistencia_temporal(z_depois)
142
+
143
+ d_qe = qe_d - qe_a
144
+ d_ct = ct_d - ct_a
145
+
146
+ # amostras por passo: QE sobre N pontos; CT sobre (T−1) transições —
147
+ # o teste usa o MENOR n (honesto: o elo fraco comanda o nível)
148
+ n_qe = x.shape[0]
149
+ n_ct = max(z_antes.shape[0] - 1, 1)
150
+ n = min(n_qe, n_ct)
151
+
152
+ alpha_f = float(getattr(cfg, "alpha", 0.05)) / 2.0
153
+ # reconstrói as séries de deltas por amostra p/ Hoeffding:
154
+ # QE: erro quadrático por ponto; CT: deriva por transição.
155
+ e_qe_a = np.sum((x - x_hat_antes) ** 2, axis=-1)
156
+ e_qe_d = np.sum((x - x_hat_depois) ** 2, axis=-1)
157
+ if norm:
158
+ e_qe_a = e_qe_a / (np.sum(x ** 2, axis=-1).mean() + 1e-12)
159
+ e_qe_d = e_qe_d / (np.sum(x ** 2, axis=-1).mean() + 1e-12)
160
+ deltas_qe = e_qe_d - e_qe_a
161
+ dr_a = np.sum((z_antes[1:] - z_antes[:-1]) ** 2, axis=(-1, -2))
162
+ dr_d = np.sum((z_depois[1:] - z_depois[:-1]) ** 2, axis=(-1, -2))
163
+ T = z_antes.shape[0]
164
+ w = np.ones(T) / T
165
+ deltas_ct = w[1:] * (dr_d - dr_a)
166
+
167
+ ucb_qe = _ucb_media(deltas_qe, alpha_f)
168
+ ucb_ct = _ucb_media(deltas_ct, alpha_f)
169
+ n_min = int(getattr(cfg, "n_min", 32))
170
+ significativo = (ucb_qe < 0.0) and (ucb_ct < 0.0) and (n >= n_min)
171
+
172
+ # compatibilidade: limiares fixos continuam como condição NECESSÁRIA
173
+ # (não suficiente) — mantém a semântica do rascunho nos casos claros
174
+ ganho = significativo and (d_qe < -cfg.eps_qe) and (d_ct < -cfg.eps_ct)
175
+ return ResultadoQECT(qe_d, ct_d, bool(ganho), d_qe, d_ct,
176
+ ucb_qe=ucb_qe, ucb_ct=ucb_ct,
177
+ significativo=bool(significativo), n_amostras=int(n))
178
+
179
+
180
+ def te_antigo(x: np.ndarray, x_hat: np.ndarray, grid: np.ndarray) -> float:
181
+ """TE legado — distância média ao centro de grade mais próximo.
182
+
183
+ v17 (Teo 29.6): consulta via cKDTree — O((G+N)·log G) em vez de
184
+ O(N·G). Para centro mínimo único, devolve o MESMO valor do argmin
185
+ exaustivo (verificado bit-a-bit na suíte v17); empates exatos têm
186
+ medida zero sob grades contínuas e o tie-break do KDTree é
187
+ documentado (menor índice não garantido — diferença só em empate)."""
188
+ from scipy.spatial import cKDTree
189
+ arvore = cKDTree(grid)
190
+ d, _ = arvore.query(x, k=1)
191
+ return float(np.mean(d))
src/khtst/aprimoramento/tradeoff_k.py ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """Trade-off de K — v17 refatorada (doc 29 §6).
3
+
4
+ Métodos: RD (J1), assintótico (J2) e grade (auditoria).
5
+
6
+ NOVOS TEOREMAS desta revisão (provas completas no doc 29):
7
+
8
+ Teo 29.9-i (UNIMODALIDADE — garante que minimize_scalar bounded acha o
9
+ mínimo GLOBAL). Com ε²(K) = C·K^{−2/d} (Zador) e
10
+ J1(K) = (1−λ)·C·K^{−2/d} + λ·(log₂K + K·d/n)/log₂d,
11
+ a derivada é
12
+ J1'(K) = −(1−λ)C·p·K^{−p−1} + λ·(K^{−1}/ln2 + d/n)/log₂d, p = 2/d.
13
+ Multiplicando por K^{p+1} > 0:
14
+ G(K) = −(1−λ)C·p + λ·(K^p/ln2 + K^{p+1}·d/n)/log₂d.
15
+ G é ESTRITAMENTE CRESCENTE em K (K^p e K^{p+1} o são, coeficientes
16
+ > 0) ⟹ G tem no máximo uma raiz ⟹ J1' muda de sinal no máximo uma
17
+ vez. Como J1'(K) → −∞ quando K→0⁺ (K^{−p−1} domina K^{−1} pois
18
+ p+1 > 1) e J1'(K) → λ·d/(n·log₂d) ≥ 0 quando K→∞, J1 decresce e
19
+ depois cresce — MÍNIMO GLOBAL ÚNICO. Nenhuma aproximação.
20
+
21
+ Teo 29.9-ii (FORMA FECHADA no regime n→∞): G(K)=0 dá
22
+ K* = [ (1−λ)·2·C·ln d / (λ·d) ]^{d/2}
23
+ (usando ln2·log₂d = ln d). Usada como INITIALIZATION/bracket do
24
+ minimizador numérico e como sanity check (o teste v17 compara a
25
+ forma fechada com a raiz numérica — coincidência a 1e-6 relativo).
26
+
27
+ Teo 29.9-iii (SENSIBILIDADE — honestidade): da forma fechada,
28
+ ∂ln K*/∂ln C = d/2 — para d grande, K* é MUITO sensível a C. Por
29
+ isso Ĉ é estimado com SHRINKAGE ao prior: Ĉ = (n_C·Ĉ_ols + κ·C₀)/
30
+ (n_C + κ) — troca viés por variância com peso explícito (James–
31
+ Stein simplificado; o κ do config expõe o trade-off).
32
+
33
+ D8 (C=1 FIXO — defeito do rascunho): a constante de Zador depende da
34
+ DISTRIBUIÇÃO (segundo momento normalizado da célula de Voronoi —
35
+ nunca é 1 em dados reais). Correção (Teo 29.8): medir ε²(K) na
36
+ grade e ajustar OLS em log-log: ln ε² = ln C − (2/d)·ln K + r;
37
+ consistência por LLN (r média-zero i.i.d. ⟹ (Ĉ, p̂) → (C, 2/d));
38
+ a INCLINAÇÃO ESTIMADA p̂ serve de TESTE DO MODELO: |p̂ + 2/d| grande
39
+ ⟹ o modelo de Zador não vale para esses dados ⟹ cai para a grade
40
+ (honestidade metodológica, registrada na telemetria).
41
+
42
+ D9 (λ_c ESTÁTICO): o rascunho lia λ do config e nunca o atualizava;
43
+ agora `resolver_K` aceita λ_c adaptativo (saída do
44
+ AutoAjusteLambdaC — integração λ_c ↔ K* pela mesma unidade de
45
+ trade-off distorção×custo).
46
+ """
47
+ from __future__ import annotations
48
+
49
+ import math
50
+ from dataclasses import dataclass, field
51
+ from typing import Dict, Tuple
52
+
53
+ import numpy as np
54
+ from scipy.optimize import minimize_scalar
55
+
56
+ from .config import TradeoffKConfig
57
+
58
+
59
+ # ------------------ modelo de erro de quantização (Zador) ------------------
60
+
61
+ def epsilon_sq(K, d: int, C: float = 1.0):
62
+ """Erro de quantização empírico ~ C·K^{−2/d} (Zador, alta resolução).
63
+
64
+ Domínio: K ≥ 1 (o modelo não é definido abaixo do codebook unitário;
65
+ K<1 é clampeado — elimina NaN de potências fracionárias negativas)."""
66
+ K = np.asarray(K, dtype=float)
67
+ return C * np.maximum(K, 1.0) ** (-2.0 / d)
68
+
69
+
70
+ def estimar_C(K_medidos, e2_medidos, d: int, C_prior: float = 1.0,
71
+ kappa: int = 8) -> dict:
72
+ """Teo 29.8 — Ĉ por OLS log-log + teste do modelo + shrinkage.
73
+
74
+ Regressão: y_i = ln e2_i, x_i = ln K_i ⟹ y = a − p·x com a = ln C.
75
+ Ĉ_ols = exp(â); p̂ é a inclinação — se o modelo vale, p̂ ≈ 2/d.
76
+ Shrinkage: Ĉ = (n_C·Ĉ_ols + κ·C₀)/(n_C + κ)."""
77
+ K = np.asarray(K_medidos, dtype=float)
78
+ e2 = np.asarray(e2_medidos, dtype=float)
79
+ ok = (K > 0) & (e2 > 0)
80
+ K, e2 = K[ok], e2[ok]
81
+ n_c = int(K.size)
82
+ if n_c < 2:
83
+ return {"C": float(C_prior), "incl": float("nan"),
84
+ "modelo_ok": False, "n": n_c}
85
+ x, y = np.log(K), np.log(e2)
86
+ # OLS fechado (1D): y = a + b·x com b = incl ⟹ a = ȳ − b·x̄
87
+ # (C = exp(a); inclinação b ≈ −2/d se o modelo de Zador vale)
88
+ xm, ym = x.mean(), y.mean()
89
+ denom = float(((x - xm) ** 2).sum()) + 1e-12
90
+ incl = float(((x - xm) * (y - ym)).sum() / denom)
91
+ a = float(ym - incl * xm) # intercepto correto (y = a + b·x)
92
+ c_ols = math.exp(a)
93
+ modelo_ok = abs(incl + 2.0 / d) <= max(0.35, 0.5 * (2.0 / d))
94
+ c_shrunk = (n_c * c_ols + kappa * float(C_prior)) / (n_c + kappa)
95
+ return {"C": float(c_shrunk), "C_ols": float(c_ols),
96
+ "incl": incl, "modelo_ok": bool(modelo_ok), "n": n_c}
97
+
98
+
99
+ # --------------------------------- métodos ---------------------------------
100
+
101
+ def J1(K: float, d: int, n: int, lam: float, C: float = 1.0,
102
+ bits_por_param: float = 16.0) -> float:
103
+ """J1 = (1−λ)·ε²(K) + λ·(log₂K + K·d/n)/log₂d — com C estimado (D8)."""
104
+ eps = float(epsilon_sq(K, d, C))
105
+ bits = (np.log2(max(K, 2)) + K * d / n
106
+ * (bits_por_param / 16.0)) / np.log2(max(d, 2))
107
+ return (1 - lam) * eps + lam * bits
108
+
109
+
110
+ def J2(K: float, d: int, lam: float, C: float = 1.0) -> float:
111
+ eps = float(epsilon_sq(K, d, C))
112
+ return eps + lam * K / np.sqrt(d)
113
+
114
+
115
+ def k_star_fechado(d: int, lam: float, C: float = 1.0) -> float:
116
+ """Teo 29.9-ii — K* = [(1−λ)·2·C·ln d/(λ·d)]^{d/2} (regime n→∞)."""
117
+ if not (0.0 < lam < 1.0) or C <= 0 or d < 2:
118
+ return float("nan")
119
+ return ((1.0 - lam) * 2.0 * C * math.log(d) / (lam * d)) ** (d / 2.0)
120
+
121
+
122
+ def K_star_rd(cfg: TradeoffKConfig, C: float | None = None) -> float:
123
+ """Mínimo GLOBAL de J1 por minimize_scalar bounded (Teo 29.9-i garante
124
+ que o mínimo local é o global). Bracket centrado na forma fechada
125
+ quando disponível (Teo 29.9-ii) — acelera e ancora a busca."""
126
+ C = C if C is not None else 1.0
127
+ k_hint = k_star_fechado(cfg.d, cfg.lambda_c, C)
128
+ lo, hi = 4.0, 4096.0
129
+ if math.isfinite(k_hint) and k_hint > 0:
130
+ lo = max(4.0, k_hint / 8.0)
131
+ hi = min(4096.0, max(k_hint * 8.0, 32.0))
132
+ if lo >= hi:
133
+ lo, hi = 4.0, 4096.0
134
+ res = minimize_scalar(
135
+ lambda k: J1(k, cfg.d, cfg.n, cfg.lambda_c, C, cfg.bits_por_param),
136
+ bounds=(lo, hi), method="bounded",
137
+ )
138
+ return float(res.x)
139
+
140
+
141
+ def K_star_asymp(cfg: TradeoffKConfig, C: float | None = None) -> float:
142
+ C = C if C is not None else 1.0
143
+ res = minimize_scalar(
144
+ lambda k: J2(k, cfg.d, cfg.lambda_c, C),
145
+ bounds=(4, 4096), method="bounded",
146
+ )
147
+ return float(res.x)
148
+
149
+
150
+ def K_star_grid(cfg: TradeoffKConfig, C: float | None = None) -> float:
151
+ vals = [(k, J1(k, cfg.d, cfg.n, cfg.lambda_c, C, cfg.bits_por_param))
152
+ for k in cfg.K_grid]
153
+ return float(min(vals, key=lambda t: t[1])[0])
154
+
155
+
156
+ # ----------------------------- orquestrador --------------------------------
157
+
158
+ @dataclass
159
+ class ResultadoK:
160
+ K_rd: float
161
+ K_asymp: float
162
+ K_grid: float
163
+ divergencia: float
164
+ metodo_escolhido: str
165
+ K_final: float
166
+ tabela: Dict[str, float]
167
+ # v17 — telemetria da estimação de C (D8) e do modelo de Zador
168
+ C_estimado: float = 1.0
169
+ C_ols: float = 1.0
170
+ inclinacao: float = float("nan")
171
+ modelo_ok: bool = False
172
+ K_fechado: float = float("nan")
173
+
174
+
175
+ def medir_epsilon_sq(dados: np.ndarray, K_medidos, seed: int = 0) -> Tuple[np.ndarray, np.ndarray]:
176
+ """Mede ε²(K) REAL por quantização por k-means leve (Teo 29.8).
177
+
178
+ Usado quando `estimar_C=True` e dados estão disponíveis; sem dados,
179
+ o chamador pode passar pares (K, ε²) medidos por outra via (ex.:
180
+ espectro PCA via Eckart–Young — patches/correcoes.py)."""
181
+ Ks = np.asarray(list(K_medidos), dtype=int)
182
+ e2 = []
183
+ rng = np.random.default_rng(seed)
184
+ amostra = dados[np.random.default_rng(seed).choice(
185
+ dados.shape[0], size=min(4096, dados.shape[0]), replace=False)]
186
+ for k in Ks:
187
+ # k-means 1 inicialização + 8 iterações de Lloyd (leve, auditável)
188
+ centros = amostra[rng.choice(amostra.shape[0], size=k, replace=False)]
189
+ for _ in range(8):
190
+ d2 = ((amostra[:, None, :] - centros[None, :, :]) ** 2).sum(-1)
191
+ lab = d2.argmin(1)
192
+ for j in range(k):
193
+ pts = amostra[lab == j]
194
+ if len(pts):
195
+ centros[j] = pts.mean(0)
196
+ d2 = ((amostra[:, None, :] - centros[None, :, :]) ** 2).sum(-1)
197
+ e2.append(float(d2.min(1).mean()))
198
+ return Ks.astype(float), np.asarray(e2)
199
+
200
+
201
+ def resolver_K(cfg: TradeoffKConfig,
202
+ pares_medidos: Tuple[np.ndarray, np.ndarray] | None = None,
203
+ lambda_c_adaptativo: float | None = None) -> ResultadoK:
204
+ """Resolve K* com Ĉ estimado (D8) e λ_c adaptativo (D9).
205
+
206
+ pares_medidos: (K, ε²) medidos — alimenta o OLS de Ĉ. Sem eles e com
207
+ estimar_C=True, usa o prior (honesto: registra modelo_ok=False)."""
208
+ lam = float(lambda_c_adaptativo) if lambda_c_adaptativo is not None \
209
+ else float(cfg.lambda_c)
210
+ C_hat, C_ols, incl, modelo_ok = 1.0, 1.0, float("nan"), False
211
+ if cfg.estimar_C and pares_medidos is not None:
212
+ est = estimar_C(pares_medidos[0], pares_medidos[1], cfg.d,
213
+ cfg.C_prior, cfg.kappa_prior)
214
+ C_hat, C_ols, incl = est["C"], est["C_ols"], est["incl"]
215
+ modelo_ok = est["modelo_ok"]
216
+
217
+ cfg_lam = TradeoffKConfig(
218
+ d=cfg.d, n=cfg.n, lambda_c=lam, K_grid=cfg.K_grid,
219
+ tol_rel=cfg.tol_rel, metodo=cfg.metodo,
220
+ estimar_C=cfg.estimar_C, C_prior=cfg.C_prior,
221
+ kappa_prior=cfg.kappa_prior, bits_por_param=cfg.bits_por_param)
222
+
223
+ k_rd = K_star_rd(cfg_lam, C_hat)
224
+ k_as = K_star_asymp(cfg_lam, C_hat)
225
+ k_gr = K_star_grid(cfg_lam, C_hat)
226
+
227
+ div = abs(k_rd - k_as) / max(k_rd, 1e-9)
228
+
229
+ if cfg.metodo == "auto":
230
+ # Teo 29.8 (honestidade): modelo de Zador ruim ⟹ confia na grade
231
+ if (not modelo_ok) and pares_medidos is not None:
232
+ escolhido, k_final = "grid", k_gr
233
+ elif div < cfg.tol_rel:
234
+ escolhido, k_final = "rd", k_rd
235
+ else:
236
+ escolhido, k_final = "grid", k_gr
237
+ else:
238
+ escolhido = cfg.metodo
239
+ k_final = {"rd": k_rd, "asymp": k_as, "grid": k_gr}[cfg.metodo]
240
+
241
+ return ResultadoK(
242
+ K_rd=k_rd, K_asymp=k_as, K_grid=k_gr,
243
+ divergencia=div, metodo_escolhido=escolhido,
244
+ K_final=k_final,
245
+ tabela={str(k): J1(k, cfg.d, cfg.n, lam, C_hat, cfg.bits_por_param)
246
+ for k in cfg.K_grid},
247
+ C_estimado=float(C_hat), C_ols=float(C_ols),
248
+ inclinacao=float(incl), modelo_ok=bool(modelo_ok),
249
+ K_fechado=float(k_star_fechado(cfg.d, lam, C_hat)))
250
+
251
+
252
+ def validar_v15_1() -> Dict[int, Tuple[float, float]]:
253
+ """Compara K* bugado (b(K)=log₂K/log₂d) com K* corrigido (rate-distortion)."""
254
+ out = {}
255
+ for d in (64, 512, 4096):
256
+ def J_bug(k, d=d):
257
+ return float(epsilon_sq(k, d)) + 0.5 * np.log2(max(k, 2)) / np.log2(d)
258
+ r_bug = minimize_scalar(J_bug, bounds=(4, 512), method="bounded")
259
+ cfg = TradeoffKConfig(d=d, n=100_000, lambda_c=0.5)
260
+ r_fix = K_star_rd(cfg)
261
+ out[d] = (float(r_bug.x), float(r_fix))
262
+ return out
src/khtst/mamba3/__pycache__/hybrid.cpython-312.pyc DELETED
Binary file (19.8 kB)
 
src/khtst/mamba3/__pycache__/kernel.cpython-312.pyc DELETED
Binary file (6.12 kB)
 
src/khtst/mamba3/__pycache__/replay.cpython-312.pyc DELETED
Binary file (5 kB)
 
src/khtst/mamba3/hybrid.py CHANGED
@@ -37,11 +37,11 @@ import torch.nn.functional as F
37
  from torch.utils.checkpoint import checkpoint
38
 
39
  from khtst.mamba3.kernel import varredura_trapezoidal
40
- from khtst.mamba3.replay import varredura_replay
41
 
42
  __all__ = ["NoPEAtencao", "Mamba3Camada", "HybridMamba3Modelo",
43
  "eh_camada_atencao", "EstadoMamba3"]
44
 
 
45
  class EstadoMamba3:
46
  """Estado recorrente de UMA Mamba3Camada para decode INCREMENTAL
47
  (v12, Teorema 24.13 — equivalência exata com a varredura paralela):
@@ -141,15 +141,11 @@ class Mamba3Camada(nn.Module):
141
  """Camada MAMBA-3 com gate SiLU + pré-norm + residual (doc 22 §3)."""
142
 
143
  def __init__(self, d_modelo: int, d_estado: int = 16, rank_mimo: int = 4,
144
- kernel_conv: int = 4, replay_segmento: int = 0):
145
  super().__init__()
146
  self.d = d_modelo
147
  self.n = d_estado
148
  self.r = rank_mimo
149
- self.k_conv = kernel_conv
150
- # v17 (doc 29, Teos 29.13–29.14) — ReplaySSM: nº de segmentos da
151
- # varredura (0 = desligado ⟹ v12 exato, nascimento neutro)
152
- self.replay_segmento = int(replay_segmento)
153
  self.entrada_proj = nn.Linear(d_modelo, 2 * d_modelo, bias=False)
154
  self.conv1d = nn.Conv1d(d_modelo, d_modelo, kernel_size=kernel_conv,
155
  padding=0, groups=d_modelo) # causal manual
@@ -188,20 +184,7 @@ class Mamba3Camada(nn.Module):
188
  uc = F.pad(u.transpose(1, 2), (self.k_conv - 1, 0))
189
  uc = self.conv1d(uc).transpose(1, 2).contiguous() # (B,L,D)
190
  delta, B_m, C_m = self._projetos(uc)
191
- # v17 — ReplaySSM (Teos 29.13/29.14): varredura POR SEGMENTOS
192
- # com replay de estados fronteira (gradiente e saída EXATOS;
193
- # ativação O(S·BDN + L_s·BDN)). Só em treino com gradiente e
194
- # L > 1 — decode incremental (T=1) nunca segmenta.
195
- seg = int(getattr(self, "replay_segmento", 0) or 0)
196
- if seg > 1 and self.training and torch.is_grad_enabled() and L > seg:
197
- if devolve_estado:
198
- y, h_final = varredura_replay(uc, delta, self.A, B_m, C_m,
199
- n_segmentos=seg,
200
- devolve_estado=True)
201
- else:
202
- y = varredura_replay(uc, delta, self.A, B_m, C_m,
203
- n_segmentos=seg)
204
- elif devolve_estado:
205
  y, h_final = varredura_trapezoidal(uc, delta, self.A, B_m,
206
  C_m, devolve_estado=True)
207
  else:
@@ -254,7 +237,7 @@ class HybridMamba3Modelo(nn.Module):
254
 
255
  def __init__(self, d_modelo: int, n_camadas: int = 6, n_cabecas: int = 4,
256
  d_estado: int = 16, rank_mimo: int = 4,
257
- grad_checkpointing: bool = True, replay_segmento: int = 0):
258
  super().__init__()
259
  self.d = d_modelo
260
  self.n_camadas = n_camadas
@@ -265,8 +248,7 @@ class HybridMamba3Modelo(nn.Module):
265
  self.camadas.append(NoPEAtencao(d_modelo, n_cabecas))
266
  else:
267
  self.camadas.append(
268
- Mamba3Camada(d_modelo, d_estado, rank_mimo,
269
- replay_segmento=replay_segmento))
270
  self.norm_f = nn.RMSNorm(d_modelo)
271
 
272
  def _corre(self, x: torch.Tensor, tarefa=None) -> torch.Tensor:
 
37
  from torch.utils.checkpoint import checkpoint
38
 
39
  from khtst.mamba3.kernel import varredura_trapezoidal
 
40
 
41
  __all__ = ["NoPEAtencao", "Mamba3Camada", "HybridMamba3Modelo",
42
  "eh_camada_atencao", "EstadoMamba3"]
43
 
44
+
45
  class EstadoMamba3:
46
  """Estado recorrente de UMA Mamba3Camada para decode INCREMENTAL
47
  (v12, Teorema 24.13 — equivalência exata com a varredura paralela):
 
141
  """Camada MAMBA-3 com gate SiLU + pré-norm + residual (doc 22 §3)."""
142
 
143
  def __init__(self, d_modelo: int, d_estado: int = 16, rank_mimo: int = 4,
144
+ kernel_conv: int = 4):
145
  super().__init__()
146
  self.d = d_modelo
147
  self.n = d_estado
148
  self.r = rank_mimo
 
 
 
 
149
  self.entrada_proj = nn.Linear(d_modelo, 2 * d_modelo, bias=False)
150
  self.conv1d = nn.Conv1d(d_modelo, d_modelo, kernel_size=kernel_conv,
151
  padding=0, groups=d_modelo) # causal manual
 
184
  uc = F.pad(u.transpose(1, 2), (self.k_conv - 1, 0))
185
  uc = self.conv1d(uc).transpose(1, 2).contiguous() # (B,L,D)
186
  delta, B_m, C_m = self._projetos(uc)
187
+ if devolve_estado:
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  y, h_final = varredura_trapezoidal(uc, delta, self.A, B_m,
189
  C_m, devolve_estado=True)
190
  else:
 
237
 
238
  def __init__(self, d_modelo: int, n_camadas: int = 6, n_cabecas: int = 4,
239
  d_estado: int = 16, rank_mimo: int = 4,
240
+ grad_checkpointing: bool = True):
241
  super().__init__()
242
  self.d = d_modelo
243
  self.n_camadas = n_camadas
 
248
  self.camadas.append(NoPEAtencao(d_modelo, n_cabecas))
249
  else:
250
  self.camadas.append(
251
+ Mamba3Camada(d_modelo, d_estado, rank_mimo))
 
252
  self.norm_f = nn.RMSNorm(d_modelo)
253
 
254
  def _corre(self, x: torch.Tensor, tarefa=None) -> torch.Tensor: