Asi padic-ultrametric-embedding
P-adic ultrametric distance for UMAP/itUMAP/HNSW with Snowflake Arctic
install
source · Clone the upstream repo
git clone https://github.com/plurigrid/asi
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/padic-ultrametric-embedding" ~/.claude/skills/plurigrid-asi-padic-ultrametric-embedding && rm -rf "$T"
manifest:
skills/padic-ultrametric-embedding/SKILL.mdsource content
P-adic Ultrametric Embedding Skill
Non-Archimedean geometry for skill embeddings. Introduces p-adic distance as foundation for understanding UMAP, itUMAP, and HNSW search structures.
Why P-adic?
The ultrametric inequality (strong triangle inequality):
d(x, z) ≤ max(d(x, y), d(y, z))
This gives:
- Hierarchical clustering - all triangles are isoceles
- Natural tree structure - skills cluster into clopen balls
- No "in-between" - either close (same prefix) or far (different subtree)
Full Stack
┌─────────────────────────────────────────────────────────────────┐ │ P-ADIC EMBEDDING STACK │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Layer 7: UMAP/itUMAP │ │ ↓ geodesic-preserving projection │ │ │ │ Layer 6: HNSW Index │ │ ↓ navigable small-world graph │ │ │ │ Layer 5: Snowflake Arctic 1024-bit │ │ ↓ semantic embedding space │ │ │ │ Layer 4: MLX Operations │ │ ↓ matmul, attention, pooling │ │ │ │ Layer 3: Metal Kernels │ │ ↓ GPU shaders on Apple Silicon │ │ │ │ Layer 2: P-adic Valuation │ │ ↓ v_p(x) = largest k where p^k | x │ │ │ │ Layer 1: SPI (Strong Parallelism Invariance) │ │ ↓ deterministic parallel execution │ │ │ │ Layer 0: Content ID + Normal Form │ │ cq | jq diffed with narya.el semantics │ │ │ └─────────────────────────────────────────────────────────────────┘
GF(3) Triad
padic-ultrametric-embedding (0) ⊗ skill-embedding-vss (-1) ⊗ gay-mcp (+1) = 0 ✓
Core Mathematics
P-adic Valuation
For prime p (default p=2):
def p_adic_valuation(n: int, p: int = 2) -> int: """v_p(n) = largest k such that p^k divides n.""" if n == 0: return float('inf') k = 0 while n % p == 0: n //= p k += 1 return k
P-adic Norm
def p_adic_norm(n: int, p: int = 2) -> float: """|n|_p = p^(-v_p(n)) — smaller for "larger" divisibility.""" v = p_adic_valuation(n, p) return 0.0 if v == float('inf') else p ** (-v)
Ultrametric Distance on Embeddings
def padic_ultrametric_distance(emb_a: np.ndarray, emb_b: np.ndarray, p: int = 2) -> float: """ d_p(a, b) = max_i |a_i - b_i|_p Satisfies strong triangle: d(x,z) ≤ max(d(x,y), d(y,z)) """ diff = emb_a - emb_b scale = 2 ** 32 # Fixed-point conversion diff_int = (diff * scale).astype(np.int64) norms = [p_adic_norm(abs(int(d)), p) if d != 0 else 0.0 for d in diff_int] return max(norms) if norms else 0.0
Content ID + Normal Form
Every skill with an
id: field gets:
@dataclass class ContentID: id: str # The skill's unique identifier content: str # Raw content normal_form: str # Canonicalized (cq/jq normalized) hash: str # SHA-256 of normal form source: str # 'cq' | 'jq' | 'narya'
cq Normalization (S-expression style)
def cq_normalize(content: str) -> str: """Normalize as EDN/S-expr: balance parens, collapse whitespace.""" content = re.sub(r'\s+', ' ', content) return content.strip()
jq Normalization (JSON style)
def jq_normalize(content: str) -> str: """Normalize as JSON: sort keys, compact.""" data = json.loads(content) return json.dumps(data, sort_keys=True, separators=(',', ':'))
Narya Diff Semantics
@dataclass class NaryaDiff: before: str after: str delta: Dict[str, Any] # {added: N, removed: M, changed: N+M} birth: List[str] # New content lines death: List[str] # Removed content lines def to_narya_witness(self) -> Dict: """Format as proof witness for narya.el.""" return { 'before': sha256(self.before)[:16], 'after': sha256(self.after)[:16], 'delta': self.delta, 'birth': len(self.birth), 'death': len(self.death), 'impact': self.delta['changed'] > 0 }
MLX Operation Trace
Every embedding generation is traced:
@dataclass class MLXTrace: operation: str # 'tokenize', 'embedding_lookup', 'attention', etc. input_shapes: List[Tuple[int, ...]] output_shape: Tuple[int, ...] metal_kernel: Optional[str] # 'gather', 'matmul_4bit', 'softmax', etc. flops: int memory_bytes: int
Traced Operations
| Operation | Metal Kernel | FLOPS Formula |
|---|---|---|
| embedding_lookup | gather | seq_len × dim |
| attention | matmul_4bit, softmax | 2 × seq² × dim |
| ffn | matmul_4bit | 4 × seq × dim² |
| layer_norm | layer_norm | 2 × seq × dim |
| pooling | mean | seq × dim |
SPI (Strong Parallelism Invariance)
class SPIVerifier: """Verifies determinism across parallel executions.""" def __init__(self, seed: int): self.seed = seed self.traces: List[MLXTrace] = [] self.checksums: List[str] = [] def log_trace(self, trace: MLXTrace): self.traces.append(trace) checksum = hashlib.sha256( f"{trace.operation}:{trace.output_shape}:{self.checksums[-1] if self.checksums else '0'}" .encode() ).hexdigest()[:16] self.checksums.append(checksum) def verify_chain(self) -> bool: """Verify checksum chain integrity.""" return len(self.checksums) == len(self.traces)
Usage
Index Skills with P-adic Distance
from padic_ultrametric import PAdicSkillIndex index = PAdicSkillIndex('/path/to/skills', seed=1069, prime=2) content_ids = index.index_skills_with_ids() # Find nearest by p-adic (not Euclidean!) neighbors = index.padic_nearest('bisimulation-game', k=5) for name, eucl, padic in neighbors: print(f"{name}: eucl={eucl:.4f}, p-adic={padic:.6f}")
Find Skills with Content IDs
# Skills with id: field and normal form for name, cid in content_ids.items(): print(f"{name}: {cid.id} (hash: {cid.hash})")
Ultrametric Clustering
clusters = index.find_ultrametric_clusters(threshold=0.3) for cluster in clusters[:5]: print(f"Cluster: {cluster}")
Narya-style Diff
diff = index.diff_skills('skill-a', 'skill-b') witness = diff.to_narya_witness() print(f"Added: {witness['birth']}, Removed: {witness['death']}")
SPI Report
report = index.spi_report() print(f"Seed: {report['seed']}, Chain valid: {report['chain_valid']}") print(f"Total FLOPS: {report['total_flops']:,}")
UMAP Connection
UMAP uses nearest-neighbor graphs; p-adic ultrametric gives hierarchical graphs:
| Property | Euclidean NN | P-adic Ultrametric |
|---|---|---|
| Triangle | Weak: d(x,z) ≤ d(x,y) + d(y,z) | Strong: d(x,z) ≤ max(d(x,y), d(y,z)) |
| Clusters | Spherical | Clopen balls (tree) |
| Interpolation | Smooth gradients | Discrete jumps |
| Graph structure | k-NN graph | Bruhat-Tits tree |
itUMAP Enhancement
Iterative UMAP with p-adic warm-start:
- Compute p-adic tree structure
- Initialize UMAP with tree distances
- Refine with geodesic optimization
Dependencies
uv pip install mlx-embeddings duckdb numpy
Files
- Core implementationpadic_ultrametric.py
- Basic VSS without p-adicskill_embedding_vss.py
- GF(3) random walks through embedding spacetrifurcate_walk.py
Invariants
invariants: - name: ultrametric_property predicate: "∀x,y,z: d(x,z) ≤ max(d(x,y), d(y,z))" scope: per_triple - name: content_id_uniqueness predicate: "distinct id: → distinct hash" scope: per_skill - name: spi_determinism predicate: "same seed → same checksum chain" scope: per_index
End-of-Skill Interface
References
- P-adic Analysis - Non-Archimedean metric
- Bruhat-Tits Trees - P-adic symmetric spaces
- UMAP - McInnes et al.
- HNSW - Malkov & Yashunin
- Snowflake Arctic
- MLX - Apple's ML framework
Autopoietic Marginalia
The interaction IS the skill improving itself.
Every use of this skill is an opportunity for worlding:
- MEMORY (-1): Record what was learned
- REMEMBERING (0): Connect patterns to other skills
- WORLDING (+1): Evolve the skill based on use
Add Interaction Exemplars here as the skill is used.