SilverSight/scripts/multi_strand_braid.py
allaun 3362d554d1 feat(braid/dag): land untracked research WIP + register 4 formal libs; ignore build artifacts
- lakefile.lean: register SilverSight.{AngrySphinx,CollatzBraid,GoldenSpiral,GCCL}
- docs/research/: braid group action, iteration DAG/regime, Sidon
  preservation/creation, unified CRT-torus DAG notes
- docs/diagrams/: DAG + heatmap + 8-strand search JSON/dot outputs
- formal/CoreFormalism/StrandCapacityBound.lean: capacity bound (passes
  hardened anti-smuggle --ci)
- scripts/, python/: braid word solver, collapse/DAG search + tuning,
  heatmap gen, YB search/verification, wrapping verifier
- .gitignore: exclude rust/**/target and coq compiled artifacts
  (*.vo/*.vok/*.vos/*.glob/*.aux) that were polluting the tree

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 15:11:37 -05:00

202 lines
6.5 KiB
Python
Raw 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
"""
Multi-Strand Braid Word Solver.
Full 16-modulus chiral torus: up to 8 strands, each with (L_id, L_ref).
Generates multi-strand braid words with coprimality constraints.
"""
import sys, math, itertools, random
from typing import List, Tuple
sys.path.insert(0, '/home/allaun/SilverSight/scripts')
from verify_wrapping import is_sidon
# ---------- Coprime CRT ----------
def pairwise_coprime(mods: List[int]) -> bool:
for i in range(len(mods)):
for j in range(i+1, len(mods)):
if math.gcd(mods[i], mods[j]) != 1:
return False
return True
def crt_lift(residues: List[int], moduli: List[int]) -> int:
assert pairwise_coprime(moduli), f"not coprime: {moduli}"
x = residues[0]
m = moduli[0]
for i in range(1, len(moduli)):
inv = pow(m % moduli[i], -1, moduli[i])
t = ((residues[i] - x) * inv) % moduli[i]
x += t * m
m *= moduli[i]
return x
def F_multi(a: int, S: int, moduli: List[int]) -> int:
residues = [a % moduli[0]] + [(S - a) % Li for Li in moduli[1:]]
return crt_lift(residues, moduli)
def moduli_from_pairs(pairs: List[Tuple[int,int]]) -> List[int]:
return [v for p in pairs for v in p]
# ---------- Generate valid coprime configurations ----------
PRIME_POOL = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53]
def coprime_pairs(count: int, pool: List[int] = None) -> List[Tuple[int,int]]:
"""Generate `count` coprime pairs using distinct primes."""
if pool is None:
pool = PRIME_POOL
used = set()
pairs = []
p_idx = 0
for _ in range(count):
p1, p2 = pool[p_idx], pool[p_idx+1]
pairs.append((p1, p2))
p_idx += 2
return pairs
def cross(pairs: List[Tuple[int,int]], strand: int, over: bool) -> List[Tuple]:
"""Cross strand `strand` (over or under), return new config or None."""
new = [p for p in pairs]
Li, Lr = new[strand]
if over:
new[strand] = (Li + 2, max(Lr - 1, 2))
else:
new[strand] = (max(Li - 1, 2), Lr + 2)
mods = moduli_from_pairs(new)
return new if pairwise_coprime(mods) else None
def braid_word(pairs_seq: List[List[Tuple]]) -> str:
"""Build braid word from a sequence of configurations."""
parts = []
for i in range(1, len(pairs_seq)):
prev, curr = pairs_seq[i-1], pairs_seq[i]
for s in range(len(curr)):
if curr[s] == prev[s]:
continue
Li, Lr = curr[s]
typ = "" if Li > Lr else ""
parts.append(f"σ_{s+1}{typ}")
return " · ".join(parts) if parts else "1"
# ---------- Multi-strand Sidon search ----------
def multi_search(A0: List[int], S: int, num_strands: int = 2, max_steps: int = 3):
"""BFS for multi-strand braid words to Sidon."""
init = coprime_pairs(num_strands)
queue = [(init, 0, A0, [init])]
visited = set()
results = []
while queue and len(results) < 20:
pairs, depth, A, path = queue.pop(0)
key = (tuple(pairs), tuple(A))
if key in visited: continue
visited.add(key)
mods = moduli_from_pairs(pairs)
M = 1
for m in mods: M *= m
maxA = max(A)
if M > maxA:
FA = [F_multi(a, S, mods) for a in A]
if is_sidon(FA):
results.append({
'word': braid_word(path),
'steps': depth, 'FA': FA, 'M': M,
'path': path
})
continue
if depth >= max_steps:
continue
for s in range(num_strands):
for over in [True, False]:
crossed = cross(pairs, s, over)
if crossed is None:
continue
mods2 = moduli_from_pairs(crossed)
new_A = [F_multi(a, S, mods2) for a in A]
queue.append((crossed, depth+1, new_A, path + [crossed]))
return results
# ---------- Braid axiom tests ----------
def test_involution():
"""σᵢ² = id: two over-crossings should return to original."""
print("=" * 60)
print("BRAID AXIOM TESTS")
print("=" * 60)
A0, S = [1, 2, 5, 6], 7
init = coprime_pairs(2) # [(2,3), (5,7)]
# σ₁ over then σ₁ over
s1 = cross(init, 0, True)
s1a = cross(s1, 0, True) if s1 else None
print(f"\n σ₁²: {(2,3)} → over→ {s1[0] if s1 else '? ()'}"
f" → over→ {s1a[0] if s1a else '? ()'}"
f" back to initial: {s1a == init if s1a else False}")
def test_far_commute():
"""σᵢσⱼ = σⱼσᵢ for |ij| ≥ 2: strand 1 and 3 commute."""
A0, S = [1, 2, 5, 6], 7
init = coprime_pairs(3)
print(f"\n σ₁σ₃ vs σ₃σ₁ on {init}:")
# σ₁ then σ₃
s1 = cross(init, 0, True)
s1s3 = cross(s1, 2, False) if s1 else None
# σ₃ then σ₁
s3 = cross(init, 2, False)
s3s1 = cross(s3, 0, True) if s3 else None
if s1s3 and s3s1:
# Same final configuration?
same = s1s3 == s3s1
w1 = braid_word([init, s1, s1s3])
w2 = braid_word([init, s3, s3s1])
print(f" σ₁σ₃: {w1}{s1s3}")
print(f" σ₃σ₁: {w2}{s3s1}")
print(f" Same: {same}")
def test_single_sidon():
"""Find single-step Sidon paths for each strand."""
print("\n" + "=" * 60)
print("MULTI-STRAND SIDON SEARCH (2 strands)")
print("=" * 60)
A0, S = [1, 2, 5, 6], 7
results = multi_search(A0, S, num_strands=2, max_steps=2)
print(f" Results: {len(results)}")
for r in sorted(results, key=lambda x: x['steps'])[:5]:
print(f" Word: {r['word']:20s} Steps={r['steps']} M={r['M']:4d} FA={r['FA']}")
def test_strand_interaction():
"""Test 2-strand configurations produce distinct results."""
print("\n" + "=" * 60)
print("STRAND INTERACTION")
print("=" * 60)
A0, S = [1, 2, 5, 6], 7
configs = [
([(2, 3), (5, 7)], "under, under"),
([(4, 2), (5, 7)], "over on 1, under on 2"), # but gcd(4,2)=2!
]
for pairs, desc in configs:
mods = moduli_from_pairs(pairs)
if not pairwise_coprime(mods):
continue
FA = [F_multi(a, S, mods) for a in A0]
M = 1
for m in mods: M *= m
sidon = is_sidon(FA)
print(f" {desc:30s} mods={mods} M={M:3d} Sidon={sidon} FA={FA}")
if __name__ == "__main__":
test_involution()
test_far_commute()
test_single_sidon()
test_strand_interaction()