The file src/27-fields/enumerate_maxwell.py of the validation package of the paper 27-fld, rendered with an anchor per line; the file itself is beside this page.
1# framed-rational status: MIXED -- exact framed-rational core; continuum constructs are confined to clearly-labelled [approx] / degenerate-idealisation comparisons (Tier 2/3/5 or measured-data), never to an exact claim.2"""3O1: uniqueness of the lattice Maxwell functional.45Determines the space of quadratic functionals S[A] = A^T Q A of a U(1) lattice6gauge field on a periodic cubic lattice that are simultaneously7 (T) translation invariant,8 (L) range-R local (kernel supported on |x-y|_inf <= R),9 (C) hypercubic invariant (the order-48 signed-permutation point group),10 (G) gauge invariant (Q B = 0, B the lattice gradient A -> A + d.lambda).1112The point group acts directly on oriented links as signed permutations (a13reflection reverses a link, flipping sign and shifting base), so conjugation14P_g^T Q P_g is a flat index-permutation-with-sign on vec(Q). We intersect (G)15and (C) via the Gram matrix on the (T,L) parameter space and report the16dimension of the admissible Q-space. Expectation: dim = 1 (Maxwell) at R = 1.17"""18import numpy as np19import itertools2021d = 3222324def build(L):25 sites = list(itertools.product(range(L), repeat=d))26 sidx = {s: i for i, s in enumerate(sites)}27 def add(x, z): return tuple((x[i] + z[i]) % L for i in range(d))28 links = [(s, mu) for s in sites for mu in range(d)]29 lidx = {l: i for i, l in enumerate(links)}30 nlink = len(links); nsite = len(sites)3132 B = np.zeros((nlink, nsite))33 for (x, mu) in links:34 e = tuple(1 if k == mu else 0 for k in range(d))35 B[lidx[(x, mu)], sidx[add(x, e)]] += 1.036 B[lidx[(x, mu)], sidx[x]] -= 1.03738 group = []39 for pi in itertools.permutations(range(d)):40 for eps in itertools.product((1, -1), repeat=d):41 R = np.zeros((d, d), dtype=int)42 for a in range(d):43 R[pi[a], a] = eps[pi[a]]44 group.append(R)4546 # link signed-permutation for each isometry: A'[k] = s[k]*A[sigma[k]]47 def link_perm(R):48 sigma = np.empty(nlink, dtype=int); s = np.empty(nlink)49 for (x, mu) in links:50 k = lidx[(x, mu)]51 col = R[:, mu]; mup = int(np.nonzero(col)[0][0]); sgn = int(col[mup])52 Rx = tuple(int(sum(R[i, j] * x[j] for j in range(d))) % L for i in range(d))53 if sgn == 1:54 src = lidx[(Rx, mup)]; sg = 1.055 else:56 base = tuple((Rx[i] - (1 if i == mup else 0)) % L for i in range(d))57 src = lidx[(base, mup)]; sg = -1.058 sigma[k] = src; s[k] = sg59 return sigma, s6061 # flat (i,j)->(t[i],t[j]) permutation and sign for conjugation P_g^T Q P_g62 flatperm, flatsign = [], []63 for R in group:64 sigma, s = link_perm(R)65 t = np.empty(nlink, dtype=int); t[sigma] = np.arange(nlink); st = s[t]66 fp = (t[:, None] * nlink + t[None, :]).reshape(-1)67 fs = (st[:, None] * st[None, :]).reshape(-1)68 flatperm.append(fp); flatsign.append(fs)6970 return dict(sites=sites, add=add, links=links, lidx=lidx, nlink=nlink,71 nsite=nsite, B=B, flatperm=flatperm, flatsign=flatsign, group=group)727374def param_basis(g, R):75 sites, add, lidx, nlink = g['sites'], g['add'], g['lidx'], g['nlink']76 disp = [z for z in itertools.product(range(-R, R + 1), repeat=d)77 if max(abs(c) for c in z) <= R]78 seen, Qs = set(), []79 for mu in range(d):80 for nu in range(d):81 for z in disp:82 if (mu, nu, z) in seen: continue83 seen.add((mu, nu, z)); seen.add((nu, mu, tuple(-c for c in z)))84 Q = np.zeros((nlink, nlink))85 for x in sites:86 Q[lidx[(x, mu)], lidx[(add(x, z), nu)]] += 1.087 Qs.append(0.5 * (Q + Q.T))88 return Qs899091def maxwell_Q(g):92 sites, add, lidx, nlink = g['sites'], g['add'], g['lidx'], g['nlink']93 Q = np.zeros((nlink, nlink))94 for x in sites:95 for mu in range(d):96 for nu in range(mu + 1, d):97 emu = tuple(1 if k == mu else 0 for k in range(d))98 enu = tuple(1 if k == nu else 0 for k in range(d))99 terms = [(+1, lidx[(x, mu)]), (+1, lidx[(add(x, emu), nu)]),100 (-1, lidx[(add(x, enu), mu)]), (-1, lidx[(x, nu)])]101 for s1, i in terms:102 for s2, j in terms:103 Q[i, j] += 0.5 * s1 * s2104 return Q105106107_P = (1 << 61) - 1 # Mersenne prime; exact finite-field linear algebra (framed-rational)108109def _nullspace_modp(M, p=_P):110 """Exact rank and nullspace basis of an integer matrix over F_p (Gaussian111 elimination in F_p, python ints, no float). Used for the exact admissible112 dimension; p > all entry magnitudes, so the F_p corank equals the rational corank."""113 A = [[int(x) % p for x in row] for row in M.tolist()]114 rows = len(A); cols = len(A[0]) if rows else 0115 r = 0; pivots = []116 for c in range(cols):117 piv = next((i for i in range(r, rows) if A[i][c] % p), None)118 if piv is None:119 continue120 A[r], A[piv] = A[piv], A[r]121 inv = pow(A[r][c], p - 2, p)122 A[r] = [(x * inv) % p for x in A[r]]123 for i in range(rows):124 if i != r and A[i][c] % p:125 f = A[i][c]; A[i] = [(A[i][j] - f * A[r][j]) % p for j in range(cols)]126 pivots.append(c); r += 1127 if r == rows:128 break129 free = [c for c in range(cols) if c not in pivots]130 basis = []131 for fc in free:132 v = [0] * cols; v[fc] = 1133 for ri, pc in enumerate(pivots):134 v[pc] = (-A[ri][fc]) % p135 basis.append([x - p if x > p // 2 else x for x in v]) # balanced representative136 return r, basis137138139def admissible(L, R):140 g = build(L)141 Qs = param_basis(g, R); n = len(Qs); nlink = g['nlink']142 Qstack = np.array([Q.reshape(-1) for Q in Qs]) # (n, nlink^2)143 # gauge residual block: vec(Q_a B)144 QB = np.array([(Q @ g['B']).reshape(-1) for Q in Qs]) # (n, nlink*nsite)145 # Exact admissible dimension (no float eigenvalues). Build the same Gram form as146 # before, but in INTEGER arithmetic (2*Q_a is integral, entries +-1), then take its147 # exact rational corank: a combination sum_a c_a Q_a is admissible iff c is in the148 # nullspace of the (integer) Gram = sum of the gauge- and cubic-constraint Grams.149 # dim = n - rank(Gram), computed exactly, not by a float eigenvalue threshold.150 Qint = [np.rint(2 * Q).astype(np.int64) for Q in Qs] # integral (entries +-1)151 Bint = g['B'].astype(np.int64)152 QBi = np.array([(Qint[a] @ Bint).reshape(-1) for a in range(n)]) # gauge block (n, nlink*nsite)153 Gram = QBi @ QBi.T # integer n x n (PSD)154 Qstk = np.array([Q.reshape(-1) for Q in Qint])155 for fp, fs in zip(g['flatperm'], g['flatsign']):156 D = Qstk[:, fp] * fs - Qstk # integer (n, nlink^2)157 Gram = Gram + D @ D.T158 _, nb = _nullspace_modp(Gram) # exact F_p corank (Tier-1 claim)159 dim = len(nb)160 # reps span the same admissible space and feed ONLY the [approx] continuum-symbol161 # reading below; a well-conditioned real basis is taken for that, and its count is162 # cross-checked against the exact framed-rational dimension above.163 w, V = np.linalg.eigh(Gram.astype(float))164 null = V[:, w < 1e-7 * max(1.0, w.max())]165 assert null.shape[1] == dim, "float/exact corank mismatch"166 reps = [sum(null[a, c] * Qs[a] for a in range(n)) for c in range(dim)]167 return dim, reps, g168169170def kernel_of(Q, g):171 """Read the translation-invariant kernel M_{mu,nu}(z) from the origin rows."""172 x0 = (0,) * d; lidx, addf = g['lidx'], g['add']173 disp = [z for z in itertools.product(range(-2, 3), repeat=d)174 if max(abs(c) for c in z) <= 2]175 K = {}176 for mu in range(d):177 for nu in range(d):178 for z in disp:179 v = Q[lidx[(x0, mu)], lidx[(addf(x0, z), nu)]]180 if abs(v) > 1e-12:181 K[(mu, nu, z)] = v182 return K183184185def symbol(K, k):186 S = np.zeros((d, d), complex)187 for (mu, nu, z), v in K.items():188 S[mu, nu] += v * np.exp(1j * np.dot(k, z))189 return 0.5 * (S + S.conj().T)190191192def relevant_split(reps, g):193 """Split the admissible space into relevant (O(k^2)) and irrelevant (O(k^4))194 by the rank of the leading small-k symbol signature; check the relevant195 operator equals the Maxwell transverse projector |k|^2 delta - k k."""196 Ks = [kernel_of(r, g) for r in reps]197 dirs = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (1, 0, 1),198 (0, 1, 1), (1, 1, 1), (1, -1, 0), (2, 1, 0)]199 t = 1e-3200 sig = []201 for K in Ks:202 row = []203 for dv in dirs:204 kk = t * np.array(dv) / np.linalg.norm(dv)205 row.append(symbol(K, kk).real[np.triu_indices(d)] / t**2)206 sig.append(np.concatenate(row))207 sig = np.array(sig)208 s = np.linalg.svd(sig.T, full_matrices=False)[1]209 nrel = int(np.sum(s > 1e-6)); nirr = len(reps) - nrel210 # relevant generator and its deviation from the Maxwell projector211 crel = np.linalg.svd(sig.T, full_matrices=False)[2][0]212 Krel = {}213 for c, K in zip(crel, Ks):214 for key, v in K.items():215 Krel[key] = Krel.get(key, 0.0) + c * v216 dev = []217 for dv in [(1, 0, 0), (1, 1, 0), (1, 1, 1), (2, 1, 0), (3, 1, 1)]:218 kk = np.array(dv); S = symbol(Krel, t * kk).real / t**2219 P = np.dot(kk, kk) * np.eye(d) - np.outer(kk, kk)220 dev.append(np.linalg.norm(S / np.trace(S @ P) * np.trace(P @ P) - P)221 / np.linalg.norm(P))222 return nrel, nirr, max(dev)223224225if __name__ == "__main__":226 print("=" * 68)227 print(f"O1 uniqueness of the lattice Maxwell functional (d={d})")228 print("=" * 68)229230 g5 = build(5); QM = maxwell_Q(g5)231 gres = np.abs(QM @ g5['B']).max()232 cub = all(np.allclose((QM.reshape(-1)[fp] * fs).reshape(g5['nlink'], g5['nlink']), QM)233 for fp, fs in zip(g5['flatperm'], g5['flatsign']))234 print(f"Maxwell plaquette action: ||Q_M B||_inf = {gres:.1e} (gauge-inv {gres<1e-9});"235 f" hypercubic-inv {cub}")236 print("-" * 68)237238 for L in (4, 5, 6):239 dim, reps, g = admissible(L=L, R=1)240 nrel, nirr, dev = relevant_split(reps, g)241 print(f"range R=1 (L={L}): dim(T&L&C&G) = {dim} ="242 f" {nrel} relevant (O(k^2)) + {nirr} irrelevant (O(k^4));"243 f" relevant vs Maxwell projector: {dev:.1e}")244 print("-" * 68)245 print("Conclusion: the range-1 admissible space is 2-dimensional, and splits")246 print("into exactly ONE relevant operator -- the Maxwell action, whose symbol")247 print("is the transverse projector |k|^2 d_{mn} - k_m k_n -- plus one")248 print("irrelevant O(k^4) higher-derivative lattice artifact. Maxwell is the")249 print("unique relevant adjacency-local gauge+hypercubic quadratic functional.")250 print("=" * 68)251