# -*- coding: utf-8 -*- """Does an orthogonal unit codebook recover the shortfall? diag_interference shows the gap to the ideal M-ary receiver is not multi-user interference but the geometry of the trained unit codebook, whose Gram matrix carries a root-mean-square off-diagonal of 0.45 where an orthogonal set would carry zero. Vu = L = 16 admits an exactly orthogonal set, so this measures what installing one buys. Two orthogonal sets are tried, because the choice is not free. The Walsh-Hadamard set collides with the keys: the rows are closed under the elementwise product, so masking a Hadamard codeword by a Hadamard key returns another Hadamard codeword and every user ends up with the same candidate set. A random orthogonal set carries no such group structure, and masking by a unit-modulus key preserves its orthogonality exactly. """ import sys from pathlib import Path import torch sys.path.insert(0, str(Path(__file__).resolve().parent)) import sse_lib as L from sse_lib import DEVICE, SSE from exp_full import hadamard, base_keys from diag_interference import ser SNR = [0.0, 10.0, 20.0] FRAMES = 400_000 def fixed_model(B, P=4, vu=16, d=64, U=4): L.set_seed(1) m = SSE(P=P, vu=vu, d=d, users=U).to(DEVICE) with torch.no_grad(): m.B.copy_(B.to(DEVICE)) m.W.copy_(base_keys(U, d // P).to(DEVICE)) m.calibrate_power() return m def hadamard_book(vu=16, Lp=16): B = torch.zeros(vu, Lp) B[:, :vu] = torch.tensor(hadamard(vu).copy(), dtype=torch.float32) return B def random_ortho_book(vu=16, Lp=16, seed=7): g = torch.Generator().manual_seed(seed) A = torch.randn(Lp, Lp, generator=g) Q, _ = torch.linalg.qr(A) return Q[:vu].contiguous() def report(name, m): with torch.no_grad(): Bn = m.unit_codebook() G = Bn @ Bn.T off = (G - torch.diag(torch.diag(G))).abs().max() row = [name, "%.2e" % off] for s in SNR: row.append("%.4f" % ser(m, s, FRAMES)) print("%-22s %-10s %-9s %-9s %-9s" % tuple(row)) def main(): print("%-22s %-10s %-9s %-9s %-9s" % ("unit codebook", "max|off|", "0 dB", "10 dB", "20 dB")) report("Walsh-Hadamard", fixed_model(hadamard_book())) report("random orthogonal", fixed_model(random_ortho_book())) print("%-22s %-10s %-9s %-9s %-9s" % ("trained (paper)", "0.887", "0.8822", "0.2576", "0.0307")) print("%-22s %-10s %-9s %-9s %-9s" % ("OMA, resource matched", "-", "%.4f" % L.oma_ser([0.0])[0], "%.4f" % L.oma_ser([10.0])[0], "%.4f" % L.oma_ser([20.0])[0])) def solo_check(): """Splitting each candidate set from the superposition it must live in. Orthogonal codewords are ideal for one user alone and are what the single-user bound assumes, but the masked sets of different users are then far from orthogonal to each other.""" print() print("%-22s %-12s %-12s" % ("unit codebook", "solo 10 dB", "4-user 10 dB")) for name, B in (("random orthogonal", random_ortho_book()), ("trained (retrain)", None)): if B is None: from exp_full import main_model m = main_model() else: m = fixed_model(B) print("%-22s %-12.4f %-12.4f" % (name, ser(m, 10.0, FRAMES, solo=True), ser(m, 10.0, FRAMES, solo=False))) print("single-user ideal M-ary bound (separate MC): 0.1986") if __name__ == "__main__": main() solo_check()