"""EXTRA (not in the plan): HNSW recall with an explicit EF_RUNTIME, same data and queries as c2_search.py."""
import redis, numpy as np, json, sys
r = redis.Redis(port=6380, protocol=2)
N, D, Q, K = 10000, 64, 100, 10
rng = np.random.default_rng(42); X = rng.standard_normal((N, D)).astype(np.float32); QV = rng.standard_normal((Q, D)).astype(np.float32)
Xn = X / np.linalg.norm(X, axis=1, keepdims=True); Qn = QV / np.linalg.norm(QV, axis=1, keepdims=True)
truth = np.argsort(-(Qn @ Xn.T), axis=1)[:, :K]
out = {}
for ef in (10, 50, 100, 200, 500):
    hits = 0
    for qi in range(Q):
        res = r.execute_command("FT.SEARCH", "idx_hnsw", f"*=>[KNN {K} @vec $q EF_RUNTIME {ef}]", "PARAMS", "2", "q", QV[qi].tobytes(), "NOCONTENT", "LIMIT", "0", str(K), "DIALECT", "2")
        ids = [x[b"id"].decode() for x in res[b"results"]] if isinstance(res, dict) else [x.decode() for x in res[1:]]
        hits += len({int(i.split(":")[1]) for i in ids} & set(truth[qi].tolist()))
    out[f"EF_RUNTIME {ef}"] = round(hits / (Q * K), 4)
json.dump(out, open(sys.argv[1], "w"), indent=1); print(out)
