Pattern Field Theory × Allen Orbital Lattice × Riemann Hypothesis — run001

Generated: 2025-09-23 12:57 UTC

Preparation & Sources

All paths are relative to this run folder: run001/

Zeros (Odlyzko)
zeros6.gz — full gzip copied for provenance; analysis in this run used the first 100,000 rows.
Figures
figures/r001_spacing_ecdf_small.png · figures/r001_spacing_ecdf_full.png · figures/r001_fft_magnitude_comp.png
Metrics
metrics/r001_metrics_demo_unfolded.csv
metrics/r001_metrics_first100k_raw.csv (raw = not unfolded)
metrics/r001_metrics_first100k_unfolded.csv (unfolded = mean spacing forced to 1.0)
Manifest
manifest.json

External references (original sources)

Odlyzko zeta tables — index.html
zeros6.gz
zeros6 (text)

Naming convention (per run)

Inputs & Method

Results (inline preview of CSVs)

Demo sanity run — unfolded spacings

File: metrics/r001_metrics_demo_unfolded.csv (unfolded by construction)

First 100k zeros — raw spacings (not unfolded)

Figure: ECDF (small demo run)

ECDF comparison — small demo run

Figure: ECDF (first 100k zeros)

ECDF comparison — first 100k zeros

Figure: FFT magnitudes (first 100k zeros)

FFT magnitude comparison

Run 001 — Report

Objective: Establish a baseline comparison between Odlyzko’s first 100,000 zeta zeros and Allen Orbital Lattice (AOL) spoke primes, and verify the pipeline + unfolding sanity checks.

Summary of results

Interpretation

The demo (unfolded) confirms the mechanics. The 100k comparison above is shown in its raw form for provenance; an unfolded version (recommended for apples-to-apples statistics) will be produced as metrics/r001_metrics_first100k_unfolded.csv in the next pass.

Artifacts

Metrics CSVs in metrics/; figures in figures/; manifest at manifest.json.

Reproducibility — Python (Run 001)

Self-contained pipeline. Source zeros file: zeros6.gz.

Environment

python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install numpy pandas matplotlib

1) Download zeros (optional)

# macOS / Linux
curl -L -o zeros6.gz "https://www-users.cse.umn.edu/~odlyzko/zeta_tables/zeros6.gz"

# Windows (PowerShell)
Invoke-WebRequest -Uri "https://www-users.cse.umn.edu/~odlyzko/zeta_tables/zeros6.gz" -OutFile "zeros6.gz"

2) Parse zeros & compute spacings

import gzip, os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

run_base = "run001"
zeros_path = "zeros6.gz"
os.makedirs(os.path.join(run_base, "metrics"), exist_ok=True)
os.makedirs(os.path.join(run_base, "figures"), exist_ok=True)
os.makedirs(os.path.join(run_base, "data"), exist_ok=True)

# Parse first ~120k rows; analyze first 100k
values = []
with gzip.open(zeros_path, "rt", encoding="utf-8", errors="ignore") as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        tok = line.split()[0]
        try:
            values.append(float(tok))
        except ValueError:
            continue
        if len(values) >= 120_000:
            break

assert len(values) >= 100_000, f"Only {len(values)} zeros parsed."
z100k = np.array(values[:100_000], float)
demo  = np.array(values[:5_000], float)

sp_raw = np.diff(z100k)
sp_demo = np.diff(demo)

3) Unfold to mean 1.0

def unfold(s: np.ndarray):
    m = float(np.mean(s))
    if m == 0 or not np.isfinite(m):
        raise ValueError("Invalid mean for unfolding.")
    return s / m, m

sp_unf, mean_raw = unfold(sp_raw)
sp_unf_demo, mean_demo = unfold(sp_demo)
print("Raw mean (first100k):", mean_raw)

4) Write metrics CSVs

pd.DataFrame({"index": np.arange(sp_unf_demo.size), "spacing": sp_unf_demo}) \
  .to_csv(os.path.join(run_base, "metrics", "r001_metrics_demo_unfolded.csv"), index=False)

pd.DataFrame({"index": np.arange(sp_raw.size), "spacing": sp_raw}) \
  .to_csv(os.path.join(run_base, "metrics", "r001_metrics_first100k_raw.csv"), index=False)

pd.DataFrame({"index": np.arange(sp_unf.size), "spacing": sp_unf}) \
  .to_csv(os.path.join(run_base, "metrics", "r001_metrics_first100k_unfolded.csv"), index=False)

5) ECDF plots

def plot_ecdf(sp, title, outpng):
    x = np.sort(sp)
    y = np.arange(1, x.size + 1) / x.size
    plt.figure(figsize=(7,4.2), dpi=150)
    plt.step(x, y, where="post")
    plt.xlabel("spacing"); plt.ylabel("ECDF"); plt.title(title)
    plt.tight_layout(); plt.savefig(outpng); plt.close()

plot_ecdf(sp_unf_demo, "ECDF — unfolded spacings (demo slice)",
          os.path.join(run_base, "figures", "r001_spacing_ecdf_small.png"))
plot_ecdf(sp_unf, "ECDF — unfolded spacings (first 100k zeros)",
          os.path.join(run_base, "figures", "r001_spacing_ecdf_full.png"))

6) FFT magnitude comparison

rng = np.random.default_rng(42)
exp_sur = rng.exponential(1.0, size=sp_unf.size)

def fft_mag(a):
    a0 = a - np.mean(a)
    F = np.fft.rfft(a0)
    return np.abs(F), np.fft.rfftfreq(a.size, d=1.0)

mag_zeros, fz = fft_mag(sp_unf)
mag_exp, fe = fft_mag(exp_sur)

plt.figure(figsize=(7,4.2), dpi=150)
plt.loglog(fz[1:], mag_zeros[1:], label="Unfolded Δγ (first 100k)")
plt.loglog(fe[1:], mag_exp[1:], label="Exponential(1) surrogate")
plt.xlabel("frequency (arb. units)"); plt.ylabel("|FFT| magnitude")
plt.title("FFT magnitude comparison — Run 001")
plt.legend(); plt.tight_layout()
plt.savefig(os.path.join(run_base, "figures", "r001_fft_magnitude_comp.png"))
plt.close()

7) Manifest (optional)

import json, hashlib, datetime

def sha256sum(path, blocksize=65536):
    h = hashlib.sha256()
    with open(path, "rb") as f:
        for chunk in iter(lambda: f.read(blocksize), b""): h.update(chunk)
    import os; return h.hexdigest(), os.path.getsize(path)

manifest = {
  "run": "run001",
  "generated_utc": datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"),
  "inputs": {"zeros_source": "zeros6.gz", "first_n_zeros": 100000, "demo_slice": 5000},
  "metrics": {"csv_files": [
    "metrics/r001_metrics_demo_unfolded.csv",
    "metrics/r001_metrics_first100k_raw.csv",
    "metrics/r001_metrics_first100k_unfolded.csv"
  ]},
  "figures": [
    "figures/r001_spacing_ecdf_small.png",
    "figures/r001_spacing_ecdf_full.png",
    "figures/r001_fft_magnitude_comp.png"
  ]
}
with open(os.path.join(run_base, "manifest.json"), "w") as f:
    json.dump(manifest, f, indent=2)

Reproducibility — PowerShell (native)

# run001_make_all.ps1
param(
  [string]$ZerosPath = "zeros6.gz",
  [string]$RunBase = "run001",
  [int]$Take = 100000,
  [int]$Demo = 5000,
  [int]$ParseCap = 120000
)
$ErrorActionPreference = "Stop"
Add-Type -AssemblyName System.IO.Compression.FileSystem
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Windows.Forms.DataVisualization

function Read-Zeros {
  param([string]$gzPath, [int]$cap)
  $fs = [IO.File]::OpenRead($gzPath)
  $gz = New-Object IO.Compression.GZipStream($fs,[IO.Compression.CompressionMode]::Decompress)
  $sr = New-Object IO.StreamReader($gz)
  $vals = New-Object System.Collections.Generic.List[double]
  while(-not $sr.EndOfStream -and $vals.Count -lt $cap){
    $line = $sr.ReadLine().Trim()
    if($line.Length -gt 0){
      $tok = $line.Split([char[]]::Parse(" `t"))[0]
      [double]$v = 0; if([double]::TryParse($tok,[ref]$v)){ $vals.Add($v) }
    }
  }
  $sr.Close(); $gz.Close(); $fs.Close()
  return ,$vals.ToArray()
}
function Diff([double[]]$a){ $n=$a.Length-1; $d=New-Object double[] $n; for($i=0;$i -lt $n;$i++){ $d[$i]=$a[$i+1]-$a[$i] } ,$d }
function Unfold([double[]]$s){
  $mean = ($s | Measure-Object -Average).Average
  if($mean -eq 0 -or [double]::IsNaN($mean)){ throw "Invalid mean." }
  $u = New-Object double[] $s.Length
  for($i=0;$i -lt $s.Length;$i++){ $u[$i] = $s[$i]/$mean }
  return @{ unfolded=$u; mean=$mean }
}
function Write-CSV($path,[double[]]$series){
  $dir=[IO.Path]::GetDirectoryName($path); if(-not(Test-Path $dir)){ New-Item -ItemType Directory $dir | Out-Null }
  $sw = New-Object IO.StreamWriter($path,$false,[Text.Encoding]::UTF8)
  $sw.WriteLine("index,spacing")
  for($i=0;$i -lt $series.Length;$i++){ $sw.WriteLine("$i,$($series[$i].ToString('R'))") }
  $sw.Close()
}
function Save-ECDF($outPng,[double[]]$spacings,[string]$title){
  $sorted = $spacings | Sort-Object
  $n = $sorted.Length
  $chart = New-Object System.Windows.Forms.DataVisualization.Charting.Chart
  $chart.Width=800; $chart.Height=480
  $area = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
  $chart.ChartAreas.Add($area)
  $series = New-Object System.Windows.Forms.DataVisualization.Charting.Series
  $series.ChartType = 'FastLine'; $series.BorderWidth = 2
  for($i=0;$i -lt $n;$i++){ [void]$series.Points.AddXY($sorted[$i], ($i+1)/$n) }
  $chart.Titles.Add($title) | Out-Null; $chart.Series.Add($series)
  $dir=[IO.Path]::GetDirectoryName($outPng); if(-not(Test-Path $dir)){ New-Item -ItemType Directory $dir | Out-Null }
  $chart.SaveImage($outPng,'Png')
}
function Save-FFT($outPng,[double[]]$spacings,[string]$title){
  $mean = ($spacings | Measure-Object -Average).Average
  $a = $spacings | ForEach-Object { $_ - $mean }
  $N = $a.Length; $M = [int][math]::Floor($N/2.0)+1
  $mag = New-Object double[] $M
  for($k=0;$k -lt $M;$k++){
    $re=0.0; $im=0.0
    for($n=0;$n -lt $N;$n++){
      $ang = -2.0*[math]::PI*$k*$n/$N
      $re += $a[$n]*[math]::Cos($ang); $im += $a[$n]*[math]::Sin($ang)
    }
    $mag[$k] = [math]::Sqrt($re*$re + $im*$im)
  }
  $chart = New-Object System.Windows.Forms.DataVisualization.Charting.Chart
  $chart.Width=800; $chart.Height=480
  $area = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
  $area.AxisX.IsLogarithmic = $true; $area.AxisY.IsLogarithmic = $true
  $chart.ChartAreas.Add($area)
  $series = New-Object System.Windows.Forms.DataVisualization.Charting.Series
  $series.ChartType = 'FastLine'; $series.BorderWidth=2
  for($k=1;$k -lt $M;$k++){ [void]$series.Points.AddXY([double]$k, $mag[$k]) }
  $chart.Titles.Add($title) | Out-Null; $chart.Series.Add($series)
  $dir=[IO.Path]::GetDirectoryName($outPng); if(-not(Test-Path $dir)){ New-Item -ItemType Directory $dir | Out-Null }
  $chart.SaveImage($outPng,'Png')
}

if(-not(Test-Path $RunBase)){ New-Item -ItemType Directory $RunBase | Out-Null }
$vals = Read-Zeros -gzPath $ZerosPath -cap $ParseCap
if($vals.Length -lt $Take){ throw "Parsed only $($vals.Length) zeros." }

$z100k = $vals[0..($Take-1)]
$demoZ = $vals[0..($Demo-1)]
$spRaw = Diff $z100k
$spDemo = Diff $demoZ
$u = Unfold $spRaw; $spUnf = $u.unfolded; $meanRaw = $u.mean

Write-CSV "$RunBase\metrics\r001_metrics_demo_unfolded.csv" (Unfold $spDemo).unfolded
Write-CSV "$RunBase\metrics\r001_metrics_first100k_raw.csv" $spRaw
Write-CSV "$RunBase\metrics\r001_metrics_first100k_unfolded.csv" $spUnf

Save-ECDF "$RunBase\figures\r001_spacing_ecdf_small.png" (Unfold $spDemo).unfolded "ECDF — demo (unfolded)"
Save-ECDF "$RunBase\figures\r001_spacing_ecdf_full.png"  $spUnf "ECDF — first 100k (unfolded)"
Save-FFT  "$RunBase\figures\r001_fft_magnitude_comp.png" $spUnf "FFT magnitude — Run 001"

Write-Host "Run001 complete. Raw mean=$([math]::Round($meanRaw,6))"

Reproducibility — PHP (CLI)

<?php
// run001_make_all.php  (CLI: php run001_make_all.php zeros6.gz)
// Outputs CSVs to run001/metrics and HTML report with inline SVG ECDF

$zeros = $argv[1] ?? 'zeros6.gz';
$run = 'run001';
$take = 100000;
$demo = 5000;
$cap  = 120000;

@mkdir("$run/metrics", 0777, true);
@mkdir("$run/figures", 0777, true);

// Parse zeros
$vals = [];
$f = gzopen($zeros, 'r');
if(!$f) die("Cannot open $zeros\n");
while(!gzeof($f) && count($vals) < $cap){
  $line = trim(gzgets($f));
  if($line === '') continue;
  $tok = preg_split('/\s+/', $line)[0];
  if(is_numeric($tok)) $vals[] = floatval($tok);
}
gzclose($f);
if(count($vals) < $take) die("Parsed only ".count($vals)." zeros\n");

// Helpers
function diff_arr($a){
  $n = count($a)-1; $d = [];
  for($i=0;$i<$n;$i++) $d[] = $a[$i+1]-$a[$i];
  return $d;
}
function unfold($s){
  $m = array_sum($s)/count($s);
  if(!$m) throw new Exception("Invalid mean");
  $u=[]; foreach($s as $v){ $u[] = $v/$m; }
  return [$u,$m];
}
function write_csv($path,$arr){
  $fh = fopen($path,'w'); fputs($fh,"index,spacing\n");
  foreach($arr as $i=>$v){ fputs($fh,"$i,$v\n"); }
  fclose($fh);
}

// Compute
$z100k = array_slice($vals,0,$take);
$demoZ = array_slice($vals,0,$demo);
$spRaw = diff_arr($z100k);
$spDemo = diff_arr($demoZ);
[$spUnf,$meanRaw] = unfold($spRaw);
[$spUnfDemo,$mDemo] = unfold($spDemo);

// CSVs
write_csv("$run/metrics/r001_metrics_demo_unfolded.csv", $spUnfDemo);
write_csv("$run/metrics/r001_metrics_first100k_raw.csv", $spRaw);
write_csv("$run/metrics/r001_metrics_first100k_unfolded.csv", $spUnf);

// Inline SVG ECDF (demo + full)
function ecdf_svg($sp,$title){
  sort($sp); $n=count($sp);
  $w=800; $h=420; $pad=50;
  $minX = $sp[0]; $maxX = $sp[$n-1];
  if($maxX==$minX){ $maxX=$minX+1e-6; }
  $path = "";
  for($i=0;$i<$n;$i++){
    $x = $sp[$i];
    $y = ($i+1)/$n;
    $sx = $pad + ($w-2*$pad) * (($x-$minX)/($maxX-$minX));
    $sy = $h-$pad - ($h-2*$pad) * $y;
    $path .= ($i==0 ? "M" : "L").round($sx,2).",".round($sy,2)." ";
  }
  return "<svg viewBox='0 0 $w $h' width='$w' height='$h'>
  <rect x='0' y='0' width='$w' height='$h' fill='white' stroke='#e5e7eb'/>
  <path d='$path' fill='none' stroke='black' stroke-width='1.5'/>
  <text x='".($w/2)."' y='24' text-anchor='middle' font-family='sans-serif' font-size='16'>$title</text>
</svg>";
}
$svg_demo = ecdf_svg($spUnfDemo, "ECDF — Demo (unfolded)");
$svg_full = ecdf_svg($spUnf,     "ECDF — First 100k (unfolded)");
file_put_contents("$run/report.html", "<!doctype html><meta charset='utf-8'><title>Run001 Report</title>
<h1>Run 001 — Report</h1>
<p>Raw mean (first100k): ".number_format($meanRaw,6)."</p>
<h2>ECDF (Demo)</h2>$svg_demo
<h2>ECDF (Full)</h2>$svg_full
<p>CSVs in <code>$run/metrics</code></p>");

echo "Done. CSVs in $run/metrics, report at $run/report.html\n";
?>

Reproducibility — C# (.NET 6 + ScottPlot)

Setup

dotnet new console -o Run001Cs
cd Run001Cs
dotnet add package ScottPlot --version 5.0.19

Program.cs

using System.IO.Compression;
using ScottPlot;

string zerosPath = args.Length > 0 ? args[0] : "zeros6.gz";
string runBase = "run001";
int take = 100_000, demo = 5_000, cap = 120_000;

Directory.CreateDirectory(Path.Combine(runBase, "metrics"));
Directory.CreateDirectory(Path.Combine(runBase, "figures"));

// Parse zeros
List<double> vals = new();
using (var fs = File.OpenRead(zerosPath))
using (var gz = new GZipStream(fs, CompressionMode.Decompress))
using (var sr = new StreamReader(gz))
{
    string? line;
    while ((line = sr.ReadLine()) != null && vals.Count < cap)
    {
        line = line.Trim();
        if (line.Length == 0) continue;
        var tok = line.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)[0];
        if (double.TryParse(tok, out double v)) vals.Add(v);
    }
}
if (vals.Count < take) throw new Exception($"Parsed only {vals.Count} zeros.");

double[] z100k = vals.Take(take).ToArray();
double[] demoZ = vals.Take(demo).ToArray();

static double[] Diff(double[] a)
{
    double[] d = new double[a.Length - 1];
    for (int i = 0; i < d.Length; i++) d[i] = a[i + 1] - a[i];
    return d;
}
static (double[] unfolded, double mean) Unfold(double[] s)
{
    double mean = s.Average();
    if (mean == 0 || double.IsNaN(mean)) throw new Exception("Invalid mean");
    double[] u = new double[s.Length];
    for (int i = 0; i < s.Length; i++) u[i] = s[i] / mean;
    return (u, mean);
}
static void WriteCsv(string path, double[] s)
{
    using var sw = new StreamWriter(path);
    sw.WriteLine("index,spacing");
    for (int i = 0; i < s.Length; i++)
        sw.WriteLine($"{i},{s[i]:R}");
}

double[] spRaw = Diff(z100k);
(double[] spUnf, double meanRaw) = Unfold(spRaw);
double[] spDemo = Diff(demoZ);
(double[] spUnfDemo, double _) = Unfold(spDemo);

// CSVs
WriteCsv(Path.Combine(runBase, "metrics", "r001_metrics_demo_unfolded.csv"), spUnfDemo);
WriteCsv(Path.Combine(runBase, "metrics", "r001_metrics_first100k_raw.csv"), spRaw);
WriteCsv(Path.Combine(runBase, "metrics", "r001_metrics_first100k_unfolded.csv"), spUnf);

// ECDF
static void SaveEcdf(string pngPath, double[] s, string title)
{
    double[] x = s.OrderBy(v => v).ToArray();
    double[] y = Enumerable.Range(1, x.Length).Select(i => (double)i / x.Length).ToArray();
    var plt = new ScottPlot.Plot(800, 480);
    plt.Add.SignalXY(x, y);
    plt.Title(title); plt.XLabel("spacing"); plt.YLabel("ECDF");
    plt.SavePng(pngPath, 800, 480);
}
SaveEcdf(Path.Combine(runBase, "figures", "r001_spacing_ecdf_small.png"), spUnfDemo, "ECDF — demo (unfolded)");
SaveEcdf(Path.Combine(runBase, "figures", "r001_spacing_ecdf_full.png"),  spUnf,     "ECDF — first 100k (unfolded)");

// FFT (naive DFT magnitude)
static (double[] mag, double[] freq) DFTMag(double[] a)
{
    int N = a.Length;
    double mean = a.Average();
    double[] x = a.Select(v => v - mean).ToArray();
    int M = N / 2 + 1;
    double[] mag = new double[M];
    for (int k = 0; k < M; k++)
    {
        double re = 0, im = 0;
        for (int n = 0; n < N; n++)
        {
            double ang = -2.0 * Math.PI * k * n / N;
            re += x[n] * Math.Cos(ang);
            im += x[n] * Math.Sin(ang);
        }
        mag[k] = Math.Sqrt(re * re + im * im);
    }
    double[] freq = Enumerable.Range(0, M).Select(i => (double)i).ToArray();
    return (mag, freq);
}
var (magZeros, fz) = DFTMag(spUnf);
var pltF = new ScottPlot.Plot(800, 480);
pltF.Add.SignalXY(fz.Skip(1).Select(v=> (double)v).ToArray(), magZeros.Skip(1).ToArray());
pltF.Axes.Bottom.ScaleLog10(true);
pltF.Axes.Left.ScaleLog10(true);
pltF.Title("FFT magnitude — Run 001 (unfolded Δγ)");
pltF.XLabel("frequency (arb. units)"); pltF.YLabel("|FFT|");
pltF.SavePng(Path.Combine(runBase, "figures", "r001_fft_magnitude_comp.png"), 800, 480);

Console.WriteLine($"Run001 complete. Raw mean={meanRaw:F6}");

Run

dotnet run -- zeros6.gz