SPB Git

spb/wp29_uqo

Public
3.0 KB · 71 lines python
1"""F5-conf-03: counterexample to 'sum of normals is normal' (prop. A) and check of B.2Run from workspace root: ~/wp29/venv/bin/python out/analysis.py3Construction: X ~ N(0,1), S ~ Rademacher(+-1 w.p. 1/2) independent of X, Y = S*X.4Y ~ N(0,1) (X symmetric, S independent); X+Y = (1+S)X equals 0 w.p. 1/2 and 2X otherwise5-> has an atom at 0 yet Var = 2 > 0, so it is neither non-degenerate normal nor constant.6"""7import json, os8import numpy as np, pandas as pd9from scipy import stats1011ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))12D = os.path.join(ROOT, "data"); O = os.path.join(ROOT, "out")1314props = pd.read_csv(os.path.join(D, "propositions.csv"))15design = pd.read_csv(os.path.join(D, "design.csv"))16par = dict(zip(design["parameter"], design["value"]))17seed, n = int(par["seed"]), int(par["n"])18data_issues = []19assert set(props["id"]) == {"A", "B"}, "unexpected proposition ids"2021rng = np.random.default_rng(seed)22x = rng.standard_normal(n)23s = rng.choice(np.array([-1.0, 1.0]), size=n)24y = s * x25z = x + y26pd.DataFrame({"x": x, "y": y}).to_csv(os.path.join(O, "counterexample.csv"), index=False)2728def ks_fit(v):29    return float(stats.kstest(v, "norm", args=(v.mean(), v.std(ddof=1))).statistic)3031cv = {32    "construction": "X ~ N(0,1); S ~ Rademacher (P(S=1)=P(S=-1)=1/2) independent of X; Y = S*X. "33                    "Then Y ~ N(0,1) but X+Y = (1+S)X is 0 with prob. 1/2 and 2X otherwise (atom at 0, Var 2).",34    "n": int(n), "seed": seed,35    "mean_x": float(x.mean()), "sd_x": float(x.std(ddof=1)),36    "mean_y": float(y.mean()), "sd_y": float(y.std(ddof=1)),37    "mean_sum": float(z.mean()), "sd_sum": float(z.std(ddof=1)),38    "ks_sum_vs_normal": ks_fit(z),39}40# supplementary diagnostics (marginals vs fitted normal, atom share, independence-based baseline for B)41supp = {42    "ks_x_vs_normal": ks_fit(x), "ks_y_vs_normal": ks_fit(y),43    "share_sum_exactly_zero": float(np.mean(z == 0.0)),44    "ks_critical_value_5pct_approx": float(1.358 / np.sqrt(n)),45    "corr_xy": float(np.corrcoef(x, y)[0, 1]),46}47rng_b = np.random.default_rng(seed + 1)  # separate stream for the B illustration only48xb, yb = rng_b.standard_normal(n), rng_b.standard_normal(n)49baseline = {"baseline_b_indep_ks_sum_vs_normal": ks_fit(xb + yb),50            "baseline_b_indep_sd_sum": float((xb + yb).std(ddof=1)),51            "baseline_b_seed": seed + 1}5253res = {54    "task_id": "F5-conf-03",55    "statement_true": False,           # by proof in out/argument.md56    "counterexample_provided": True,57    "counterexample_values": cv,58    "statement_b_true": True,          # by proof (characteristic functions) in out/argument.md59    "feasibility": "complete",60    "feasibility_reason": None,61    "data_issues": data_issues,62    "n_input_rows": {"propositions.csv": int(len(props)), "design.csv": int(len(design))},63    "n_analysed": int(n),64    "random_seed": seed,65    "supplementary_diagnostics": supp,66    **baseline,67}68with open(os.path.join(O, "results.json"), "w") as f:69    json.dump(res, f, indent=2)70print(json.dumps(res, indent=2))71
Files · main
Menu

Theme