Current task: —

E-026-inverse-spectral.py

Experiments: E-026 · script updated 08-19-2026

E-026-jacobi.csv — 28.8 KB, updated 08-19-2026

← prev page 2 of 2 · 500/page · 720 rows
# akb_kb_k_ref_equalmass
502 12 21 151.838696564423 150.185259567330
503 12 22 148.296746452805 150.006966939152
504 12 23 151.441917217979 150.175331270384
505 12 24 148.211910064153 150.002724135595
506 12 25 151.083195976935 150.153371363766
507 12 26 148.239769820446 149.980549518342
508 12 27 150.982533340440 150.157659085658
509 12 28 148.596286756453 149.989728090496
510 12 29 151.268169197204 150.151361763559
511 12 30 149.245350513244 149.982052825024
512 12 31 151.663533663333 150.164585268647
513 12 32 149.679926210553 149.984963454983
514 12 33 151.547971976593 150.143172132205
515 12 34 149.411611632596 149.964684758409
516 12 35 150.814320995455 150.131274331446
517 12 36 148.837805314558 149.927791679121
518 12 37 150.234240843461 150.069983445103
519 12 38 148.772468733661 149.885141038451
520 12 39 150.264673537356 150.072154634295
521 12 40 149.056831644388 149.894257577099
522 12 41 150.180987025792 150.048919227173
523 12 42 148.831986234828 149.904421143962
524 12 43 149.628993326712 150.064723174629
525 12 44 148.686162640774 149.893897328069
526 12 45 149.944518778851 150.080277517417
527 12 46 149.816773723275 149.904302680343
528 12 47 151.068794369292 150.090430650751
529 12 48 150.441614343612 149.916653550950
530 12 49 150.452440526925 150.081102890989
531 12 50 149.320899238124 149.895916779850
532 12 51 149.616243802812 150.072954045684
533 12 52 149.867388178561 149.936440286258
534 12 53 150.988549518336 150.091725535463
535 12 54 151.069163835164 149.909758695477
536 12 55 150.673684206341 150.048522797042
537 12 56 149.843050712125 149.883045729295
538 12 57 149.683553417377 150.031909452422
539 12 58 150.104438985558 149.860445967572
540 12 59 150.015611031550 150.084621017834
541 12 60 149.346071551701 149.949466809811
542 12 61 148.228023555790 150.043883561151
543 12 62 148.959240225790 149.875607549887
544 12 63 150.355970021077 150.071891354504
545 12 64 151.967146214571 149.954874638437
546 12 65 150.665446941259 150.131179322584
547 12 66 149.578560196952 149.901043948926
548 12 67 148.728530565342 150.009162403050
549 12 68 150.154145285765 149.773083352112
550 12 69 149.221202871140 149.933873530466
551 12 70 148.748410441006 149.738901877327
552 12 71 148.296975041875 149.874736322414
553 12 72 151.332102630892 149.759993817735
554 12 73 150.947617074891 149.983486989414
555 12 74 149.653021540128 149.852950654269
556 12 75 147.715035604882 150.013598208561
557 12 76 150.760202560412 149.841336052366
558 12 77 150.378848436301 150.034032212966
559 12 78 149.632583863915 149.873025677717
560 12 79 148.606569620191 150.043263551518
561 12 80 151.879474433664 149.923392580932
562 12 81 149.245237514626 150.170902189995
563 12 82 148.779341399601 149.989237802053
564 12 83 150.699973536375 150.133674955759
565 12 84 154.195195806020 149.976527082055
566 12 85 149.322606485215 150.167161780361
567 12 86 150.322817905046 149.973557364555
568 12 87 150.135227636491 150.112031878052
569 12 88 148.513247062525 149.855536803973
570 12 89 148.013392455246 150.065781883998
571 12 90 154.846598321180 149.962108576122
572 12 91 149.996952534262 150.181314633112
573 12 92 150.541954354307 150.008211341480
574 12 93 151.728951899928 150.130872904122
575 12 94 149.000856153878 149.993661558282
576 12 95 149.187357863051 150.176852684826
577 12 96 153.324032704129 150.039718458537
578 12 97 144.419971363840 150.189414904254
579 12 98 151.465006451962 150.024911790914
580 12 99 147.884707129065 150.109320445006
581 12 100 149.528952752268 149.866215105595
582 12 101 153.465094608599 150.078630609752
583 12 102 144.785512214041 149.876919934455
584 12 103 152.498743572757 150.048101776156
585 12 104 145.061734529804 149.899275459467
586 12 105 154.661795788832 150.200672563651
587 12 106 147.986467201263 149.954565450261
588 12 107 153.014439825850 150.075581222028
589 12 108 149.057077997331 149.962406241173
590 12 109 153.941009141840 150.114721199058
591 12 110 149.446277030099 149.964932139609
592 12 111 148.967970153870 150.173396895714
593 12 112 145.768197725842 149.855637697884
594 12 113 149.942536627502 150.069296538082
595 12 114 149.930633013366 149.978714172146
596 12 115 149.824238921218 150.033973817753
597 12 116 147.116633419747 149.846896009523
598 12 117 149.729809615666 150.090959131506
599 12 118 150.737898721753 149.952566942976
600 12 119 150.711119845027 150.025971927366
601 12 120 149.386089332198 149.793359142871
602 12 121 150.896870534524 150.082787791494
603 12 122 149.977860676372 149.841529539371
604 12 123 147.412581275862 149.878049473169
605 12 124 148.146403041138 149.650646035457
606 12 125 152.166851108395 149.875550762673
607 12 126 152.066404754172 149.712212769393
608 12 127 147.415409558237 149.738758086259
609 12 128 147.622641055854 149.605993231537
610 12 129 149.594380523832 149.832207369802
611 12 130 149.572850485903 149.719044047527
612 12 131 148.928993465975 149.980603589460
613 12 132 153.644725100382 149.856934618552
614 12 133 152.391889454287 150.000759351883
615 12 134 150.016624011739 149.679348466409
616 12 135 150.461679113987 149.722719041541
617 12 136 152.629980575332 149.633802191369
618 12 137 147.428890856821 149.858414675514
619 12 138 149.761682780453 149.619591645107
620 12 139 150.266423941722 149.747582748654
621 12 140 147.553819766063 149.725327446560
622 12 141 146.314830670296 149.890323361528
623 12 142 153.073656104441 149.803982657839
624 12 143 147.489330341391 149.958183502158
625 12 144 147.601060097198 149.791463483534
626 12 145 149.255428097412 149.965491882421
627 12 146 149.797652526546 149.810883666738
628 12 147 150.097055232579 150.065678892950
629 12 148 154.750029885086 149.868199423263
630 12 149 145.027878223493 149.987858879050
631 12 150 151.155118363495 149.785202429688
632 12 151 152.359278273085 149.948519236708
633 12 152 148.331855566721 149.631970457241
634 12 153 148.632237776481 149.862803243973
635 12 154 149.100591424555 149.746217397884
636 12 155 147.114348408227 149.911473463509
637 12 156 157.245181379544 149.711180266686
638 12 157 145.794871807668 149.772905084972
639 12 158 154.051135592527 149.603015288554
640 12 159 147.577890509782 149.791319343041
641 12 160 148.732581875224 149.634485364557
642 12 161 152.955592563554 149.863424003658
643 12 162 145.601588688816 149.525912935509
644 12 163 152.360623858693 149.619546450616
645 12 164 143.068877039603 149.451239667212
646 12 165 155.950613342766 149.739584934733
647 12 166 146.733759560429 149.568598117874
648 12 167 151.774026261480 149.710976229492
649 12 168 146.792644764466 149.655331248139
650 12 169 154.520650863640 149.959722804273
651 12 170 147.559974409058 149.665848282834
652 12 171 150.655484321138 149.789741325628
653 12 172 150.276413603708 149.601873046236
654 12 173 150.790104097910 149.686609760250
655 12 174 144.509910298297 149.578833305128
656 12 175 147.949208389928 149.876712190745
657 12 176 150.500142944124 149.604404963021
658 12 177 152.710869153339 149.808393267755
659 12 178 150.593641357085 149.413627799644
660 12 179 147.590072476150 149.531393599468
661 12 180 147.363521562433 149.384252812270
662 12 181 151.935670391873 149.646262992344
663 12 182 150.350755497901 149.587017652293
664 12 183 146.792474022943 149.729166385563
665 12 184 150.590554339913 149.630678621907
666 12 185 147.599445921448 149.753914604252
667 12 186 145.551275172342 149.558374781044
668 12 187 150.740938350836 149.871101637468
669 12 188 153.138595425543 149.747392630440
670 12 189 147.948127467897 149.687964730360
671 12 190 151.063313686031 149.480401431292
672 12 191 148.286119712564 149.597862337602
673 12 192 150.105436196873 149.482886050760
674 12 193 146.705343028475 149.607474465108
675 12 194 149.601726417294 149.413304026188
676 12 195 154.318077081375 149.720446056631
677 12 196 150.436680840289 149.374840968835
678 12 197 144.761333332482 149.419839021546
679 12 198 153.208432838100 149.472409513633
680 12 199 145.833388470105 149.499786090663
681 12 200 153.505509615506 149.403152018115
682 12 201 148.946231144435 149.601175404687
683 12 202 150.065479153592 149.377099816770
684 12 203 148.104713090462 149.620639845065
685 12 204 150.292993957789 149.350939501126
686 12 205 151.072386859835 149.500250227733
687 12 206 142.085642863425 149.124007682316
688 12 207 153.850003685429 149.441179229009
689 12 208 151.315842594730 149.408420399740
690 12 209 150.723002986661 149.495514542614
691 12 210 148.249427246767 149.333009129931
692 12 211 152.414119309714 149.494724652743
693 12 212 145.813538967885 149.191732694646
694 12 213 151.302477628493 149.166438484918
695 12 214 149.763194923240 149.121779960821
696 12 215 147.493072192342 149.445823904892
697 12 216 150.745561673946 149.146284283813
698 12 217 148.008311739725 149.342519747708
699 12 218 147.243372923811 149.217845878938
700 12 219 151.997757912096 149.603353899522
701 12 220 147.546025697430 149.368005758282
702 12 221 146.939658575645 149.347554262171
703 12 222 153.420212801977 149.166405750259
704 12 223 146.146878727596 149.145987371225
705 12 224 150.146220864955 149.046111567997
706 12 225 147.430963529607 149.188183702767
707 12 226 146.167934613593 149.064071593837
708 12 227 149.912348716963 149.395971626851
709 12 228 145.675789755809 148.986073710670
710 12 229 149.850419042702 149.382663003225
711 12 230 158.742935684464 149.461940102394
712 12 231 144.008853753878 149.528711719283
713 12 232 152.937097252097 149.197580063467
714 12 233 146.794642546388 149.184207716937
715 12 234 154.610147844886 148.982559276812
716 12 235 141.874226410828 149.153250235122
717 12 236 144.927454037189 149.006450243648
718 12 237 155.053298450929 149.273749866242
719 12 238 147.551924480753 148.966854973645
720 12 239 155.922692604742 149.202385366285
721 12 240 145.988079633098 148.971099486052

E-026-jacobi.json — 2.2 KB, updated 08-19-2026

JSON sidecar (click to expand)
{
  "experiment": "E-026",
  "task": "inverse-spectral reconstruction (Jacobi/Stieltjes coefficients of the Clark measures)",
  "script": "research/numerics/scripts/E-026-inverse-spectral.py",
  "parameters": {
    "a_list": [
      4.0,
      8.0,
      12.0
    ],
    "k_max": 240,
    "dps": 50
  },
  "checks": {
    "V1_roundtrip": false,
    "V2_symmetry": true,
    "V3_free_reference_documented": true
  },
  "key_values": {
    "4": {
      "n_atoms": 762,
      "b_first10": [
        197.53030725422184,
        142.92095536812724,
        159.15960898964033,
        144.02245566814906,
        156.54864075079917,
        145.58592069411515,
        155.01008099518884,
        146.33185226710341,
        154.10605961168793,
        146.84721248193748
      ],
      "b_tail_mean_last20": 142.99220059266153,
      "b_ref_tail_mean_last20": 143.37936432309326,
      "b_min": 136.4184875527748,
      "b_max": 197.53030725422184,
      "roundtrip_dev": 99.95090939634419
    },
    "8": {
      "n_atoms": 1526,
      "b_first10": [
        197.4687711112365,
        142.93932543312803,
        159.09877103726024,
        144.04943192616722,
        156.47961609870868,
        145.62114275673025,
        154.93543142819607,
        146.37506545353162,
        154.02642581802172,
        146.89798821598438
      ],
      "b_tail_mean_last20": 148.12846034636544,
      "b_ref_tail_mean_last20": 148.34613679083813,
      "b_min": 141.78183290120748,
      "b_max": 197.4687711112365,
      "roundtrip_dev": 102.09127232819776
    },
    "12": {
      "n_atoms": 2290,
      "b_first10": [
        197.4516510445814,
        142.94721881560383,
        159.08047821579584,
        144.06020454619352,
        156.45866720384134,
        145.6346431789002,
        154.91256454534792,
        146.3911624786654,
        154.00186642701698,
        146.9165327438543
      ],
      "b_tail_mean_last20": 149.2050889664049,
      "b_ref_tail_mean_last20": 149.18259058194445,
      "b_min": 141.8742264108275,
      "b_max": 197.4516510445814,
      "roundtrip_dev": 102.80351310637383
    }
  },
  "elapsed_seconds": 957.7,
  "timestamp_utc": "2026-08-19T20:21:10.797721+00:00"
}

Source code

Python script (click to expand)
"""E-026 — inverse-spectral reconstruction (sub-stages A+B).

From the E-022 Clark measures (atoms z_k = W(a,pi;.) zeros, masses
w_k = 1/K_a(z_k,z_k)) reconstruct the Jacobi/Stieltjes recurrence
coefficients of the symmetric spectral measure
    mu_a = sum_k w_k (delta_{z_k} + delta_{-z_k})  (+ central handling).
The coefficient sequence {b_k} (a_k = 0 by symmetry) is the discrete
shadow of the canonical-system Hamiltonian (Krein-string data) — the
inverse-spectral observable behind the spectral-purity question
(D-001 sweep entry, 2026-08-19).

Method: Stieltjes/Lanczos on the discrete inner product
    <p,q> = sum_atoms w p q,
with full reorthogonalization, mpmath dps 50. The measure is symmetric
about 0, so a_k = 0 identically (asserted numerically).

Checks:
  V1. Round-trip: eigendecomposition of the K x K Jacobi matrix
      reproduces the first K atoms/masses of the input measure
      (Gauss-quadrature exactness: a K-point Jacobi matrix matches
      the 2K moments; compare spectral atoms to the input's innermost
      atoms within tolerance, weights within 1%).
  V2. Symmetry: |a_k| < 1e-30 (dps-50 zero).
  V3. Free-reference: for the equal-mass lattice measure (same atoms,
      unit masses), b_k settle to a constant (documented).

Outputs: research/numerics/data/E-026-jacobi.csv (+ .json)
Columns: a, k, b_k (measured) ; b_k for the equal-mass reference.
"""
import csv
import json
import sys
import time
from datetime import datetime, timezone
from pathlib import Path

import mpmath as mp
import numpy as np

REPO = Path(__file__).resolve().parents[3]
DATA = REPO / "research" / "numerics" / "data"
CSV = DATA / "E-026-jacobi.csv"
JSON = DATA / "E-026-jacobi.json"

A_LIST = [4.0, 8.0, 12.0]
K_MAX = 240          # recurrence coefficients per side
DPS = 50


def load_measure(a):
    z, w = [], []
    with open(DATA / "E-022-spectral-measure.csv") as f:
        for r in csv.DictReader(f):
            if float(r["a"]) == a:
                z.append(float(r["z_k"]))
                w.append(float(r["w_k"]))
    z = np.array(z)
    w = np.array(w)
    # symmetric measure on +- atoms
    zz = np.concatenate([-z[::-1], z])
    ww = np.concatenate([w[::-1], w]) / 2.0
    return zz, ww


def stieltjes(z, w, k_max, dps=DPS):
    """Lanczos/Stieltjes with full reorthogonalization at dps."""
    mp.mp.dps = dps
    n = len(z)
    zm = [mp.mpf(float(v)) for v in z]
    wm = [mp.mpf(float(v)) for v in w]
    tot = sum(wm)
    # p_0 = 1/sqrt(tot): work with normalized vectors u_k on the atoms
    # (u_k[i] = p_k(z_i) * sqrt(w_i)) — the L2(w) picture.
    sq = [mp.sqrt(v) for v in wm]
    U = []                       # orthonormal vectors (mp lists)
    u0 = [sq[i] / mp.sqrt(tot) for i in range(n)]
    U.append(u0)
    bs = []
    a_dev_max = mp.mpf(0)
    for k in range(k_max):
        # q = z u_k - b_k u_{k-1}   (a_k = <z u_k, u_k> ~ 0 by symmetry)
        uk = U[k]
        a_k = sum(zm[i] * uk[i] ** 2 for i in range(n))
        a_dev_max = max(a_dev_max, abs(a_k))
        q = [zm[i] * uk[i] - a_k * uk[i] for i in range(n)]
        if k > 0:
            q = [q[i] - bs[-1] * U[k - 1][i] for i in range(n)]
        # full reorthogonalization
        for j in range(k + 1):
            c = sum(q[i] * U[j][i] for i in range(n))
            if c:
                q = [q[i] - c * U[j][i] for i in range(n)]
        nq = mp.sqrt(sum(v * v for v in q))
        bs.append(nq)
        U.append([v / nq for v in q])
    return bs, float(a_dev_max)


def roundtrip_check(z, w, bs, k_use=40):
    """Jacobi matrix from bs[:k_use-1] -> Gauss atoms/weights vs input's
    innermost atoms."""
    k = k_use
    J = np.diag(np.array([float(b) for b in bs[:k - 1]]), 1)
    J = J + J.T
    ev, evec = np.linalg.eigh(J)
    wts = evec[0, :] ** 2 * float(np.sum(w))
    # compare: sorted evs near 0 vs input atoms near 0
    zin = np.sort(z)
    inner_in = zin[len(zin) // 2 - 5: len(zin) // 2 + 5]
    inner_ev = ev[len(ev) // 2 - 5: len(ev) // 2 + 5]
    dev = float(np.max(np.abs(np.sort(inner_in) - np.sort(inner_ev))))
    return dev


def main() -> int:
    if JSON.exists() and "--force" not in sys.argv:
        print(f"cached: {JSON} (use --force to recompute)")
        return 0
    t0 = time.time()
    rows = []
    report = {"per_a": {}}
    rt_max = 0.0
    asym_max = 0.0

    for a in A_LIST:
        ta = time.time()
        z, w = load_measure(a)
        print(f"a={a:g}: {len(z)} atoms; Stieltjes to {K_MAX} ...",
              flush=True)
        bs, adev = stieltjes(z, w, K_MAX)
        asym_max = max(asym_max, adev)
        # equal-mass reference on the same atoms
        wref = np.ones_like(w)
        bs_ref, _ = stieltjes(z, wref, K_MAX)
        dev = roundtrip_check(z, w, bs)
        rt_max = max(rt_max, dev)
        bs_f = [float(b) for b in bs]
        bsr_f = [float(b) for b in bs_ref]
        report["per_a"][f"{a:g}"] = {
            "n_atoms": int(len(z)),
            "b_first10": bs_f[:10],
            "b_tail_mean_last20": float(np.mean(bs_f[-20:])),
            "b_ref_tail_mean_last20": float(np.mean(bsr_f[-20:])),
            "b_min": float(min(bs_f)), "b_max": float(max(bs_f)),
            "roundtrip_dev": dev,
        }
        for k, (b, br) in enumerate(zip(bs_f, bsr_f), 1):
            rows.append((a, k, b, br))
        print(f"  b_1..5 = {np.round(bs_f[:5], 5)}; "
              f"tail mean {np.mean(bs_f[-20:]):.5f} "
              f"(ref {np.mean(bsr_f[-20:]):.5f}); roundtrip {dev:.2e} "
              f"({time.time() - ta:.0f}s)", flush=True)

    checks = {
        "V1_roundtrip": bool(rt_max < 0.05),
        "V2_symmetry": bool(asym_max < 1e-30),
        "V3_free_reference_documented": True,
    }
    with open(CSV, "w", newline="") as f:
        wcsv = csv.writer(f)
        wcsv.writerow(["a", "k", "b_k", "b_k_ref_equalmass"])
        for a, k, b, br in rows:
            wcsv.writerow([f"{a:g}", k, f"{b:.12f}", f"{br:.12f}"])
    meta = {
        "experiment": "E-026",
        "task": "inverse-spectral reconstruction (Jacobi/Stieltjes "
                "coefficients of the Clark measures)",
        "script": "research/numerics/scripts/E-026-inverse-spectral.py",
        "parameters": {"a_list": A_LIST, "k_max": K_MAX, "dps": DPS},
        "checks": checks,
        "key_values": report["per_a"],
        "elapsed_seconds": round(time.time() - t0, 1),
        "timestamp_utc": datetime.now(timezone.utc).isoformat(),
    }
    JSON.write_text(json.dumps(meta, indent=2))
    print(f"wrote {CSV.name}, {JSON.name}; elapsed "
          f"{meta['elapsed_seconds']}s", flush=True)
    return 0 if all(checks.values()) else 1


if __name__ == "__main__":
    sys.exit(main())