sillclass.py
Checks: THERMAL: The lim inf is the class minimum theorem; observation; THERMAL: The 2-power tower raises the sill theorem; rule.
Cited on: THERMAL.
To run it: save sillclass.py, with fieldtop.py, growth.py, memory.py, spectrum.py, splitend.py, splitloss.py, splitsharp.py, typeloss.py beside it; needs mpmath, numpy, scipy.
"""sillclass.py -- the sill without its hypothesis: the lim inf of the
columns at the places of prime norm, read through the classes that K's
largest abelian subfield K_ab allows, and whether a field containing
Q(i), where the sill rises, still loses.
QUESTION. The sill L = L(2) is the lim inf over split r = 3 mod 4
given a prime s = 3 mod 4 split completely and = 1 mod no odd ramified
prime. Without that hypothesis, what is the lim inf of the headroom sums
at the places P of prime norm r, and at type (1, 0) with Q(i) inside K,
where it rises, does the F2 place still lose, at every degree?
THE DERIVATION. N~ the Galois closure, H = Gal(N~/K), A = N~ cap Q^ab,
K_ab = K cap Q^ab, f its conductor, N = lcm(4, f), m(a) = prod over
l | N of l^min(v_l(a - 1), v_l(N)), L(m) the product over the places R
of K of 1 + n^-b + ... + n^-(j b), n = N(R), j the deepest with
lambda(R^j) | m (finite: lambda(R) | m needs n <= m + 1).
(1) CLASSES. r has a place of degree 1 iff Frob_r lies in U, the union
of H's conjugates; conjugation is trivial on A, so U|_A = H|_A =
Gal(A/K_ab): the classes r mod N that occur are the a trivial on K_ab
(G_N). Split r give only the classes trivial on A.
(2) FLOOR. At P of prime norm r > m(a) + 1, r = a mod N: m(a) | r - 1,
so every R with lambda(R^j) | m(a) enters to depth j: Sigma >= L(m(a)).
(3) REACH (the sill's z-step). A lift a' mod N rad N with v_l(a' - 1)
= v_l(m(a)) exactly, r = a' there, Frob_r in U over a, r != 1 mod each
l < z off N, z > N + 1: an entrant past L(m(a)) has n > z (a prime of
n - 1 off N divides r - 1) or lies over r (norm r without bound, factor
-> 1; norm r^f, f >= 2, never), and no entrant of L(m(a)) is deeper
(its prime p is below z and deepens R only where p | r - 1, so p
divides N, where v_p(r - 1) is exact).
(4) TAIL (Brun-Titchmarsh): log T = O(d A(r)) + o(1), A(r)
the sum of delta^-b over divisors z <= delta <= sqrt r of r - 1, its
sum to X at most (4X/log X) eps(z), eps(z) -> 0.
(5) DENSITY (Chebotarev). F = N~ cap Q(zeta_N'), N' = N rad N times
the l < z off N, lies in A; any c mod N' with c = a' and c != 0, 1
mod each such l is trivial on K_ab, so c|_F is in Gal(F/F cap K_ab) =
U|_F and some sigma in U matches it: the set has density at least
[F:Q] prod (l - 2) / (|Gal(N~/Q)| phi(N rad N) prod (l - 1)), of order
1/log z, c mod l off N being free, and by Markov half of it has A(r) <= 9 eps(z)/c_z -> 0.
So lim inf over the places of prime norm of Sigma(P) is L* = min over
a in G_N of L(m(a)), finitely many classes, a read through 2 and the
primes ramified in K_ab. K_ab = Q (every primitive K not Galois over
Q, every S_d closure at d >= 3 among them, Q(i) or Q(sqrt -3) in it or
not; a quadratic or cyclic K has K_ab = K): a = 3 mod 4, m = 2, L* = L. K containing Q(i): every a is 1 mod 4 and every
odd norm 1 mod 4 (p = 3 mod 4 is inert in Q(i)), so L(4) floors every
odd column of norm above 5; it is sharp where some a in G_N has m(a)
= 4 (then a lift a' = 5 mod 8 in step (3)), as at K_ab = Q(i). At Q(i)
itself U^1 = mu_4 x U^3 and squaring
maps U^j onto U^(j+2) for j >= 3, so the chain over 2 is 1, 2, 4, 4, 4,
4, 4, 8: depth 7. At type (1, 0), e = d >= 4, the place over 2 is
held to depth exactly 4 at v_2 = 2 ((1 + pi)^2 has valuation 2, its
square 4 when e > 2; every 4th power of a 1-unit is in U^4), no place
has norm 3: L_i = (1 + x + x^2 + x^3 + x^4) S5 against sigma_F2 = S5 W'.
M = l - l5 - w' (norm 5 cancels); at x_c, M = h5(x_c) + w5(x_c), h5 = 2
l - l5 + log x increasing; (1 - x) M' = 1 - 5 x^4/(1 + ... + x^4) - the
n != 5 terms, each increasing on (0, 1/2] (typeloss's D(x, a) > 0 at a
>= log2 9), so M is quasi-concave on [0, x_c], x_c <= 1/2, and
log(1 + margin) >= min(0, M(x_c)). At fixed n5 both terms rise with x_c,
which falls with the other counts, so the bound takes them maximal
(n9 <= d/2: 3 is inert in Q(i)) and scans n5 = 0..d.
REALIZATION. K = Q(i)[t]/g, g monic over Z[i] of degree m = d/2, by
the Chinese remainder theorem near local polynomials at the primes of
Z[i] below Y = 10^5 and, by Krasner's lemma, with exactly those local
algebras; at three primes of Z[i] above Y of norm a rational prime the
unramified field of degree m, degree m - 1 beside Q_p, and the
unramified quadratic beside Q_p^(m - 2) give S_m over Q(i) (m >= 3),
and K_ab = Q(i): S_m is primitive, so no field lies strictly between
Q(i) and K, and K is not Galois over Q(i), so not abelian; at m = 2, split at one prime over q >= Y
and inert at its conjugate, K is not Galois over Q, D_4, K_ab =
Q(i). At 2,
Q_2(i)((1 + i)^(1/m)), e = d.
(L) THE LEMMA FROM 930, at arm B's law (below). lam = log(1/x), a_n
= log2 n, y = 9^-b = x^a9. The point solves l + lz + log(1 - (1 -
x)e^-s) = 0, lz the log of the odd places' zeta, s = log(Z'/W); the
last term is at most log x + s/x, so g_up = l + lz + log x + s/x
bounds the left side, which rises with x. x1 solves d x^a9 = lam (the
d/2 places of norm 9 give (d/2) 9^-b = lam/2), falls as d rises, and
x1 <= 1/7 iff d >= d0 = lam0 7^a9, lam0 = log 7. There, with d = lam
9^b: lz <= (lam/2)/(1 - y) + lam sum_{n = 17, 257, 65537} (9/n)^b/(1
- n^-b) + lam (9/Y)^b (1 + Y/(b - 1))/(1 - Y^-b) (the tail past Y, d
places over each prime) + E, E over the places of norm p^m and p^d
below Y, at most 4 5^(-m b)(1 + 5/(m b - 1)) (integral test); s/x <=
(lam/2) x^(a9 - 1)/(1 - y^2) + lam sum_n (18/n^2)^b/(1 - n^-2b) + lam
(18/Y)^b (1 + Y/(b - 1))/(1 - Y^-b) + E/x (a place of W adds
-log(1 - y^2) <= y^2/(1 - y^2), the others whole). Every coefficient
of lam rises with x, so is bounded at 1/7, and l <= log(7/6): g_up(x1)
<= log(7/6) - (1 - c_z - c_s) lam0 + E', needing 1 - c_z - c_s > 0.
w' >= (d/2) log(1 + y) >= (lam/2)(1 - y/2), so M(x1) <= log(7/6) -
(lam0/2)(1 - y0/2), y0 = 7^-a9; M'(x1) <= 7/6 - a9 (lam0/2) 7/(1 +
y0), every other term of M' being negative. Where g_up(x1) < 0 the
point is above x1; M is quasi-concave on [0, x_c], the point at most
x_c, so M'(x1) < 0 puts x1 past the peak and the margin at most M(x1).
PREDICTIONS (frozen before this code).
P1 quadratic fields with an F2 place, |D| <= 400: L* = L at every D
but -4; at -4, L* = (1 + ... + x^7)(1 + 5^-b)^2, the chain over 2
of Z[i] reading 1, 2, 4, 4, 4, 4, 4, 8.
P2 at Q(i) and Q(sqrt -7), over the split r < 2*10^5 in the best
class, Sigma/L* - 1 >= -1e-12 and its least value below 1e-4; in
a worse class (Q(sqrt -7), a = 1 mod 8) its least value stays above
L(8)/L* - 1 > 0.01.
P3 K in Q(i), type (1, 0), even d: the bound positive up to D_low,
the certificate negative from D_high, both in [30, 100], and
negative at every even d from D_high to 1000.
P4 (the lemma, frozen before its code) d0 = ceil(log 7 * 7^a9) is
between 900 and 960.
P5 at x = 1/7: g_up <= -0.40, M <= -0.80, M' <= -20. KILL: g_up >= 0,
M >= 0 or M' >= 0 printed at x = 1/7, or d0 > 1000.
CONTROLS (frozen).
C1 at six quadratic fields the class minimum equals the direct L to
1e-12 at b = 1.5.
C2 at Q(i), L* >= sigma_F2 at the F2 point (the quadratic theorem).
C3 the brute chain over 2 at Q(i), j = 1..8, is 1, 2, 4, 4, 4, 4, 4,
8.
C4 with the sill and law set back to typeloss's (1, 0), QiLaw's
certificate reproduces typeloss.extremal(1, 0, d, "E").cert() to
1e-12 at d = 4, 8.
C5 PLANT: a Q(i) law with 5, 17, 257, 65537 of residue degree m over
each prime of Z[i] gives a certificate >= 0 at D_high.
C6 (added at review, the new M's own control): QiLaw.m at x = 0.3
equals log(L_i/sigma_F2) from the products at qi_law(20) to 1e-12;
QiLaw.dm equals M's central difference to 1e-6; and at d = 20, n5 =
0 and 20, bound_i's h5(x_c) + n5 log(1 + x_c^a5) equals QiLaw.m at
x_c on the law of exactly those counts, to 1e-12.
C7 at every even d from d0 to 1000, at arm B's law: x1 <= x_low of
the certificate, C <= M(x1) <= the lemma's M bound, and the law's
own g_up(x1) and M'(x1) below the lemma's.
C8 PLANT: the lemma's constants with d places of norm 9 (3 split
completely, which Q(i) forbids) print g_up >= 0 at x = 1/7.
C9 the lemma's lz and s/x bounds against a brute sum over arm B's
places at d = 1000, x = x1, coefficients at 1/7 and at x1.
FINDINGS.
CONTROLS. C1: L* = L to the last printed digit at D = -7, 8, -8, 12,
-20, 17, each at m = 2 (a = 11 mod 28, 7 mod 8, 3 mod 8, 11 mod 12,
3 mod 20, 15 mod 68). C2: at Q(i) the F2 point 1.496693, sigma_F2
1.268618, L* 1.839476, +0.44998. C3: the chain over 2 of Z[i] is 1,
2, 4, 4, 4, 4, 4, 8, 8, 16, 16, 32, 32 at j = 1..13. C4: difference 0
at d = 4 and 8 (C -0.075606, -0.332186, typeloss's), by construction
(QiLaw(old=True) is typeloss's TypeLaw): it reads the wiring, not the
new M. C5 (restated, see RUN RECORD): no certificate negative where the
bound is positive. C6: 8.9e-16, 3.7e-10, 6.1e-16.
P1 HOLDS. 160 fundamental D, |D| <= 400, with an F2 place; L* != L at
D = -4 alone, L*/L - 1 = 0.241461 at b = 1.5, m = 4, entrants (2, 7),
(5, 1), (5, 1); the old hypothesis holds exactly where some class has
m = 2 (no field differs).
P2 FAILS as frozen, at one column: at Q(i), r = 5, Sigma/L* - 1 =
-0.07317, the column at a place of norm 5 = m + 1, which L* counts as
an entrant (the floor needs r > m(a) + 1). Over r > m + 1, 0 of the
4510 columns past r = 5 at Q(i) (r = 5 mod 8) and 0 of the 4511 at
Q(sqrt -7) (split, r = 3 mod 4, the classes of m = 2 and 14) fall
below L*; the least Sigma/L* - 1 is 1.165e-8 at r = 199877 (r - 1 =
4*107*467) and 1.558e-9 at r = 199679 (r - 1 = 2*99839). In the worse class (Q(sqrt -7), r = 1 mod 8) the least over
2195 columns is 4.467e-2 at r = 198377, L(8)/L* - 1 = 0.044666.
P3 FAILS as frozen. The bound is positive at every even d <= 10
(+0.282440 at 4, +0.027465 at 10) and at most 0 at every even d from
12 (-0.029970) to 200, where it is computed, its argmin n5 = 0 at
every d printed: the worst field has no place of
norm 5, which cancels in M and only holds the point low. So the frozen
law (5 split completely) is not the worst: its certificate is
positive to d = 62 (+0.001821) and negative from 64 (-0.000138) to
1000 (-0.073291), M' < 0 and x_c < 1/2 at each. ARM B, added after
the run, the bound's argmin, 5 of residue degree m over each prime of
Z[i]: certificate +0.041683 at 12, negative from 14 (-0.007276) at
every even d to 1000 (-1.537822), M' < 0, x_c < 1/2. So with Q(i) in
K, type (1, 0): no field loses at d = 4..10, and at every even d =
14..1000 a field that loses exists (realized by Krasner over Z[i],
K_ab = Q(i)), d = 12 undecided at this law (tower.py, its algebras
fixed to Y = 10^30, certifies it). "Loses" means infinitely many
columns top the F2 place: the at most d columns at places of norm 5 sit below L_i (the
r = 5 print at Q(i)) and are raced apart, as the cubic column of norm
3 is.
THE LEMMA. C7: at each of the 36 even d from 930 to 1000 it holds, the
largest M(x1) -1.144476 at d = 930 (x1 0.142816, x_low 0.154056, C
-1.513372, g_up(x1) -0.478610, M'(x1) -29.7347). C8: c_z 1.169962,
g_up <= +0.514220, so the lemma can say no. C9: lz + lt 1.307854
against c_z lam 1.315025 (at 1/7) and 1.308875 (at x1); (lz - sw +
lt)/x 1.455e-2 against 1.523e-2 and 1.455e-2 (the norm-9 term all but
exact at x1). P4 HOLDS: d0 = 930 (929.0096). P5 HOLDS: c_z 0.668913,
c_s 0.007745, 1 - c_z - c_s 0.323342, E' at most 10^-910.94 (kept as
1e-300, an upper bound, not a float zero); g_up <= -0.475044, M <=
-0.817785, M' <= -20.3776.
KILL MISSED: arm B loses at every even d >= 930, so with its
certificates, a field containing Q(i), type (1, 0), loses at every
even d >= 14.
RUN RECORD. `python sillclass.py` under the gate's 512 MB cap: 16 of 16
checks (12 before section L), 24.7 s, peak commit 68.7 MB. First run: the chain over 2 (to
norm 2^13) ran out at r - 1 with a high power of 2; extended by lambda(j)
= 2 lambda(j - e) past the brute (long_chain), read against the brute
at Q(i) through j = 13. The P1 print first compared the old hypothesis
with the first minimizing class's m, which ties miscount (D = 120,
204); it now asks whether some class has m = 2. The r > m + 1 read was
added beside the frozen one after the r = 5 column. C5 was frozen as
"the law with 5, 17, 257, 65537 of residue degree m prints C >= 0 at
D_high" (a plant meant to show the certificate can say no); it printed
-0.357978, the plant pushing the wrong way (dropping norm 5 hurts the
F2 place), and is restated as the consistency check above. At review:
C1 was frozen at five fields and runs six; C4 was frozen to reproduce
typeloss.bound too, and its bound arm was dropped (bound_i shares no code
with it), C4 reading only the subclass wiring; C6 was added as the new
M's control, read failing on a scratch copy with l5 replaced by l4.
The lemma (section L) ran first as a lab script, its first run
4 of 4 checks; it entered here unchanged but for names, the kill's
slope clause (1 - c_z - c_s > 0, which the frozen kill lacks and the
step in lam needs) printed beside the frozen ones.
"""
import math
import os
import sys
import time
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.join(HERE, "..", "code"))
os.environ.setdefault("OPENBLAS_NUM_THREADS", "1")
import numpy as np # noqa: E402
from scipy.optimize import brentq # noqa: E402
import fieldtop as ft # noqa: E402
import splitend as se # noqa: E402
import splitsharp as ss # noqa: E402
import typeloss as tl # noqa: E402
from growth import factor, is_prime_mr # noqa: E402
CHECKS = []
A5 = math.log2(5)
def check(name, ok, detail=""):
CHECKS.append(bool(ok))
print(f" [{'PASS' if ok else 'FAIL'}] {name}" + (f" ({detail})"
if detail else ""))
def guard():
if not all(CHECKS):
print("a control failed: no verdict")
sys.exit(1)
def vl(n, l):
v = 0
while n % l == 0:
n //= l
v += 1
return v
# ------------------------------------------- the classes, quadratic K
def classes(F):
"""G_N and m(a) for K = Q(sqrt D): K_ab = K, f = |D|."""
f = abs(F.D)
N = f * 4 // math.gcd(f, 4)
ls = sorted(factor(N))
out = []
for a in range(1, N):
if math.gcd(a, N) != 1 or ft.kronecker(F.D, a) != 1:
continue
m = 1
for l in ls:
cap = vl(N, l)
m *= l ** (cap if (a - 1) % l ** cap == 0 else vl(a - 1, l))
out.append((a, m))
return N, out
def entrants(F, ch2, m):
"""(norm, depth) of every place R with lambda(R) | m."""
out = []
for r in range(2, m + 2):
if not is_prime_mr(r):
continue
if r == 2:
for NR, ch in ch2:
j = 0
while j < len(ch) and m % ch[j] == 0:
j += 1
assert j < len(ch)
if j:
out.append((NR, j))
continue
k = F.kind(r)
NR = r * r if k == "inert" else r
cnt = 2 if k == "split" else 1
if m % ft.lam_formula(F, r, 1):
continue
j = 1
while m % ft.lam_formula(F, r, j + 1) == 0:
j += 1
out += [(NR, j)] * cnt
return out
def lval(ent, b):
s = 1.0
for NR, j in ent:
x = NR ** -b
s *= sum(x ** k for k in range(j + 1))
return s
def direct_sill(F, b):
x = 2.0 ** -b
k2, k3 = F.kind(2), F.kind(3)
L = (1 + x + x * x + x ** 3) ** 2 if k2 == "split" else 1 + x + x * x
S3 = {"split": (1 + 3.0 ** -b) ** 2, "ram": 1 + 3.0 ** -b,
"inert": 1.0}[k3]
return L * S3
def lstar(F, ch2, b):
N, cl = classes(F)
best = None
for a, m in cl:
v = lval(entrants(F, ch2, m), b)
if best is None or v < best[0] - 1e-15:
best = (v, a, m)
return best + (N,)
def old_hyp(F):
"""A split prime s = 3 mod 4, = 1 mod no odd prime dividing D."""
odd = [p for p in factor(abs(F.D)) if p != 2]
for s in range(3, 20000, 4):
if is_prime_mr(s) and F.kind(s) == "split" and \
all((s - 1) % p for p in odd):
return s
return None
def fundamental(D):
if D in (0, 1):
return False
if D % 4 == 1:
core = D
elif D % 4 == 0 and (D // 4) % 4 in (2, 3):
core = D // 4
else:
return False
return all(e == 1 for e in factor(abs(core)).values()) if abs(core) > 1 \
else core == -1
def section_q():
print("\n=== Q: the class minimum at the quadratic fields")
print("CONTROL C3: the chain over 2 at Q(i)")
Fi = ft.Field(-4)
ch = ft.chain2(Fi, 16)
print(f" chains over 2: {ch}")
check("C3 lambda((1 + i)^j), j = 1..8, is 1, 2, 4, 4, 4, 4, 4, 8",
ch[0][1][:8] == [1, 2, 4, 4, 4, 4, 4, 8])
print("CONTROL C1: the class minimum against the direct sill, b = 1.5")
for D in (-7, 8, -8, 12, -20, 17):
F = ft.Field(D)
v, a, m, N = lstar(F, ft.chain2(F, 16), 1.5)
L = direct_sill(F, 1.5)
check(f"C1 D={D}: L* = L", abs(v / L - 1) < 1e-12,
f"L* {v:.15f} at a={a} mod {N}, m={m}; L {L:.15f}")
guard()
print("P1: every fundamental D, |D| <= 400, with an F2 place")
raised, n, bad_old = [], 0, []
for D in range(-400, 401):
if not fundamental(D) or D % 8 == 5:
continue
F = ft.Field(D)
ch2 = ft.chain2(F, 16)
n += 1
v, a, m, N = lstar(F, ch2, 1.5)
L = direct_sill(F, 1.5)
s = old_hyp(F)
m2 = any(mm == 2 for _, mm in classes(F)[1])
if (s is None) != (not m2):
bad_old.append(D)
if abs(v / L - 1) > 1e-12:
raised.append((D, v / L - 1, a, m, N, s))
print(f" {n} fields read; L* != L at {[r[0] for r in raised]}")
for D, rel, a, m, N, s in raised:
print(f" D={D}: L*/L - 1 = {rel:.6f} at a={a} mod {N}, m={m}; "
f"old hypothesis s = {s}")
print(f" fields where 'old hypothesis holds' differs from 'some class "
f"has m = 2': {bad_old}")
ent = entrants(Fi, ch, 4)
print(f" Q(i) at m = 4: entrants {ent}")
p1 = [r[0] for r in raised] == [-4] and \
sorted(ent) == [(2, 7), (5, 1), (5, 1)]
print(f" P1 {'holds' if p1 else 'FAILS'}")
return Fi, ch
# --------------------------------------------- R: the reach, sampled
def column_sum(F, ch2, r, b, nmax=10 ** 10):
"""Sigma at a place of norm r (r split), entrants of norm <= nmax."""
s = 1.0 / (1 - r ** -b) # the conjugate over r, without bound
divs = [1]
for p, e in factor(r - 1).items():
divs = [dd * p ** k for dd in divs for k in range(e + 1)]
seen = set()
for dlt in divs:
n = dlt + 1
while n <= nmax:
if n not in seen:
seen.add(n)
s *= norm_factor(F, ch2, n, r, b)
n = (n - 1) * r + 1
return s
def norm_factor(F, ch2, n, r, b):
if n == 2:
f = 1.0
for NR, ch in ch2:
if NR != 2:
continue
j = 0
while j < len(ch) and ft.fits(ch[j], r, r):
j += 1
assert j < len(ch)
f *= sum(2.0 ** (-b * k) for k in range(j + 1))
return f
if n % 2 == 0:
k = 0
while n % 2 == 0:
n //= 2
k += 1
if n != 1:
return 1.0
return math.prod(sum(NR ** (-b * t) for t in range(_depth(ch, r) + 1))
for NR, ch in ch2 if NR == 2 ** k)
if is_prime_mr(n):
p, NR = n, n
else:
q = math.isqrt(n)
if q * q != n or not is_prime_mr(q):
return 1.0
p, NR = q, n
if p == r:
return 1.0
k = F.kind(p)
if (k == "inert") != (NR == p * p):
return 1.0
cnt = 2 if k == "split" else 1
j = 1
while ft.fits(ft.lam_formula(F, p, j + 1), r, r):
j += 1
x = NR ** -b
return sum(x ** t for t in range(j + 1)) ** cnt
def _depth(ch, r):
j = 0
while j < len(ch) and ft.fits(ch[j], r, r):
j += 1
assert j < len(ch)
return j
def long_chain(F, jmax=80):
"""The brute chains over 2 (to norm 2^13), extended by lambda(j) =
2 lambda(j - e) past them (squaring U^j onto U^(j+e) for j > e)."""
out = []
for NR, ch in ft.chain2(F, 16):
e = 1 if F.kind(2) == "split" else 2
ch = list(ch)
while len(ch) < jmax:
ch.append(2 * ch[len(ch) - e])
out.append((NR, ch))
return out
def f2_point(D):
F = ft.Field(D)
ch2 = long_chain(F)
men = ft.menu(F, (2, 2), ch2)
b = ft.point(F, men)
return F, ch2, b, ft.sigma(men, b)
def section_r():
print("\n=== R: the reach, the columns at split r < 2*10^5")
Fi, ch2, bi, sfi = f2_point(-4)
Ls, a, m, N = lstar(Fi, ch2, bi)
print(f" Q(i): F2 point {bi:.6f}, sigma_F2 {sfi:.6f}, L* {Ls:.6f} "
f"(a={a} mod {N}, m={m})")
check("C2 Q(i): L* >= sigma_F2 at the F2 point", Ls >= sfi,
f"{Ls / sfi - 1:+.5f}")
guard()
out = {}
for D, cls, tag in ((-4, (5, 8), "best"), (-7, None, "best"),
(-7, (1, 8), "worse")):
F, ch2, b, sf = f2_point(D)
Lb, a, m, N = lstar(F, ch2, b)
ref = Lb
if cls is None:
ok = (lambda r: r % 4 == 3)
else:
ok = (lambda r, c=cls: r % c[1] == c[0])
rel, n, neg, big = [], 0, 0, []
for r in range(3, 2 * 10 ** 5):
if not is_prime_mr(r) or F.kind(r) != "split" or not ok(r):
continue
n += 1
v = column_sum(F, ch2, r, b) / ref - 1
rel.append((v, r))
neg += v < -1e-12
if r > m + 1:
big.append((v, r))
rel.sort()
lo = rel[0]
big.sort()
lob = big[0]
nbig = sum(v < -1e-12 for v, _ in big)
extra = ""
if tag == "worse":
L8 = lval(entrants(F, ch2, 8), b)
extra = f"; L(8)/L* - 1 = {L8 / ref - 1:.6f}"
out["L8"] = L8 / ref - 1
print(f" D={D} {tag} class {cls or '3 mod 4'}: {n} columns, "
f"{neg} below L*, least Sigma/L* - 1 = {lo[0]:.3e} at r={lo[1]}"
f" (r - 1 = {dict(factor(lo[1] - 1))}){extra}")
print(f" over r > m + 1 = {m + 1}: {nbig} of {len(big)} below "
f"L*, least "
f"{lob[0]:.3e} at r={lob[1]} (r - 1 = {dict(factor(lob[1] - 1))})")
out[(D, tag)] = (n, neg, lo[0])
p2 = (out[(-4, "best")][1] == 0 and out[(-4, "best")][2] < 1e-4
and out[(-7, "best")][1] == 0 and out[(-7, "best")][2] < 1e-4
and out[(-7, "worse")][2] >= out["L8"] - 1e-12 > 0.01)
print(f" P2 {'holds' if p2 else 'FAILS'}")
# ------------------------------- I: type (1, 0) with Q(i) inside K
def l5(x):
return -math.log1p(-x ** 5)
def h5(x):
return 2 * se.lf(x) - l5(x) + math.log(x)
def bound_at(d, n5):
"""(M(x_c), n5, x_c) at n5 places of norm 5, the others maximal."""
cnt = [n5] + se.counts(d)[1:]
xc = brentq(lambda x: se.lf(x) + se.wlog(x, cnt) + math.log(x),
1e-14, 0.5, xtol=1e-18, rtol=1e-15, maxiter=500)
return h5(xc) + n5 * math.log1p(xc ** A5), n5, xc
def bound_i(d):
"""min over n5 = 0..d of M(x_c) at the worst other counts."""
return min((bound_at(d, n5) for n5 in range(d + 1)),
key=lambda r: r[0])
def qi_law(d, plant=False, no5=False):
"""K in Q(i), d = 2m: odd places below Y. 3 gives d/2 of norm 9;
5, 17, 257, 65537 split completely (plant: residue degree m over
each prime of Z[i]); every other p = 1 mod 4 residue degree m over
each prime of Z[i], p = 3 mod 4 residue degree d."""
m = d // 2
W = [(math.log2(9), m, 1)]
for n in (5, 17, 257, 65537):
W.append((m * math.log2(n), 2, 0) if plant or (no5 and n == 5)
else (math.log2(n), d, 1))
for p in ss.INERT:
if p % 4 == 1:
W.append((m * math.log2(p), 2, 0))
else:
W.append((d * math.log2(p), 1, 0))
return ss.Law(d, W)
class QiLaw(tl.TypeLaw):
"""Type (1, 0) at 2, M = l - l5 - (w - w5) (old=True: typeloss's
M = l - l3 - w, for the instrument control)."""
def __init__(self, base, old=False):
super().__init__(1, 0, [], base)
self.old = old
def w5(self, x):
B = self.base
sel = (B.k == 1) & (np.abs(B.a - A5) < 1e-12)
return float((B.c[sel] * np.log1p(x ** B.a[sel])).sum())
def m(self, x):
if self.old:
return super().m(x)
return se.lf(x) - l5(x) - (self.w(x) - self.w5(x))
def dm(self, x):
if self.old:
return super().dm(x)
B = self.base
sel = (B.k == 1) & (np.abs(B.a - A5) > 1e-12)
aa = B.a[sel]
dw = float((B.c[sel] * aa * x ** (aa - 1) / (1 + x ** aa)).sum())
return 1 / (1 - x) - 5 * x ** 4 / (1 - x ** 5) - dw
def section_i(dmax=1000):
print("\n=== I: type (1, 0), K in Q(i), even d")
print("CONTROL C4: QiLaw with typeloss's sill and law")
for d in (4, 8):
a = QiLaw(ss.law(d, "E"), old=True).cert()
b = tl.extremal(1, 0, d, "E").cert()
dif = max(abs(u - v) for u, v in zip(a, b))
check(f"C4 d={d}: the certificate is typeloss's", dif < 1e-12,
f"{dif:.1e}, C {a[0]:+.6f}")
print("CONTROL C6: the new M against its products, its derivative "
"and bound_i")
law = qi_law(20)
q = QiLaw(law)
x = 0.3
b = -math.log2(x)
lnum = math.log(sum(x ** k for k in range(5))) + 20 * math.log1p(5 ** -b)
lden = sum(c * math.log1p(2 ** (-b * a)) for a, c, k in
zip(law.a, law.c, law.k) if k == 1)
e1 = abs(q.m(x) - (lnum - lden))
hh = 1e-6
e2 = abs(q.dm(x) - (q.m(x + hh) - q.m(x - hh)) / (2 * hh))
rest = se.counts(20)[1:]
e3 = 0.0
for n5 in (0, 20):
v, _, xc = bound_at(20, n5)
W = [(e, c, 1) for e, c in zip(se.EXPS, [n5] + rest) if c]
e3 = max(e3, abs(v - QiLaw(ss.Law(20, W, tail=False)).m(xc)))
check("C6 M = log(L_i/sigma_F2), M' its derivative, bound_i = M(x_c)",
e1 < 1e-12 and e2 < 1e-6 and e3 < 1e-12,
f"{e1:.1e}, {e2:.1e}, {e3:.1e}")
guard()
rows = {}
for d in range(4, dmax + 1, 2):
C, dm, xl, xc = QiLaw(qi_law(d)).cert()
rows[d] = [C, dm, xl, xc, None]
for d in range(4, min(dmax, 200) + 1, 2):
rows[d][4] = bound_i(d)
pos = [d for d in rows if rows[d][4] is not None and rows[d][4][0] > 0]
d_low = max(pos) if pos else None
neg_b = [d for d in rows if rows[d][4] is not None and rows[d][4][0] <= 0]
mono = all(d < min(neg_b) for d in pos) if neg_b else True
cert = [d for d in rows if rows[d][0] < 0 and rows[d][1] < 0
and rows[d][3] < 0.5]
d_high = min(cert) if cert else None
for d in sorted(rows):
C, dm, xl, xc, bd = rows[d]
if d <= 120 or d % 100 == 0:
bs = (f"bound {bd[0]:+.6f} (n5 {bd[1]}, x_c {bd[2]:.5f})"
if bd else "")
print(f" d={d:4d}: certificate {C:+.6f} (M' {dm:+.3f}, x_low "
f"{xl:.5f}, x_c {xc:.5f}) {bs}")
print(f" bound positive at every even d <= {d_low}, monotone: {mono}")
print(f" least even d with a certificate (C < 0, M' < 0, x_c < 1/2): "
f"{d_high}")
tail = d_high is not None and all(d in cert for d in rows if d >= d_high)
print(f" every even d from {d_high} to {dmax} certified: {tail}")
if d_high:
C = QiLaw(qi_law(d_high, plant=True)).cert()[0]
print(f" the frozen C5 law (5, 17, 257, 65537 of residue degree m) "
f"at d = {d_high}: certificate {C:+.6f}")
print(" ARM B (added after the run): 5 of residue degree m over each "
"prime of Z[i], n5 = 0, the bound's argmin")
certb = []
for d in range(4, dmax + 1, 2):
C, dm, xl, xc = QiLaw(qi_law(d, no5=True)).cert()
ok = C < 0 and dm < 0 and xc < 0.5
if ok:
certb.append(d)
if d <= 30 or d % 100 == 0:
bd = rows[d][4]
print(f" d={d:4d}: certificate B {C:+.6f} (M' {dm:+.3f}, x_low "
f"{xl:.5f}, x_c {xc:.5f})"
+ (f" bound {bd[0]:+.6f}" if bd else ""))
db = min(certb) if certb else None
clash = [d for d in pos if d in cert or d in certb]
check("C5 no certificate (arm A or B) is negative where the bound is "
"positive", not clash, f"bound positive at {min(pos)}..{max(pos)}")
tb = db is not None and all(d in certb for d in range(db, dmax + 1, 2))
print(f" ARM B: least certified even d {db}; every even d from it to "
f"{dmax} certified: {tb}; bound positive to {d_low}")
p3 = (d_low is not None and d_high is not None and 30 <= d_low <= 100
and 30 <= d_high <= 100 and tail)
print(f" P3 {'holds' if p3 else 'FAILS'}")
# ------------------------------- L: the loss from 930, a lemma
A9 = math.log2(9)
LY = 10 ** 5
LX0 = 1 / 7
LAM0 = math.log(7)
FERMAT = (17, 257, 65537)
def lemma_d0():
return math.ceil(LAM0 * 7 ** A9)
def lemma_coeffs(x, h=0.5):
"""(c_z, c_s): lz <= c_z lam + E and s/x <= c_s lam + E/x at x, the
norm-9 count h d (h = 1/2 at arm B, 1 at the plant)."""
b = -math.log2(x)
y = 9.0 ** -b
tail = (9 / LY) ** b * (1 + LY / (b - 1)) / (1 - LY ** -b)
cz = h / (1 - y) + sum((9 / n) ** b / (1 - n ** -b) for n in FERMAT) \
+ tail
stail = (18 / LY) ** b * (1 + LY / (b - 1)) / (1 - LY ** -b)
cs = h * x ** (A9 - 1) / (1 - y * y) \
+ sum((18 / n ** 2) ** b / (1 - n ** (-2 * b)) for n in FERMAT) \
+ stail
return cz, cs
def lemma_e(m, x, log10=False):
"""E + E/x, E <= 4 5^(-m b)(1 + 5/(m b - 1)), kept as an upper bound
(1e-300 where the float would underflow; log10=True: its exponent)."""
b = -math.log2(x)
lg = (math.log10(4) - m * b * math.log10(5)
+ math.log10(1 + 5 / (m * b - 1)) + math.log10(1 + 1 / x))
if log10:
return lg
return max(10.0 ** lg, 1e-300) if lg > -300 else 1e-300
def lemma(h=0.5, x=LX0):
"""The lemma's bounds at x: g_up, M and M' at x1, and the slope."""
lam = -math.log(x)
y = 9.0 ** (math.log2(x))
cz, cs = lemma_coeffs(x, h)
E = lemma_e(lemma_d0() // 2, x)
lx = -math.log1p(-x)
return dict(cz=cz, cs=cs, E=E, slope=1 - cz - cs,
G=lx - (1 - cz - cs) * lam + E,
M=lx - h * lam * (1 - y / 2),
Mp=1 / (1 - x) - A9 * h * lam / (x * (1 + y)))
def lemma_x1(d):
return brentq(lambda x: d * x ** A9 + math.log(x), 1e-12, 0.5,
xtol=1e-18, rtol=1e-15, maxiter=500)
def section_l():
print("\n=== L: arm B from 930, the lemma at x = 1/7")
D0 = lemma_d0()
L = lemma()
print(f" d0 = ceil(log 7 * 7^a9) = {D0} (log 7 * 7^a9 = "
f"{LAM0 * 7 ** A9:.4f})")
print(f" c_z {L['cz']:.6f}, c_s {L['cs']:.6f}, 1 - c_z - c_s "
f"{L['slope']:.6f}, E' <= {L['E']:.1e} (10^"
f"{lemma_e(D0 // 2, LX0, log10=True):.2f})")
print(f" g_up <= {L['G']:+.6f}; M <= {L['M']:+.6f}; M' <= "
f"{L['Mp']:+.4f}")
P = lemma(h=1.0)
check("C8 PLANT: d places of norm 9 (3 split completely) give g_up "
">= 0", P["G"] >= 0, f"c_z {P['cz']:.6f}, g_up <= {P['G']:+.6f}")
d = 1000
x = lemma_x1(d)
lam = -math.log(x)
lz, sw, w, lt = qi_law(d, no5=True).parts(x)
E = lemma_e(d // 2, x)
for tag, xx in (("1/7", LX0), ("x1", x)):
cz, cs = lemma_coeffs(xx)
check(f"C9 d = 1000, coefficients at {tag}: lz + lt <= c_z lam + "
f"E, (lz - sw + lt)/x <= c_s lam + E/x",
lz + lt <= cz * lam + E and (lz - sw + lt) / x <= cs * lam + E,
f"{lz + lt:.6f} <= {cz * lam:.6f}; {(lz - sw + lt) / x:.3e} "
f"<= {cs * lam:.3e}")
bad, worst = [], None
degs = range(D0 + D0 % 2, 1001, 2)
for d in degs:
q = QiLaw(qi_law(d, no5=True))
C, dm, xl, xc = q.cert()
x = lemma_x1(d)
ok = (x <= LX0 and x <= xl and C <= q.m(x) <= L["M"]
and q.g_up(x) <= L["G"] and q.dm(x) <= L["Mp"])
if not ok:
bad.append(d)
row = (q.m(x), q.g_up(x), q.dm(x), d, x, xl, C)
worst = row if worst is None or row[0] > worst[0] else worst
m, g, dmx, d, x, xl, C = worst
check(f"C7 at the {len(degs)} even d from {degs[0]} to 1000: x1 <= "
f"1/7, x1 <= x_low, C <= M(x1) <= M bound, g_up(x1) and M'(x1) "
f"below theirs", not bad, f"largest M(x1) {m:+.6f} at d = {d}, "
f"x1 {x:.6f}, x_low {xl:.6f}, C {C:+.6f}, g_up(x1) {g:+.6f}, "
f"M'(x1) {dmx:+.4f}")
guard()
p4 = 900 <= D0 <= 960
p5 = L["G"] <= -0.40 and L["M"] <= -0.80 and L["Mp"] <= -20
kill = (L["G"] >= 0 or L["M"] >= 0 or L["Mp"] >= 0 or D0 > 1000
or L["slope"] <= 0)
print(f" P4 {'holds' if p4 else 'FAILS'}; P5 {'holds' if p5 else 'FAILS'}")
print(f" KILL {'fires' if kill else 'missed'}: arm B loses at every "
f"even d >= {D0}")
def main():
t0 = time.time()
section_q()
section_r()
section_i()
section_l()
print(f"\n{sum(CHECKS)} of {len(CHECKS)} checks, "
f"{time.time() - t0:.1f} s")
return 0 if all(CHECKS) else 1
if __name__ == "__main__":
sys.exit(main())