#!/usr/bin/env python3 """ 8-Strand Chiral Torus DAG — full search on provider-nixos. Runs the dual-model DAG with: - 8 strands × 2 moduli = 16 coprime moduli (prime-product method) - Axis-swap braid generators (YB-verified) - Adjustment crossings with capacity tracking - Multi-seed Sidon search (4 different A₀ sets) - BFS up to max_steps=12, max_branch=100 Output: per-seed JSON + summary JSON to docs/diagrams/ """ import sys, math, json, time sys.path.insert(0, '/home/allaun/SilverSight/scripts') from full_chiral_dag import ChiralDAG, BraidDAGNode, chiral_pairs SEEDS = [ {"id": "canonical", "A": [1, 2, 5, 6], "S": 7}, {"id": "sparse", "A": [0, 1, 3, 8, 13], "S": 27}, {"id": "five_element", "A": [1, 4, 9, 11, 16], "S": 20}, {"id": "seven_element", "A": [2, 3, 7, 10, 14, 18, 21], "S": 24}, ] def run_search(seed, n_strands=3, max_steps=8, max_branch=60, spacing=200): """Run a single DAG search with given parameters.""" dag = ChiralDAG(seed["A"], seed["S"], n_strands=n_strands, max_steps=max_steps, max_branch=max_branch, min_spacing=spacing) # Use small initial pairs for the wrapping regime init_pairs = chiral_pairs(n_strands) dag.root = BraidDAGNode(init_pairs, seed["A"], seed["S"]) dag.all_nodes = {dag.root.key(): dag.root} dag.n_strands = n_strands start = time.time() dag.build(use_axis_swap=True, use_adjustment=True, bypass_preservation=True) elapsed = time.time() - start result = { "seed_id": seed["id"], "A0": seed["A"], "S": seed["S"], "n_strands": n_strands, "max_steps": max_steps, "max_branch": max_branch, "elapsed_s": round(elapsed, 2), "stats": dag.stats, "nodes_total": len(dag.all_nodes), "sidon_paths": [], "root_moduli": dag.root.moduli, "root_capacity": dag.root.capacity_left, "root_spacing": dag.root._spacing if hasattr(dag.root, '_spacing') else None, } for path in dag.sidon_paths: result["sidon_paths"].append({ "braid_word": path[-1].braid_word, "steps": len(path) - 1, "final_A": path[-1].A, "final_M": path[-1].M, "final_capacity": path[-1].capacity_left, "node_count": len(path), }) if result["sidon_paths"]: shortest = min(result["sidon_paths"], key=lambda p: p["steps"]) result["shortest_path"] = shortest["braid_word"] result["shortest_steps"] = shortest["steps"] else: result["shortest_path"] = None result["shortest_steps"] = None return result, dag def run_8strand_validation(): """Validate that the 8-strand config is constructible and compute bounds.""" pairs = chiral_pairs(8) mods = [] for p in pairs: mods.extend(p) from full_chiral_dag import pairwise_coprime, compute_spacing, remaining_capacity return { "n_moduli": len(mods), "coprime": pairwise_coprime(mods), "moduli": mods, "pairs": pairs, "min_spacing": compute_spacing(pairs)["min_spacing"], "capacity": remaining_capacity(pairs), "max_modulus": max(mods), "max_modulus_ok": max(mods) < 32767, } if __name__ == "__main__": print("=" * 60) print("8-STRAND CHIRAL TORUS DAG - FULL SEARCH") print("=" * 60) print() # 1. Validate 8-strand construction print("--- 8-Strand Configuration Validation ---") v8 = run_8strand_validation() print(f" Moduli: {v8['n_moduli']} (8 strands × 2)") print(f" Coprime: {v8['coprime']}") print(f" Min spacing: {v8['min_spacing']}") print(f" Capacity: {v8['capacity']}") print(f" Max modulus: {v8['max_modulus']} < 32767: {v8['max_modulus_ok']}") print() # 2. Run searches at increasing strand counts all_results = {"8strand_config": v8, "seeds": []} configs = [ (3, 8, 80, "3-strand, 8 steps"), (4, 8, 60, "4-strand, 8 steps"), (6, 6, 40, "6-strand, 6 steps"), (8, 5, 30, "8-strand, 5 steps"), ] for n_strands, max_steps, max_branch, label in configs: print(f"--- {label} ---") for seed in SEEDS: result, dag = run_search(seed, n_strands, max_steps, max_branch) print(f" Seed '{seed['id']}': " f"nodes={result['nodes_total']}, " f"sidon={result['stats']['sidon_found']}, " f"shortest={result['shortest_path'] or 'NONE'}, " f"{result['elapsed_s']}s") all_results["seeds"].append(result) # Per-strand-count summary seed_results = [r for r in all_results["seeds"] if r["n_strands"] == n_strands] found = sum(1 for r in seed_results if r["sidon_paths"]) total_nodes = sum(r["nodes_total"] for r in seed_results) total_time = sum(r["elapsed_s"] for r in seed_results) print(f" [{label}] Total: {found}/{len(SEEDS)} seeds found Sidon, " f"{total_nodes} nodes, {total_time:.1f}s") print() # 3. Overall summary print("=" * 60) print("SUMMARY") print("=" * 60) total_seeds = sum(1 for r in all_results["seeds"] if r["sidon_paths"]) total_found = len([r for r in all_results["seeds"] if r["sidon_paths"]]) print(f" Total runs: {len(all_results['seeds'])}") print(f" Seeds with Sidon paths: {total_seeds}") print(f" Shortest paths across all: ", end="") shortest = min((r for r in all_results["seeds"] if r["sidon_paths"]), key=lambda r: r["shortest_steps"], default=None) if shortest: print(f"{shortest['shortest_path']} ({shortest['shortest_steps']} steps, " f"seed={shortest['seed_id']}, {shortest['n_strands']} strands)") else: print("NONE") # 4. Write results path = "/home/allaun/SilverSight/docs/diagrams/8strand_search_results.json" with open(path, 'w') as f: json.dump(all_results, f, indent=2) print(f"\n Results written to {path}")