#!/usr/bin/env python3 """Find exact collapse depth for each strand count via DFS. Uses depth-first search with backtracking to find the maximum depth reachable before the Coprimality Guard kills all paths. """ import sys, math, time, json sys.path.insert(0, '/home/allaun/SilverSight/scripts') from full_chiral_dag import * A0 = [0, 1, 2, 3, 4, 5] S = 5 def find_collapse_depth(n_strands): pairs = chiral_pairs(n_strands=n_strands, band_gap=0, base_prime_offset=10) root = DAGNode(pairs, A0, S, depth=0) visited = {root.modulus_hash(): root} max_depth = 0 nodes_created = 1 coprimality_prunes = 0 energy_prunes = 0 dedup = 0 # DFS stack: (node, strand_idx, dir_idx) # We try crossings in a systematic order: strand 0..n-1, both directions stack = [(root, 0, 0)] path = [root] start = time.time() report_at = 0 while stack: node, s, d_idx = stack[-1] # If we exhausted all crossings at this node, backtrack if s >= n_strands: stack.pop() path.pop() continue direction = 'over' if d_idx == 0 else 'under' # Move to next crossing at this node if d_idx == 1: stack[-1] = (node, s + 1, 0) else: stack[-1] = (node, s, d_idx + 1) result = coupled_crossing(node.pairs, s, direction, A0, S) if result is None: coprimality_prunes += 1 continue new_pairs, new_energy = result child = DAGNode(pairs=new_pairs, A0=A0, S=S, depth=node.depth + 1) if child.energy > node.energy + 1e-9: energy_prunes += 1 continue h = child.modulus_hash() if h in visited: existing = visited[h] if existing.energy <= child.energy: dedup += 1 continue visited[h] = child nodes_created += 1 path.append(child) stack.append((child, 0, 0)) if child.depth > max_depth: max_depth = child.depth # Report if nodes_created > report_at: report_at = nodes_created + 50000 elapsed = time.time() - start print( f" [{elapsed:.0f}s] n_strands={n_strands} " f"depth={max_depth} " f"nodes={nodes_created} " f"copr={coprimality_prunes} " f"en={energy_prunes} " f"dedup={dedup}" ) sys.stdout.flush() if max_depth > 500: return { 'n_strands': n_strands, 'collapse_depth': max_depth, 'collapsed': False, 'reason': 'depth_limit', 'nodes_created': nodes_created, 'coprimality_prunes': coprimality_prunes, 'energy_prunes': energy_prunes, 'dedup': dedup, 'runtime_s': round(time.time() - start, 2), 'max_modulus': max(m for n in visited.values() for m in n.moduli), } # DFS exhausted — we've found the deepest reachable state return { 'n_strands': n_strands, 'collapse_depth': max_depth, 'collapsed': True, 'reason': 'dfs_exhausted', 'nodes_created': nodes_created, 'coprimality_prunes': coprimality_prunes, 'energy_prunes': energy_prunes, 'dedup': dedup, 'runtime_s': round(time.time() - start, 2), 'max_modulus': max(m for n in visited.values() for m in n.moduli) if visited else 0, } results = [] for n_strands in [2, 3, 4, 5, 6, 7, 8]: print(f"\n{'=' * 60}") print(f"Strands: {n_strands}") print(f"{'=' * 60}") r = find_collapse_depth(n_strands) results.append(r) status = "COLLAPSED" if r['collapsed'] else "NO COLLAPSE" print(f"\n → {status} at depth {r['collapse_depth']}") print(f" nodes={r['nodes_created']}, runtime={r['runtime_s']}s") print(f" copr={r['coprimality_prunes']}, en={r['energy_prunes']}") print(f" max_mod={r['max_modulus']}") print(f"\n{'=' * 60}") print("FINAL RESULTS") print(f"{'=' * 60}") for r in results: print(f" {r['n_strands']} strands: " f"{'COLLAPSED' if r['collapsed'] else 'LIMIT'}" f" @ depth {r['collapse_depth']} " f"({r['nodes_created']} nodes, {r['runtime_s']}s)")