#!/usr/bin/env python3
"""v610 -- QGEO.LANDSCAPE.01: the curve landscape round -- what else the
mu3-cover carries -- the
Jacobian splits into two new canonical CM objects, the point counts
confirm the splitting, and the integer-spectrum census honestly
relativizes single-spectrum hits (the anchor class is the most frequent
nontrivial family; the compiler distinction lives in the joint relations).

Round 13 of the QGEO cover program (after v609).  Executes the "does the
curve carry entirely other solutions?" survey:

  (L1) THE JACOBIAN SPLITS [E chars + C reading]: the three holomorphic
       differentials of C: y^3 = x^4 - 1 carry (deck, rotation) =
       (mu3, mu4) characters of combined orders (12, 12, 6):
       dx/y ~ (w^-1, i), dx/y^2 ~ (w, i), x dx/y^2 ~ (w, -1).  By CM
       theory this splits the Jacobian up to isogeny into an ABELIAN
       SURFACE with CM by Q(zeta_12) = Q(i, sqrt3) -- the field
       generated by the deck AND the mark rotation together -- times an
       ELLIPTIC CURVE with CM by Q(omega) (the quotient curve
       E: y^3 = u^2 - 1 under x -> -x).

  (L2) THE SPLITTING CONFIRMED BY POINT COUNTS [E]: for ALL tested
       primes p != 1 mod 12 (ten primes: 5,7,11,17,19,23,29,31,41,43)
       the Frobenius traces agree EXACTLY, a_p(C) = a_p(E) -- the
       zeta_12 surface is supersingular there (trace 0), as CM theory
       demands; for the four tested p = 1 mod 12 (13, 37, 61, 73) the
       surface contributes nonzero traces (-8, 4, -20, -32).

  (L3) THE OMEGA-CM PATTERN [E]: a_p(C) = 0 for every tested
       p = 2 mod 3 (inert in Q(omega)): the full Jacobian is
       supersingular there.

  (L4) THE INTEGER-SPECTRUM CENSUS [E + honest relativization]: in the
       declared degree <= 2 J-projector pool (a + b X + c Y, coeffs in
       {-2..2}/{-2..3}, 16 generators), integer characteristic
       polynomials are COMMON (thousands of entries), and the census
       shows: the ANCHOR CLASS chi = (x-1)^2(x-2) up to shift/negation
       is the MOST FREQUENT nontrivial family (286 entries), while
       non-compiler spectra also exist (e.g. {1,1,3} with 254 entries).
       Honest reading: single integer spectra are CHEAP on the curve --
       the compiler's distinction is the JOINT algebra structure
       (v600: rank 7, joint traces, saturation 81), not individual
       characteristic polynomials.  This retroactively confirms the
       correct typing of the v598/v599 char-level hits as candidates.

  (L5) NEW NAMED RESOURCES [C]: the zeta_12 CM surface and the omega CM
       elliptic curve are two canonical objects of the cover not yet
       used by the program; their periods are classical Gamma/Beta
       values -- the named resource for future RP/Hodge rounds.

All checks deterministic (exact sympy characters; integer point counts;
fixed-range census).  Verdict enums (frozen): LANDSCAPE-MAPPED (all),
LANDSCAPE-FAILS, MIXED.

FIREWALL: GATE.QGEO does not move; no marker changes; L1's isogeny
statement is typed [C] (standard CM theory, cited not re-proved); the
census relativization does not retract any promoted claim (v598/v599
hits were typed as candidates; the embedding claim v600 is joint-level).

PROVENANCE: discovery probe curve_landscape_probe.py (2026-08-01, 9/9,
verdict LANDSCAPE-MAPPED).
Python-only, counted per GATE.WOLFRAM.02.
"""

import itertools
from collections import Counter

import numpy as np
import sympy as sp

t = sp.symbols("t")
x = sp.symbols("x")
OMEGA = sp.Rational(-1, 2) + sp.sqrt(3) * sp.I / 2

CHECKS = []


def check(name, ok, detail=""):
    CHECKS.append((name, bool(ok)))
    print("[%s] %s%s" % ("PASS" if ok else "FAIL", name, (" -- " + detail) if detail else ""))


# ---------------------------------------------------------------- L1
print("=" * 72)
print("L1: the differential characters and the CM splitting")
print("=" * 72)

w3 = sp.exp(2 * sp.pi * sp.I / 3)
basis = {"dx/y": (0, 1), "dx/y^2": (0, 2), "x dx/y^2": (1, 2)}
orders = {}
for nm, (k, j) in basis.items():
    cs = sp.simplify(w3 ** (-j))          # deck y -> w y
    cr = sp.simplify(sp.I ** (k + 1))     # rotation x -> i x
    z = sp.simplify(cs * cr)
    for n in (1, 2, 3, 4, 6, 12):
        if sp.simplify(z ** n - 1) == 0:
            orders[nm] = n
            break
check("L1.1 combined character orders are (12, 12, 6) for (dx/y, dx/y^2, x dx/y^2)",
      orders == {"dx/y": 12, "dx/y^2": 12, "x dx/y^2": 6}, str(orders))
check("L1.2 [C] hence Jac(C) ~ A_2(CM Q(zeta_12)) x E(CM Q(omega)) up to isogeny "
      "(standard CM theory; the two order-12 characters are Galois-conjugate over "
      "the degree-4 field Q(zeta_12))", True)

# ---------------------------------------------------------------- L2 + L3
print("=" * 72)
print("L2/L3: point counts confirm the splitting")
print("=" * 72)


def count_C(p):
    cnt = 0
    for xv in range(p):
        rhs = (xv ** 4 - 1) % p
        for yv in range(p):
            if (yv * yv * yv - rhs) % p == 0:
                cnt += 1
    return cnt + 1


def count_E(p):
    cnt = 0
    for uv in range(p):
        rhs = (uv * uv - 1) % p
        for yv in range(p):
            if (yv * yv * yv - rhs) % p == 0:
                cnt += 1
    return cnt + 1


primes = [5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 61, 73]
aC = {p: p + 1 - count_C(p) for p in primes}
aE = {p: p + 1 - count_E(p) for p in primes}
not1mod12 = [p for p in primes if p % 12 != 1]
is1mod12 = [p for p in primes if p % 12 == 1]
check("L2.1 a_p(C) = a_p(E) EXACTLY for all %d tested primes p != 1 mod 12 "
      "(the zeta_12 surface is supersingular there)" % len(not1mod12),
      all(aC[p] == aE[p] for p in not1mod12))
check("L2.2 the surface contributes nonzero traces exactly at p = 1 mod 12: "
      "(13, 37, 61, 73) -> (-8, 4, -20, -32)",
      [aC[p] - aE[p] for p in is1mod12] == [-8, 4, -20, -32],
      str([aC[p] - aE[p] for p in is1mod12]))
p2mod3 = [p for p in primes if p % 3 == 2]
check("L3.1 a_p(C) = 0 for every tested p = 2 mod 3 (inert in Q(omega): fully "
      "supersingular)", all(aC[p] == 0 for p in p2mod3),
      "primes %s" % p2mod3)

# ---------------------------------------------------------------- L4
print("=" * 72)
print("L4: the integer-spectrum census (honest relativization)")
print("=" * 72)


def burau_gen(i, n=4):
    m = n - 1
    M = sp.eye(m)
    if i - 2 >= 0:
        M[i - 2, i - 1] = t
    M[i - 1, i - 1] = -t
    if i < m:
        M[i, i - 1] = 1
    return M


I3 = sp.eye(3)
S = [sp.simplify(burau_gen(i).subs({t: OMEGA})) for i in (1, 2, 3)]
r = sp.simplify(S[0] * S[1] * S[2])
T = [S[0]]
for _ in range(3):
    T.append(sp.simplify(r * T[-1] * r.inv()))
J = sp.Matrix([[0, 1 + sp.sqrt(3) * sp.I, -1 + sp.sqrt(3) * sp.I],
               [1 - sp.sqrt(3) * sp.I, 2, 1 + sp.sqrt(3) * sp.I],
               [-1 - sp.sqrt(3) * sp.I, 1 - sp.sqrt(3) * sp.I, 0]])
GJ = [sp.simplify((I3 - T[k]) * J.inv() * (I3 - T[k]).conjugate().T * J) for k in range(4)]
GJn = [np.array(sp.N(g).tolist(), dtype=complex) for g in GJ]
In = np.eye(3, dtype=complex)
pool = {}
for i in range(4):
    pool["P%d" % (i + 1)] = GJn[i]
    for j in range(4):
        if i != j:
            pool["P%d%d" % (i + 1, j + 1)] = GJn[i] @ GJn[j]
names = list(pool)
mats = [pool[n] for n in names]

census = Counter()
rng = [-2, -1, 1, 2]
for i in range(len(mats)):
    for j in range(i + 1, len(mats)):
        for b, c in itertools.product(rng, repeat=2):
            for a in range(-2, 4):
                Mx = a * In + b * mats[i] + c * mats[j]
                lam_ = np.linalg.eigvals(Mx)
                co = np.array([-lam_.sum(), lam_[0] * lam_[1] + lam_[0] * lam_[2]
                               + lam_[1] * lam_[2], -lam_.prod()])
                if np.max(np.abs(co.imag)) > 1e-8:
                    continue
                ints = np.round(co.real)
                if np.max(np.abs(co.real - ints)) > 1e-7:
                    continue
                if np.max(np.abs(ints)) > 12:
                    continue
                census[tuple(int(v) for v in ints)] += 1

anchor_key = (4, 5, 2)     # (x+1)^2(x+2): the anchor class representative (shift/negation)
n_anchor = census[anchor_key]
nontrivial = {k: v for k, v in census.items()
              if k not in [(0, 0, 0)]
              and not (k[1] == 0 and k[2] == 0)}   # drop rank-<=1-type trivials x^2(x-s)
maxcount = max(nontrivial.values())
check("L4.1 integer characteristic polynomials are COMMON in the declared pool "
      "(%d entries total): single spectra are cheap" % sum(census.values()),
      sum(census.values()) > 5000)
check("L4.2 the ANCHOR CLASS (chi = (x+1)^2(x+2), i.e. {1,1,2} up to negation) is "
      "the MOST FREQUENT nontrivial family (%d entries = the maximum)" % n_anchor,
      n_anchor == maxcount and n_anchor == 286, "max nontrivial count = %d" % maxcount)
check("L4.3 non-compiler spectra exist (e.g. {1,1,3} via chi = x^3-5x^2+7x-3: %d "
      "entries): the compiler's distinction is the JOINT structure (v600), not "
      "single spectra -- the v598/v599 char hits were correctly typed candidates"
      % census[(-5, 7, -3)], census[(-5, 7, -3)] >= 200)

# ---------------------------------------------------------------- L5
print("=" * 72)
print("L5: new named resources")
print("=" * 72)

check("L5.1 [C] two canonical objects named for future rounds: the zeta_12 CM "
      "surface (the field of deck AND marks together) and the omega CM elliptic "
      "curve E: y^3 = u^2 - 1; their periods are classical Beta values (the "
      "RP/Hodge period resource)", True)

# ---------------------------------------------------------------- summary
print("=" * 72)
n_pass = sum(1 for _, ok in CHECKS if ok)
print("%d/%d checks passed" % (n_pass, len(CHECKS)))
if n_pass == len(CHECKS):
    print("ALL CHECKS PASSED")
    print("VERDICT: LANDSCAPE-MAPPED -- the Jacobian splits into the zeta_12 CM")
    print("surface and the omega CM elliptic curve (point-count-confirmed); the")
    print("anchor class is the most frequent nontrivial integer family; single")
    print("spectra are cheap, the joint structure is the distinction.")
else:
    print("SOME CHECKS FAILED")


def run():
    """run_all.py entry point; the checks execute at import time above."""
    return len([1 for _, ok in CHECKS if not ok])


if __name__ == "__main__":
    raise SystemExit(1 if run() else 0)
