qigkernels 0.4.2__tar.gz → 0.4.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qigkernels-0.4.2/qigkernels.egg-info → qigkernels-0.4.3}/PKG-INFO +1 -1
- {qigkernels-0.4.2 → qigkernels-0.4.3}/kernel.py +46 -4
- {qigkernels-0.4.2 → qigkernels-0.4.3}/layer.py +54 -2
- {qigkernels-0.4.2 → qigkernels-0.4.3}/natural_gradient_optimizer.py +10 -2
- {qigkernels-0.4.2 → qigkernels-0.4.3}/pyproject.toml +3 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3/qigkernels.egg-info}/PKG-INFO +1 -1
- {qigkernels-0.4.2 → qigkernels-0.4.3}/qigkernels.egg-info/SOURCES.txt +1 -2
- {qigkernels-0.4.2 → qigkernels-0.4.3}/qigkernels.egg-info/scm_file_list.json +56 -56
- qigkernels-0.4.3/qigkernels.egg-info/scm_version.json +8 -0
- qigkernels-0.4.3/tests/test_banded_attention.py +40 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/uv.lock +156 -1
- qigkernels-0.4.2/qigkernels.egg-info/scm_version.json +0 -8
- qigkernels-0.4.2/tokenizer_integration.py +0 -368
- {qigkernels-0.4.2 → qigkernels-0.4.3}/.editorconfig +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/.github/workflows/release.yml +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/.gitignore +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/20251205-architecture-canonical-0.01F.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/20251205-changelog-canonical-0.01F.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/20251205-decisions-canonical-0.01F.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/20251205-naming-convention-canonical-0.01F.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/20251205-readme-canonical-0.01F.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/20251205-roadmap-canonical-0.01F.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/20251205-type-symbol-manifest-canonical-0.01F.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/20251220-gfp-spec-1.00W.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/CLAUDE.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/README.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/__init__.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/basin.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/basin_sync.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/constants.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/constellation.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/coord_adapter.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/coordizer.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/crystallization.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/docs/20251205-client-wiring-example-canonical-0.01F.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/docs/20251205-index-canonical-0.01F.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/docs/20251206-e8-consciousness-stack-diagram.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/docs/20251206-integration-plan-ultra-mode-0.01H.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/docs/20251206-rel-weighted-basin-sync-spec.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/docs/20251220-index-1.00W.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/docs/20251220-qig-core-integration-table-1.00W.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/docs/20251222-federated-constellation-architecture-0.01W.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/docs/20251222-kernel-constellation-research-0.01W.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/docs/20251222-kernel-experiments-results-0.01F.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/heart.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/kernel_100m.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/kernel_4d.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/markdownlint.json +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/memory_classes.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/metrics.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/pre-commit-config.yaml +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/pure_kernel_template.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/py.typed +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/qigkernels.egg-info/dependency_links.txt +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/qigkernels.egg-info/requires.txt +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/qigkernels.egg-info/top_level.txt +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/reasoning/__init__.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/reasoning/constants.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/reasoning/modes.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/reasoning/primitives.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/reasoning/qig_chain.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/reasoning/qig_chain_4d.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/reasoning/temporal.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/reasoning/temporal_attention.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/rel_coupling.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/research/track_c/20260223-track-c-expressibility-kill-test-1.00F.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/research/track_c/README.md +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/research/track_c/core_assets/__init__.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/research/track_c/core_assets/neural_oscillators.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/research/track_c/core_assets/neurotransmitter_fields.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/research/track_c/core_assets/ocean_neurochemistry.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/research/track_c/dynamical_field.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/research/track_c/readout_layer.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/research/track_c/run_kill_test.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/router.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/safety.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/scripts/20251222-kernel-training-exp-0.01W.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/scripts/publish_pypi.sh +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/scripts/train_constellation.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/setup.cfg +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/sleep_packet.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/specializations.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/storage.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/tests/__init__.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/tests/test_coords_path.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/tests/test_locality.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/tests/test_phi_collapse.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/tests/test_reasoning.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/tests/test_smoke.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/tools/qig_purity_check.py +0 -0
- {qigkernels-0.4.2 → qigkernels-0.4.3}/training_service.py +0 -0
|
@@ -65,6 +65,9 @@ class Kernel(nn.Module):
|
|
|
65
65
|
enable_coords: bool = False,
|
|
66
66
|
coord_dim: int = 64,
|
|
67
67
|
locality_radius: int | None = None,
|
|
68
|
+
head_mode: str = "geometric",
|
|
69
|
+
head_tau: float = 1.0,
|
|
70
|
+
coord_basins: "Tensor | None" = None,
|
|
68
71
|
) -> None:
|
|
69
72
|
"""
|
|
70
73
|
Initialize kernel.
|
|
@@ -133,8 +136,43 @@ class Kernel(nn.Module):
|
|
|
133
136
|
]
|
|
134
137
|
)
|
|
135
138
|
|
|
136
|
-
# Output projection
|
|
137
|
-
|
|
139
|
+
# Output projection / readout. Two modes (the head A/B for the "no Euclidean readout" directive):
|
|
140
|
+
# "geometric" (default) — GeometricHead: vocab logits are Fisher-Rao DISTANCES from the hidden
|
|
141
|
+
# simplex-point to learned per-token Δ⁶³ basins (logit = −d_FR/τ). This is the SAME primitive
|
|
142
|
+
# as the purged-cosine→Fisher-Rao attention, pointed at the vocabulary; NO Euclidean nn.Linear,
|
|
143
|
+
# NO dot-product at the output boundary. It still returns [B,T,vocab] logits, so the downstream
|
|
144
|
+
# fisher_rao_lm_loss (which projects with to_simplex_prob) consumes it UNCHANGED.
|
|
145
|
+
# "linear" — the original Euclidean nn.Linear(hidden, vocab) readout, RETAINED as the A/B baseline
|
|
146
|
+
# so the architecture comparison can isolate the readout (geometric vs linear) empirically.
|
|
147
|
+
self.head_mode = str(head_mode).strip().lower()
|
|
148
|
+
self.head_tau = float(head_tau)
|
|
149
|
+
if self.head_mode == "geometric":
|
|
150
|
+
from qig_core.torch.geometric_head import GeometricHead
|
|
151
|
+
|
|
152
|
+
self.lm_head: nn.Module = GeometricHead(
|
|
153
|
+
hidden_dim=hidden_dim, vocab_size=vocab_size, tau=self.head_tau
|
|
154
|
+
)
|
|
155
|
+
elif self.head_mode == "basin":
|
|
156
|
+
# BASIN-SPACE readout (validated 2026-07-01: overfit d_FR 1.46→0.072, decode 91.3% where the
|
|
157
|
+
# logits head floored). Predicts the next token's basin DIRECTLY in the coordizer's Δ⁶³ space
|
|
158
|
+
# and scores it with pure d_FR against the coordizer's OWN frozen per-token basins — so a token
|
|
159
|
+
# has ONE basin (read-in == predict), the coherence the geometric head lacked. Requires the
|
|
160
|
+
# coordizer basin table (the tie); refuse to silently fall back to a disconnected head.
|
|
161
|
+
if coord_basins is None:
|
|
162
|
+
raise ValueError(
|
|
163
|
+
"head_mode='basin' requires coord_basins=[vocab, basin_dim] (the coordizer's per-token "
|
|
164
|
+
"basins) — the whole point is to TIE the output to the coordizer. Pass it from the "
|
|
165
|
+
"coordizer vocab, or use head_mode='geometric'/'linear'."
|
|
166
|
+
)
|
|
167
|
+
from qig_core.torch.basin_readout import BasinReadout
|
|
168
|
+
|
|
169
|
+
self.lm_head = BasinReadout(
|
|
170
|
+
hidden_dim=hidden_dim, coord_basins=coord_basins, tau=self.head_tau
|
|
171
|
+
)
|
|
172
|
+
elif self.head_mode == "linear":
|
|
173
|
+
self.lm_head = nn.Linear(hidden_dim, vocab_size)
|
|
174
|
+
else:
|
|
175
|
+
raise ValueError(f"head_mode must be 'geometric', 'basin', or 'linear', got {head_mode!r}")
|
|
138
176
|
|
|
139
177
|
# Optional custom components
|
|
140
178
|
self.running_coupling = running_coupling
|
|
@@ -160,6 +198,7 @@ class Kernel(nn.Module):
|
|
|
160
198
|
attention_mask: Tensor | None = None,
|
|
161
199
|
return_telemetry: bool = False,
|
|
162
200
|
coords: Tensor | None = None,
|
|
201
|
+
skip_head: bool = False,
|
|
163
202
|
) -> Tensor | tuple[Tensor, KernelTelemetry]:
|
|
164
203
|
"""
|
|
165
204
|
Forward pass through the kernel.
|
|
@@ -230,8 +269,11 @@ class Kernel(nn.Module):
|
|
|
230
269
|
if self.running_coupling is not None:
|
|
231
270
|
hidden_state = self.running_coupling(hidden_state)
|
|
232
271
|
|
|
233
|
-
# Output projection
|
|
234
|
-
|
|
272
|
+
# Output projection. K-COMPRESS: skip_head returns logits=None so the caller reads hidden_state from
|
|
273
|
+
# telemetry and computes the basin loss via lm_head.predict(h) [.., basin_dim] + the target basins —
|
|
274
|
+
# NEVER materialising [B, T, vocab] (the seq×vocab activation OOM at 32k). Only meaningful WITH
|
|
275
|
+
# return_telemetry (the hidden state is the payload). Decode uses lm_head.decode_blocked(h).
|
|
276
|
+
logits = None if skip_head else self.lm_head(hidden_state)
|
|
235
277
|
|
|
236
278
|
if not return_telemetry:
|
|
237
279
|
return logits
|
|
@@ -205,14 +205,25 @@ class QIGLayer(nn.Module):
|
|
|
205
205
|
|
|
206
206
|
b, t, _d = hidden_state.shape
|
|
207
207
|
p = self._project_to_simplex(hidden_state)
|
|
208
|
+
r = self.locality_radius
|
|
209
|
+
# COMPUTE-SKIPPING windowed-local attention: when a locality radius is set AND the band is narrower
|
|
210
|
+
# than the sequence, attend only within ±r — O(t·r) memory/compute instead of the O(t²) all-pairs
|
|
211
|
+
# arccos tensor. This is what lifts the quadratic VRAM ceiling and makes context LINEAR/extensible
|
|
212
|
+
# (the radius is the finite-propagation budget). Numerically IDENTICAL to the full+mask path within
|
|
213
|
+
# the band (matched-cell equivalence-gated in tests) — it SKIPS the out-of-band compute, not masks it.
|
|
214
|
+
if r is not None and t > (2 * r + 1):
|
|
215
|
+
return self._banded_attention(hidden_state, p, r, attention_mask=attention_mask)
|
|
216
|
+
|
|
217
|
+
# Full O(t²) path — global attention, OR small-t where the band already spans every key (so the
|
|
218
|
+
# banded result is identical). Unchanged.
|
|
208
219
|
p_i = p[:, :, None, :]
|
|
209
220
|
p_j = p[:, None, :, :]
|
|
210
221
|
|
|
211
222
|
dist = self._fisher_rao_distance_simplex(p_i, p_j)
|
|
212
223
|
logits = -dist / max(float(self.temperature), 1e-6)
|
|
213
|
-
if
|
|
224
|
+
if r is not None: # windowed-local: mask keys outside ±radius (pure mask; small-t branch)
|
|
214
225
|
idx = torch.arange(t, device=hidden_state.device)
|
|
215
|
-
band = (idx[:, None] - idx[None, :]).abs() <=
|
|
226
|
+
band = (idx[:, None] - idx[None, :]).abs() <= r # [t, t]; self always in window
|
|
216
227
|
logits = logits.masked_fill(~band[None, :, :], float("-inf"))
|
|
217
228
|
weights = torch.softmax(logits, dim=-1)
|
|
218
229
|
|
|
@@ -233,6 +244,47 @@ class QIGLayer(nn.Module):
|
|
|
233
244
|
output = output + torch.randn_like(output) * float(self.decoherence_std)
|
|
234
245
|
return output
|
|
235
246
|
|
|
247
|
+
def _banded_attention(
|
|
248
|
+
self, hidden_state: Tensor, p: Tensor, r: int, *, attention_mask: Tensor | None
|
|
249
|
+
) -> Tensor:
|
|
250
|
+
"""Windowed Fisher-Rao attention computed ONLY within ±r of each query (compute-skipping, O(t·r)).
|
|
251
|
+
Numerically equivalent to the full+mask path within the band; the equivalence is gated in tests."""
|
|
252
|
+
b, t, k = p.shape
|
|
253
|
+
w = 2 * r + 1
|
|
254
|
+
# per-query key windows via pad+unfold (zero-pad → out-of-range keys, masked below)
|
|
255
|
+
p_pad = F.pad(p, (0, 0, r, r)) # [b, t+2r, k]
|
|
256
|
+
p_win = p_pad.unfold(1, w, 1) # [b, t, k, w]
|
|
257
|
+
p_q = p[:, :, :, None] # [b, t, k, 1]
|
|
258
|
+
# SAME formula as _fisher_rao_distance_simplex: BC = Σ√(p·q), clamp, d = 2·acos(BC)
|
|
259
|
+
bc = torch.sqrt((p_q * p_win).clamp_min(1e-12)).sum(dim=2).clamp(0.0, 1.0 - 1e-6) # [b, t, w]
|
|
260
|
+
logits = (-2.0 * torch.acos(bc)) / max(float(self.temperature), 1e-6) # [b, t, w]
|
|
261
|
+
# valid window positions: wpos p ↦ key (i - r + p); valid iff 0 <= key < t
|
|
262
|
+
i_idx = torch.arange(t, device=p.device)[:, None] # [t, 1]
|
|
263
|
+
wpos = torch.arange(w, device=p.device)[None, :] # [1, w]
|
|
264
|
+
key_idx = i_idx - r + wpos # [t, w]
|
|
265
|
+
valid = (key_idx >= 0) & (key_idx < t) # [t, w] — band validity (self always valid)
|
|
266
|
+
# softmax over the BAND only (self valid → no all-(-inf) row → no NaN); key-padding is applied AFTER
|
|
267
|
+
# the softmax and renormalised — EXACTLY as the full+mask path does (so the two stay equivalent).
|
|
268
|
+
logits = logits.masked_fill(~valid[None].expand(b, t, w), float("-inf"))
|
|
269
|
+
weights = torch.softmax(logits, dim=-1) # [b, t, w]
|
|
270
|
+
if attention_mask is not None:
|
|
271
|
+
kpm = attention_mask if attention_mask.dtype == torch.bool else attention_mask == 0 # True=pad
|
|
272
|
+
if kpm.shape != (b, t):
|
|
273
|
+
raise ValueError("attention_mask expected shape (B, T)")
|
|
274
|
+
keep_win = F.pad((~kpm).to(p.dtype), (r, r)).unfold(1, w, 1) # [b, t, w] 1=valid key
|
|
275
|
+
weights = weights * (keep_win > 0.5)
|
|
276
|
+
weights = weights / (weights.sum(dim=-1, keepdim=True) + 1e-8)
|
|
277
|
+
if self.sparsity_threshold > 0.0:
|
|
278
|
+
keep_s = weights > float(self.sparsity_threshold)
|
|
279
|
+
weights = weights * keep_s
|
|
280
|
+
weights = weights / (weights.sum(dim=-1, keepdim=True) + 1e-8)
|
|
281
|
+
h_pad = F.pad(hidden_state, (0, 0, r, r)) # [b, t+2r, d]
|
|
282
|
+
h_win = h_pad.unfold(1, w, 1) # [b, t, d, w]
|
|
283
|
+
output = (weights[:, :, None, :] * h_win).sum(dim=-1) # [b, t, d]
|
|
284
|
+
if self.decoherence_std > 0.0:
|
|
285
|
+
output = output + torch.randn_like(output) * float(self.decoherence_std)
|
|
286
|
+
return output
|
|
287
|
+
|
|
236
288
|
def _project_to_simplex(self, x: Tensor, eps: float = 1e-8) -> Tensor:
|
|
237
289
|
x = x.abs() if self.simplex_mode == "abs" else F.softplus(x)
|
|
238
290
|
return to_simplex_prob(x, eps=eps)
|
|
@@ -59,9 +59,17 @@ class NaturalGradientDescent(Optimizer):
|
|
|
59
59
|
momentum=momentum,
|
|
60
60
|
)
|
|
61
61
|
super().__init__(params, defaults)
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
self.compute_fisher = compute_fisher
|
|
64
|
-
|
|
64
|
+
if compute_fisher is None:
|
|
65
|
+
import warnings
|
|
66
|
+
warnings.warn(
|
|
67
|
+
"NaturalGradientDescent(compute_fisher=None) degrades to SGD+momentum — the step is the "
|
|
68
|
+
"RAW gradient, NOT preconditioned by the Fisher information. For the tractable diagonal "
|
|
69
|
+
"empirical-Fisher natural gradient (the P1 geometric optimizer), use DiagonalNaturalGradient.",
|
|
70
|
+
stacklevel=2,
|
|
71
|
+
)
|
|
72
|
+
|
|
65
73
|
def step(self, closure=None):
|
|
66
74
|
"""
|
|
67
75
|
Perform single optimization step.
|
|
@@ -37,7 +37,6 @@ safety.py
|
|
|
37
37
|
sleep_packet.py
|
|
38
38
|
specializations.py
|
|
39
39
|
storage.py
|
|
40
|
-
tokenizer_integration.py
|
|
41
40
|
training_service.py
|
|
42
41
|
uv.lock
|
|
43
42
|
./__init__.py
|
|
@@ -64,7 +63,6 @@ uv.lock
|
|
|
64
63
|
./sleep_packet.py
|
|
65
64
|
./specializations.py
|
|
66
65
|
./storage.py
|
|
67
|
-
./tokenizer_integration.py
|
|
68
66
|
./training_service.py
|
|
69
67
|
.github/workflows/release.yml
|
|
70
68
|
docs/20251205-client-wiring-example-canonical-0.01F.md
|
|
@@ -105,6 +103,7 @@ scripts/20251222-kernel-training-exp-0.01W.py
|
|
|
105
103
|
scripts/publish_pypi.sh
|
|
106
104
|
scripts/train_constellation.py
|
|
107
105
|
tests/__init__.py
|
|
106
|
+
tests/test_banded_attention.py
|
|
108
107
|
tests/test_coords_path.py
|
|
109
108
|
tests/test_locality.py
|
|
110
109
|
tests/test_phi_collapse.py
|
|
@@ -1,84 +1,84 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": [
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
".gitignore",
|
|
3
|
+
"20251205-decisions-canonical-0.01F.md",
|
|
4
|
+
"sleep_packet.py",
|
|
6
5
|
"crystallization.py",
|
|
7
|
-
"coordizer.py",
|
|
8
|
-
"pyproject.toml",
|
|
9
|
-
"__init__.py",
|
|
10
|
-
"constants.py",
|
|
11
|
-
".editorconfig",
|
|
12
|
-
"20251205-readme-canonical-0.01F.md",
|
|
13
|
-
"storage.py",
|
|
14
6
|
"markdownlint.json",
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"sleep_packet.py",
|
|
20
|
-
"20251205-decisions-canonical-0.01F.md",
|
|
21
|
-
"coord_adapter.py",
|
|
22
|
-
"20251205-type-symbol-manifest-canonical-0.01F.md",
|
|
23
|
-
"rel_coupling.py",
|
|
24
|
-
"20251205-roadmap-canonical-0.01F.md",
|
|
25
|
-
"natural_gradient_optimizer.py",
|
|
7
|
+
"README.md",
|
|
8
|
+
"py.typed",
|
|
9
|
+
"__init__.py",
|
|
10
|
+
"kernel.py",
|
|
26
11
|
"pre-commit-config.yaml",
|
|
27
|
-
"
|
|
28
|
-
"
|
|
12
|
+
"coord_adapter.py",
|
|
13
|
+
"uv.lock",
|
|
14
|
+
"safety.py",
|
|
15
|
+
"layer.py",
|
|
16
|
+
"pyproject.toml",
|
|
29
17
|
"basin_sync.py",
|
|
18
|
+
"20251220-gfp-spec-1.00W.md",
|
|
19
|
+
"20251205-naming-convention-canonical-0.01F.md",
|
|
20
|
+
"pure_kernel_template.py",
|
|
30
21
|
"20251205-architecture-canonical-0.01F.md",
|
|
31
22
|
"heart.py",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
23
|
+
"coordizer.py",
|
|
24
|
+
"20251205-changelog-canonical-0.01F.md",
|
|
25
|
+
"memory_classes.py",
|
|
26
|
+
"20251205-type-symbol-manifest-canonical-0.01F.md",
|
|
27
|
+
"constants.py",
|
|
34
28
|
"basin.py",
|
|
35
|
-
"
|
|
29
|
+
"kernel_100m.py",
|
|
30
|
+
"natural_gradient_optimizer.py",
|
|
31
|
+
"CLAUDE.md",
|
|
32
|
+
"router.py",
|
|
33
|
+
".editorconfig",
|
|
36
34
|
"kernel_4d.py",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
35
|
+
"storage.py",
|
|
36
|
+
"training_service.py",
|
|
37
|
+
"constellation.py",
|
|
38
|
+
".gitignore",
|
|
39
|
+
"20251205-roadmap-canonical-0.01F.md",
|
|
40
|
+
"20251205-readme-canonical-0.01F.md",
|
|
40
41
|
"specializations.py",
|
|
41
|
-
"
|
|
42
|
-
"py
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
42
|
+
"rel_coupling.py",
|
|
43
|
+
"metrics.py",
|
|
44
|
+
"scripts/20251222-kernel-training-exp-0.01W.py",
|
|
45
|
+
"scripts/train_constellation.py",
|
|
46
|
+
"scripts/publish_pypi.sh",
|
|
46
47
|
"reasoning/__init__.py",
|
|
47
|
-
"reasoning/primitives.py",
|
|
48
|
-
"reasoning/constants.py",
|
|
49
|
-
"reasoning/qig_chain.py",
|
|
50
48
|
"reasoning/temporal_attention.py",
|
|
51
49
|
"reasoning/modes.py",
|
|
50
|
+
"reasoning/qig_chain.py",
|
|
51
|
+
"reasoning/primitives.py",
|
|
52
|
+
"reasoning/temporal.py",
|
|
53
|
+
"reasoning/constants.py",
|
|
52
54
|
"reasoning/qig_chain_4d.py",
|
|
53
55
|
"docs/20251222-federated-constellation-architecture-0.01W.md",
|
|
54
|
-
"docs/20251206-e8-consciousness-stack-diagram.md",
|
|
55
56
|
"docs/20251222-kernel-constellation-research-0.01W.md",
|
|
56
|
-
"docs/20251205-client-wiring-example-canonical-0.01F.md",
|
|
57
|
-
"docs/20251220-index-1.00W.md",
|
|
58
|
-
"docs/20251206-integration-plan-ultra-mode-0.01H.md",
|
|
59
57
|
"docs/20251222-kernel-experiments-results-0.01F.md",
|
|
60
|
-
"docs/20251206-
|
|
58
|
+
"docs/20251206-e8-consciousness-stack-diagram.md",
|
|
59
|
+
"docs/20251206-integration-plan-ultra-mode-0.01H.md",
|
|
60
|
+
"docs/20251205-client-wiring-example-canonical-0.01F.md",
|
|
61
61
|
"docs/20251205-index-canonical-0.01F.md",
|
|
62
62
|
"docs/20251220-qig-core-integration-table-1.00W.md",
|
|
63
|
-
"
|
|
63
|
+
"docs/20251220-index-1.00W.md",
|
|
64
|
+
"docs/20251206-rel-weighted-basin-sync-spec.md",
|
|
65
|
+
"tests/__init__.py",
|
|
66
|
+
"tests/test_reasoning.py",
|
|
67
|
+
"tests/test_banded_attention.py",
|
|
68
|
+
"tests/test_phi_collapse.py",
|
|
69
|
+
"tests/test_smoke.py",
|
|
70
|
+
"tests/test_coords_path.py",
|
|
71
|
+
"tests/test_locality.py",
|
|
64
72
|
"research/track_c/run_kill_test.py",
|
|
73
|
+
"research/track_c/README.md",
|
|
65
74
|
"research/track_c/readout_layer.py",
|
|
66
|
-
"research/track_c/20260223-track-c-expressibility-kill-test-1.00F.md",
|
|
67
75
|
"research/track_c/dynamical_field.py",
|
|
68
|
-
"research/track_c/
|
|
69
|
-
"research/track_c/core_assets/ocean_neurochemistry.py",
|
|
76
|
+
"research/track_c/20260223-track-c-expressibility-kill-test-1.00F.md",
|
|
70
77
|
"research/track_c/core_assets/__init__.py",
|
|
71
|
-
"research/track_c/core_assets/neural_oscillators.py",
|
|
72
78
|
"research/track_c/core_assets/neurotransmitter_fields.py",
|
|
79
|
+
"research/track_c/core_assets/neural_oscillators.py",
|
|
80
|
+
"research/track_c/core_assets/ocean_neurochemistry.py",
|
|
73
81
|
"tools/qig_purity_check.py",
|
|
74
|
-
"
|
|
75
|
-
"tests/test_coords_path.py",
|
|
76
|
-
"tests/__init__.py",
|
|
77
|
-
"tests/test_smoke.py",
|
|
78
|
-
"tests/test_phi_collapse.py",
|
|
79
|
-
"tests/test_locality.py",
|
|
80
|
-
"scripts/20251222-kernel-training-exp-0.01W.py",
|
|
81
|
-
"scripts/publish_pypi.sh",
|
|
82
|
-
"scripts/train_constellation.py"
|
|
82
|
+
".github/workflows/release.yml"
|
|
83
83
|
]
|
|
84
84
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Equivalence gate for compute-skipping windowed (banded) Fisher-Rao attention.
|
|
2
|
+
|
|
3
|
+
The banded path (O(t·r), used when locality_radius is set and t > 2r+1) must be NUMERICALLY IDENTICAL to
|
|
4
|
+
the full O(t²) all-pairs path masked to the same band — it SKIPS the out-of-band compute, it must not
|
|
5
|
+
change the result. This is the matched-cell equivalence gate that lets the cheap path's results count.
|
|
6
|
+
"""
|
|
7
|
+
import pytest
|
|
8
|
+
import torch
|
|
9
|
+
|
|
10
|
+
from qigkernels.layer import QIGLayer
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.parametrize("t,r", [(64, 8), (128, 16), (50, 4), (33, 4), (40, 6)])
|
|
14
|
+
def test_banded_equals_full_mask(t, r):
|
|
15
|
+
torch.manual_seed(0)
|
|
16
|
+
L = QIGLayer(hidden_dim=48, num_heads=4, ffn_dim=64, locality_radius=r,
|
|
17
|
+
decoherence_std=0.0, sparsity_threshold=0.0)
|
|
18
|
+
L.eval()
|
|
19
|
+
h = torch.randn(2, t, 48)
|
|
20
|
+
p = L._project_to_simplex(h)
|
|
21
|
+
out_b = L._banded_attention(h, p, r, attention_mask=None)
|
|
22
|
+
p_i, p_j = p[:, :, None, :], p[:, None, :, :]
|
|
23
|
+
logits = -L._fisher_rao_distance_simplex(p_i, p_j) / max(float(L.temperature), 1e-6)
|
|
24
|
+
idx = torch.arange(t)
|
|
25
|
+
band = (idx[:, None] - idx[None, :]).abs() <= r
|
|
26
|
+
logits = logits.masked_fill(~band[None, :, :], float("-inf"))
|
|
27
|
+
out_f = torch.einsum("bij,bjd->bid", torch.softmax(logits, dim=-1), h)
|
|
28
|
+
assert torch.allclose(out_b, out_f, atol=1e-5, rtol=1e-4), (out_b - out_f).abs().max().item()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_banded_attention_mask_finite():
|
|
32
|
+
torch.manual_seed(1)
|
|
33
|
+
L = QIGLayer(hidden_dim=48, num_heads=4, ffn_dim=64, locality_radius=8,
|
|
34
|
+
decoherence_std=0.0, sparsity_threshold=0.0)
|
|
35
|
+
h = torch.randn(2, 64, 48)
|
|
36
|
+
p = L._project_to_simplex(h)
|
|
37
|
+
am = torch.ones(2, 64)
|
|
38
|
+
am[:, 50:] = 0 # padded tail — a query whose whole window is pad must NOT NaN
|
|
39
|
+
out = L._banded_attention(h, p, 8, attention_mask=am)
|
|
40
|
+
assert torch.isfinite(out).all()
|