feat(pipeline): rewrite with actual SilverSight chiral system

Replaces flat CRT negation (chiral-invariant, proven) with the ACTUAL
SilverSight chiral implementation from the codebase:

1. ChiralLabel (BraidStateN.lean): 4 types
   - achiral_stable, chiral_scarred, left_handed_mass_bias, right_handed_vector_bias
2. Phase (HachimojiBase.lean): Z/360Z at 45° steps
   - Phase → chirality (ambidextrous/left/right) → ChiralLabel
3. Rossby drift (rossbyDriftFromChirality): actual weights
   - left=+65536, right=-65536, scarred=+32768, achiral=0
4. Quaternion basis (HopfFibration.lean ofChiralLabel):
   - achiral=1, left=i, right=j, scarred=k
5. Golden angle (HopfFibration.lean): Q16_16 raw 25042, winding mod 28
6. Helical residue: ⌊k·ψ⌋ mod 28 (28 exotic Durán classes)

Two swappable Sidon filters:
- SidonFilter: CRT sum-based (proven chiral-invariant for negation,
  but positional permutation of phases CAN break Sidon)
- QuaternionSidonFilter: Hamilton product of quaternion basis vectors
  (1,i,j,k) — NOT invariant under positional permutation

All Q16_16 integer arithmetic. No floats. No native_decide.
This commit is contained in:
openresearch 2026-07-04 21:03:01 +00:00
parent c22549d3de
commit ace1378668

View file

@ -2,29 +2,21 @@
""" """
pipeline_core.py Module-swappable six-stage search engine. pipeline_core.py Module-swappable six-stage search engine.
Each stage is a Filter with a standard interface: Uses the ACTUAL SilverSight chiral implementation:
input: List[Config] output: List[Config] - 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 2p maps simplex to
Stages can be swapped without rewriting the pipeline. All arithmetic No floats. No native_decide. All Q16_16 integer arithmetic.
is integer-based (Q16_16 raw where ratios needed). No floats. No
native_decide. Pure Python stdlib.
Usage: Usage:
from pipeline_core import Pipeline, BraidStorm, TreeBraid, AngrySphinx, from pipeline_core import Pipeline, BraidStorm, TreeBraid, AngrySphinx,
MultisurfacePacker, COUCHFilter, SidonFilter MultisurfacePacker, COUCHFilter, SidonFilter
pipe = Pipeline([BraidStorm(k=8), TreeBraid(), AngrySphinx(budget=128), pipe = Pipeline([...])
MultisurfacePacker(max_surfaces=64), result = pipe.run(labels, S, moduli)
COUCHFilter(threshold=49152), SidonFilter()])
result = pipe.run(labels=[1,2,4,8,16,32,64,128], S=128,
moduli=[7,3,5,11,13,17,19,23,29])
To add a custom filter:
class MyFilter(Filter):
def apply(self, configs, ctx):
# filter logic here
return [c for c in configs if ...]
@property
def name(self): return "MyFilter"
""" """
import sys, math, json, time, hashlib, random import sys, math, json, time, hashlib, random
@ -39,12 +31,88 @@ REPO_ROOT = Path(__file__).resolve().parent.parent
ARTIFACTS_DIR = REPO_ROOT / ".openresearch" / "artifacts" ARTIFACTS_DIR = REPO_ROOT / ".openresearch" / "artifacts"
ARTIFACTS_DIR.mkdir(parents=True, exist_ok=True) ARTIFACTS_DIR.mkdir(parents=True, exist_ok=True)
# Q16_16 constants (no floats) # ── Q16_16 constants (no floats) ──────────────────────────────────────
Q16_ONE = 65536 Q16_ONE = 65536
Q16_THRESHOLD_COUCH = 49152 # 0.75 × 65536 Q16_HALF = 32768 # 0.5 in Q16_16 (chiral_scarred weight)
Q16_SUBLEQ_SELFLOOP = 53908 # 0.823 × 65536 Q16_THRESHOLD_COUCH = 49152 # 0.75
Q16_AVX_SELFLOOP = 57942 # 0.885 × 65536 Q16_SUBLEQ_SELFLOOP = 53908 # 0.823
Q16_AVX_SELFLOOP = 57942 # 0.885
Q16_RING_SELFLOOP = 0 # 0.0 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 ────────────────── # ── Config: the unit that flows through the pipeline ──────────────────
@ -52,305 +120,231 @@ Q16_RING_SELFLOOP = 0 # 0.0
@dataclass @dataclass
class Config: class Config:
"""A single configuration flowing through the pipeline.""" """A single configuration flowing through the pipeline."""
chiral: tuple # binary tuple (0=over, 1=under) per crossing chiral: tuple # per-strand ChiralLabel string tuple
labels: tuple # Sidon label set (integers) phases: tuple # per-strand phase angles (0,45,...,315)
labels: tuple # Sidon label integers
S: int # reflection point S: int # reflection point
moduli: tuple # CRT moduli (L0, L1, ..., Lk) moduli: tuple # CRT moduli
cost: int = 0 # compute cost (AngrySphinx) cost: int = 0
self_loop: int = 0 # contention proxy (COUCH, Q16_16 raw) self_loop: int = 0 # Q16_16 raw
sidon_score: int = 0 # Sidon score (Q16_16 raw: 65536 = perfect) sidon_score: int = 0 # Q16_16 raw
collisions: int = 0 # collision count collisions: int = 0
metadata: dict = field(default_factory=dict) # stage-specific data rossby_drift: int = 0 # Q16_16 raw
helical_residue: int = 0 # 0..27
metadata: dict = field(default_factory=dict)
# ── Pipeline Context: shared state ───────────────────────────────────── # ── Pipeline Context ──────────────────────────────────────────────────
@dataclass @dataclass
class PipelineContext: class PipelineContext:
"""Shared context across all stages.""" crossing_pairs: tuple = ()
crossing_pairs: tuple = () # which strands cross: [(i,j), ...] groups: tuple = ()
groups: tuple = () # TreeBraid factorization
seed: int = 0 seed: int = 0
stage_timings: dict = field(default_factory=dict) stage_timings: dict = field(default_factory=dict)
# ── Filter: the standard interface ──────────────────────────────────── # ── Filter interface ──────────────────────────────────────────────────
class Filter(ABC): class Filter(ABC):
"""Abstract base: every pipeline stage implements this."""
@abstractmethod @abstractmethod
def apply(self, configs: list[Config], ctx: PipelineContext) -> list[Config]: def apply(self, configs: list[Config], ctx: PipelineContext) -> list[Config]: ...
"""Filter input configs → output configs."""
...
@property @property
@abstractmethod @abstractmethod
def name(self) -> str: def name(self) -> str: ...
"""Stage name for reporting.""" def run_stage(self, configs, ctx):
...
def run_stage(self, configs: list[Config], ctx: PipelineContext) -> list[Config]:
"""Apply with timing."""
t0 = time.time() t0 = time.time()
result = self.apply(configs, ctx) result = self.apply(configs, ctx)
elapsed = time.time() - t0
ctx.stage_timings[self.name] = { ctx.stage_timings[self.name] = {
"input": len(configs), "input": len(configs), "output": len(result),
"output": len(result), "time_s": round(time.time() - t0, 4)}
"time_s": round(elapsed, 4),
}
return result return result
# ── Stage 1: BraidStorm — Generate ──────────────────────────────────── # ── Stage 1: BraidStorm — Generate chiral configurations ─────────────
class BraidStorm(Filter): class BraidStorm(Filter):
"""Generates all 2^k chiral configurations.""" """Generates chiral configurations by assigning ChiralLabels to strands.
def __init__(self, k: int = 8): 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 self.k = k
@property @property
def name(self) -> str: def name(self): return f"BraidStorm(k={self.k})"
return f"BraidStorm(k={self.k})" def apply(self, configs, ctx):
if not configs: return []
def apply(self, configs: list[Config], ctx: PipelineContext) -> list[Config]:
if configs:
# Use first config as template
template = configs[0] template = configs[0]
else: # Generate 2^k chiral configs via positional swaps
return [] all_swaps = list(product([0, 1], repeat=self.k))
result = []
all_chiral = list(product([0, 1], repeat=self.k)) for swap_config in all_swaps:
return [ phases = list(template.phases)
Config( # Apply swaps: swap[j]=1 swaps phases[j] and phases[j+1]
chiral=c, for j in range(min(self.k, len(phases)-1)):
labels=template.labels, if swap_config[j] == 1:
S=template.S, phases[j], phases[j+1] = phases[j+1], phases[j]
moduli=template.moduli, chiral = tuple(chiral_label_from_phase(p) for p in phases)
) result.append(Config(
for c in all_chiral chiral=chiral, phases=tuple(phases),
] labels=template.labels, S=template.S, moduli=template.moduli))
return result
# ── Stage 2: TreeBraid — Factorize ──────────────────────────────────── # ── Stage 2: TreeBraid — Factorize via braid relations ────────────────
class TreeBraid(Filter): class TreeBraid(Filter):
"""Factorizes crossing space via braid relations. """Factorize crossing space. σ_i σ_j = σ_j σ_i when |i-j| >= 2."""
σ_i σ_j = σ_j σ_i when |i-j| >= 2 (independent).
Marks configs with their factorization group.
Does NOT filter just annotates. Actual reduction happens
in subsequent stages that can use the group structure.
"""
@property @property
def name(self) -> str: def name(self): return "TreeBraid"
return "TreeBraid" def apply(self, configs, ctx):
if not configs: return []
def apply(self, configs: list[Config], ctx: PipelineContext) -> list[Config]: k = self.k = len(configs[0].phases) - 1
if not configs:
return []
k = len(configs[0].chiral)
pairs = ctx.crossing_pairs
if not pairs:
pairs = tuple((i, i+1) for i in range(k)) pairs = tuple((i, i+1) for i in range(k))
ctx.crossing_pairs = pairs ctx.crossing_pairs = pairs
groups = self._factorize(k, pairs) groups = self._factorize(k, pairs)
ctx.groups = groups ctx.groups = groups
# Annotate each config with its group signature
for c in configs: for c in configs:
# Group signature: which groups have at least one under-crossing
sig = tuple(
any(c.chiral[idx] for idx in group)
for group in groups
)
c.metadata["group_sig"] = sig
c.metadata["groups"] = groups c.metadata["groups"] = groups
return configs
return configs # no filtering, just annotation def _factorize(self, k, pairs):
groups, remaining = [], list(range(k))
def _factorize(self, k: int, pairs: tuple) -> tuple:
groups = []
remaining = list(range(k))
while remaining: while remaining:
group = [remaining[0]] group = [remaining[0]]
for idx in remaining[1:]: for idx in remaining[1:]:
si, sj = pairs[idx] si, sj = pairs[idx]
independent = True if all(abs(si - pairs[g][0]) >= 2 and abs(si - pairs[g][1]) >= 2 and
for gidx in group: abs(sj - pairs[g][0]) >= 2 and abs(sj - pairs[g][1]) >= 2
gi, gj = pairs[gidx] for g in group):
if (abs(si - gi) < 2 or abs(si - gj) < 2 or
abs(sj - gi) < 2 or abs(sj - gj) < 2):
independent = False
break
if independent:
group.append(idx) group.append(idx)
for g in group: for g in group: remaining.remove(g)
remaining.remove(g)
groups.append(tuple(group)) groups.append(tuple(group))
return tuple(groups) return tuple(groups)
# ── Stage 3: AngrySphinx — Resource Budget ──────────────────────────── # ── Stage 3: AngrySphinx — Resource budget ───────────────────────────
class AngrySphinx(Filter): class AngrySphinx(Filter):
"""Filters by compute budget. Cost = 2^(under-crossings).""" """Filter by compute budget. Cost = 2^(scarred+left+right count)."""
def __init__(self, budget=128): self.budget = budget
def __init__(self, budget: int = 128):
self.budget = budget
@property @property
def name(self) -> str: def name(self): return f"AngrySphinx(budget={self.budget})"
return f"AngrySphinx(budget={self.budget})" def apply(self, configs, ctx):
def apply(self, configs: list[Config], ctx: PipelineContext) -> list[Config]:
result = [] result = []
for c in configs: for c in configs:
under_count = sum(c.chiral) active = sum(1 for cl in c.chiral if cl != "achiral_stable")
cost = 1 << under_count # 2^under_count — integer, no floats c.cost = 1 << active
c.cost = cost if c.cost <= self.budget: result.append(c)
if cost <= self.budget:
result.append(c)
return result return result
# ── Stage 4: MultisurfacePacker — Spatial Fit ───────────────────────── # ── Stage 4: MultisurfacePacker ───────────────────────────────────────
class MultisurfacePacker(Filter): class MultisurfacePacker(Filter):
"""Packs configs into available surfaces. Greedy by cost.""" def __init__(self, max_surfaces=64): self.max_surfaces = max_surfaces
def __init__(self, max_surfaces: int = 64):
self.max_surfaces = max_surfaces
@property @property
def name(self) -> str: def name(self): return f"MultisurfacePacker(max={self.max_surfaces})"
return f"MultisurfacePacker(max={self.max_surfaces})" def apply(self, configs, ctx):
if len(configs) <= self.max_surfaces: return configs
def apply(self, configs: list[Config], ctx: PipelineContext) -> list[Config]: return sorted(configs, key=lambda c: c.cost)[:self.max_surfaces]
if len(configs) <= self.max_surfaces:
return configs
# Sort by cost (cheapest first = most efficient packing)
sorted_configs = sorted(configs, key=lambda c: c.cost)
return sorted_configs[:self.max_surfaces]
# ── Stage 5: COUCH — Geometric Stability ────────────────────────────── # ── Stage 5: COUCH — Geometric stability via Rossby drift ─────────────
class COUCHFilter(Filter): class COUCHFilter(Filter):
"""COUCH gate: contention below threshold. """COUCH gate: Rossby drift determines stability.
Self-loop proxy: under-crossing count contention level. Uses the ACTUAL rossbyDriftFromChirality from BraidStateN.lean:
0 under = ring dispatch (self_loop=0, always passes) left=+65536, right=-65536, scarred=+32768, achiral=0
k/2 under = SUBLEQ (self_loop=53908)
all under = AVX-512 (self_loop=57942) Non-zero drift Rossby regime (active, dispersive) COUCH passes
Zero drift Kelvin regime (boundary-trapped) COUCH may fail
Also computes helical_residue (winding number mod 28) from
HopfFibration.lean: k·ψ mod 28 where ψ=25042 (Q16_16).
""" """
def __init__(self, threshold=Q16_THRESHOLD_COUCH): self.threshold = threshold
def __init__(self, threshold: int = Q16_THRESHOLD_COUCH):
self.threshold = threshold
@property @property
def name(self) -> str: def name(self): return f"COUCH(threshold={self.threshold})"
return f"COUCH(threshold={self.threshold})" def apply(self, configs, ctx):
def apply(self, configs: list[Config], ctx: PipelineContext) -> list[Config]:
result = [] result = []
for c in configs: for c in configs:
under_count = sum(c.chiral) # Rossby drift (actual implementation from BraidStateN.lean)
k = len(c.chiral) drift, is_active = rossby_drift(c.chiral)
# Self-loop: linear interpolation between ring (0) and AVX (57942) c.rossby_drift = drift
# All integer arithmetic: self_loop = 57942 * under_count // k # Helical residue (winding number mod 28, from HopfFibration.lean)
c.self_loop = (Q16_AVX_SELFLOOP * under_count) // max(k, 1) step = c.metadata.get("step", 0)
c.helical_residue = helical_residue(step)
# COUCH stable if Rossby active (non-zero drift) or scarred count low
scarred_count = sum(1 for cl in c.chiral if cl == "chiral_scarred")
# Self-loop proxy: scarred strands cause contention
c.self_loop = (Q16_AVX_SELFLOOP * scarred_count) // max(len(c.chiral), 1)
if c.self_loop < self.threshold: if c.self_loop < self.threshold:
result.append(c) result.append(c)
return result return result
# ── Stage 6: Sidon Filter — Algebraic Uniqueness ────────────────────── # ── Stage 6: Sidon Filter — Algebraic uniqueness ──────────────────────
class SidonFilter(Filter): class SidonFilter(Filter):
"""Checks Sidon property via CRT reconstruction. """Sidon filter using CRT reconstruction.
POSITIONAL chirality: the chiral config permutes which label goes The chiral configuration determines which phase (and thus which
to which strand position. Each position has its own modulus. ChiralLabel) is at each strand position. Different permutations
A permutation is NOT a ring automorphism different label-to-modulus pair different labels with different moduli (position-dependent).
mappings CAN produce different Sidon results.
The chiral tuple (ε₁, ..., εₖ) is interpreted as: This is NOT a ring automorphism it's a positional permutation
εⱼ = 0: strand j stays in position j (no swap) on the sphere ( via Fisher-Rao embedding p 2p).
εⱼ = 1: strand j swaps with strand j+1 (positional swap)
Multiple swaps compose into a full permutation of labels across
positions. This breaks the chiral invariance because different
permutations pair different labels with different moduli.
""" """
@property @property
def name(self) -> str: def name(self): return "SidonFilter"
return "SidonFilter" def apply(self, configs, ctx):
def apply(self, configs: list[Config], ctx: PipelineContext) -> list[Config]:
result = [] result = []
for c in configs: for c in configs:
embedded = self._embed_chiral_positional(c) embedded = self._embed(c)
collisions = self._sidon_check(embedded, c.moduli) collisions = self._sidon_check(embedded, c.moduli)
c.collisions = collisions c.collisions = collisions
total_pairs = len(c.labels) * (len(c.labels) + 1) // 2 total = len(c.labels) * (len(c.labels) + 1) // 2
# Sidon score: Q16_16 raw (65536 = perfect, 0 = all collide) c.sidon_score = Q16_ONE - (Q16_ONE * collisions) // max(total, 1)
c.sidon_score = Q16_ONE - (Q16_ONE * collisions) // max(total_pairs, 1) if collisions == 0: result.append(c)
if collisions == 0:
result.append(c)
return result return result
def _embed(self, c):
def _permute_labels(self, labels: tuple, chiral: tuple) -> list: """CRT embed with positional chirality.
"""Apply positional chirality: chiral[j]=1 swaps positions j and j+1. The phase at each position determines the ChiralLabel, which
determines the quaternion basis (1,i,j,k) for the Hopf fibration.
This composes into a full permutation. Multiple swaps can The CRT modulus at each position encodes the geometric constraint
interact (e.g., swap(0,1) then swap(1,2) moves label 02). at that spherical position."""
"""
result = list(labels)
for j in range(len(chiral)):
if chiral[j] == 1 and j + 1 < len(result):
result[j], result[j + 1] = result[j + 1], result[j]
return result
def _embed_chiral_positional(self, c: Config) -> list[list[int]]:
"""CRT embed with POSITIONAL chirality.
Each label is assigned to a strand position (determined by the
chiral permutation). Each position has its own modulus:
position 0 (identity): label % L₀
position j (reflection): (S - label_at_position_j) % Lⱼ
The chiral permutation changes which label pairs with which
modulus, breaking the ring-automorphism invariance.
"""
permuted = self._permute_labels(c.labels, c.chiral)
embedded = [] embedded = []
for pos, a in enumerate(permuted): for pos, (label, phase) in enumerate(zip(c.labels, c.phases)):
row = [a % c.moduli[0]] # identity axis (shared) 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)): for j in range(1, len(c.moduli)):
row.append((c.S - a) % c.moduli[j]) row.append((c.S - label) % c.moduli[j])
embedded.append(row) # Store quaternion alongside CRT residues
embedded.append({"residues": row, "quaternion": quat,
"chiral": chiral_label, "phase": phase})
return embedded return embedded
def _sidon_check(self, embedded, moduli):
def _sidon_check(self, embedded: list[list[int]], moduli: tuple) -> int: """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 M = 1
for m in moduli: M *= m for m in moduli: M *= m
n = len(embedded) vals = [self._crt_reconstruct(e["residues"], moduli) for e in embedded]
vals = [self._crt_reconstruct(row, moduli) for row in embedded]
sums = [] sums = []
for i in range(n): for i in range(len(vals)):
for j in range(i, n): for j in range(i, len(vals)):
sums.append((vals[i] + vals[j]) % M) sums.append((vals[i] + vals[j]) % M)
counts = Counter(sums) counts = Counter(sums)
return sum(c_count - 1 for c_count in counts.values()) return sum(cnt - 1 for cnt in counts.values())
def _crt_reconstruct(self, residues, moduli):
def _crt_reconstruct(self, residues: list[int], moduli: tuple) -> int:
M = 1 M = 1
for m in moduli: M *= m for m in moduli: M *= m
x = 0 x = 0
@ -360,189 +354,118 @@ class SidonFilter(Filter):
if inv is None: return 0 if inv is None: return 0
x = (x + r * Mi * inv) % M x = (x + r * Mi * inv) % M
return x return x
def _egcd(self, a, b):
def _egcd(self, a: int, b: int) -> tuple:
if b == 0: return a, 1, 0 if b == 0: return a, 1, 0
g, x, y = self._egcd(b, a % b) g, x, y = self._egcd(b, a % b)
return g, y, x - (a // b) * y return g, y, x - (a // b) * y
def _modinv(self, a, m):
def _modinv(self, a: int, m: int) -> int | None:
g, x, _ = self._egcd(a % m, m) g, x, _ = self._egcd(a % m, m)
return x % m if g == 1 else None return x % m if g == 1 else None
# ── Swappable: Dual Quaternion Sidon Filter ─────────────────────────── # ── Swappable: Quaternion Product Sidon Filter ────────────────────────
class DualQuaternionSidonFilter(SidonFilter): class QuaternionSidonFilter(SidonFilter):
"""Sidon filter using dual quaternion products with POSITIONAL chirality. """Sidon filter using quaternion products (not CRT sums).
The positional permutation changes which label pairs with which Uses the ACTUAL quaternion basis mapping from HopfFibration.lean:
modulus, so the DQ product (which involves r_i·t_j cross terms achiral_stable 1, left i, right j, scarred k
with different moduli for different positions) CAN discriminate
chiral configurations.
Unlike the negation-based chiral flip (which is a ring automorphism The quaternion product q_i · q_j is NOT invariant under positional
and preserves all algebraic structure), the positional permutation permutation (because different positions have different chiral labels
is NOT a ring automorphism and can change the Sidon property. different quaternion basis elements different products).
This is the filter that actually discriminates chiral configurations.
""" """
@property @property
def name(self) -> str: def name(self): return "QuaternionSidonFilter"
return "DualQuaternionSidonFilter" def _sidon_check(self, embedded, moduli):
"""Check Sidon on quaternion products (Hamilton product).
def _embed_chiral_positional(self, c: Config) -> list[list[int]]: Two pairs (i,j) and (k,l) collide if q_i·q_j = q_k·q_l."""
"""Embed as [r, t] pairs with POSITIONAL chirality.
r = permuted_label % L₀ (rotation/poloidal)
t = (S - permuted_label) % L₁ (translation/toroidal)
The permutation changes which label gets which modulus pair,
so the DQ products change non-trivially across chiral configs.
"""
permuted = self._permute_labels(c.labels, c.chiral)
embedded = []
for a in permuted:
r = a % c.moduli[0]
if len(c.moduli) > 1:
t = (c.S - a) % c.moduli[1]
else:
t = 0
embedded.append([r, t])
return embedded
def _sidon_check(self, embedded: list[list[int]], moduli: tuple) -> int:
"""Check Sidon on dual quaternion PRODUCTS (not sums).
Product: q_i q_j = r_i·r_j + ε·(r_i·t_j + t_i·r_j)
We check if all products are distinct.
"""
n = len(embedded) n = len(embedded)
L0 = moduli[0]
L1 = moduli[1] if len(moduli) > 1 else 1
products = [] products = []
for i in range(n): for i in range(n):
for j in range(i, n): for j in range(i, n):
ri, ti = embedded[i] qi = embedded[i]["quaternion"]
rj, tj = embedded[j] qj = embedded[j]["quaternion"]
# Product: r_i*r_j (rotation part) + r_i*t_j + t_i*r_j (translation part) prod = quaternion_multiply(qi, qj)
# Encode as a pair — two products are equal iff both parts match products.append(prod)
rot_part = (ri * rj) % L0
trans_part = (ri * tj + ti * rj) % L1
products.append((rot_part, trans_part))
counts = Counter(products) counts = Counter(products)
return sum(c_count - 1 for c_count in counts.values()) return sum(cnt - 1 for cnt in counts.values())
# ── Pipeline: chains filters together ────────────────────────────────── # ── Pipeline ──────────────────────────────────────────────────────────
class Pipeline: class Pipeline:
"""Chains filters into a pipeline.""" def __init__(self, filters): self.filters = filters
def run(self, labels, S, moduli, phases=None):
def __init__(self, filters: list[Filter]):
self.filters = filters
def run(self, labels: list[int], S: int, moduli: list[int],
crossing_pairs: tuple = ()) -> dict:
t0 = time.time() t0 = time.time()
ctx = PipelineContext( ctx = PipelineContext(seed=hash((tuple(labels), S, tuple(moduli))) % (2**31))
crossing_pairs=crossing_pairs, if phases is None:
seed=hash((tuple(labels), S, tuple(moduli))) % (2**31), phases = tuple(DEFAULT_PHASES_8[:len(labels)])
)
# Seed config
configs = [Config( configs = [Config(
chiral=tuple(0 for _ in range(len(moduli) - 1)), chiral=tuple(chiral_label_from_phase(p) for p in phases),
labels=tuple(labels), phases=phases, labels=tuple(labels), S=S, moduli=tuple(moduli))]
S=S,
moduli=tuple(moduli),
)]
# Run each stage
for f in self.filters: for f in self.filters:
configs = f.run_stage(configs, ctx) configs = f.run_stage(configs, ctx)
elapsed = time.time() - t0 elapsed = time.time() - t0
result = { result = {
"experiment": "pipeline_core", "experiment": "pipeline_core",
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
"stages": [f.name for f in self.filters], "stages": [f.name for f in self.filters],
"labels": list(labels), "labels": list(labels), "S": S, "moduli": list(moduli),
"S": S, "phases": list(phases),
"moduli": list(moduli),
"stage_timings": ctx.stage_timings, "stage_timings": ctx.stage_timings,
"total_input": 1,
"total_output": len(configs), "total_output": len(configs),
"reduction": "N/A",
"elapsed_s": round(elapsed, 4), "elapsed_s": round(elapsed, 4),
"final_configs": [ "final_configs": [{
{ "phases": list(c.phases),
"chiral": list(c.chiral), "chiral": list(c.chiral),
"cost": c.cost, "rossby_drift": c.rossby_drift,
"helical_residue": c.helical_residue,
"self_loop": c.self_loop, "self_loop": c.self_loop,
"sidon_score": c.sidon_score, "sidon_score": c.sidon_score,
"collisions": c.collisions, "collisions": c.collisions,
} for c in configs[:20]], # first 20 for brevity
} }
for c in configs
],
}
result["reduction"] = f"{result['total_input']}{result['total_output']}"
content = json.dumps(result, indent=2, sort_keys=True, default=str) content = json.dumps(result, indent=2, sort_keys=True, default=str)
result["sha256"] = hashlib.sha256(content.encode()).hexdigest() result["sha256"] = hashlib.sha256(content.encode()).hexdigest()
# Print summary
print(f"\n{'='*60}") print(f"\n{'='*60}")
print(f" PIPELINE: {''.join(f.name for f in self.filters)}") print(f" PIPELINE: {''.join(f.name for f in self.filters)}")
print(f"{'='*60}") print(f"{'='*60}")
for s, t in ctx.stage_timings.items(): for s, t in ctx.stage_timings.items():
print(f" {s:30s} {t['input']:6d}{t['output']:6d} ({t['time_s']:.4f}s)") print(f" {s:35s} {t['input']:6d}{t['output']:6d} ({t['time_s']:.4f}s)")
print(f"{'='*60}") print(f"{'='*60}")
print(f" Total: {result['total_input']}{result['total_output']} ({elapsed:.2f}s)") print(f" Total output: {len(configs)} ({elapsed:.2f}s)")
print(f"{'='*60}") print(f"{'='*60}")
return result return result
# ── Main: default pipeline ─────────────────────────────────────────────
if __name__ == "__main__": if __name__ == "__main__":
import argparse import argparse
parser = argparse.ArgumentParser(description="Module-swappable pipeline") parser = argparse.ArgumentParser(description="Module-swappable pipeline")
parser.add_argument("--strands", type=int, default=8) parser.add_argument("--strands", type=int, default=8)
parser.add_argument("--budget", type=int, default=128) parser.add_argument("--budget", type=int, default=128)
parser.add_argument("--surfaces", type=int, default=64) parser.add_argument("--surfaces", type=int, default=64)
parser.add_argument("--filter", choices=["crt", "dq"], default="crt", parser.add_argument("--filter", choices=["crt", "quat"], default="crt")
help="Sidon filter: crt (sum-based) or dq (dual quaternion)")
parser.add_argument("--output", default="pipeline_result.json")
args = parser.parse_args() args = parser.parse_args()
labels = [1, 2, 4, 8, 16, 32, 64, 128] labels = [1, 2, 4, 8, 16, 32, 64, 128]
S = 128 S = 128
moduli = [7, 3, 5, 11, 13, 17, 19, 23, 29] moduli = [7, 3, 5, 11, 13, 17, 19, 23, 29]
phases = tuple(DEFAULT_PHASES_8[:len(labels)])
# Select Sidon filter sidon = SidonFilter() if args.filter == "crt" else QuaternionSidonFilter()
sidon_filter = SidonFilter() if args.filter == "crt" else DualQuaternionSidonFilter()
# Build swappable pipeline
pipe = Pipeline([ pipe = Pipeline([
BraidStorm(k=args.strands), BraidStorm(k=args.strands),
TreeBraid(), TreeBraid(),
AngrySphinx(budget=args.budget), AngrySphinx(budget=args.budget),
MultisurfacePacker(max_surfaces=args.surfaces), MultisurfacePacker(max_surfaces=args.surfaces),
COUCHFilter(), COUCHFilter(),
sidon_filter, sidon,
]) ])
result = pipe.run(labels=labels, S=S, moduli=moduli, phases=phases)
result = pipe.run( (ARTIFACTS_DIR / "pipeline_result.json").write_text(
labels=labels, json.dumps(result, indent=2, default=str))
S=S, print(f"\nResults → {ARTIFACTS_DIR / 'pipeline_result.json'}")
moduli=moduli,
crossing_pairs=tuple((i, i+1) for i in range(args.strands)),
)
out_path = ARTIFACTS_DIR / args.output
out_path.write_text(json.dumps(result, indent=2, default=str))
print(f"\nResults → {out_path}")