#!/usr/bin/env python3 """ Braid Word Solver: maps DAG iteration paths to braid words. 8 strands → 16 moduli in 8 chiral pairs (L_{2i-1}, L_{2i}). Each pair: identity modulus > reflection modulus = σ_i⁺ (over-crossing). DAG path = braid word: sequence of crossings that transforms A₀ to Sidon. """ import sys, math, json from typing import List, Tuple from collections import defaultdict sys.path.insert(0, '/home/allaun/SilverSight/scripts') from verify_wrapping import f_k, is_sidon from iteration_dag import IterationDAG, AdaptiveRule, DAGNode # ---------- Braid Word Representation ---------- def moduli_to_braid_word(moduli_sequence: List[List[int]]) -> str: """Convert a sequence of modulus choices to a braid word. Each modulus vector has 2k entries (k strands, 2 axes each). A modulus pair [L_id, L_ref] for strand i encodes: - L_id > L_ref → σ_i⁺ (over-crossing, identity dominates) - L_id < L_ref → σ_i⁻ (under-crossing, reflection dominates) - Large M → active crossing (big change in configuration) - Small M → gentle crossing (small change) """ strands = len(moduli_sequence[0]) // 2 if moduli_sequence else 0 if strands == 0: return "1" # identity braid word = [] for moduli in moduli_sequence: for i in range(strands): L_id = moduli[2*i] # identity axis L_ref = moduli[2*i+1] # reflection axis if L_id > L_ref: word.append(f"σ_{i+1}⁺") elif L_ref > L_id: word.append(f"σ_{i+1}⁻") # if equal, no crossing return " · ".join(word) if word else "1" # ---------- 16D Braid Configuration ---------- class BraidConfig: """Represent a braid configuration as 8 chiral modulus pairs.""" def __init__(self, base_moduli: List[Tuple[int,int]] = None): """Initialize with 8 strand pairs. Default: all (5,3).""" if base_moduli: self.pairs = list(base_moduli) else: # Default: each strand has id=5, ref=3 (L_id > L_ref = over) self.pairs = [(5, 3)] * 8 assert len(self.pairs) == 8, "Need exactly 8 strand pairs" def to_moduli_list(self) -> List[int]: """Flatten to [L1, L2, ..., L15, L16] for CRT use.""" result = [] for L_id, L_ref in self.pairs: result.append(L_id) result.append(L_ref) return result def apply_crossing(self, strand: int, over: bool = True): """Apply σ_strand (over or under) by adjusting the pair.""" i = strand - 1 # 0-indexed L_id, L_ref = self.pairs[i] if over: # Over-crossing: identity dominates → increase identity modulus self.pairs[i] = (L_id + 2, max(L_ref - 1, 2)) else: # Under-crossing: reflection dominates → increase reflection modulus self.pairs[i] = (max(L_id - 1, 2), L_ref + 2) @staticmethod def from_moduli_list(moduli: List[int]): """Convert flat moduli list back to strand pairs.""" pairs = [] for i in range(0, len(moduli), 2): pairs.append((moduli[i], moduli[i+1])) return BraidConfig(pairs) # ---------- DAG → Braid Word Mapping ---------- def dag_path_to_braid(A0: List[int], S: int, path: List[DAGNode]) -> Tuple[str, List[BraidConfig]]: """Convert a DAG path to a braid word. Root (A₀) → node1 (A₁) → node2 (A₂) → ... Each non-root node's moduli encode the crossing applied to reach it: moduli = [L_id, L_ref, ...] L_id > L_ref → σ⁺ (over-crossing) L_id < L_ref → σ⁻ (under-crossing) Unused strands (beyond the first pair) default to idle. """ crossings = [] for i in range(1, len(path)): mods = path[i].moduli pair = (mods[0], mods[1]) if len(mods) >= 2 else (2, 2) L_id, L_ref = pair if L_id > L_ref: crossings.append("σ₁⁺") elif L_ref > L_id: crossings.append("σ₁⁻") else: crossings.append("σ₁·") braid_word = " · ".join(crossings) if crossings else "1" return braid_word def solve_braid_word(A0: List[int], S: int, max_steps: int = 4) -> dict: """Find the shortest braid word that transforms A0 to Sidon.""" rule = AdaptiveRule(max_val=16) dag = IterationDAG(A0, S, rule, max_steps=max_steps) dag.build() results = { 'A0': A0, 'S': S, 'paths': [], 'summary': {} } for path in dag.sidon_paths: braid_word = dag_path_to_braid(A0, S, path) results['paths'].append({ 'steps': len(path) - 1, 'braid_word': braid_word, 'As': [n.A for n in path], 'Ms': [n.M for n in path] }) if results['paths']: shortest = min(results['paths'], key=lambda p: p['steps']) results['summary'] = { 'total_paths': len(results['paths']), 'shortest_word': shortest['braid_word'], 'shortest_steps': shortest['steps'], 'final_set': shortest['As'][-1], 'moduli_path': shortest['Ms'] } return results # ---------- Test & Demonstration ---------- def demo_sidon_example(): """Map the known Sidon example to a braid word.""" A0, S = [1, 2, 5, 6], 7 print("=" * 60) print("BRAID WORD SOLVER — Sidon Example") print("=" * 60) result = solve_braid_word(A0, S) if result['paths']: p = result['paths'][0] # First path found print(f"\nA₀ = {result['A0']}") print(f"S = {result['S']}") print(f"\nBraid word: {p['braid_word']}") print(f"\nStep-by-step:") for i in range(len(p['As'])): sidon = " ★SIDON" if is_sidon(p['As'][i]) else "" print(f" Step {i}: A = {p['As'][i]} M = {p['Ms'][i]}{sidon}") print(f"\nSummary: {result['summary']}") def demo_complex_set(): """Map the complex set to a braid word — shows multi-step paths.""" A0, S = [0, 1, 3, 8, 13], 27 print("\n" + "=" * 60) print("BRAID WORD SOLVER — Complex Set (multi-step)") print("=" * 60) result = solve_braid_word(A0, S) if result['paths']: p = min(result['paths'], key=lambda x: x['steps']) print(f"\nA₀ = {result['A0']}") print(f"S = {result['S']}") print(f"\nShortest braid word ({p['steps']} steps): {p['braid_word']}") print(f"\nPath:") for i in range(len(p['As'])): sidon = " ★" if is_sidon(p['As'][i]) else "" print(f" {i}: A={p['As'][i]} M={p['Ms'][i]}{sidon}") print(f"\nTotal paths found: {result['summary'].get('total_paths', 0)}") def demo_braid_vs_moduli(): """Show how DAG path = braid word with modulus ordering.""" print("\n" + "=" * 60) print("BRAID WORD = DAG PATH") print("=" * 60) print() print("Each DAG step chooses moduli (L_id, L_ref) for a strand.") print("L_id > L_ref → σ⁺ (over-crossing)") print("L_id < L_ref → σ⁻ (under-crossing)") print() print("Example path:") print(" Step 1: (7, 3) → σ₁⁺ (strand 1 over-crosses, gap=7)") print(" Step 2: (11, 2) → σ₁⁺ (strand 1 over-crosses again, gap=11)") print(" Step 3: Sidon reached → braid word = σ₁⁺·σ₁⁺") print() print("The braid word IS the iteration path.") if __name__ == "__main__": demo_sidon_example() demo_complex_set() demo_braid_vs_moduli()