9.3. Numerical Values and Empirical Verification
Table 9. Generalised Euler product : paper formula (10) vs. corrected formula (11) vs. empirical mean of over primes in . The corrected formula agrees to within ; the paper formula deviates by –.
Figure 8.
Correction of Conjecture 12.1. (A) (log scale) for . Red circles: paper formula (incorrect for ); blue squares: corrected formula; green triangles: empirical mean. (B) Local factor at : linear growth (paper) vs. exponential growth (exact). [CORRECTED] [NEW] [COMP. VERIF.].
Figure 8.
Correction of Conjecture 12.1. (A) (log scale) for . Red circles: paper formula (incorrect for ); blue squares: corrected formula; green triangles: empirical mean. (B) Local factor at : linear growth (paper) vs. exponential growth (exact). [CORRECTED] [NEW] [COMP. VERIF.].
Figure 9.
Generalised Euler product (log scale) with percentage deviations of the paper formula. The corrected formula and the empirical mean are indistinguishable at this scale. [CORRECTED] [COMP. VERIF.].
Figure 9.
Generalised Euler product (log scale) with percentage deviations of the paper formula. The corrected formula and the empirical mean are indistinguishable at this scale. [CORRECTED] [COMP. VERIF.].
Figure 10.
Exponential growth of and Generalised Amplification family . (A) Blue dots: verified values ; red dashed: exponential fit confirming (Theorem 9.2). (B) Amplification constants for classical Goldbach (proved, ), shifted primes (proved, ), Mirror and Anchor-3 primes (conditionally proved, ). [NEW].
Figure 10.
Exponential growth of and Generalised Amplification family . (A) Blue dots: verified values ; red dashed: exponential fit confirming (Theorem 9.2). (B) Amplification constants for classical Goldbach (proved, ), shifted primes (proved, ), Mirror and Anchor-3 primes (conditionally proved, ). [NEW].
10. Amplification Constants for Mirror and Anchor-3 Primes
10.1. Definitions
Definition 10.1 (Prime taxonomy). A prime is:
10.2. Analytic Computation
Proposition 10.2 (Amplification constants).
[COND. PROVED, Thm. 2.4 analogue] [NEW] To leading order in the Dirichlet-density expansion,
The equalityis a non-obvious prediction.
Proof sketch. By Theorem 2.4 applied to Mirror and Anchor-3 subsequences, equals the Cesàro mean of over . Both Mirror primes () and Anchor-3 primes () satisfy , hence for all in either class. Therefore the dominant factor at contributes 1 (instead of for the unrestricted shifted-prime case). For , the Dirichlet densities are identical for both subsequences by the Chinese Remainder Theorem. Thus to leading order.
Figure 11.
Schematic of the Generalised Amplification family . Solid bars: proved values. Hatched bars: conditionally proved (Proposition 10.2). [NEW].
Figure 11.
Schematic of the Generalised Amplification family . Solid bars: proved values. Hatched bars: conditionally proved (Proposition 10.2). [NEW].
10.3. Empirical Class Ratios
Figure 12 shows the mean
normalised by
, by prime class and range. The ratios
and
are stable across three prime ranges in
, [COMP. VERIF.].
11. The Generalised Amplification Conjecture
Conjecture 11.1 (Generalised Spectral Amplification). [NEW] [CONJECTURE] Let be defined by an arithmetic restriction (e.g., primality of , membership in a fixed congruence class, or simultaneous primality conditions). Define . Then there exists a constant , given by an Euler product over primes reflecting the Dirichlet-density profile of , such that the explicit formula for has residue coefficients at each non-trivial zero . In particular, the ratio of Mellin -scores between and the unrestricted Goldbach sum converges to .
Table 10. Known and conjectural members of the spectral amplification family. Hatched entries indicate conditionally proved values.
Theorem 11.2 (GAC for Mirror primes). [COND. PROVED, RH + HL-B] [NEW] Conjecture 11.1 holds for with , conditional on: (i) the Riemann Hypothesis, (ii) Hardy–Littlewood Conjecture B, and (iii) the Cesàro convergence (an open analogue of Theorem 2.4 for Mirror primes).
Proof sketch. The three analytic gaps (Lemmas 3.1-3.3) each extend to as follows. Gap 1 applies Bombieri–Vinogradov to the progression (the Mirror-prime congruence), yielding main term . Gap 2 is inherited since remains uniformly bounded. Gap 3 follows because inherits the pole structure of with residues scaled by . Given condition (iii), the explicit formula takes the form of Theorem 3.4 with replaced by .
Remark 11.3 (Mechanism: Dirichlet bias). The mechanism driving is always the same: the arithmetic restriction systematically elevates the density of divisibility events above the generic , creating a Dirichlet bias that inflates the singular factor and hence the residue coefficients in the explicit formula. The more restrictive is, the larger .
12. Zero Detection in the Subsequence12.1. Theoretical Amplification
For the congruence class
, the theoretical amplification constant is
giving a predicted improvement factor
in signal-to-noise ratio relative to the unrestricted shifted-prime case.
12.2. Computational Setup
The script constructs a sieve up to and extracts all primes in that range (approximately primes). is computed by the same Numba-JIT inner loop. Results are cached to datos .npz so that repeated runs skip the computation. The Mellin analysis and 200-permutation test are then applied to the first 200 zeros.
12.3. Expected Output
Based on the theoretical amplification and the empirical scaling law (13) (Section 14), this subsequence is expected to detect approximately – of the first 200 zeros at with primes, outperforming the unrestricted subsequence at the same sample size.
13. Supplementary Computational Results
13.1. Monotone Growth ofFigure 13 shows that
grows monotonically by decade up to
, reaching
in
. The growth factor stabilises at
per decade, consistent with the prediction
(Law 3).
13.2. Empirical Trajectory ofThe empirical constant converges to from above, with a secondary-term fit . At , the deviation is , consistent with slow convergence.
Figure 14.
Empirical trajectory of . Secondary-term fit: . [NEW] [COMP. VERIF.].
Figure 14.
Empirical trajectory of . Secondary-term fit: . [NEW] [COMP. VERIF.].
14. Discussion and Limitations
14.1. Scope and Signal-to-Noise Scaling
This paper does not discover new Riemann zeros; all detected are known beyond via the Odlyzko–Schönhage algorithm. What it demonstrates is that the shifted-prime subsequence, governed by , produces measurable oscillatory signatures at the known imaginary parts, consistent with (5) and RH.
The signal-to-noise scaling for detecting zero
requires:
where
is the empirical mean of
and
. Extending to
primes (range
) is expected to raise detection to approximately 150/200 at
.
14.2. Limitations
(L1) The amplification ratio has not converged to . The gap of – is consistent with slow convergence but remains unproved.
(L2) The decay-law – leaves substantial variance unexplained. This is expected noise for the given sample size; is predicted to reach – at primes.
(L3) The corrected formula (11) is proved (Theorem 9.1), but the Cesàro analogue for Mirror primes (condition (iii) of Theorem 11.2) is open.
(L4) The computations have not been independently reproduced by a third party.
(L5) The gap in Lemma 3.3 (meromorphic continuation of
) is fully argued in [
26] but the sketch given here is not self-contained.
14.3. Open Questions
(Q1) Prove the Cesàro analogue for Mirror primes: .
(Q2) Compute for Orphan and other subsequences and verify empirically.
(Q3) Show that the decay slope converges to exactly as , or identify sub-leading corrections.
(Q4) Prove Conjecture 11.1 for at least one additional non-trivial arithmetic restriction.
(Q5) Characterise the growth rate of as with explicit constant.
(Q6) Extend the computation to primes (range ) and verify the predicted detection rate.
15. Summary of Results and Epistemic Status
Table 11. Complete epistemic status of all main results.
16. Conclusions
What Is Solid (Unconditional): The convergence of and its role as the amplification constant in the explicit formula for are proved unconditionally. The corrected generalised Euler product converges for all and grows as , resolving a significant error in the prior literature. Computationally, using 334,351 primes, 61.5% of the first 200 non-trivial Riemann zeros are detected at , with a decay slope of (1.8% error). The corrected formula matches empirical data to within 0.04% for .
What Is Conditional: Under RH, the decay slope converges to exactly (Q3), and the amplification constants for Mirror and Anchor-3 primes equal (Q2). Under RH and Hardy–Littlewood Conjecture B, the Generalised Amplification Conjecture holds for Mirror primes (Q4).
What Is Conjectural: The Generalised Spectral Amplification Conjecture 11.1 proposes that every arithmetically restricted prime subsequence carries its own Euler-product amplification constant , of which the classical Goldbach bridge (, Fujii) and the shifted-prime bridge (, Anderson) are the first two verified members. Proving even one additional case beyond the Mirror case treated here would constitute a significant extension of the Goldbach–Riemann bridge programme.
The Goldbach–Riemann Bridge: The explicit formula (5) carries a structurally new amplification factor , absent from all classical bridges (Fujii, Bhowmik–Schlage-Puchta, Goldston–Suriajaya). The Generalised Amplification Conjecture proposes that this is the first member of an infinite family of arithmetic Riemann bridges, each characterised by its own Euler-product constant . The key mechanism—Dirichlet divisibility bias inflating the singular factor—is explicit and computable for any arithmetic restriction.
17. Appendix (Script Python)
17.1. Description of the Unified Verification Script_python.py
The script reproduces all numerical results of the paper (preprint v4). It is structured into the following functional blocks (line numbers are approximate and refer to the actual script listing).
17.2. Installation Requirements (pip)
pip install numpy numba sympy matplotlib scipy
17.3. Block-by-Block Functionality
Lines (approx.): Function
1–30: Header, documentation, global parameters (prime range, permutations, zeros).
32–48: Imports: os, sys, time, json, random, numpy, multiprocessing, matplotlib. Optional detection of numba and sympy.
50–70: Paper constants: C2, TWO_C2, S_INF, ALPHA_INF_CONJ. Array GAMMA_200 with the first 200 non-trivial zeros (imaginary parts).
72–115: Numba-JIT optimised functions: compute_N_jit – accelerated computation of N(p).
117–142: Utilities: build_sieve (Eratosthenes sieve as bytearray), compute_S_vectorized (singular factor S(p+1)).
144–165: Local fit and residuals: compute_alpha_and_residuals (α, ε(p), RMSE, coverage).
167–226: Statistical core: mellin_and_permutations – discrete Mellin transform for the zeros and permutation test (500 permutations by default).
228–340: Part 1 – Detection of 200 zeros in range [1e6, 6e6] (334,351 primes, 500 permutations). Computes N(p), S(p+1), residuals, z-scores, p-values, log-log regression, and saves plots.
342–405: Part 2 – Subsequence p ≡ 14 (mod 15) up to 8·10⁶ (200 permutations). Uses cache (datos_subsecuencia_8M.npz) to avoid recomputing N(p).
407–425: Part 3 – Growth of min N(p) and convergence of Ĉ(x) (simplified version; refers to Goldbach_4.py for full figures 13-14).
427–509: Part 4 – Amplification ratio (Anderson vs. classical Goldbach) for two ranges: [1e6,2e6] and [1e6,6e6]. Computes z-scores for both residual types and the mean ratio over common zeros with z>2.
511–542: Main() function: fixes random seeds, creates output directory, runs all four parts sequentially.
544–546: Main guard (if __name__ == “__main__”: mp.freeze_support(); main()) for Windows compatibility.
17.4. Script
import os
import sys
import time
import json
import math
import random
import numpy as np
import multiprocessing as mp
from collections import defaultdict
try:
from numba import njit, prange
NUMBA_AVAILABLE = True
print("✓ Numba disponible - optimización activada")
except ImportError:
NUMBA_AVAILABLE = False
print("✗ Numba NO disponible - usando modo lento")
def njit(f): return f
def prange(range): return range
try:
from sympy import isprime as sympy_isprime, nextprime as sympy_nextprime
SYMPY_AVAILABLE = True
except ImportError:
SYMPY_AVAILABLE = False
import matplotlib.pyplot as plt
# ============================================================================
# CONSTANTES DEL PAPER
# ============================================================================
C2 = 0.6601618158468696
TWO_C2 = 2 * C2
S_INF = 1.7427253553918328
ALPHA_INF_CONJ = 1.0 / S_INF
# Primeros 200 ceros no triviales (parte imaginaria)
GAMMA_200 = np.array([
14.134725141734693790, 21.022039638771554993, 25.010857580145688763,
30.424876125859513210, 32.935061587739189691, 37.586178158825671257,
40.918719012147495187, 43.327073280914999519, 48.005150881167159728,
49.773832477672302182, 52.970321477714460644, 56.446247697063394804,
59.347044002602353079, 60.831778524609809844, 65.112544048081606660,
67.079810529494173714, 69.546401711173979252, 72.067157674481907583,
75.704690699083933168, 77.144840068874805373, 79.337375020249367922,
82.910380854086419494, 84.735492980517944342, 87.425274613125484385,
88.809111207634078295, 92.491899270558393445, 94.651344040519966296,
95.870634228245100676, 98.831194218154647771, 101.317851005731359128,
103.725538040478496151, 105.446623052332139824, 107.168611184547512718,
109.333415286312632280, 111.029535543058416172, 112.948105007737889636,
114.936519236288949726, 116.226680320065765313, 118.790782866128076055,
121.370125002122158041, 122.946829293659598744, 124.256818554345157982,
127.516683879443672573, 129.578704199956048450, 131.087688530932730187,
133.497737202997519744, 134.756509753525313045, 138.116042054533222112,
139.736208952121396713, 141.123707404021137350, 143.111845807620590275,
146.000982486771652810, 147.422765343731659747, 150.053520420677144901,
150.925257611418143090, 153.024693811796247402, 156.112909288629071952,
157.597591235046217562, 158.849988738993101257, 161.188964136063822527,
163.030709562472751867, 165.537069187388736543, 167.184439072157705648,
169.094515694588222512, 169.911976479010507729, 173.411534131323027049,
174.754191521203717248, 176.441434528214457251, 178.377407710091689986,
179.916484013815138825, 182.207065696367917673, 184.874467748503760979,
185.598783678848901320, 187.228922897848025788, 189.416158739034808324,
192.026656362955215567, 193.079726608649474848, 195.265396934283938510,
196.876481281228532052, 198.015309682682571249, 201.264751562355525939,
202.493594514928002567, 204.189171809036253110, 205.394693249391084706,
207.906258878873659097, 209.576509714716128024, 211.690862550125132970,
213.347819360297605394, 214.475102041831637118, 216.661959518910707580,
218.787557909624020881, 220.010451436425577729, 221.962661780554385401,
223.637436674563482208, 225.631369742380975582, 227.128195946253098083,
228.669395751931371466, 230.619565446488142848, 232.270249227058096778,
233.794646626301497672, 235.655330689102971606, 237.227428044076825862,
238.657054106665028401, 240.597579310252330237, 242.388194793152186882,
243.952168330866813334, 245.595047441800273176, 247.270562507297293065,
248.812592562970211030, 250.228075270217066775, 251.687795718001369680,
253.442359342480281230, 255.215570326081526677, 256.683468466768875251,
258.360541595758658243, 259.924613984570195815, 261.745886864284053556,
263.223756131717551490, 264.747926097164596303, 266.550649550286930492,
268.018288970430318601, 269.448978409762598276, 271.371504503754371715,
272.980270664386080630, 274.658474285311602510, 276.333151266655756263,
277.713534092639224138, 279.457861243173114174, 280.990303102009278098,
282.526213720594053896, 284.256149594656890462, 285.881304546141721843,
287.266439957396404149, 288.990303955160801363, 290.743601051930711953,
292.336211912286758845, 293.888234921427760576, 295.489478500355961266,
297.112083366898511223, 298.631122681139273257, 300.254735356217215632,
301.898291322173405065, 303.480372722178400984, 304.984373103854993948,
306.611098561598461541, 308.228578736636023301, 309.865590506574064396,
311.409065095227352772, 312.958396277825718207, 314.588159128169683186,
316.184748932414671039, 317.767797569012508809, 319.333451822733034088,
320.982179572404269123, 322.614173845050761110, 324.182640648708615098,
325.745612149489734092, 327.346622727958625537, 328.970164392959827641,
330.527211289470087757, 332.168182846924886559, 333.753162058167868025,
335.348188593501365831, 336.961375422666104519, 338.562087934525113735,
340.164399997974342245, 341.771801655876417623, 343.356072160299814540,
344.948398457288074705, 346.569393508222255258, 348.169528391439111342,
349.763964802763847434, 351.361247187529694210, 352.952848573980510942,
354.527545732162147625, 356.148820631701850894, 357.724352038326903050,
359.346108893166868634, 360.951278327646883621, 362.562293296550534674,
364.173552436998838328, 365.764316901735722936, 367.352392731042519660,
368.953562217912312213, 370.560280843393917589, 372.167560708851206075,
373.771413837507144752, 375.368976901814142445, 376.968910551646645598,
378.582795266915706246, 380.182466299153110038, 381.788843001980190684,
383.394554295341689222, 385.002530749090327548, 386.599064353619353261,
388.211780318531094071, 389.818702369754762133, 391.421429969497411229,
393.027110517784569138, 394.639875120576159338, 396.244829763454777515,
397.852376223488025062, 399.462795391553867297, 401.071618962370059792,
402.678641574094627770, 404.287374413391446162, 405.893127342971456455,
407.503169849746834701, 409.111222786801032741, 410.721753060446577417,
412.329590504281708313, 413.939478951296710469, 415.547392244526652748,
417.158158973534367345, 418.767387942216931117, 420.375234456075165747,
421.987168256159481962, 423.595887699635128268, 425.206006890044124083,
426.813288319733574845, 428.424899575700890624, 430.032928177584870069,
431.644544455838330127, 433.252707238513965722, 434.862324657725479783,
436.470903105956495424, 438.082543498929032512, 439.690527924984631886,
441.301020208117759402, 442.909306167729692443, 444.519815266238088365,
446.127863289866668440, 447.738427235521922284, 449.346553801165417941,
450.957436195429346208, 452.565856711377277183, 454.176308870195031713
])
# ============================================================================
# FUNCIONES OPTIMIZADAS CON NUMBA JIT
# ============================================================================
@njit(cache=True)
def compute_N_jit(primes_a, all_primes, is_prime):
"""
Versión JIT compilada de N(p)
Calcula N(p) = #{q <= (p+1)/2, q + r = p+1, ambos primos}
~8-10x más rápida que la versión vectorizada
"""
n = len(primes_a)
N = np.zeros(n, dtype=np.int32)
max_n = len(is_prime)
for i in range(n):
p = primes_a[i]
target = p + 1
half = target // 2
count = 0
# Iterar sobre primos q (all_primes está ordenado)
for j in range(len(all_primes)):
q = all_primes[j]
if q > half:
break
r = target - q
if r >= 2 and r < max_n and is_prime[r]:
count += 1
N[i] = count
return N
def build_sieve(limit):
"""Criba de Eratóstenes (bytearray) - optimizada"""
print(f" Construyendo criba hasta {limit:,}...", end=' ', flush=True)
t0 = time.time()
s = bytearray(b'\x01') * (limit + 1)
s[0] = s[1] = 0
i = 2
while i * i <= limit:
if s[i]:
step = i
start = i * i
s[start:limit+1:step] = b'\x00' * ((limit - start) // step + 1)
i += 1
is_prime = np.frombuffer(s, dtype=np.uint8).astype(np.bool_)
print(f"hecho en {time.time()-t0:.2f}s, {is_prime.nbytes/1e6:.1f} MB")
return is_prime
def compute_S_vectorized(primes_a, all_primes):
"""Cálculo vectorizado de S(p+1) usando primos hasta 10000"""
ns = (primes_a + 1).astype(np.int64)
result = np.ones(len(ns), dtype=np.float64)
ms = ns.copy()
# Quitar factores 2
while True:
mask2 = (ms % 2 == 0)
if not mask2.any():
break
ms[mask2] //= 2
# Primos pequeños hasta 10000
small_primes = all_primes[(all_primes > 2) & (all_primes < 10000)]
for p in small_primes:
mask = (ms % p == 0)
if mask.any():
factor = (p - 1.0) / (p - 2.0)
result[mask] *= factor
while True:
still = mask & (ms % p == 0)
if not still.any():
break
ms[still] //= p
# Resto primo grande
leftover = ms > 1
if leftover.any():
lp = ms[leftover].astype(np.float64)
result[leftover] *= (lp - 1.0) / (lp - 2.0)
return result
def compute_alpha_and_residuals(primes_a, N, Sf):
"""Ajuste local y residuos"""
ps = primes_a.astype(np.float64)
lps = np.log(ps)
C_hat = np.mean(N * lps*lps / ps)
S_bar = np.mean(Sf)
alpha = C_hat / (TWO_C2 * S_bar)
Nhat = alpha * TWO_C2 * Sf * ps / (lps*lps)
eps = (N - Nhat) / Nhat
rmse = np.sqrt(np.mean(eps*eps))
cov30 = np.mean(np.abs(eps) < 0.30) * 100
cov50 = np.mean(np.abs(eps) < 0.50) * 100
return alpha, eps, rmse, cov30, cov50, C_hat, S_bar
def mellin_and_permutations(primes_a, eps, gammas, n_perm=500):
"""Transformada de Mellin y test de permutaciones"""
n = len(primes_a)
ps = primes_a.astype(np.float64)
log_ps = np.log(ps)
sqrt_ps = np.sqrt(ps)
w = eps / sqrt_ps
n_zeros = len(gammas)
print(f" Calculando Mellin para {n_zeros} ceros...")
t0 = time.time()
Mk_obs = np.zeros(n_zeros)
for k, gamma in enumerate(gammas):
phase = gamma * log_ps
re = np.sum(w * np.cos(phase)) / n
im = np.sum(w * np.sin(phase)) / n
Mk_obs[k] = np.sqrt(re*re + im*im)
print(f" Mellin completado en {time.time()-t0:.2f}s")
# Permutaciones
print(f" Ejecutando {n_perm} permutaciones...")
t0 = time.time()
perm_matrix = np.zeros((n_perm, n_zeros))
for i_perm in range(n_perm):
if (i_perm + 1) % 100 == 0:
print(f" Permutación {i_perm+1}/{n_perm}...")
eps_perm = np.random.permutation(eps)
w_perm = eps_perm / sqrt_ps
for k, gamma in enumerate(gammas):
phase = gamma * log_ps
re = np.sum(w_perm * np.cos(phase)) / n
im = np.sum(w_perm * np.sin(phase)) / n
perm_matrix[i_perm, k] = np.sqrt(re*re + im*im)
print(f" Permutaciones completadas en {time.time()-t0:.2f}s")
bl_mean = np.mean(perm_matrix, axis=0)
bl_std = np.std(perm_matrix, axis=0)
z_scores = np.where(bl_std > 0, (Mk_obs - bl_mean) / bl_std, 0.0)
p_values = np.mean(perm_matrix >= Mk_obs[np.newaxis, :], axis=0)
return z_scores, p_values, Mk_obs
# ============================================================================
# PARTE 1: DETECCIÓN DE 200 CEROS (rango 1e6-6e6, 500 permutaciones)
# ============================================================================
def parte1_deteccion_ceros(out_dir):
print("\n" + "="*70)
print("PARTE 1: Detección de 200 ceros de Riemann (p ∈ [1e6, 6e6])")
print("="*70)
p_start = 1_000_000
p_end = 6_000_000
n_zeros = 200
n_perm = 500
# Construir criba y primos
sieve = build_sieve(p_end)
all_primes = np.where(sieve)[0].astype(np.int64)
primes_a = all_primes[(all_primes >= p_start) & (all_primes <= p_end)]
print(f" Primos en el rango: {len(primes_a):,}")
print(f" Objetivo del paper: 334,351 primos")
# Calcular N(p) con VERSIÓN JIT OPTIMIZADA
print(" Calculando N(p) con Numba JIT (optimizado)...")
t0 = time.time()
is_prime_bool = sieve.astype(np.bool_)
N = compute_N_jit(primes_a, all_primes, is_prime_bool)
print(f" N(p) calculado en {time.time()-t0:.2f}s")
print(f" min N(p) = {N.min()}, max N(p) = {N.max()}")
print(f" Esperado paper: min=3972, max=73710")
# Calcular S(p+1)
print(" Calculando S(p+1)...")
t0 = time.time()
Sf = compute_S_vectorized(primes_a, all_primes)
print(f" S(p+1) calculado en {time.time()-t0:.2f}s")
# Ajuste local y residuos
alpha, eps, rmse, cov30, cov50, C_hat, S_bar = compute_alpha_and_residuals(primes_a, N, Sf)
print(f" α = {alpha:.6f} (1/S∞ = {ALPHA_INF_CONJ:.6f})")
print(f" Esperado paper: α = 0.578245")
print(f" RMSE = {rmse:.6f}, Cov±30% = {cov30:.2f}%")
print(f" Esperado paper: RMSE=0.006455, Cov=100%")
# Mellin y permutaciones
print(f" Transformada de Mellin y {n_perm} permutaciones...")
t0 = time.time()
gammas = GAMMA_200[:n_zeros]
z_scores, p_values, Mk_obs = mellin_and_permutations(primes_a, eps, gammas, n_perm)
print(f" Transformada completada en {time.time()-t0:.2f}s")
# Tablas
det_p001 = np.sum(p_values < 0.001)
det_p01 = np.sum(p_values < 0.01)
det_p05 = np.sum(p_values < 0.05)
print(f"\n Detección: p<0.001: {det_p001}/{n_zeros} ({100*det_p001/n_zeros:.1f}%)")
print(f" p<0.01 : {det_p01}/{n_zeros} ({100*det_p01/n_zeros:.1f}%)")
print(f" p<0.05 : {det_p05}/{n_zeros} ({100*det_p05/n_zeros:.1f}%)")
print(f" Esperado paper: p<0.001: 102/200 (51%), p<0.01: 123/200 (61.5%)")
# Top 10 z-scores
top10_idx = np.argsort(z_scores)[-10:][::-1]
print("\n Top 10 zeros por z-score:")
print(" k γ_k z-score p-value")
for idx in top10_idx:
print(f" {idx+1:3d} {gammas[idx]:12.6f} {z_scores[idx]:9.2f} {p_values[idx]:.4e}")
print(f"\n Esperado paper: γ₁=14.1347, z=104.12")
# Regresión log-log para decay slope
valid = z_scores > 0.5
if np.sum(valid) > 2:
log_g = np.log(gammas[valid])
log_z = np.log(z_scores[valid])
from scipy import stats
slope, intercept, r_value, p_val, std_err = stats.linregress(log_g, log_z)
print(f"\n Decaimiento espectral: slope = {slope:.4f} (R² = {r_value**2:.4f})")
print(f" Esperado paper: slope = -1.0182, R² = 0.516")
else:
print("\n No hay suficientes z-scores >0.5 para regresión.")
slope = None
# Guardar resultados
os.makedirs(out_dir, exist_ok=True)
np.savez(os.path.join(out_dir, "parte1_deteccion.npz"),
primes=primes_a, N=N, Sf=Sf, eps=eps, z_scores=z_scores, p_values=p_values)
with open(os.path.join(out_dir, "parte1_resumen.json"), "w") as f:
json.dump({
"n_primes": len(primes_a),
"alpha": float(alpha),
"detected_p001": int(det_p001),
"detected_p01": int(det_p01),
"detected_p05": int(det_p05),
"slope": float(slope) if slope else None,
"top10_zscores": [float(z_scores[i]) for i in top10_idx],
}, f, indent=2)
# Figuras
plt.figure(figsize=(12,5))
plt.subplot(1,2,1)
colors = ['darkblue' if pv<0.001 else 'mediumblue' if pv<0.01 else 'lightblue' if pv<0.05 else 'lightgrey' for pv in p_values]
plt.bar(range(1, n_zeros+1), z_scores, color=colors, alpha=0.7)
plt.axhline(y=2, color='r', linestyle='--', label='z=2')
plt.xlabel('Zero index')
plt.ylabel('z-score')
plt.title('z-scores (500 permutations)')
plt.legend()
plt.subplot(1,2,2)
plt.plot(range(1, n_zeros+1), p_values, 'o-', color='darkgreen')
plt.axhline(y=0.05, color='r', linestyle='--')
plt.yscale('log')
plt.xlabel('Zero index')
plt.ylabel('p-value (log scale)')
plt.title('Permutation p-values')
plt.tight_layout()
plt.savefig(os.path.join(out_dir, "parte1_zeros.png"), dpi=150)
plt.close()
print(f" Resultados guardados en {out_dir}/")
# ============================================================================
# PARTE 2: SUBSUCESIÓN p ≡ 14 (mod 15) hasta 8e6
# ============================================================================
def parte2_subsecuencia_mod15(out_dir):
print("\n" + "="*70)
print("PARTE 2: Subsucesión p ≡ 14 (mod 15) hasta 8e6")
print("="*70)
LIMITE = 8_000_000
MOD = 15
RESIDUE = 14
n_zeros = 200
n_perm = 200
sieve = build_sieve(LIMITE + 2)
all_primes = np.where(sieve)[0].astype(np.int64)
primes_amp = np.array([p for p in all_primes if p % MOD == RESIDUE], dtype=np.int64)
print(f" Primos en la subsucesión: {len(primes_amp):,}")
cache_file = os.path.join(out_dir, "datos_subsecuencia_8M.npz")
if os.path.exists(cache_file):
print(" Cargando datos cacheados...")
data = np.load(cache_file)
primes_amp = data["primes"]
N = data["N"]
Sf = data["S"]
alpha = float(data["alpha"])
eps = data["eps"]
else:
print(" Calculando N(p) con Numba JIT...")
is_prime_bool = sieve.astype(np.bool_)
N = compute_N_jit(primes_amp, all_primes, is_prime_bool)
Sf = compute_S_vectorized(primes_amp, all_primes)
alpha, eps, _, _, _, _, _ = compute_alpha_and_residuals(primes_amp, N, Sf)
np.savez(cache_file, primes=primes_amp, N=N, S=Sf, alpha=alpha, eps=eps)
print(f" Datos cacheados en {cache_file}")
gammas = GAMMA_200[:n_zeros]
z_scores, p_values, _ = mellin_and_permutations(primes_amp, eps, gammas, n_perm)
det_p01 = np.sum(p_values < 0.01)
print(f"\n Detección p<0.01: {det_p01}/{n_zeros} ({100*det_p01/n_zeros:.1f}%)")
os.makedirs(out_dir, exist_ok=True)
with open(os.path.join(out_dir, "parte2_resumen.json"), "w") as f:
json.dump({
"n_primes": len(primes_amp),
"detected_p01": int(det_p01),
"alpha": float(alpha),
}, f, indent=2)
plt.figure(figsize=(10,5))
plt.bar(range(1, n_zeros+1), z_scores, color='darkblue', alpha=0.7)
plt.axhline(y=2, color='r', linestyle='--')
plt.xlabel('Zero index')
plt.ylabel('z-score')
plt.title(f'Subsecuencia p ≡ {RESIDUE} mod {MOD} (n={len(primes_amp):,})')
plt.savefig(os.path.join(out_dir, "parte2_zscores.png"), dpi=150)
plt.close()
print(f" Resultados guardados en {out_dir}/")
# ============================================================================
# PARTE 3: min N(p) y Ĉ(x) (simplificada)
# ============================================================================
def parte3_min_N_y_Chapeau(out_dir):
print("\n" + "="*70)
print("PARTE 3: Crecimiento de min N(p) y convergencia de Ĉ(x)")
print("="*70)
print(" Nota: Para reproducción completa de Fig 13-14, ejecutar Goldbach_4.py")
print(" Generando resultados limitados...")
# Versión simplificada - para reproducción completa se necesita Goldbach_4.py
os.makedirs(out_dir, exist_ok=True)
with open(os.path.join(out_dir, "parte3_nota.txt"), "w") as f:
f.write("Para reproducción completa de Figuras 13 y 14, ejecutar Goldbach_4.py\n")
f.write("con checkpoints hasta 1e8.\n")
print(" Parte 3 finalizada (resultados limitados).")
# ============================================================================
# PARTE 4: RELACIÓN DE AMPLIFICACIÓN (Tabla 8)
# ============================================================================
def parte4_relacion_amplificacion(out_dir):
print("\n" + "="*70)
print("PARTE 4: Relación de amplificación (Anderson vs Goldbach clásico)")
print("="*70)
rangos = [(1_000_000, 2_000_000), (1_000_000, 6_000_000)]
resultados = []
for p_start, p_end in rangos:
print(f"\n Rango: [{p_start//1000}K, {p_end//1000}K]")
sieve = build_sieve(p_end)
all_primes = np.where(sieve)[0].astype(np.int64)
primes_and = all_primes[(all_primes >= p_start) & (all_primes <= p_end)]
n_and = len(primes_and)
print(f" Primos Anderson: {n_and:,}")
# Calcular residuos de Anderson
is_prime_bool = sieve.astype(np.bool_)
N_and = compute_N_jit(primes_and, all_primes, is_prime_bool)
Sf_and = compute_S_vectorized(primes_and, all_primes)
alpha_and, eps_and, _, _, _, _, _ = compute_alpha_and_residuals(primes_and, N_and, Sf_and)
# Goldbach clásico
n_vals = primes_and + 1
R_classic = np.zeros(len(n_vals), dtype=np.int32)
for idx, n in enumerate(n_vals):
half = n // 2
cut = np.searchsorted(all_primes, half, side='right')
qs = all_primes[:cut]
rs = n - qs
valid = (rs >= 2) & (rs < len(sieve))
R_classic[idx] = np.sum(sieve[rs[valid]])
nf = n_vals.astype(np.float64)
Nhat_classic = TWO_C2 * nf / (np.log(nf)**2)
eps_classic = (R_classic - Nhat_classic) / Nhat_classic
# z-scores
gammas = GAMMA_200[:200]
z_and, p_and, _ = mellin_and_permutations(primes_and, eps_and, gammas, n_perm=200)
z_class, p_class, _ = mellin_and_permutations(primes_and, eps_classic, gammas, n_perm=200)
mask = (z_and > 2) & (z_class > 2)
if np.sum(mask) > 0:
ratio = z_and[mask] / z_class[mask]
r_mean = np.mean(ratio)
r_std = np.std(ratio)
print(f" Ceros con ambos z>2: {np.sum(mask)}")
print(f" Relación media = {r_mean:.4f} ± {r_std:.4f}")
else:
print(" No hay ceros con ambos z>2 en este rango.")
r_mean = None
resultados.append({
"range": f"[{p_start}, {p_end}]",
"n_primes": n_and,
"mean_ratio": r_mean,
"detected_and": int(np.sum(p_and < 0.01)),
"detected_class": int(np.sum(p_class < 0.01))
})
os.makedirs(out_dir, exist_ok=True)
with open(os.path.join(out_dir, "parte4_relacion.json"), "w") as f:
json.dump(resultados, f, indent=2)
print("\n Tabla 8 (relación de amplificación):")
for r in resultados:
print(f" {r['range']:20s} n={r['n_primes']:6d} ratio={r['mean_ratio'] if r['mean_ratio'] else '---'} det_And={r['detected_and']} det_Class={r['detected_class']}")
# ============================================================================
# MAIN
# ============================================================================
def main():
print("\n" + "="*70)
print("REPRODUCCIÓN DE RESULTADOS DEL PAPER ANDERSON (2026)")
print("Script optimizado con Numba JIT")
print("="*70)
print(f"Rango: [1e6, 6e6] - {334_351:,} primos")
print(f"Permutaciones: 500")
print(f"Ceros: 200")
print("="*70)
# Fijar semillas para reproducibilidad
random.seed(42)
np.random.seed(42)
out_dir = "resultados_paper_reproducibilidad"
os.makedirs(out_dir, exist_ok=True)
# Ejecutar partes
parte1_deteccion_ceros(out_dir)
parte2_subsecuencia_mod15(out_dir)
parte3_min_N_y_Chapeau(out_dir)
parte4_relacion_amplificacion(out_dir)
print("\n" + "="*70)
print("¡Reproducción completada!")
print(f"Todos los resultados guardados en '{out_dir}/'")
print("="*70)
if __name__ == "__main__":
# Para multiprocessing en Windows
mp.freeze_support()
main()
References
E. Ingham, “On the estimation of T. Oliveira e Silva, S. Herzog, and S. Pardi, “Empirical verification of the even Goldbach conjecture and computation of prime gaps up to F. Anderson, “The Goldbach–Riemann Bridge for Shifted Primes: Analytic Structure, the Singular-Factor Constant , Explicit Formula for