Files
blackroad-operating-system/packs/research-lab/experiments/hilbert_polya_gue.py
Alexa Louise 0108860bff feat: Add Research Lab pack with paralleled math modules
Create comprehensive research-lab pack structure with mathematical
and quantum computing modules from blackroad-prism-console:

Math Modules:
- hilbert_core.py: Hilbert space symbolic reasoning
- collatz/: Distributed Collatz conjecture verification
- linmath/: Linear mathematics C library
- lucidia_math_forge/: Symbolic proof engine
- lucidia_math_lab/: Experimental mathematics

Quantum Modules:
- lucidia_quantum/: Quantum core
- quantum_engine/: Circuit simulation

Experiments:
- br_math/: Gödel gap, quantum experiments

Includes pack.yaml manifest and comprehensive README.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 23:49:03 -06:00

84 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""HilbertPólya / GUE spacing test.
This script compares normalized spacing distributions of the
first `nzeros` nontrivial zeros of the Riemann zeta function and
random Gaussian Unitary Ensemble (GUE) eigenvalues against the
Wigner surmise. It reports the KolmogorovSmirnov distance for
both samples relative to the Wigner CDF.
"""
from __future__ import annotations
import argparse
import math
from typing import Callable
import mpmath as mp
import numpy as np
def wigner_cdf(s: np.ndarray) -> np.ndarray:
"""CDF of the Wigner surmise for the GUE."""
return np.vectorize(
lambda x: math.erf(2 * x / math.sqrt(math.pi))
- (4 * x / math.pi) * math.exp(-4 * x**2 / math.pi)
)(s)
def ks_distance(sample: np.ndarray, cdf: Callable[[np.ndarray], np.ndarray]) -> float:
"""Return the two-sided KolmogorovSmirnov distance between a sample and a CDF."""
x = np.sort(sample)
n = x.size
if n == 0:
raise ValueError("sample must contain at least one element")
cdf_vals = cdf(x)
ecdf_right = np.arange(1, n + 1) / n
ecdf_left = np.arange(0, n) / n
d_plus = np.max(ecdf_right - cdf_vals)
d_minus = np.max(cdf_vals - ecdf_left)
return float(max(d_plus, d_minus))
def riemann_zeros(n: int) -> np.ndarray:
"""Return the imaginary parts of the first n Riemann zeta zeros."""
mp.mp.dps = 30
return np.array([float(mp.zetazero(k).imag) for k in range(1, n + 1)])
def normalized_spacings(vals: np.ndarray) -> np.ndarray:
"""Return consecutive spacings normalised to unit mean."""
diffs = np.diff(vals)
return diffs / np.mean(diffs)
def gue_spacings(n: int, k: int) -> np.ndarray:
"""Sample spacings from k random n×n GUE matrices."""
spacings: list[float] = []
for _ in range(k):
a = np.random.normal(size=(n, n)) + 1j * np.random.normal(size=(n, n))
h = (a + a.conj().T) / 2 # Hermitian
eigvals = np.linalg.eigvalsh(h)
spacings.extend(normalized_spacings(eigvals))
return np.array(spacings)
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--nzeros", type=int, default=200, help="number of zeta zeros")
parser.add_argument("--gue_n", type=int, default=200, help="dimension of GUE matrix")
parser.add_argument("--gue_k", type=int, default=20, help="number of GUE samples")
args = parser.parse_args()
zero_spacings = normalized_spacings(riemann_zeros(args.nzeros))
gue_sample = gue_spacings(args.gue_n, args.gue_k)
ks_zero = ks_distance(zero_spacings, wigner_cdf)
ks_gue = ks_distance(gue_sample, wigner_cdf)
print(f"KS distance (zeros vs Wigner): {ks_zero:.4f}")
print(f"KS distance (GUE vs Wigner): {ks_gue:.4f}")
if __name__ == "__main__":
main()