SilverSight/scripts/collapse_depth_search.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

140 lines
4.3 KiB
Python

#!/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)")