File size: 4,491 Bytes
515b676
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
"""Aggregate the sweeps into slopes, ratios and the numbers quoted in pages/."""
import glob
import json
import os
import numpy as np
import rdpg

R = 5


def load(tag):
    with open(f"outputs/main_{tag}.json") as f:
        return json.load(f)


def agg(tag):
    d = load(tag)
    runs = d["runs"]
    ns = sorted({r["n"] for r in runs})
    by = {n: [r for r in runs if r["n"] == n] for n in ns}
    out = {"tag": tag, "ngrid": ns, "reps": [len(by[n]) for n in ns], "dims": d["dims"]}

    def col(f):
        return [float(np.mean([f(r) for r in by[n]])) for n in ns]

    def colmed(f):
        return [float(np.median([f(r) for r in by[n]])) for n in ns]

    out["err_mean"] = {str(dd): col(lambda r, dd=dd: r["err"][str(dd)]) for dd in d["dims"]}
    out["err_se"] = {str(dd): [float(np.std([r["err"][str(dd)] for r in by[n]], ddof=1)
                                     / np.sqrt(len(by[n]))) for n in ns] for dd in d["dims"]}
    out["base_mean"] = col(lambda r: r["base_2inf"])
    out["trail_mean"] = {str(dd): col(lambda r, dd=dd: r["trail_2inf"][str(dd)])
                         for dd in d["dims"] if dd > R}
    out["deloc_all_mean"] = col(lambda r: r["deloc_max_all"])
    out["deloc_all_med"] = colmed(lambda r: r["deloc_max_all"])
    out["deloc_rp1_mean"] = col(lambda r: r["deloc_max_rp1"])
    out["deloc_rp1_med"] = colmed(lambda r: r["deloc_max_rp1"])
    out["signal_2inf_mean"] = col(lambda r: r["signal_2inf"])
    out["min_decomp_slack"] = float(min(min(r["decomp_slack"].values()) for r in runs))
    out["s_hat_mean"] = [float(np.mean([r["s_hat"][i] for r in by[ns[-1]]])) for i in range(8)]

    lg = np.log(np.array(ns, float))
    out["slopes"] = {k: rdpg.loglog_slope(ns, v) for k, v in out["err_mean"].items()}
    out["slopes_trail"] = {k: rdpg.loglog_slope(ns, v) for k, v in out["trail_mean"].items()}
    out["slope_base"] = rdpg.loglog_slope(ns, out["base_mean"])
    out["slope_deloc_all"] = rdpg.loglog_slope(ns, out["deloc_all_mean"])
    out["slope_deloc_rp1"] = rdpg.loglog_slope(ns, out["deloc_rp1_mean"])
    # remove the sqrt(log n) factor that delocalised max-entry statistics carry
    out["slope_deloc_rp1_delogged"] = rdpg.loglog_slope(
        ns, np.array(out["deloc_rp1_mean"]) / np.sqrt(lg))
    out["deloc_rp1_over_sqrt2logn"] = [
        float(v / np.sqrt(2 * np.log(n) / n)) for v, n in zip(out["deloc_rp1_mean"], ns)]
    out["deloc_all_over_sqrt4logn"] = [
        float(v / np.sqrt(4 * np.log(n) / n)) for v, n in zip(out["deloc_all_mean"], ns)]
    out["theorem31_bound_gamma0"] = [float(R ** 2 * np.log(n) ** 4 / np.sqrt(n)) for n in ns]
    out["theorem31_bound_holds"] = bool(all(
        v <= b for v, b in zip(out["deloc_all_mean"], out["theorem31_bound_gamma0"])))
    # over-specification: strip the predicted sqrt(log n)
    out["slopes_delogged"] = {k: rdpg.loglog_slope(ns, np.array(v) / np.sqrt(lg))
                              for k, v in out["err_mean"].items()}
    out["slopes_trail_delogged"] = {k: rdpg.loglog_slope(ns, np.array(v) / np.sqrt(lg))
                                    for k, v in out["trail_mean"].items()}
    # predicted trailing-term constant sqrt(4 sigma k log n) n^{-1/4} check
    return out


if __name__ == "__main__":
    tags = sorted(os.path.basename(p)[5:-5] for p in glob.glob("outputs/main_*.json"))
    A = {t: agg(t) for t in tags}
    with open("outputs/analysis.json", "w") as f:
        json.dump(A, f, indent=1)
    for t in tags:
        a = A[t]
        print(f"\n===== {t}  n={a['ngrid']} reps={a['reps']}")
        print("  d :  slope  R2   | delogged slope |  err(n_max)")
        for dd in a["dims"]:
            s = a["slopes"][str(dd)]
            sd = a["slopes_delogged"][str(dd)]
            print(f"  {dd:2d}: {s[0]:+.3f} {s[2]:.3f} | {sd[0]:+.3f} {sd[2]:.3f} |"
                  f" {a['err_mean'][str(dd)][-1]:.4f}")
        print(f"  base slope {a['slope_base'][0]:+.3f} (R2 {a['slope_base'][2]:.3f})"
              f"  min decomposition slack {a['min_decomp_slack']:.3e}")
        print(f"  deloc(all>r) slope {a['slope_deloc_all'][0]:+.3f}"
              f"  ratio to sqrt(4 log n/n): {[round(x,3) for x in a['deloc_all_over_sqrt4logn']]}")
        print(f"  deloc(r+1)  slope {a['slope_deloc_rp1'][0]:+.3f}"
              f" delogged {a['slope_deloc_rp1_delogged'][0]:+.3f}"
              f"  ratio to sqrt(2 log n/n): {[round(x,3) for x in a['deloc_rp1_over_sqrt2logn']]}")
        print(f"  s_hat(n_max)[:8] {[round(x,1) for x in a['s_hat_mean']]}")