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