"""firstmove.py -- can a coprime grown world hide its FIRST MOVE at every temperature, when it cannot hide the route? QUESTION. quarantine.py proves that in a coprime grown world no two routes to one dated fiber tie at every beta, so no fiber is robust for the route. The coarser datum, the first move, is left open: a fiber meeting two first moves or more is FLAT FOR THE FIRST MOVE at beta when its first-move classes carry equal posterior mass there, and whether a coprime fiber is flat for it at every beta asks for an identity between SUMS of route weights, which the quarantine's collision of products does not reach. quarantine.py measured it: 0 of 120,386 fibers of at most eight routes. Is it a theorem? THE ARGUMENT (written before the engine). (A) INDEPENDENT VARIABLES. A route r of a fiber with endpoint N has posterior proportional to 1 / D_r, D_r the product of the normalizers Psi at the states r passes before its endpoint, the seed's included (quarantine.py's (A)). Write x_q = q^-beta for each prime q; n^-beta is the monomial prod x_q^(v_q(n)), distinct n giving distinct monomials, so a Dirichlet polynomial is a polynomial in the x_q with the same coefficients. Let S_c be the sum of 1 / D_r over the routes whose first move is c. Flat for the first move at every beta > 0 means S_a = S_b for every two first moves a, b met; clearing denominators, a Dirichlet polynomial vanishes on beta > 0, so all its coefficients vanish (sums of n^-beta over distinct n are linearly independent), and S_a = S_b holds as an identity of rational functions in the independent x_q: at every positive assignment, not only on the curve x_q = q^-beta. Every D_r holds the seed's Psi; dividing it out leaves D'_r, the product over the later states, and the identity S'_a = S'_b. (B) A SEPARATING PRIME. Coprime menus share no prime with their state, so every move after the first is prime to the first move a, and v_q(N) = v_q(a) at every prime q of a; likewise for b. So a and b are unitary divisors of N, and if they had the same primes they would be equal. Hence, a != b, some prime p divides one and not the other; name them so that p | a, p does not divide b. (C) THE CLASS OF a IS BLIND TO x_p. Every later state of a route opening with a is divisible by a, hence by p, and its coprime menu offers no multiple of p: every D'_r with r opening with a has x_p-degree 0, so S'_a does not move with x_p. (D) THE CLASS OF b DIES IN x_p. A route opening with b reaches N, divisible by p, so p divides a later move m_j, j >= 2, drawn from the menu at the state before it; that Psi holds the monomial of m_j with coefficient 1 and x_p-degree v_p(m_j) >= 1. Every coefficient is nonnegative, so with the other x_q held at positive values, D'_r -> infinity as x_p -> infinity, and S'_b -> 0, while S'_a stays at its positive value. So S'_a != S'_b as functions, the cleared Dirichlet polynomial is nonzero, and it has finitely many real zeros (no more than its sign changes, Laguerre's extension of Descartes' rule). THEOREM (to be ruled). In a coprime grown world, menus a function of the route so far, no fiber meeting two first moves or more is flat for the first move at every beta; it is flat at finitely many beta at most. It holds on any set of routes of one age to one endpoint, so no state map refining (state, age) cuts such a fiber into blocks each spread and flat for the first move at every beta. A hypothesis is the load: the depth column, menu {2, 3} at every state, recycles the first move's primes and hides the first move at every beta on the dated fiber (2^k 3^k, 2k) (forget.py's count leak, zero when the two exponents agree). (E) WHAT THE PROOF USES. Steps (B) and (C) read only that every menu after the first move avoids the first move's primes; (D) reads nothing of the menus. So the theorem holds in a FIRST-COPRIME world, each later menu prime to the first move and free to recycle the others, where the route itself can tie: menu(a) = {b, c} and menu(a, b) = menu(a, c) = {b, c} put a,b,c and a,c,b in one fiber with one D. The first move is quarantined by a weaker hypothesis than the route. THE CHECK. The proof is the verifier; the script reads its two steps on the populations quarantine.py scans, with no cap on the routes: for every fiber meeting two first moves or more and every pair (a, b) of them, it looks for a separating prime p (B), takes the x_p-degree of every D'_r (the largest v_p over its support) in the class blind to p (C, every degree 0) and in the other (D, every degree at least 1), and counts the pairs where a step fails. POPULATIONS, as quarantine.py's arms, same seeds and walk order: COPRIME-STATE and COPRIME-HISTORY (moves US, ages 2 and 3, 3000 worlds each, seeds 0 and 1), their large forms (moves UL, ages 2 to 4, 1000 each, seeds 4 and 5), and the exhaustive arm (87,885 tables on the moves 2 to 6, ages 2 and 3). CONTROLS, read first: the depth column's dated fiber (36, 4) is flat for the first move at every beta (quarantine.first_move_robust) and its step (C) fails; quarantine.py's last-move world's fiber (30, 3) fails step (C); the LAST-HISTORY and FREE-STATE arms (seeds 2, 3) fail a step at some pair. A step check that never fails off coprimality reads nothing. THE BOUNDARY ARM, FIRST-COPRIME: moves US, menus keyed by the route so far, each later menu prime to the first move only, sizes 1 to 2, ages 2 and 3, 3000 worlds, seed 6; its route ties are counted as quarantine.ties counts them. POPULATION CHECK: the fibers of at most eight routes meeting two first moves or more number 120,386 over the five coprime arms, as quarantine.py prints, or the populations differ. PREDICTIONS (frozen before the engine). (P1) Every control fails as stated; the depth column's (36, 4) is flat for the first move. (P2) The population check reads 120,386. (P3) Over the five coprime arms, every pair has a separating prime, and steps (C) and (D) hold at every pair: 0 failures. (P4) The FIRST-COPRIME arm: 0 failures, and route ties above 0. KILL: the script prints a failure count above 0 over the five coprime arms (P3). A failure there is a coprime fiber the argument misreads: the theorem is wrong as stated until that fiber is read by hand. A failure on FIRST-COPRIME alone kills (E), not the theorem. FINDINGS. (P1) held: the depth column's (36, 4) is flat for the first move and fails step C, the last-move world's (30, 3) fails step C, and the LAST-HISTORY and FREE-STATE arms fail a step at 194 of 476 and 336 of 383 pairs (C at 156 and 263, B at 38 and 73). (P2) held: 120386 capped fibers. Every fiber read held at most eight routes (fibers = capped in every arm), so the uncapped read adds no fiber to quarantine.py's population. (P3) held, the kill missed: 0 failing of 145744 pairs over 120386 fibers of the five coprime arms. (P4) held: FIRST-COPRIME, 0 failing of 369 pairs, 86 route ties: a world prime to its first move only ties routes and still keeps the argument's steps at every pair read. The step counts read the generators more than the mathematics: D failed at no pair of any arm, controls included, holding by construction (a route reaching N must take p somewhere), and on the coprime and FIRST-COPRIME arms C holds by construction too, their menus drawn prime to the state or the first move; P3's 0 reads that the arms are what they say. The conclusion is read directly by quarantine.first_move_robust (exact formal Dirichlet sums), added after the run when the steps were seen to be fixed by construction: 0 of 120386 coprime fibers (quarantine.py's own read, repeated) and 0 of 369 FIRST-COPRIME fibers (new) flat for the first move at every beta, while the counter fires off coprimality (LAST-HISTORY 1, FREE-STATE 2) and on the depth column's control. The verifier is the argument, (A)..(E), by hand. RUN RECORD. python firstmove.py: 8 of 8 checks, 1.2 s, peak commit 9.1 MB; with the two CONCLUSION checks added after it, 10 of 10, 6.3 s, peak 12.7 MB. """ import random import sys import time from collections import defaultdict from math import gcd import quarantine as Q CHECKS = [] def check(name, ok, detail=""): CHECKS.append(bool(ok)) print(f" [{'PASS' if ok else 'FAIL'}] {name}" + (f": {detail}" if detail else "")) def primes(n): out, q = [], 2 while q * q <= n: if n % q == 0: out.append(q) while n % q == 0: n //= q q += 1 return out + ([n] if n > 1 else []) def vp(n, p): k = 0 while n % p == 0: n //= p k += 1 return k def degree(menus, p): """x_p-degree of the product of the Psi of these menus: each Psi's degree is its menu's largest v_p, coefficients being nonnegative.""" return sum(max(vp(m, p) for m in mu) for mu in menus) def steps(items): """Per pair of first moves of one fiber: the steps that fail. Returns (pairs read, Counter of failing steps, failing pairs).""" classes = defaultdict(list) for r, ms in items: classes[r[0]].append(ms[1:]) firsts = sorted(classes) pairs = bad = 0 fails = defaultdict(int) for i, a in enumerate(firsts): for b in firsts[i + 1:]: pairs += 1 seps = [(p, a, b) for p in primes(a) if b % p] + \ [(p, b, a) for p in primes(b) if a % p] got = set() if not seps: got.add("B") for p, blind, other in seps: if any(degree(ms, p) > 0 for ms in classes[blind]): got.add("C") if any(degree(ms, p) == 0 for ms in classes[other]): got.add("D") for g in got: fails[g] += 1 bad += bool(got) return pairs, fails, bad def read(menus, ages, tally_ties=False): t = defaultdict(int) for menu in menus: t["worlds"] += 1 for age in ages: for items in Q.fibers(menu, age).values(): if len({r[0] for r, _ in items}) < 2: continue t["fibers"] += 1 if len(items) <= 8: t["capped"] += 1 pairs, fails, bad = steps(items) t["pairs"] += pairs t["failing pairs"] += bad for g, c in fails.items(): t["step " + g] += c if tally_ties: w, f = Q.ties(items) t["route ties"] += w + f t["first move flat"] += Q.first_move_robust(items) if tally_ties: for items in Q.fibers(menu, age).values(): if len(items) >= 2 and \ len({r[0] for r, _ in items}) < 2: w, f = Q.ties(items) t["route ties"] += w + f return dict(t) def first_only(m, n, prefix): return not prefix or gcd(m, prefix[0]) == 1 def main(): t0 = time.time() print("CONTROLS") depth = Q.fibers(lambda p, n: (2, 3), 4)[36] check("depth column (36, 4) flat for the first move at every beta", Q.first_move_robust(depth)) _, f, bad = steps(depth) check("depth column (36, 4) fails step C", f.get("C", 0) > 0, dict(f)) last = Q.fibers(Q.LAST, 3)[30] _, f, bad = steps(last) check("last-move world (30, 3) fails step C", f.get("C", 0) > 0, dict(f)) arms = [("COPRIME-STATE", Q.US, Q.coprime, "state", (1, 2), (2, 3), 3000), ("COPRIME-HISTORY", Q.US, Q.coprime, "prefix", (1, 2), (2, 3), 3000), ("LAST-HISTORY", Q.US, Q.last_move, "prefix", (1, 2), (2, 3), 3000), ("FREE-STATE", Q.US, Q.free, "state", (1, 2), (2, 3), 3000), ("COPRIME-STATE large", Q.UL, Q.coprime, "state", (1, 3), (2, 3, 4), 1000), ("COPRIME-HISTORY large", Q.UL, Q.coprime, "prefix", (1, 3), (2, 3, 4), 1000), ("FIRST-COPRIME", Q.US, first_only, "prefix", (1, 2), (2, 3), 3000)] out = {} for seed, (name, uni, allowed, keyed, sizes, ages, count) in \ enumerate(arms): rng = random.Random(seed) menus = (Q.random_world(rng, uni, allowed, keyed, sizes) for _ in range(count)) out[name] = read(menus, ages, tally_ties=name == "FIRST-COPRIME") print(f" {name}: {out[name]}") for name in ("LAST-HISTORY", "FREE-STATE"): check(f"{name} fails a step at some pair", out[name].get("failing pairs", 0) > 0) out["EXHAUSTIVE"] = read(Q.exhaustive_worlds(), (2, 3)) print(f" EXHAUSTIVE: {out['EXHAUSTIVE']}") co = ("COPRIME-STATE", "COPRIME-HISTORY", "COPRIME-STATE large", "COPRIME-HISTORY large", "EXHAUSTIVE") capped = sum(out[n].get("capped", 0) for n in co) check("POPULATION: capped fibers over the five coprime arms 120,386", capped == 120386, f"{capped}") fibers = sum(out[n].get("fibers", 0) for n in co) pairs = sum(out[n].get("pairs", 0) for n in co) fails = sum(out[n].get("failing pairs", 0) for n in co) print(f" the five coprime arms: {fibers} fibers meeting two first " f"moves or more, {pairs} pairs, {fails} failing") check("P3 KILL not fired: 0 failing pairs over the coprime arms", fails == 0 and pairs > 0, f"{fails} of {pairs}") fc = out["FIRST-COPRIME"] flat = sum(out[n].get("first move flat", 0) for n in co) check("CONCLUSION: no fiber of the coprime arms flat for the first " "move at every beta", flat == 0, f"{flat} of {fibers}") check("CONCLUSION: no FIRST-COPRIME fiber flat for the first move", out["FIRST-COPRIME"].get("first move flat", 0) == 0, f"{out['FIRST-COPRIME'].get('first move flat', 0)} of " f"{out['FIRST-COPRIME'].get('fibers', 0)}") check("P4 FIRST-COPRIME: 0 failing pairs, route ties above 0", fc.get("failing pairs", 0) == 0 and fc.get("pairs", 0) > 0 and fc.get("route ties", 0) > 0, f"{fc.get('failing pairs', 0)} of {fc.get('pairs', 0)} pairs, " f"{fc.get('route ties', 0)} route ties") wall = time.time() - t0 print(f"{sum(CHECKS)}/{len(CHECKS)} checks passed, {wall:.1f} s") sys.exit(0 if all(CHECKS) else 1) if __name__ == "__main__": main()