"""memory.py -- what a grown world can know of its own genesis: the evidence a state, a dated state, a watched path and a probe each carry about the generator that grew it, fate by fate. QUESTION. thermal.py grows a state Z/N by a Boltzmann choice: from N an admissible m is picked with probability m^(-beta) / Psi_N(beta), Psi_N(beta) the sum of m^(-beta) over the admissible m, beta > 1. The GENERATOR of a world is its demand and its beta, with the seed 1 unless stated. An observer inside the world is handed less than the outside view: the STATE N (its ring's isomorphism class), the DATED STATE (N and the move count tau), the PATH (the moves as they happened), or a PROBE (it may ask whether a proposed move is admissible). What does each view carry about the generator, and about the ROUTE (the order in which the moves came, given the state)? Does the answer depend on the fate the demand grows? THE OBJECT. The demands: independence (m coprime to N), dynamics (lambda(Nm) > lambda(N)), semisimplicity (Nm squarefree), and new idempotents (m has a prime factor not dividing N). A(N) is the admissible set and Psi_N(beta) the sum of m^(-beta) over it. For independence Psi_N = zeta(beta) prod_{p | N} (1 - p^(-beta)) - 1; for dynamics Psi_N = zeta(beta) - sigma_beta(xi), xi = W(lambda(N)) / N the headroom (thermal.py). The INDEPENDENCE world is the one independence grows, its limit the zeta measure (G_p independent geometric of ratio p^(-beta)); the CRYSTAL is its beta = infinity limit, every G_p = 1. The DEPTH world is the column 3^t that greedy dynamics grows from seed 1. A ONE-WINDOW world has the menu {3^a : a >= 1} at every state. THE ARGUMENT (written before the engine). (1) THE ROUTE-WEIGHT CANCELLATION. A history from seed s to N is an ordered factorization N/s = m_1 ... m_tau into admissible moves; its probability is prod m_i^(-beta) / Psi_{N_(i-1)} = (N/s)^(-beta) prod 1/Psi_{N_(i-1)}. The numerator is the same for every history, so given the state the posterior over histories is proportional to prod 1/Psi over the states the history passed through: every piece of route information sits in the normalizers, in what the intermediate worlds could have done, never in what they did. This holds for any demand and makes every posterior exact. (2) THE BOUNDED-EVIDENCE LAW. A squarefree world read on the primes p <= y has likelihood 1 under the crystal and prod (1 - p^(-beta)) under the zeta measure, so the ratio for the crystal is prod (1 - p^(-beta))^(-1), increasing in y to zeta(beta): the whole infinite world gives odds zeta(beta):1 for cold genesis and no more, while one column of depth >= 2 refutes it outright. (As written before the run; that is, a world not squarefree refutes the crystal outright.) Cold genesis is falsifiable and never confirmable beyond zeta(beta):1 against a given beta. (3) THE FINITE THERMOMETER. The profile's temperature information is the Fisher information of independent geometrics, I_p = (log p)^2 r / (1 - r)^2 with r = p^(-beta), and the sum over p converges for beta > 1: any unbiased estimate of beta read off the completed profile has sd >= I_total^(-1/2) forever. The score of a squarefree profile is sum_p log p r/(1 - r) > 0 at every beta, so its likelihood rises toward 1 as beta grows, with no finite maximizer, and its maximum likelihood reading is the crystal: the share of worlds that read as crystals is the squarefree share, 1/zeta(beta), exactly. (4) THE PEELABLE PASTS. Greedy independence picks the least prime not dividing the state. So (s, tau) reaches N iff N/s is the product of a set Q of tau primes, each with v_p(N) = 1, such that every prime below a member of Q divides N. Call a prime p PEELABLE in N when v_p(N) = 1 and every prime below p divides N; the pasts of N at zero temperature are the subsets of its peelable primes, 2^j of them, j the peelable count. Seed and history are separable from inside only by the seed-1 convention. (5) THE COLUMN'S NORMALIZER. lambda(3^a) = 2 3^(a-1), and the primes p with p - 1 | 2 3^(a-1) are 2, 3 and the primes 2 3^j + 1, j = 1..a-1, so xi_a = W(lambda(3^a)) / 3^a = 8 prod {2 3^j + 1 prime, 1 <= j <= a - 1}, and Psi_(3^a) = zeta - sigma_beta(xi_a) is non-increasing in a, to Psi_col = zeta - sigma_beta(xi_infinity). (6) THE UNBOUNDED-MEMORY LAW. From seed 1 every move 3^k from 3^a is admissible, and the histories to 3^t are the subsets of the depths 1..t-1, so by (1) the probability that a thermal dynamics world passes through 3^t is f(t) = 3^(-beta t) / Psi_1 prod_{a < t} (1 + 1/Psi_(3^a)). The greedy world passes through 3^t surely, so the log-odds for cold genesis given 3^t is -log f(t), with slope beta log 3 - log(1 + 1/Psi_col) per deepening. The slope is positive for every beta > 1: 3, 5 and 6 never divide xi, so Psi_col >= 3^(-b) + 5^(-b) + 6^(-b), and 5^(-b) >= 9^(-b) / (1 - 3^(-b)) because (9/5)^b (1 - 3^(-b)) is 1.2 at b = 1 and increasing, so Psi_col > 1/(3^b - 1), which is 3^b > 1 + 1/Psi_col. Evidence grows linearly in depth where independence's is capped. (7) THE COLUMN READS ITS PRIME. For C coprime to p, lambda(C p^e) = lcm(L_0, p^(e-1)) with L_0 = lcm(lambda(C), p - 1) (odd p), so the ratio lambda(C p^(e+1)) / lambda(C p^e) is p exactly for e >= e_0 = v_p(L_0) + 1 and not at e_0 - 1; at p = 2, e_0 = max(3, v_2(lambda(C)) + 2). The limit of Z/(C p^e), Z/C x Z_p, carries |.|_p on its deep factor, v_p(x) read off x mod p^e whenever v < e, while the crystal's limit prod_l F_l has only finite fields as factors, on which every absolute value is trivial (x^(l-1) = 1 for x != 0). (8) THE WITNESS FAMILY. P_N(m) = m^(-beta) / Psi_N is an exponential family in beta with statistic -log m, so a watched move carries Fisher information Var_N(log m) and d/dbeta E_N[log m] = -Var_N(log m): the rate at which a state's expected log-step falls as beta rises is the watch's per-move information. The dated state is a function of the path, so the chain rule for Fisher information gives I_path = I_dated + E[I_route], the last term the information of the route posterior given the dated state, which by (1) is carried by the normalizers alone. THE WITNESS GAP is that term. Along the cold path N = p_k#, independence's menu sums close: with f = zeta(beta) prod_(p <= p_k) (1 - p^-beta) and g = log f, S0 = f - 1, S1 = -f g', S2 = f (g'' + g'^2), so Var_N(log m) = f (g''(f - 1) - g'^2)/(f - 1)^2, cumulative in k. (9) THE COLD BLINDNESS. Let q be the least prime not dividing N. Every m in A(N) under independence or new idempotents has a prime factor not dividing N, so m >= q, and q itself is admissible; under semisimplicity from squarefree N the same holds. All three greedy picks are q, so from a squarefree seed the three demands write one world forever and no watcher learns which. For N > 1 with least prime p | N, the probe q^2 is refused only by semisimplicity and pq is admitted only by new idempotents: two probes read the whole law. THE DISCRIMINATION RATE: for nested admissible sets A_n in A_w, KL(P_n || P_w) = log(Psi_w / Psi_n) exactly, which as beta grows is asymptotic to (m*/q)^(-beta), m* the least move in A_w not in A_n, so -log KL grows with slope log(m*/q). (As written before the run; below, the subscripts n and w are written narrow and wide.) (10) THE FOSSIL PARADOX. In a one-window world every state has the same normalizer, so by (1) the route posterior given the dated state 3^t, tau is uniform over the compositions of t into tau parts and free of beta: the dated state is sufficient, the witness gap is zero, I_dated = I_path = tau (log 3)^2 r / (1 - r)^2 with r = 3^(-beta), and the route's entropy given the dated state is the largest any law on those compositions allows. Zero menu drift makes the dated state a perfect generator fossil and gives a maximally unreadable past at once. The chain rule J(G; path) = J(G; dated) + J(G; path | dated) holds for any prior on the generator G, since the dated state is a function of the path; in a world whose menu drifts the last term is positive and the route posterior is skewed below uniform. DESIGN. Standard library and mpmath; one process. growth.py supplies its prime list, value, factor, merge_add, v2, lcm, lambda (on a factorization and on an integer) and the wall. C POSITIVE CONTROLS, before any verdict. C1 the Euler-Maclaurin sums of n^(-s) (log n)^k, k = 0, 1, 2, against zeta(2) = pi^2/6, zeta(4) = pi^4/90, zeta'(2) = -0.93754825431584 and mpmath's zeta''(2). C2 lambda(M) against the largest element order of (Z/M)^x at every M <= 300. C3 the independence normalizer's closed form against brute sums to 30,000 with the tail bracketed, at N = 1, 6, 30, 210, beta 1.5, 2, 3. R R1a the histories to p_n#, n <= 5, counted against the ordered set partitions. R1b every history to every N <= 360 under independence and dynamics, its probability the product of m^(-beta)/Psi over its moves, Psi in closed form (C3 reads independence's against brute sums, D2 the column's closed form at N = 3^a, a = 1..6, which D1 ties to dynamics' headroom), summed against the forward visit probability: a control of the history enumeration, both sides reading one Psi; the cancellation is the proof's. B the independence world. B1 the likelihood ratio at the cutoff 2 10^5 against zeta(beta) inside the Euler tail's bracket, at beta 1.5, 2, 3. B2 I_total over primes to 2 10^6 plus the integral bound on the tail, and the Cramer-Rao floor. B4 the peelable count against the brute pasts of every N <= 2000, pasts found by running greedy independence from every seed s <= 2000. D the depth world. D1 xi_a against W(lambda(3^a)) / 3^a, a = 1..9. D2 Psi_(3^a) against brute admissible sums to 30,000 with lambda computed per m, a = 1..6, beta 1.5, 2, 3. D3 f(t) against the enumerated histories, t <= 8. D4 the slope at beta 1.25, 1.5, 2, 3, 6 from Psi_col bracketed between Psi_(3^a) at large a and the tail of xi's product; the term test's inequality on the same grid. D5 the lambda ratio over A in {1, 2, 5, 7, 11, 13, 21, 30, 77, 120, 385, 1001}, q in {2, 3, 5, 7, 13} coprime to A, e = 1..10, against e_0. D6 the route coins: the entropy of the enumerated route posterior given 3^t, t <= 8, against the sum over a < t of h(1/(1 + Psi_(3^a))), h the binary entropy; beta_c, the root of Psi_col = 1, bisected at both ends of D4's bracket. W the watch. W1 the exponential family on truncated menus: the derivative of log Psi against -E[log m] and of E[log m] against -Var(log m) by central differences, 12 (state, demand) pairs. W2 the witness gap on the truncated world (menu 2..12, seed 1, age 4, a world with an empty menu frozen): I_path, I_dated and E[I_route] computed exactly, independence and dynamics, beta 1.5, 2, 3, I_path from the paths' squared scores against the sum of the per-move Var along them; the split itself is the law of total variance over one path list, argued, not checked. W3 the depth watcher: Var(log m) under the column's limit law at beta = 2, a print, not a check. W4, before W5, the cold path's control: the closed form of (8) at k = 3 and 50 against direct sums over m < 2 10^6 with least prime factor above p_k, plus the density prod (1 - 1/p) times the integral tail, agreeing to 1e-3 (added before the first run: the neglected tail moves Var by about 1e-2 at k = 50). W5 the cold path's Var at every 3 <= k <= 10^5, beta 2: its least and greatest. Kill: the old record's four values missed by 1e-3, or any k below 0.8. Added after the first run: W5 widened to 1 <= k and computed from mpmath's zeta(2), zeta'(2), zeta''(2) at 40 digits; em no longer feeds the cold path, and C1 checks it at zeta(2) and both derivatives, before C, B, D and W3 use it. P the probe. P1 the three greedy picks at every N <= 10^5 (new idempotents and independence) and every squarefree N <= 3000 (all three), against the least prime not dividing N; T = 0 trajectories of 25 moves from seeds 1, 30, 105. P2 the probe rows at every squarefree 1 < N <= 3000. P3 KL by its definition on menus to 10^5 at N = 30, beta 9 and 10, and the slope of -log KL between them against log(m*/q); KL = log(Psi_wide / Psi_narrow) is algebra. F the fossil. F1 the one-window world at tau <= 4, beta 1.5, 2, 3: I_dated, from the law of t summed over t < 600, against tau I_1, which is I_path, the moves being independent; that every composition is equiprobable is (10)'s algebra. F2 the views on the truncated world with the generator uniform over beta in {1.5, 2, 3}, age uniform over 1..4: J(G; state) < J(G; dated) < J(G; path) for independence and dynamics; the chain rule is algebra. F3 the residual route entropy H(route | dated, G) against its uniform maximum, the one-window world (menu {3, 9}) and independence. PREDICTIONS, fixed before the run. C C1 within 1e-12; C2 agreement everywhere; C3 inside the bracket. R every history agrees to 1e-12. B B1 monotone, zeta(2) = 1.6449 reached inside the bracket, log zeta(2) = 0.4977 nats; p <= 10 carrying about 94% of the log-odds at beta = 2. B2 I_total(2) inside [0.8844, 0.8859] (the replaced record's bracket), sd floor 1.06. B3 positive everywhere (argued, not run). B4 zero disagreements; N = 210 has 16 pasts. D D1 zero disagreements. D2 Psi_1(2) = 0.394934 and Psi_3(2) = 0.316809 (the replaced record's figures). D3 to 1e-12. D4 slope(2) = 0.6936, slope(6) = 0.0619; the term test holds at each of the five beta; the log-odds at depth 1 above log zeta(beta) at each. D5 zero disagreements, the tightness at e_0 - 1 included. D6 to 1e-12; beta_c inside (1.49, 1.50), the replaced record's 1.49595. W W1 to 1e-6. W2 the identity to 1e-12 in every cell; one cell reproduces the replaced record's 0.649817 = 0.446763 + 0.203054. W3 1.2430. W4 0.91336 against 0.91336 (k = 3), 0.81292 against 0.81288 (k = 50). W5 (as read at the widening) 0.9474, 0.9153, 0.9134, 0.8129, 0.8668, 0.8907 at k = 1, 2, 3, 50, 5000, 10^5, the old record's four (k = 3, 50, 5000, 10^5) matched; least 0.8055 at k = 30 (p_k = 113), greatest 0.9474 at k = 1 (predicted least near 0.81 at k near 50: missed). Its first form took zeta(2) and its derivatives from em, whose zeta(2) C prints 5.6e-15 off; divided by f - 1 near k = 10^5 that error printed 0.8908 there, where the 40-digit value is 0.89074, just under the rounding boundary; the brute control reaches only k = 50. P P1, P2 zero disagreements. P3 the identity to 1e-12 (argued, not run); slopes within 0.05 of log 2 (independence against new idempotents) and log 7 (semisimplicity against independence). F F1 uniform to 1e-12, the three informations equal to 1e-12 (F1 runs I_dated against tau I_1 alone). F2 both ladders strict, the replaced record's rows 0.0628 < 0.0758 (independence) and 0.0693 < 0.0726 (dynamics); the identity to 1e-12 (argued, not run). F3 the one-window world at its maximum to 1e-12, 0.3183 bits; independence strictly below its maximum. A KILL is any exact disagreement in C, R, B1, B4, D1-D3, D5, D6, W1, W2, P1, P2, F1 or the F3 one-window equality; a slope in D4 at or below zero; a term test failing; a P3 slope off its band. A control out of its band voids the verdicts that lean on it. A replaced record's figure not reproduced, with the identities green, is a definition to read, not a kill. FINDINGS. 27/27 checks PASS and no kill (D4c, depth 1 against independence's whole ceiling log zeta(beta), was a print gated into a check after the predictions froze and sits outside the KILL list, though its failure fails the run); one check was written stronger than its argument and was narrowed to it, recorded below. The splits of W2 and F2, F1's equiprobability, P3's closed form, B1's monotonicity and the squarefree score's sign hold by algebra: argued, not checked. C zeta(2) off by 5.6e-15, zeta(4) by 5.6e-14, zeta'(2) by 3.9e-15, zeta''(2) by 1.4e-14; lambda equals the largest unit order at every M <= 300; the independence normalizer inside its bracket at 4 states x 3 betas. R the histories to p_n# number 1, 3, 13, 75, 541, the ordered set partitions; every history sum equals the forward visit probability at every N <= 360 under both demands, worst 1.1e-16. B the odds for the crystal rise to zeta: 2.6124, 1.6449, 1.2021 (0.9603, 0.4977, 0.1840 nats) at beta 1.5, 2, 3, the primes p <= 10 carrying 83.2%, 93.8%, 99.0% of the log-odds; the crystal share 1/zeta is 0.3828, 0.6079, 0.8319. I_total lies in [0.88447, 0.88459] at beta 2 (sd floor 1.063), [0.17228, 0.17228] at 3, and [3.83162, 4.22270] at 1.5, where the integral tail bound is loose. The zero-temperature pasts equal 2^(peelable count) at every N <= 2000; the most is 16, at 210. D xi_a = 8, 56, 1064, 1064, 173432, 84461384, 123229159256 (three times) for a = 1..9, equal to W(lambda(3^a))/3^a; Psi_1(2) = 0.394934, Psi_3(2) = 0.316809; f(t) against the enumerated histories to 4.3e-16 relative. Psi_col = 2.7266876, 0.9870668, 0.2858929, 0.0559803, 0.0014615 at beta 1.25, 1.5, 2, 3, 6, the bracket closed to the printed digits; the slope 1.0608, 0.9482, 0.6936, 0.3586, 0.0619 nats per deepening; depth 1 alone gives 2.5285, 1.8781, 1.2682, 0.7326, 0.2251 against independence's whole ceiling 1.5250, 0.9603, 0.4977, 0.1840, 0.0172. The term test holds at each of the five beta. The lambda ratio is q from e_0 on in all 417 cells read (e >= e_0 - 1), and not q at e_0 - 1 wherever e_0 >= 2. NARROWED: the check as first written asked that the ratio differ from q at EVERY e < e_0, which the argument never claimed, and it failed at one cell, A = 1, q = 2, e = 1, where lambda(2) = 1 and lambda(4) = 2 already give the ratio 2 before lambda(4) = lambda(8) = 2 stalls it; e_0 is where the ratio becomes q for good, not where it is first q. D6: the route entropy given 3^t equals the depth coins' sum to 2.2e-16 at t = 2..8 and beta 1.5, 2, 3; beta_c = 1.495950 at both ends of the bracket. W the two exponential-family identities to 6.2e-9 and 5.0e-9 by central differences. The witness gap at age 4, I_path against the summed Var to 1.4e-15: independence (648 paths, 26 end states) 0.798016 = 0.599353 + 0.198663, 0.649817 = 0.446763 + 0.203054, 0.370647 = 0.212363 + 0.158284 at beta 1.5, 2, 3; dynamics (4166 paths, 310 end states) 0.810389 = 0.763430 + 0.046959, 0.733136 = 0.682622 + 0.050514, 0.501002 = 0.466505 + 0.034497. The replaced record's figure is independence at beta 2. The depth watcher's per-move information under the column's limit law at beta 2 is 1.2430. A watcher of the cold path p_k# gains between 0.8055 and 0.9474 per move at beta 2 at every 1 <= k <= 10^5 (rule in range): within two moves more than the Fisher bound B2 brackets for a completed state. P the three greedy picks are the least prime not dividing N at every N <= 10^5 and at all 1824 squarefree N <= 3000, and the 25-move trajectories from 1, 30 and 105 coincide; the probe rows are as argued at every squarefree 1 < N <= 3000. At N = 30, q = 7, m* = 14 for independence inside new idempotents (slope 0.7023 against log 2 = 0.6931) and m* = 49 for semisimplicity inside independence (slope 1.9380 against log 7 = 1.9459). F the one-window world's I_dated = tau I_1 to 4.4e-16, I_1 = 0.35618, 0.16973, 0.04821. The ladders, generator uniform over beta in {1.5, 2, 3}, age over 1..4: independence 0.0489 < 0.0628 < 0.0758, dynamics 0.0512 < 0.0693 < 0.0726, the one-window world 0.0144 < 0.0388 = 0.0388. The residual route entropy: one-window 0.3183 of 0.3183 bits, dynamics 1.1754 of 1.2492, independence 1.5414 of 2.0900. Tiers: (1), (2), (4), (5), (6) and (9) are theorems, the closed forms verified in the ranges printed; (3) is a theorem, the convergence proved and the value bracketed; (7) is a theorem, its absolute-value half a property; (8) is a theorem, the split proved, the gap's values and its strict ladder on the truncated world observations; (10) is a theorem for the one-window world, the gap and the route entropy values computed on the truncated world observations. RUN RECORD. python memory.py: 27/27 checks, 6.2 s (the cold path's 40-digit sum and brute control about 4 s of it), peak commit 44.6 MB under a 512 MB ceiling (read by an external guard, not printed here). """ import math import os import sys import time from math import gcd, log sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import growth # noqa: E402 import mpmath # noqa: E402 CHECKS = [] BETAS = (1.5, 2.0, 3.0) def check(name, ok, detail=""): CHECKS.append(bool(ok)) print(f" {'PASS' if ok else 'FAIL'} {name}" + (f" [{detail}]" if detail else "")) def section(title): print() print(title) # --------------------------------------------------------- the sums _EM = {} def em(s, k): """sum over n >= 1 of n^(-s) (log n)^k, k = 0, 1, 2: direct to N - 1, then the integral, f(N)/2 and -f'(N)/12.""" key = (s, k) if key in _EM: return _EM[key] N = 10000 tot = 0.0 for n in range(2 if k else 1, N): tot += n ** -s * log(n) ** k L = log(N) a = s - 1 integral = N ** -a * [1 / a, L / a + 1 / a ** 2, L * L / a + 2 * L / a ** 2 + 2 / a ** 3][k] f = N ** -s * L ** k fp = N ** (-s - 1) * ((k * L ** (k - 1) if k else 0) - s * L ** k) _EM[key] = tot + integral + f / 2 - fp / 12 return _EM[key] def zeta(s): return em(s, 0) def sigma(n, beta): """sum of d^(-beta) over the divisors d of n.""" out = 1.0 for p, e in growth.factor(n).items(): out *= sum(p ** (-beta * i) for i in range(e + 1)) return out def divisors(n): ds = [1] for p, e in growth.factor(n).items(): ds = [d * p ** i for d in ds for i in range(e + 1)] return ds def is_prime(n): """Miller-Rabin with the first 13 prime bases: exact below 3.3 10^24.""" if n < 2: return False small = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41) for p in small: if n % p == 0: return n == p d, r = n - 1, 0 while d % 2 == 0: d //= 2 r += 1 for a in small: x = pow(a, d, n) if x in (1, n - 1): continue for _ in range(r - 1): x = x * x % n if x == n - 1: break else: return False return True def sieve(n): s = bytearray([1]) * (n + 1) s[0] = s[1] = 0 for i in range(2, int(n ** 0.5) + 1): if s[i]: s[i * i::i] = bytearray(len(s[i * i::i])) return s def lam(N): return growth.lam_int(N) def lam_f(f): return growth.value(growth.lam(f)) # ------------------------------------------------------- the demands def strips_to_one(m, N): """Every prime of m divides N.""" g = gcd(m, N) while g > 1: while m % g == 0: m //= g g = gcd(m, N) return m == 1 def squarefree(n): return all(e == 1 for e in growth.factor(n).values()) def adm(demand, N, m, lamN=None): if demand == "ind": return gcd(m, N) == 1 if demand == "mem": return not strips_to_one(m, N) if demand == "semi": return squarefree(N * m) if demand == "dyn": L = lam(N) if lamN is None else lamN return lam(N * m) != L if demand == "col": return m in (3, 9) raise ValueError(demand) def z_ind(N, beta): out = zeta(beta) for p in growth.factor(N) if N > 1 else (): out *= 1 - p ** -beta return out - 1 def xi_of(N): return growth.wall(lam(N)) // N def z_dyn(N, beta): return zeta(beta) - sigma(xi_of(N), beta) Z = {"ind": z_ind, "dyn": z_dyn} # --------------------------------------------------------- C controls def section_c(): section("C positive controls") e2 = abs(zeta(2.0) - math.pi ** 2 / 6) e4 = abs(zeta(4.0) - math.pi ** 4 / 90) ed = abs(-em(2.0, 1) - (-0.93754825431584)) edd = abs(em(2.0, 2) - float(mpmath.zeta(2, 1, 2))) print(f" zeta(2) off by {e2:.1e}, zeta(4) by {e4:.1e}, " f"zeta'(2) by {ed:.1e}, zeta''(2) by {edd:.1e}") check("C1 Euler-Maclaurin sums, k = 0, 1, 2, within 1e-12", max(e2, e4, ed, edd) < 1e-12) bad = 0 for M in range(2, 301): best = 1 for a in range(1, M): if gcd(a, M) != 1: continue x, o = a % M, 1 while x != 1 % M: x = x * a % M o += 1 best = max(best, o) bad += best != lam(M) check("C2 lambda equals the largest unit order, M <= 300", bad == 0, f"{bad} disagreements") X = 30000 worst = 0.0 ok = True for N in (1, 6, 30, 210): for b in BETAS: brute = sum(m ** -b for m in range(2, X + 1) if gcd(m, N) == 1) tail = X ** (1 - b) / (b - 1) cf = z_ind(N, b) ok &= brute - 1e-12 <= cf <= brute + tail + 1e-12 worst = max(worst, cf - brute) check("C3 independence normalizer inside the brute bracket", ok, f"largest tail used {worst:.2e}") # ----------------------------------------------------- R the routes def histories(demand, N, s=1): """Every ordered factorization of N/s into moves admissible along the way, as lists of (state, move).""" out = [] def go(M, acc): if M == N: out.append(list(acc)) return for m in divisors(N // M): if m >= 2 and adm(demand, M, m): acc.append((M, m)) go(M * m, acc) acc.pop() go(s, []) return out def section_r(): section("R the route-weight cancellation") fub = [] for n in range(1, 6): P = growth.value({p: 1 for p in growth.PRIMES[:n]}) fub.append(len(histories("ind", P))) print(f" histories to p_n#, n = 1..5: {fub}") check("R1a the histories to p_n# are the ordered set partitions", fub == [1, 3, 13, 75, 541]) worst = 0.0 for demand in ("ind", "dyn"): for b in BETAS: zc = {} def zz(M): if M not in zc: zc[M] = Z[demand](M, b) return zc[M] visit = {1: 1.0} for N in range(2, 361): v = 0.0 for M in divisors(N): if M < N and M in visit and adm(demand, M, N // M): v += visit[M] * (N // M) ** -b / zz(M) if v: visit[N] = v direct = sum(math.prod(m ** -b / zz(M) for M, m in h) for h in histories(demand, N)) worst = max(worst, abs(direct - v)) check("R1b every history sum equals the forward visit probability, " "N <= 360, both demands", worst < 1e-12, f"worst {worst:.1e}") # ---------------------------------------------- B the independence world def section_b(big): section("B the independence world") X = 200000 primes = [p for p in range(2, X + 1) if big[p]] ok_br = True for b in BETAS: acc = 1.0 for p in primes: acc /= 1 - p ** -b if p == 7: upto10 = acc z = zeta(b) ok_br &= z * (1 - X ** (1 - b) / (b - 1)) <= acc <= z print(f" beta {b}: odds for the crystal -> zeta = {z:.4f} " f"({log(z):.4f} nats); primes to 2 10^5 give {acc:.6f}; " f"p <= 10 carries {log(upto10) / log(z):.1%} of the " f"log-odds; crystal share 1/zeta = {1 / z:.4f}") check("B1 the likelihood ratio at 2 10^5 inside the Euler tail's " "bracket below zeta", ok_br) Y = len(big) - 1 i2 = None for b in BETAS: tot = 0.0 for p in range(2, Y + 1): if big[p]: r = p ** -b tot += log(p) ** 2 * r / (1 - r) ** 2 L, a = log(Y), b - 1 tail = Y ** -a * (L * L / a + 2 * L / a ** 2 + 2 / a ** 3) tail /= (1 - Y ** -b) ** 2 print(f" beta {b}: I_total in [{tot:.5f}, {tot + tail:.5f}], " f"sd floor >= {(tot + tail) ** -0.5:.3f}") if b == 2.0: i2 = (tot, tot + tail) check("B2 I_total(2) inside the frozen bracket [0.8844, 0.8859]", 0.8844 <= i2[0] and i2[1] <= 0.8859) LIM = 2000 pasts = [0] * (LIM + 1) for s in range(1, LIM + 1): N = s while N <= LIM: pasts[N] += 1 N *= next(p for p in growth.PRIMES if N % p) bad = 0 for N in range(1, LIM + 1): f = growth.factor(N) if N > 1 else {} peel = sum(1 for p, e in f.items() if e == 1 and all(N % r == 0 for r in growth.PRIMES if r < p)) bad += pasts[N] != 2 ** peel print(f" pasts(210) = {pasts[210]}, the most pasts to 2000: " f"{max(pasts)} at N = {pasts.index(max(pasts))}") check("B4 the zero-temperature pasts are the peelable subsets, " "N <= 2000", bad == 0 and pasts[210] == 16, f"{bad} off") # ---------------------------------------------------- D the depth world def sigma_col(a, beta): """sigma_beta(xi_a), xi_a = 8 prod(2 3^j + 1 prime, j < a).""" out = sum(2 ** (-beta * i) for i in range(4)) for j in range(1, a): p = 2 * 3 ** j + 1 if is_prime(p): out *= 1 + p ** -beta return out def xi_col(a): x = 8 for j in range(1, a): if is_prime(2 * 3 ** j + 1): x *= 2 * 3 ** j + 1 return x def z_col(a, beta): return zeta(beta) - sigma_col(a, beta) def z_col_bracket(beta, a=40): grow = math.exp((2 * 3 ** a) ** -beta / (1 - 3 ** -beta)) return zeta(beta) - sigma_col(a, beta) * grow, z_col(a, beta) def section_d(): section("D the depth world") bad = sum(xi_col(a) != xi_of(3 ** a) for a in range(1, 10)) print(f" xi_a, a = 1..9: {[xi_col(a) for a in range(1, 10)]}") check("D1 xi_a = 8 prod(2 3^j + 1 prime) equals W(lambda(3^a))/3^a", bad == 0) X = 30000 ok = True for a in range(1, 7): L = lam(3 ** a) good = [m for m in range(2, X + 1) if lam_f(growth.merge_add({3: a}, growth.factor(m))) != L] for b in BETAS: brute = sum(m ** -b for m in good) cf = z_col(a, b) ok &= brute - 1e-12 <= cf <= brute + X ** (1 - b) / (b - 1) print(f" Psi_1(2) = {z_dyn(1, 2.0):.6f}, Psi_3(2) = {z_dyn(3, 2.0):.6f}") check("D2 the column's normalizer inside the brute bracket, a <= 6", ok) worst = 0.0 for b in BETAS: for t in range(1, 9): f = 3 ** (-b * t) / z_dyn(1, b) for a in range(1, t): f *= 1 + 1 / z_col(a, b) enum = sum(math.prod(m ** -b / z_dyn(M, b) for M, m in h) for h in histories("dyn", 3 ** t)) worst = max(worst, abs(f - enum) / enum) check("D3 the visit probability f(t) against the enumerated " "histories, t <= 8", worst < 1e-12, f"relative {worst:.1e}") ok_slope, ok_test, ok_one = True, True, True for b in (1.25, 1.5, 2.0, 3.0, 6.0): lo, hi = z_col_bracket(b) s_lo = b * log(3) - log(1 + 1 / lo) s_hi = b * log(3) - log(1 + 1 / hi) one = b * log(3) + log(z_dyn(1, b)) print(f" beta {b}: Psi_col in [{lo:.7f}, {hi:.7f}], slope in " f"[{s_lo:.4f}, {s_hi:.4f}] nats per deepening; depth 1 " f"gives {one:.4f} against independence's ceiling " f"{log(zeta(b)):.4f}") ok_slope &= s_lo > 0 ok_test &= 3 ** -b + 5 ** -b + 6 ** -b > 1 / (3 ** b - 1) ok_one &= one > log(zeta(b)) check("D4a the slope is positive at the five beta", ok_slope) check("D4b the three-term test holds at the five beta", ok_test) check("D4c depth 1 out-earns independence's whole ceiling, five beta", ok_one) bad = n = 0 early = [] for A in (1, 2, 5, 7, 11, 13, 21, 30, 77, 120, 385, 1001): fA = growth.factor(A) if A > 1 else {} lA = lam(A) for q in (2, 3, 5, 7, 13): if A % q == 0: continue if q == 2: e0 = max(3, growth.v2(lA) + 2) else: L0, v = growth.lcm(lA, q - 1), 0 while L0 % q == 0: L0 //= q v += 1 e0 = v + 1 for e in range(1, 11): l1 = lam_f(growth.merge_add(fA, {q: e})) l2 = lam_f(growth.merge_add(fA, {q: e + 1})) if e >= e0 - 1: n += 1 bad += (l2 == q * l1) != (e >= e0) elif l2 == q * l1: early.append((A, q, e)) check("D5 the lambda ratio is q from e_0 on and not at e_0 - 1", bad == 0, f"{n} cells, {bad} off") print(f" ratio q already below e_0 - 1 at (A, q, e) = {early}") def h(x): return -(x * log(x) + (1 - x) * log(1 - x)) worst = 0.0 for b in BETAS: for t in range(2, 9): ws = [math.prod(m ** -b / z_dyn(M, b) for M, m in hs) for hs in histories("dyn", 3 ** t)] tot = sum(ws) enum = -sum(w / tot * log(w / tot) for w in ws) coins = sum(h(1 / (1 + z_col(a, b))) for a in range(1, t)) worst = max(worst, abs(enum - coins)) def root(side): lo, hi = 1.3, 1.7 for _ in range(60): mid = (lo + hi) / 2 lo, hi = (mid, hi) if z_col_bracket(mid)[side] > 1 else (lo, mid) return lo b_lo, b_hi = root(0), root(1) check("D6 the route entropy is the sum of the depth coins, t <= 8; " "beta_c in (1.49, 1.50)", worst < 1e-12 and 1.49 < b_lo <= b_hi < 1.50, f"worst {worst:.1e}; beta_c in [{b_lo:.6f}, {b_hi:.6f}]") # ---------------------------------------------- the truncated world def paths(demand, beta, tau, top=12): """Every path of tau moves from seed 1 on the menu 2..top, as (moves, end state, probability, score, sum of per-move variances). A state with an empty menu is frozen: the move 1, probability 1.""" menus = {} def menu(N): if N not in menus: ms = [m for m in range(2, top + 1) if adm(demand, N, m)] if not ms: menus[N] = None else: w = [m ** -beta for m in ms] z = sum(w) el = sum(wi * log(m) for wi, m in zip(w, ms)) / z v = sum(wi * log(m) ** 2 for wi, m in zip(w, ms)) / z - el ** 2 menus[N] = (ms, [wi / z for wi in w], el, v) return menus[N] out = [] def go(N, moves, pr, sc, vs): if len(moves) == tau: out.append((tuple(moves), N, pr, sc, vs)) return mu = menu(N) if mu is None: go(N, moves + [1], pr, sc, vs) return ms, ps, el, v = mu for m, p in zip(ms, ps): go(N * m, moves + [m], pr * p, sc - log(m) + el, vs + v) go(1, [], 1.0, 0.0, 0.0) return out def fisher_split(ps): """I_path, I_dated and E[I_route] of one fixed-age path list.""" i_path = sum(p * s * s for _, _, p, s, _ in ps) i_var = sum(p * v for _, _, p, _, v in ps) byN = {} for _, N, p, s, _ in ps: a = byN.setdefault(N, [0.0, 0.0]) a[0] += p a[1] += p * s i_dated = sum(d * d / P for P, d in byN.values()) i_route = sum(p * (s - byN[N][1] / byN[N][0]) ** 2 for _, N, p, s, _ in ps) return i_path, i_var, i_dated, i_route, len(ps), len(byN) # ---------------------------------------------------------- W the watch def section_w(big=None): section("W the watch") worst1 = worst2 = 0.0 h = 1e-4 for demand in ("ind", "dyn"): for N in (1, 6, 7, 12, 30, 360): ms = [m for m in range(2, 1001) if adm(demand, N, m)] for b in (1.5, 2.5): def lz(x): return log(sum(m ** -x for m in ms)) def el(x): return (sum(m ** -x * log(m) for m in ms) / sum(m ** -x for m in ms)) def var(x): z = sum(m ** -x for m in ms) return (sum(m ** -x * log(m) ** 2 for m in ms) / z - el(x) ** 2) d1 = (lz(b + h) - lz(b - h)) / (2 * h) d2 = (el(b + h) - el(b - h)) / (2 * h) worst1 = max(worst1, abs(d1 + el(b))) worst2 = max(worst2, abs(d2 + var(b))) check("W1 dlogZ/dbeta = -E[log m] and dE[log m]/dbeta = -Var(log m)", max(worst1, worst2) < 1e-6, f"worst {worst1:.1e}, {worst2:.1e}") worst = 0.0 hit = False for demand in ("ind", "dyn"): for b in BETAS: ip, iv, idt, ir, npth, nend = fisher_split(paths(demand, b, 4)) worst = max(worst, abs(ip - iv)) hit |= abs(ip - 0.649817) < 5e-7 and abs(idt - 0.446763) < 5e-7 print(f" {demand} beta {b}: I_path {ip:.6f} = I_dated " f"{idt:.6f} + E[I_route] {ir:.6f} ({npth} paths, " f"{nend} end states)") check("W2 the witness gap's I_path = the summed per-move Var", worst < 1e-12, f"worst {worst:.1e}") print(f" the replaced record's 0.649817 = 0.446763 + 0.203054 " f"reproduced in some cell: {hit}") b = 2.0 primes = [2] for j in range(1, 25): if is_prime(2 * 3 ** j + 1): primes.append(2 * 3 ** j + 1) ds = [1] for p in primes: e = 3 if p == 2 else 1 ds = [d * p ** i for d in ds for i in range(e + 1)] s0 = zeta(b) - sum(d ** -b for d in ds) s1 = em(b, 1) - sum(d ** -b * log(d) for d in ds if d > 1) s2 = em(b, 2) - sum(d ** -b * log(d) ** 2 for d in ds if d > 1) vcol = s2 / s0 - (s1 / s0) ** 2 print(f" the depth watcher: Var(log m) under the column's limit law " f"at beta 2 = {vcol:.4f}") if big is not None: cold_watch(big) def cold_var(big, K, b=2): """Var_N(log m) on the independence menu at N = p_k#, k = 1..K, at beta = b: f = zeta(b) prod (1 - p^-b), g = log f, S0 = f - 1, S1 = -f g', S2 = f (g'' + g'^2), Var = f (g''(f - 1) - g'^2)/(f - 1)^2. The zeta values are mpmath's at 40 digits: an error in zeta(2) is divided by f - 1, which falls toward 5e-8 by k = 10^5, so em's zeta(2), off by the 5.6e-15 that C prints, moved Var's fourth digit there.""" mp = mpmath.mp mp.dps = 40 z0 = mpmath.zeta(b) z1, z2 = mpmath.zeta(b, 1, 1), mpmath.zeta(b, 1, 2) lf, g1, g2 = mpmath.log(z0), z1 / z0, z2 / z0 - (z1 / z0) ** 2 out, k, p = {}, 0, 1 while k < K: p += 1 if not big[p]: continue k += 1 t = mpmath.mpf(p) ** -b lp = mpmath.log(p) lf += mpmath.log1p(-t) g1 += lp * t / (1 - t) g2 -= lp ** 2 * t / (1 - t) ** 2 f1 = mpmath.expm1(lf) out[k] = (p, float((1 + f1) * (g2 * f1 - g1 * g1) / (f1 * f1))) return out def cold_brute(big, k, X=2000000): """The same Var at beta 2 by direct sums over 2 <= m < X with least prime factor above p_k, plus the density times the integral tail, whose closed forms are beta 2's.""" b = 2.0 ps = [p for p in range(2, X) if big[p]][:k] keep = bytearray([1]) * X keep[0] = keep[1] = 0 for p in ps: keep[p::p] = bytearray(len(keep[p::p])) s0 = s1 = s2 = 0.0 for m in range(2, X): if keep[m]: w, L = m ** -b, log(m) s0 += w s1 += w * L s2 += w * L * L d = math.prod(1 - 1 / p for p in ps) L = log(X) s0 += d / X s1 += d * (L + 1) / X s2 += d * (L * L + 2 * L + 2) / X return s2 / s0 - (s1 / s0) ** 2 def cold_watch(big): cv = cold_var(big, 100000) br = {k: cold_brute(big, k) for k in (3, 50)} ok = all(abs(cv[k][1] - br[k]) < 1e-3 for k in br) check("W4 control, before W5: the cold path's closed form against " "brute sums at k = 3, 50", ok, ", ".join(f"k {k}: {cv[k][1]:.5f} vs {br[k]:.5f}" for k in br)) print(" cold path p_k#, beta 2, Var_N(log m): " + ", ".join(f"k {k} {cv[k][1]:.5f}" for k in (1, 2, 3, 50, 5000, 100000))) lo = min(range(1, 100001), key=lambda k: cv[k][1]) hi = max(range(1, 100001), key=lambda k: cv[k][1]) print(f" over 1 <= k <= 10^5: least {cv[lo][1]:.4f} at k = {lo} " f"(p_k = {cv[lo][0]}), greatest {cv[hi][1]:.4f} at k = {hi}") old = {3: 0.9134, 50: 0.8129, 5000: 0.8668, 100000: 0.8907} check("W5 the cold path's watch stays between 0.8 and 1 at every " "1 <= k <= 10^5, the old record's four within 1e-3", 0.8 <= cv[lo][1] and cv[hi][1] < 1 and all(abs(cv[k][1] - v) < 1e-3 for k, v in old.items()), f"{cv[lo][1]:.4f} .. {cv[hi][1]:.4f}") # ---------------------------------------------------------- P the probe def least_prime_not_dividing(N): return next(p for p in growth.PRIMES if N % p) def section_p(): section("P the probe") bad = 0 for N in range(1, 100001): q = least_prime_not_dividing(N) mi = next(m for m in range(2, q + 1) if gcd(m, N) == 1) mm = next(m for m in range(2, q + 1) if not strips_to_one(m, N)) bad += mi != q or mm != q sq = [N for N in range(1, 3001) if N == 1 or squarefree(N)] for N in sq: q = least_prime_not_dividing(N) ms = next(m for m in range(2, q + 1) if squarefree(N * m)) bad += ms != q print(f" {len(sq)} squarefree states checked for semisimplicity") def greedy(demand, N): m = 2 while not adm(demand, N, m): m += 1 return m same = True for seed in (1, 30, 105): runs = [] for demand in ("semi", "ind", "mem"): N, seq = seed, [] for _ in range(25): m = greedy(demand, N) seq.append(m) N *= m runs.append(seq) same &= runs[0] == runs[1] == runs[2] check("P1 the three greedy picks are the least prime not dividing N; " "three demands, one world", bad == 0 and same, f"{bad} off; trajectories identical: {same}") bad = 0 for N in sq[1:]: q = least_prime_not_dividing(N) p = min(growth.factor(N)) rows = [(adm(d, N, q * q), adm(d, N, p * q)) for d in ("semi", "ind", "mem")] bad += rows != [(False, False), (True, False), (True, True)] check("P2 the probes q^2 and pq read the whole law at every " "squarefree 1 < N <= 3000", bad == 0, f"{bad} off") N, X = 30, 100000 A = {d: [m for m in range(2, X + 1) if adm(d, N, m)] for d in ("semi", "ind", "mem")} ok = True for narrow, wide in (("ind", "mem"), ("semi", "ind")): mstar = min(set(A[wide]) - set(A[narrow])) q = min(A[narrow]) kls = {} for b in (9, 10): zn = sum(m ** -b for m in A[narrow]) zw = sum(m ** -b for m in A[wide]) kls[b] = sum(m ** -b / zn * (log(m ** -b / zn) - log(m ** -b / zw)) for m in A[narrow]) slope = log(kls[9]) - log(kls[10]) print(f" {narrow} inside {wide} at N = 30: q = {q}, m* = {mstar}; " f"slope of -log KL between beta 9 and 10 = {slope:.4f} " f"against log(m*/q) = {log(mstar / q):.4f}") ok &= abs(slope - log(mstar / q)) < 0.05 check("P3 the slope of -log KL within 0.05 of log(m*/q), both pairs", ok) # --------------------------------------------------------- F the fossil def section_f(): section("F the fossil") worst = 0.0 for b in BETAS: r = 3 ** -b i1 = log(3) ** 2 * r / (1 - r) ** 2 for tau in range(1, 5): info = 0.0 for t in range(tau, 600): P = math.comb(t - 1, tau - 1) * r ** (t - tau) * (1 - r) ** tau dlog = -(t - tau) * log(3) + tau * log(3) * r / (1 - r) info += P * dlog * dlog worst = max(worst, abs(info - tau * i1)) print(f" beta {b}: I_1 = {i1:.5f}; I_dated = tau I_1, " f"I_path's value") check("F1 the one-window world: I_dated from the law of t = tau I_1", worst < 1e-12, f"worst {worst:.1e}") H = log(3) rows = {} for demand in ("ind", "dyn", "col"): joint = [] for b in BETAS: for tau in range(1, 5): for mv, N, p, _, _ in paths(demand, b, tau): joint.append((b, tau, mv, N, p / 12)) def cond_h(key): agg, tot = {}, {} for g, tau, mv, N, p in joint: k = key(tau, mv, N) agg.setdefault(k, {}).setdefault(g, 0.0) agg[k][g] += p tot[k] = tot.get(k, 0.0) + p return -sum(pg * log(pg / tot[k]) for k, d in agg.items() for pg in d.values() if pg > 0) j_state = H - cond_h(lambda tau, mv, N: N) j_dated = H - cond_h(lambda tau, mv, N: (N, tau)) j_path = H - cond_h(lambda tau, mv, N: mv) pgd = {} for g, tau, mv, N, p in joint: pgd[(g, (N, tau))] = pgd.get((g, (N, tau)), 0.0) + p hr = hmax = 0.0 for (g, d), pg_d in pgd.items(): sub = [p for gg, tau, mv, N, p in joint if gg == g and (N, tau) == d] hr -= sum(p * log2(p / pg_d) for p in sub) hmax += pg_d * log2(len(sub)) rows[demand] = (j_state, j_dated, j_path, hr, hmax) print(f" {demand}: J(G; state) {j_state:.4f}, J(G; dated) " f"{j_dated:.4f}, J(G; path) {j_path:.4f}; route entropy " f"given the dated state and G {hr:.4f} bits of a uniform " f"maximum {hmax:.4f}") ok = all(rows[d][0] < rows[d][1] < rows[d][2] for d in ("ind", "dyn")) check("F2 the view ladder is strict for independence and dynamics", ok) c = rows["col"] check("F3 the one-window world: zero information gap, route entropy " "at its maximum", abs(c[2] - c[1]) < 1e-12 and abs(c[3] - c[4]) < 1e-12, f"{c[3]:.4f} of {c[4]:.4f} bits") i = rows["ind"] check("F3 independence: route entropy strictly below its maximum", i[3] < i[4] - 1e-9, f"{i[3]:.4f} of {i[4]:.4f} bits") def log2(x): return log(x) / log(2) def main(): t0 = time.time() big = sieve(2000000) section_c() section_r() section_b(big) section_d() section_w(big) section_p() section_f() print() print(f"{sum(CHECKS)}/{len(CHECKS)} checks passed, " f"{time.time() - t0:.1f} s") raise SystemExit(0 if all(CHECKS) else 1) if __name__ == "__main__": main()