SilverSight/scripts/pipeline_core.py
2026-07-04 21:27:02 +00:00

492 lines
20 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
pipeline_core.py — Module-swappable six-stage search engine.
Uses the ACTUAL SilverSight chiral implementation:
- ChiralLabel: 4 types (achiral_stable, chiral_scarred, left_handed, right_handed)
- Phase: Z/360Z at 45° steps (0,45,90,135,180,225,270,315)
- Rossby drift: weights left=+65536, right=-65536, scarred=+32768, achiral=0
- Quaternion basis: achiral=1, left=i, right=j, scarred=k (HopfFibration)
- Golden angle: 25042 Q16_16 (2π/φ²), winding mod 28
- Fisher-Rao sphere: p → 2√p maps simplex to S²
No floats. No native_decide. All Q16_16 integer arithmetic.
Usage:
from pipeline_core import Pipeline, BraidStorm, TreeBraid, AngrySphinx,
MultisurfacePacker, COUCHFilter, SidonFilter
pipe = Pipeline([...])
result = pipe.run(labels, S, moduli)
"""
import sys, math, json, time, hashlib, random
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from pathlib import Path
from itertools import product
from collections import Counter
from typing import Any
REPO_ROOT = Path(__file__).resolve().parent.parent
ARTIFACTS_DIR = REPO_ROOT / ".openresearch" / "artifacts"
ARTIFACTS_DIR.mkdir(parents=True, exist_ok=True)
# ── Q16_16 constants (no floats) ──────────────────────────────────────
Q16_ONE = 65536
Q16_HALF = 32768 # 0.5 in Q16_16 (chiral_scarred weight)
Q16_THRESHOLD_COUCH = 49152 # 0.75
Q16_SUBLEQ_SELFLOOP = 53908 # 0.823
Q16_AVX_SELFLOOP = 57942 # 0.885
Q16_RING_SELFLOOP = 0 # 0.0
Q16_GOLDEN_ANGLE = 25042 # 2π/φ² in Q16_16
EXOTIC_CLASSES = 28 # Durán exotic sphere classes
Q16_TWO_PI = 411775 # 2π in Q16_16 (≈ 6.28318)
# ── ChiralLabel (from BraidStateN.lean) ───────────────────────────────
CHIRAL_LABELS = ["achiral_stable", "chiral_scarred",
"left_handed_mass_bias", "right_handed_vector_bias"]
# Rossby drift weights (from rossbyDriftFromChirality)
ROSSBY_WEIGHTS = {
"achiral_stable": 0, # Q16_16.zero
"chiral_scarred": Q16_HALF, # 32768 = 0.5
"left_handed_mass_bias": Q16_ONE, # +1
"right_handed_vector_bias": -Q16_ONE, # -1
}
# Phase angles (from HachimojiBase.lean) — Z/360Z at 45° steps
PHASE_ANGLES = [0, 45, 90, 135, 180, 225, 270, 315]
# Chirality from phase (from HachimojiBase.chirality)
def chirality_from_phase(phase):
"""Map phase angle to chirality (HachimojiBase.lean line 176)."""
if phase in (0, 90, 180): return "ambidextrous"
if phase in (45, 135): return "left"
if phase in (225, 270, 315): return "right"
return "right"
# Quaternion basis mapping (from HopfFibration.lean ofChiralLabel)
# achiral_stable → 1 (scalar), left → i, right → j, scarred → k
QUATERNION_BASIS = {
"achiral_stable": (Q16_ONE, 0, 0, 0), # 1
"left_handed_mass_bias": (0, Q16_ONE, 0, 0), # i
"right_handed_vector_bias": (0, 0, Q16_ONE, 0), # j
"chiral_scarred": (0, 0, 0, Q16_ONE), # k
}
# ChiralLabel from chirality (mapping Hachimoji chirality → BraidStateN ChiralLabel)
def chiral_label_from_phase(phase):
"""Map phase to ChiralLabel (combining HachimojiBase + BraidStateN)."""
chi = chirality_from_phase(phase)
if chi == "ambidextrous": return "achiral_stable"
if chi == "left": return "left_handed_mass_bias"
if chi == "right": return "right_handed_vector_bias"
return "achiral_stable"
# 8-strand default chiral assignments (from BraidStateN.lean rossbyLabels8)
# Cycles through phases 0..315 for strands 0..7
DEFAULT_PHASES_8 = PHASE_ANGLES # [0, 45, 90, 135, 180, 225, 270, 315]
def rossby_drift(chiral_labels):
"""Compute Rossby drift from per-strand chiral labels.
(Python port of rossbyDriftFromChirality from BraidStateN.lean)
Returns (asymmetry_q16, is_active)."""
total = 0
for label in chiral_labels:
total += ROSSBY_WEIGHTS.get(label, 0)
return total, total != 0
def helical_residue(k):
"""Helical boundary residue at step k: ⌊k·ψ⌋ mod 28.
(Python port of helicalResidue from HopfFibration.lean)"""
return ((k * Q16_GOLDEN_ANGLE) // Q16_ONE) % EXOTIC_CLASSES
def quaternion_multiply(q1, q2):
"""Multiply two Q16_16 quaternions (a,b,c,d) where q = a + bi + cj + dk.
All integer arithmetic, result scaled by Q16_ONE (divide at end)."""
a1, b1, c1, d1 = q1
a2, b2, c2, d2 = q2
# Hamilton product: (a1a2 - b1b2 - c1c2 - d1d2) + ...i + ...j + ...k
a = (a1*a2 - b1*b2 - c1*c2 - d1*d2) // Q16_ONE
b = (a1*b2 + b1*a2 + c1*d2 - d1*c2) // Q16_ONE
c = (a1*c2 - b1*d2 + c1*a2 + d1*b2) // Q16_ONE
d = (a1*d2 + b1*c2 - c1*b2 + d1*a2) // Q16_ONE
return (a, b, c, d)
# ── Config: the unit that flows through the pipeline ──────────────────
@dataclass
class Config:
"""A single configuration flowing through the pipeline."""
chiral: tuple # per-strand ChiralLabel string tuple
phases: tuple # per-strand phase angles (0,45,...,315)
labels: tuple # Sidon label integers
S: int # reflection point
moduli: tuple # CRT moduli
cost: int = 0
self_loop: int = 0 # Q16_16 raw
sidon_score: int = 0 # Q16_16 raw
collisions: int = 0
rossby_drift: int = 0 # Q16_16 raw
helical_residue: int = 0 # 0..27
metadata: dict = field(default_factory=dict)
# ── Pipeline Context ──────────────────────────────────────────────────
@dataclass
class PipelineContext:
crossing_pairs: tuple = ()
groups: tuple = ()
seed: int = 0
stage_timings: dict = field(default_factory=dict)
# ── Filter interface ──────────────────────────────────────────────────
class Filter(ABC):
@abstractmethod
def apply(self, configs: list[Config], ctx: PipelineContext) -> list[Config]: ...
@property
@abstractmethod
def name(self) -> str: ...
def run_stage(self, configs, ctx):
t0 = time.time()
result = self.apply(configs, ctx)
ctx.stage_timings[self.name] = {
"input": len(configs), "output": len(result),
"time_s": round(time.time() - t0, 4)}
return result
# ── Stage 1: BraidStorm — Generate chiral configurations ─────────────
class BraidStorm(Filter):
"""Generates chiral configurations by assigning ChiralLabels to strands.
Each strand gets a phase angle from Z/360Z (45° steps). The chiral
label is DERIVED from the phase (HachimojiBase.lean). Different phase
assignments = different chiral configurations.
For 8 strands with 8 phases: 8! = 40320 permutations (too many).
Use k swap positions: 2^k configurations from positional swaps.
"""
def __init__(self, k=8):
self.k = k
@property
def name(self): return f"BraidStorm(k={self.k})"
def apply(self, configs, ctx):
if not configs: return []
template = configs[0]
# Generate 2^k chiral configs via positional swaps
all_swaps = list(product([0, 1], repeat=self.k))
result = []
for swap_config in all_swaps:
phases = list(template.phases)
# Apply swaps: swap[j]=1 swaps phases[j] and phases[j+1]
for j in range(min(self.k, len(phases)-1)):
if swap_config[j] == 1:
phases[j], phases[j+1] = phases[j+1], phases[j]
chiral = tuple(chiral_label_from_phase(p) for p in phases)
result.append(Config(
chiral=chiral, phases=tuple(phases),
labels=template.labels, S=template.S, moduli=template.moduli))
return result
# ── Stage 2: TreeBraid — Factorize via braid relations ────────────────
class TreeBraid(Filter):
"""Factorize crossing space. σ_i σ_j = σ_j σ_i when |i-j| >= 2."""
@property
def name(self): return "TreeBraid"
def apply(self, configs, ctx):
if not configs: return []
k = self.k = len(configs[0].phases) - 1
pairs = tuple((i, i+1) for i in range(k))
ctx.crossing_pairs = pairs
groups = self._factorize(k, pairs)
ctx.groups = groups
for c in configs:
c.metadata["groups"] = groups
return configs
def _factorize(self, k, pairs):
groups, remaining = [], list(range(k))
while remaining:
group = [remaining[0]]
for idx in remaining[1:]:
si, sj = pairs[idx]
if all(abs(si - pairs[g][0]) >= 2 and abs(si - pairs[g][1]) >= 2 and
abs(sj - pairs[g][0]) >= 2 and abs(sj - pairs[g][1]) >= 2
for g in group):
group.append(idx)
for g in group: remaining.remove(g)
groups.append(tuple(group))
return tuple(groups)
# ── Stage 3: AngrySphinx — Resource budget ───────────────────────────
class AngrySphinx(Filter):
"""Filter by compute budget. Cost = 2^(scarred+left+right count)."""
def __init__(self, budget=128): self.budget = budget
@property
def name(self): return f"AngrySphinx(budget={self.budget})"
def apply(self, configs, ctx):
result = []
for c in configs:
active = sum(1 for cl in c.chiral if cl != "achiral_stable")
c.cost = 1 << active
if c.cost <= self.budget: result.append(c)
return result
# ── Stage 4: MultisurfacePacker ───────────────────────────────────────
class MultisurfacePacker(Filter):
def __init__(self, max_surfaces=64): self.max_surfaces = max_surfaces
@property
def name(self): return f"MultisurfacePacker(max={self.max_surfaces})"
def apply(self, configs, ctx):
if len(configs) <= self.max_surfaces: return configs
return sorted(configs, key=lambda c: c.cost)[:self.max_surfaces]
# ── Stage 5: COUCH — Geometric stability via Rossby drift ─────────────
class COUCHFilter(Filter):
"""COUCH gate: two-stage stability check.
Stage A — Rossby/Kelvin regime check (from BraidStateN.lean):
- Rossby drift ≠ 0 → Rossby regime (dispersive, active mixing) → PASS
- Rossby drift = 0 → Kelvin regime (boundary-trapped, NO mixing) → FAIL
The Kelvin regime is the degenerate case: perfectly balanced chiral
distribution (left+right cancel, no scarred). Energy dissipation rate
is ZERO (proven: rossby_energy_dissipation_rate requires isActive).
This is the "q=1 degenerate" / "rational surface" / "AVX-512 stuck"
case — the system can't mix.
rossbyLabels8 (BraidStateN.lean line 327): alternating left/right
→ drift ≠ 0 → Rossby → dispersive → COUCH passes
kelvinLabels8 (BraidStateN.lean line 338): all achiral_stable
→ drift = 0 → Kelvin → boundary-trapped → COUCH fails
Stage B — Scarred contention check (from HCMR):
- scarred_count → self_loop proxy → threshold check
- High scarred count = high contention = AVX-512 regime
A config passes COUCH iff BOTH stages pass.
"""
def __init__(self, threshold=Q16_THRESHOLD_COUCH): self.threshold = threshold
@property
def name(self): return f"COUCH(threshold={self.threshold})"
def apply(self, configs, ctx):
result = []
for c in configs:
# Stage A: Rossby/Kelvin regime
drift, is_active = rossby_drift(c.chiral)
c.rossby_drift = drift
if not is_active:
# Kelvin regime: boundary-trapped, no mixing → COUCH FAILS
c.metadata["regime"] = "kelvin"
c.self_loop = Q16_AVX_SELFLOOP # stuck, like AVX-512
continue
c.metadata["regime"] = "rossby"
# Stage B: scarred contention
scarred_count = sum(1 for cl in c.chiral if cl == "chiral_scarred")
c.self_loop = (Q16_AVX_SELFLOOP * scarred_count) // max(len(c.chiral), 1)
if c.self_loop >= self.threshold:
continue # too much contention
# Helical residue (winding mod 28, from HopfFibration.lean)
step = c.metadata.get("step", 0)
c.helical_residue = helical_residue(step)
result.append(c)
return result
# ── Stage 6: Sidon Filter — Algebraic uniqueness ──────────────────────
class SidonFilter(Filter):
"""Sidon filter using CRT reconstruction.
The chiral configuration determines which phase (and thus which
ChiralLabel) is at each strand position. Different permutations
pair different labels with different moduli (position-dependent).
This is NOT a ring automorphism — it's a positional permutation
on the sphere (S² via Fisher-Rao embedding p → 2√p).
"""
@property
def name(self): return "SidonFilter"
def apply(self, configs, ctx):
result = []
for c in configs:
embedded = self._embed(c)
collisions = self._sidon_check(embedded, c.moduli)
c.collisions = collisions
total = len(c.labels) * (len(c.labels) + 1) // 2
c.sidon_score = Q16_ONE - (Q16_ONE * collisions) // max(total, 1)
if collisions == 0: result.append(c)
return result
def _embed(self, c):
"""CRT embed with positional chirality.
The phase at each position determines the ChiralLabel, which
determines the quaternion basis (1,i,j,k) for the Hopf fibration.
The CRT modulus at each position encodes the geometric constraint
at that spherical position."""
embedded = []
for pos, (label, phase) in enumerate(zip(c.labels, c.phases)):
chiral_label = chiral_label_from_phase(phase)
quat = QUATERNION_BASIS[chiral_label]
# CRT: identity = label % L0, reflection = (S-label) % Lj
row = [label % c.moduli[0]]
for j in range(1, len(c.moduli)):
row.append((c.S - label) % c.moduli[j])
# Store quaternion alongside CRT residues
embedded.append({"residues": row, "quaternion": quat,
"chiral": chiral_label, "phase": phase})
return embedded
def _sidon_check(self, embedded, moduli):
"""Check Sidon on CRT sums (proven chiral-invariant for negation,
but positional permutation of phases changes which label gets
which modulus, which CAN break Sidon)."""
M = 1
for m in moduli: M *= m
vals = [self._crt_reconstruct(e["residues"], moduli) for e in embedded]
sums = []
for i in range(len(vals)):
for j in range(i, len(vals)):
sums.append((vals[i] + vals[j]) % M)
counts = Counter(sums)
return sum(cnt - 1 for cnt in counts.values())
def _crt_reconstruct(self, residues, moduli):
M = 1
for m in moduli: M *= m
x = 0
for r, m in zip(residues, moduli):
Mi = M // m
inv = self._modinv(Mi % m, m)
if inv is None: return 0
x = (x + r * Mi * inv) % M
return x
def _egcd(self, a, b):
if b == 0: return a, 1, 0
g, x, y = self._egcd(b, a % b)
return g, y, x - (a // b) * y
def _modinv(self, a, m):
g, x, _ = self._egcd(a % m, m)
return x % m if g == 1 else None
# ── Swappable: Quaternion Product Sidon Filter ────────────────────────
class QuaternionSidonFilter(SidonFilter):
"""Sidon filter using quaternion products (not CRT sums).
Uses the ACTUAL quaternion basis mapping from HopfFibration.lean:
achiral_stable → 1, left → i, right → j, scarred → k
The quaternion product q_i · q_j is NOT invariant under positional
permutation (because different positions have different chiral labels
→ different quaternion basis elements → different products).
This is the filter that actually discriminates chiral configurations.
"""
@property
def name(self): return "QuaternionSidonFilter"
def _sidon_check(self, embedded, moduli):
"""Check Sidon on quaternion products (Hamilton product).
Two pairs (i,j) and (k,l) collide if q_i·q_j = q_k·q_l."""
n = len(embedded)
products = []
for i in range(n):
for j in range(i, n):
qi = embedded[i]["quaternion"]
qj = embedded[j]["quaternion"]
prod = quaternion_multiply(qi, qj)
products.append(prod)
counts = Counter(products)
return sum(cnt - 1 for cnt in counts.values())
# ── Pipeline ──────────────────────────────────────────────────────────
class Pipeline:
def __init__(self, filters): self.filters = filters
def run(self, labels, S, moduli, phases=None):
t0 = time.time()
ctx = PipelineContext(seed=hash((tuple(labels), S, tuple(moduli))) % (2**31))
if phases is None:
phases = tuple(DEFAULT_PHASES_8[:len(labels)])
configs = [Config(
chiral=tuple(chiral_label_from_phase(p) for p in phases),
phases=phases, labels=tuple(labels), S=S, moduli=tuple(moduli))]
for f in self.filters:
configs = f.run_stage(configs, ctx)
elapsed = time.time() - t0
result = {
"experiment": "pipeline_core",
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
"stages": [f.name for f in self.filters],
"labels": list(labels), "S": S, "moduli": list(moduli),
"phases": list(phases),
"stage_timings": ctx.stage_timings,
"total_output": len(configs),
"elapsed_s": round(elapsed, 4),
"final_configs": [{
"phases": list(c.phases),
"chiral": list(c.chiral),
"rossby_drift": c.rossby_drift,
"helical_residue": c.helical_residue,
"self_loop": c.self_loop,
"sidon_score": c.sidon_score,
"collisions": c.collisions,
} for c in configs[:20]], # first 20 for brevity
}
content = json.dumps(result, indent=2, sort_keys=True, default=str)
result["sha256"] = hashlib.sha256(content.encode()).hexdigest()
print(f"\n{'='*60}")
print(f" PIPELINE: {''.join(f.name for f in self.filters)}")
print(f"{'='*60}")
for s, t in ctx.stage_timings.items():
print(f" {s:35s} {t['input']:6d}{t['output']:6d} ({t['time_s']:.4f}s)")
print(f"{'='*60}")
print(f" Total output: {len(configs)} ({elapsed:.2f}s)")
print(f"{'='*60}")
return result
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description="Module-swappable pipeline")
parser.add_argument("--strands", type=int, default=8)
parser.add_argument("--budget", type=int, default=128)
parser.add_argument("--surfaces", type=int, default=64)
parser.add_argument("--filter", choices=["crt", "quat"], default="crt")
parser.add_argument("--output", default="pipeline_result.json")
args = parser.parse_args()
labels = [1, 2, 4, 8, 16, 32, 64, 128]
S = 128
moduli = [7, 3, 5, 11, 13, 17, 19, 23, 29]
phases = tuple(DEFAULT_PHASES_8[:len(labels)])
sidon = SidonFilter() if args.filter == "crt" else QuaternionSidonFilter()
pipe = Pipeline([
BraidStorm(k=args.strands),
TreeBraid(),
AngrySphinx(budget=args.budget),
MultisurfacePacker(max_surfaces=args.surfaces),
COUCHFilter(),
sidon,
])
result = pipe.run(labels=labels, S=S, moduli=moduli, phases=phases)
(ARTIFACTS_DIR / "pipeline_result.json").write_text(
json.dumps(result, indent=2, default=str))
print(f"\nResults → {ARTIFACTS_DIR / 'pipeline_result.json'}")