mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
This squashes all local history (768 commits) onto the scrubbed PR #90 baseline. Individual commits were lost during filter-repo corruption; the working tree content is preserved intact. Build: N/A (working tree state only)
247 lines
8.9 KiB
Python
247 lines
8.9 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
16D Chaos Game via QR Braid Crossings.
|
||
|
||
The 16D manifold V₁₆ = (q_void, q_orbit, q_braid, q_observer) is encoded
|
||
as an 8×8 matrix where each row is a 2×4 block (8 strands × 2 quadrants).
|
||
Householder reflections (braid crossings) are randomly applied — the
|
||
accumulated trajectory is the shock front of the 16D chaos game.
|
||
|
||
The attractor structure reveals the "folded prime" geometry of the
|
||
16D search manifold.
|
||
|
||
Reference:
|
||
- VCN QR pipeline (vcn_dsp_pipeline.py) — Householder = braid crossing
|
||
- BraidShock 16D (braid_shock_16d.py) — 16D shock propagation
|
||
- 16D Manifold Adjustment doc — V₁₆ decomposition
|
||
"""
|
||
|
||
import hashlib
|
||
import json
|
||
import math
|
||
import random
|
||
from collections import Counter
|
||
from datetime import datetime, timezone
|
||
|
||
Q16 = 65536
|
||
EPSILON = 1e-14
|
||
|
||
|
||
def sidon(k):
|
||
return 1 << k
|
||
|
||
|
||
def random_householder(n):
|
||
"""Generate a random Householder reflector H = I - τ·v·vᵀ."""
|
||
v = [random.uniform(-1, 1) for _ in range(n)]
|
||
norm = math.sqrt(sum(xi * xi for xi in v))
|
||
if norm < EPSILON:
|
||
return [float(i == j) for i in range(n)], 0.0
|
||
v = [xi / norm for xi in v]
|
||
tau = 2.0 # full reflection for normalized v
|
||
return v, tau
|
||
|
||
|
||
def apply_reflector(A, k, v, tau):
|
||
"""Apply Householder reflector at column k of matrix A."""
|
||
m = len(A)
|
||
n = len(A[0])
|
||
for j in range(k, n):
|
||
dot = sum(v[i] * A[i][j] for i in range(m))
|
||
for i in range(m):
|
||
A[i][j] -= tau * v[i] * dot
|
||
|
||
|
||
class ChaosGame16D:
|
||
"""16D chaos game driven by random Householder braid crossings."""
|
||
|
||
def __init__(self, size=8):
|
||
self.size = size # 8×8 matrix encodes 16D state
|
||
self.history = []
|
||
self.quadrant_map = {
|
||
"q_void": (0, 3), # rows 0-3, cols 0-1 (4D)
|
||
"q_orbit": (0, 3), # rows 0-3, cols 2-3 (4D)
|
||
"q_braid": (4, 7), # rows 4-7, cols 0-1 (4D)
|
||
"q_observer": (4, 7), # rows 4-7, cols 2-3 (4D)
|
||
}
|
||
|
||
def init_state(self, mode="random"):
|
||
"""Initialize the 8×8 state matrix for the chaos game."""
|
||
A = [[0.0] * self.size for _ in range(self.size)]
|
||
if mode == "identity":
|
||
for i in range(self.size):
|
||
A[i][i] = 1.0
|
||
elif mode == "sidon":
|
||
# Sidon-labeled diagonal: powers of 2
|
||
for i in range(self.size):
|
||
A[i][i] = sidon(i)
|
||
elif mode == "random":
|
||
for i in range(self.size):
|
||
for j in range(self.size):
|
||
A[i][j] = random.uniform(-1, 1)
|
||
elif mode == "unit":
|
||
# All-ones matrix (uniform energy)
|
||
for i in range(self.size):
|
||
for j in range(self.size):
|
||
A[i][j] = 1.0
|
||
return A
|
||
|
||
def step(self, A, target_strand=None):
|
||
"""One chaos game step: apply a random Householder reflector.
|
||
If target_strand is None, picks a random strand (0..7).
|
||
Returns the reflector info and the new matrix."""
|
||
k = target_strand if target_strand is not None else random.randint(0, self.size - 1)
|
||
v, tau = random_householder(self.size - k)
|
||
# Pad v to full size
|
||
v_full = [0.0] * k + v
|
||
apply_reflector(A, k, v_full, tau)
|
||
return {
|
||
"strand": k,
|
||
"sidon": sidon(k),
|
||
"tau": round(tau, 4),
|
||
"nz": sum(1 for vi in v if abs(vi) > EPSILON),
|
||
}
|
||
|
||
def run(self, steps=1000, record_every=10):
|
||
"""Run the chaos game for `steps` iterations."""
|
||
A = self.init_state("random")
|
||
self.history = []
|
||
trace = []
|
||
|
||
for s in range(steps):
|
||
ref = self.step(A)
|
||
if s % record_every == 0:
|
||
# Compute quadrant energies
|
||
energy = self.quadrant_energy(A)
|
||
trace.append({
|
||
"step": s,
|
||
"last_strand": ref["strand"],
|
||
"sidon": ref["sidon"],
|
||
"energy": energy,
|
||
})
|
||
|
||
self.history = trace
|
||
return A
|
||
|
||
def quadrant_energy(self, A):
|
||
"""Compute energy in each 4D quadrant of the 16D manifold."""
|
||
qe = {}
|
||
for name, (r_start, r_end) in self.quadrant_map.items():
|
||
e = 0.0
|
||
for i in range(r_start, r_end + 1):
|
||
for j in range(self.size):
|
||
e += A[i][j] * A[i][j]
|
||
qe[name] = round(math.sqrt(e), 6)
|
||
qe["total"] = round(sum(qe.values()), 6)
|
||
return qe
|
||
|
||
def energy_ratio(self, A):
|
||
"""Compute q_braid / q_void energy ratio = braid tension."""
|
||
qe = self.quadrant_energy(A)
|
||
v = qe["q_void"]
|
||
return qe["q_braid"] / v if v > 0 else float("inf")
|
||
|
||
def sidon_sumset(self):
|
||
"""Compute the Sidon sumset of all visited strand pairs."""
|
||
pairs = set()
|
||
for t in self.history:
|
||
s = t["sidon"]
|
||
for other_s in [sidon(i) for i in range(self.size)]:
|
||
if other_s != s:
|
||
pairs.add(s + other_s)
|
||
return sorted(pairs)
|
||
|
||
|
||
def main():
|
||
random.seed(42)
|
||
print("=" * 60)
|
||
print("16D Chaos Game — QR Braid Crossing Model")
|
||
print("=" * 60)
|
||
|
||
game = ChaosGame16D()
|
||
|
||
# ─── Run multiple trajectories ───────────────────────────────────────
|
||
trajectories = []
|
||
for trial in range(5):
|
||
A = game.run(steps=500, record_every=25)
|
||
final_energy = game.quadrant_energy(A)
|
||
braid_tension = game.energy_ratio(A)
|
||
sumset = game.sidon_sumset()
|
||
|
||
print(f"\nTrial {trial + 1}:")
|
||
print(f" Final energy: {final_energy['total']:.4f}")
|
||
print(f" Braid tension: {braid_tension:.4f} (q_braid/q_void)")
|
||
print(f" Sidon sumset: {len(sumset)} unique sums")
|
||
print(f" Strand usage: {Counter(t['last_strand'] for t in game.history).most_common(3)}")
|
||
|
||
trajectories.append({
|
||
"trial": trial + 1,
|
||
"final_energy": final_energy,
|
||
"braid_tension": round(braid_tension, 4),
|
||
"sidon_sumset_size": len(sumset),
|
||
"sidon_sumset": sumset[:20], # first 20
|
||
"energy_evolution": game.history[::4],
|
||
})
|
||
|
||
# ─── Run with fixed Sidon sequence ───────────────────────────────────
|
||
print(f"\n{'─' * 60}")
|
||
print("Sidon-ordered chaos: cycling strands 0..7 repeatedly")
|
||
A = game.init_state("sidon")
|
||
sidon_trace = []
|
||
for cycle in range(10):
|
||
for strand in range(8):
|
||
ref = game.step(A, target_strand=strand)
|
||
if cycle % 2 == 0:
|
||
sidon_trace.append({
|
||
"cycle": cycle,
|
||
"strand": strand,
|
||
"sidon": ref["sidon"],
|
||
"energy": game.quadrant_energy(A),
|
||
})
|
||
final = game.quadrant_energy(A)
|
||
print(f" Final energy: {final['total']:.4f}")
|
||
print(f" Quadrants: { {k: round(v, 4) for k, v in final.items()} }")
|
||
|
||
# ─── Receipt ─────────────────────────────────────────────────────────
|
||
receipt = {
|
||
"schema": "rrc_chaos_game_16d_v1",
|
||
"claim_boundary": "random_householder_braid_crossings_on_8x8;sidon_mapped_quadrants",
|
||
"description": (
|
||
"The 16D chaos game applies random Householder reflections "
|
||
"(braid crossings) to an 8×8 state matrix. The 16D manifold "
|
||
"quadrants (q_void, q_orbit, q_braid, q_observer) are 4×8 "
|
||
"blocks of the matrix. Sidon addresses {1..128} label the "
|
||
"8 strands. The attractor is the shock front ensemble."
|
||
),
|
||
"v16_structure": {
|
||
"encoding": "8×8 matrix split into 4 quadrant blocks",
|
||
"q_void": "rows 0-3, cols 0-1",
|
||
"q_orbit": "rows 0-3, cols 2-3",
|
||
"q_braid": "rows 4-7, cols 0-1",
|
||
"q_observer": "rows 4-7, cols 2-3",
|
||
},
|
||
"sidon_addresses": [sidon(k) for k in range(8)],
|
||
"trajectories": trajectories,
|
||
"sidon_ordered": sidon_trace,
|
||
"summary": {
|
||
"total_trials": len(trajectories),
|
||
"avg_braid_tension": round(sum(t["braid_tension"] for t in trajectories) / len(trajectories), 4),
|
||
"avg_energy": round(sum(t["final_energy"]["total"] for t in trajectories) / len(trajectories), 4),
|
||
},
|
||
"computed_at": datetime.now(timezone.utc).isoformat(),
|
||
}
|
||
|
||
canonical = json.dumps(receipt, sort_keys=True, separators=(",", ":"))
|
||
receipt["receipt_sha256"] = hashlib.sha256(canonical.encode()).hexdigest()
|
||
|
||
path = "chaos_game_16d_receipt.json"
|
||
with open(path, "w") as f:
|
||
json.dump(receipt, f, indent=2)
|
||
|
||
print(f"\n{'=' * 60}")
|
||
print(f"Receipt: {path}")
|
||
print(f"SHA256: {receipt['receipt_sha256']}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|