mirror of
https://github.com/allaunthefox/SilverSight.git
synced 2026-07-31 01:25:21 +00:00
- 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>
261 lines
9.1 KiB
Python
261 lines
9.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Iteration DAG for CRT Torus Embedding.
|
|
|
|
Traces paths through modulus space, searching for a sequence of
|
|
modulus choices that transforms A into a Sidon set.
|
|
"""
|
|
import sys, math, random, itertools
|
|
from typing import List, Tuple, Optional, Dict, Set
|
|
|
|
sys.path.insert(0, '/home/allaun/SilverSight/scripts')
|
|
from verify_wrapping import *
|
|
|
|
# ---------- DAG Node ----------
|
|
|
|
class DAGNode:
|
|
__slots__ = ('step', 'A', 'moduli', 'S', 'M', 'sidon', 'parent', 'children',
|
|
'terminal', 'reason', 'id')
|
|
_next_id = 0
|
|
|
|
def __init__(self, A, moduli, S, parent=None, step=0):
|
|
self.id = DAGNode._next_id; DAGNode._next_id += 1
|
|
self.step = step
|
|
self.A = sorted(A)
|
|
self.moduli = list(moduli)
|
|
self.S = S
|
|
self.M = 1
|
|
for Li in moduli: self.M *= Li
|
|
self.sidon = is_sidon(self.A)
|
|
self.parent = parent
|
|
self.children = []
|
|
self.terminal = False
|
|
self.reason = ""
|
|
|
|
def key(self):
|
|
return (tuple(self.A), tuple(self.moduli), self.S)
|
|
|
|
def __repr__(self):
|
|
return f"Node#{self.id}(step={self.step}, |A|={len(self.A)}, M={self.M}, sidon={self.sidon})"
|
|
|
|
# ---------- Regeneration Rules ----------
|
|
|
|
class GeometricRule:
|
|
"""Geometric growth: L1' = alpha * L1, L2' = beta * L2, ensuring coprimality."""
|
|
def __init__(self, alpha=2, beta=3):
|
|
self.alpha = alpha
|
|
self.beta = beta
|
|
|
|
def next_moduli(self, current_moduli, maxA=None):
|
|
# Ensure next moduli remain coprime by using distinct growth factors
|
|
results = []
|
|
L1, L2 = current_moduli
|
|
for a in [1, 2, 3]:
|
|
for b in [1, 2, 3]:
|
|
if a == b: continue # keep moduli distinct
|
|
nL1 = a * L1 if a > 0 else L1
|
|
nL2 = b * L2 if b > 0 else L2
|
|
if math.gcd(nL1, nL2) == 1:
|
|
results.append([nL1, nL2])
|
|
return results[:5] # limit branching
|
|
|
|
class AdaptiveRule:
|
|
"""Try all coprime modulus pairs with M in (maxA, 2*maxA]."""
|
|
def __init__(self, max_val=16):
|
|
self.numbers = [n for n in range(2, max_val + 1)]
|
|
|
|
def next_moduli(self, current_moduli, maxA):
|
|
candidates = []
|
|
for L1 in self.numbers:
|
|
for L2 in self.numbers:
|
|
if L1 == L2:
|
|
continue
|
|
if math.gcd(L1, L2) != 1:
|
|
continue
|
|
M = L1 * L2
|
|
if maxA < M <= 2 * maxA:
|
|
candidates.append([L1, L2])
|
|
return candidates
|
|
|
|
class ExhaustiveRule:
|
|
"""Try all coprime k-modulus tuples within a bound."""
|
|
def __init__(self, max_val=16):
|
|
self.numbers = [n for n in range(2, max_val + 1)]
|
|
|
|
def next_moduli(self, current_moduli, maxA):
|
|
candidates = []
|
|
for k in range(2, 5):
|
|
for combo in itertools.permutations(self.numbers, k):
|
|
# Check pairwise coprimality
|
|
ok = True
|
|
for i in range(k):
|
|
for j in range(i+1, k):
|
|
if math.gcd(combo[i], combo[j]) != 1:
|
|
ok = False
|
|
break
|
|
if not ok: break
|
|
if not ok: continue
|
|
M = 1
|
|
for n in combo: M *= n
|
|
if maxA < M <= 2 * maxA:
|
|
candidates.append(list(combo))
|
|
return candidates[:self.max_branch] if hasattr(self, 'max_branch') else candidates
|
|
|
|
# ---------- DAG Builder ----------
|
|
|
|
class IterationDAG:
|
|
def __init__(self, A0, S, regen_rule, max_steps=5, max_branch=100):
|
|
self.root = DAGNode(A0, [3, 4], S) # default initial moduli
|
|
self.regen_rule = regen_rule
|
|
self.max_steps = max_steps
|
|
self.max_branch = max_branch
|
|
self.all_nodes: Dict[str, DAGNode] = {self.root.key(): self.root}
|
|
self.sidon_paths: List[List[DAGNode]] = []
|
|
self.stats = {"explored": 0, "sidon_found": 0, "terminal": 0}
|
|
|
|
def apply_F(self, node, new_moduli):
|
|
"""Apply F with new moduli to node.A, return child node or None."""
|
|
new_A = [f_k(a, node.S, new_moduli) for a in node.A]
|
|
child = DAGNode(new_A, new_moduli, node.S, parent=node, step=node.step + 1)
|
|
return child
|
|
|
|
def should_terminate(self, node):
|
|
"""Check if a node is terminal."""
|
|
if node.sidon:
|
|
node.terminal = True
|
|
node.reason = "Sidon (goal reached)"
|
|
return True
|
|
if node.M > 2 * max(node.A):
|
|
node.terminal = True
|
|
node.reason = f"Preservation regime (M={node.M} > 2*maxA)"
|
|
return True
|
|
if node.step >= self.max_steps:
|
|
node.terminal = True
|
|
node.reason = f"Max steps ({self.max_steps}) reached"
|
|
return True
|
|
return False
|
|
|
|
def build(self):
|
|
"""BFS build of the DAG."""
|
|
queue = [self.root]
|
|
visited = set()
|
|
|
|
while queue:
|
|
node = queue.pop(0)
|
|
|
|
if node.key() in visited:
|
|
continue
|
|
visited.add(node.key())
|
|
|
|
self.stats["explored"] += 1
|
|
|
|
if self.should_terminate(node):
|
|
self.stats["terminal"] += 1
|
|
if node.sidon:
|
|
# Trace path to root
|
|
path = []
|
|
n = node
|
|
while n:
|
|
path.append(n)
|
|
n = n.parent
|
|
path.reverse()
|
|
self.sidon_paths.append(path)
|
|
self.stats["sidon_found"] += 1
|
|
continue
|
|
|
|
maxA = max(node.A)
|
|
candidates = self.regen_rule.next_moduli(node.moduli, maxA)
|
|
|
|
# Limit branching
|
|
if len(candidates) > self.max_branch:
|
|
candidates = candidates[:self.max_branch]
|
|
|
|
for new_moduli in candidates:
|
|
child = self.apply_F(node, new_moduli)
|
|
if child.key() not in self.all_nodes:
|
|
self.all_nodes[child.key()] = child
|
|
node.children.append(child)
|
|
queue.append(child)
|
|
|
|
return self
|
|
|
|
def print_path(self, path):
|
|
"""Pretty-print a path from root to Sidon."""
|
|
for i, node in enumerate(path):
|
|
sidon = "★ SIDON" if node.sidon else ""
|
|
term = " ⚑" if node.terminal else ""
|
|
print(f" Step {i}: A={node.A} M={node.M} {sidon}{term}")
|
|
if node.parent and i > 0:
|
|
print(f" moduli={node.moduli}")
|
|
|
|
def to_dot(self, filename=None):
|
|
"""Export DAG as DOT graph for visualization."""
|
|
lines = ["digraph IterationDAG {"]
|
|
lines.append(" rankdir=TB;")
|
|
lines.append(" node [shape=record];")
|
|
for key, node in self.all_nodes.items():
|
|
sidon_style = "style=filled, fillcolor=lightgreen" if node.sidon else ""
|
|
term_style = "style=filled, fillcolor=lightyellow" if node.terminal else ""
|
|
style = sidon_style or term_style or ""
|
|
label = f"A={node.A}\\nM={node.M} step={node.step}"
|
|
if node.sidon: label += " ★SIDON"
|
|
if style:
|
|
lines.append(f" n{node.id} [{style}, label=\"{label}\"];")
|
|
else:
|
|
lines.append(f" n{node.id} [label=\"{label}\"];")
|
|
for key, node in self.all_nodes.items():
|
|
for child in node.children:
|
|
lines.append(f" n{node.id} -> n{child.id} [label=\"{child.moduli}\"];")
|
|
lines.append("}")
|
|
dot = "\n".join(lines)
|
|
if filename:
|
|
with open(filename, 'w') as f:
|
|
f.write(dot)
|
|
print(f" DOT written to {filename}")
|
|
return dot
|
|
|
|
def summary(self):
|
|
"""Print DAG statistics."""
|
|
print(f"DAG Statistics:")
|
|
print(f" Nodes explored: {self.stats['explored']}")
|
|
print(f" Sidon paths found: {self.stats['sidon_found']}")
|
|
print(f" Terminal nodes: {self.stats['terminal']}")
|
|
print(f" Total nodes: {len(self.all_nodes)}")
|
|
if self.sidon_paths:
|
|
print(f" Shortest path length: {len(min(self.sidon_paths, key=len))}")
|
|
print(f"\n Shortest path:")
|
|
self.print_path(min(self.sidon_paths, key=len))
|
|
|
|
# ---------- Main ----------
|
|
|
|
def test_sidon_example():
|
|
"""Trace the known Sidon creation example."""
|
|
print("=== Sidon Creation Example ===")
|
|
A0, S0 = [1, 2, 5, 6], 7
|
|
rule = AdaptiveRule()
|
|
dag = IterationDAG(A0, S0, rule, max_steps=3)
|
|
dag.build()
|
|
dag.summary()
|
|
|
|
def test_evolution():
|
|
"""Trace evolution of a non-Sidon set through modulus choices."""
|
|
print("\n=== Evolution of A={0,1,3,8,13} ===")
|
|
A0, S0 = [0, 1, 3, 8, 13], 27
|
|
rule = AdaptiveRule()
|
|
dag = IterationDAG(A0, S0, rule, max_steps=3)
|
|
dag.build()
|
|
dag.summary()
|
|
|
|
def test_geometric_cascade():
|
|
"""Trace a deterministic geometric cascade."""
|
|
print("\n=== Geometric Cascade ===")
|
|
A0, S0 = [1, 2, 5, 6], 7
|
|
rule = GeometricRule(alpha=2, beta=2)
|
|
dag = IterationDAG(A0, S0, rule, max_steps=5)
|
|
dag.build()
|
|
dag.summary()
|
|
|
|
if __name__ == "__main__":
|
|
test_sidon_example()
|
|
test_evolution()
|
|
test_geometric_cascade()
|