#!/usr/bin/env python3
"""
Computation 84 -- Multi-generator CC inner-fluctuation route for Z^2: multi-generator inner fluctuation
==================================================================
Multi-generator inner fluctuation: extend Comp 74 from single ω generator to K coherent
generators across the substrate Clifford algebra, looking for a
structural K (or Bernoulli-activation probability p) that delivers the
Z^2 target y/Lambda = 2^{-1/4} = mu_site^{1/4}.

SETUP (Comp 74 baseline + multi-generator extension)
----------------------------------------------------
D_sub = sum_a e_a in Cl(0, D), eigenvalues +/- sqrt(D).
Each pair (e_{2k-1}, e_{2k}) supports a quaternion volume element
omega_k = e_{2k-1} e_{2k}, omega_k^2 = -I.

For K orthogonal pair-generators activated coherently:
  A = -i phi sum_{k=1}^{K} (e_{2k-1} - e_{2k})
  D_phi = D_sub + A
  D_phi^2 = D + 2K phi^2   (each pair contributes 2 phi^2 in the
                            anticommutator + diagonal sum)

For matched scaling Lambda = sqrt(D):
  S/2^D = exp(-1) * exp(-2K phi^2 / D)
        = exp(-1) * [1 - 2K phi^2 / D + 2K^2 phi^4 / D^2 - O(phi^6)]

phi^4 coefficient:  2 K^2 exp(-1) / D^2

Comp 72 target:  exp(-1) y^4 / (2 Lambda^4) = exp(-1) y^4 / (2 D^2)

Matching:  2K^2 / D^2 = y^4 / (2 D^2)  =>  y^4 = 4K^2  =>  y = sqrt(2K)
Normalized:  y / Lambda = sqrt(2K / D)

For y/Lambda = 2^{-1/4} target (the D-independent Z^2 = e^{-1} closure):
  2K / D = 1 / sqrt(2)
  K = D / (2 sqrt(2)) = D * 2^{-3/2}

BERNOULLI EXTENSION
-------------------
If each ω_k is "active" with probability p independently (Bernoulli),
then in the D -> infinity limit:
  E[S/2^D] -> exp(-1) * exp(-p phi^2)
  phi^4 coefficient = exp(-1) * p^2 / 2

Matching:  p^2 / 2 = y^4 / (2 D^2)  =>  y = sqrt(p D)
Normalized:  y / Lambda = sqrt(p)

For y/Lambda = 2^{-1/4} target:
  p = 2^{-1/2} = 1 / sqrt(2) = mu_site^{1/2}

This is the AMPLITUDE-SQUARED interpretation: probability p of each
generator being active equals the SQUARED Yukawa coupling (y/Lambda)^2.
Self-consistent in form.

STRUCTURAL CONCLUSION
------------------
- Multi-generator DETERMINISTIC: requires K = D * 2^{-3/2}, not an
  integer count of natural Clifford generators.
- Multi-generator BERNOULLI: requires per-generator activation
  probability p = mu_site^{1/2}.  Form-self-consistent (p = (y/Lambda)^2)
  but with a magic mu_site^{1/2} factor not derivable from P1 alone:
  the substrate measure assigns probability mu_site = 1/2 per BIT, not
  per GENERATOR-PAIR.

The Bernoulli reading is closer to a structural closure but still
requires an additional structural input.  The deterministic reading
fails at the integer-count level.
"""

from __future__ import annotations
import math
import numpy as np


def predicted_y_over_lambda_det(K: int, D: int) -> float:
    """Deterministic K-coherent generators: y/Lambda = sqrt(2K/D)."""
    return math.sqrt(2 * K / D)


def predicted_y_over_lambda_bern(p: float) -> float:
    """Bernoulli p-activation (D -> infinity limit): y/Lambda = sqrt(p)."""
    return math.sqrt(p)


def spectral_action_ratio_det(K: int, D: int, phi: float) -> float:
    """Exact S/2^D for K-coherent generators at Lambda = sqrt(D)."""
    return math.exp(-1.0) * math.exp(-2 * K * phi**2 / D)


def spectral_action_ratio_bern(p: float, D: int, phi: float) -> float:
    """Average S/2^D under Bernoulli p-activation."""
    # E[S/2^D] = e^{-1} (1 - p + p exp(-2 phi^2 / D))^(D/2)
    e = math.exp(-2 * phi**2 / D)
    return math.exp(-1.0) * (1 - p + p * e) ** (D // 2)


def main():
    print("=" * 100)
    print("  Computation 84 -- Multi-generator CC inner-fluctuation route for Z^2: multi-generator inner fluctuation")
    print("=" * 100)
    print()

    print("TARGET FROM COMP 72")
    print("-" * 100)
    target_y_over_lambda = 2 ** (-0.25)
    print(f"  y / Lambda = 2^(-1/4) = mu_site^(1/4) = {target_y_over_lambda:.6f}")
    print(f"  (D-independent, this is the Z^2 = e^{-1} closure condition)")
    print()

    print("BASELINE: COMP 74 (K = 1, single generator)")
    print("-" * 100)
    for D in [2, 4, 8, 16, 32]:
        ratio = predicted_y_over_lambda_det(K=1, D=D)
        print(f"  D = {D:>3}:  y/Lambda = sqrt(2/{D}) = {ratio:.4f}  "
              f"(target {target_y_over_lambda:.4f}, "
              f"err {(ratio - target_y_over_lambda)/target_y_over_lambda*100:+.1f}%)")
    print()
    print("  Comp 74 verdict: D-DEPENDENT, decreasing as 1/sqrt(D).")
    print("  Hits target at D = 2 sqrt(2) / 2 = sqrt(2), non-integer.")
    print()

    print("MULTI-GENERATOR DETERMINISTIC: K varies with D")
    print("-" * 100)
    print(f"  {'D':>6}  {'K = sqrt(D)':>20}  {'K = D/2':>15}  {'K = D/(2 sqrt 2)':>20}")
    print(f"  {'':>6}  {'y/Lambda':>20}  {'y/Lambda':>15}  {'y/Lambda':>20}")
    for D in [8, 16, 32, 64, 128]:
        K_sqrtD = int(round(math.sqrt(D)))
        K_half = D // 2
        K_magic = D / (2 * math.sqrt(2))
        y_sqrtD = predicted_y_over_lambda_det(K_sqrtD, D)
        y_half = predicted_y_over_lambda_det(K_half, D)
        y_magic = math.sqrt(2 * K_magic / D)
        print(f"  {D:>6}  K={K_sqrtD:>3} {y_sqrtD:>15.4f}  K={K_half:>3} {y_half:>10.4f}  "
              f"K={K_magic:>7.2f}  {y_magic:>5.4f}")
    print()
    print(f"  Only K = D / (2 sqrt 2) hits target 2^(-1/4) = {target_y_over_lambda:.4f}")
    print(f"  BUT D / (2 sqrt 2) is NEVER INTEGER for finite D.")
    print(f"  Verdict: deterministic multi-generator with integer K does NOT close.")
    print()

    print("MULTI-GENERATOR BERNOULLI: per-generator activation probability p")
    print("-" * 100)
    print(f"  {'p':>10}  {'y/Lambda (D -> infty)':>25}  {'numerical D=32':>20}  "
          f"{'verdict':>10}")
    for p in [0.25, 1 / math.sqrt(2), 0.5, 0.7, 1.0]:
        y_lim = predicted_y_over_lambda_bern(p)
        # numerical at D = 32 from full Bernoulli average
        D_test = 32
        phi_test = 0.5
        S_avg = spectral_action_ratio_bern(p, D_test, phi_test)
        # extract approximate phi^4 coefficient
        S_0 = math.exp(-1.0)
        S_at_phi = spectral_action_ratio_bern(p, D_test, phi_test)
        S_at_2phi = spectral_action_ratio_bern(p, D_test, 2 * phi_test)
        # Taylor: S = e^{-1}(1 - p phi^2 + p^2 phi^4 / 2 - ...)
        # phi^4 coef = (S(2phi) - 2 S(phi) + S(0)) / phi^4 / 4  (centered FD)
        # actually use 1d Taylor inversion
        x = phi_test**2
        # S = e^{-1} exp(-p x) = e^{-1} (1 - p x + (p x)^2 / 2 ...)
        # Compute exact phi^4 coef:
        phi4_coef_exact = math.exp(-1.0) * p**2 / 2  # leading order
        # match to target y^4 = D^2 * phi4_coef * 2 / e^{-1} = D^2 p^2
        y_extracted = (D_test**2 * p**2) ** 0.25
        y_over_lambda_extracted = y_extracted / math.sqrt(D_test)
        # which should equal sqrt(p):
        match = abs(y_over_lambda_extracted - math.sqrt(p)) < 1e-4
        verdict = "HIT" if abs(y_lim - target_y_over_lambda) < 1e-4 else "miss"
        print(f"  {p:>10.4f}  y/Lambda = sqrt(p) = {y_lim:>10.4f}  "
              f"D=32: {y_over_lambda_extracted:>10.4f}  {verdict:>10}")
    print()
    print(f"  HIT at p = 1/sqrt(2) = {1/math.sqrt(2):.6f}")
    print(f"  Self-consistent: p = (y/Lambda)^2, so amplitude-squared = activation prob.")
    print(f"  However: substrate measure assigns mu_site = 1/2 per BIT, not")
    print(f"  per GENERATOR-PAIR.  mu_site^(1/2) is not directly the substrate")
    print(f"  per-site weight.")
    print()

    print("STRUCTURAL READING (HONEST)")
    print("-" * 100)
    print()
    print("  DETERMINISTIC: requires K = D 2^{-3/2}, not integer.  FAILS.")
    print()
    print("  BERNOULLI: requires p = mu_site^{1/2} = 1/sqrt(2).")
    print("             Self-consistent form (p = (y/Lambda)^2) but the")
    print("             SPECIFIC value 1/sqrt(2) lacks substrate combinatorial")
    print("             origin from the P1 Bernoulli measure (which gives")
    print("             mu_site = 1/2, not 1/sqrt(2)).")
    print()
    print("  CONCLUSION: Multi-generator Angle A does NOT close Z^2.")
    print("             The right scaling form exists but the multiplicative")
    print("             constant cannot be derived from P1 alone in either")
    print("             deterministic or Bernoulli reading.  The multi-generator inner-fluctuation route does not close the Z² identification at this level; the partition-function-level route in Comps 87-92 takes a different substrate-side approach.")
    print()
    print("  Comp 84 documents the negative result with the exact ALGEBRAIC")
    print("  obstruction: the matching equation y/Lambda = sqrt(2K/D) has no")
    print("  solution at structurally natural (integer K or Bernoulli p =")
    print("  mu_site^q for integer q) values.")
    print()


if __name__ == "__main__":
    main()
