SilverSight/python/hopf_dna_fiber.py
allaun b533b8d6ca fix(avm-review): resolve adversarial review findings
Rust fixes:
- Remove Q0_16 Not arm (was silently returning Bool(false) instead of type error)
- Replace inline floor division with floor_div() calls in MulSatQ16/DivSatQ16
- Fix comment ranges for Q0_16 [-32767, 32767] and Q16_16 [-2147483647, 2147483647]

Go fixes:
- Add euclideanDiv() matching Lean Int.ediv (remainder ≥ 0)
- Use euclideanDiv for MulSatQ16 and DivSatQ16
- Change Locals from []*Val to []Val (dangling pointer fix)
- Step on halted state returns &s, nil (Lean returns Ok s)
- OOB PC returns error instead of silent halt
- Halt does not increment PC (Lean: PC unchanged)

All Go tests pass (9/9)
2026-06-30 19:01:47 -05:00

180 lines
No EOL
5.7 KiB
Python

#!/usr/bin/env python3
"""
HopfDNA Fiber Analysis — Count exotic classes via S³ fiber structure
The 28 exotic spheres are NOT features of the S⁴ base.
They are TWISTS in the S³ FIBER over each base point.
For each S⁴ projection (base point), collect all DNA sequences
that map to it. Their fiber coordinates (the S³ = SU(2) element)
should show exactly 28 distinct twist patterns.
This is the correct topological approach: the 28 lives in the fiber.
"""
import math
import itertools
from collections import defaultdict
DNA_TO_Q = {
'A': (1, 0, 0, 0),
'C': (0, 1, 0, 0),
'G': (0, 0, 1, 0),
'T': (0, 0, 0, 1),
}
def quat_mul(a, b):
a1, a2, a3, a4 = a
b1, b2, b3, b4 = b
return (
a1*b1 - a2*b2 - a3*b3 - a4*b4,
a1*b2 + a2*b1 + a3*b4 - a4*b3,
a1*b3 - a2*b4 + a3*b1 + a4*b2,
a1*b4 + a2*b3 - a3*b2 + a4*b1,
)
def quat_conj(q):
return (q[0], -q[1], -q[2], -q[3])
def quat_norm_sq(q):
return q[0]**2 + q[1]**2 + q[2]**2 + q[3]**2
def quat_inv(q):
ns = quat_norm_sq(q)
if ns == 0: return None
c = quat_conj(q)
return tuple(x/ns for x in c)
def quat_div(a, b):
bi = quat_inv(b)
if bi is None: return None
return quat_mul(a, bi)
def dna_to_s7(seq):
def bases_to_quat(bases):
q = [0.0, 0.0, 0.0, 0.0]
for b in bases:
v = DNA_TO_Q[b]
q[0] += v[0]; q[1] += v[1]; q[2] += v[2]; q[3] += v[3]
return tuple(q)
q1 = bases_to_quat(seq[:4])
q2 = bases_to_quat(seq[4:])
n1 = quat_norm_sq(q1)
n2 = quat_norm_sq(q2)
total = n1 + n2
if total == 0: return ((1,0,0,0), (0,0,0,1))
scale = math.sqrt(total)
return (tuple(x/scale for x in q1), tuple(x/scale for x in q2))
def hopf_map(s7_point):
q1, q2 = s7_point
return quat_div(q1, q2)
def fiber_coordinate(s7_point):
"""
The FIBER coordinate of (q1, q2) ∈ S⁷ over base π(q1,q2) = q1/q2.
Two points (q1,q2) and (q1',q2') are in the same fiber iff
q1/q2 = q1'/q2', i.e., q1*q2⁻¹ = q1'*q2'⁻¹.
The fiber element is λ = q2/|q2| ∈ S³ (the phase of q2).
This is the SU(2) rotation that distinguishes exotic classes.
"""
q1, q2 = s7_point
n2 = math.sqrt(quat_norm_sq(q2))
if n2 < 1e-15:
return (1, 0, 0, 0) # identity at infinity
return tuple(x/n2 for x in q2)
def fiber_distance(a, b):
"""S³ = SU(2) distance: chordal distance on the 3-sphere."""
return math.sqrt(sum((a[i] - b[i])**2 for i in range(4)))
def s4_key(p, precision=4):
"""Canonical S⁴ key for grouping points in the same fiber."""
if p is None:
return None
if p[0] < 0:
return tuple(round(-x, precision) for x in p)
return tuple(round(x, precision) for x in p)
def main():
print("=" * 60)
print("HopfDNA Fiber Analysis — 28 exotic classes via S³ fiber")
print("=" * 60)
bases = ['A', 'C', 'G', 'T']
all_seqs = [''.join(p) for p in itertools.product(bases, repeat=8)]
print(f"\nTotal sequences: {len(all_seqs)}")
# Group sequences by S⁴ base point (fiber)
base_to_fibers = defaultdict(list)
for seq in all_seqs:
s7 = dna_to_s7(seq)
s4 = hopf_map(s7)
fiber = fiber_coordinate(s7)
key = s4_key(s4)
base_to_fibers[key].append(fiber)
print(f"Distinct S⁴ base points: {len(base_to_fibers)}")
# For each base point, count distinct fiber elements
total_fiber_elements = set()
base_fiber_counts = []
for base_key, fibers in base_to_fibers.items():
# Deduplicate fiber elements within this base point
unique_fibers = set()
for f in fibers:
# Round fiber coordinates
fr = tuple(round(x, 3) for x in f)
unique_fibers.add(fr)
base_fiber_counts.append(len(unique_fibers))
for uf in unique_fibers:
total_fiber_elements.add((base_key, uf))
print(f"\nFiber analysis:")
print(f" Total (base, fiber) pairs: {len(total_fiber_elements)}")
print(f" Avg fibers per base: {sum(base_fiber_counts)/len(base_fiber_counts):.1f}")
print(f" Max fibers per base: {max(base_fiber_counts)}")
print(f" Min fibers per base: {min(base_fiber_counts)}")
# Cluster ALL fiber elements globally
# The 28 exotic classes should appear as clusters in the fiber S³
all_fibers = list(total_fiber_elements)
fiber_points = [f for (_, f) in all_fibers]
print(f"\n Total distinct fiber elements: {len(fiber_points)}")
# Cluster fiber elements via single-linkage on S³
print(f"\n S³ fiber clustering (single-linkage):")
for eps in [0.5, 0.8, 1.0, 1.2, 1.3, 1.4, 1.41, 1.42, 1.5, 1.6, 1.8, 2.0]:
n = len(fiber_points)
parent = list(range(n))
def find(x):
while parent[x] != x:
parent[x] = parent[parent[x]]
x = parent[x]
return x
def union(x, y):
parent[find(x)] = find(y)
for i in range(min(n, 5000)): # subsample for speed
for j in range(i+1, min(n, 5000)):
d = fiber_distance(fiber_points[i], fiber_points[j])
if d < eps:
union(i, j)
comps = len(set(find(i) for i in range(min(n, 5000))))
marker = " ◄═══ 28" if comps == 28 else ""
print(f" eps={eps:.2f}: {comps} clusters{marker}")
# Also try: count distinct fiber elements per base,
# then look at the DISTRIBUTION of these counts
count_dist = Counter(base_fiber_counts)
print(f"\n Distribution of fiber counts per base:")
for count, freq in sorted(count_dist.items()):
print(f" {count} fibers: {freq} base points")
print(f"\n{'' * 60}")
if __name__ == "__main__":
main()