SilverSight/python/chaos_game.py
SilverSight Agent 3c35fe50c2 Initial SilverSight: deterministic equation search via Fisher geometry
Core components:
- ChentsovFinite.lean (883 lines, 0 sorry): Fisher metric uniqueness on 8-state simplex
- HachimojiCodec.lean: Deterministic E=mc^2 -> Hachimoji state pipeline
- PVGS_DQ_Bridge (8 sections, ~6,150 lines): Photon-Varied Gaussian to Dual Quaternion
- UniversalMathEncoding.lean: 50-token math address space (~10^15 addresses)
- ChiralitySpace.lean: 4D descriptor (phase x chirality x direction x regime) ~2x10^25
- BindingSite (3 files): Amino acid vocabulary, entropy-based bindability
- Python: chaos game, Sidon addressing, Q16.16 canonical, Finsler metric, QUBO/QAOA
- CI: Lean check, Python check, Q16 roundtrip workflows

Papers: Giani-Win-Conti 2025, Chabaud-Mehraban 2022, Pizzimenti 2024, Wassner 2025
2026-06-21 18:02:05 +08:00

305 lines
9.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
chaos_game.py — Deterministic Chaos Game Engine
Deterministic chaos game using IFS contraction on 8×8 state matrix.
4 basins: q_void (rows 0-1), q_orbit (rows 2-3), q_braid (rows 4-5), q_observer (rows 6-7).
"""
import hashlib
import json
import math
from typing import Dict, List, Optional
from sidon_address import (
SIDON_ADDRESSES,
_ADDRESS_TO_STRAND,
address_to_strand,
compute_full_address,
structural_hash,
verify_sidon_property,
)
from spectral_profile import compute_spectral_profile
EPSILON = 1e-14
N = 8
IFS_ALPHA = 0.75 # Strong contraction for fast convergence
BASIN_ROWS = {
"q_void": (0, 1),
"q_orbit": (2, 3),
"q_braid": (4, 5),
"q_observer": (6, 7),
}
LCG_A = 1664525
LCG_C = 1013904223
LCG_M = 2**32
DEFAULT_CONVERGENCE_THRESHOLD = 0.95
DEFAULT_MAX_STEPS = 10000
DEFAULT_CONVERGENCE_WINDOW = 10
class LCG:
def __init__(self, seed: int):
self.state = seed & 0xFFFFFFFF
def next(self) -> int:
self.state = (LCG_A * self.state + LCG_C) % LCG_M
return self.state
def next_float(self) -> float:
return self.next() / LCG_M
def init_state_matrix(seed: int) -> List[List[float]]:
"""Initialize 8×8 state matrix deterministically from seed."""
lcg = LCG(seed)
A = [[0.0] * N for _ in range(N)]
for i in range(N):
for j in range(N):
if i == j:
A[i][j] = SIDON_ADDRESSES[i] / 128.0 + 0.5
elif abs(i - j) == 1:
A[i][j] = -0.1 + 0.04 * (lcg.next_float() - 0.5)
else:
A[i][j] = 0.05 * (lcg.next_float() - 0.5)
return A
def mat_copy(A): return [row[:] for row in A]
def mat_diff_norm(A, B):
return math.sqrt(sum((A[i][j] - B[i][j])**2 for i in range(N) for j in range(N)))
def mat_norm(A):
return math.sqrt(sum(A[i][j]**2 for i in range(N) for j in range(N)))
def strand_to_basin(strand: int) -> str:
if strand < 2: return "q_void"
elif strand < 4: return "q_orbit"
elif strand < 6: return "q_braid"
else: return "q_observer"
def get_basin_rows(strand: int):
return BASIN_ROWS[strand_to_basin(strand)]
def ifs_contract(A, strand, step, eq_hash):
"""Apply IFS contraction toward a strand's quadrant.
Pure IFS contraction: A <- (1-alpha)*A + alpha*T where T is the
target matrix with strong energy in the target strand's basin and
suppressed energy elsewhere. No post-step modifications.
"""
alpha = IFS_ALPHA
r0, r1 = get_basin_rows(strand)
lcg = LCG((eq_hash + step * 104729 + strand * 7919) & 0xFFFFFFFF)
for i in range(N):
for j in range(N):
in_basin = (r0 <= i <= r1)
on_diag = (i == j)
is_strand = (i == strand)
if is_strand and on_diag:
target = 10.0 # maximum energy at strand diagonal
elif is_strand:
target = 3.0 + 0.5 * lcg.next_float()
elif in_basin and on_diag:
target = 4.0 + 0.5 * lcg.next_float()
elif in_basin:
target = 1.5 + 0.3 * lcg.next_float()
elif on_diag:
target = 0.02 + 0.01 * lcg.next_float()
else:
target = 0.005 * lcg.next_float()
A[i][j] = (1 - alpha) * A[i][j] + alpha * target
def quadrant_energy(A):
"""Compute Frobenius energy in each basin (2-row block)."""
energy = {}
for basin, (r0, r1) in BASIN_ROWS.items():
e = sum(A[i][j]**2 for i in range(r0, r1 + 1) for j in range(N))
energy[basin] = math.sqrt(e)
energy["total"] = sum(v for k, v in energy.items())
return energy
def energy_ratio(A):
"""Ratio of dominant basin energy to total energy."""
qe = quadrant_energy(A)
total = qe["total"]
if total < EPSILON:
return 0.0
basin_energies = {k: v for k, v in qe.items() if k != "total"}
return max(basin_energies.values()) / total
def dominant_basin(A):
qe = quadrant_energy(A)
del qe["total"]
return max(qe, key=qe.get)
def detect_quarantine(equation):
if not equation or not equation.strip():
return "empty_equation"
eq = equation.strip()
normalized = eq.replace(" ", "").replace("\t", "")
contradictions = {"0=1", "1=0", "false=true", "true=false",
"False=True", "True=False", "⊥=", "=⊥"}
if normalized in contradictions:
return "explicit_contradiction"
if eq in {"0 = 1", "1 = 0", "False = True", "True = False", "⊥ = ", " = ⊥"}:
return "explicit_contradiction"
return None
def sidon_guided_chaos_game(
target_address: list,
max_steps: int = DEFAULT_MAX_STEPS,
convergence_threshold: float = DEFAULT_CONVERGENCE_THRESHOLD,
convergence_window: int = DEFAULT_CONVERGENCE_WINDOW,
equation: str = "",
):
"""Deterministic chaos game guided by Sidon address."""
# Quarantine check
quarantine = detect_quarantine(equation) if equation else None
if quarantine:
return {
"converged": False,
"basin": "QUARANTINE",
"steps": -1,
"energy_ratio": 0.0,
"address": target_address,
"hash": hex(structural_hash(equation))[2:18] if equation else "",
"target_strand": -1,
"quarantine": quarantine,
}
primary = target_address[0] if target_address else SIDON_ADDRESSES[0]
primary_strand = address_to_strand(primary)
eq_hash = structural_hash(equation) if equation else 42
A = init_state_matrix(eq_hash & 0xFFFFFFFF)
converged = False
basin_history = []
trajectory = []
for step in range(max_steps):
# Adaptive: emphasize target strand more over time
progress = min(step / max(max_steps // 3, 1), 1.0)
target_prob = 0.5 + 0.45 * progress
lcg = LCG((eq_hash + step * 104729) & 0xFFFFFFFF)
if lcg.next_float() < target_prob:
chosen = primary_strand
else:
others = [s for s in range(N) if s != primary_strand]
chosen = others[step % len(others)]
ifs_contract(A, chosen, step, eq_hash)
trajectory.append(chosen)
# Check convergence every 4 steps
if step % 4 == 0 and step > 0:
ratio = energy_ratio(A)
current_basin = dominant_basin(A)
basin_history.append(current_basin)
if ratio >= convergence_threshold:
if len(basin_history) >= convergence_window:
recent = basin_history[-convergence_window:]
if len(set(recent)) == 1:
converged = True
break
steps = step + 1 if converged else max_steps
final_ratio = energy_ratio(A)
final_basin = dominant_basin(A)
if not converged and final_ratio >= convergence_threshold:
converged = True
qe = quadrant_energy(A)
profile = energy_to_profile(qe)
from sidon_address import spectral_to_sidon_address
achieved = spectral_to_sidon_address(profile, eq_hash)
return {
"converged": converged,
"basin": final_basin,
"steps": steps,
"energy_ratio": round(final_ratio, 6),
"address": achieved,
"hash": hex(eq_hash)[2:18],
"target_strand": primary_strand,
"quarantine": None,
"trajectory": trajectory[:100],
}
def energy_to_profile(energy):
"""Convert quadrant energies to 8D profile."""
total = energy.get("total", 1.0)
if total < EPSILON:
total = 1.0
v = energy.get("q_void", 0.0) / total
o = energy.get("q_orbit", 0.0) / total
b = energy.get("q_braid", 0.0) / total
ob = energy.get("q_observer", 0.0) / total
profile = [v, v*v, o, o*o, b, b*b, ob, ob*ob]
s = sum(profile)
if s > 0:
profile = [p / s for p in profile]
else:
profile = [0.125] * 8
return profile
def generate_receipt(results, schema_version="stage3_v1"):
import datetime
converged = sum(1 for r in results if r.get("converged"))
quarantined = sum(1 for r in results if r.get("quarantine"))
basin_counts = {"q_void": 0, "q_orbit": 0, "q_braid": 0, "q_observer": 0}
for r in results:
b = r.get("basin", "")
if b in basin_counts:
basin_counts[b] += 1
receipt = {
"schema": f"rrc_chaos_game_search_{schema_version}",
"sidon_property_verified": verify_sidon_property(),
"total_searches": len(results),
"converged": converged,
"quarantined": quarantined,
"failed": len(results) - converged - quarantined,
"basin_distribution": basin_counts,
"convergence_rate": round(converged / len(results), 4) if results else 0.0,
"parameters": {
"matrix_size": N,
"ifs_alpha": IFS_ALPHA,
"convergence_threshold": DEFAULT_CONVERGENCE_THRESHOLD,
"max_steps": DEFAULT_MAX_STEPS,
"convergence_window": DEFAULT_CONVERGENCE_WINDOW,
},
"results": results,
"computed_at": datetime.datetime.now(datetime.timezone.utc).isoformat(),
}
canonical = json.dumps(receipt, sort_keys=True, separators=(",", ":"))
receipt["receipt_sha256"] = hashlib.sha256(canonical.encode()).hexdigest()
return receipt
def search_equation(equation: str, **kwargs):
"""Full pipeline: equation → profile → address → chaos game → result."""
profile = compute_spectral_profile(equation)
address = compute_full_address(equation)
result = sidon_guided_chaos_game(
target_address=address,
equation=equation,
**kwargs,
)
result["spectral_profile"] = [round(x, 6) for x in profile]
return result