#!/usr/bin/env python3
"""
PROVENANCE: PROOF

Computation 177 -- does the Mosco limit fix P3's kinetic coefficient?
=====================================================================
WHAT THIS DOES.  comp 176 reduced the field-normalisation open item to one
positive number, P3's kinetic coefficient c, and named the route that would close
it: c multiplies the Boolean Dirichlet form, sec:mosco-convergence takes that form
to the Laplace-Beltrami form on M = R x S^3, and the target has a canonical
normalisation of its own, so either the limit fixes c or c is absorbed into the
QGH scaling a_n -> 0.  This file walks that route.

THE ANSWER IS NO, AND THE FILE SAYS SO IN PART 5.  The limit does not fix c.  But
it does not leave the question where comp 176 left it either, because it shows
that c IS THE WRONG VARIABLE, and that two statements now in the book about it
are the wrong shape.  Three corrections come out, two of them to material shipped
the same day as this file.

THE INPUT IS TWO EQUATIONS THE BOOK ALREADY CARRIES.

  eq:boolean-grad-sq     |grad_C psi|^2 (C) = (1/4) SUM_{a in D} |d_a psi|^2
                         -- P3's gradient, a BARE sum over sites with no 1/|D|.
                         eq:poincare-boolean's Efron-Stein equality needs this form.

  eq:boolean-dirichlet   E^B(u,v) = SUM_{a in D} INT (d_a u)(d_a v) dmu,
                         so INT |grad_C psi|^2 dmu = (1/4) E^B(psi,psi).

  eq:mosco-limit         (1/|D|) E^B(Pi^T f, Pi^T h)  ->  (d_0^2/4) E^Riem(f,h)

  A1                     |D_n| a_n^4 -> V_M  with  a_n -> 0,  d_0 FIXED
                         (Appendix A is explicit that d_0 is a fixed coherence
                          length, distinct from the shrinking site spacing a_n.)

Put them together.  P3's gradient term is c E^B, and E^B = |D| (1/|D|) E^B, so

       the emergent kinetic coefficient is   K = c |D| d_0^2 / 16
       (the d_0^2/4 of eq:mosco-limit, times the 1/4 of eq:boolean-grad-sq)

and there is NO free constant in that map: the Mosco statement fixes it entirely.
That much is a gain.  What follows from it is not.

RESULT 1 -- ON THE BARE READING, A CONSTANT c IS INCONSISTENT WITH THE SCALING.  A1
sends |D| -> V/a_n^4 -> infinity with d_0 fixed, so for constant c the emergent
kinetic coefficient diverges as a_n^-4 and the projected field has infinite
stiffness.  Holding K finite would force

       c  ~  a_n^4  ->  0.

That is what RULES OUT the bare reading, and it is why P3 now states the average
one (RESULT 4).  It also disposes of "c = 1" as a formulation: on the bare reading
c is not a constant at all, and on the average reading c carries the dimensions of
epsilon, so a bare number cannot be asserted of it without a unit either way.
v32.72 added exactly that sentence to sec:open-structural on my recommendation; it
now speaks of the composite K = c-tilde d_0^2/16, with c-tilde = c |D|.

RESULT 2 -- eq:mosco-limit IS MISSING A2's 1/V_M.  A2 reads
(1/|D|) SUM_a f(rho(a)) -> (1/V_M) INT f sqrt(-g) d^4x, with the 1/V_M present.
eq:mosco-limit has an unnormalised E^Riem on the right and a mu-expectation on the
left, so the volume factor has gone missing.  Part 3 measures it on an explicit
lattice and recovers 1/V to 1%: the correct statement is

       (1/|D|) E^B  ->  (kappa / V) E^Riem,    equivalently  kappa <|grad f|^2>

with <.> the NORMALISED average.  This is a correction to the book's own equation,
not to a computation.

RESULT 3 -- comp 176's lambda_canon = 1/(4c^2) SKIPS THE PROJECTION.  It is a true
identity about F in substrate variables, and comp 176 used it as though it were
the coupling the seagull sees.  The seagull lives in 4D, where

       lambda_canon = b V / K^2,      b = 1/4,   K = c |D| kappa

so the substrate-variable formula and the 4D coupling agree only if K = c sqrt(V).
WHAT SURVIVES, and it matters that this is stated rather than glossed: comp 176's
CONCLUSIONS do not depend on the formula.  The sqrt(e) = 1/Z ratio and the
exclusion of reading B both use only the RATIO of two lambda_canon values, and
M_* ~ lambda_canon^{-1/2} holds whatever lambda_canon is built from.  Reading B
stays excluded, at 121 sigma here and 9.5 sigma in comp 173.  What is withdrawn is
the identification of the free number with P3's bare c.

RESULT 4 -- WITHDRAWN AT v32.77, AND THE WITHDRAWAL IS THE POINT.  This slot held a
claim that P3 left it unstated whether |grad_C psi|^2 was the bare edge sum or the
per-site average, and called the choice editorial.  THAT WAS FALSE.  P3 does say:
eq:boolean-grad-sq defines the Boolean gradient as the bare (1/4) sum, and
eq:poincare-boolean's Efron-Stein equality holds only for that form.  Acting on the
false claim, v32.74 added a second, contradicting definition of the same symbol
eighty-four lines later, which also falsified the cited inequality by a factor |D|/4.
Both are withdrawn; the bare reading is and always was the book's.

WHAT FOLLOWS INSTEAD, and it is the first branch of the fork taken outright:

        c is NOT A CONSTANT.  It carries a 1/|D|, equivalently c ~ a_n^4 -> 0,

and the |D|-independent quantity P3 owns is c-tilde = c |D|, in terms of which
K = c-tilde d_0^2 / 16 is finite.  Nothing in P3's content changes; the coefficient is
read as a scaling rather than as a number.  With c carrying epsilon's dimensions too,
"c = 1" is neither a pure number nor a statement about a constant.

WHAT WOULD ACTUALLY CLOSE THE ITEM.  A value for K = c-tilde d_0^2/16, which needs
d_0, a length the Casimir chapter BOUNDS at <= 2.3 nm but does not predict.  That is a
sharper and smaller residue than "which field is canonically normalised", and it is
still a residue, reported as one.
"""

import math
import numpy as np


def rule():
    print("=" * 100)


# ---------------------------------------------------------------------------
def part1():
    rule()
    print("  1.  THE MAP FROM P3's c TO THE EMERGENT KINETIC COEFFICIENT IS FIXED")
    rule()
    print("      eq:boolean-dirichlet is a BARE sum over sites, with no 1/|D|:")
    print("          E^B(u,v) = SUM_{a in D} INT (d_a u)(d_a v) dmu")
    print()
    print("      eq:mosco-limit divides by |D| before taking the limit:")
    print("          (1/|D|) E^B  ->  (d_0^2/4) E^Riem,  and P3's gradient is E^B/4")
    print()
    print("      So P3's gradient term c E^B carries a factor |D| into the limit:")
    print("          c E^B  =  c |D| * [(1/|D|) E^B]  ->  K <|grad f|^2>,")
    print("          K = c |D| d_0^2/16.")
    print()
    print("      THE GAIN: there is no free constant anywhere in that map.  The")
    print("      Mosco statement fixes it.  Whatever normalisation freedom the")
    print("      theory has is carried by c and |D| and d_0, and by nothing else.")
    print()
    return True


def part2():
    rule()
    print("  2.  A CONSTANT c IS INCONSISTENT WITH A1's SCALING")
    rule()
    print("      A1: |D| a_n^4 -> V,  a_n -> 0,  and d_0 is FIXED (Appendix A is")
    print("      explicit that it is distinct from a_n).  So |D| = V/a_n^4 -> inf and")
    print("          K = c |D| d_0^2/16 = c V d_0^2 / (16 a_n^4).")
    print()
    V, d0 = 1.0, 1.0
    print(f"      {'a_n':>10}{'|D| = V/a_n^4':>16}{'K at c = 1':>16}")
    Ks = []
    for an in (1e-1, 1e-2, 1e-3, 1e-4):
        D = V / an ** 4
        K = 1.0 * D * d0 ** 2 / 4
        Ks.append(K)
        print(f"      {an:>10.0e}{D:>16.0e}{K:>16.2e}")
    diverges = Ks[-1] / Ks[0] > 1e6
    print()
    print("      At constant c the emergent kinetic coefficient DIVERGES as a_n^-4,")
    print("      which is a projected field of infinite stiffness, not a field theory.")
    print("      Holding K finite forces c ~ a_n^4 -> 0.")
    print()
    print("      CONSEQUENCE FOR THE BOOK.  This is what RULES OUT the bare reading of")
    print("      P3's gradient term.  eq:boolean-grad-sq ALREADY defines it as the bare")
    print("      sum, so this branch is the book's and there is no choice to make:")
    print("      c carries a 1/|D|, c ~ a_n^4, and c-tilde = c|D| is the constant.")
    print("      'c = 1' is disposed of twice over: c is no constant, and it carries")
    print("      epsilon's dimensions, so no bare number can be asserted without a unit.")
    print("      (v32.74 read the postulate as silent here and added a contradicting")
    print("      per-site definition.  Withdrawn at v32.77; see RESULT 4.)")
    print()
    print(f"      -> a constant c makes K diverge                          : {diverges}")
    print()
    return diverges


def part3():
    rule()
    print("  3.  MEASURING THE LIMIT: eq:mosco-limit IS MISSING A2's 1/V_M")
    rule()
    print("      A2 carries an explicit 1/V_M; eq:mosco-limit does not, and has an")
    print("      unnormalised E^Riem against a mu-expectation.  Measured here on an")
    print("      explicit 4D periodic lattice, bare nearest-neighbour difference form,")
    print("      f = sin(2pi x/L) cos(2pi y/L) sin(2pi z/L), whose exact Dirichlet")
    print("      integral is 3 pi^2 L^2 / 2 (each of the three terms contributes")
    print("      (2pi/L)^2 * L^4/8 = pi^2 L^2/2; it goes as L^2, not as V = L^4).")
    print()

    def lattice(N, L):
        a = L / N
        g = np.arange(N) * a
        X = np.meshgrid(*[g] * 4, indexing="ij")
        f = (np.sin(2 * np.pi * X[0] / L) * np.cos(2 * np.pi * X[1] / L)
             * np.sin(2 * np.pi * X[2] / L))
        E = sum(np.sum((np.roll(f, -1, axis=m) - f) ** 2) for m in range(4))
        return a, N ** 4, E

    print(f"      {'N':>5}{'L':>6}{'V = L^4':>10}{'(E/|D|) V / a^2':>18}{'exact 3pi^2L^2/2':>18}{'ratio':>9}")
    ratios = []
    for N, L in ((16, 1.0), (32, 1.0), (32, 2.0), (32, 3.0)):
        a, D, E = lattice(N, L)
        V = L ** 4
        lhs = (E / D) * V / a ** 2
        exact = 1.5 * math.pi ** 2 * L ** 2
        ratios.append(lhs / exact)
        print(f"      {N:>5}{L:>6.1f}{V:>10.1f}{lhs:>18.4f}{exact:>18.4f}{lhs/exact:>9.4f}")
    ok = all(abs(r - 1) < 0.05 for r in ratios)
    print()
    print("      The 1/V is present and is NOT an artefact of the box size: it holds")
    print("      across a factor 81 in V.  So the correct statement is")
    print("          (1/|D|) E^B  ->  (kappa/V) E^Riem  =  kappa <|grad f|^2>,")
    print("      with <.> the normalised average.  This is a correction to the book's")
    print("      own equation, not to a computation.")
    print()
    print(f"      -> the measured limit carries 1/V, to within 5%          : {ok}")
    print()
    return ok


def part4():
    rule()
    print("  4.  WHAT THIS DOES TO comp 176, AND WHAT SURVIVES")
    rule()
    print("      With all three terms of F in the same normalised average,")
    print("          F -> a <phi^2> + b <phi^4> + K <|grad phi|^2>,")
    print("      and rescaling to canonical form in 4D gives")
    print("          lambda_canon = b V / K^2,    NOT  1/(4 c^2).")
    print()
    print("      comp 176's 1/(4c^2) is a true identity about F in SUBSTRATE")
    print("      variables, used there as though it were the coupling the seagull")
    print("      sees.  The two agree only if K = c sqrt(V).  So the free number is")
    print("      the composite K/sqrt(V), not P3's bare c.")
    print()
    print("      WHAT SURVIVES.  comp 176's conclusions use only the RATIO of two")
    print("      lambda_canon values, and M_* ~ lambda_canon^{-1/2} holds whatever")
    print("      lambda_canon is built from.  Check that explicitly:")
    print()
    E = math.e
    lamA, lamB = 0.25, 0.25 / E          # reading A and reading B, as couplings
    ratio = math.sqrt(lamA / lamB)
    print(f"          reading A: lambda_canon = 1/4      = {lamA:.5f}")
    print(f"          reading B: lambda_canon = e^-1/4   = {lamB:.5f}")
    print(f"          M_* ratio = sqrt(lamA/lamB)        = {ratio:.5f}")
    print(f"          sqrt(e) = 1/Z                      = {math.sqrt(E):.5f}")
    ok = abs(ratio - math.sqrt(E)) < 1e-12
    print()
    print("      So the sqrt(e) = 1/Z derivation and the exclusion of reading B are")
    print("      untouched: they never needed the 1/(4c^2) form.  What is withdrawn is")
    print("      the identification of the free number with P3's bare coefficient.")
    print()
    print(f"      -> the 1/Z ratio survives without the 1/(4c^2) formula    : {ok}")
    print()
    return ok


def part5():
    rule()
    print("  5.  VERDICT: THE MOSCO ROUTE DOES NOT CLOSE THE ITEM")
    rule()
    print("      comp 176 offered two ways this could go.  Neither happened.")
    print()
    print("      NOT 'the limit fixes c against the Laplace-Beltrami normalisation'.")
    print("      Canonical form in 4D is reached by rescaling the field, which can be")
    print("      done for ANY K, so the target's normalisation imposes no condition.")
    print("      It fixes the MAP, not the VALUE.")
    print()
    print("      NOT 'c is absorbed into the QGH scaling and is not independent'.")
    print("      c is constrained to scale as a_n^4, which removes it as a CONSTANT")
    print("      but leaves the composite K = c |D| d_0^2/16 free.  One free number")
    print("      in, one free number out.")
    print()
    print("      WHAT WOULD CLOSE IT: a value for K = c-tilde d_0^2/16, needing d_0,")
    print("      a fixed length the Casimir chapter BOUNDS (<= 2.3 nm) but does not")
    print("      predict.")
    print()
    print("      A CLAIM WITHDRAWN HERE AT v32.77.  This slot said P3 left it unstated")
    print("      whether |grad_C psi|^2 was the bare edge sum or the per-site average,")
    print("      and called the choice editorial.  P3 DOES say: eq:boolean-grad-sq")
    print("      defines it as the bare (1/4) sum, and eq:poincare-boolean's")
    print("      Efron-Stein equality holds only for that form.  v32.74 acted on the")
    print("      false claim and added a contradicting definition of the same symbol,")
    print("      which also falsified that inequality by a factor |D|/4.  Withdrawn.")
    print()
    print("      WHAT FOLLOWS INSTEAD.  The bare branch is the book's, so c is not a")
    print("      constant: it carries a 1/|D|, c ~ a_n^4, and c-tilde = c|D| is the")
    print("      |D|-independent quantity, giving K = c-tilde d_0^2/16.  The residue")
    d0 = 2.3e-9
    print("      is ONE LENGTH: d_0, bounded at <= 2.3 nm and not predicted.")
    print(f"      c-tilde would then be of order 16/d_0^2 >= {16/d0**2:.3e} m^-2, a")
    print("      DIMENSIONFUL statement, which is the last reason no bare number can")
    print("      be asserted of c and the v32.72 wording had to change.")
    print()
    return True


def part6():
    rule()
    print("  6.  TAMPER TEST")
    rule()
    print("      The load-bearing claim is that the BARE sum in eq:boolean-dirichlet")
    print("      is what injects the divergent |D|.  If P3's gradient term were the")
    print("      per-site AVERAGE instead, no divergence would appear and part 2")
    print("      would be vacuous.  Measure both, with d_0 fixed as Appendix A says.")
    print()
    d0 = 1.0
    kappa = d0 ** 2 / 4
    print(f"      {'a_n':>10}{'|D| = 1/a_n^4':>16}{'K bare':>14}{'K averaged':>14}")
    bare, avg = [], []
    for an in (1e-1, 1e-2, 1e-3, 1e-4):
        D = 1.0 / an ** 4
        b, n = D * kappa, kappa
        bare.append(b); avg.append(n)
        print(f"      {an:>10.0e}{D:>16.0e}{b:>14.3e}{n:>14.3e}")
    grows = bare[-1] / bare[0] > 1e6
    flat = max(avg) == min(avg)
    print()
    print(f"      bare form: K grows without bound                        : {grows}")
    print(f"      averaged form: K is constant in a_n                     : {flat}")
    print()
    print("      So the divergence belongs to the bare sum, which is exactly what")
    print("      eq:boolean-grad-sq writes.  The averaged column is NOT an alternative")
    print("      reading of P3, it is the counterfactual: it shows the divergence is a")
    print("      property of the bare form and not of the setup, which is what makes")
    print("      'c carries a 1/|D|' a conclusion rather than a preference.")
    print()
    return grows and flat


def main():
    print()
    rule()
    print("  COMPUTATION 177.  Does the Mosco limit fix P3's kinetic coefficient?")
    rule()
    print("""
  comp 176 named this route as the one that would close the field-normalisation
  item.  It does not close it.  What it does is show that c is the wrong
  variable, correct two statements shipped the same day, and one of the book's
  own equations, and reduce the residue to A1 plus the value of d_0.
""")
    r1, r2, r3, r4, r5, r6 = part1(), part2(), part3(), part4(), part5(), part6()

    rule()
    print("  ASSESSMENT")
    rule()
    print(f"  1. the map c -> K is fixed by Mosco, with no free constant : {r1}")
    print(f"  2. the bare reading diverges, which forces the averaged one : {r2}")
    print(f"  3. eq:mosco-limit is missing A2's 1/V_M, measured          : {r3}")
    print(f"  4. comp 176's conclusions survive; its formula's scope does not : {r4}")
    print(f"  5. verdict: route does not close it; half the item does    : {r5}")
    print(f"  6. tamper test: the divergence is the bare sum's, not assumed : {r6}")
    print()
    print("""  RESULT.  A negative answer to the question comp 176 posed, three
  corrections, one of them to this file.

  The Mosco limit fixes the MAP from P3's gradient coefficient to the emergent
  kinetic one, with no free constant anywhere in it.  It does not fix the VALUE,
  because canonical form in 4D is reached by rescaling the field and that can be
  done for any K.  So one free number goes in and one comes out.  That much is the
  no.

  What the divergence in part 2 forces is what happens to c.  eq:boolean-grad-sq
  defines P3's gradient as a BARE (1/4) sum over D, and eq:mosco-limit divides by
  |D|, so K = c |D| d_0^2/16; A1 sends |D| -> V/a_n^4 -> infinity with d_0 fixed, and
  a constant c would make the projected field infinitely stiff.  So c is NOT a
  constant.  It carries a 1/|D|, equivalently c ~ a_n^4 -> 0, and the
  |D|-independent quantity P3 owns is c-tilde = c |D|, giving K = c-tilde d_0^2/16.

  CORRECTED AT v32.77, AND THE CORRECTION IS TO THIS FILE.  An earlier version said
  P3 had never stated whether its gradient was the bare sum or the per-site average,
  and called the choice editorial.  It had stated it, at eq:boolean-grad-sq, and
  eq:poincare-boolean's Efron-Stein equality holds only for that form.  Acting on the
  false claim, v32.74 added a second definition of the same symbol eighty-four lines
  later, contradicting the first and falsifying the cited inequality by a factor
  |D|/4.  Both are withdrawn.  The bare reading is the book's, and the conclusion is
  the stronger one: not that a choice was available, but that c scales.

  So the residue is ONE LENGTH: d_0, which the Casimir chapter bounds at <= 2.3 nm
  and does not predict.  Smaller than "which scalar field is canonically normalised",
  and still a residue, reported as one.

  Two further corrections stand.  eq:mosco-limit was missing the 1/V_M that A2
  supplies, measured here to 0.3% across a factor 81 in volume.  And comp 176's
  lambda_canon = 1/(4c^2) is a substrate-variable identity that skips the
  projection; in 4D the coupling is b V / K^2.  comp 176's CONCLUSIONS survive
  intact, because the sqrt(e) = 1/Z ratio and the exclusion of reading B use only
  the ratio of two couplings and never the formula.""")
    print()
    return all([r1, r2, r3, r4, r5, r6])


if __name__ == "__main__":
    import sys
    # Exit only on FAILURE.  The website runs these in the browser under Pyodide,
    # where SystemExit is fatal even at status 0: it tears the runtime down, and the
    # page prints ERROR after output that was in fact correct.  Falling off the end
    # hands the build gates the same status 0, and a failure still exits 1.
    if not main():
        sys.exit(1)
