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

124 lines
4.3 KiB
Python
Raw Permalink 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
"""
Comprehensive tests for the Braid Word Solver.
"""
import sys, math
sys.path.insert(0, '/home/allaun/SilverSight/scripts')
from braid_word_solver import *
from verify_wrapping import f_k, is_sidon
from iteration_dag import IterationDAG, AdaptiveRule
passed = 0
failed = 0
def check(name, condition, detail=""):
global passed, failed
if condition:
passed += 1
print(f"{name}")
else:
failed += 1
print(f"{name}: {detail}")
print("=" * 60)
print("BRAID WORD SOLVER TESTS")
print("=" * 60)
# --- Test 1: Sidon example ---
print("\n--- Test 1: Sidon example σ₁⁻ ---")
A0, S = [1, 2, 5, 6], 7
result = solve_braid_word(A0, S)
p = result['paths'][0]
check("braid word is σ₁⁻", p['braid_word'] == "σ₁⁻",
f"got {p['braid_word']}")
check("1 step", p['steps'] == 1, f"got {p['steps']}")
check("final set is Sidon", is_sidon(p['As'][-1]),
f"A={p['As'][-1]}")
check("final set matches expected", set(p['As'][-1]) == {2, 5, 9, 10},
f"got {p['As'][-1]}")
check("moduli are [3,4]", p['Ms'][1] == 12,
f"M={p['Ms'][1]}")
# --- Test 2: Complex set ---
print("\n--- Test 2: Complex set σ₁⁺ ---")
A0, S = [0, 1, 3, 8, 13], 27
result = solve_braid_word(A0, S)
shortest = min(result['paths'], key=lambda x: x['steps'])
check("shortest braid word is σ₁⁺", "σ₁⁺" in shortest['braid_word'],
f"got {shortest['braid_word']}")
check("final set is Sidon", is_sidon(shortest['As'][-1]),
f"A={shortest['As'][-1]}")
# --- Test 3: Non-Sidon A that stays non-Sidon ---
print("\n--- Test 3: No-Sidon path ---")
# A set where no modulus in range creates Sidon
A0, S = [0, 1, 2, 4, 8], 12
result = solve_braid_word(A0, S)
check("some paths found", result['summary']['total_paths'] > 0,
f"no paths")
for p in result['paths']:
check(f"braid word non-empty", len(p['braid_word']) > 0,
p['braid_word'])
# --- Test 4: Multi-step path ---
print("\n--- Test 4: Multi-step check ---")
A0, S = [1, 3, 5, 7], 8 # symmetric set, may need multi-step
rule = AdaptiveRule(max_val=20)
dag = IterationDAG(A0, S, rule, max_steps=4, max_branch=50)
dag.build()
if dag.sidon_paths:
p = min(dag.sidon_paths, key=lambda x: len(x))
bw = dag_path_to_braid(A0, S, p)
check(f"multi-step ({len(p)-1} steps) has braid word",
len(bw) > 0, f"word={bw}")
check("braid word has correct crossing count",
bw.count("σ") == len(p) - 1,
f"{p} stops, word='{bw}'")
# --- Test 5: Over vs Under crossing ---
print("\n--- Test 5: L_id > L_ref → σ⁺, L_id < L_ref → σ⁻ ---")
A0, S = [1, 2, 5, 6], 7
# Directly create nodes and test
from verify_wrapping import f_k, is_sidon
for L_id, L_ref, expected in [(7, 3, "σ₁⁺"), (3, 7, "σ₁⁻"), (5, 2, "σ₁⁺"), (2, 5, "σ₁⁻")]:
n_mods = [L_id, L_ref]
n_A = [f_k(a, S, n_mods) for a in A0]
n_sidon = is_sidon(n_A)
# Check that the modulus ordering predicts crossing type
actual = "σ₁⁺" if L_id > L_ref else "σ₁⁻"
check(f"({L_id},{L_ref}) → {expected}",
actual == expected, f"got {actual}")
# --- Test 6: Modulus ordering rule ---
print("\n--- Test 6: L_id > L_ref required for Sidon (complex set) ---")
A0, S = [0, 1, 3, 8, 13], 27
for (L_id, L_ref) in [(7, 3), (11, 2), (8, 3), (13, 2)]:
FA = [f_k(a, S, [L_id, L_ref]) for a in A0]
sidon = is_sidon(FA)
check(f"[{L_id},{L_ref}] Sidon={sidon} (L_id>L_ref={L_id>L_ref})",
sidon, f"FA={FA}")
for (L_id, L_ref) in [(3, 7), (2, 11), (3, 8), (2, 13)]:
FA = [f_k(a, S, [L_id, L_ref]) for a in A0]
sidon = is_sidon(FA)
check(f"[{L_id},{L_ref}] Sidon={sidon} (L_id<L_ref={L_id<L_ref})",
not sidon, f"FA={FA}")
# --- Test 7: L_id > L_2 rule ---
print("\n--- Test 7: Wrapping works at ANY M > max(A) ---")
A0, S = [1, 2, 5, 6], 7
maxA = max(A0)
for (L_id, L_ref) in [(7, 3), (11, 2), (13, 2), (5, 3)]:
FA = [f_k(a, S, [L_id, L_ref]) for a in A0]
M = L_id * L_ref
sidon = is_sidon(FA)
regime = "M > 2*maxA (no sum alias)" if M > 2 * maxA else "creation regime"
check(f"[{L_id},{L_ref}] M={M} ({regime}) Sidon={sidon}",
M > maxA, f"M={M} should be > maxA={maxA}")
# --- Summary ---
print(f"\n{'='*60}")
print(f"RESULTS: {passed} passed, {failed} failed out of {passed+failed}")
if failed == 0:
print("ALL TESTS PASSED ✓")
else:
print(f"{failed} TEST(S) FAILED ✗")