File size: 10,858 Bytes
4ef8b0b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
"""geolip_vitals.py β€” the shared diagnostic harness (progression plan Tree 7a).
One implementation, every tree imports it. ALL functions are READOUTS: no gradients,
no losses. CV is a readout, never a force (discovery_catalog #3). Judge addressing by
drift->0.29154 and CV->0.20, never recon cosine (MANIFEST).

Vitals provided:
  anchor_drift        β€” geodesic drift of anchors from init; binding fraction @0.29154
  pentachoron_cv      β€” CM 4-volume CV over random 5-row subsets (geovocab2 import)
  axis_aliveness      β€” oriented-address usage: axes alive, hppl, collapse flag
  gate_stats          β€” gate means vs the 0.012-0.03 band
  path_diversity      β€” unique-path counting, FIXED high-bits hash (low-16 bug is the
                        retracted artifact β€” never use the low bits)
  grad_norm_spread    β€” gradient democracy monitor (orders-of-magnitude spread)
  CVScreen            β€” CV@1000-batch early band screen (<0.30 LOW / .35-.50 MID / >.80 HIGH)

Smoke on a torch-capable env:  python geolip_vitals.py
"""
from __future__ import annotations
import math
import torch

BINDING = 0.29154            # radians; the binding/separation constant (MANIFEST)
CV_BAND = (0.13, 0.30)       # CM CV band (discovery_catalog #4)
GATE_BAND = (0.012, 0.03)    # live invariant candidate (acd_campaign)
KNUTH32 = 2654435761


# ----------------------------------------------------------------------------- drift
@torch.no_grad()
def anchor_drift(current: torch.Tensor, init: torch.Tensor, tol: float = 0.05) -> dict:
    """Geodesic drift (radians) of each row of `current` from its row in `init`,
    both row-normalized. Returns mean/std/per-row drift and the fraction of rows
    within +/-tol of BINDING (the GLFM '46%' readout)."""
    a = torch.nn.functional.normalize(current.float(), dim=-1)
    b = torch.nn.functional.normalize(init.float(), dim=-1)
    cos = (a * b).sum(-1).clamp(-1.0, 1.0)
    drift = torch.arccos(cos)
    frac = ((drift - BINDING).abs() <= tol).float().mean()
    return {"mean": drift.mean().item(), "std": drift.std().item(),
            "per_row": drift, "binding_fraction": frac.item()}


# -------------------------------------------------------------------------------- cv
@torch.no_grad()
def _pentachoron_volumes(pts: torch.Tensor) -> torch.Tensor:
    """Batched Cayley-Menger 4-simplex volumes. pts: (B, 5, D) -> (B,) volumes.
    One float64 det over all samples (vol^2 = -det(CM)/9216 for n=4). Built-in
    per the 2026-07-11 rider amendment (the operator: the installed geovocab2 path is a
    per-sample class call β€” too slow for a vitals loop); geovocab2 stays the
    reference implementation, parity-checked via cv_reference_check()."""
    B = pts.shape[0]
    d2 = torch.cdist(pts.double(), pts.double()).pow(2)          # (B,5,5)
    cm = torch.ones(B, 6, 6, dtype=torch.float64, device=pts.device)
    cm[:, 0, 0] = 0.0
    cm[:, 1:, 1:] = d2
    det = torch.linalg.det(cm)
    return (-det / 9216.0).clamp_min(0.0).sqrt().float()


@torch.no_grad()
def pentachoron_cv(rows: torch.Tensor, n_samples: int = 200,
                   generator: torch.Generator | None = None) -> float:
    """CV (std/mean) of Cayley-Menger 4-simplex volumes over n_samples random
    5-row subsets. Rows are row-normalized before measurement. Uses the built-in
    batched CM (float64 det); validate against geovocab2 with
    cv_reference_check() after any change to the volume math."""
    x = torch.nn.functional.normalize(rows.float(), dim=-1)
    n = x.shape[0]
    if n < 5:
        raise ValueError(f"pentachoron_cv needs >=5 rows, got {n}")
    g = generator or torch.Generator(device="cpu").manual_seed(0)
    idx = torch.stack([torch.randperm(n, generator=g)[:5]
                       for _ in range(n_samples)])               # (B,5)
    v = _pentachoron_volumes(x[idx].cpu())
    return (v.std() / v.mean().clamp_min(1e-12)).item()


@torch.no_grad()
def cv_reference_check(n_trials: int = 50, tol: float = 1e-5) -> float:
    """Parity check of the built-in batched CM against geovocab2's reference
    implementation (the formula's source of truth). Returns max |rel diff|;
    raises if geovocab2 is absent or parity fails. Run after touching
    _pentachoron_volumes."""
    try:
        from geovocab2.shapes.formula.symbolic.cayley_menger import (
            CayleyMengerFromSimplex)
    except Exception as e:  # pragma: no cover
        raise ImportError(
            "cv_reference_check requires geovocab2 (install via the geolip-svae "
            "umbrella: pip install git+https://github.com/AbstractEyes/"
            "geolip-svae).") from e
    ref = CayleyMengerFromSimplex()
    g = torch.Generator().manual_seed(0)
    pts = torch.nn.functional.normalize(
        torch.randn(n_trials, 5, 4, generator=g), dim=-1)
    mine = _pentachoron_volumes(pts)
    # compare at float64: the reference computes in the INPUT dtype, and fp32
    # dets lose up to ~4% on near-degenerate pentachora (measured 2026-07-11)
    tsuccessors = torch.stack([ref.forward(p.double())["volume"].float() for p in pts])
    rel = ((mine - tsuccessors).abs() / tsuccessors.abs().clamp_min(1e-12)).max().item()
    if rel > tol:
        raise AssertionError(f"CM parity vs geovocab2 failed: max rel {rel}")
    return rel


# ------------------------------------------------------------------------- aliveness
@torch.no_grad()
def axis_aliveness(oriented_weights: torch.Tensor, alive_thresh: float = 1e-3) -> dict:
    """`oriented_weights`: (..., 2K) nonnegative oriented-softmax address rows
    (sum to 1 on the last dim). Returns axes-alive count, mean-usage perplexity
    (hppl analogue; healthy hosted reference 125-126/128), and a collapse flag.
    Reference behavior: near-uniform aliveness at div_weight=0 (discovery #22)."""
    w = oriented_weights.reshape(-1, oriented_weights.shape[-1]).float()
    usage = w.mean(0)
    usage = usage / usage.sum().clamp_min(1e-12)
    # an axis is alive if its mean usage exceeds alive_thresh x the uniform share
    alive = int((usage > alive_thresh * (1.0 / usage.numel())).sum())
    ent = -(usage.clamp_min(1e-12) * usage.clamp_min(1e-12).log()).sum()
    ppl = float(ent.exp())
    return {"axes_total": usage.numel(), "axes_alive": alive, "usage_ppl": ppl,
            "collapsed": ppl < 0.05 * usage.numel()}


# ------------------------------------------------------------------------------ gates
@torch.no_grad()
def gate_stats(gates: torch.Tensor) -> dict:
    """Gate values (post-sigmoid/clamp). Reports mean and whether it sits in the
    0.012-0.03 band (read-only β€” the band is a candidate invariant, never a target)."""
    g = gates.float().flatten()
    m = g.mean().item()
    return {"mean": m, "std": g.std().item(),
            "in_band": GATE_BAND[0] <= m <= GATE_BAND[1]}


# ------------------------------------------------------------------------------ paths
@torch.no_grad()
def path_diversity(ids: torch.Tensor) -> dict:
    """Unique-path counting with the FIXED multiplicative hash:
    ((ids * 2654435761) % 2^32) >> 16 β€” Knuth needs the HIGH bits; the low-16
    variant produced the retracted ~1,500 path ceiling (sessions/2026-07-07).
    `ids`: integer tensor, one composed path id per row (any shape)."""
    x = ids.reshape(-1).to(torch.int64)
    hashed = ((x * KNUTH32) % (1 << 32)) >> 16
    return {"n": int(x.numel()),
            "unique_raw": int(torch.unique(x).numel()),
            "unique_hashed": int(torch.unique(hashed).numel())}


@torch.no_grad()
def compose_path_ids(stage_indices: list[torch.Tensor], radix: int) -> torch.Tensor:
    """Compose per-stage discrete indices (each (...,) int in [0, radix)) into a
    single path id, positional base-`radix` β€” construction, not hashing."""
    out = torch.zeros_like(stage_indices[0], dtype=torch.int64)
    for s in stage_indices:
        out = out * radix + s.to(torch.int64)
    return out


# --------------------------------------------------------------------- grad democracy
@torch.no_grad()
def grad_norm_spread(groups: dict[str, list[torch.nn.Parameter]]) -> dict:
    """Gradient-democracy monitor. `groups`: name -> params of one parallel member
    (tower/expert). Reports per-group grad norms and the orders-of-magnitude spread.
    Reference: unequalized heterogeneous towers spread ~20 orders (fibonacci dead at
    2.25e-21 under helix); equalized ~0.0 (canon/fibonacci_systems.md)."""
    norms = {}
    for name, params in groups.items():
        gs = [p.grad for p in params if p.grad is not None]
        norms[name] = float(torch.sqrt(sum((g.float() ** 2).sum() for g in gs)).item()) \
            if gs else 0.0
    vals = [v for v in norms.values() if v > 0]
    spread = (math.log10(max(vals)) - math.log10(min(vals))) if len(vals) >= 2 else 0.0
    return {"norms": norms, "spread_orders": spread, "dead": [k for k, v in norms.items() if v == 0.0]}


# ----------------------------------------------------------------------------- screen
class CVScreen:
    """CV@N early band screen (tri-band ft1): record pentachoron CV at `step_mark`
    batches; classify <0.30 LOW / 0.35-0.50 MID / >0.80 HIGH. Turns ~2h/config
    into ~7min. Readout only."""
    def __init__(self, step_mark: int = 1000):
        self.step_mark = step_mark
        self.recorded: float | None = None

    def maybe_record(self, step: int, rows: torch.Tensor) -> float | None:
        if self.recorded is None and step >= self.step_mark:
            self.recorded = pentachoron_cv(rows)
        return self.recorded

    @property
    def band(self) -> str | None:
        c = self.recorded
        if c is None:
            return None
        if c < 0.30:
            return "LOW"
        if 0.35 <= c <= 0.50:
            return "MID"
        if c > 0.80:
            return "HIGH"
        return "BETWEEN"


# ------------------------------------------------------------------------------ smoke
if __name__ == "__main__":  # shapes/parse smoke ONLY β€” no training, ever.
    g = torch.Generator().manual_seed(0)
    K, D = 64, 4
    init = torch.nn.functional.normalize(torch.randn(K, D, generator=g), dim=-1)
    cur = torch.nn.functional.normalize(init + 0.29 * torch.randn(K, D, generator=g), dim=-1)
    print("drift:", {k: v for k, v in anchor_drift(cur, init).items() if k != "per_row"})
    w = torch.softmax(torch.randn(32, 2 * K, generator=g), dim=-1)
    print("aliveness:", axis_aliveness(w))
    print("gates:", gate_stats(torch.full((8,), 0.024)))
    ids = compose_path_ids([torch.randint(0, 16, (4096,), generator=g) for _ in range(4)], 16)
    print("paths:", path_diversity(ids))
    lin = torch.nn.Linear(8, 8)
    lin(torch.randn(4, 8)).sum().backward()
    print("democracy:", grad_norm_spread({"a": list(lin.parameters())}))
    print("OK β€” vitals smoke passed (pentachoron_cv needs geovocab2; run on GPU env)")