mirror of
https://github.com/allaunthefox/SilverSight.git
synced 2026-07-31 01:25:21 +00:00
Hopf Portability Criterion: - 6 necessary conditions for problem portability (A-F) - 28 = 4×7 = 2²×(2³−1) factorization theorem - n=8 is the maximal group-theoretic Hopf encoding - 15 annotated domain templates Hopf Ingest Bridge: - Input schema: problem metadata → 6 conditions → fingerprint - 15 pre-classified templates (physics, optimization, NT, geometry) - Output receipt: schema hopf_ingest_receipt_v1 - Architecture: JSON → Checker → Computer → Matcher → Receipt Cross-agent consensus: - Topological insulators: strongest physics port - Anyons/TQC: π⁷(S⁴)=ℤ₂₈ exact match (deepest theory) - QUBO: strongest optimization port - Crystalline cohomology: strongest arithmetic port
246 lines
7.8 KiB
Python
246 lines
7.8 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
PIST Fiedler-Aware Chiral Boundary Detection
|
||
|
||
Extends PIST spectral analysis (SpectralN.lean) with Fiedler vector
|
||
sign-pattern analysis for chiral boundary classification.
|
||
|
||
References:
|
||
- formal/SilverSight/PIST/SpectralN.lean (shift-deflation, Fiedler)
|
||
- formal/SilverSight/PIST/CartanConnection.lean (D=1792, crossing weights)
|
||
- formal/CoreFormalism/BraidStateN.lean (chiral state enum)
|
||
"""
|
||
|
||
import numpy as np
|
||
from typing import Tuple, Optional
|
||
|
||
# ── PIST constants (from I₂) ──────────────────────────────────────────
|
||
|
||
SIGMA_Q16 = 9984 # 39/256 in Q16_16 units
|
||
TAU_Q16 = 9362 # 1/7 ≈ 9362/65536
|
||
D = 1792 # lcm(7, 256)
|
||
SCALE = 65536
|
||
|
||
CHIRAL_LABELS = ["achiral_stable", "left_handed", "right_handed", "chiral_scarred"]
|
||
|
||
|
||
def build_laplacian_8x8(cross_coupling: float = 1e-6) -> np.ndarray:
|
||
"""Build graph Laplacian from the Sidon crossing matrix.
|
||
|
||
The crossing matrix C has:
|
||
C[i,i] = σ = 39/256 (self-weight, diagonal)
|
||
C[i,j] = τ = 1/7 (paired strands, same block)
|
||
C[i,j] = ε (cross-block, small coupling)
|
||
|
||
The small cross-block coupling ε breaks the 4-block degeneracy
|
||
so the Fiedler vector is well-defined.
|
||
|
||
Args:
|
||
cross_coupling: tiny cross-block weight to regularize (default 1e-6)
|
||
|
||
Adjacency A = off-diagonal entries.
|
||
Degree D[i,i] = sum_j A[i,j].
|
||
Laplacian L = D - A.
|
||
"""
|
||
C = np.zeros((8, 8), dtype=np.float64)
|
||
for i in range(8):
|
||
C[i, i] = 39 / 256
|
||
for j in range(8):
|
||
if i != j:
|
||
if i // 2 == j // 2:
|
||
C[i, j] = 1 / 7
|
||
else:
|
||
C[i, j] = cross_coupling
|
||
|
||
A = C.copy()
|
||
np.fill_diagonal(A, 0.0)
|
||
D = np.diag(A.sum(axis=1))
|
||
L = D - A
|
||
return L
|
||
|
||
|
||
def power_iteration(mat: np.ndarray, max_iter: int = 100,
|
||
tol: float = 1e-8) -> Tuple[float, np.ndarray]:
|
||
"""Dominant eigenvalue and eigenvector via power iteration.
|
||
|
||
Args:
|
||
mat: n×n symmetric matrix
|
||
max_iter: maximum iterations
|
||
tol: convergence tolerance (residual)
|
||
|
||
Returns:
|
||
(eigenvalue, eigenvector)
|
||
"""
|
||
n = mat.shape[0]
|
||
v = np.arange(1.0, n + 1.0)
|
||
|
||
for _ in range(max_iter):
|
||
mv = mat @ v
|
||
eig = np.dot(v, mv) / np.dot(v, v)
|
||
norm = np.linalg.norm(mv)
|
||
if norm < 1e-15:
|
||
break
|
||
v_new = mv / norm
|
||
resid = np.linalg.norm(mv - eig * v) / n
|
||
v = v_new
|
||
if resid < tol:
|
||
break
|
||
|
||
mv = mat @ v
|
||
eig = np.dot(v, mv) / np.dot(v, v)
|
||
return eig, v
|
||
|
||
|
||
def fiedler_vector(L: np.ndarray) -> Tuple[float, np.ndarray]:
|
||
"""Compute Fiedler value (2nd smallest eigenvalue) and vector.
|
||
|
||
Uses full eigendecomposition. For n=8 this is trivially small.
|
||
For larger n, use shift-deflation power iteration (SpectralN.lean).
|
||
|
||
Args:
|
||
L: n×n Laplacian matrix
|
||
|
||
Returns:
|
||
(fiedler_value, fiedler_vector)
|
||
"""
|
||
eig_vals, eig_vecs = np.linalg.eigh(L)
|
||
# Fiedler = second smallest eigenvalue
|
||
fiedler_val = eig_vals[1]
|
||
fiedler_vec = eig_vecs[:, 1]
|
||
return fiedler_val, fiedler_vec
|
||
|
||
|
||
def classify_chiral_boundary(fiedler_vec: np.ndarray) -> str:
|
||
"""Classify chiral boundary state from Fiedler vector sign pattern.
|
||
|
||
The Fiedler vector has one component per strand (8 total, 4 pairs).
|
||
Sign pattern across paired strands determines chirality:
|
||
|
||
Pattern | Chirality
|
||
---------------------------------------------------------
|
||
All + (or all -) | achiral_stable (no boundary)
|
||
Mixed per pair (+, -) | left_handed (mass bias)
|
||
Mixed per pair (-, +) | right_handed (vector bias)
|
||
Both pairs strongly mixed | chiral_scarred (topological defect)
|
||
|
||
Args:
|
||
fiedler_vec: 8-component Fiedler eigenvector
|
||
|
||
Returns:
|
||
chiral label string
|
||
"""
|
||
sign = np.sign(fiedler_vec)
|
||
|
||
# Count sign flips within each pair
|
||
intra_flips = 0
|
||
for k in range(4):
|
||
if sign[2*k] != sign[2*k+1]:
|
||
intra_flips += 1
|
||
|
||
# Count sign flips between adjacent pairs
|
||
inter_flips = 0
|
||
for k in range(3):
|
||
if sign[2*k+1] != sign[2*k+2]:
|
||
inter_flips += 1
|
||
|
||
# Compute pair-wise net sign: bias within each pair
|
||
bias = []
|
||
for k in range(4):
|
||
pair_sign = fiedler_vec[2*k] + fiedler_vec[2*k+1]
|
||
bias.append(pair_sign)
|
||
|
||
net_bias = sum(bias)
|
||
|
||
# Classification rules
|
||
if intra_flips == 0 and inter_flips == 0:
|
||
return "achiral_stable" # all same sign
|
||
elif intra_flips > 0 and net_bias < 0:
|
||
return "left_handed" # mass bias (negative)
|
||
elif intra_flips > 0 and net_bias > 0:
|
||
return "right_handed" # vector bias (positive)
|
||
else:
|
||
return "chiral_scarred" # mixed topological defect
|
||
|
||
|
||
def compute_chiral_boundary_profile(C_matrix: Optional[np.ndarray] = None) -> dict:
|
||
"""Full chiral boundary analysis of the Sidon crossing matrix.
|
||
|
||
Returns:
|
||
dict with keys: fiedler_value, fiedler_vector, chiral_label,
|
||
intra_pair_flips, inter_pair_flips, spectral_gap
|
||
"""
|
||
if C_matrix is not None:
|
||
L = build_laplacian_from_matrix(C_matrix)
|
||
else:
|
||
L = build_laplacian_8x8()
|
||
|
||
# Fiedler analysis
|
||
f_val, f_vec = fiedler_vector(L)
|
||
chiral_label = classify_chiral_boundary(f_vec)
|
||
|
||
# Spectral gap
|
||
lambda_max, _ = power_iteration(L)
|
||
spectral_gap = lambda_max - f_val
|
||
|
||
return {
|
||
"fiedler_value": float(f_val),
|
||
"fiedler_vector": f_vec.tolist(),
|
||
"chiral_label": chiral_label,
|
||
"intra_pair_flips": sum(1 for k in range(4) if np.sign(f_vec[2*k]) != np.sign(f_vec[2*k+1])),
|
||
"inter_pair_flips": sum(1 for k in range(3) if np.sign(f_vec[2*k+1]) != np.sign(f_vec[2*k+2])),
|
||
"spectral_gap": float(spectral_gap),
|
||
"dominant_eigenvalue": float(lambda_max),
|
||
}
|
||
|
||
|
||
def build_laplacian_from_matrix(mat: np.ndarray) -> np.ndarray:
|
||
"""Build Laplacian from arbitrary 8x8 matrix.
|
||
|
||
Args:
|
||
mat: 8×8 adjacency/intensity matrix (Int or float)
|
||
|
||
Returns:
|
||
8×8 Laplacian
|
||
"""
|
||
A = np.abs(mat).astype(np.float64)
|
||
np.fill_diagonal(A, 0.0)
|
||
D = np.diag(A.sum(axis=1))
|
||
return D - A
|
||
|
||
|
||
# ── Demo ──────────────────────────────────────────────────────────────
|
||
|
||
def demo():
|
||
print("=" * 60)
|
||
print("PIST Fiedler-Aware Chiral Boundary Detection")
|
||
print("=" * 60)
|
||
|
||
L = build_laplacian_8x8()
|
||
print(f"\nLaplacian L:\n{L}")
|
||
|
||
lambda_max, v1 = power_iteration(L)
|
||
print(f"\nλ_max (dominant): {lambda_max:.6f}")
|
||
|
||
f_val, f_vec = fiedler_vector(L)
|
||
print(f"Fiedler value (λ₂): {f_val:.6f}")
|
||
print(f"Spectral gap: {lambda_max - f_val:.6f}")
|
||
print(f"Fiedler vector: {np.array2string(f_vec, precision=6, suppress_small=True)}")
|
||
print(f"Sign pattern: {np.array2string(np.sign(f_vec), precision=0, suppress_small=True)}")
|
||
|
||
profile = compute_chiral_boundary_profile()
|
||
print(f"\nChiral classification: {profile['chiral_label']}")
|
||
print(f"Intra-pair sign flips: {profile['intra_pair_flips']}")
|
||
print(f"Inter-pair sign flips: {profile['inter_pair_flips']}")
|
||
|
||
# Test on perturbed matrices
|
||
print("\n--- Perturbation analysis ---")
|
||
|
||
# Left-handed perturbation: add negative bias to pair (0,1)
|
||
L_pert = L.copy()
|
||
L_pert[0, 0] += 0.5 # increase degree for strand 0
|
||
fv, _ = fiedler_vector(L_pert)
|
||
print(f"Left-bias perturbation: Fiedler={fv:.6f}, chiral={classify_chiral_boundary(_)}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
demo()
|