Add check_consistency.py, correct two stale figures in comments
check_consistency.py asserts every headline number against its raw CSV, so a stale quoted value fails loudly instead of surviving a revision. It skips the manuscript-side assertions when main.tex is absent, which is the case in this package. The blind-versus-permutation agreement is 0.002, not 0.0015, and the resource-matched OMA is undefined below L=16 rather than wherever 16/L is not an integer.
This commit is contained in:
@@ -0,0 +1,93 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Final consistency check: every headline number vs its raw CSV."""
|
||||||
|
import csv
|
||||||
|
import math
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
base = Path(__file__).resolve().parents[1]
|
||||||
|
# The manuscript is not part of the reproducibility package, so the
|
||||||
|
# tex-side assertions are skipped when it is absent and the data-side
|
||||||
|
# assertions still run.
|
||||||
|
_tex_path = base / "main.tex"
|
||||||
|
HAVE_TEX = _tex_path.exists()
|
||||||
|
tex = _tex_path.read_text(encoding="utf-8") if HAVE_TEX else ""
|
||||||
|
|
||||||
|
|
||||||
|
def rows(name):
|
||||||
|
with open(base / "data" / name) as f:
|
||||||
|
return list(csv.DictReader(f))
|
||||||
|
|
||||||
|
|
||||||
|
def col(name, k):
|
||||||
|
return [float(r[k]) for r in rows(name) if r[k] != "nan"]
|
||||||
|
|
||||||
|
|
||||||
|
ok = True
|
||||||
|
|
||||||
|
|
||||||
|
def chk(label, cond, detail, needs_tex=False):
|
||||||
|
global ok
|
||||||
|
if needs_tex and not HAVE_TEX:
|
||||||
|
print(" SKIP " + label + " :: main.tex not in this package")
|
||||||
|
return
|
||||||
|
print((" PASS " if cond else " FAIL ") + label + " :: " + detail)
|
||||||
|
if not cond:
|
||||||
|
ok = False
|
||||||
|
|
||||||
|
|
||||||
|
print("headline numbers vs raw data")
|
||||||
|
|
||||||
|
# 1.27x key-length ratio
|
||||||
|
k = rows("sec_keylen.csv")
|
||||||
|
r64 = [x for x in k if int(x["L"]) == 64][0]
|
||||||
|
ratio = float(r64["oma"]) / float(r64["legit_ser"])
|
||||||
|
chk("key-length ratio 1.27", round(ratio, 2) == 1.27, "%.4f" % ratio)
|
||||||
|
chk("1.27 in tex", tex.count("1.27") >= 2, "%d occurrences" % tex.count("1.27"), needs_tex=True)
|
||||||
|
|
||||||
|
# blind-jammer gap
|
||||||
|
g = col("sec_jam_gap.csv", "gap_db")
|
||||||
|
chk("gap 7.4-8.1 dB", round(min(g), 1) == 7.4 and round(max(g), 1) == 8.1,
|
||||||
|
"%.3f to %.3f" % (min(g), max(g)))
|
||||||
|
chk("no stale 8.5 dB", "8.5$~dB" not in tex, "searched tex", needs_tex=True)
|
||||||
|
lin = (10 ** (min(g) / 10), 10 ** (max(g) / 10))
|
||||||
|
chk("about six times power", lin[0] < 6.5 and lin[1] > 5.5,
|
||||||
|
"%.2f to %.2f" % lin)
|
||||||
|
|
||||||
|
# blind vs permutation
|
||||||
|
j = rows("sec_jam_cmp.csv")
|
||||||
|
dmax = max(abs(float(r["blind"]) - float(r["perm_blind"])) for r in j)
|
||||||
|
chk("within 0.002", dmax <= 0.002, "%.5f" % dmax)
|
||||||
|
chk("no stale 0.0015 in jamming", "$0.0015$ of the proposed" not in tex, "ok", needs_tex=True)
|
||||||
|
|
||||||
|
# brute force
|
||||||
|
b = rows("sec_brute_cmp.csv")
|
||||||
|
sm = float(b[-1]["ser_mask"])
|
||||||
|
chk("brute 0.76 both places", tex.count("$0.76$") >= 2, "%.4f measured" % sm, needs_tex=True)
|
||||||
|
chk("no stale 0.75 in summary",
|
||||||
|
"$0.75$ after $10^{6}$" not in tex, "summary row", needs_tex=True)
|
||||||
|
|
||||||
|
# refresh
|
||||||
|
rs = {r["scheme"]: r for r in rows("refresh_summary.csv")}
|
||||||
|
chk("refresh 64.8 bits",
|
||||||
|
round(float(rs["Invariant"]["entropy_bits"]), 1) == 64.8,
|
||||||
|
"%.3f" % float(rs["Invariant"]["entropy_bits"]))
|
||||||
|
chk("fixed key 15.0 bits",
|
||||||
|
round(float(rs["None (fixed key)"]["entropy_bits"]), 1) == 15.0,
|
||||||
|
"%.4f" % float(rs["None (fixed key)"]["entropy_bits"]))
|
||||||
|
|
||||||
|
# permutation KPA
|
||||||
|
pk = rows("pkpa.csv")
|
||||||
|
p6 = float([r for r in pk if r["n_frames"] == "6"][0]["eve_ser"])
|
||||||
|
chk("perm KPA at N=6 near 0.303", abs(p6 - 0.303) < 0.005, "%.4f" % p6)
|
||||||
|
|
||||||
|
# abstract
|
||||||
|
a = (tex.split(r"\begin{abstract}")[1].split(r"\end{abstract}")[0].strip()
|
||||||
|
if HAVE_TEX else "")
|
||||||
|
w = len(re.split(r"\s+", a)) if a else 0
|
||||||
|
chk("abstract <= 250 words", w <= 250, "%d words" % w, needs_tex=True)
|
||||||
|
chk("abstract has no abbreviations",
|
||||||
|
not re.findall(r"\b[A-Z]{2,}\b", a), str(re.findall(r"\b[A-Z]{2,}\b", a)), needs_tex=True)
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("ALL CONSISTENT" if ok else "INCONSISTENCIES FOUND")
|
||||||
@@ -136,7 +136,7 @@ def fig_snr():
|
|||||||
|
|
||||||
def fig_keylen():
|
def fig_keylen():
|
||||||
"""The OMA reference is the resource-matched one of oma_ser_keylen,
|
"""The OMA reference is the resource-matched one of oma_ser_keylen,
|
||||||
which is undefined at key lengths where 16/L is not an integer; those
|
which is undefined below L=16 unless 16/L is an integer; those
|
||||||
rows carry nan and are skipped."""
|
rows carry nan and are skipped."""
|
||||||
r = load("sec_keylen.csv")
|
r = load("sec_keylen.csv")
|
||||||
x = col(r, "L", int)
|
x = col(r, "L", int)
|
||||||
@@ -169,7 +169,7 @@ def fig_jam():
|
|||||||
markevery=me, label=LBL["mask"] + ", matched")
|
markevery=me, label=LBL["mask"] + ", matched")
|
||||||
ax.plot(x, col(r, "oma_targeted"), color=C_PUB, marker="^", ls=":",
|
ax.plot(x, col(r, "oma_targeted"), color=C_PUB, marker="^", ls=":",
|
||||||
markevery=me, label=LBL["oma"] + ", targeted")
|
markevery=me, label=LBL["oma"] + ", targeted")
|
||||||
# the two blind curves agree to 0.0015; deliberate layering
|
# the two blind curves agree to 0.002; deliberate layering
|
||||||
ax.plot(x, col(r, "blind"), color=C_LEGIT, marker="o", ls="-",
|
ax.plot(x, col(r, "blind"), color=C_LEGIT, marker="o", ls="-",
|
||||||
markevery=me, label=LBL["mask"] + ", blind", **UNDER)
|
markevery=me, label=LBL["mask"] + ", blind", **UNDER)
|
||||||
ax.plot(x, col(r, "perm_blind"), color=C_EVE, marker="s", ls="-.",
|
ax.plot(x, col(r, "perm_blind"), color=C_EVE, marker="s", ls="-.",
|
||||||
|
|||||||
Reference in New Issue
Block a user