chore: organise examples/research-sota/ into 9 thematic folders with READMEs (#744)

User request: organise examples/research-sota/ into folders with READMEs and main overview.

Moved 46 files into 9 thematic folders by thread family + research category:

01-physics-floor/      (R1, R6, R6.1) — bedrock primitives
02-placement/          (R6.2 family, 7 sub-ticks) — antenna placement
03-spatial-intelligence/ (R5, R7) — saliency + mincut
04-rssi/               (R8, R9) — RSSI-only sensing
05-cross-room-reid/    (R3 arc, 3 ticks) — cross-room identity
06-structure-detection/ (R12 arc, 3 ticks) — PABS + closed loop
07-negative-results/   (R13) — productive failure
08-verticals/          (R10, R11) — wildlife + maritime physics
09-quantum-fusion/     (R20.1) — ADR-114 quantum-classical demo

Each folder has its own README.md documenting:
- Scripts + headlines table
- Why this folder bounds / composes with others
- Sample output / honest scope
- Cross-references to related loop notes + ADRs

Main README.md at the top covers:
- Folder map with thread numbers
- Cross-folder dependency graph
- Headline findings table (8 entries)
- Reading order for newcomers (4 scripts in suggested order)
- Honest scope (synthetic-physics caveats)

All git mv operations preserve file history. Total: 46 files moved, 10
new READMEs (main + 9 sub) totalling ~1300 lines of organising
documentation.
This commit is contained in:
rUv
2026-05-22 07:52:57 -04:00
committed by GitHub
parent 759b487a82
commit 4e879bf62a
47 changed files with 0 additions and 0 deletions
@@ -0,0 +1,232 @@
#!/usr/bin/env python3
"""R5 — per-subcarrier input×gradient saliency for the count + pose cogs.
See docs/research/sota-2026-05-22/R5-subcarrier-saliency.md for context.
Usage:
python examples/research-sota/r5_subcarrier_saliency.py \
--paired data/paired/wiflow-p7-1779210883.paired.jsonl \
--model v2/crates/cog-person-count/cog/artifacts/count_v1.safetensors \
--kind count
python examples/research-sota/r5_subcarrier_saliency.py \
--paired data/paired/wiflow-p7-1779210883.paired.jsonl \
--model v2/crates/cog-pose-estimation/cog/artifacts/pose_v1.safetensors \
--kind pose
Output:
<dirname-of-model>/saliency.json per-subcarrier saliency + top-K lists
stdout summary table
Method (per ADR/research note):
S_k = E_samples[ |dL/dx_k| * |x_k| ]
"""
from __future__ import annotations
import argparse
import json
import struct
from pathlib import Path
from typing import Tuple
import numpy as np
N_SUB, N_FRAMES = 56, 20
def load_paired(path: Path, kind: str, max_samples: int | None = None) -> Tuple[np.ndarray, np.ndarray]:
"""Returns (X, y) — X is [N, 56, 20] float32, y depends on kind.
kind="count" → y is [N] int64 in {0..7}
kind="pose" → y is [N, 17, 2] float32 in [0, 1]
"""
csis, ys = [], []
with path.open(encoding="utf-8") as f:
for line in f:
if not line.strip():
continue
d = json.loads(line)
shape = d.get("csi_shape", [N_SUB, N_FRAMES])
if shape != [N_SUB, N_FRAMES]:
continue
csi = np.asarray(d["csi"], dtype=np.float32).reshape(N_SUB, N_FRAMES)
csis.append(csi)
if kind == "count":
ys.append(int(d.get("n_persons_mode", 0)))
elif kind == "pose":
ys.append(np.asarray(d.get("kp", []), dtype=np.float32))
else:
raise ValueError(f"unknown kind: {kind}")
if max_samples and len(csis) >= max_samples:
break
return np.stack(csis), np.asarray(ys, dtype=(np.int64 if kind == "count" else np.float32))
def load_safetensors(path: Path) -> dict[str, np.ndarray]:
"""Pure-python safetensors reader. Returns {name: ndarray}."""
with path.open("rb") as f:
hlen = struct.unpack("<Q", f.read(8))[0]
header = json.loads(f.read(hlen).decode("utf-8"))
out = {}
for name, meta in header.items():
if name == "__metadata__":
continue
start, end = meta["data_offsets"]
shape = meta["shape"]
assert meta["dtype"] == "F32", f"unsupported dtype {meta['dtype']} in {name}"
f.seek(8 + hlen + start)
buf = f.read(end - start)
arr = np.frombuffer(buf, dtype=np.float32).copy().reshape(shape)
out[name] = arr
return out
def conv1d_forward(x: np.ndarray, w: np.ndarray, b: np.ndarray, padding: int, dilation: int) -> np.ndarray:
"""Pure-numpy Conv1d forward. x: [B, Cin, T], w: [Cout, Cin, K]. Returns [B, Cout, T']."""
B, Cin, T = x.shape
Cout, _, K = w.shape
# Pad
xp = np.pad(x, ((0, 0), (0, 0), (padding, padding)), mode="constant")
Tp = xp.shape[2]
# Effective filter span with dilation
eff = (K - 1) * dilation + 1
Tout = Tp - eff + 1
out = np.zeros((B, Cout, Tout), dtype=np.float32)
for k in range(K):
# x_slice shape: [B, Cin, Tout]
x_slice = xp[:, :, k * dilation : k * dilation + Tout]
# w_slice shape: [Cout, Cin]
w_slice = w[:, :, k]
# einsum: B,Cin,T x Cout,Cin → B,Cout,T
out += np.einsum("bct,oc->bot", x_slice, w_slice)
return out + b[None, :, None]
def relu(x: np.ndarray) -> np.ndarray:
return np.maximum(x, 0.0)
def softmax(x: np.ndarray, axis: int = -1) -> np.ndarray:
m = x.max(axis=axis, keepdims=True)
e = np.exp(x - m)
return e / e.sum(axis=axis, keepdims=True)
def forward_count(x: np.ndarray, w: dict[str, np.ndarray]) -> np.ndarray:
"""CountNet forward. x: [B, 56, 20] → probs [B, 8]."""
h = conv1d_forward(x, w["enc.c1.weight"], w["enc.c1.bias"], padding=1, dilation=1)
h = relu(h)
h = conv1d_forward(h, w["enc.c2.weight"], w["enc.c2.bias"], padding=2, dilation=2)
h = relu(h)
h = conv1d_forward(h, w["enc.c3.weight"], w["enc.c3.bias"], padding=4, dilation=4)
h = relu(h)
h = h.mean(axis=2) # [B, 128]
# count head
z = relu(h @ w["count_head.fc1.weight"].T + w["count_head.fc1.bias"])
z = z @ w["count_head.fc2.weight"].T + w["count_head.fc2.bias"]
return softmax(z, axis=-1)
def saliency_input_gradient(
X: np.ndarray,
y: np.ndarray,
weights: dict[str, np.ndarray],
kind: str,
eps: float = 1e-3,
) -> np.ndarray:
"""Per-subcarrier saliency: S_k = E[|dL/dx_k| * |x_k|].
Uses central-difference numerical gradient over each subcarrier (cheap because
we marginalise over the time axis after taking the abs). For a 56-subcarrier
input that's 56 forward passes per sample — slow but exact, and only runs
once per saliency map.
"""
B, N_sub, T = X.shape
saliency = np.zeros(N_sub, dtype=np.float64)
if kind == "count":
# Loss = -log(p_true). Compute baseline log-prob.
for k in range(N_sub):
x_plus = X.copy()
x_plus[:, k, :] += eps
x_minus = X.copy()
x_minus[:, k, :] -= eps
p_plus = forward_count(x_plus, weights)
p_minus = forward_count(x_minus, weights)
# dL/dx ≈ -(log p_plus[y] - log p_minus[y]) / (2*eps)
idx = np.arange(B)
lp_plus = np.log(p_plus[idx, y] + 1e-12)
lp_minus = np.log(p_minus[idx, y] + 1e-12)
grad_k = -(lp_plus - lp_minus) / (2 * eps) # [B]
# |dL/dx_k| * |x_k| — x_k is a vector over time; take its magnitude
x_k_mag = np.abs(X[:, k, :]).mean(axis=1) # [B]
saliency[k] += float((np.abs(grad_k) * x_k_mag).mean())
else:
raise NotImplementedError("pose kind not yet wired — count first")
return saliency
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--paired", required=True)
parser.add_argument("--model", required=True)
parser.add_argument("--kind", choices=["count", "pose"], default="count")
parser.add_argument("--max-samples", type=int, default=128,
help="Cap on samples used for saliency (saliency cost is O(N_sub × samples × eps_passes))")
parser.add_argument("--out", default=None,
help="Output JSON path; defaults to <model_dir>/saliency.json")
args = parser.parse_args()
print(f"Loading paired data from {args.paired} (kind={args.kind})")
X, y = load_paired(Path(args.paired), kind=args.kind, max_samples=args.max_samples)
print(f" X: {X.shape}, y: {y.shape}")
if args.kind == "count":
unique, counts = np.unique(y, return_counts=True)
print(f" label distribution: {dict(zip(unique.tolist(), counts.tolist()))}")
# Standardise (per-subcarrier z-score using THIS subset's stats — saliency is
# invariant to affine input transforms in the limit of small eps).
mu = X.mean(axis=(0, 2), keepdims=True)
sd = X.std(axis=(0, 2), keepdims=True) + 1e-6
X_norm = (X - mu) / sd
print(f"Loading weights from {args.model}")
weights = load_safetensors(Path(args.model))
print(f" loaded {len(weights)} tensors: {sorted(list(weights.keys()))[:6]}...")
print(f"Computing input×gradient saliency over {X.shape[0]} samples × 56 subcarriers...")
saliency = saliency_input_gradient(X_norm, y, weights, kind=args.kind, eps=1e-3)
order = np.argsort(saliency)[::-1] # descending
top_k = {k: order[:k].tolist() for k in (8, 16, 32)}
out = {
"kind": args.kind,
"model": str(args.model),
"n_samples": int(X.shape[0]),
"saliency_per_subcarrier": saliency.tolist(),
"ranking_high_to_low": order.tolist(),
"top_k_subcarriers": top_k,
"saliency_summary": {
"min": float(saliency.min()),
"max": float(saliency.max()),
"mean": float(saliency.mean()),
"std": float(saliency.std()),
"max_to_mean_ratio": float(saliency.max() / max(saliency.mean(), 1e-12)),
},
}
out_path = Path(args.out) if args.out else Path(args.model).parent / "saliency.json"
out_path.write_text(json.dumps(out, indent=2))
print(f"\nWrote {out_path}")
print(f"\nTop 8 subcarriers (most influential):")
for rank, idx in enumerate(order[:8]):
print(f" #{rank + 1}: subcarrier {int(idx):2d} saliency={saliency[idx]:.4f}")
print(f"\nMax/mean ratio: {out['saliency_summary']['max_to_mean_ratio']:.2f}× "
f"(higher = signal more concentrated in a few subcarriers)")
if __name__ == "__main__":
main()
@@ -0,0 +1,208 @@
#!/usr/bin/env python3
"""R7 — multi-link consistency detection via Stoer-Wagner-style mincut.
See docs/research/sota-2026-05-22/R7-multilink-consistency.md.
Premise: in a multi-node CSI mesh, all nodes observe the same physical
scene through slightly different channels. Their per-window CSI features
should cluster tightly under a similarity metric. If one node is
compromised (spoofed CSI, replay attack, jamming-induced corruption), its
features fall outside the cluster — and the mincut of the inter-node
similarity graph isolates it cleanly.
This demo:
1. Synthesises 4 "honest" CSI windows from one underlying scene + per-node
Gaussian noise (realistic multipath variability).
2. Synthesises 1 "adversarial" CSI window via three attack modes:
(a) replay — paste in a stale window from earlier
(b) shift — add a constant offset to every subcarrier
(c) noise — pure white noise of the same magnitude as honest CSI
3. Builds a 5×5 cross-node CSI cosine-similarity matrix.
4. Solves Stoer-Wagner mincut on the resulting graph.
5. Reports whether the mincut partition isolates the adversarial node.
No framework deps — pure NumPy.
Usage:
python examples/research-sota/r7_multilink_consistency.py \
--paired data/paired/wiflow-p7-1779210883.paired.jsonl
"""
from __future__ import annotations
import argparse
import json
from pathlib import Path
import numpy as np
N_SUB, N_FRAMES = 56, 20
def load_one_window(path: Path, idx: int = 0) -> np.ndarray:
"""Pull one [56, 20] CSI window from the paired data — the scene we'll synthesise around."""
with path.open(encoding="utf-8") as f:
for i, line in enumerate(f):
if i < idx:
continue
d = json.loads(line)
shape = d.get("csi_shape", [N_SUB, N_FRAMES])
if shape == [N_SUB, N_FRAMES]:
return np.asarray(d["csi"], dtype=np.float32).reshape(N_SUB, N_FRAMES)
return None
return None
def synth_honest_nodes(base: np.ndarray, n_nodes: int = 4, noise_db: float = 6.0, seed: int = 42):
"""`n_nodes` honest observers — each sees the base scene through independent multipath
(modelled as additive Gaussian on the per-subcarrier amplitudes at `noise_db` below signal)."""
rng = np.random.default_rng(seed)
sigma = base.std() * 10 ** (-noise_db / 20.0)
return np.stack([base + rng.normal(0, sigma, size=base.shape).astype(np.float32) for _ in range(n_nodes)])
def synth_adversarial(base: np.ndarray, mode: str, replay_window: np.ndarray | None = None, seed: int = 7):
"""One adversarial observer. `mode` ∈ {replay, shift, noise}."""
rng = np.random.default_rng(seed)
if mode == "replay":
if replay_window is None:
raise ValueError("replay needs a stale window")
# Stale window with a tiny perturbation to look "fresh"
return replay_window + rng.normal(0, 0.01, size=base.shape).astype(np.float32)
if mode == "shift":
return base + 3.0 * base.std() # constant offset — gives away the attack
if mode == "noise":
return rng.normal(base.mean(), base.std(), size=base.shape).astype(np.float32)
raise ValueError(f"unknown adversarial mode: {mode}")
def cosine_sim_matrix(windows: np.ndarray) -> np.ndarray:
"""Pairwise cosine similarity on flattened windows. Returns [N, N] matrix."""
flat = windows.reshape(windows.shape[0], -1)
norms = np.linalg.norm(flat, axis=1, keepdims=True) + 1e-9
normalized = flat / norms
return normalized @ normalized.T
def stoer_wagner_mincut(W: np.ndarray) -> tuple[float, list[int]]:
"""Classical Stoer-Wagner mincut. Input: symmetric [N, N] non-negative weights.
Returns: (cut_value, partition_a_node_indices)
The algorithm:
while G has more than one node:
do a minimum-cut-phase: find the order in which nodes are added
the last node added is one side of a candidate cut; the rest is the other side
merge the last two nodes into one super-node, accumulate their weights
track the minimum candidate cut across all phases
"""
n = W.shape[0]
nodes = [{i} for i in range(n)] # start with each node a singleton
W = W.astype(np.float64).copy()
best_cut = np.inf
best_partition_b = None
while len(nodes) > 1:
# minimum-cut-phase
n_left = len(nodes)
A = [0] # start anywhere
in_A = np.zeros(n_left, dtype=bool); in_A[0] = True
weights_to_A = W[:, 0].copy()
weights_to_A[0] = -1
last, second_last = 0, 0
for _ in range(n_left - 1):
# pick the not-yet-in-A node most tightly connected to A
cand = int(np.argmax(np.where(in_A, -1, weights_to_A)))
second_last = last
last = cand
in_A[cand] = True
A.append(cand)
# update weights — add cand's edges
weights_to_A = np.where(in_A, -1, weights_to_A + W[:, cand])
# cut-of-the-phase = sum of edges from `last` to all others
cut_val = float((W[last, :].sum() - W[last, last]))
if cut_val < best_cut:
best_cut = cut_val
best_partition_b = nodes[last].copy()
# merge last + second_last
merged = nodes[last] | nodes[second_last]
# merge their rows/cols
W[second_last, :] += W[last, :]
W[:, second_last] += W[:, last]
W[second_last, second_last] = 0
# remove `last`
keep = [i for i in range(n_left) if i != last]
W = W[np.ix_(keep, keep)]
nodes = [merged if i == second_last else nodes[i] for i in keep]
partition_b = sorted(best_partition_b) if best_partition_b else []
return best_cut, partition_b
def run_scenario(base: np.ndarray, replay_window: np.ndarray, mode: str, n_honest: int = 4):
"""Run one adversarial scenario, return diagnostic info."""
honest = synth_honest_nodes(base, n_nodes=n_honest, noise_db=6.0)
adv = synth_adversarial(base, mode=mode, replay_window=replay_window)
windows = np.concatenate([honest, adv[None, ...]], axis=0) # [n_honest + 1, 56, 20]
adv_idx = n_honest # last node is the adversarial one
sim = cosine_sim_matrix(windows)
# Convert similarity → edge weight. Mincut on similarity finds the
# minimum-similarity partition, which is the *most-suspicious* split.
# Use (1 - sim) as the weight if we want to minimise dissimilarity, but
# the natural framing is: mincut over similarity-weighted graph isolates
# the node least-similar to the rest.
np.fill_diagonal(sim, 0.0)
cut_val, partition_b = stoer_wagner_mincut(sim)
detected = (set(partition_b) == {adv_idx}) or (set(range(len(windows))) - set(partition_b) == {adv_idx})
return {
"mode": mode,
"n_honest": n_honest,
"adv_idx": adv_idx,
"sim_matrix": sim.round(4).tolist(),
"mincut_value": float(cut_val),
"partition_b": partition_b,
"adv_isolated": bool(detected),
}
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--paired", required=True)
parser.add_argument("--out", default="examples/research-sota/r7_multilink_consistency_results.json")
args = parser.parse_args()
base = load_one_window(Path(args.paired), idx=10)
stale = load_one_window(Path(args.paired), idx=900)
if base is None or stale is None:
raise SystemExit("need at least 901 samples in the paired file")
results = {}
for mode in ["replay", "shift", "noise"]:
scenario = run_scenario(base, stale, mode=mode, n_honest=4)
results[mode] = scenario
print(f"\n=== adversarial mode: {mode} ===")
print(f" mincut value: {scenario['mincut_value']:.4f}")
print(f" partition B (less-similar side): {scenario['partition_b']}")
print(f" adversarial node isolated? {'YES' if scenario['adv_isolated'] else 'no'}")
n_detected = sum(1 for r in results.values() if r["adv_isolated"])
summary = {
"n_scenarios": len(results),
"n_detected": n_detected,
"detection_rate": n_detected / len(results),
}
print(f"\n=== summary ===")
print(f" detection rate: {n_detected}/{len(results)} = {summary['detection_rate']:.0%}")
out_path = Path(args.out)
out_path.parent.mkdir(parents=True, exist_ok=True)
out_path.write_text(json.dumps({"summary": summary, "scenarios": results}, indent=2))
print(f"\nWrote {out_path}")
if __name__ == "__main__":
main()
@@ -0,0 +1,150 @@
{
"summary": {
"n_scenarios": 3,
"n_detected": 3,
"detection_rate": 1.0
},
"scenarios": {
"replay": {
"mode": "replay",
"n_honest": 4,
"adv_idx": 4,
"sim_matrix": [
[
0.0,
0.9218999743461609,
0.9277999997138977,
0.9269000291824341,
0.863099992275238
],
[
0.9218999743461609,
0.0,
0.9218999743461609,
0.9254000186920166,
0.8618999719619751
],
[
0.9277999997138977,
0.9218999743461609,
0.0,
0.9291999936103821,
0.8615999817848206
],
[
0.9269000291824341,
0.9254000186920166,
0.9291999936103821,
0.0,
0.864799976348877
],
[
0.863099992275238,
0.8618999719619751,
0.8615999817848206,
0.864799976348877,
0.0
]
],
"mincut_value": 3.451315999031067,
"partition_b": [
4
],
"adv_isolated": true
},
"shift": {
"mode": "shift",
"n_honest": 4,
"adv_idx": 4,
"sim_matrix": [
[
0.0,
0.9218999743461609,
0.9277999997138977,
0.9269000291824341,
0.8944000005722046
],
[
0.9218999743461609,
0.0,
0.9218999743461609,
0.9254000186920166,
0.8917999863624573
],
[
0.9277999997138977,
0.9218999743461609,
0.0,
0.9291999936103821,
0.8942999839782715
],
[
0.9269000291824341,
0.9254000186920166,
0.9291999936103821,
0.0,
0.8917999863624573
],
[
0.8944000005722046,
0.8917999863624573,
0.8942999839782715,
0.8917999863624573,
0.0
]
],
"mincut_value": 3.5724358558654785,
"partition_b": [
4
],
"adv_isolated": true
},
"noise": {
"mode": "noise",
"n_honest": 4,
"adv_idx": 4,
"sim_matrix": [
[
0.0,
0.9218999743461609,
0.9277999997138977,
0.9269000291824341,
0.6425999999046326
],
[
0.9218999743461609,
0.0,
0.9218999743461609,
0.9254000186920166,
0.6444000005722046
],
[
0.9277999997138977,
0.9218999743461609,
0.0,
0.9291999936103821,
0.6389999985694885
],
[
0.9269000291824341,
0.9254000186920166,
0.9291999936103821,
0.0,
0.6326000094413757
],
[
0.6425999999046326,
0.6444000005722046,
0.6389999985694885,
0.6326000094413757,
0.0
]
],
"mincut_value": 2.5585585832595825,
"partition_b": [
4
],
"adv_isolated": true
}
}
}