#!/usr/bin/env python3
"""
Computation 37 -- Spinor extension on H^2_alpha(B^2) tensor C^2 for L_comm
===========================================================================
Computation 36 established that the simple holomorphic-Toeplitz bridge of
Computation 35, with T_{bar z_a} as the Clifford analog, cannot close
L_comm because the substrate commutator is bimodal (0 or 2) while the
Toeplitz commutator is a continuous alpha-function.  The diagnostic
explicitly identified two paths forward: (i) an alpha-twisted Berezin
derivative with selectivity per substrate site, or (ii) the spinor
extension on H^2_alpha(B^2) tensor C^2 (the more PST-native approach,
matching the spinor C^2 fibre of the round-S^3 spectral triple of
Baer 1996).

This computation pursues path (ii): tensor a spinor C^2 (or C^4)
fibre with the Bergman space and add Pauli factors to the bridge of
the Clifford generators.  Tests whether the spinor C^2 structure
supplies the additional internal degrees of freedom needed to close
L_comm.

CONSTRUCTIONS TESTED.

(A) TRIVIAL SPINOR EXTENSION.
    H_full = H^2_alpha(B^2, N) tensor C^2.
    Walsh bridge: b(chi_S) = b_holo(chi_S) tensor I_C2 (no spinor activity).
    Clifford bridge: b(chi_a^{Cliff}) = T_{bar z_{a mod 2}} tensor sigma_{(a mod 3)+1}.
    PREDICTION: tensor factors decouple, so the spinor structure does not
    affect the operator norm. The gap is identical to Computation 35.

(B) SPINOR-COUPLED EXTENSION.
    H_full = H^2_alpha(B^2, N) tensor C^4 with Cl(0, 4) Clifford on C^4.
    Walsh bridge: b(chi_S) = b_holo(chi_S) tensor I_C4.
    Clifford bridge: b(chi_a^{Cliff}) = T_{z_b(a)} tensor gamma_a, where
        gamma_a are the Cl(0, 4) generators on C^4 and the Toeplitz factor
        T_{z_b(a)} is the matching holomorphic generator from
        Computation 35.
    PREDICTION: since chi_S maps to (holo) tensor I and chi_a^{Cliff} maps
    to (holo) tensor gamma_a, the cross-commutator factorises as
        [b(chi_a^{Cliff}), b(chi_S)] = [T_{z_b(a)}, b_holo(chi_S)] tensor gamma_a
    The holomorphic Toeplitz operators COMMUTE among themselves
    (Computation 35), so [T_{z_b(a)}, b_holo(chi_S)] = 0 for all (a, S).
    The cross-commutator is identically zero -- which mismatches the
    substrate by a factor of 2 when a in S.

CONCLUSION (preview).
Neither (A) nor (B) closes L_comm.  In (A), the tensor structure
decouples; in (B), the bridge image of chi_a^{Cliff} sits in the
COMMUTANT of the Walsh bridge image (since both use holo Toeplitz),
making all cross-commutators zero.  Closing L_comm requires the
Clifford bridge to involve operators OUTSIDE the holomorphic commutant
(i.e., anti-holo or non-Toeplitz operators) on the Bergman factor,
while still preserving the Cl(0, D) anti-commutation structure on the
spinor C^N factor.

The next concrete step is the "mixed-bridge" construction:
chi_a^{Cliff} -> T_{bar z_b(a)} tensor gamma_a, with the anti-holo
Toeplitz providing non-trivial commutator with the Walsh holo bridge,
and the Pauli gamma_a tracking the substrate's Cl(0, D) anti-commutation.
"""
import math
import numpy as np
import numpy.linalg as la


sx = np.array([[0, 1], [1, 0]], dtype=complex)
sy = np.array([[0, -1j], [1j, 0]], dtype=complex)
sz = np.array([[1, 0], [0, -1]], dtype=complex)
I2 = np.eye(2, dtype=complex)
I4 = np.eye(4, dtype=complex)


def kron_chain(ops):
    out = ops[0]
    for op in ops[1:]:
        out = np.kron(out, op)
    return out


def chi_walsh(D, S):
    return kron_chain([sz if a in S else I2 for a in range(D)])


def chi_clifford(D, a):
    return kron_chain([sz] * a + [sx] + [I2] * (D - 1 - a))


def op_norm(M):
    return float(la.norm(M, ord=2))


def basis_indices(N):
    return [(m1, m2) for m1 in range(N + 1) for m2 in range(N + 1 - m1)]


def log_norm_sq(m1, m2, alpha):
    return (math.lgamma(m1 + 1) + math.lgamma(m2 + 1)
            + math.lgamma(alpha + 3) - math.lgamma(m1 + m2 + alpha + 3))


def Tz_matrix(a, basis, alpha):
    n = len(basis)
    idx = {J: i for i, J in enumerate(basis)}
    M = np.zeros((n, n), dtype=complex)
    for j, J in enumerate(basis):
        Jp = list(J)
        Jp[a] += 1
        Jp = tuple(Jp)
        if Jp in idx:
            log_ratio = 0.5 * (log_norm_sq(Jp[0], Jp[1], alpha)
                               - log_norm_sq(J[0], J[1], alpha))
            M[idx[Jp], j] = math.exp(log_ratio)
    return M


def Tzbar_matrix(a, basis, alpha):
    return Tz_matrix(a, basis, alpha).conj().T


def site_to_holo(D, basis, alpha, Tz):
    return {0: Tz[0], 1: Tz[1], 2: Tz[0] @ Tz[0], 3: Tz[1] @ Tz[1]}


def bridge_holo(D, S, basis, alpha, Tz):
    site_map = site_to_holo(D, basis, alpha, Tz)
    n = len(basis)
    out = np.eye(n, dtype=complex)
    for a in sorted(S):
        out = out @ site_map[a]
    return out


def cl04_gammas():
    """Cl(0, 4) generators on C^4."""
    return [
        np.kron(sx, I2),
        np.kron(sy, I2),
        np.kron(sz, sx),
        np.kron(sz, sy),
    ]


def verify_cl04(gammas):
    """Verify Cl(0, 4) anti-commutation relations."""
    n = len(gammas)
    for i in range(n):
        for j in range(n):
            anti = gammas[i] @ gammas[j] + gammas[j] @ gammas[i]
            expected = (2.0 if i == j else 0.0) * np.eye(4, dtype=complex)
            if not np.allclose(anti, expected):
                return False
    return True


def main():
    D = 4
    N = 5
    alphas = [0.0, 1.0, 2.0, 5.0]
    basis = basis_indices(N)
    dim_Toep = len(basis)

    print("=" * 90)
    print("  Computation 37  --  spinor extension on H^2_alpha(B^2) tensor C^N for L_comm")
    print("=" * 90)
    print()
    print(f"  D = {D}, N = {N}, dim H^2_alpha = {dim_Toep}")
    print()

    cases = [
        (0, {0}),    # a in S, k=1
        (0, {1}),    # a not in S
        (0, {0, 1}), # a in S, k=2
        (0, {1, 2}), # a not in S, k=2
        (1, {0, 1}), # a in S, different a
        (2, {0, 2}), # a in S, mixed
    ]

    # Precompute substrate norms
    sub_norms = {}
    for a, S in cases:
        chi_a = chi_clifford(D, a)
        chi_S = chi_walsh(D, S)
        sub_norms[(a, frozenset(S))] = op_norm(chi_a @ chi_S - chi_S @ chi_a)

    # ============================================
    # Construction (A): trivial spinor extension
    # ============================================
    print("  Construction (A): Trivial spinor extension (Walsh tensor I, Clifford tensor Pauli)")
    print("  -----------------------------------------------------------------------------------")
    print()
    print("    Walsh bridge:    b(chi_S) = b_holo(chi_S) tensor I_C2")
    print("    Clifford bridge: b(chi_a^Cliff) = T_{bar z_(a mod 2)} tensor sigma_((a mod 3)+1)")
    print()
    paulis = [sx, sy, sz]
    print(f"    {'case':>20}  ||sub||  " + "  ".join(f"a={alpha:5.1f}" for alpha in alphas))
    for a, S in cases:
        sn = sub_norms[(a, frozenset(S))]
        row = f"    a={a}, S={str(set(S)):<10}  {sn:>6.4f}  "
        for alpha in alphas:
            Tz = [Tz_matrix(0, basis, alpha), Tz_matrix(1, basis, alpha)]
            # Walsh bridge: holo tensor I_C2
            b_S_holo = bridge_holo(D, S, basis, alpha, Tz)
            b_S = np.kron(b_S_holo, I2)
            # Clifford bridge: T_{bar z_(a mod 2)} tensor Pauli
            tzbar = Tzbar_matrix(a % 2, basis, alpha)
            sigma_a = paulis[a % 3]
            b_a = np.kron(tzbar, sigma_a)
            comm = b_a @ b_S - b_S @ b_a
            row += f"  {op_norm(comm):>9.4f}"
        print(row)
    print()
    print("  Observation: results are identical to Computation 35 (Pauli factor doesn't")
    print("  enter the op-norm because the tensor structure decouples).")
    print()

    # ============================================
    # Construction (B): C^4 spinor with Cl(0, 4)
    # ============================================
    print("  Construction (B): C^4 spinor with Cl(0, 4); Clifford bridge via HOLO Toeplitz")
    print("  ------------------------------------------------------------------------------")
    print()
    print("    Walsh bridge:    b(chi_S) = b_holo(chi_S) tensor I_C4")
    print("    Clifford bridge: b(chi_a^Cliff) = T_{z_(a mod 2)} tensor gamma_a")
    print()

    gammas = cl04_gammas()
    print(f"    Cl(0, 4) anti-commutation verified: {verify_cl04(gammas)}")
    print()
    print(f"    {'case':>20}  ||sub||  " + "  ".join(f"a={alpha:5.1f}" for alpha in alphas))
    for a, S in cases:
        sn = sub_norms[(a, frozenset(S))]
        row = f"    a={a}, S={str(set(S)):<10}  {sn:>6.4f}  "
        for alpha in alphas:
            Tz = [Tz_matrix(0, basis, alpha), Tz_matrix(1, basis, alpha)]
            site_map = site_to_holo(D, basis, alpha, Tz)
            b_S_holo = bridge_holo(D, S, basis, alpha, Tz)
            b_S = np.kron(b_S_holo, I4)
            # Clifford bridge: HOLO toeplitz tensor gamma_a
            b_a = np.kron(site_map[a], gammas[a])
            comm = b_a @ b_S - b_S @ b_a
            row += f"  {op_norm(comm):>9.4f}"
        print(row)
    print()
    print("  Observation: ALL cross-commutators are zero.  The Clifford bridge image")
    print("  is in the (abelian) holomorphic Toeplitz subalgebra tensored with gamma_a;")
    print("  the Walsh bridge image is in the SAME (abelian) holomorphic subalgebra")
    print("  tensored with I.  These commute because the holo Toeplitz operators")
    print("  commute, regardless of the Pauli factor.")
    print()

    # ============================================
    # Construction (C): mixed bridge -- anti-holo for Clifford
    # ============================================
    print("  Construction (C): MIXED bridge -- ANTI-HOLO Toeplitz for Clifford")
    print("  ------------------------------------------------------------------")
    print()
    print("    Walsh bridge:    b(chi_S) = b_holo(chi_S) tensor I_C4")
    print("    Clifford bridge: b(chi_a^Cliff) = T_{bar z_(a mod 2)} tensor gamma_a")
    print()
    print(f"    {'case':>20}  ||sub||  " + "  ".join(f"a={alpha:5.1f}" for alpha in alphas))
    for a, S in cases:
        sn = sub_norms[(a, frozenset(S))]
        row = f"    a={a}, S={str(set(S)):<10}  {sn:>6.4f}  "
        for alpha in alphas:
            Tz = [Tz_matrix(0, basis, alpha), Tz_matrix(1, basis, alpha)]
            b_S_holo = bridge_holo(D, S, basis, alpha, Tz)
            b_S = np.kron(b_S_holo, I4)
            tzbar = Tzbar_matrix(a % 2, basis, alpha)
            b_a = np.kron(tzbar, gammas[a])
            comm = b_a @ b_S - b_S @ b_a
            row += f"  {op_norm(comm):>9.4f}"
        print(row)
    print()
    print("  Observation: same as (A) modulo a unitary spinor rotation -- the op-norm")
    print("  is again decoupled from the gamma factor.  The anti-holo Toeplitz gives a")
    print("  non-zero commutator with the holo Walsh bridge (the Computation 33 mechanism),")
    print("  but the gamma factor only multiplies by 1 in op-norm.")
    print()

    print("=" * 90)
    print("  Verdict")
    print("=" * 90)
    print()
    print("  Tensor spinor extensions do NOT close L_comm on their own.  In all three")
    print("  constructions tested, the tensor factor structure decouples:")
    print()
    print("    H_full = H^2_alpha(B^2) tensor C^N")
    print("    A acts on H^2_alpha, B acts on C^N => (A tensor B)'s op-norm = |A||B|")
    print()
    print("  Adding a Pauli/Clifford factor to one side does not change the op-norm")
    print("  contribution from the other side; the spinor extension just MULTIPLIES")
    print("  the existing gap by a unitary factor.")
    print()
    print("  CONSEQUENCE.")
    print("  Closing L_comm requires a NON-TENSOR coupling between the Bergman factor")
    print("  and the spinor factor.  The natural candidate is the round-S^3 Dirac")
    print("  operator D = sum_a sigma_a tensor X_a, where X_a are the SU(2) left-")
    print("  invariant vector fields on H^2_alpha (acting as su(2) raising/lowering on")
    print("  the Wigner-D monomial basis), and the sigma_a's mix the spinor C^2 fibre.")
    print("  The full Dirac operator does NOT decompose as a single A tensor B; it is")
    print("  a SUM of such terms, which produces the non-tensor coupling.")
    print()
    print("  Implementing D = sum_a sigma_a tensor X_a explicitly and computing the")
    print("  commutator gap is the next concrete step.  This requires representing")
    print("  X_a as raising/lowering operators on the H^2_alpha(B^2) monomial basis")
    print("  according to the SU(2) action on monomials z_1^m1 z_2^m2.")


if __name__ == "__main__":
    main()
