v2 design: independent masks + affinity-aware Wiener demultiplexer
Redesign after the independent-mask dominance finding: the affinity now parameterizes the receiver (closed-form Wiener) instead of the mask ensemble. New Theorem 1 (spectral closed form), floors sqrt(1-b^2)/2 vs 1/2, full-cooperation bound with equality at b=1. GPU (torch) Monte Carlo backend, decision-directed SIC baseline, TikZ block diagram source, verification suite V1-V11.
This commit is contained in:
@@ -10,66 +10,78 @@ This repository contains the simulation code, the raw result data, and
|
|||||||
the figure files behind every numerical claim in the paper. It is
|
the figure files behind every numerical claim in the paper. It is
|
||||||
private during peer review and will be made public upon publication.
|
private during peer review and will be made public upon publication.
|
||||||
|
|
||||||
|
The design under test: each user applies an independent Haar
|
||||||
|
orthogonal mask, and the receiver runs a matched filter followed by
|
||||||
|
the closed-form affinity-aware Wiener demultiplexer, which harvests
|
||||||
|
the coherent interference component that the measured pairwise
|
||||||
|
affinity `beta` predicts. The affinity-blind reference sets `beta = 0`
|
||||||
|
in the same filter.
|
||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
| Folder | Contents |
|
| Folder | Contents |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `code/` | Simulation and plotting scripts (Python, CPU only) |
|
| `code/` | Simulation and plotting scripts (Python) |
|
||||||
| `data/` | Raw results written by the scripts, one CSV per experiment |
|
| `data/` | Raw results written by the scripts, one CSV per experiment |
|
||||||
| `fig/` | Figure PDFs included in the manuscript |
|
| `fig/` | Figure PDFs included in the manuscript (`block_diagram_src.tex` is the TikZ source of Fig. 1) |
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
Python 3.10 or later with `numpy` and `matplotlib`. The Fig. 4
|
Python 3.10 or later with `numpy` and `matplotlib`. The Monte Carlo
|
||||||
experiment additionally uses `torch` (CPU build is sufficient). No GPU
|
experiments in `revision_sims_gpu.py`, `fig_real_merged.py`, and
|
||||||
is required. Every script fixes the seed 2026 and writes its raw output
|
`refine_matched.py` use `torch` (CUDA when available; the scripts fall
|
||||||
to `data/`, so plotting is decoupled from simulation.
|
back to CPU). All random draws come from the numpy generator with the
|
||||||
|
fixed seed 2026 — torch only accelerates QR, matrix products, and
|
||||||
|
linear solves — and every script writes its raw output to `data/`, so
|
||||||
|
plotting is fully decoupled from simulation.
|
||||||
|
|
||||||
## Reproducing the figures
|
## Reproducing the figures
|
||||||
|
|
||||||
Run the scripts from inside `code/`.
|
Run the scripts from inside `code/`. All plots are rendered from
|
||||||
|
`data/` only, by `replot_all.py` (Figs. 2, 3, 5, 6, 7) and
|
||||||
|
`replot_merged.py` (Fig. 4).
|
||||||
|
|
||||||
| Figure | Content | Script | Data |
|
| Figure | Content | Simulation | Data |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| Fig. 2 | Per-user MSE and self-interference floor | `revision_sims.py E1` | `floor_validation.csv` |
|
| Fig. 1 | System diagram | `latexmk -pdf fig/block_diagram_src.tex` | — |
|
||||||
|
| Fig. 2 | Per-user MSE, aware vs blind floor | `revision_sims.py E1` | `floor_validation.csv` |
|
||||||
| Fig. 3 | Effective sum rate at the CLIP affinity | `revision_sims.py E7a` | `rate_corrected.csv` |
|
| Fig. 3 | Effective sum rate at the CLIP affinity | `revision_sims.py E7a` | `rate_corrected.csv` |
|
||||||
| Fig. 4 | Cosine recovery on real BERT+ViT pairs | `fig_real_merged.py`, then `refine_matched.py`; replot with `replot_merged.py` | `bertvit_merged.csv` |
|
| Fig. 4 | Cosine recovery on real BERT+ViT pairs | `fig_real_merged.py`, then `refine_matched.py` | `bertvit_merged.csv` |
|
||||||
| Fig. 5 | Realizable versus genie-aided SIC | `revision_sims.py E2`; replot with `replot_sic.py` | `sic_comparison.csv` |
|
| Fig. 5 | Receiver comparison under Rayleigh fading | `revision_sims_gpu.py E2` | `sic_comparison.csv` |
|
||||||
| Fig. 6 | Affinity sweep and crossover | `revision_sims.py E7a` | `beta_sweep_corrected.csv` |
|
| Fig. 6 | Value of the measured affinity | `revision_sims.py E7a` | `beta_sweep_corrected.csv` |
|
||||||
| Fig. 7 | Multi-user scaling | `revision_sims.py E7c` | `multiuser_corrected.csv` |
|
| Fig. 7 | Multi-user scaling (joint Wiener) | `revision_sims_gpu.py E7c` | `multiuser_corrected.csv` |
|
||||||
|
|
||||||
Fig. 1 is a system diagram and has no simulation behind it.
|
|
||||||
|
|
||||||
Quantities quoted in the text but not plotted come from the same
|
Quantities quoted in the text but not plotted come from the same
|
||||||
driver: `revision_sims.py E0` writes `theorem_check.csv` (Theorem 1
|
drivers: `revision_sims.py E0` writes `theorem_check.csv` (Theorem 1
|
||||||
constants), `E4` writes `csi_error.csv` (imperfect-CSI robustness), and
|
validation across affinities and channel phases),
|
||||||
`E5` writes `mask_family_rev.csv` (Walsh–Hadamard versus Haar masks).
|
`revision_sims_gpu.py E3` writes `rayleigh_mse.csv` (unconditional
|
||||||
`revision_sims.py` with no argument runs every experiment.
|
Rayleigh MSE), `E4` writes `csi_error.csv` (imperfect-CSI
|
||||||
|
robustness), `E5` writes `mask_family_rev.csv` (Walsh–Hadamard versus
|
||||||
|
Haar), `E8` writes `mismatch.csv` (affinity mismatch and
|
||||||
|
quantization), and `E9` writes `cosine_ceiling.csv` (cosine-ceiling
|
||||||
|
corollary check).
|
||||||
|
|
||||||
## Verifying the analysis
|
## Verifying the analysis
|
||||||
|
|
||||||
`verify_math.py` re-derives every closed-form expression in the paper
|
`verify_math.py` re-derives every closed-form claim numerically and
|
||||||
numerically and prints one PASS/FAIL line per item, covering the
|
prints one PASS/FAIL line per item: Theorem 1 at the equal-gain point
|
||||||
per-realization Gram identity, Theorem 1 and its self-interference
|
and under random channel phases for both users, the aware and blind
|
||||||
constants, the effective-SINR corollary, the MAC-consistency
|
error floors and the value-of-affinity ratio, the cosine-ceiling
|
||||||
proposition, the wideband limit, both crossover conditions, the
|
corollary, the blind-receiver/matched-filter cosine equivalence, the
|
||||||
affinity-mismatch bound, the CSI-invariance identity, the multi-user
|
monotonicity proposition, the full-cooperation bound with its
|
||||||
inverse formula, and the Walsh–Hadamard construction. It depends only
|
equality case at `beta = 1`, the finite-SNR MAC-condition boundary,
|
||||||
on `numpy`.
|
the exact Walsh–Hadamard closed form, the quadratic mismatch
|
||||||
|
stationarity, and the dominated floor of the correlated-mask
|
||||||
|
alternative from the Appendix. It depends only on `numpy`.
|
||||||
|
|
||||||
## Conventions
|
## Conventions
|
||||||
|
|
||||||
The scripts follow the manuscript exactly: unit per-block transmit
|
The scripts follow the manuscript exactly: unit per-block transmit
|
||||||
energy `E_b = 1` per user, `rho = E_b / sigma_n^2` as the per-block
|
energy `E_b = 1` per user, `rho = E_b / sigma_n^2` as the per-block
|
||||||
SNR with per-symbol SNR `rho/d`, complex block-Rayleigh gains unless
|
SNR with per-symbol SNR `rho/d`, complex block-Rayleigh gains unless
|
||||||
the evaluation point `h_u = 1` is stated, real unit-norm embeddings,
|
the evaluation point `h_u = 1` is stated, real unit-norm embeddings
|
||||||
and masks drawn fresh from the Haar mixture on every realization.
|
with the orientation `<e1, e2> = +beta`, and independent Haar masks
|
||||||
|
drawn fresh on every realization.
|
||||||
`fig_real_merged.py` also produces columns for a retrained
|
|
||||||
attention-based receiver. Those columns are kept in `bertvit_merged.csv`
|
|
||||||
for completeness but are not used by any figure in the paper.
|
|
||||||
`revision_sims.py E6` covers a high-affinity combining mode that is
|
|
||||||
outside the scope of this paper.
|
|
||||||
|
|
||||||
## Citation and license
|
## Citation and license
|
||||||
|
|
||||||
|
|||||||
+96
-182
@@ -1,30 +1,30 @@
|
|||||||
"""
|
"""
|
||||||
Merged real-data comparison figure (replaces separate Figs 4 and 5).
|
Real-data comparison on cached BERT (text) + ViT (image) pairs.
|
||||||
===================================================================
|
===================================================================
|
||||||
Evaluates ALL schemes on the cached real BERT (text) + ViT (image)
|
Evaluates the schemes on the cached real embedding pairs
|
||||||
embedding pairs (16 pairs, d = 768, measured mean affinity ~0.028)
|
(16 pairs, d = 768, measured mean affinity ~0.028) under the
|
||||||
under the manuscript's complex block-Rayleigh channel:
|
manuscript's complex block-Rayleigh channel:
|
||||||
|
|
||||||
r = h1 M1 e1 + h2 M2 e2 + n, n ~ CN(0, sigma^2 I), h_u ~ CN(0,1),
|
r = h1 M1 e1 + h2 M2 e2 + n, n ~ CN(0, sigma^2 I), h_u ~ CN(0,1),
|
||||||
per-block energy E_b = 1, rho = 1/sigma^2 (per-block SNR).
|
per-block energy E_b = 1, rho = 1/sigma^2 (per-block SNR).
|
||||||
|
|
||||||
Schemes:
|
Schemes (v2 design: independent Haar masks per user):
|
||||||
1. EDMA : per-realisation Haar-mixture masks with the per-pair
|
1. EDMA : affinity-aware Wiener demultiplexer with the
|
||||||
measured beta_i, closed-form demux (13).
|
per-pair measured beta_i.
|
||||||
2. OMA : equivalent-bandwidth model, noise std x sqrt(2).
|
2. OMA : equivalent-bandwidth model, noise std x sqrt(2).
|
||||||
3. Genie SIC : perfect removal of the other user's waveform.
|
3. Genie SIC : perfect removal of the other user's waveform.
|
||||||
4. Attention : retrained reproduction of the learned predecessor,
|
4. ToDMA-adapted: OMP sparse coding of the real embedding (T = 16
|
||||||
d = 768, trained on parametric pairs at the measured
|
|
||||||
mean affinity with Rayleigh channels and
|
|
||||||
channel-equalised matched-filter inputs
|
|
||||||
x_u = Re(M_u^T r / h_u); evaluated on the REAL pairs.
|
|
||||||
5. ToDMA-adapted: OMP sparse coding of the real embedding (T = 16
|
|
||||||
atoms, V = 1024), T slots x L = 48 signatures,
|
atoms, V = 1024), T slots x L = 48 signatures,
|
||||||
per-slot OMP detection on the complex observation,
|
per-slot OMP detection on the complex observation,
|
||||||
genie association, true coefficients granted.
|
genie association, true coefficients granted.
|
||||||
|
|
||||||
Outputs: fig/fig_bertvit_merged.pdf, data/bertvit_merged.csv.
|
The hybrid (EDMA + refinement stage) curve is produced separately by
|
||||||
200 fading realisations per pair -> 3,200 Monte-Carlo samples per SNR.
|
refine_matched.py (torch) and merged by replot_merged.py.
|
||||||
|
|
||||||
|
EDMA/OMA/genie run in torch (CUDA when available, batched over the
|
||||||
|
SNR grid); the ToDMA detector runs in numpy on the CPU. Run under
|
||||||
|
WSL for GPU acceleration. Outputs: data/bertvit_merged.csv.
|
||||||
|
NFADE fading realisations per pair; ToDMA uses the first 40.
|
||||||
Seed fixed.
|
Seed fixed.
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
@@ -35,38 +35,20 @@ import time
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import torch
|
import torch
|
||||||
import matplotlib
|
|
||||||
matplotlib.use("Agg")
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
DATA = ROOT / "data"
|
DATA = ROOT / "data"
|
||||||
FIG = ROOT / "fig"
|
FIG = ROOT / "fig"
|
||||||
|
|
||||||
plt.rcParams.update({
|
|
||||||
"font.family": "serif",
|
|
||||||
"font.serif": ["DejaVu Serif", "Times New Roman"],
|
|
||||||
"font.size": 9, "axes.labelsize": 9, "legend.fontsize": 6.6,
|
|
||||||
"xtick.labelsize": 8, "ytick.labelsize": 8,
|
|
||||||
"axes.grid": True, "grid.linestyle": "--", "grid.linewidth": 0.4,
|
|
||||||
"grid.alpha": 0.6, "lines.linewidth": 1.4, "lines.markersize": 4.0,
|
|
||||||
"figure.figsize": (3.15, 2.36), "pdf.fonttype": 42,
|
|
||||||
})
|
|
||||||
AXES_RECT = dict(left=0.205, right=0.965, top=0.955, bottom=0.185)
|
|
||||||
|
|
||||||
SEED = 2026
|
SEED = 2026
|
||||||
rng = np.random.default_rng(SEED)
|
rng = np.random.default_rng(SEED)
|
||||||
torch.manual_seed(SEED)
|
torch.manual_seed(SEED)
|
||||||
|
DEV = "cuda" if torch.cuda.is_available() else "cpu"
|
||||||
|
|
||||||
D = 768
|
D = 768
|
||||||
SNRS = np.arange(0.0, 31.0, 5.0)
|
SNRS = np.arange(0.0, 31.0, 2.5)
|
||||||
NFADE = 200 # fading realisations per pair
|
NFADE = 100 # fading realisations per pair
|
||||||
|
NFADE_TOD = 40 # ToDMA heavier: first 40 draws
|
||||||
|
|
||||||
def haar(d):
|
|
||||||
G = rng.standard_normal((d, d))
|
|
||||||
Q, R = np.linalg.qr(G)
|
|
||||||
return Q * np.sign(np.diag(R))
|
|
||||||
|
|
||||||
|
|
||||||
def unit(v):
|
def unit(v):
|
||||||
@@ -87,100 +69,35 @@ def load_pairs():
|
|||||||
return a, b, betas
|
return a, b, betas
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
def haar_t(n, gen):
|
||||||
# attention model: trained at the measured mean affinity, d=768,
|
G = torch.randn(n, D, D, generator=gen, device=DEV)
|
||||||
# Rayleigh channels, channel-equalised MF inputs
|
Q, R = torch.linalg.qr(G)
|
||||||
# ------------------------------------------------------------------
|
return Q * torch.sign(torch.diagonal(R, dim1=-2, dim2=-1)).unsqueeze(-2)
|
||||||
EPS_EQ = 0.1 # regularised equalisation h*/(|h|^2+EPS_EQ):
|
|
||||||
# caps deep-fade amplification for the learned readout
|
|
||||||
|
|
||||||
|
|
||||||
def train_attention(beta0, epochs=150, steps=20, batch=48, lr=5e-4,
|
def aware_batch(t, Q, beta, c, nvar):
|
||||||
l1=1.0, l2=0.5, l3=0.5):
|
"""Batched affinity-aware Wiener demux. t: (b,D) cfloat, Q: (D,D),
|
||||||
print(f"=== training attention reproduction (d={D}, beta={beta0:.3f}, "
|
c: complex scalar, nvar: (b,) real."""
|
||||||
f"{epochs} epochs, Rayleigh) ===", flush=True)
|
b = t.shape[0]
|
||||||
gen = torch.Generator().manual_seed(SEED)
|
g = 1.0 - beta * beta
|
||||||
g0 = math.sqrt(1.0 - beta0**2)
|
rho = g * abs(c)**2 / D + nvar # (b,)
|
||||||
|
Qc = Q.to(torch.cfloat)
|
||||||
def torch_pairs(n):
|
A = torch.eye(D, device=DEV, dtype=torch.cfloat) + beta * c * Qc
|
||||||
e1 = torch.nn.functional.normalize(
|
S = (A @ A.mH / D).unsqueeze(0) \
|
||||||
torch.randn(n, D, generator=gen), dim=1)
|
+ rho.view(b, 1, 1) * torch.eye(D, device=DEV,
|
||||||
w = torch.randn(n, D, generator=gen)
|
dtype=torch.cfloat)
|
||||||
w = w - (w * e1).sum(1, keepdim=True) * e1
|
x = torch.linalg.solve(S, t.unsqueeze(-1))
|
||||||
w = torch.nn.functional.normalize(w, dim=1)
|
return (A.mH.unsqueeze(0) @ x).squeeze(-1) / D
|
||||||
return e1, beta0 * e1 + g0 * w
|
|
||||||
|
|
||||||
M1 = torch.nn.Parameter(torch.linalg.qr(
|
|
||||||
torch.randn(D, D, generator=gen))[0])
|
|
||||||
M2 = torch.nn.Parameter(beta0 * M1.detach()
|
|
||||||
+ g0 * torch.linalg.qr(
|
|
||||||
torch.randn(D, D, generator=gen))[0])
|
|
||||||
Q1 = torch.nn.Parameter(torch.randn(D, D, generator=gen) / math.sqrt(D))
|
|
||||||
Q2 = torch.nn.Parameter(torch.randn(D, D, generator=gen) / math.sqrt(D))
|
|
||||||
opt = torch.optim.Adam([M1, M2, Q1, Q2], lr=lr)
|
|
||||||
eye = torch.eye(D)
|
|
||||||
|
|
||||||
t0 = time.time()
|
|
||||||
for ep in range(epochs):
|
|
||||||
for _ in range(steps):
|
|
||||||
e1, e2 = torch_pairs(batch)
|
|
||||||
snr_db = 5.0 + 20.0 * torch.rand(batch, 1, generator=gen)
|
|
||||||
sig = 10 ** (-snr_db / 20.0)
|
|
||||||
hr = torch.randn(batch, 2, generator=gen)
|
|
||||||
hi = torch.randn(batch, 2, generator=gen)
|
|
||||||
# complex channel on real signals; equalised MF real part:
|
|
||||||
# x_u = Re(M_u^T r / h_u); build via real/imag components
|
|
||||||
s1 = e1 @ M1.T
|
|
||||||
s2 = e2 @ M2.T
|
|
||||||
nr = sig * torch.randn(batch, D, generator=gen) / math.sqrt(2)
|
|
||||||
ni = sig * torch.randn(batch, D, generator=gen) / math.sqrt(2)
|
|
||||||
rr = (hr[:, :1] * s1 + hr[:, 1:2] * s2) / math.sqrt(2) + nr
|
|
||||||
ri = (hi[:, :1] * s1 + hi[:, 1:2] * s2) / math.sqrt(2) + ni
|
|
||||||
outs = []
|
|
||||||
for u, (Mu, Qu) in enumerate(((M1, Q1), (M2, Q2))):
|
|
||||||
hu_r = hr[:, u:u+1] / math.sqrt(2)
|
|
||||||
hu_i = hi[:, u:u+1] / math.sqrt(2)
|
|
||||||
mag = hu_r**2 + hu_i**2 + EPS_EQ
|
|
||||||
xr = (rr @ Mu)
|
|
||||||
xi = (ri @ Mu)
|
|
||||||
xu = (xr * hu_r + xi * hu_i) / mag # Re(h* r'/(|h|^2+eps))
|
|
||||||
sc = (xu @ Qu.T) / math.sqrt(D)
|
|
||||||
outs.append(D * torch.softmax(sc, dim=1) * xu)
|
|
||||||
gram = ((M1.T @ M1 - eye)**2).mean() \
|
|
||||||
+ ((M2.T @ M2 - eye)**2).mean() \
|
|
||||||
+ ((M1.T @ M2 - beta0 * eye)**2).mean()
|
|
||||||
mse = ((outs[0] - e1)**2).mean() + ((outs[1] - e2)**2).mean()
|
|
||||||
cs = torch.nn.functional.cosine_similarity(
|
|
||||||
outs[0], e1, dim=1).mean() \
|
|
||||||
+ torch.nn.functional.cosine_similarity(
|
|
||||||
outs[1], e2, dim=1).mean()
|
|
||||||
loss = l1 * gram + l2 * mse + l3 * (2.0 - cs)
|
|
||||||
opt.zero_grad(); loss.backward()
|
|
||||||
torch.nn.utils.clip_grad_norm_([M1, M2, Q1, Q2], 1.0)
|
|
||||||
opt.step()
|
|
||||||
if (ep + 1) % 50 == 0:
|
|
||||||
print(f" epoch {ep+1}: loss {float(loss.detach()):.4f}",
|
|
||||||
flush=True)
|
|
||||||
print(f" trained in {time.time()-t0:.0f}s, "
|
|
||||||
f"{4*D*D/1e6:.2f}M parameters")
|
|
||||||
return (M1.detach().numpy(), M2.detach().numpy(),
|
|
||||||
Q1.detach().numpy(), Q2.detach().numpy())
|
|
||||||
|
|
||||||
|
|
||||||
def att_apply(model, r, h1, h2):
|
def abscos(a, b):
|
||||||
M1, M2, Q1, Q2 = model
|
"""a: (b,D) cfloat, b: (D,) float -> (b,) abs cosine."""
|
||||||
outs = []
|
num = (a * b.to(torch.cfloat).conj()).sum(1).abs()
|
||||||
for u, (Mu, Qu, hu) in enumerate(((M1, Q1, h1), (M2, Q2, h2))):
|
return (num / (a.norm(dim=1) * b.norm())).cpu().numpy()
|
||||||
xu = np.real(np.conj(hu) * (Mu.T @ r)) / (abs(hu)**2 + EPS_EQ)
|
|
||||||
sc = (Qu @ xu) / math.sqrt(D)
|
|
||||||
sc = sc - sc.max()
|
|
||||||
w = np.exp(sc); w /= w.sum()
|
|
||||||
outs.append(D * w * xu)
|
|
||||||
return outs
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# ToDMA-adapted on real embeddings (complex channel)
|
# ToDMA-adapted on real embeddings (complex channel, numpy)
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
def todma_prepare(V=1024, T=16):
|
def todma_prepare(V=1024, T=16):
|
||||||
L = D // T
|
L = D // T
|
||||||
@@ -238,58 +155,73 @@ def todma_run(tod, codes, h, sig, noise_slots):
|
|||||||
def main():
|
def main():
|
||||||
A, B, betas = load_pairs()
|
A, B, betas = load_pairs()
|
||||||
npairs = len(A)
|
npairs = len(A)
|
||||||
model = train_attention(float(betas.mean()))
|
|
||||||
tod = todma_prepare()
|
tod = todma_prepare()
|
||||||
codes = [(omp_code(tod[0], A[i], tod[3]),
|
codes = [(omp_code(tod[0], A[i], tod[3]),
|
||||||
omp_code(tod[0], B[i], tod[3])) for i in range(npairs)]
|
omp_code(tod[0], B[i], tod[3])) for i in range(npairs)]
|
||||||
print("[todma] sparse codes prepared")
|
print(f"[todma] sparse codes prepared; device = {DEV}")
|
||||||
|
|
||||||
keys = ("edma", "oma", "genie", "att", "att_x", "todma")
|
gen = torch.Generator(device=DEV).manual_seed(SEED)
|
||||||
res = {k: np.zeros(len(SNRS)) for k in keys}
|
nb = len(SNRS)
|
||||||
cnt = {k: np.zeros(len(SNRS)) for k in keys}
|
sigs_t = torch.tensor(10 ** (-SNRS / 20.0), device=DEV,
|
||||||
|
dtype=torch.float32)
|
||||||
|
keys = ("edma", "oma", "genie", "todma")
|
||||||
|
res = {k: np.zeros(nb) for k in keys}
|
||||||
|
cnt = {k: np.zeros(nb) for k in keys}
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
for i in range(npairs):
|
for i in range(npairs):
|
||||||
e1, e2, bi = A[i], B[i], float(betas[i])
|
bi = float(betas[i])
|
||||||
gi = 1.0 - bi**2
|
e1 = torch.tensor(A[i], dtype=torch.float32, device=DEV)
|
||||||
c1, c2 = codes[i]
|
e2 = torch.tensor(B[i], dtype=torch.float32, device=DEV)
|
||||||
|
c1c, c2c = codes[i]
|
||||||
for f in range(NFADE):
|
for f in range(NFADE):
|
||||||
U1, U2 = haar(D), haar(D)
|
M = haar_t(2, gen)
|
||||||
M1 = U1
|
M1, M2 = M[0], M[1]
|
||||||
M2 = bi * U1 + math.sqrt(gi) * U2
|
Q = M1.T @ M2
|
||||||
h = (rng.standard_normal(2) + 1j * rng.standard_normal(2)) \
|
h = (torch.randn(2, generator=gen, device=DEV)
|
||||||
|
+ 1j * torch.randn(2, generator=gen, device=DEV)) \
|
||||||
/ math.sqrt(2)
|
/ math.sqrt(2)
|
||||||
h1, h2 = h
|
n = (torch.randn(D, generator=gen, device=DEV)
|
||||||
r0 = h1 * (M1 @ e1) + h2 * (M2 @ e2)
|
+ 1j * torch.randn(D, generator=gen, device=DEV)) \
|
||||||
n = (rng.standard_normal(D) + 1j * rng.standard_normal(D)) \
|
|
||||||
/ math.sqrt(2)
|
/ math.sqrt(2)
|
||||||
n2 = (rng.standard_normal(D) + 1j * rng.standard_normal(D)) \
|
n2 = (torch.randn(D, generator=gen, device=DEV)
|
||||||
|
+ 1j * torch.randn(D, generator=gen, device=DEV)) \
|
||||||
/ math.sqrt(2)
|
/ math.sqrt(2)
|
||||||
|
r0 = h[0] * (M1 @ e1).to(torch.cfloat) \
|
||||||
|
+ h[1] * (M2 @ e2).to(torch.cfloat)
|
||||||
|
r = r0.unsqueeze(0) + sigs_t.view(-1, 1) * n.unsqueeze(0)
|
||||||
|
t1 = (M1.T.to(torch.cfloat) @ r.unsqueeze(-1)).squeeze(-1) / h[0]
|
||||||
|
t2 = (M2.T.to(torch.cfloat) @ r.unsqueeze(-1)).squeeze(-1) / h[1]
|
||||||
|
c1 = (h[1] / h[0]).item()
|
||||||
|
c2 = (h[0] / h[1]).item()
|
||||||
|
v1 = sigs_t**2 / h[0].abs()**2
|
||||||
|
v2 = sigs_t**2 / h[1].abs()**2
|
||||||
|
g1 = aware_batch(t1, Q, bi, c1, v1)
|
||||||
|
g2 = aware_batch(t2, Q.T, bi, c2, v2)
|
||||||
|
res["edma"] += 0.5 * (abscos(g1, e1) + abscos(g2, e2))
|
||||||
|
o1 = e1.to(torch.cfloat).unsqueeze(0) \
|
||||||
|
+ math.sqrt(2) * sigs_t.view(-1, 1) * n.unsqueeze(0) / h[0]
|
||||||
|
o2 = e2.to(torch.cfloat).unsqueeze(0) \
|
||||||
|
+ math.sqrt(2) * sigs_t.view(-1, 1) * n2.unsqueeze(0) / h[1]
|
||||||
|
res["oma"] += 0.5 * (abscos(o1, e1) + abscos(o2, e2))
|
||||||
|
ge1 = (M1.T.to(torch.cfloat)
|
||||||
|
@ (r - h[1] * (M2 @ e2).to(torch.cfloat)).unsqueeze(-1)
|
||||||
|
).squeeze(-1) / h[0]
|
||||||
|
ge2 = (M2.T.to(torch.cfloat)
|
||||||
|
@ (r - h[0] * (M1 @ e1).to(torch.cfloat)).unsqueeze(-1)
|
||||||
|
).squeeze(-1) / h[1]
|
||||||
|
res["genie"] += 0.5 * (abscos(ge1, e1) + abscos(ge2, e2))
|
||||||
|
for kk in ("edma", "oma", "genie"):
|
||||||
|
cnt[kk] += 1
|
||||||
|
if f < NFADE_TOD:
|
||||||
|
hnp = (complex(h[0].item()), complex(h[1].item()))
|
||||||
nslots = [(rng.standard_normal(tod[4])
|
nslots = [(rng.standard_normal(tod[4])
|
||||||
+ 1j * rng.standard_normal(tod[4])) / math.sqrt(2)
|
+ 1j * rng.standard_normal(tod[4]))
|
||||||
for _ in range(tod[3])]
|
/ math.sqrt(2) for _ in range(tod[3])]
|
||||||
# attention scheme transmits with ITS OWN trained masks
|
e1n, e2n = A[i], B[i]
|
||||||
r0a = h1 * (model[0] @ e1) + h2 * (model[1] @ e2)
|
|
||||||
for k, s in enumerate(SNRS):
|
for k, s in enumerate(SNRS):
|
||||||
sig = 10 ** (-s / 20.0)
|
sig = 10 ** (-s / 20.0)
|
||||||
r = r0 + sig * n
|
recs = todma_run(tod, (c1c, c2c), hnp, sig, nslots)
|
||||||
t1 = M1.T @ r / h1; t2 = M2.T @ r / h2
|
got = [cosine(recs[j], (e1n, e2n)[j])
|
||||||
g1 = (t1 - bi * (h2 / h1) * t2) / gi
|
|
||||||
g2 = (t2 - bi * (h1 / h2) * t1) / gi
|
|
||||||
res["edma"][k] += 0.5 * (cosine(g1, e1) + cosine(g2, e2))
|
|
||||||
o1 = e1 + math.sqrt(2) * sig * n / h1
|
|
||||||
o2 = e2 + math.sqrt(2) * sig * n2 / h2
|
|
||||||
res["oma"][k] += 0.5 * (cosine(o1, e1) + cosine(o2, e2))
|
|
||||||
ge1 = M1.T @ (r - h2 * (M2 @ e2)) / h1
|
|
||||||
ge2 = M2.T @ (r - h1 * (M1 @ e1)) / h2
|
|
||||||
res["genie"][k] += 0.5 * (cosine(ge1, e1) + cosine(ge2, e2))
|
|
||||||
a1, a2 = att_apply(model, r0a + sig * n, h1, h2)
|
|
||||||
res["att"][k] += 0.5 * (cosine(a1, e1) + cosine(a2, e2))
|
|
||||||
res["att_x"][k] += 0.5 * (cosine(a1, e2) + cosine(a2, e1))
|
|
||||||
for kk in ("edma", "oma", "genie", "att", "att_x"):
|
|
||||||
cnt[kk][k] += 1
|
|
||||||
if f < 40: # ToDMA heavier: 40 fading draws
|
|
||||||
recs = todma_run(tod, (c1, c2), (h1, h2), sig, nslots)
|
|
||||||
got = [cosine(recs[j], (e1, e2)[j])
|
|
||||||
for j in range(2) if recs[j] is not None]
|
for j in range(2) if recs[j] is not None]
|
||||||
if got:
|
if got:
|
||||||
res["todma"][k] += float(np.mean(got))
|
res["todma"][k] += float(np.mean(got))
|
||||||
@@ -299,23 +231,6 @@ def main():
|
|||||||
for k in keys:
|
for k in keys:
|
||||||
res[k] /= np.maximum(cnt[k], 1)
|
res[k] /= np.maximum(cnt[k], 1)
|
||||||
|
|
||||||
fig, ax = plt.subplots()
|
|
||||||
ax.plot(SNRS, res["edma"], "o-", color="C3", label="EDMA (closed form)")
|
|
||||||
ax.plot(SNRS, res["att"], "s--", color="C0",
|
|
||||||
label="Attention-based (retrained)")
|
|
||||||
ax.plot(SNRS, res["todma"], "d-.", color="C4", label="ToDMA-adapted")
|
|
||||||
ax.plot(SNRS, res["oma"], "v:", color="C1", label="OMA")
|
|
||||||
ax.plot(SNRS, res["genie"], "-", color="gray", lw=1.0,
|
|
||||||
label="Genie-aided SIC bound")
|
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
|
||||||
ax.set_ylabel("Mean cosine similarity")
|
|
||||||
ax.set_xlim(SNRS[0], SNRS[-1]); ax.set_ylim(0, 0.85)
|
|
||||||
ax.legend(loc="upper left")
|
|
||||||
fig.subplots_adjust(**AXES_RECT)
|
|
||||||
fig.savefig(FIG / "fig_bertvit_merged.pdf")
|
|
||||||
plt.close(fig)
|
|
||||||
print(f"[OK] wrote {FIG/'fig_bertvit_merged.pdf'}")
|
|
||||||
|
|
||||||
with open(DATA / "bertvit_merged.csv", "w", newline="") as fcsv:
|
with open(DATA / "bertvit_merged.csv", "w", newline="") as fcsv:
|
||||||
w = csv.writer(fcsv)
|
w = csv.writer(fcsv)
|
||||||
w.writerow(["snr_db"] + list(keys))
|
w.writerow(["snr_db"] + list(keys))
|
||||||
@@ -323,8 +238,7 @@ def main():
|
|||||||
w.writerow([s] + [res[key][k] for key in keys])
|
w.writerow([s] + [res[key][k] for key in keys])
|
||||||
print(f"[OK] wrote {DATA/'bertvit_merged.csv'}")
|
print(f"[OK] wrote {DATA/'bertvit_merged.csv'}")
|
||||||
for k, s in enumerate(SNRS):
|
for k, s in enumerate(SNRS):
|
||||||
print(f" {s:4.0f} dB EDMA {res['edma'][k]:.3f} "
|
print(f" {s:4.1f} dB EDMA {res['edma'][k]:.3f} "
|
||||||
f"ATT {res['att'][k]:.3f} (x {res['att_x'][k]:.3f}) "
|
|
||||||
f"ToDMA {res['todma'][k]:.3f} OMA {res['oma'][k]:.3f} "
|
f"ToDMA {res['todma'][k]:.3f} OMA {res['oma'][k]:.3f} "
|
||||||
f"genie {res['genie'][k]:.3f}")
|
f"genie {res['genie'][k]:.3f}")
|
||||||
|
|
||||||
|
|||||||
+140
-119
@@ -1,23 +1,23 @@
|
|||||||
"""
|
"""
|
||||||
Capacity-matched EDMA refinement (parameter budget equal to the
|
Refinement stage for the v2 (affinity-aware Wiener) EDMA receiver.
|
||||||
attention scheme: 4 d^2 = 2.36M at d = 768).
|
|
||||||
================================================================
|
================================================================
|
||||||
Four-head averaged gated refinement applied to the closed-form
|
Trains the single-gate refinement operator
|
||||||
demultiplexer output:
|
|
||||||
|
|
||||||
out = (1/4) sum_k D softmax(Q_k x / sqrt(D)) .* x,
|
out = D softmax(W z / sqrt(D)) .* z, z = Re(e_hat),
|
||||||
|
|
||||||
with Q_1..Q_4 in R^{D x D} (4 d^2 parameters, exactly the
|
(0.59M parameters at d = 768) on aware-demultiplexer outputs, then
|
||||||
attention scheme's budget). The single-gate 0.59M refiner is the
|
warm-starts a capacity-check variant with four heads (4 d^2 = 2.36M)
|
||||||
special case of four identical heads, so the family contains it
|
and fine-tunes it, so the family contains the single gate by
|
||||||
by construction. Same training recipe: demux outputs from
|
construction. Training data: parametric pairs at beta = 0.028, a
|
||||||
parametric pairs at beta = 0.028, Haar pool 32, Rayleigh
|
fixed pool of 32 independent Haar mask pairs, Rayleigh channels,
|
||||||
channels, complex noise, training SNR uniform in [5, 25] dB,
|
complex noise, training SNR uniform in [5, 25] dB, Adam 5e-4 with
|
||||||
Adam 5e-4 with gradient clipping, batch 48, 200 epochs.
|
gradient clipping, batch 48, 220 epochs (stage 2 from epoch 120 at
|
||||||
|
lr 2e-4).
|
||||||
|
|
||||||
Evaluation on the real BERT/ViT pairs with fresh Haar masks and
|
Evaluation on the real BERT/ViT pairs with fresh Haar masks and
|
||||||
200 fading draws per pair. Appends column `edma_ref2` to
|
NFADE fading draws per pair. Appends columns `edma_ref` (single
|
||||||
data/bertvit_merged.csv and prints all-curve numbers.
|
gate) and `edma_ref2` (four heads) to data/bertvit_merged.csv.
|
||||||
|
Requires torch (run under WSL with CUDA if available).
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import csv
|
import csv
|
||||||
@@ -26,161 +26,182 @@ import time
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import torch
|
import torch
|
||||||
|
|
||||||
from fig_real_merged import load_pairs, cosine, SNRS, NFADE, D, DATA
|
from fig_real_merged import load_pairs, SNRS, NFADE, D, DATA
|
||||||
|
|
||||||
SEED = 2026
|
SEED = 2026
|
||||||
rng = np.random.default_rng(SEED + 31)
|
|
||||||
torch.manual_seed(SEED + 31)
|
torch.manual_seed(SEED + 31)
|
||||||
|
DEV = "cuda" if torch.cuda.is_available() else "cpu"
|
||||||
BETA0 = 0.028
|
BETA0 = 0.028
|
||||||
G0 = 1.0 - BETA0**2
|
G0 = 1.0 - BETA0**2
|
||||||
|
print(f"[refine] device = {DEV}")
|
||||||
|
|
||||||
|
|
||||||
def haar_t(gen):
|
def haar_t(n, gen):
|
||||||
Q, R = torch.linalg.qr(torch.randn(D, D, generator=gen))
|
G = torch.randn(n, D, D, generator=gen, device=DEV)
|
||||||
return Q * torch.sign(torch.diagonal(R))
|
Q, R = torch.linalg.qr(G)
|
||||||
|
return Q * torch.sign(torch.diagonal(R, dim1=-2, dim2=-1)).unsqueeze(-2)
|
||||||
|
|
||||||
|
|
||||||
def train_refiner2(epochs=220, steps=20, batch=48, lr=5e-4,
|
def aware_t(t1, Q, beta, c1, nvar):
|
||||||
l2=0.5, l3=0.5, pool=32):
|
"""Batched affinity-aware Wiener demux in torch (complex)."""
|
||||||
"""Stage 1 trains a single gate (the proven 0.59M recipe); stage 2
|
b = t1.shape[0]
|
||||||
warm-starts four heads from it plus small perturbations and
|
g = 1.0 - beta * beta
|
||||||
fine-tunes at a reduced learning rate, so the capacity-matched
|
rho = g * (c1.abs()**2) / D + nvar # (b,)
|
||||||
family starts at the single-gate solution it contains."""
|
A = torch.eye(D, device=DEV, dtype=torch.cfloat).expand(b, D, D) \
|
||||||
print(f"=== training capacity-matched refinement (4-head gate, "
|
+ beta * c1.view(b, 1, 1) * Q.to(torch.cfloat)
|
||||||
f"4d^2 = {4*D*D/1e6:.2f}M params, warm-started) ===",
|
S = A @ A.mH / D + rho.view(b, 1, 1) \
|
||||||
flush=True)
|
* torch.eye(D, device=DEV, dtype=torch.cfloat)
|
||||||
gen = torch.Generator().manual_seed(SEED + 31)
|
x = torch.linalg.solve(S, t1.unsqueeze(-1))
|
||||||
masks = []
|
return (A.mH @ x).squeeze(-1) / D
|
||||||
for _ in range(pool):
|
|
||||||
U1, U2 = haar_t(gen), haar_t(gen)
|
|
||||||
masks.append((U1.numpy(), (BETA0 * U1
|
def train_batch(masks, Qs, gen, batch):
|
||||||
+ math.sqrt(G0) * U2).numpy()))
|
"""Generate one training batch of aware-demux outputs (user 1)."""
|
||||||
Q0 = torch.nn.Parameter(torch.randn(D, D, generator=gen)
|
e1 = torch.nn.functional.normalize(
|
||||||
/ math.sqrt(D))
|
torch.randn(batch, D, generator=gen, device=DEV), dim=1)
|
||||||
params = [Q0]
|
w = torch.randn(batch, D, generator=gen, device=DEV)
|
||||||
|
w = w - (w * e1).sum(1, keepdim=True) * e1
|
||||||
|
w = torch.nn.functional.normalize(w, dim=1)
|
||||||
|
e2 = BETA0 * e1 + math.sqrt(G0) * w
|
||||||
|
sel = torch.randint(len(masks), (batch,), generator=gen, device=DEV)
|
||||||
|
M1 = masks[0][sel]; M2 = masks[1][sel]; Q = Qs[sel]
|
||||||
|
snr = 5.0 + 20.0 * torch.rand(batch, generator=gen, device=DEV)
|
||||||
|
sig = 10 ** (-snr / 20.0)
|
||||||
|
h = (torch.randn(batch, 2, generator=gen, device=DEV)
|
||||||
|
+ 1j * torch.randn(batch, 2, generator=gen, device=DEV)) \
|
||||||
|
/ math.sqrt(2)
|
||||||
|
n = (torch.randn(batch, D, generator=gen, device=DEV)
|
||||||
|
+ 1j * torch.randn(batch, D, generator=gen, device=DEV)) \
|
||||||
|
/ math.sqrt(2)
|
||||||
|
r = h[:, :1] * (M1 @ e1.unsqueeze(-1)).squeeze(-1).to(torch.cfloat) \
|
||||||
|
+ h[:, 1:2] * (M2 @ e2.unsqueeze(-1)).squeeze(-1).to(torch.cfloat) \
|
||||||
|
+ sig.view(-1, 1) * n
|
||||||
|
t1 = (M1.transpose(-1, -2).to(torch.cfloat)
|
||||||
|
@ r.unsqueeze(-1)).squeeze(-1) / h[:, :1]
|
||||||
|
c1 = h[:, 1] / h[:, 0]
|
||||||
|
nvar = sig**2 / h[:, 0].abs()**2
|
||||||
|
g1 = aware_t(t1, Q, BETA0, c1, nvar)
|
||||||
|
return g1.real.float(), e1
|
||||||
|
|
||||||
|
|
||||||
|
def train_refiners(epochs=220, steps=20, batch=48, lr=5e-4,
|
||||||
|
l2=0.5, l3=0.5, pool=32, stage2_at=120):
|
||||||
|
print(f"=== training refinement (single gate {D*D/1e6:.2f}M, "
|
||||||
|
f"then 4-head warm start {4*D*D/1e6:.2f}M) ===", flush=True)
|
||||||
|
gen = torch.Generator(device=DEV).manual_seed(SEED + 31)
|
||||||
|
U1 = haar_t(pool, gen); U2 = haar_t(pool, gen)
|
||||||
|
masks = (U1, U2)
|
||||||
|
Qs = U1.transpose(-1, -2) @ U2
|
||||||
|
params = [torch.nn.Parameter(
|
||||||
|
torch.randn(D, D, generator=gen, device=DEV) / math.sqrt(D))]
|
||||||
opt = torch.optim.Adam(params, lr=lr)
|
opt = torch.optim.Adam(params, lr=lr)
|
||||||
stage2_at = 120 # epochs of single-gate pre-training
|
P_single = None
|
||||||
|
|
||||||
def forward(x):
|
def forward(x, ps):
|
||||||
outs = [D * torch.softmax((x @ Qk.T) / math.sqrt(D), dim=1) * x
|
outs = [D * torch.softmax((x @ Qk.T) / math.sqrt(D), dim=1) * x
|
||||||
for Qk in params]
|
for Qk in ps]
|
||||||
return sum(outs) / len(params)
|
return sum(outs) / len(ps)
|
||||||
|
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
for ep in range(epochs):
|
for ep in range(epochs):
|
||||||
if ep == stage2_at:
|
if ep == stage2_at:
|
||||||
|
P_single = params[0].detach().clone()
|
||||||
base = params[0].detach()
|
base = params[0].detach()
|
||||||
params = [torch.nn.Parameter(
|
params = [torch.nn.Parameter(
|
||||||
base.clone() + 0.02 * torch.randn(D, D, generator=gen)
|
base.clone() + 0.02 * torch.randn(D, D, generator=gen,
|
||||||
|
device=DEV)
|
||||||
/ math.sqrt(D)) for _ in range(4)]
|
/ math.sqrt(D)) for _ in range(4)]
|
||||||
opt = torch.optim.Adam(params, lr=2e-4)
|
opt = torch.optim.Adam(params, lr=2e-4)
|
||||||
print(f" [warm start] 4 heads initialised from the trained "
|
print(f" [warm start] 4 heads at epoch {ep}", flush=True)
|
||||||
f"gate at epoch {ep}", flush=True)
|
|
||||||
for _ in range(steps):
|
for _ in range(steps):
|
||||||
xs, ts = [], []
|
with torch.no_grad():
|
||||||
for _ in range(batch):
|
x, tgt = train_batch(masks, Qs, gen, batch)
|
||||||
e1 = torch.nn.functional.normalize(
|
out = forward(x, params)
|
||||||
torch.randn(D, generator=gen), dim=0).numpy()
|
mse = ((out - tgt)**2).mean()
|
||||||
w = torch.randn(D, generator=gen).numpy()
|
cs = torch.nn.functional.cosine_similarity(out, tgt, dim=1).mean()
|
||||||
w = w - (w @ e1) * e1
|
|
||||||
w = w / np.linalg.norm(w)
|
|
||||||
e2 = BETA0 * e1 + math.sqrt(G0) * w
|
|
||||||
M1, M2 = masks[int(torch.randint(pool, (1,),
|
|
||||||
generator=gen))]
|
|
||||||
snr = float(5.0 + 20.0 * torch.rand(1, generator=gen))
|
|
||||||
sig = 10 ** (-snr / 20.0)
|
|
||||||
h = (torch.randn(2, generator=gen).numpy()
|
|
||||||
+ 1j * torch.randn(2, generator=gen).numpy()) \
|
|
||||||
/ math.sqrt(2)
|
|
||||||
nc = (torch.randn(D, generator=gen).numpy()
|
|
||||||
+ 1j * torch.randn(D, generator=gen).numpy()) \
|
|
||||||
/ math.sqrt(2)
|
|
||||||
rc = h[0] * (M1 @ e1) + h[1] * (M2 @ e2) + sig * nc
|
|
||||||
t1 = M1.T @ rc / h[0]
|
|
||||||
t2 = M2.T @ rc / h[1]
|
|
||||||
g1 = (t1 - BETA0 * (h[1] / h[0]) * t2) / G0
|
|
||||||
xs.append(torch.tensor(np.real(g1), dtype=torch.float32))
|
|
||||||
ts.append(torch.tensor(e1, dtype=torch.float32))
|
|
||||||
x = torch.stack(xs); t = torch.stack(ts)
|
|
||||||
out = forward(x)
|
|
||||||
mse = ((out - t)**2).mean()
|
|
||||||
cs = torch.nn.functional.cosine_similarity(out, t, dim=1).mean()
|
|
||||||
loss = l2 * mse + l3 * (1.0 - cs)
|
loss = l2 * mse + l3 * (1.0 - cs)
|
||||||
opt.zero_grad(); loss.backward()
|
opt.zero_grad(); loss.backward()
|
||||||
torch.nn.utils.clip_grad_norm_(params, 1.0)
|
torch.nn.utils.clip_grad_norm_(params, 1.0)
|
||||||
opt.step()
|
opt.step()
|
||||||
if (ep + 1) % 50 == 0:
|
if (ep + 1) % 40 == 0:
|
||||||
print(f" epoch {ep+1}: loss {float(loss.detach()):.4f} "
|
print(f" epoch {ep+1}: loss {float(loss.detach()):.4f} "
|
||||||
f"(cos {float(cs.detach()):.3f})", flush=True)
|
f"(cos {float(cs.detach()):.3f})", flush=True)
|
||||||
print(f" trained in {time.time()-t0:.0f}s")
|
print(f" trained in {time.time()-t0:.0f}s")
|
||||||
return [p.detach().numpy() for p in params]
|
return P_single, [p.detach() for p in params]
|
||||||
|
|
||||||
|
|
||||||
def refine2(P, g):
|
def refine_apply(ps, z):
|
||||||
x = np.real(g)
|
"""z: (b, D) real torch tensor; ps: list of gates."""
|
||||||
|
outs = [D * torch.softmax((z @ Qk.T) / math.sqrt(D), dim=1) * z
|
||||||
def gate(Q, v):
|
for Qk in ps]
|
||||||
sc = (Q @ v) / math.sqrt(D)
|
return sum(outs) / len(ps)
|
||||||
sc = sc - sc.max()
|
|
||||||
w = np.exp(sc); w /= w.sum()
|
|
||||||
return D * w * v
|
|
||||||
|
|
||||||
return sum(gate(Qk, x) for Qk in P) / 4.0
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
A, B, betas = load_pairs()
|
A, B, betas = load_pairs()
|
||||||
P = train_refiner2()
|
P1, P4 = train_refiners()
|
||||||
ref = np.zeros(len(SNRS)); cnt = 0
|
gen = torch.Generator(device=DEV).manual_seed(SEED + 77)
|
||||||
|
ref1 = np.zeros(len(SNRS)); ref4 = np.zeros(len(SNRS)); cnt = 0
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
|
At = torch.tensor(A, dtype=torch.float32, device=DEV)
|
||||||
|
Bt = torch.tensor(B, dtype=torch.float32, device=DEV)
|
||||||
for i in range(len(A)):
|
for i in range(len(A)):
|
||||||
e1, e2, bi = A[i], B[i], float(betas[i])
|
bi = float(betas[i])
|
||||||
gi = 1.0 - bi**2
|
e1 = At[i]; e2 = Bt[i]
|
||||||
for f in range(NFADE):
|
for f in range(NFADE):
|
||||||
G1 = rng.standard_normal((D, D))
|
M = haar_t(2, gen)
|
||||||
Qh, Rh = np.linalg.qr(G1)
|
M1, M2 = M[0], M[1]
|
||||||
U1 = Qh * np.sign(np.diag(Rh))
|
Q = M1.T @ M2
|
||||||
G2 = rng.standard_normal((D, D))
|
h = (torch.randn(2, generator=gen, device=DEV)
|
||||||
Qh, Rh = np.linalg.qr(G2)
|
+ 1j * torch.randn(2, generator=gen, device=DEV)) \
|
||||||
U2 = Qh * np.sign(np.diag(Rh))
|
|
||||||
M1 = U1
|
|
||||||
M2 = bi * U1 + math.sqrt(gi) * U2
|
|
||||||
h = (rng.standard_normal(2) + 1j * rng.standard_normal(2)) \
|
|
||||||
/ math.sqrt(2)
|
/ math.sqrt(2)
|
||||||
h1, h2 = h
|
n = (torch.randn(D, generator=gen, device=DEV)
|
||||||
r0 = h1 * (M1 @ e1) + h2 * (M2 @ e2)
|
+ 1j * torch.randn(D, generator=gen, device=DEV)) \
|
||||||
n = (rng.standard_normal(D) + 1j * rng.standard_normal(D)) \
|
|
||||||
/ math.sqrt(2)
|
/ math.sqrt(2)
|
||||||
for k, s in enumerate(SNRS):
|
r0 = h[0] * (M1 @ e1).to(torch.cfloat) \
|
||||||
sig = 10 ** (-s / 20.0)
|
+ h[1] * (M2 @ e2).to(torch.cfloat)
|
||||||
r = r0 + sig * n
|
sigs = torch.tensor(10 ** (-SNRS / 20.0), device=DEV,
|
||||||
t1 = M1.T @ r / h1; t2 = M2.T @ r / h2
|
dtype=torch.float32)
|
||||||
g1 = (t1 - bi * (h2 / h1) * t2) / gi
|
nb = len(SNRS)
|
||||||
g2 = (t2 - bi * (h1 / h2) * t1) / gi
|
r = r0.unsqueeze(0) + sigs.view(-1, 1) * n.unsqueeze(0)
|
||||||
ref[k] += 0.5 * (cosine(refine2(P, g1), e1)
|
t1 = (M1.T.to(torch.cfloat) @ r.unsqueeze(-1)).squeeze(-1) / h[0]
|
||||||
+ cosine(refine2(P, g2), e2))
|
t2 = (M2.T.to(torch.cfloat) @ r.unsqueeze(-1)).squeeze(-1) / h[1]
|
||||||
|
c1 = (h[1] / h[0]).expand(nb)
|
||||||
|
c2 = (h[0] / h[1]).expand(nb)
|
||||||
|
v1 = (sigs**2 / h[0].abs()**2)
|
||||||
|
v2 = (sigs**2 / h[1].abs()**2)
|
||||||
|
g1 = aware_t(t1, Q.expand(nb, D, D), bi, c1, v1).real.float()
|
||||||
|
g2 = aware_t(t2, Q.T.expand(nb, D, D), bi, c2, v2).real.float()
|
||||||
|
with torch.no_grad():
|
||||||
|
for P, acc in ((([P1]), ref1), ((P4), ref4)):
|
||||||
|
o1 = refine_apply(P, g1)
|
||||||
|
o2 = refine_apply(P, g2)
|
||||||
|
cs1 = torch.nn.functional.cosine_similarity(
|
||||||
|
o1, e1.unsqueeze(0), dim=1).abs()
|
||||||
|
cs2 = torch.nn.functional.cosine_similarity(
|
||||||
|
o2, e2.unsqueeze(0), dim=1).abs()
|
||||||
|
acc += (0.5 * (cs1 + cs2)).cpu().numpy()
|
||||||
cnt += 1
|
cnt += 1
|
||||||
print(f" pair {i+1}/{len(A)} done ({time.time()-t0:.0f}s)",
|
print(f" pair {i+1}/{len(A)} done ({time.time()-t0:.0f}s)",
|
||||||
flush=True)
|
flush=True)
|
||||||
ref /= cnt
|
ref1 /= cnt; ref4 /= cnt
|
||||||
|
|
||||||
rows = list(csv.DictReader(open(DATA / "bertvit_merged.csv")))
|
rows = list(csv.DictReader(open(DATA / "bertvit_merged.csv")))
|
||||||
names = list(rows[0].keys())
|
names = list(rows[0].keys())
|
||||||
if "edma_ref2" not in names:
|
for col in ("edma_ref", "edma_ref2"):
|
||||||
names.append("edma_ref2")
|
if col not in names:
|
||||||
|
names.append(col)
|
||||||
for k, r in enumerate(rows):
|
for k, r in enumerate(rows):
|
||||||
r["edma_ref2"] = f"{ref[k]}"
|
r["edma_ref"] = f"{ref1[k]}"
|
||||||
|
r["edma_ref2"] = f"{ref4[k]}"
|
||||||
with open(DATA / "bertvit_merged.csv", "w", newline="") as f:
|
with open(DATA / "bertvit_merged.csv", "w", newline="") as f:
|
||||||
w = csv.DictWriter(f, fieldnames=names)
|
w = csv.DictWriter(f, fieldnames=names)
|
||||||
w.writeheader(); w.writerows(rows)
|
w.writeheader(); w.writerows(rows)
|
||||||
print("[OK] appended edma_ref2 to bertvit_merged.csv")
|
print("[OK] appended edma_ref / edma_ref2 to bertvit_merged.csv")
|
||||||
for k, r in enumerate(rows):
|
for k, r in enumerate(rows):
|
||||||
print(f" {float(r['snr_db']):4.0f} dB "
|
print(f" {float(r['snr_db']):4.1f} dB "
|
||||||
f"EDMA {float(r['edma']):.3f} "
|
f"EDMA {float(r['edma']):.3f} ref {ref1[k]:.3f} "
|
||||||
f"ref(0.59M) {float(r['edma_ref']):.3f} "
|
f"ref2 {ref4[k]:.3f} genie {float(r['genie']):.3f}")
|
||||||
f"ref2(2.36M) {ref[k]:.3f} "
|
|
||||||
f"ATT(2.36M) {float(r['att']):.3f} "
|
|
||||||
f"genie {float(r['genie']):.3f}")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -0,0 +1,179 @@
|
|||||||
|
"""Canonical figure rendering. Reads ONLY data/*.csv, writes fig/*.pdf.
|
||||||
|
|
||||||
|
Figures: fig_floor, fig_rate_corrected, fig_beta_sweep_corrected,
|
||||||
|
fig_sic, fig_multiuser_corrected. (fig_bertvit_merged is rendered by
|
||||||
|
replot_merged.py; block_diagram.pdf comes from block_diagram_src.tex.)
|
||||||
|
One physical geometry and one label dictionary for every plot.
|
||||||
|
"""
|
||||||
|
import csv
|
||||||
|
import math
|
||||||
|
from pathlib import Path
|
||||||
|
import matplotlib
|
||||||
|
matplotlib.use("Agg")
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
DATA = ROOT / "data"
|
||||||
|
FIG = ROOT / "fig"
|
||||||
|
|
||||||
|
plt.rcParams.update({
|
||||||
|
"font.family": "serif",
|
||||||
|
"font.serif": ["DejaVu Serif", "Times New Roman"],
|
||||||
|
"font.size": 9, "axes.labelsize": 9, "legend.fontsize": 6.6,
|
||||||
|
"xtick.labelsize": 8, "ytick.labelsize": 8,
|
||||||
|
"axes.grid": True, "grid.linestyle": "--", "grid.linewidth": 0.4,
|
||||||
|
"grid.alpha": 0.6, "lines.linewidth": 1.4, "lines.markersize": 4.0,
|
||||||
|
"figure.figsize": (3.15, 2.36), "pdf.fonttype": 42,
|
||||||
|
})
|
||||||
|
AXES_RECT = dict(left=0.205, right=0.965, top=0.955, bottom=0.185)
|
||||||
|
|
||||||
|
LBL = {
|
||||||
|
"edma": "EDMA",
|
||||||
|
"blind": "Affinity-blind",
|
||||||
|
"oma": "OMA",
|
||||||
|
"genie": "Genie-aided SIC bound",
|
||||||
|
"sic": "Realizable analog SIC",
|
||||||
|
"todma": "ToDMA-adapted",
|
||||||
|
"mac": "MAC sum capacity",
|
||||||
|
"coop": "Full-cooperation bound",
|
||||||
|
"hybrid": "EDMA + refinement stage",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def rows_of(name):
|
||||||
|
return list(csv.DictReader(open(DATA / f"{name}.csv")))
|
||||||
|
|
||||||
|
|
||||||
|
def col(rows, k):
|
||||||
|
return [float(r[k]) for r in rows]
|
||||||
|
|
||||||
|
|
||||||
|
def save(fig, name):
|
||||||
|
fig.subplots_adjust(**AXES_RECT)
|
||||||
|
fig.savefig(FIG / f"{name}.pdf")
|
||||||
|
plt.close(fig)
|
||||||
|
print(f"[OK] wrote {name}.pdf")
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------ fig_floor
|
||||||
|
def fig_floor():
|
||||||
|
rows = rows_of("floor_validation")
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
colors = {"256": "C0", "768": "C3"}
|
||||||
|
beta = 0.311
|
||||||
|
for d in ("256", "768"):
|
||||||
|
rd = [r for r in rows if r["d"] == d or r["d"] == f"{d}.0"
|
||||||
|
or float(r["d"]) == float(d)]
|
||||||
|
snr = col(rd, "snr_db")
|
||||||
|
ax.plot(snr, col(rd, "mse_mc"), "o", ms=3.5, color=colors[d],
|
||||||
|
mfc="none", label=rf"Monte Carlo, $d={d}$")
|
||||||
|
ax.plot(snr, col(rd, "mse_theory"), "-", color=colors[d],
|
||||||
|
label=rf"Theorem 1, $d={d}$")
|
||||||
|
if d == "768":
|
||||||
|
ax.plot(snr, col(rd, "mse_blind"), "--", color="C1", lw=1.2,
|
||||||
|
label=LBL["blind"])
|
||||||
|
g = 1.0 - beta**2
|
||||||
|
ax.axhline(math.sqrt(g) / 2, color="gray", lw=0.8, ls="--")
|
||||||
|
ax.axhline(0.5, color="gray", lw=0.8, ls=":")
|
||||||
|
ax.annotate("blind floor $1/2$", xy=(17.0, 0.512), fontsize=7,
|
||||||
|
color="gray")
|
||||||
|
ax.annotate(r"aware floor $\sqrt{1-\beta^2}/2$", xy=(14.0, 0.432),
|
||||||
|
fontsize=7, color="gray")
|
||||||
|
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
||||||
|
ax.set_ylabel(r"Per-user MSE $\mathbb{E}\|\hat{\mathbf{e}}_u-\mathbf{e}_u\|_2^2$")
|
||||||
|
ax.set_xlim(0, 40); ax.set_ylim(0.4, 1.05)
|
||||||
|
ax.legend(loc="lower left", bbox_to_anchor=(0.02, 0.18))
|
||||||
|
save(fig, "fig_floor")
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------ fig_rate_corrected
|
||||||
|
def fig_rate():
|
||||||
|
rows = rows_of("rate_corrected")
|
||||||
|
snr = col(rows, "snr_db")
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
ax.plot(snr, col(rows, "edma"), "-", color="C3", label=LBL["edma"])
|
||||||
|
ax.plot(snr, col(rows, "blind"), ":", color="C4", lw=1.2,
|
||||||
|
label=LBL["blind"])
|
||||||
|
ax.plot(snr, col(rows, "oma"), "--", color="C1", label=LBL["oma"])
|
||||||
|
ax.plot(snr, col(rows, "genie"), "-.", color="C0", label=LBL["genie"])
|
||||||
|
ax.plot(snr, col(rows, "mac"), "-", color="k", lw=1.0, label=LBL["mac"])
|
||||||
|
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
||||||
|
ax.set_ylabel("Effective sum rate [bps/Hz]")
|
||||||
|
ax.set_xlim(0, 40); ax.set_ylim(0, 3.2)
|
||||||
|
ax.legend(loc="upper left")
|
||||||
|
save(fig, "fig_rate_corrected")
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------ fig_beta_sweep_corrected
|
||||||
|
def fig_beta_sweep():
|
||||||
|
rows = rows_of("beta_sweep_corrected")
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
for s, cc in (("10", "C0"), ("20", "C3")):
|
||||||
|
rd = [r for r in rows if float(r["snr_db"]) == float(s)]
|
||||||
|
b = col(rd, "beta")
|
||||||
|
ax.plot(b, col(rd, "edma"), "-", color=cc,
|
||||||
|
label=rf"EDMA, $\rho={s}$ dB")
|
||||||
|
ax.axhline(float(rd[0]["blind"]), color=cc, ls=":", lw=1.0)
|
||||||
|
ax.axhline(float(rd[0]["oma"]), color=cc, ls="--", lw=1.0)
|
||||||
|
ax.axhline(float(rd[0]["genie"]), color=cc, ls="-.", lw=0.8)
|
||||||
|
# one legend entry per reference style (color-independent)
|
||||||
|
ax.plot([], [], ls=":", color="gray", label=LBL["blind"])
|
||||||
|
ax.plot([], [], ls="--", color="gray", label=LBL["oma"])
|
||||||
|
ax.plot([], [], ls="-.", color="gray", label=LBL["genie"])
|
||||||
|
for b0 in (0.030, 0.311):
|
||||||
|
ax.axvline(b0, color="gray", ls=":", lw=0.9)
|
||||||
|
ax.set_xlabel(r"Pairwise affinity $\beta$")
|
||||||
|
ax.set_ylabel("Effective sum rate [bps/Hz]")
|
||||||
|
ax.set_xlim(0, 1); ax.set_ylim(0, 1.0)
|
||||||
|
ax.legend(loc="upper left")
|
||||||
|
save(fig, "fig_beta_sweep_corrected")
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------- fig_sic
|
||||||
|
def fig_sic():
|
||||||
|
rows = rows_of("sic_comparison")
|
||||||
|
snr = col(rows, "snr_db")
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
ax.plot(snr, col(rows, "edma"), "o-", color="C3", label=LBL["edma"])
|
||||||
|
ax.plot(snr, col(rows, "blind"), "d:", color="C4", label=LBL["blind"])
|
||||||
|
ax.plot(snr, col(rows, "sic"), "^-.", color="C2", label=LBL["sic"])
|
||||||
|
ax.plot(snr, col(rows, "oma"), "v--", color="C1", label=LBL["oma"])
|
||||||
|
ax.plot(snr, col(rows, "genie"), "-", color="gray", lw=1.0,
|
||||||
|
label=LBL["genie"])
|
||||||
|
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
||||||
|
ax.set_ylabel("Mean cosine similarity")
|
||||||
|
ax.set_xlim(snr[0], snr[-1]); ax.set_ylim(0, 0.7)
|
||||||
|
ax.legend(loc="upper left")
|
||||||
|
save(fig, "fig_sic")
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------ fig_multiuser_corrected
|
||||||
|
def fig_multiuser():
|
||||||
|
rows = rows_of("multiuser_corrected")
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
colors = {"2": "C0", "3": "C2", "4": "C3"}
|
||||||
|
for U in ("2", "3", "4"):
|
||||||
|
rd = [r for r in rows if float(r["U"]) == float(U)]
|
||||||
|
snr = col(rd, "snr_db")
|
||||||
|
ax.plot(snr, col(rd, "edma_mc"), "-", color=colors[U],
|
||||||
|
label=rf"EDMA, $U={U}$")
|
||||||
|
ax.plot(snr, col(rd, "oma"), "--", color=colors[U], lw=1.0,
|
||||||
|
label=rf"OMA, $U={U}$")
|
||||||
|
mk = [i for i, s in enumerate(snr) if s % 5 == 0]
|
||||||
|
ax.plot([snr[i] for i in mk], [col(rd, "edma_mc")[i] for i in mk],
|
||||||
|
"o", color=colors[U], ms=4, mfc="none")
|
||||||
|
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
||||||
|
ax.set_ylabel("Effective sum rate [bps/Hz]")
|
||||||
|
ax.set_xlim(0, 30)
|
||||||
|
ax.legend(loc="upper left")
|
||||||
|
save(fig, "fig_multiuser_corrected")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
todo = set(sys.argv[1:])
|
||||||
|
ALL = {"floor": fig_floor, "rate": fig_rate, "beta": fig_beta_sweep,
|
||||||
|
"sic": fig_sic, "multi": fig_multiuser}
|
||||||
|
for name, fn in ALL.items():
|
||||||
|
if not todo or name in todo:
|
||||||
|
fn()
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
"""Canonical replot of fig_bertvit_merged.pdf from data/bertvit_merged.csv.
|
"""Canonical replot of fig_bertvit_merged.pdf from data/bertvit_merged.csv.
|
||||||
Curves: EDMA, EDMA + refinement (hybrid), ToDMA-adapted, OMA, genie bound.
|
Curves: EDMA, EDMA + refinement (hybrid), ToDMA-adapted, OMA, genie bound.
|
||||||
The attention columns remain in the CSV but are not plotted."""
|
The capacity-check column edma_ref2 remains in the CSV but is not
|
||||||
|
plotted (it tracks edma_ref; quoted in the text only)."""
|
||||||
import csv
|
import csv
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import matplotlib
|
import matplotlib
|
||||||
@@ -24,7 +25,7 @@ snr = [float(r["snr_db"]) for r in rows]
|
|||||||
col = lambda k: [float(r[k]) for r in rows]
|
col = lambda k: [float(r[k]) for r in rows]
|
||||||
|
|
||||||
fig, ax = plt.subplots()
|
fig, ax = plt.subplots()
|
||||||
ax.plot(snr, col("edma"), "o-", color="C3", label="EDMA (closed form)")
|
ax.plot(snr, col("edma"), "o-", color="C3", label="EDMA")
|
||||||
ax.plot(snr, col("edma_ref"), "^-", color="C2",
|
ax.plot(snr, col("edma_ref"), "^-", color="C2",
|
||||||
label="EDMA + refinement stage")
|
label="EDMA + refinement stage")
|
||||||
ax.plot(snr, col("todma"), "d-.", color="C4", label="ToDMA-adapted")
|
ax.plot(snr, col("todma"), "d-.", color="C4", label="ToDMA-adapted")
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
"""Canonical replot of fig_sic.pdf from data/sic_comparison.csv
|
|
||||||
(realizable analog SIC vs genie SIC vs EDMA vs OMA, beta = 0.311,
|
|
||||||
d = 512, block-Rayleigh). US-spelling labels, uniform geometry."""
|
|
||||||
import csv
|
|
||||||
from pathlib import Path
|
|
||||||
import matplotlib
|
|
||||||
matplotlib.use("Agg")
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
|
||||||
plt.rcParams.update({
|
|
||||||
"font.family": "serif",
|
|
||||||
"font.serif": ["DejaVu Serif", "Times New Roman"],
|
|
||||||
"font.size": 9, "axes.labelsize": 9, "legend.fontsize": 6.6,
|
|
||||||
"xtick.labelsize": 8, "ytick.labelsize": 8,
|
|
||||||
"axes.grid": True, "grid.linestyle": "--", "grid.linewidth": 0.4,
|
|
||||||
"grid.alpha": 0.6, "lines.linewidth": 1.4, "lines.markersize": 4.0,
|
|
||||||
"figure.figsize": (3.15, 2.36), "pdf.fonttype": 42,
|
|
||||||
})
|
|
||||||
AXES_RECT = dict(left=0.205, right=0.965, top=0.955, bottom=0.185)
|
|
||||||
|
|
||||||
rows = list(csv.DictReader(open(ROOT / "data" / "sic_comparison.csv")))
|
|
||||||
snr = [float(r["snr_db"]) for r in rows]
|
|
||||||
col = lambda k: [float(r[k]) for r in rows]
|
|
||||||
|
|
||||||
fig, ax = plt.subplots()
|
|
||||||
ax.plot(snr, col("edma"), "o-", color="C3", label="EDMA (closed form)")
|
|
||||||
ax.plot(snr, col("sic"), "^-.", color="C2", label="Realizable analog SIC")
|
|
||||||
ax.plot(snr, col("oma"), "v:", color="C1", label="OMA")
|
|
||||||
ax.plot(snr, col("genie"), "-", color="gray", lw=1.0,
|
|
||||||
label="Genie-aided SIC bound")
|
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
|
||||||
ax.set_ylabel("Mean cosine similarity")
|
|
||||||
ax.set_xlim(snr[0], snr[-1])
|
|
||||||
ax.set_ylim(0, 0.7)
|
|
||||||
ax.legend(loc="upper left")
|
|
||||||
fig.subplots_adjust(**AXES_RECT)
|
|
||||||
fig.savefig(ROOT / "fig" / "fig_sic.pdf")
|
|
||||||
print("[OK] wrote fig_sic.pdf")
|
|
||||||
for r in rows:
|
|
||||||
print(f" {float(r['snr_db']):4.0f} dB EDMA {float(r['edma']):.3f} "
|
|
||||||
f"SIC {float(r['sic']):.3f} genie {float(r['genie']):.3f} "
|
|
||||||
f"OMA {float(r['oma']):.3f}")
|
|
||||||
+182
-449
@@ -1,26 +1,45 @@
|
|||||||
"""
|
"""
|
||||||
Revision simulations for the EDMA TCOM resubmission.
|
Simulations for the EDMA TVT manuscript (v2 design).
|
||||||
=======================================================
|
=======================================================
|
||||||
Implements the per-realisation (finite-d) analysis and the corrected
|
Design v2: each user applies an independent orthogonal mask; the
|
||||||
energy-normalised rate accounting, plus the reviewer-requested
|
receiver runs one matched filter per user followed by the
|
||||||
experiments:
|
affinity-aware linear MMSE demultiplexer, which exploits the
|
||||||
|
coherent interference component that the pairwise affinity beta
|
||||||
|
predicts. Per-realization statistic for user 1 (c1 = h2/h1):
|
||||||
|
|
||||||
E0 Theorem-1 verification: exact self-interference constant C_SI
|
t1 = (I + beta*c1*Q) e1 + sqrt(g)*c1*Q w + n_t, Q = M1^T M2,
|
||||||
E1 fig_floor : per-user MSE vs block SNR, interference floor
|
|
||||||
E2 fig_sic : realisable SIC vs genie SIC vs EDMA vs OMA
|
|
||||||
E3 (text numbers) : Rayleigh unconditional MSE, ZF vs regularised
|
|
||||||
E4 fig_csi : imperfect-CSI robustness
|
|
||||||
E5 fig_maskfam : Walsh-Hadamard structured masks vs Haar
|
|
||||||
E6 fig_coop : high-affinity combining-mode crossover
|
|
||||||
E7 fig_rate_corrected, fig_beta_sweep_corrected, fig_multiuser_corrected
|
|
||||||
|
|
||||||
Conventions (identical to the revised manuscript):
|
and the demultiplexer is the Wiener filter
|
||||||
|
|
||||||
|
e1_hat = (1/d) A^H (A A^H/d + (g|c1|^2/d + sig^2/|h1|^2) I)^{-1} t1,
|
||||||
|
A = I + beta*c1*Q, g = 1 - beta^2.
|
||||||
|
|
||||||
|
Closed form (Theorem 1, d -> inf, per channel realization):
|
||||||
|
|
||||||
|
MSE_1 = rho_e / sqrt((1 + beta^2|c1|^2 + rho_e)^2 - 4 beta^2|c1|^2),
|
||||||
|
rho_e = g|c1|^2 + d sig^2/|h1|^2; floor at |c1| = 1: sqrt(g)/2.
|
||||||
|
|
||||||
|
The affinity-blind receiver (beta = 0 in the filter) reduces to a
|
||||||
|
scalar shrinkage of the matched filter with floor 1/2, so the entire
|
||||||
|
cosine gain of the aware receiver is attributable to the predicted
|
||||||
|
affinity. Effective SINR: eta = 1/MSE - 1 (biased MMSE convention).
|
||||||
|
|
||||||
|
Experiments in this file (CPU, numpy):
|
||||||
|
E0 theorem_check : closed form vs Monte Carlo, both users
|
||||||
|
E1 fig_floor : per-user MSE vs block SNR, aware vs blind floor
|
||||||
|
E7a rate_corrected + beta_sweep_corrected : closed-form rate curves
|
||||||
|
|
||||||
|
The Monte Carlo experiments E2, E3, E4, E5, E7c, E8, E9 are canonical
|
||||||
|
in revision_sims_gpu.py (torch backend, run under WSL); figures are
|
||||||
|
rendered from data/ by replot_all.py and replot_merged.py.
|
||||||
|
|
||||||
|
Conventions (identical to the manuscript):
|
||||||
* unit per-block transmit energy E_b = 1 per user
|
* unit per-block transmit energy E_b = 1 per user
|
||||||
* rho = E_b / sigma_n^2 (per-block received SNR; per-symbol SNR rho/d)
|
* rho = E_b / sigma_n^2 (per-block received SNR; per-symbol SNR rho/d)
|
||||||
* block-Rayleigh h ~ CN(0,1) unless the AWGN point |h|=1 is stated
|
* block-Rayleigh h ~ CN(0,1) unless the AWGN point |h|=1 is stated
|
||||||
* complex AWGN CN(0, sigma^2 I_d); embeddings real, unit norm
|
* complex AWGN CN(0, sigma^2 I_d); embeddings real, unit norm
|
||||||
* orientation convention <e1,e2> = +beta
|
* orientation convention <e1,e2> = +beta
|
||||||
Fixed seed. CSVs -> ../fig, PDFs -> ../fig_toc.
|
Fixed seed 2026. CSVs -> ../data, PDFs -> ../fig.
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import csv
|
import csv
|
||||||
@@ -39,13 +58,27 @@ plt.rcParams.update({
|
|||||||
"font.family": "serif",
|
"font.family": "serif",
|
||||||
"font.serif": ["DejaVu Serif", "Times New Roman"],
|
"font.serif": ["DejaVu Serif", "Times New Roman"],
|
||||||
"font.size": 9, "axes.labelsize": 9, "axes.titlesize": 9,
|
"font.size": 9, "axes.labelsize": 9, "axes.titlesize": 9,
|
||||||
"legend.fontsize": 7.0, "xtick.labelsize": 8, "ytick.labelsize": 8,
|
"legend.fontsize": 6.6, "xtick.labelsize": 8, "ytick.labelsize": 8,
|
||||||
"axes.grid": True, "grid.linestyle": "--", "grid.linewidth": 0.4,
|
"axes.grid": True, "grid.linestyle": "--", "grid.linewidth": 0.4,
|
||||||
"grid.alpha": 0.6, "lines.linewidth": 1.4, "lines.markersize": 4.0,
|
"grid.alpha": 0.6, "lines.linewidth": 1.4, "lines.markersize": 4.0,
|
||||||
"figure.figsize": (3.15, 2.36), "pdf.fonttype": 42,
|
"figure.figsize": (3.15, 2.36), "pdf.fonttype": 42,
|
||||||
})
|
})
|
||||||
AXES_RECT = dict(left=0.205, right=0.965, top=0.955, bottom=0.185)
|
AXES_RECT = dict(left=0.205, right=0.965, top=0.955, bottom=0.185)
|
||||||
|
|
||||||
|
# shared legend-label dictionary (single source for every figure)
|
||||||
|
LBL = {
|
||||||
|
"edma": "EDMA",
|
||||||
|
"blind": "Affinity-blind",
|
||||||
|
"oma": "OMA",
|
||||||
|
"genie": "Genie-aided SIC bound",
|
||||||
|
"sic": "Realizable analog SIC",
|
||||||
|
"todma": "ToDMA-adapted",
|
||||||
|
"mac": "MAC sum capacity",
|
||||||
|
"hybrid": "EDMA + refinement stage",
|
||||||
|
"haar": "Haar masks",
|
||||||
|
"wh": "Walsh-Hadamard masks",
|
||||||
|
}
|
||||||
|
|
||||||
rng = np.random.default_rng(2026)
|
rng = np.random.default_rng(2026)
|
||||||
|
|
||||||
|
|
||||||
@@ -86,69 +119,80 @@ def embed_pair(d, beta):
|
|||||||
return e1, e2
|
return e1, e2
|
||||||
|
|
||||||
|
|
||||||
def two_user_masks(d, beta, U1=None, U2=None):
|
|
||||||
if U1 is None: U1 = haar(d)
|
|
||||||
if U2 is None: U2 = haar(d)
|
|
||||||
g = math.sqrt(1.0 - beta**2)
|
|
||||||
return U1, beta * U1 + g * U2
|
|
||||||
|
|
||||||
|
|
||||||
def rayleigh(n=1):
|
def rayleigh(n=1):
|
||||||
return (rng.standard_normal(n) + 1j * rng.standard_normal(n)) / math.sqrt(2)
|
return (rng.standard_normal(n) + 1j * rng.standard_normal(n)) / math.sqrt(2)
|
||||||
|
|
||||||
|
|
||||||
def C_SI(beta, c):
|
def cnoise(d):
|
||||||
"""User-1 self-interference constant (exact to O(1/d)), <e1,e2>=+beta."""
|
return (rng.standard_normal(d) + 1j * rng.standard_normal(d)) / math.sqrt(2)
|
||||||
g = 1.0 - beta**2
|
|
||||||
return (g**2 * abs(c)**2 + beta**2 + beta**4 * abs(c)**2
|
|
||||||
+ 2.0 * beta**4 * np.real(c)) / g
|
|
||||||
|
|
||||||
|
|
||||||
def C_SI2(beta, c2):
|
|
||||||
"""User-2 self-interference constant (deterministic), c2 = h1/h2."""
|
|
||||||
g = 1.0 - beta**2
|
|
||||||
return (abs(c2)**2 + beta**2 + 2.0 * beta**2 * np.real(c2)) / g
|
|
||||||
|
|
||||||
|
|
||||||
def C_bar(beta):
|
|
||||||
"""Symmetrised constant at |h|=1 (block-alternating mask roles)."""
|
|
||||||
return 0.5 * (C_SI(beta, 1.0 + 0j) + C_SI2(beta, 1.0 + 0j))
|
|
||||||
|
|
||||||
|
|
||||||
def demux(r, M1, M2, h1, h2, beta):
|
|
||||||
"""beta-aware demultiplexer (13); returns (e1_hat, e2_hat)."""
|
|
||||||
g = 1.0 - beta**2
|
|
||||||
t1 = (M1.T @ r) / h1
|
|
||||||
t2 = (M2.T @ r) / h2
|
|
||||||
e1 = (t1 - beta * (h2 / h1) * t2) / g
|
|
||||||
e2 = (t2 - beta * (h1 / h2) * t1) / g
|
|
||||||
return e1, e2
|
|
||||||
|
|
||||||
|
|
||||||
def cosine(a, b):
|
def cosine(a, b):
|
||||||
return abs(np.vdot(a, b)) / (np.linalg.norm(a) * np.linalg.norm(b))
|
return abs(np.vdot(a, b)) / (np.linalg.norm(a) * np.linalg.norm(b))
|
||||||
|
|
||||||
|
|
||||||
|
def mse_theory(beta, c1, rho_e):
|
||||||
|
"""Theorem 1: per-realization MSE of the aware demultiplexer."""
|
||||||
|
a0 = 1.0 + beta**2 * abs(c1)**2 + rho_e
|
||||||
|
return rho_e / math.sqrt(a0 * a0 - 4.0 * beta**2 * abs(c1)**2)
|
||||||
|
|
||||||
|
|
||||||
|
def mse_blind(c1, dsig2_h):
|
||||||
|
"""Affinity-blind scalar-shrinkage MSE (beta = 0 in the filter)."""
|
||||||
|
r0 = abs(c1)**2 + dsig2_h
|
||||||
|
return r0 / (1.0 + r0)
|
||||||
|
|
||||||
|
|
||||||
|
def eta_of(mse):
|
||||||
|
"""Effective SINR of a (possibly biased) estimator with unit signal."""
|
||||||
|
return 1.0 / mse - 1.0
|
||||||
|
|
||||||
|
|
||||||
|
def aware(t1, Q, beta, c1, nvar, d):
|
||||||
|
"""Affinity-aware Wiener demultiplexer applied to t1 = M1^T r / h1.
|
||||||
|
|
||||||
|
Uses A A^H = (1+beta^2|c1|^2) I + beta(c1 Q + conj(c1) Q^T), so the
|
||||||
|
system matrix is assembled in O(d^2) and solved with one LU."""
|
||||||
|
g = 1.0 - beta * beta
|
||||||
|
rho = g * abs(c1)**2 / d + nvar
|
||||||
|
S = beta * (c1 * Q + np.conj(c1) * Q.T) / d
|
||||||
|
S[np.diag_indices(d)] += (1.0 + beta**2 * abs(c1)**2) / d + rho
|
||||||
|
x = np.linalg.solve(S, t1)
|
||||||
|
return (x + beta * np.conj(c1) * (Q.T @ x)) / d
|
||||||
|
|
||||||
|
|
||||||
|
def blind(t1, c1, nvar, d):
|
||||||
|
"""Affinity-blind receiver: scalar shrinkage of the matched filter."""
|
||||||
|
lam = (1.0 / d) / (1.0 / d + abs(c1)**2 / d + nvar)
|
||||||
|
return lam * t1
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# E0 : Theorem-1 verification
|
# E0 : Theorem-1 verification (both users, random phases)
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
def E0_theorem_check(d=512, betas=(0.0, 0.311, 0.5, 0.7), ntr=300):
|
def E0_theorem_check(d=512, betas=(0.0, 0.311, 0.5, 0.7), ntr=200, snr=20.0):
|
||||||
print("\n=== E0: Theorem 1 (self-interference constant) verification ===")
|
print("\n=== E0: Theorem 1 (aware-demultiplexer MSE) verification ===")
|
||||||
|
sig = 10 ** (-snr / 20.0)
|
||||||
rows = []
|
rows = []
|
||||||
worst = 0.0
|
worst = 0.0
|
||||||
for beta in betas:
|
for beta in betas:
|
||||||
# random unit-modulus channels (AWGN-type magnitude, random phase)
|
g = 1.0 - beta**2
|
||||||
errs1, errs2 = [], []
|
r1s, r2s = [], []
|
||||||
for _ in range(ntr):
|
for _ in range(ntr):
|
||||||
h1 = np.exp(1j * rng.uniform(0, 2 * np.pi))
|
h1 = np.exp(1j * rng.uniform(0, 2 * np.pi))
|
||||||
h2 = np.exp(1j * rng.uniform(0, 2 * np.pi))
|
h2 = np.exp(1j * rng.uniform(0, 2 * np.pi))
|
||||||
e1, e2 = embed_pair(d, beta)
|
e1, e2 = embed_pair(d, beta)
|
||||||
M1, M2 = two_user_masks(d, beta)
|
M1, M2 = haar(d), haar(d)
|
||||||
r = h1 * (M1 @ e1) + h2 * (M2 @ e2) # noise-free
|
Q = M1.T @ M2
|
||||||
g1, g2 = demux(r, M1, M2, h1, h2, beta)
|
r = h1 * (M1 @ e1) + h2 * (M2 @ e2) + sig * cnoise(d)
|
||||||
errs1.append(np.linalg.norm(g1 - e1)**2 / C_SI(beta, h2 / h1))
|
c1, c2 = h2 / h1, h1 / h2
|
||||||
errs2.append(np.linalg.norm(g2 - e2)**2 / C_SI2(beta, h1 / h2))
|
g1 = aware(M1.T @ r / h1, Q, beta, c1, sig**2 / abs(h1)**2, d)
|
||||||
r1, r2 = float(np.mean(errs1)), float(np.mean(errs2))
|
g2 = aware(M2.T @ r / h2, Q.T, beta, c2, sig**2 / abs(h2)**2, d)
|
||||||
|
th1 = mse_theory(beta, c1, g * abs(c1)**2 + d * sig**2 / abs(h1)**2)
|
||||||
|
th2 = mse_theory(beta, c2, g * abs(c2)**2 + d * sig**2 / abs(h2)**2)
|
||||||
|
r1s.append(np.linalg.norm(g1 - e1)**2 / th1)
|
||||||
|
r2s.append(np.linalg.norm(g2 - e2)**2 / th2)
|
||||||
|
r1, r2 = float(np.mean(r1s)), float(np.mean(r2s))
|
||||||
dev = max(abs(r1 - 1.0), abs(r2 - 1.0)) * 100
|
dev = max(abs(r1 - 1.0), abs(r2 - 1.0)) * 100
|
||||||
worst = max(worst, dev)
|
worst = max(worst, dev)
|
||||||
print(f" beta={beta:.3f} MC/theory user1 = {r1:.4f}, user2 = {r2:.4f}"
|
print(f" beta={beta:.3f} MC/theory user1 = {r1:.4f}, user2 = {r2:.4f}"
|
||||||
@@ -161,12 +205,11 @@ def E0_theorem_check(d=512, betas=(0.0, 0.311, 0.5, 0.7), ntr=300):
|
|||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# E1 : interference floor (MSE vs block SNR), AWGN point |h|=1
|
# E1 : MSE vs block SNR at |h|=1 -- aware floor sqrt(g)/2 vs blind 1/2
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
def E1_floor(beta=0.311, dims=(256, 768), snr_db=np.arange(0, 41, 2.5), ntr=150):
|
def E1_floor(beta=0.311, dims=(256, 768), snr_db=np.arange(0, 41, 2.5), ntr=120):
|
||||||
print("\n=== E1: finite-d interference floor ===")
|
print("\n=== E1: finite-d validation, aware vs blind floor ===")
|
||||||
g = 1.0 - beta**2
|
g = 1.0 - beta**2
|
||||||
csi = C_SI(beta, 1.0 + 0j)
|
|
||||||
fig, ax = plt.subplots()
|
fig, ax = plt.subplots()
|
||||||
colors = {256: "C0", 768: "C3"}
|
colors = {256: "C0", 768: "C3"}
|
||||||
rows = []
|
rows = []
|
||||||
@@ -174,444 +217,134 @@ def E1_floor(beta=0.311, dims=(256, 768), snr_db=np.arange(0, 41, 2.5), ntr=150)
|
|||||||
mc = np.zeros(len(snr_db))
|
mc = np.zeros(len(snr_db))
|
||||||
for _ in range(ntr):
|
for _ in range(ntr):
|
||||||
e1, e2 = embed_pair(d, beta)
|
e1, e2 = embed_pair(d, beta)
|
||||||
M1, M2 = two_user_masks(d, beta)
|
M1, M2 = haar(d), haar(d)
|
||||||
|
Q = M1.T @ M2
|
||||||
r0 = (M1 @ e1) + (M2 @ e2)
|
r0 = (M1 @ e1) + (M2 @ e2)
|
||||||
n = (rng.standard_normal(d) + 1j * rng.standard_normal(d)) / math.sqrt(2)
|
n = cnoise(d)
|
||||||
for k, s in enumerate(snr_db):
|
for k, s in enumerate(snr_db):
|
||||||
sig = 10 ** (-s / 20.0)
|
sig = 10 ** (-s / 20.0)
|
||||||
g1, _ = demux(r0 + sig * n, M1, M2, 1.0, 1.0, beta)
|
g1 = aware(M1.T @ (r0 + sig * n), Q, beta, 1.0, sig**2, d)
|
||||||
mc[k] += np.linalg.norm(g1 - e1)**2
|
mc[k] += np.linalg.norm(g1 - e1)**2
|
||||||
mc /= ntr
|
mc /= ntr
|
||||||
rho = 10 ** (snr_db / 10.0)
|
rho = 10 ** (snr_db / 10.0)
|
||||||
th = d / (rho * g) + csi
|
th = np.array([mse_theory(beta, 1.0, g + d / r) for r in rho])
|
||||||
ideal = d / (rho * g)
|
bl = np.array([mse_blind(1.0, d / r) for r in rho])
|
||||||
ax.semilogy(snr_db, mc, "o", ms=3.5, color=colors[d], mfc="none",
|
ax.semilogy(snr_db, mc, "o", ms=3.5, color=colors[d], mfc="none",
|
||||||
label=rf"MC, $d={d}$")
|
label=rf"Monte Carlo, $d={d}$")
|
||||||
ax.semilogy(snr_db, th, "-", color=colors[d],
|
ax.semilogy(snr_db, th, "-", color=colors[d],
|
||||||
label=rf"Theorem 1, $d={d}$")
|
label=rf"Theorem 1, $d={d}$")
|
||||||
if d == dims[-1]:
|
if d == dims[-1]:
|
||||||
ax.semilogy(snr_db, ideal, ":", color="k", lw=1.1,
|
ax.semilogy(snr_db, bl, "--", color="C1", lw=1.1,
|
||||||
label="Idealized (no floor)")
|
label=LBL["blind"])
|
||||||
for s, m, t, i in zip(snr_db, mc, th, ideal):
|
for s, m, t, b in zip(snr_db, mc, th, bl):
|
||||||
rows.append([d, s, m, t, i])
|
rows.append([d, s, m, t, b])
|
||||||
onset = 10 * math.log10(d / (g * csi))
|
dev = 100 * max(abs(mc / th - 1))
|
||||||
print(f" d={d}: floor C_SI={csi:.4f}, onset ~{onset:.1f} dB, "
|
print(f" d={d}: max MC/theory dev {dev:.1f}%")
|
||||||
f"max MC/theory dev "
|
ax.axhline(math.sqrt(g) / 2, color="gray", lw=0.8, ls="--")
|
||||||
f"{100*max(abs(mc/th-1)):.1f}%")
|
ax.axhline(0.5, color="gray", lw=0.8, ls=":")
|
||||||
ax.axhline(csi, color="gray", lw=0.8, ls="--")
|
ax.text(1.0, 0.52, r"blind floor $1/2$", fontsize=7, color="gray")
|
||||||
ax.text(1.0, csi * 1.15, r"floor $C_{\mathrm{SI}}$", fontsize=7, color="gray")
|
ax.text(22.0, 0.40, r"aware floor $\sqrt{1-\beta^2}/2$",
|
||||||
|
fontsize=7, color="gray")
|
||||||
|
ax.set_yscale("linear")
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
||||||
ax.set_ylabel(r"Per-user MSE $\mathbb{E}\|\hat{\mathbf{e}}_u-\mathbf{e}_u\|_2^2$")
|
ax.set_ylabel(r"Per-user MSE $\mathbb{E}\|\hat{\mathbf{e}}_u-\mathbf{e}_u\|_2^2$")
|
||||||
ax.set_xlim(0, 40); ax.set_ylim(0.5, 2000)
|
ax.set_xlim(0, 40); ax.set_ylim(0.4, 1.05)
|
||||||
ax.legend(loc="upper right", ncol=1)
|
ax.legend(loc="upper right", ncol=1)
|
||||||
save_fig(fig, "fig_floor")
|
save_fig(fig, "fig_floor")
|
||||||
write_csv("floor_validation", ["d", "snr_db", "mse_mc", "mse_theory", "mse_ideal"], rows)
|
write_csv("floor_validation",
|
||||||
|
["d", "snr_db", "mse_mc", "mse_theory", "mse_blind"], rows)
|
||||||
|
print(f" aware floor {math.sqrt(g)/2:.4f} vs blind floor 0.5000 "
|
||||||
|
f"(ratio {0.5/(math.sqrt(g)/2):.4f} = 1/sqrt(1-beta^2))")
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# E2 : realisable SIC vs genie SIC vs EDMA vs OMA (Rayleigh)
|
# E7 : effective-rate figures (eta = 1/MSE - 1)
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
def E2_sic(beta=0.311, d=512, snr_db=np.arange(0, 31, 5), ntr=400):
|
def T_edma(rho, d, beta):
|
||||||
print("\n=== E2: realisable vs genie SIC (Rayleigh) ===")
|
m = mse_theory(beta, 1.0, (1.0 - beta**2) + d / rho)
|
||||||
res = {k: np.zeros(len(snr_db)) for k in
|
return 2.0 * math.log2(1.0 + eta_of(m))
|
||||||
("edma", "oma", "genie", "sic")}
|
|
||||||
for _ in range(ntr):
|
|
||||||
e1, e2 = embed_pair(d, beta)
|
|
||||||
M1, M2 = two_user_masks(d, beta)
|
|
||||||
h1, h2 = rayleigh(2)
|
|
||||||
r0 = h1 * (M1 @ e1) + h2 * (M2 @ e2)
|
|
||||||
n = (rng.standard_normal(d) + 1j * rng.standard_normal(d)) / math.sqrt(2)
|
|
||||||
n2 = (rng.standard_normal(d) + 1j * rng.standard_normal(d)) / math.sqrt(2)
|
|
||||||
for k, s in enumerate(snr_db):
|
|
||||||
sig = 10 ** (-s / 20.0)
|
|
||||||
r = r0 + sig * n
|
|
||||||
# EDMA
|
|
||||||
g1, g2 = demux(r, M1, M2, h1, h2, beta)
|
|
||||||
res["edma"][k] += 0.5 * (cosine(g1, e1) + cosine(g2, e2))
|
|
||||||
# OMA equivalent-bandwidth model: interference-free, noise x sqrt(2)
|
|
||||||
o1 = e1 + math.sqrt(2) * sig * n / h1
|
|
||||||
o2 = e2 + math.sqrt(2) * sig * n2 / h2
|
|
||||||
res["oma"][k] += 0.5 * (cosine(o1, e1) + cosine(o2, e2))
|
|
||||||
# genie SIC: perfect removal of the other user for BOTH users
|
|
||||||
ge1 = M1.T @ (r - h2 * (M2 @ e2)) / h1
|
|
||||||
ge2 = M2.T @ (r - h1 * (M1 @ e1)) / h2
|
|
||||||
res["genie"][k] += 0.5 * (cosine(ge1, e1) + cosine(ge2, e2))
|
|
||||||
# realisable SIC: stronger user first (matched filter),
|
|
||||||
# unit-norm projection as the analog decision, then subtract
|
|
||||||
if abs(h1) >= abs(h2):
|
|
||||||
hs, hw, Ms, Mw, es, ew = h1, h2, M1, M2, e1, e2
|
|
||||||
else:
|
|
||||||
hs, hw, Ms, Mw, es, ew = h2, h1, M2, M1, e2, e1
|
|
||||||
d_s = Ms.T @ r / hs
|
|
||||||
dec_s = d_s / np.linalg.norm(d_s) # analog decision
|
|
||||||
r_res = r - hs * (Ms @ dec_s)
|
|
||||||
d_w = Mw.T @ r_res / hw
|
|
||||||
res["sic"][k] += 0.5 * (cosine(d_s, es) + cosine(d_w, ew))
|
|
||||||
for k in res:
|
|
||||||
res[k] /= ntr
|
|
||||||
fig, ax = plt.subplots()
|
|
||||||
ax.plot(snr_db, res["edma"], "o-", color="C3", label="EDMA")
|
|
||||||
ax.plot(snr_db, res["genie"], "s--", color="C0", label="Genie-aided SIC")
|
|
||||||
ax.plot(snr_db, res["sic"], "^-.", color="C2", label="Realisable SIC")
|
|
||||||
ax.plot(snr_db, res["oma"], "v:", color="C1", label="OMA")
|
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
|
||||||
ax.set_ylabel("Mean cosine similarity")
|
|
||||||
ax.set_xlim(snr_db[0], snr_db[-1]); ax.set_ylim(0, 1)
|
|
||||||
ax.legend(loc="upper left")
|
|
||||||
save_fig(fig, "fig_sic")
|
|
||||||
rows = [[s] + [res[k][i] for k in ("edma", "oma", "genie", "sic")]
|
|
||||||
for i, s in enumerate(snr_db)]
|
|
||||||
write_csv("sic_comparison", ["snr_db", "edma", "oma", "genie", "sic"], rows)
|
|
||||||
i20 = list(snr_db).index(20)
|
|
||||||
print(f" at 20 dB: EDMA {res['edma'][i20]:.3f}, realisable SIC "
|
|
||||||
f"{res['sic'][i20]:.3f}, genie {res['genie'][i20]:.3f}, "
|
|
||||||
f"OMA {res['oma'][i20]:.3f}")
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
def T_blind(rho, d):
|
||||||
# E3 : Rayleigh unconditional MSE ??ZF inversion vs regularised
|
return 2.0 * math.log2(1.0 + 1.0 / (1.0 + d / rho))
|
||||||
# ------------------------------------------------------------------
|
|
||||||
def E3_regularised(beta=0.311, d=512, snrs=(10, 20), ntr=4000):
|
|
||||||
print("\n=== E3: Rayleigh unconditional MSE, ZF vs regularised ===")
|
|
||||||
rows = []
|
|
||||||
for s in snrs:
|
|
||||||
sig = 10 ** (-s / 20.0)
|
|
||||||
sig2 = sig**2
|
|
||||||
mse_zf, mse_rg = [], []
|
|
||||||
for _ in range(ntr):
|
|
||||||
e1, e2 = embed_pair(d, beta)
|
|
||||||
M1, M2 = two_user_masks(d, beta)
|
|
||||||
h1, h2 = rayleigh(2)
|
|
||||||
r = h1 * (M1 @ e1) + h2 * (M2 @ e2) \
|
|
||||||
+ sig * (rng.standard_normal(d) + 1j * rng.standard_normal(d)) / math.sqrt(2)
|
|
||||||
g1, _ = demux(r, M1, M2, h1, h2, beta)
|
|
||||||
mse_zf.append(np.linalg.norm(g1 - e1)**2)
|
|
||||||
# regularised inversion: 1/h -> h*/(|h|^2 + d sigma^2)
|
|
||||||
eps = d * sig2
|
|
||||||
f1 = (abs(h1)**2 + eps) / np.conj(h1)
|
|
||||||
f2 = (abs(h2)**2 + eps) / np.conj(h2)
|
|
||||||
g1r, _ = demux(r, M1, M2, f1, f2, beta)
|
|
||||||
mse_rg.append(np.linalg.norm(g1r - e1)**2)
|
|
||||||
zf_mean, zf_med = float(np.mean(mse_zf)), float(np.median(mse_zf))
|
|
||||||
rg_mean, rg_med = float(np.mean(mse_rg)), float(np.median(mse_rg))
|
|
||||||
print(f" {s} dB: ZF mean {zf_mean:9.2f} (median {zf_med:6.2f}) | "
|
|
||||||
f"regularised mean {rg_mean:6.3f} (median {rg_med:6.3f})")
|
|
||||||
rows.append([s, zf_mean, zf_med, rg_mean, rg_med])
|
|
||||||
write_csv("rayleigh_mse", ["snr_db", "zf_mean", "zf_median",
|
|
||||||
"reg_mean", "reg_median"], rows)
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
# E4 : imperfect CSI
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
def E4_csi(beta=0.311, d=512, snr=30.0,
|
|
||||||
sh2=np.array([0.0, 0.01, 0.02, 0.05, 0.1, 0.2, 0.3]), ntr=400):
|
|
||||||
"""EDMA cosine is CSI-direction-invariant (h-estimates cancel in the
|
|
||||||
demux direction); realisable SIC degrades through its subtraction stage."""
|
|
||||||
print("\n=== E4: imperfect CSI robustness (EDMA vs realisable SIC) ===")
|
|
||||||
sig = 10 ** (-snr / 20.0)
|
|
||||||
res_e = np.zeros(len(sh2)); res_s = np.zeros(len(sh2))
|
|
||||||
for _ in range(ntr):
|
|
||||||
e1, e2 = embed_pair(d, beta)
|
|
||||||
M1, M2 = two_user_masks(d, beta)
|
|
||||||
h1, h2 = rayleigh(2)
|
|
||||||
r = h1 * (M1 @ e1) + h2 * (M2 @ e2) + sig * (
|
|
||||||
rng.standard_normal(d) + 1j * rng.standard_normal(d)) / math.sqrt(2)
|
|
||||||
eps1, eps2 = rayleigh(2)
|
|
||||||
for j, v in enumerate(sh2):
|
|
||||||
hh1 = h1 + math.sqrt(v) * eps1
|
|
||||||
hh2 = h2 + math.sqrt(v) * eps2
|
|
||||||
g1, g2 = demux(r, M1, M2, hh1, hh2, beta)
|
|
||||||
res_e[j] += 0.5 * (cosine(g1, e1) + cosine(g2, e2))
|
|
||||||
# realisable SIC with the same imperfect estimates
|
|
||||||
if abs(hh1) >= abs(hh2):
|
|
||||||
hs, hw, Ms, Mw, es, ew = hh1, hh2, M1, M2, e1, e2
|
|
||||||
else:
|
|
||||||
hs, hw, Ms, Mw, es, ew = hh2, hh1, M2, M1, e2, e1
|
|
||||||
d_s = Ms.T @ r / hs
|
|
||||||
dec_s = d_s / np.linalg.norm(d_s)
|
|
||||||
r_res = r - hs * (Ms @ dec_s)
|
|
||||||
d_w = Mw.T @ r_res / hw
|
|
||||||
res_s[j] += 0.5 * (cosine(d_s, es) + cosine(d_w, ew))
|
|
||||||
res_e /= ntr; res_s /= ntr
|
|
||||||
print(f" EDMA: {res_e[0]:.4f} -> {res_e[-1]:.4f} "
|
|
||||||
f"(delta {100*(res_e[0]-res_e[-1]):.2f} points)")
|
|
||||||
print(f" SIC : {res_s[0]:.4f} -> {res_s[-1]:.4f} "
|
|
||||||
f"(delta {100*(res_s[0]-res_s[-1]):.2f} points)")
|
|
||||||
fig, ax = plt.subplots()
|
|
||||||
ax.plot(sh2, res_e, "o-", color="C3", label="EDMA")
|
|
||||||
ax.plot(sh2, res_s, "^-.", color="C2", label="Realisable SIC")
|
|
||||||
ax.set_xlabel(r"CSI error variance $\sigma_h^2$")
|
|
||||||
ax.set_ylabel("Mean cosine similarity")
|
|
||||||
ax.set_xlim(0, sh2[-1]); ax.set_ylim(0, 0.7)
|
|
||||||
ax.legend(loc="lower left")
|
|
||||||
save_fig(fig, "fig_csi")
|
|
||||||
rows = [[v, res_e[j], res_s[j]] for j, v in enumerate(sh2)]
|
|
||||||
write_csv("csi_error", ["sigma_h2", "edma", "sic"], rows)
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
# E5 : Walsh-Hadamard structured masks vs Haar
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
def hadamard(n):
|
|
||||||
H = np.array([[1.0]])
|
|
||||||
while H.shape[0] < n:
|
|
||||||
H = np.block([[H, H], [H, -H]])
|
|
||||||
return H / math.sqrt(n)
|
|
||||||
|
|
||||||
|
|
||||||
def E5_maskfam(beta=0.311, d=512, snr_db=np.arange(0, 41, 5), ntr=200):
|
|
||||||
print("\n=== E5: Walsh-Hadamard masks vs Haar mixture ===")
|
|
||||||
H = hadamard(d)
|
|
||||||
g = math.sqrt(1.0 - beta**2)
|
|
||||||
res = {"haar": np.zeros(len(snr_db)), "wh": np.zeros(len(snr_db))}
|
|
||||||
for _ in range(ntr):
|
|
||||||
e1, e2 = embed_pair(d, beta)
|
|
||||||
M1, M2 = two_user_masks(d, beta)
|
|
||||||
D1 = np.diag(rng.choice([-1.0, 1.0], d))
|
|
||||||
D2 = np.diag(rng.choice([-1.0, 1.0], d))
|
|
||||||
W1 = H @ D1
|
|
||||||
W2 = beta * W1 + g * (H @ D2)
|
|
||||||
r0h = (M1 @ e1) + (M2 @ e2)
|
|
||||||
r0w = (W1 @ e1) + (W2 @ e2)
|
|
||||||
n = (rng.standard_normal(d) + 1j * rng.standard_normal(d)) / math.sqrt(2)
|
|
||||||
for k, s in enumerate(snr_db):
|
|
||||||
sig = 10 ** (-s / 20.0)
|
|
||||||
g1, _ = demux(r0h + sig * n, M1, M2, 1.0, 1.0, beta)
|
|
||||||
w1, _ = demux(r0w + sig * n, W1, W2, 1.0, 1.0, beta)
|
|
||||||
res["haar"][k] += cosine(g1, e1)
|
|
||||||
res["wh"][k] += cosine(w1, e1)
|
|
||||||
for k in res:
|
|
||||||
res[k] /= ntr
|
|
||||||
dev = 100 * np.max(np.abs(res["wh"] - res["haar"]))
|
|
||||||
print(f" max |WH - Haar| cosine deviation: {dev:.2f} points")
|
|
||||||
fig, ax = plt.subplots()
|
|
||||||
ax.plot(snr_db, res["haar"], "o-", color="C3",
|
|
||||||
label=r"Haar mixture, $\mathcal{O}(d^2)$")
|
|
||||||
ax.plot(snr_db, res["wh"], "s--", color="C0",
|
|
||||||
label=r"Walsh-Hadamard, $\mathcal{O}(d\log d)$")
|
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
|
||||||
ax.set_ylabel("Mean cosine similarity")
|
|
||||||
ax.set_xlim(snr_db[0], snr_db[-1]); ax.set_ylim(0, 0.8)
|
|
||||||
ax.legend(loc="upper left")
|
|
||||||
save_fig(fig, "fig_maskfam")
|
|
||||||
rows = [[s, res["haar"][i], res["wh"][i]] for i, s in enumerate(snr_db)]
|
|
||||||
write_csv("mask_family_rev", ["snr_db", "haar", "wh"], rows)
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
# E6 : high-affinity combining mode
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
def E6_coop(d=512, snr=20.0, betas=np.linspace(0.0, 0.98, 21), ntr=100):
|
|
||||||
print("\n=== E6: high-affinity combining-mode crossover ===")
|
|
||||||
sig = 10 ** (-snr / 20.0)
|
|
||||||
pairs = [(haar(d), haar(d)) for _ in range(ntr)]
|
|
||||||
chans = [rayleigh(2) for _ in range(ntr)]
|
|
||||||
cos_dx = np.zeros(len(betas)); cos_cb = np.zeros(len(betas))
|
|
||||||
for j, beta in enumerate(betas):
|
|
||||||
for t in range(ntr):
|
|
||||||
U1, U2 = pairs[t]
|
|
||||||
h1, h2 = chans[t]
|
|
||||||
e1, e2 = embed_pair(d, beta)
|
|
||||||
M1, M2 = two_user_masks(d, beta, U1, U2)
|
|
||||||
r = h1 * (M1 @ e1) + h2 * (M2 @ e2) + sig * (
|
|
||||||
rng.standard_normal(d) + 1j * rng.standard_normal(d)) / math.sqrt(2)
|
|
||||||
g1, _ = demux(r, M1, M2, h1, h2, beta)
|
|
||||||
cos_dx[j] += cosine(g1, e1)
|
|
||||||
# affinity combining: coherent weights for the e1 component
|
|
||||||
a1 = h1 + beta**2 * h2
|
|
||||||
a2 = beta * (h1 + h2)
|
|
||||||
comb = np.conj(a1) * (M1.T @ r) + np.conj(a2) * (M2.T @ r)
|
|
||||||
cos_cb[j] += cosine(comb, e1)
|
|
||||||
cos_dx /= ntr; cos_cb /= ntr
|
|
||||||
ix = np.where(cos_cb >= cos_dx)[0]
|
|
||||||
cross = betas[ix[0]] if len(ix) else float("nan")
|
|
||||||
print(f" crossover affinity ~ {cross:.2f} at rho={snr:.0f} dB")
|
|
||||||
fig, ax = plt.subplots()
|
|
||||||
ax.plot(betas, cos_dx, "o-", color="C3", label="Separation mode (demux)")
|
|
||||||
ax.plot(betas, cos_cb, "s--", color="C0", label="Combining mode")
|
|
||||||
ax.set_xlabel(r"Pairwise affinity $\beta$")
|
|
||||||
ax.set_ylabel("Mean cosine similarity")
|
|
||||||
ax.set_xlim(0, 1); ax.set_ylim(0, 0.8)
|
|
||||||
ax.legend(loc="lower left")
|
|
||||||
save_fig(fig, "fig_coop")
|
|
||||||
rows = [[b, cos_dx[i], cos_cb[i]] for i, b in enumerate(betas)]
|
|
||||||
write_csv("coop_mode", ["beta", "cos_demux", "cos_combine"], rows)
|
|
||||||
return cross
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
# E7 : corrected effective-rate figures
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
def eta_edma(rho, d, beta, csi=None):
|
|
||||||
g = 1.0 - beta**2
|
|
||||||
if csi is None:
|
|
||||||
csi = C_bar(beta) # symmetrised constant (alternating masks)
|
|
||||||
return 1.0 / (d / (rho * g) + csi)
|
|
||||||
|
|
||||||
|
|
||||||
def E7_rates(beta=0.311, d=512):
|
def E7_rates(beta=0.311, d=512):
|
||||||
print("\n=== E7a: corrected effective-rate comparison ===")
|
print("\n=== E7a: effective-rate comparison ===")
|
||||||
snr_db = np.arange(0, 31, 1.0)
|
snr_db = np.arange(0, 41, 0.5)
|
||||||
rho = 10 ** (snr_db / 10.0)
|
rho = 10 ** (snr_db / 10.0)
|
||||||
g = 1.0 - beta**2
|
Te = np.array([T_edma(r, d, beta) for r in rho])
|
||||||
T_edma = 2 * np.log2(1 + eta_edma(rho, d, beta))
|
Tb = np.array([T_blind(r, d) for r in rho])
|
||||||
T_ideal = 2 * np.log2(1 + rho * g / d)
|
To = 2 * np.log2(1 + rho / (2 * d))
|
||||||
T_oma = 2 * np.log2(1 + rho / (2 * d))
|
Tg = 2 * np.log2(1 + rho / d)
|
||||||
T_genie = 2 * np.log2(1 + rho / d)
|
Cm = np.log2(1 + 2 * rho / d)
|
||||||
C_mac = np.log2(1 + 2 * rho / d)
|
|
||||||
fig, ax = plt.subplots()
|
fig, ax = plt.subplots()
|
||||||
ax.plot(snr_db, T_edma, "-", color="C3", label="EDMA (Theorem 1)")
|
ax.plot(snr_db, Te, "-", color="C3", label=LBL["edma"])
|
||||||
ax.plot(snr_db, T_ideal, ":", color="C3", lw=1.1,
|
ax.plot(snr_db, Tb, ":", color="C4", lw=1.2, label=LBL["blind"])
|
||||||
label="EDMA idealized (infeasible)")
|
ax.plot(snr_db, To, "--", color="C1", label=LBL["oma"])
|
||||||
ax.plot(snr_db, T_oma, "--", color="C1", label="OMA")
|
ax.plot(snr_db, Tg, "-.", color="C0", label=LBL["genie"])
|
||||||
ax.plot(snr_db, T_genie, "-.", color="C0", label="Genie-aided SIC bound")
|
ax.plot(snr_db, Cm, "-", color="k", lw=1.0, label=LBL["mac"])
|
||||||
ax.plot(snr_db, C_mac, "-", color="k", lw=1.0, label="MAC sum capacity")
|
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
||||||
ax.set_ylabel("Effective sum rate [bps/Hz]")
|
ax.set_ylabel("Effective sum rate [bps/Hz]")
|
||||||
ax.set_xlim(0, 30); ax.set_ylim(0, 3.2)
|
ax.set_xlim(0, 40); ax.set_ylim(0, 3.2)
|
||||||
ax.legend(loc="upper left")
|
ax.legend(loc="upper left")
|
||||||
save_fig(fig, "fig_rate_corrected")
|
save_fig(fig, "fig_rate_corrected")
|
||||||
rows = [[s, T_edma[i], T_ideal[i], T_oma[i], T_genie[i], C_mac[i]]
|
rows = [[s, Te[i], Tb[i], To[i], Tg[i], Cm[i]]
|
||||||
for i, s in enumerate(snr_db)]
|
for i, s in enumerate(snr_db)]
|
||||||
write_csv("rate_corrected",
|
write_csv("rate_corrected",
|
||||||
["snr_db", "edma", "edma_ideal", "oma", "genie", "mac"], rows)
|
["snr_db", "edma", "blind", "oma", "genie", "mac"], rows)
|
||||||
i20 = list(snr_db).index(20.0)
|
i20 = list(snr_db).index(20.0)
|
||||||
csi = C_bar(beta)
|
print(f" at 20 dB: EDMA {Te[i20]:.3f}, blind {Tb[i20]:.3f}, "
|
||||||
rho_c = d * (2 - 1 / g) / csi
|
f"OMA {To[i20]:.3f} (gain {Te[i20]/To[i20]:.2f}x), "
|
||||||
print(f" at 20 dB: EDMA {T_edma[i20]:.3f}, OMA {T_oma[i20]:.3f} "
|
f"MAC {Cm[i20]:.3f}, EDMA/MAC {Te[i20]/Cm[i20]:.3f}")
|
||||||
f"(gain {T_edma[i20]/T_oma[i20]:.2f}x), MAC {C_mac[i20]:.3f}, "
|
g = 1.0 - beta**2
|
||||||
f"EDMA/MAC {T_edma[i20]/C_mac[i20]:.3f} (gamma={g:.3f})")
|
rho_c = 2 * d * (2 / math.sqrt(g) - 1)
|
||||||
print(f" OMA re-crossover rho_c = {10*math.log10(rho_c):.1f} dB")
|
ix = np.where(To >= Te)[0]
|
||||||
|
rc_num = snr_db[ix[0]] if len(ix) else float("nan")
|
||||||
|
print(f" OMA re-crossover: floor formula {10*math.log10(rho_c):.1f} dB, "
|
||||||
|
f"numerical {rc_num:.1f} dB "
|
||||||
|
f"(blind: {10*math.log10(2*d):.1f} dB)")
|
||||||
|
|
||||||
print("\n=== E7b: corrected beta sweep ===")
|
print("\n=== E7b: value-of-affinity sweep ===")
|
||||||
betas = np.linspace(0.0, 0.98, 99)
|
betas = np.linspace(0.0, 0.98, 99)
|
||||||
fig, ax = plt.subplots()
|
fig, ax = plt.subplots()
|
||||||
rows = []
|
rows = []
|
||||||
for s, col in ((10, "C0"), (20, "C3")):
|
for s, col in ((10, "C0"), (20, "C3")):
|
||||||
rho_s = 10 ** (s / 10.0)
|
rho_s = 10 ** (s / 10.0)
|
||||||
Te = np.array([2 * np.log2(1 + eta_edma(rho_s, d, b)) for b in betas])
|
Te = np.array([T_edma(rho_s, d, b) for b in betas])
|
||||||
To = 2 * np.log2(1 + rho_s / (2 * d))
|
Tb = T_blind(rho_s, d)
|
||||||
Tg = 2 * np.log2(1 + rho_s / d)
|
To = 2 * math.log2(1 + rho_s / (2 * d))
|
||||||
|
Tg = 2 * math.log2(1 + rho_s / d)
|
||||||
ax.plot(betas, Te, "-", color=col, label=rf"EDMA, $\rho={s}$ dB")
|
ax.plot(betas, Te, "-", color=col, label=rf"EDMA, $\rho={s}$ dB")
|
||||||
ax.axhline(To, color=col, ls="--", lw=1.0,
|
ax.axhline(Tb, color=col, ls=":", lw=1.0)
|
||||||
label=rf"OMA, $\rho={s}$ dB")
|
ax.axhline(To, color=col, ls="--", lw=1.0)
|
||||||
ax.axhline(Tg, color=col, ls="-.", lw=0.8,
|
ax.axhline(Tg, color=col, ls="-.", lw=0.8)
|
||||||
label=rf"Genie-aided SIC, $\rho={s}$ dB")
|
ixg = np.where(Te >= Tg)[0]
|
||||||
ix = np.where(Te <= To)[0]
|
bg = betas[ixg[0]] if len(ixg) else float("nan")
|
||||||
bstar = betas[ix[0]] if len(ix) else float("nan")
|
print(f" rho={s} dB: EDMA(0)/blind = {Te[0]/Tb:.3f}, "
|
||||||
print(f" rho={s} dB: crossover beta* = {bstar:.3f} "
|
f"EDMA(0.311) gain over blind "
|
||||||
f"(wideband limit 1/sqrt(2)=0.707)")
|
f"{Te[np.argmin(abs(betas-0.311))]/Tb:.3f}x, "
|
||||||
|
f"crosses genie at beta ~ {bg:.2f}")
|
||||||
for i, b in enumerate(betas):
|
for i, b in enumerate(betas):
|
||||||
rows.append([s, b, Te[i], To, Tg])
|
rows.append([s, b, Te[i], Tb, To, Tg])
|
||||||
for b0 in (0.031, 0.311):
|
for b0 in (0.030, 0.311):
|
||||||
ax.axvline(b0, color="gray", ls=":", lw=0.9)
|
ax.axvline(b0, color="gray", ls=":", lw=0.9)
|
||||||
ax.set_xlabel(r"Pairwise affinity $\beta$")
|
ax.set_xlabel(r"Pairwise affinity $\beta$")
|
||||||
ax.set_ylabel("Effective sum rate [bps/Hz]")
|
ax.set_ylabel("Effective sum rate [bps/Hz]")
|
||||||
ax.set_xlim(0, 1); ax.set_ylim(0, 1.02)
|
ax.set_xlim(0, 1)
|
||||||
ax.set_yticks([0.0, 0.2, 0.4, 0.6, 0.8, 1.0])
|
ax.legend(loc="upper left")
|
||||||
ax.legend(loc="upper right", ncol=1, fontsize=5.8,
|
|
||||||
handlelength=1.5, borderaxespad=0.2)
|
|
||||||
save_fig(fig, "fig_beta_sweep_corrected")
|
save_fig(fig, "fig_beta_sweep_corrected")
|
||||||
write_csv("beta_sweep_corrected",
|
write_csv("beta_sweep_corrected",
|
||||||
["snr_db", "beta", "edma", "oma", "genie"], rows)
|
["snr_db", "beta", "edma", "blind", "oma", "genie"], rows)
|
||||||
|
|
||||||
|
|
||||||
def E7_multiuser(beta=0.311, d=512, Us=(2, 3, 4), ntr_cal=80, ntr_mc=120):
|
|
||||||
print("\n=== E7c: corrected multi-user scaling ===")
|
|
||||||
snr_db = np.arange(0, 31, 2.5)
|
|
||||||
snr_mk = np.arange(0, 31, 5)
|
|
||||||
rho = 10 ** (snr_db / 10.0)
|
|
||||||
fig, ax = plt.subplots()
|
|
||||||
colors = {2: "C0", 3: "C2", 4: "C3"}
|
|
||||||
rows = []
|
|
||||||
csi2 = C_SI(beta, 1.0 + 0j)
|
|
||||||
for U in Us:
|
|
||||||
B = (1 - beta) * np.eye(U) + beta * np.ones((U, U))
|
|
||||||
Binv_uu = np.linalg.inv(B)[0, 0]
|
|
||||||
gU = 1.0 / Binv_uu
|
|
||||||
# calibrate C_SI^(U) by noise-free MC at h_u = 1 (the same
|
|
||||||
# evaluation convention as the two-user rate curves, so the
|
|
||||||
# U = 2 curve reduces exactly to T_EDMA with C_bar),
|
|
||||||
# averaged over all users (mask roles are asymmetric)
|
|
||||||
acc = 0.0
|
|
||||||
for _ in range(ntr_cal):
|
|
||||||
A = np.linalg.cholesky(B)
|
|
||||||
Uks = [haar(d) for _ in range(U)]
|
|
||||||
Ms = [sum(A[u, k] * Uks[k] for k in range(U)) for u in range(U)]
|
|
||||||
h = np.ones(U, dtype=complex)
|
|
||||||
# symmetric equal-affinity embeddings: e_u = beta-mixed set
|
|
||||||
base = unit(rng.standard_normal(d))
|
|
||||||
es = []
|
|
||||||
for u in range(U):
|
|
||||||
w = rng.standard_normal(d)
|
|
||||||
w = unit(w - (w @ base) * base)
|
|
||||||
# construct so that <e_u,e_v> ~ beta pairwise
|
|
||||||
es.append(unit(math.sqrt(beta) * base
|
|
||||||
+ math.sqrt(1 - beta) * w))
|
|
||||||
r = sum(h[u] * (Ms[u] @ es[u]) for u in range(U))
|
|
||||||
Binv = np.linalg.inv(B)
|
|
||||||
# block demux e_hat_u = (1/h_u) sum_v Binv[u,v] M_v^T r
|
|
||||||
for u in range(U):
|
|
||||||
eh = sum(Binv[u, v] * (Ms[v].T @ r) for v in range(U)) / h[u]
|
|
||||||
acc += np.linalg.norm(eh - es[u])**2
|
|
||||||
csiU = acc / (ntr_cal * U)
|
|
||||||
print(f" U={U}: C_SI^(U) = {csiU:.3f} "
|
|
||||||
f"((U-1)*C_bar = {(U-1)*C_bar(beta):.3f}), gamma_U = {gU:.3f}")
|
|
||||||
eta = 1.0 / (d * Binv_uu / rho + csiU)
|
|
||||||
T_th = U * np.log2(1 + eta)
|
|
||||||
T_oma = U * np.log2(1 + rho / (U * d))
|
|
||||||
ax.plot(snr_db, T_th, "-", color=colors[U], label=rf"EDMA, $U={U}$")
|
|
||||||
ax.plot(snr_db, T_oma, "--", color=colors[U], lw=1.0,
|
|
||||||
label=rf"OMA, $U={U}$")
|
|
||||||
# MC markers (with noise, h_u = 1, per-realization real masks)
|
|
||||||
err_mc = np.zeros(len(snr_mk))
|
|
||||||
for _ in range(ntr_mc):
|
|
||||||
A = np.linalg.cholesky(B)
|
|
||||||
Uks = [haar(d) for _ in range(U)]
|
|
||||||
Ms = [sum(A[u, k] * Uks[k] for k in range(U)) for u in range(U)]
|
|
||||||
h = np.ones(U, dtype=complex)
|
|
||||||
base = unit(rng.standard_normal(d))
|
|
||||||
es = []
|
|
||||||
for u in range(U):
|
|
||||||
w = rng.standard_normal(d)
|
|
||||||
w = unit(w - (w @ base) * base)
|
|
||||||
es.append(unit(math.sqrt(beta) * base
|
|
||||||
+ math.sqrt(1 - beta) * w))
|
|
||||||
r0 = sum(h[u] * (Ms[u] @ es[u]) for u in range(U))
|
|
||||||
n = (rng.standard_normal(d) + 1j * rng.standard_normal(d)) / math.sqrt(2)
|
|
||||||
Binv = np.linalg.inv(B)
|
|
||||||
for k, s in enumerate(snr_mk):
|
|
||||||
sig = 10 ** (-s / 20.0)
|
|
||||||
r = r0 + sig * n
|
|
||||||
for u in range(U):
|
|
||||||
eh = sum(Binv[u, v] * (Ms[v].T @ r) for v in range(U)) / h[u]
|
|
||||||
err_mc[k] += np.linalg.norm(eh - es[u])**2
|
|
||||||
err_mc /= ntr_mc * U
|
|
||||||
T_mc = U * np.log2(1 + 1.0 / err_mc)
|
|
||||||
ax.plot(snr_mk, T_mc, "o", color=colors[U], ms=4, mfc="none")
|
|
||||||
for i, s in enumerate(snr_db):
|
|
||||||
rows.append([U, s, T_th[i], T_oma[i]])
|
|
||||||
i20 = list(snr_db).index(20.0)
|
|
||||||
print(f" at 20 dB: EDMA {T_th[i20]:.3f} vs OMA {T_oma[i20]:.3f} "
|
|
||||||
f"(gain {T_th[i20]/T_oma[i20]:.2f}x)")
|
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
|
||||||
ax.set_ylabel("Effective sum rate [bps/Hz]")
|
|
||||||
ax.set_xlim(0, 30); ax.set_ylim(0, 1.5)
|
|
||||||
ax.legend(loc="upper left", ncol=1, fontsize=6.2)
|
|
||||||
save_fig(fig, "fig_multiuser_corrected")
|
|
||||||
write_csv("multiuser_corrected", ["U", "snr_db", "edma", "oma"], rows)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
todo = set(sys.argv[1:])
|
todo = set(sys.argv[1:])
|
||||||
ALL = {
|
ALL = {
|
||||||
"E0": E0_theorem_check, "E1": E1_floor, "E2": E2_sic,
|
"E0": E0_theorem_check, "E1": E1_floor, "E7a": E7_rates,
|
||||||
"E3": E3_regularised, "E4": E4_csi, "E5": E5_maskfam,
|
|
||||||
"E6": E6_coop, "E7a": E7_rates, "E7c": E7_multiuser,
|
|
||||||
}
|
}
|
||||||
for name, fn in ALL.items():
|
for name, fn in ALL.items():
|
||||||
if not todo or name in todo:
|
if not todo or name in todo:
|
||||||
fn()
|
fn()
|
||||||
print("\nAll requested revision simulations complete.")
|
print("\nAll requested simulations complete.")
|
||||||
|
|||||||
@@ -0,0 +1,416 @@
|
|||||||
|
"""
|
||||||
|
GPU-accelerated Monte Carlo experiments (torch backend).
|
||||||
|
========================================================
|
||||||
|
Computes the CSV artifacts of experiments E2, E3, E4, E5, E7c, E8
|
||||||
|
of revision_sims.py with identical models and conventions, using
|
||||||
|
torch (CUDA when available) for the dense linear algebra. All
|
||||||
|
random draws come from the numpy generator with the documented seed
|
||||||
|
2026, so the sample stream is platform-independent; torch only
|
||||||
|
accelerates QR, matrix products, and linear solves in float32 /
|
||||||
|
complex64 precision. Figures are rendered separately by
|
||||||
|
replot_all.py, which reads only data/.
|
||||||
|
|
||||||
|
Run under WSL: python3 revision_sims_gpu.py E2 E3 E4 E5 E7c E8
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
import csv
|
||||||
|
import math
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
import numpy as np
|
||||||
|
import torch
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
CSV_DIR = ROOT / "data"
|
||||||
|
|
||||||
|
SEED = 2026
|
||||||
|
rng = np.random.default_rng(SEED)
|
||||||
|
DEV = "cuda" if torch.cuda.is_available() else "cpu"
|
||||||
|
print(f"[gpu] device = {DEV}")
|
||||||
|
|
||||||
|
|
||||||
|
def write_csv(name, header, rows):
|
||||||
|
p = CSV_DIR / f"{name}.csv"
|
||||||
|
with open(p, "w", newline="") as f:
|
||||||
|
w = csv.writer(f); w.writerow(header); w.writerows(rows)
|
||||||
|
print(f"[OK] wrote {p}")
|
||||||
|
|
||||||
|
|
||||||
|
def haar_g(d):
|
||||||
|
"""Haar orthogonal on the GPU from a numpy Gaussian draw."""
|
||||||
|
G = torch.tensor(rng.standard_normal((d, d)), dtype=torch.float32,
|
||||||
|
device=DEV)
|
||||||
|
Q, R = torch.linalg.qr(G)
|
||||||
|
return Q * torch.sign(torch.diagonal(R)).unsqueeze(0)
|
||||||
|
|
||||||
|
|
||||||
|
def embed_pair(d, beta):
|
||||||
|
e1 = rng.standard_normal(d)
|
||||||
|
e1 /= np.linalg.norm(e1)
|
||||||
|
w = rng.standard_normal(d)
|
||||||
|
w -= (w @ e1) * e1
|
||||||
|
w /= np.linalg.norm(w)
|
||||||
|
e2 = beta * e1 + math.sqrt(1.0 - beta**2) * w
|
||||||
|
return (torch.tensor(e1, dtype=torch.float32, device=DEV),
|
||||||
|
torch.tensor(e2, dtype=torch.float32, device=DEV))
|
||||||
|
|
||||||
|
|
||||||
|
def rayleigh2():
|
||||||
|
h = (rng.standard_normal(2) + 1j * rng.standard_normal(2)) / math.sqrt(2)
|
||||||
|
return complex(h[0]), complex(h[1])
|
||||||
|
|
||||||
|
|
||||||
|
def cnoise_g(d):
|
||||||
|
n = (rng.standard_normal(d) + 1j * rng.standard_normal(d)) / math.sqrt(2)
|
||||||
|
return torch.tensor(n, dtype=torch.complex64, device=DEV)
|
||||||
|
|
||||||
|
|
||||||
|
def aware_g(t, Q, beta, c, nvar):
|
||||||
|
"""Batched aware Wiener demux. t: (b,d) cfloat, Q: (d,d) float,
|
||||||
|
c: python complex, nvar: (b,) tensor."""
|
||||||
|
d = Q.shape[0]
|
||||||
|
b = t.shape[0]
|
||||||
|
g = 1.0 - beta * beta
|
||||||
|
rho = g * abs(c)**2 / d + nvar
|
||||||
|
A = torch.eye(d, device=DEV, dtype=torch.complex64) \
|
||||||
|
+ beta * c * Q.to(torch.complex64)
|
||||||
|
S = (A @ A.mH / d).unsqueeze(0) \
|
||||||
|
+ rho.view(b, 1, 1) * torch.eye(d, device=DEV,
|
||||||
|
dtype=torch.complex64)
|
||||||
|
x = torch.linalg.solve(S, t.unsqueeze(-1))
|
||||||
|
return (A.mH.unsqueeze(0) @ x).squeeze(-1) / d
|
||||||
|
|
||||||
|
|
||||||
|
def abscos(a, e):
|
||||||
|
num = (a * e.to(a.dtype).conj()).sum(-1).abs()
|
||||||
|
return (num / (a.norm(dim=-1) * e.norm())).cpu().numpy()
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
def E2_sic(beta=0.311, d=512, ntr=400):
|
||||||
|
print("\n=== E2: receiver comparison under block-Rayleigh fading ===")
|
||||||
|
snr_db = np.arange(0, 31, 2.5)
|
||||||
|
sigs = torch.tensor(10 ** (-snr_db / 20.0), dtype=torch.float32,
|
||||||
|
device=DEV)
|
||||||
|
nb = len(snr_db)
|
||||||
|
res = {k: np.zeros(nb) for k in ("edma", "blind", "oma", "genie", "sic")}
|
||||||
|
t0 = time.time()
|
||||||
|
for tr in range(ntr):
|
||||||
|
e1, e2 = embed_pair(d, beta)
|
||||||
|
M1, M2 = haar_g(d), haar_g(d)
|
||||||
|
Q = M1.T @ M2
|
||||||
|
h1, h2 = rayleigh2()
|
||||||
|
n = cnoise_g(d); n2 = cnoise_g(d)
|
||||||
|
r0 = h1 * (M1 @ e1).to(torch.complex64) \
|
||||||
|
+ h2 * (M2 @ e2).to(torch.complex64)
|
||||||
|
r = r0.unsqueeze(0) + sigs.view(-1, 1) * n.unsqueeze(0)
|
||||||
|
t1 = (M1.T.to(torch.complex64) @ r.unsqueeze(-1)).squeeze(-1) / h1
|
||||||
|
t2 = (M2.T.to(torch.complex64) @ r.unsqueeze(-1)).squeeze(-1) / h2
|
||||||
|
c1, c2 = h2 / h1, h1 / h2
|
||||||
|
v1 = sigs**2 / abs(h1)**2
|
||||||
|
v2 = sigs**2 / abs(h2)**2
|
||||||
|
g1 = aware_g(t1, Q, beta, c1, v1)
|
||||||
|
g2 = aware_g(t2, Q.T, beta, c2, v2)
|
||||||
|
res["edma"] += 0.5 * (abscos(g1, e1) + abscos(g2, e2))
|
||||||
|
res["blind"] += 0.5 * (abscos(t1, e1) + abscos(t2, e2))
|
||||||
|
o1 = e1.to(torch.complex64).unsqueeze(0) \
|
||||||
|
+ math.sqrt(2) * sigs.view(-1, 1) * n.unsqueeze(0) / h1
|
||||||
|
o2 = e2.to(torch.complex64).unsqueeze(0) \
|
||||||
|
+ math.sqrt(2) * sigs.view(-1, 1) * n2.unsqueeze(0) / h2
|
||||||
|
res["oma"] += 0.5 * (abscos(o1, e1) + abscos(o2, e2))
|
||||||
|
ge1 = (M1.T.to(torch.complex64)
|
||||||
|
@ (r - h2 * (M2 @ e2).to(torch.complex64)).unsqueeze(-1)
|
||||||
|
).squeeze(-1) / h1
|
||||||
|
ge2 = (M2.T.to(torch.complex64)
|
||||||
|
@ (r - h1 * (M1 @ e1).to(torch.complex64)).unsqueeze(-1)
|
||||||
|
).squeeze(-1) / h2
|
||||||
|
res["genie"] += 0.5 * (abscos(ge1, e1) + abscos(ge2, e2))
|
||||||
|
# realizable decision-directed SIC: the stronger user is detected
|
||||||
|
# with the same aware Wiener stage (a scalar-scaled matched-filter
|
||||||
|
# decision would re-modulate to a multiple of r itself, because
|
||||||
|
# M_s M_s^T = I, and cancel nothing), its re-modulated estimate is
|
||||||
|
# subtracted, and the weaker user is read from the residual.
|
||||||
|
if abs(h1) >= abs(h2):
|
||||||
|
hs, hw, Ms, Mw, es, ew = h1, h2, M1, M2, e1, e2
|
||||||
|
Qsw, csw, vsw = Q, c1, v1
|
||||||
|
else:
|
||||||
|
hs, hw, Ms, Mw, es, ew = h2, h1, M2, M1, e2, e1
|
||||||
|
Qsw, csw, vsw = Q.T, c2, v2
|
||||||
|
t_s = (Ms.T.to(torch.complex64) @ r.unsqueeze(-1)).squeeze(-1) / hs
|
||||||
|
dec = aware_g(t_s, Qsw, beta, csw, vsw)
|
||||||
|
r_res = r - hs * (Ms.to(torch.complex64)
|
||||||
|
@ dec.unsqueeze(-1)).squeeze(-1)
|
||||||
|
d_w = (Mw.T.to(torch.complex64) @ r_res.unsqueeze(-1)).squeeze(-1) / hw
|
||||||
|
res["sic"] += 0.5 * (abscos(dec, es) + abscos(d_w, ew))
|
||||||
|
if (tr + 1) % 100 == 0:
|
||||||
|
print(f" {tr+1}/{ntr} ({time.time()-t0:.0f}s)", flush=True)
|
||||||
|
for k in res:
|
||||||
|
res[k] /= ntr
|
||||||
|
rows = [[s] + [res[k][i] for k in ("edma", "blind", "oma", "genie", "sic")]
|
||||||
|
for i, s in enumerate(snr_db)]
|
||||||
|
write_csv("sic_comparison",
|
||||||
|
["snr_db", "edma", "blind", "oma", "genie", "sic"], rows)
|
||||||
|
i20 = list(snr_db).index(20)
|
||||||
|
print(f" at 20 dB: EDMA {res['edma'][i20]:.3f}, blind "
|
||||||
|
f"{res['blind'][i20]:.3f}, SIC {res['sic'][i20]:.3f}, "
|
||||||
|
f"genie {res['genie'][i20]:.3f}, OMA {res['oma'][i20]:.3f}")
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
def E3_unconditional(beta=0.311, d=512, ntr=1500):
|
||||||
|
print("\n=== E3: Rayleigh unconditional MSE of the aware receiver ===")
|
||||||
|
rows = []
|
||||||
|
for s in (10, 20):
|
||||||
|
sig = 10 ** (-s / 20.0)
|
||||||
|
mses, bl = [], []
|
||||||
|
for _ in range(ntr):
|
||||||
|
e1, e2 = embed_pair(d, beta)
|
||||||
|
M1, M2 = haar_g(d), haar_g(d)
|
||||||
|
Q = M1.T @ M2
|
||||||
|
h1, h2 = rayleigh2()
|
||||||
|
n = cnoise_g(d)
|
||||||
|
r = h1 * (M1 @ e1).to(torch.complex64) \
|
||||||
|
+ h2 * (M2 @ e2).to(torch.complex64) + sig * n
|
||||||
|
t1 = (M1.T.to(torch.complex64) @ r) / h1
|
||||||
|
c1 = h2 / h1
|
||||||
|
nv = torch.tensor([sig**2 / abs(h1)**2], device=DEV)
|
||||||
|
g1 = aware_g(t1.unsqueeze(0), Q, beta, c1, nv)[0]
|
||||||
|
mses.append(float((g1 - e1.to(torch.complex64)).norm()**2))
|
||||||
|
lam = (1.0 / d) / (1.0 / d + abs(c1)**2 / d + sig**2 / abs(h1)**2)
|
||||||
|
b1 = lam * t1
|
||||||
|
bl.append(float((b1 - e1.to(torch.complex64)).norm()**2))
|
||||||
|
rows.append([s, float(np.mean(mses)), float(np.median(mses)),
|
||||||
|
float(np.mean(bl)), float(np.median(bl))])
|
||||||
|
print(f" {s} dB: aware mean {rows[-1][1]:.4f} "
|
||||||
|
f"(median {rows[-1][2]:.4f}) | blind mean {rows[-1][3]:.4f} "
|
||||||
|
f"(median {rows[-1][4]:.4f})")
|
||||||
|
write_csv("rayleigh_mse", ["snr_db", "aware_mean", "aware_median",
|
||||||
|
"blind_mean", "blind_median"], rows)
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
def E4_csi(beta=0.311, d=512, snr=30.0, ntr=400):
|
||||||
|
print("\n=== E4: imperfect CSI robustness (EDMA vs realizable SIC) ===")
|
||||||
|
sh2 = np.array([0.0, 0.01, 0.02, 0.05, 0.1, 0.2, 0.3])
|
||||||
|
sig = 10 ** (-snr / 20.0)
|
||||||
|
res_e = np.zeros(len(sh2)); res_s = np.zeros(len(sh2))
|
||||||
|
for _ in range(ntr):
|
||||||
|
e1, e2 = embed_pair(d, beta)
|
||||||
|
M1, M2 = haar_g(d), haar_g(d)
|
||||||
|
Q = M1.T @ M2
|
||||||
|
h1, h2 = rayleigh2()
|
||||||
|
n = cnoise_g(d)
|
||||||
|
r = h1 * (M1 @ e1).to(torch.complex64) \
|
||||||
|
+ h2 * (M2 @ e2).to(torch.complex64) + sig * n
|
||||||
|
eps1, eps2 = rayleigh2()
|
||||||
|
for j, v in enumerate(sh2):
|
||||||
|
hh1 = h1 + math.sqrt(v) * eps1
|
||||||
|
hh2 = h2 + math.sqrt(v) * eps2
|
||||||
|
t1 = (M1.T.to(torch.complex64) @ r) / hh1
|
||||||
|
t2 = (M2.T.to(torch.complex64) @ r) / hh2
|
||||||
|
nv1 = torch.tensor([sig**2 / abs(hh1)**2], device=DEV)
|
||||||
|
nv2 = torch.tensor([sig**2 / abs(hh2)**2], device=DEV)
|
||||||
|
g1 = aware_g(t1.unsqueeze(0), Q, beta, hh2 / hh1, nv1)[0]
|
||||||
|
g2 = aware_g(t2.unsqueeze(0), Q.T, beta, hh1 / hh2, nv2)[0]
|
||||||
|
res_e[j] += 0.5 * (float(abscos(g1.unsqueeze(0), e1)[0])
|
||||||
|
+ float(abscos(g2.unsqueeze(0), e2)[0]))
|
||||||
|
if abs(hh1) >= abs(hh2):
|
||||||
|
hs, hw, Ms, Mw, es, ew = hh1, hh2, M1, M2, e1, e2
|
||||||
|
Qsw, csw = Q, hh2 / hh1
|
||||||
|
else:
|
||||||
|
hs, hw, Ms, Mw, es, ew = hh2, hh1, M2, M1, e2, e1
|
||||||
|
Qsw, csw = Q.T, hh1 / hh2
|
||||||
|
t_s = (Ms.T.to(torch.complex64) @ r) / hs
|
||||||
|
nvs = torch.tensor([sig**2 / abs(hs)**2], device=DEV)
|
||||||
|
dec = aware_g(t_s.unsqueeze(0), Qsw, beta, csw, nvs)[0]
|
||||||
|
r_res = r - hs * (Ms.to(torch.complex64) @ dec)
|
||||||
|
d_w = (Mw.T.to(torch.complex64) @ r_res) / hw
|
||||||
|
res_s[j] += 0.5 * (float(abscos(dec.unsqueeze(0), es)[0])
|
||||||
|
+ float(abscos(d_w.unsqueeze(0), ew)[0]))
|
||||||
|
res_e /= ntr; res_s /= ntr
|
||||||
|
print(f" EDMA: {res_e[0]:.4f} -> {res_e[-1]:.4f} "
|
||||||
|
f"(delta {100*(res_e[0]-res_e[-1]):.2f} points)")
|
||||||
|
print(f" SIC : {res_s[0]:.4f} -> {res_s[-1]:.4f} "
|
||||||
|
f"(delta {100*(res_s[0]-res_s[-1]):.2f} points)")
|
||||||
|
rows = [[v, res_e[j], res_s[j]] for j, v in enumerate(sh2)]
|
||||||
|
write_csv("csi_error", ["sigma_h2", "edma", "sic"], rows)
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
def E5_maskfam(beta=0.311, d=512, ntr=200):
|
||||||
|
print("\n=== E5: Walsh-Hadamard diagonal variant vs Haar ===")
|
||||||
|
snr_db = np.arange(0, 41, 5)
|
||||||
|
sigs = torch.tensor(10 ** (-snr_db / 20.0), dtype=torch.float32,
|
||||||
|
device=DEV)
|
||||||
|
nb = len(snr_db)
|
||||||
|
H = np.array([[1.0]])
|
||||||
|
while H.shape[0] < d:
|
||||||
|
H = np.block([[H, H], [H, -H]])
|
||||||
|
Ht = torch.tensor(H / math.sqrt(d), dtype=torch.float32, device=DEV)
|
||||||
|
g = 1.0 - beta**2
|
||||||
|
res = {"haar": np.zeros(nb), "wh": np.zeros(nb)}
|
||||||
|
exact = np.zeros(nb)
|
||||||
|
for _ in range(ntr):
|
||||||
|
e1, e2 = embed_pair(d, beta)
|
||||||
|
M1, M2 = haar_g(d), haar_g(d)
|
||||||
|
Q = M1.T @ M2
|
||||||
|
D1 = torch.tensor(np.sign(rng.standard_normal(d)),
|
||||||
|
dtype=torch.float32, device=DEV)
|
||||||
|
D2 = torch.tensor(np.sign(rng.standard_normal(d)),
|
||||||
|
dtype=torch.float32, device=DEV)
|
||||||
|
W1, W2 = Ht * D1.unsqueeze(0), Ht * D2.unsqueeze(0)
|
||||||
|
q = D1 * D2
|
||||||
|
n = cnoise_g(d)
|
||||||
|
r0h = (M1 @ e1 + M2 @ e2).to(torch.complex64)
|
||||||
|
r0w = (W1 @ e1 + W2 @ e2).to(torch.complex64)
|
||||||
|
rh = r0h.unsqueeze(0) + sigs.view(-1, 1) * n.unsqueeze(0)
|
||||||
|
rw = r0w.unsqueeze(0) + sigs.view(-1, 1) * n.unsqueeze(0)
|
||||||
|
t1 = (M1.T.to(torch.complex64) @ rh.unsqueeze(-1)).squeeze(-1)
|
||||||
|
g1 = aware_g(t1, Q, beta, 1.0, sigs**2)
|
||||||
|
res["haar"] += abscos(g1, e1)
|
||||||
|
tw = (W1.T.to(torch.complex64) @ rw.unsqueeze(-1)).squeeze(-1)
|
||||||
|
a = 1.0 + beta * q # (d,)
|
||||||
|
rho = g / d + sigs**2 # (nb,)
|
||||||
|
wdiag = a.unsqueeze(0) / (a.unsqueeze(0)**2 / d
|
||||||
|
+ rho.view(-1, 1)) # (nb,d)
|
||||||
|
w1 = (wdiag.to(torch.complex64) / d) * tw
|
||||||
|
res["wh"] += abscos(w1, e1)
|
||||||
|
exact += ((g + d * sigs.view(-1, 1)**2)
|
||||||
|
/ (a.unsqueeze(0)**2 + g + d * sigs.view(-1, 1)**2)
|
||||||
|
).mean(1).cpu().numpy()
|
||||||
|
for k in res:
|
||||||
|
res[k] /= ntr
|
||||||
|
exact /= ntr
|
||||||
|
print(f" max |WH - Haar| cosine dev: "
|
||||||
|
f"{100*np.max(np.abs(res['wh']-res['haar'])):.2f} points; "
|
||||||
|
f"40 dB WH {res['wh'][-1]:.4f} vs Haar {res['haar'][-1]:.4f}")
|
||||||
|
rows = [[s, res["haar"][i], res["wh"][i], exact[i]]
|
||||||
|
for i, s in enumerate(snr_db)]
|
||||||
|
write_csv("mask_family_rev", ["snr_db", "haar", "wh", "wh_exact_mse"],
|
||||||
|
rows)
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
def E7_multiuser(beta=0.311, d=512, ntr=100):
|
||||||
|
print("\n=== E7c: multi-user scaling (joint Wiener) ===")
|
||||||
|
snr_db = np.arange(0, 31, 2.5)
|
||||||
|
sigs = torch.tensor(10 ** (-snr_db / 20.0), dtype=torch.float32,
|
||||||
|
device=DEV)
|
||||||
|
nb = len(snr_db)
|
||||||
|
rows = []
|
||||||
|
for U in (2, 3, 4):
|
||||||
|
B = (1 - beta) * np.eye(U) + beta * np.ones((U, U))
|
||||||
|
A = np.linalg.cholesky(B)
|
||||||
|
Bt = torch.tensor(B, dtype=torch.float32, device=DEV)
|
||||||
|
err = np.zeros(nb)
|
||||||
|
t0 = time.time()
|
||||||
|
for _ in range(ntr):
|
||||||
|
F = rng.standard_normal((d, U))
|
||||||
|
Fq, _ = np.linalg.qr(F)
|
||||||
|
E = (Fq @ A.T).T
|
||||||
|
Et = torch.tensor(E, dtype=torch.float32, device=DEV)
|
||||||
|
masks = [haar_g(d) for _ in range(U)]
|
||||||
|
n = cnoise_g(d)
|
||||||
|
r0 = sum(masks[u] @ Et[u] for u in range(U)).to(torch.complex64)
|
||||||
|
Qs = [masks[0].T @ masks[v] for v in range(U)]
|
||||||
|
Ret = sum(Bt[0, v] * Qs[v].T for v in range(U)) / d
|
||||||
|
S0 = sum(Bt[v, w] * (Qs[v] @ Qs[w].T)
|
||||||
|
for v in range(U) for w in range(U)) / d
|
||||||
|
r = r0.unsqueeze(0) + sigs.view(-1, 1) * n.unsqueeze(0)
|
||||||
|
t = (masks[0].T.to(torch.complex64)
|
||||||
|
@ r.unsqueeze(-1)).squeeze(-1)
|
||||||
|
S = S0.to(torch.complex64).unsqueeze(0) \
|
||||||
|
+ (sigs**2).view(-1, 1, 1) \
|
||||||
|
* torch.eye(d, device=DEV, dtype=torch.complex64)
|
||||||
|
x = torch.linalg.solve(S, t.unsqueeze(-1))
|
||||||
|
eh = (Ret.to(torch.complex64).unsqueeze(0) @ x).squeeze(-1)
|
||||||
|
err += ((eh - Et[0].to(torch.complex64)).norm(dim=1)**2
|
||||||
|
).cpu().numpy()
|
||||||
|
err /= ntr
|
||||||
|
T_mc = U * np.log2(1.0 / err)
|
||||||
|
r0v = (U - 1) + d / 10 ** (snr_db / 10.0)
|
||||||
|
T_bl = U * np.log2(1.0 + 1.0 / r0v)
|
||||||
|
T_oma = U * np.log2(1 + 10 ** (snr_db / 10.0) / (U * d))
|
||||||
|
for i, s in enumerate(snr_db):
|
||||||
|
rows.append([U, s, T_mc[i], T_bl[i], T_oma[i], err[i]])
|
||||||
|
i20 = list(snr_db).index(20.0)
|
||||||
|
print(f" U={U}: at 20 dB EDMA {T_mc[i20]:.3f} vs blind "
|
||||||
|
f"{T_bl[i20]:.3f} vs OMA {T_oma[i20]:.3f} "
|
||||||
|
f"(gain {T_mc[i20]/T_oma[i20]:.2f}x), floor MSE {err[-1]:.4f}"
|
||||||
|
f" [{time.time()-t0:.0f}s]")
|
||||||
|
write_csv("multiuser_corrected",
|
||||||
|
["U", "snr_db", "edma_mc", "blind", "oma", "mse_mc"], rows)
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
def E8_mismatch(beta=0.311, d=512, snr=20.0, ntr=200):
|
||||||
|
print("\n=== E8: affinity mismatch of the aware receiver ===")
|
||||||
|
sig = 10 ** (-snr / 20.0)
|
||||||
|
bhs = [b for b in (beta - 0.1, beta - 0.06, beta, beta + 0.06,
|
||||||
|
beta + 0.1, beta + 2 ** -8, 0.0) if b >= 0]
|
||||||
|
accs = np.zeros(len(bhs)); msea = np.zeros(len(bhs))
|
||||||
|
for _ in range(ntr):
|
||||||
|
e1, e2 = embed_pair(d, beta)
|
||||||
|
M1, M2 = haar_g(d), haar_g(d)
|
||||||
|
Q = M1.T @ M2
|
||||||
|
n = cnoise_g(d)
|
||||||
|
r = (M1 @ e1 + M2 @ e2).to(torch.complex64) + sig * n
|
||||||
|
t1 = (M1.T.to(torch.complex64) @ r)
|
||||||
|
nv = torch.tensor([sig**2], device=DEV)
|
||||||
|
for j, bh in enumerate(bhs):
|
||||||
|
g1 = aware_g(t1.unsqueeze(0), Q, bh, 1.0, nv)[0]
|
||||||
|
accs[j] += float(abscos(g1.unsqueeze(0), e1)[0])
|
||||||
|
msea[j] += float((g1 - e1.to(torch.complex64)).norm()**2)
|
||||||
|
accs /= ntr; msea /= ntr
|
||||||
|
rows = []
|
||||||
|
for j, bh in enumerate(bhs):
|
||||||
|
tag = ("quant b=7" if abs(bh - beta - 2**-8) < 1e-12 else
|
||||||
|
("blind" if bh == 0.0 else f"delta={bh-beta:+.2f}"))
|
||||||
|
print(f" beta_hat={bh:.4f} ({tag}): cosine {accs[j]:.4f}, "
|
||||||
|
f"MSE {msea[j]:.4f}")
|
||||||
|
rows.append([bh, accs[j], msea[j]])
|
||||||
|
write_csv("mismatch", ["beta_hat", "cosine", "mse"], rows)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
def E9_ceiling(d=512, snr=60.0, ntr=200):
|
||||||
|
print(chr(10) + '=== E9: cosine-ceiling verification (h=1) ===')
|
||||||
|
sig = 10 ** (-snr / 20.0)
|
||||||
|
rows = []
|
||||||
|
for beta in (0.311, 0.8):
|
||||||
|
g = 1.0 - beta**2
|
||||||
|
acc_a = 0.0; acc_b = 0.0
|
||||||
|
for _ in range(ntr):
|
||||||
|
e1, e2 = embed_pair(d, beta)
|
||||||
|
M1, M2 = haar_g(d), haar_g(d)
|
||||||
|
Q = M1.T @ M2
|
||||||
|
n = cnoise_g(d)
|
||||||
|
r = (M1 @ e1 + M2 @ e2).to(torch.complex64) + sig * n
|
||||||
|
t1 = (M1.T.to(torch.complex64) @ r)
|
||||||
|
nv = torch.tensor([sig**2], device=DEV)
|
||||||
|
g1 = aware_g(t1.unsqueeze(0), Q, beta, 1.0, nv)[0]
|
||||||
|
acc_a += float(abscos(g1.unsqueeze(0), e1)[0])
|
||||||
|
acc_b += float(abscos(t1.unsqueeze(0), e1)[0])
|
||||||
|
acc_a /= ntr; acc_b /= ntr
|
||||||
|
import math as _m
|
||||||
|
pred_a = _m.sqrt(1.0 - _m.sqrt(g) / 2.0)
|
||||||
|
pred_b = _m.sqrt(0.5)
|
||||||
|
print(f' beta={beta}: aware MC {acc_a:.4f} pred {pred_a:.4f} | '
|
||||||
|
f'blind MC {acc_b:.4f} pred {pred_b:.4f}')
|
||||||
|
rows.append([beta, acc_a, pred_a, acc_b, pred_b])
|
||||||
|
write_csv('cosine_ceiling', ['beta', 'aware_mc', 'aware_pred',
|
||||||
|
'blind_mc', 'blind_pred'], rows)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
todo = set(sys.argv[1:])
|
||||||
|
ALL = {"E2": E2_sic, "E3": E3_unconditional, "E4": E4_csi,
|
||||||
|
"E5": E5_maskfam, "E7c": E7_multiuser, "E8": E8_mismatch,
|
||||||
|
"E9": E9_ceiling}
|
||||||
|
for name, fn in ALL.items():
|
||||||
|
if not todo or name in todo:
|
||||||
|
fn()
|
||||||
|
print("\nAll requested GPU simulations complete.")
|
||||||
+222
-335
@@ -1,70 +1,35 @@
|
|||||||
"""
|
"""
|
||||||
Complete numerical verification of every closed form in the manuscript.
|
Monte Carlo verification of every closed-form claim (v2 design).
|
||||||
=======================================================================
|
================================================================
|
||||||
Each check implements the formula EXACTLY as printed in main.tex and
|
Independent Haar masks + affinity-aware Wiener demultiplexer.
|
||||||
compares it against a direct Monte-Carlo or algebraic evaluation.
|
Checks (d = 256 for speed; deviations shrink as O(1/d)):
|
||||||
Prints PASS/FAIL per item with the achieved deviation. Fixed seed.
|
|
||||||
|
|
||||||
V1 per-realization Gram identity M1^T M2 = beta I + sqrt(g) Q
|
V1 Theorem 1 MSE formula vs MC at several (beta, SNR), h = 1
|
||||||
V2 Theorem 1 full MSE (noise + C_SI,u) vs MC, random complex h
|
V2 Theorem 1 under random channel phases, both users
|
||||||
V3 noise-free calibration of C_SI,1 / C_SI,2 (several phases)
|
V3 floors: aware sqrt(g)/2 vs blind 1/2, and the value ratio
|
||||||
V4 quoted constants: C_SI,1, C_SI,2, C-bar at (0.311, h=1);
|
V4 cosine ceiling sqrt(1 - MSE) (Corollary: cosine)
|
||||||
cosine ceiling 1/sqrt(1+C_SI,1) = 0.70; rho_f = 28 dB at d=768
|
V5 blind receiver == matched filter in cosine (scalar shrinkage)
|
||||||
V5 SINR corollary eta_u = 1/MSE (per-coordinate accounting)
|
V6 monotonicity of the MSE in beta (Proposition)
|
||||||
V6 C_SI,u >= 1 for all beta (proof identities gamma*C_SI,1 =
|
V7 full-cooperation bound T <= log2(1+4 rho/d), equality at beta=1
|
||||||
gamma + 4 beta^4, gamma*C_SI,2 = 1 + 3 beta^2 at h=1)
|
V8 MAC condition gamma^2 (2+k) >= 2 beta^2 k^2 boundary
|
||||||
V7 Proposition (MAC consistency) on a (beta, rho) grid
|
V9 Walsh-Hadamard diagonal variant: exact finite-d closed form
|
||||||
V8 wideband limit T/C_MAC -> gamma
|
V10 mismatch stationarity: MSE(beta_hat) - MSE(beta) = O(delta^2)
|
||||||
V9 beta* crossover roots at 10/20 dB (0.700 / 0.590, d=512)
|
V11 correlated-mask alternative floor 1 + 4 beta^4 / gamma
|
||||||
V10 rho_c = d(2-1/gamma)/C-bar exact iff-condition + 25.7 dB value
|
(Remark and Appendix), dominated by the aware receiver
|
||||||
V11 idealized no-floor variant crosses C_MAC at 2 beta^2 d/gamma^2
|
|
||||||
(~21 dB at d=512, beta=0.311)
|
Pure numpy, fixed seed, ~2 minutes on a laptop.
|
||||||
V12 mismatch identity (eq:mismatch) + bound value 8.8e-3
|
|
||||||
V13 CSI-direction invariance: |cos| unchanged under wrong h-hat;
|
|
||||||
eq:csi-free equals eq:correct
|
|
||||||
V14 cross-moment lemma E[n^H M_u M_v^T n] = sigma^2 beta d
|
|
||||||
V15 multi-user [B^-1]_uu Sherman-Morrison formula, U = 2..6
|
|
||||||
V16 multi-user noise-free C_SI^(U) ~ (U-1) C-bar (within 10 %)
|
|
||||||
V17 Walsh-Hadamard masks: exact orthogonality + expected cross-Gram
|
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import math
|
import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
def hadamard(n):
|
|
||||||
H = np.array([[1.0]])
|
|
||||||
while H.shape[0] < n:
|
|
||||||
H = np.block([[H, H], [H, -H]])
|
|
||||||
return H
|
|
||||||
|
|
||||||
|
|
||||||
def brentq(f, a, b, tol=1e-12):
|
|
||||||
fa, fb = f(a), f(b)
|
|
||||||
assert fa * fb < 0, "no sign change"
|
|
||||||
for _ in range(200):
|
|
||||||
m = 0.5 * (a + b)
|
|
||||||
fm = f(m)
|
|
||||||
if abs(fm) < tol or (b - a) < tol:
|
|
||||||
return m
|
|
||||||
if fa * fm < 0:
|
|
||||||
b, fb = m, fm
|
|
||||||
else:
|
|
||||||
a, fa = m, fm
|
|
||||||
return 0.5 * (a + b)
|
|
||||||
|
|
||||||
rng = np.random.default_rng(2026)
|
rng = np.random.default_rng(2026)
|
||||||
FAIL = []
|
D = 256
|
||||||
|
|
||||||
|
|
||||||
def report(name, ok, detail):
|
|
||||||
tag = "PASS" if ok else "FAIL"
|
|
||||||
if not ok:
|
|
||||||
FAIL.append(name)
|
|
||||||
print(f"[{tag}] {name}: {detail}")
|
|
||||||
|
|
||||||
|
|
||||||
def haar(d):
|
def haar(d):
|
||||||
Q, R = np.linalg.qr(rng.standard_normal((d, d)))
|
G = rng.standard_normal((d, d))
|
||||||
|
Q, R = np.linalg.qr(G)
|
||||||
return Q * np.sign(np.diag(R))
|
return Q * np.sign(np.diag(R))
|
||||||
|
|
||||||
|
|
||||||
@@ -72,303 +37,225 @@ def unit(v):
|
|||||||
return v / np.linalg.norm(v)
|
return v / np.linalg.norm(v)
|
||||||
|
|
||||||
|
|
||||||
def pair(d, beta):
|
def cosim(a, b):
|
||||||
|
return float(abs(np.vdot(a, b)) / (np.linalg.norm(a) * np.linalg.norm(b)))
|
||||||
|
|
||||||
|
|
||||||
|
def embed_pair(d, beta):
|
||||||
e1 = unit(rng.standard_normal(d))
|
e1 = unit(rng.standard_normal(d))
|
||||||
w = rng.standard_normal(d)
|
w = rng.standard_normal(d)
|
||||||
w = unit(w - (w @ e1) * e1)
|
w = unit(w - (w @ e1) * e1)
|
||||||
return e1, beta * e1 + math.sqrt(1 - beta**2) * w
|
return e1, beta * e1 + math.sqrt(1 - beta * beta) * w
|
||||||
|
|
||||||
|
|
||||||
def csi1(beta, c):
|
def cnoise(d):
|
||||||
g = 1 - beta**2
|
return (rng.standard_normal(d) + 1j * rng.standard_normal(d)) / math.sqrt(2)
|
||||||
n2 = 1 + beta**2 * abs(c)**2 + 2 * beta**2 * np.real(c)
|
|
||||||
return (g**2 * abs(c)**2 + beta**2 * n2) / g
|
|
||||||
|
|
||||||
|
|
||||||
def csi2(beta, c):
|
def mse_theory(beta, c1, rho_e):
|
||||||
g = 1 - beta**2
|
a0 = 1.0 + beta**2 * abs(c1)**2 + rho_e
|
||||||
return (abs(c)**2 + beta**2 + 2 * beta**2 * np.real(c)) / g
|
return rho_e / math.sqrt(a0 * a0 - 4.0 * beta**2 * abs(c1)**2)
|
||||||
|
|
||||||
|
|
||||||
# ---------------- V1: per-realization Gram identity ----------------
|
def aware(t1, Q, beta, c1, nvar, d):
|
||||||
d, beta = 256, 0.311
|
g = 1.0 - beta * beta
|
||||||
g = 1 - beta**2
|
rho = g * abs(c1)**2 / d + nvar
|
||||||
U1, U2 = haar(d), haar(d)
|
S = beta * (c1 * Q + np.conj(c1) * Q.T) / d
|
||||||
M1, M2 = U1, beta * U1 + math.sqrt(g) * U2
|
S[np.diag_indices(d)] += (1.0 + beta**2 * abs(c1)**2) / d + rho
|
||||||
dev = np.abs(M1.T @ M2 - (beta * np.eye(d)
|
x = np.linalg.solve(S, t1)
|
||||||
+ math.sqrt(g) * U1.T @ U2)).max()
|
return (x + beta * np.conj(c1) * (Q.T @ x)) / d
|
||||||
report("V1 Gram identity", dev < 1e-12, f"max dev {dev:.2e}")
|
|
||||||
|
|
||||||
# ---------------- V2: Theorem 1 full MSE, random complex h ---------
|
|
||||||
d = 512
|
def run_pair(beta, sig, h1=1.0 + 0j, h2=1.0 + 0j, d=D):
|
||||||
for beta in (0.1, 0.311, 0.5):
|
e1, e2 = embed_pair(d, beta)
|
||||||
g = 1 - beta**2
|
M1, M2 = haar(d), haar(d)
|
||||||
h = (rng.standard_normal(2) + 1j * rng.standard_normal(2)) / math.sqrt(2)
|
Q = M1.T @ M2
|
||||||
h1, h2 = h
|
r = h1 * (M1 @ e1) + h2 * (M2 @ e2) + sig * cnoise(d)
|
||||||
rho_db = 15.0
|
|
||||||
sig = 10 ** (-rho_db / 20.0)
|
|
||||||
e1, e2 = pair(d, beta)
|
|
||||||
mc = np.zeros(2)
|
|
||||||
NT = 300
|
|
||||||
for _ in range(NT):
|
|
||||||
U1, U2 = haar(d), haar(d)
|
|
||||||
M1, M2 = U1, beta * U1 + math.sqrt(g) * U2
|
|
||||||
n = (rng.standard_normal(d) + 1j * rng.standard_normal(d)) \
|
|
||||||
/ math.sqrt(2)
|
|
||||||
r = h1 * (M1 @ e1) + h2 * (M2 @ e2) + sig * n
|
|
||||||
t1 = M1.T @ r / h1
|
t1 = M1.T @ r / h1
|
||||||
t2 = M2.T @ r / h2
|
return e1, e2, Q, t1, M2.T @ r / h2
|
||||||
g1 = (t1 - beta * (h2 / h1) * t2) / g
|
|
||||||
g2 = (t2 - beta * (h1 / h2) * t1) / g
|
|
||||||
mc[0] += np.linalg.norm(g1 - e1)**2
|
|
||||||
mc[1] += np.linalg.norm(g2 - e2)**2
|
|
||||||
mc /= NT
|
|
||||||
th1 = d * sig**2 / (abs(h1)**2 * g) + csi1(beta, h2 / h1)
|
|
||||||
th2 = d * sig**2 / (abs(h2)**2 * g) + csi2(beta, h1 / h2)
|
|
||||||
dev = max(abs(mc[0] / th1 - 1), abs(mc[1] / th2 - 1))
|
|
||||||
report(f"V2 Theorem 1 MSE (beta={beta})", dev < 0.02,
|
|
||||||
f"MC/theory dev {100*dev:.2f}% (O(1/d) at d={d})")
|
|
||||||
|
|
||||||
# ---------------- V3: noise-free C_SI calibration ------------------
|
|
||||||
d = 512
|
def check(name, ok, detail=""):
|
||||||
for phase in (0.0, math.pi / 3, math.pi):
|
print(f"[{'PASS' if ok else 'FAIL'}] {name} {detail}")
|
||||||
beta = 0.311
|
return ok
|
||||||
g = 1 - beta**2
|
|
||||||
h1 = 1.0 + 0j
|
|
||||||
h2 = np.exp(1j * phase)
|
allok = True
|
||||||
e1, e2 = pair(d, beta)
|
|
||||||
mc = np.zeros(2)
|
# ---------------------------------------------------------------- V1
|
||||||
NT = 200
|
devs = []
|
||||||
|
for beta in (0.0, 0.311, 0.6):
|
||||||
|
for snr in (10.0, 20.0, 60.0):
|
||||||
|
sig = 10 ** (-snr / 20.0)
|
||||||
|
mc = 0.0
|
||||||
|
NT = 40
|
||||||
for _ in range(NT):
|
for _ in range(NT):
|
||||||
U1, U2 = haar(d), haar(d)
|
e1, _, Q, t1, _ = run_pair(beta, sig)
|
||||||
M1, M2 = U1, beta * U1 + math.sqrt(g) * U2
|
g1 = aware(t1, Q, beta, 1.0, sig * sig, D)
|
||||||
r = h1 * (M1 @ e1) + h2 * (M2 @ e2)
|
mc += float(np.linalg.norm(g1 - e1) ** 2)
|
||||||
t1 = M1.T @ r / h1
|
|
||||||
t2 = M2.T @ r / h2
|
|
||||||
g1 = (t1 - beta * (h2 / h1) * t2) / g
|
|
||||||
g2 = (t2 - beta * (h1 / h2) * t1) / g
|
|
||||||
mc[0] += np.linalg.norm(g1 - e1)**2
|
|
||||||
mc[1] += np.linalg.norm(g2 - e2)**2
|
|
||||||
mc /= NT
|
mc /= NT
|
||||||
t1v, t2v = csi1(beta, h2 / h1), csi2(beta, h1 / h2)
|
th = mse_theory(beta, 1.0, (1 - beta**2) + D * sig * sig)
|
||||||
dev = max(abs(mc[0] / t1v - 1), abs(mc[1] / t2v - 1))
|
devs.append(abs(mc / th - 1))
|
||||||
report(f"V3 noise-free C_SI (phase={phase:.2f})", dev < 0.02,
|
allok &= check("V1 Theorem 1 (h=1)", max(devs) < 0.03,
|
||||||
f"dev {100*dev:.2f}%")
|
f"max dev {100*max(devs):.2f}%")
|
||||||
|
|
||||||
# ---------------- V4: quoted constants -----------------------------
|
# ---------------------------------------------------------------- V2
|
||||||
|
devs = []
|
||||||
|
sig = 10 ** (-20.0 / 20.0)
|
||||||
|
for beta in (0.311, 0.5):
|
||||||
|
for _ in range(30):
|
||||||
|
h1 = np.exp(1j * rng.uniform(0, 2 * np.pi))
|
||||||
|
h2 = np.exp(1j * rng.uniform(0, 2 * np.pi))
|
||||||
|
e1, e2, Q, t1, t2 = run_pair(beta, sig, h1, h2)
|
||||||
|
c1, c2 = h2 / h1, h1 / h2
|
||||||
|
g1 = aware(t1, Q, beta, c1, sig**2, D)
|
||||||
|
g2 = aware(t2, Q.T, beta, c2, sig**2, D)
|
||||||
|
g = 1 - beta**2
|
||||||
|
th1 = mse_theory(beta, c1, g * abs(c1)**2 + D * sig**2)
|
||||||
|
th2 = mse_theory(beta, c2, g * abs(c2)**2 + D * sig**2)
|
||||||
|
devs.append(abs(np.linalg.norm(g1 - e1)**2 / th1 - 1))
|
||||||
|
devs.append(abs(np.linalg.norm(g2 - e2)**2 / th2 - 1))
|
||||||
|
allok &= check("V2 Theorem 1 (random phases, both users)",
|
||||||
|
float(np.mean(devs)) < 0.05,
|
||||||
|
f"mean dev {100*float(np.mean(devs)):.2f}%")
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- V3
|
||||||
|
beta = 0.6
|
||||||
|
sig = 1e-3
|
||||||
|
mc_a, mc_b = 0.0, 0.0
|
||||||
|
NT = 40
|
||||||
|
for _ in range(NT):
|
||||||
|
e1, _, Q, t1, _ = run_pair(beta, sig)
|
||||||
|
g1 = aware(t1, Q, beta, 1.0, sig * sig, D)
|
||||||
|
mc_a += float(np.linalg.norm(g1 - e1) ** 2)
|
||||||
|
lam = (1.0 / D) / (2.0 / D + sig * sig)
|
||||||
|
mc_b += float(np.linalg.norm(lam * t1 - e1) ** 2)
|
||||||
|
mc_a /= NT
|
||||||
|
mc_b /= NT
|
||||||
|
fa, fb = math.sqrt(1 - beta**2) / 2, 0.5
|
||||||
|
allok &= check("V3 floors sqrt(g)/2 vs 1/2",
|
||||||
|
abs(mc_a - fa) < 0.02 and abs(mc_b - fb) < 0.02,
|
||||||
|
f"aware {mc_a:.4f}~{fa:.4f}, blind {mc_b:.4f}~{fb:.4f}, "
|
||||||
|
f"ratio {mc_b/mc_a:.3f}~{1/math.sqrt(1-beta**2):.3f}")
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- V4
|
||||||
|
acc = 0.0
|
||||||
|
for _ in range(NT):
|
||||||
|
e1, _, Q, t1, _ = run_pair(beta, sig)
|
||||||
|
acc += cosim(aware(t1, Q, beta, 1.0, sig * sig, D), e1)
|
||||||
|
acc /= NT
|
||||||
|
pred = math.sqrt(1 - fa)
|
||||||
|
allok &= check("V4 cosine ceiling sqrt(1-MSE)", abs(acc - pred) < 0.01,
|
||||||
|
f"MC {acc:.4f} vs {pred:.4f}")
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- V5
|
||||||
|
e1, _, Q, t1, _ = run_pair(0.311, 0.1)
|
||||||
|
lam = 0.37 # any scalar
|
||||||
|
allok &= check("V5 blind == MF in cosine",
|
||||||
|
abs(cosim(lam * t1, e1) - cosim(t1, e1)) < 1e-12)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- V6
|
||||||
|
k = D / 100.0
|
||||||
|
vals = [mse_theory(b, 1.0, (1 - b * b) + k)
|
||||||
|
for b in np.linspace(0, 0.99, 50)]
|
||||||
|
allok &= check("V6 monotonic decrease in beta",
|
||||||
|
all(x > y for x, y in zip(vals, vals[1:])))
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- V7
|
||||||
|
ok7 = True
|
||||||
|
worst = 0.0
|
||||||
|
for rho in (1.0, 100.0, 1e4):
|
||||||
|
kk = D / rho
|
||||||
|
coop = math.log2(1 + 4 * rho / D)
|
||||||
|
for b in np.linspace(0, 1.0, 41):
|
||||||
|
m = mse_theory(b, 1.0, (1 - b * b) + kk)
|
||||||
|
T = 2 * math.log2(1 / m)
|
||||||
|
ok7 &= T <= coop + 1e-9
|
||||||
|
worst = max(worst, T - coop)
|
||||||
|
m1 = mse_theory(1.0, 1.0, kk)
|
||||||
|
ok7 &= abs(2 * math.log2(1 / m1) - coop) < 1e-9
|
||||||
|
allok &= check("V7 full-cooperation bound, equality at beta=1", ok7,
|
||||||
|
f"max T-coop {worst:.2e}")
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- V8
|
||||||
|
ok8 = True
|
||||||
|
for rho in (1.0, 10.0, 100.0, 1e3):
|
||||||
|
kk = D / rho
|
||||||
|
for b in (0.1, 0.311, 0.6, 0.9):
|
||||||
|
g = 1 - b * b
|
||||||
|
m = mse_theory(b, 1.0, g + kk)
|
||||||
|
T = 2 * math.log2(1 / m)
|
||||||
|
mac = math.log2(1 + 2 * rho / D)
|
||||||
|
lhs = g * g * (2 + kk)
|
||||||
|
rhs = 2 * b * b * kk * kk
|
||||||
|
ok8 &= (T <= mac + 1e-9) == (lhs >= rhs - 1e-9)
|
||||||
|
allok &= check("V8 MAC-condition boundary", ok8)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- V9
|
||||||
beta = 0.311
|
beta = 0.311
|
||||||
g = 1 - beta**2
|
g = 1 - beta**2
|
||||||
c1v, c2v = csi1(beta, 1.0 + 0j), csi2(beta, 1.0 + 0j)
|
sig = 10 ** (-20.0 / 20.0)
|
||||||
cbar = (c1v + c2v) / 2
|
H = np.array([[1.0]])
|
||||||
ceil1 = 1 / math.sqrt(1 + c1v)
|
while H.shape[0] < D:
|
||||||
rho_f_db = 10 * math.log10(768 * g / c1v)
|
H = np.block([[H, H], [H, -H]])
|
||||||
ok = (abs(cbar - 1.2349) < 5e-4 and abs(ceil1 - 0.70) < 5e-3
|
H /= math.sqrt(D)
|
||||||
and abs(rho_f_db - 28) < 0.5)
|
mc, th = 0.0, 0.0
|
||||||
report("V4 quoted constants", ok,
|
for _ in range(30):
|
||||||
f"C_SI,1 {c1v:.4f}, C_SI,2 {c2v:.4f}, C-bar {cbar:.4f} "
|
e1, e2 = embed_pair(D, beta)
|
||||||
f"(quoted 1.2349), ceiling {ceil1:.4f} (quoted 0.70), "
|
D1 = np.sign(rng.standard_normal(D))
|
||||||
f"rho_f {rho_f_db:.1f} dB (quoted 28)")
|
D2 = np.sign(rng.standard_normal(D))
|
||||||
|
W1, W2 = H * D1[None, :], H * D2[None, :]
|
||||||
|
r = W1 @ e1 + W2 @ e2 + sig * cnoise(D)
|
||||||
|
t1 = W1.T @ r
|
||||||
|
q = D1 * D2
|
||||||
|
a = 1.0 + beta * q
|
||||||
|
rho = g / D + sig * sig
|
||||||
|
w1 = (a / (a * a / D + rho)) * t1 / D
|
||||||
|
mc += float(np.linalg.norm(w1 - e1) ** 2)
|
||||||
|
th += float(np.mean((g + D * sig**2) / (a * a + g + D * sig**2)))
|
||||||
|
allok &= check("V9 WH exact finite-d closed form",
|
||||||
|
abs(mc / th - 1) < 0.03, f"dev {100*abs(mc/th-1):.2f}%")
|
||||||
|
|
||||||
# ---------------- V5: SINR = 1/MSE ---------------------------------
|
# ---------------------------------------------------------------- V10
|
||||||
rho = 10 ** (15 / 10)
|
beta = 0.3
|
||||||
eta = 1 / (512 / (rho * g) + c1v)
|
sig = 10 ** (-20.0 / 20.0)
|
||||||
mse = 512 / (rho * g) + c1v
|
base, d1, d2 = 0.0, 0.0, 0.0
|
||||||
report("V5 SINR corollary", abs(eta * mse - 1) < 1e-12,
|
for _ in range(30):
|
||||||
f"eta*MSE = {eta*mse:.6f}")
|
e1, _, Q, t1, _ = run_pair(beta, sig)
|
||||||
|
for bh, tag in ((beta, "b"), (beta + 0.2, "1"), (beta + 0.4, "2")):
|
||||||
# ---------------- V6: C_SI >= 1 and proof identities ---------------
|
g1 = aware(t1, Q, bh, 1.0, sig * sig, D)
|
||||||
ok = True
|
m = float(np.linalg.norm(g1 - e1) ** 2)
|
||||||
worst = 1e9
|
if tag == "b":
|
||||||
for b in np.linspace(0.0, 0.99, 200):
|
base += m
|
||||||
gg = 1 - b**2
|
elif tag == "1":
|
||||||
lhs1 = gg * csi1(b, 1.0 + 0j)
|
d1 += m
|
||||||
lhs2 = gg * csi2(b, 1.0 + 0j)
|
|
||||||
if abs(lhs1 - (gg + 4 * b**4)) > 1e-12: ok = False
|
|
||||||
if abs(lhs2 - (1 + 3 * b**2)) > 1e-12: ok = False
|
|
||||||
worst = min(worst, csi1(b, 1.0 + 0j), csi2(b, 1.0 + 0j))
|
|
||||||
report("V6 C_SI >= 1 + proof identities", ok and worst >= 1 - 1e-12,
|
|
||||||
f"min C_SI over beta grid = {worst:.6f}")
|
|
||||||
|
|
||||||
# ---------------- V7: MAC consistency on a grid --------------------
|
|
||||||
def T_edma(b, r_, d_):
|
|
||||||
gg = 1 - b**2
|
|
||||||
cb = (csi1(b, 1 + 0j) + csi2(b, 1 + 0j)) / 2
|
|
||||||
return 2 * np.log2(1 + 1 / (d_ / (r_ * gg) + cb))
|
|
||||||
|
|
||||||
ok = True
|
|
||||||
for b in np.linspace(0, 0.95, 40):
|
|
||||||
for rdb in np.linspace(-10, 60, 60):
|
|
||||||
r_ = 10 ** (rdb / 10)
|
|
||||||
gg = 1 - b**2
|
|
||||||
mid = np.log2(1 + 2 * r_ * gg / 512)
|
|
||||||
cmac = np.log2(1 + 2 * r_ / 512)
|
|
||||||
if T_edma(b, r_, 512) > mid + 1e-12 or mid > cmac + 1e-12:
|
|
||||||
ok = False
|
|
||||||
report("V7 MAC consistency grid", ok, "T_EDMA <= log2(1+2 rho g/d) <= C_MAC")
|
|
||||||
|
|
||||||
# ---------------- V8: wideband limit -------------------------------
|
|
||||||
b = 0.311
|
|
||||||
r_ = 1e-6 * 512
|
|
||||||
lim = T_edma(b, r_, 512) / np.log2(1 + 2 * r_ / 512)
|
|
||||||
report("V8 wideband limit", abs(lim - (1 - b**2)) < 1e-3,
|
|
||||||
f"T/C_MAC at rho/d=1e-6: {lim:.5f} vs gamma {1-b**2:.5f}")
|
|
||||||
|
|
||||||
# ---------------- V9: beta* crossover roots ------------------------
|
|
||||||
def beta_star(rdb, d_=512):
|
|
||||||
r_ = 10 ** (rdb / 10)
|
|
||||||
T_oma = 2 * np.log2(1 + r_ / (2 * d_))
|
|
||||||
return brentq(lambda b: T_edma(b, r_, d_) - T_oma, 0.3, 0.9)
|
|
||||||
|
|
||||||
b10, b20 = beta_star(10), beta_star(20)
|
|
||||||
report("V9 beta* crossover", abs(b10 - 0.700) < 5e-3
|
|
||||||
and abs(b20 - 0.590) < 5e-3,
|
|
||||||
f"10 dB: {b10:.3f} (quoted 0.700), 20 dB: {b20:.3f} (quoted 0.590)")
|
|
||||||
|
|
||||||
# ---------------- V10: rho_c iff-condition + value -----------------
|
|
||||||
b = 0.311
|
|
||||||
gg = 1 - b**2
|
|
||||||
cb = (csi1(b, 1 + 0j) + csi2(b, 1 + 0j)) / 2
|
|
||||||
rho_c = 512 * (2 - 1 / gg) / cb
|
|
||||||
rho_c_db = 10 * math.log10(rho_c)
|
|
||||||
eps = 1e-4
|
|
||||||
below = T_edma(b, rho_c * (1 - eps), 512) \
|
|
||||||
- 2 * np.log2(1 + rho_c * (1 - eps) / 1024)
|
|
||||||
above = T_edma(b, rho_c * (1 + eps), 512) \
|
|
||||||
- 2 * np.log2(1 + rho_c * (1 + eps) / 1024)
|
|
||||||
report("V10 rho_c crossover", below > 0 > above
|
|
||||||
and abs(rho_c_db - 25.7) < 0.1,
|
|
||||||
f"rho_c {rho_c_db:.2f} dB (quoted 25.7), sign flip verified")
|
|
||||||
|
|
||||||
# ---------------- V11: idealized-MAC crossing ----------------------
|
|
||||||
rho_x = 2 * b**2 * 512 / gg**2
|
|
||||||
f = lambda r_: 2 * np.log2(1 + r_ * gg / 512) - np.log2(1 + 2 * r_ / 512)
|
|
||||||
root = brentq(f, 10.0, 1e4)
|
|
||||||
report("V11 idealized crossing", abs(root / rho_x - 1) < 1e-6
|
|
||||||
and abs(10 * math.log10(root) - 21) < 0.3,
|
|
||||||
f"root {10*math.log10(root):.2f} dB, formula 2b^2d/g^2 "
|
|
||||||
f"{10*math.log10(rho_x):.2f} dB (quoted ~21)")
|
|
||||||
|
|
||||||
# ---------------- V12: mismatch identity + bound value -------------
|
|
||||||
b, delta = 0.3, 0.06
|
|
||||||
bh = b + delta
|
|
||||||
hr = 1.0 + 0j
|
|
||||||
e1, e2 = pair(64, b)
|
|
||||||
t1 = e1 + b * hr * e2 # expected-Gram surrogate outputs
|
|
||||||
t2v_ = e2 + b * np.conj(hr) * e1
|
|
||||||
g1 = (t1 - bh * hr * t2v_) / (1 - bh**2)
|
|
||||||
lhs = g1 - e1
|
|
||||||
rhs = delta / (1 - bh**2) * (bh * e1 - hr * e2)
|
|
||||||
dev = np.linalg.norm(lhs - rhs)
|
|
||||||
bound = delta**2 * (abs(bh) + abs(hr))**2 / (1 - bh**2)**2
|
|
||||||
report("V12 mismatch identity", dev < 1e-12
|
|
||||||
and abs(bound - 8.8e-3) < 2e-4,
|
|
||||||
f"identity dev {dev:.1e}, bound {bound:.4f} (quoted 8.8e-3)")
|
|
||||||
|
|
||||||
# ---------------- V13: CSI-direction invariance --------------------
|
|
||||||
d = 256
|
|
||||||
b = 0.311
|
|
||||||
g = 1 - b**2
|
|
||||||
e1, e2 = pair(d, b)
|
|
||||||
U1, U2 = haar(d), haar(d)
|
|
||||||
M1, M2 = U1, b * U1 + math.sqrt(g) * U2
|
|
||||||
h1, h2 = 0.7 - 0.4j, -0.2 + 1.1j
|
|
||||||
n = (rng.standard_normal(d) + 1j * rng.standard_normal(d)) / math.sqrt(2)
|
|
||||||
r = h1 * (M1 @ e1) + h2 * (M2 @ e2) + 0.1 * n
|
|
||||||
truec = (M1.T @ r / h1 - b * (h2 / h1) * (M2.T @ r / h2)) / g
|
|
||||||
csif = (M1 - b * M2).T @ r / (h1 * g)
|
|
||||||
dev1 = np.abs(truec - csif).max()
|
|
||||||
h1w = h1 * (1.5 * np.exp(0.8j)) # badly wrong estimate
|
|
||||||
wrong = (M1 - b * M2).T @ r / (h1w * g)
|
|
||||||
c_true = abs(np.vdot(truec, e1)) / (np.linalg.norm(truec))
|
|
||||||
c_wrong = abs(np.vdot(wrong, e1)) / (np.linalg.norm(wrong))
|
|
||||||
report("V13 CSI invariance", dev1 < 1e-12 and abs(c_true - c_wrong) < 1e-12,
|
|
||||||
f"csi-free identity dev {dev1:.1e}, |cos| unchanged "
|
|
||||||
f"({c_true:.6f} vs {c_wrong:.6f})")
|
|
||||||
|
|
||||||
# ---------------- V14: cross-moment lemma --------------------------
|
|
||||||
d = 256
|
|
||||||
b = 0.311
|
|
||||||
sig2 = 0.5
|
|
||||||
acc = 0.0
|
|
||||||
NT = 4000
|
|
||||||
U1, U2 = haar(d), haar(d)
|
|
||||||
M1, M2 = U1, b * U1 + math.sqrt(1 - b**2) * U2
|
|
||||||
for _ in range(NT):
|
|
||||||
n = math.sqrt(sig2) * (rng.standard_normal(d)
|
|
||||||
+ 1j * rng.standard_normal(d)) / math.sqrt(2)
|
|
||||||
acc += np.real(np.conj(n) @ (M1 @ (M2.T @ n)))
|
|
||||||
acc /= NT
|
|
||||||
th = sig2 * b * d
|
|
||||||
report("V14 cross-moment lemma", abs(acc / th - 1) < 0.05,
|
|
||||||
f"MC {acc:.3f} vs sigma^2 beta d {th:.3f} "
|
|
||||||
f"({100*abs(acc/th-1):.1f}%)")
|
|
||||||
|
|
||||||
# ---------------- V15: [B^-1]_uu Sherman-Morrison ------------------
|
|
||||||
ok = True
|
|
||||||
for U in range(2, 7):
|
|
||||||
for b in (0.1, 0.311, 0.6):
|
|
||||||
B = (1 - b) * np.eye(U) + b * np.ones((U, U))
|
|
||||||
num = 1 + (U - 2) * b
|
|
||||||
den = (1 - b) * (1 + (U - 1) * b)
|
|
||||||
if abs(np.linalg.inv(B)[0, 0] - num / den) > 1e-12:
|
|
||||||
ok = False
|
|
||||||
report("V15 [B^-1]_uu formula", ok, "U=2..6, beta grid, exact")
|
|
||||||
|
|
||||||
# ---------------- V16: multi-user C_SI^(U) -------------------------
|
|
||||||
d = 512
|
|
||||||
b = 0.311
|
|
||||||
g = 1 - b**2
|
|
||||||
cb = (csi1(b, 1 + 0j) + csi2(b, 1 + 0j)) / 2
|
|
||||||
for U in (3, 4):
|
|
||||||
B = (1 - b) * np.eye(U) + b * np.ones((U, U))
|
|
||||||
Binv = np.linalg.inv(B)
|
|
||||||
es = []
|
|
||||||
e1 = unit(rng.standard_normal(d))
|
|
||||||
for u in range(U):
|
|
||||||
if u == 0:
|
|
||||||
es.append(e1)
|
|
||||||
else:
|
else:
|
||||||
w = rng.standard_normal(d)
|
d2 += m
|
||||||
w = unit(w - (w @ e1) * e1)
|
base /= 30; d1 /= 30; d2 /= 30
|
||||||
es.append(b * e1 + math.sqrt(g) * w)
|
r_quad = (d2 - base) / max(d1 - base, 1e-12)
|
||||||
mse = 0.0
|
allok &= check("V10 quadratic mismatch (delta doubling ~ 4x)",
|
||||||
NT = 60
|
2.5 < r_quad < 6.5,
|
||||||
for _ in range(NT):
|
f"MSE(+0)={base:.4f} MSE(+0.2)={d1:.4f} "
|
||||||
Us = [haar(d) for _ in range(U)]
|
f"MSE(+0.4)={d2:.4f} ratio {r_quad:.2f}")
|
||||||
Ms = [Us[0]]
|
|
||||||
for u in range(1, U):
|
|
||||||
Ms.append(b * Us[0] + math.sqrt(g) * Us[u])
|
|
||||||
r = sum(Ms[u] @ es[u] for u in range(U)) # h_u = 1
|
|
||||||
t = np.stack([Ms[u].T @ r for u in range(U)])
|
|
||||||
rec = np.einsum("uv,vd->ud", Binv, t)
|
|
||||||
mse += np.linalg.norm(rec[0] - es[0])**2
|
|
||||||
mse /= NT
|
|
||||||
ratio = mse / ((U - 1) * cb)
|
|
||||||
report(f"V16 C_SI^(U) additivity (U={U})", abs(ratio - 1) < 0.10,
|
|
||||||
f"noise-free MSE {mse:.3f} vs (U-1)C-bar "
|
|
||||||
f"{(U-1)*cb:.3f} (ratio {ratio:.3f})")
|
|
||||||
|
|
||||||
# ---------------- V17: Walsh-Hadamard masks ------------------------
|
# ---------------------------------------------------------------- V11
|
||||||
d = 256
|
beta = 0.311
|
||||||
H = hadamard(d) / math.sqrt(d)
|
g = 1 - beta**2
|
||||||
b = 0.311
|
mc = 0.0
|
||||||
acc = np.zeros((d, d))
|
for _ in range(30):
|
||||||
NT = 400
|
e1, e2 = embed_pair(D, beta)
|
||||||
for _ in range(NT):
|
U1, U2 = haar(D), haar(D)
|
||||||
D1 = np.diag(rng.choice([-1.0, 1.0], d))
|
M1, M2 = U1, beta * U1 + math.sqrt(g) * U2
|
||||||
D2 = np.diag(rng.choice([-1.0, 1.0], d))
|
r = M1 @ e1 + M2 @ e2 # noise-free -> floor
|
||||||
W1 = H @ D1
|
t1 = M1.T @ r
|
||||||
W2 = b * W1 + math.sqrt(1 - b**2) * H @ D2
|
t2 = M2.T @ r
|
||||||
acc += W1.T @ W2 / NT
|
g1 = (t1 - beta * t2) / g
|
||||||
orth = np.abs((H @ np.diag(rng.choice([-1.0, 1.0], d))).T
|
mc += float(np.linalg.norm(g1 - e1) ** 2)
|
||||||
@ (H @ np.diag(rng.choice([-1.0, 1.0], d)))
|
mc /= 30
|
||||||
@ np.ones(d) / d).max()
|
th = 1 + 4 * beta**4 / g
|
||||||
diag_dev = abs(np.diag(acc).mean() - b)
|
allok &= check("V11 correlated-mask floor 1+4b^4/g",
|
||||||
off = np.abs(acc - np.diag(np.diag(acc))).mean()
|
abs(mc / th - 1) < 0.05,
|
||||||
report("V17 WH masks", diag_dev < 0.02 and off < 0.01,
|
f"MC {mc:.4f} vs {th:.4f}; aware floor "
|
||||||
f"E[cross-Gram] diag {np.diag(acc).mean():.4f} vs beta {b}, "
|
f"{math.sqrt(g)/2:.4f} (dominated)")
|
||||||
f"mean |off-diag| {off:.4f}")
|
|
||||||
|
|
||||||
print()
|
print("\nALL CHECKS PASSED" if allok else "\nSOME CHECKS FAILED")
|
||||||
print("=" * 60)
|
|
||||||
print(f"RESULT: {'ALL PASS' if not FAIL else 'FAILURES: ' + ', '.join(FAIL)}")
|
|
||||||
|
|||||||
+14
-8
@@ -1,8 +1,14 @@
|
|||||||
snr_db,edma,oma,genie,att,att_x,todma,edma_ref,edma_ref2
|
snr_db,edma,oma,genie,todma,edma_ref,edma_ref2
|
||||||
0.0,0.04509729548248326,0.03878942917318714,0.04510116805362887,0.06537951208185813,0.028956357115368724,0.009263779561898224,0.051216359648716556,0.05146971093667761
|
0.0,0.04467206875531701,0.0395211911102524,0.04470823034964269,0.00808752125339693,0.051258400181977776,0.051258395044569624
|
||||||
5.0,0.06451154394270053,0.0507439763307109,0.06460883367368744,0.11006860490285489,0.02899092581015571,0.014985754149760718,0.08214049352367703,0.08245299246543433
|
2.5,0.052661077863012905,0.044328911576594694,0.05274493153032381,0.010903122079792332,0.06411670899382443,0.06411670250265161
|
||||||
10.0,0.10340689217396296,0.07698703231946222,0.10399757263661547,0.18771051966437632,0.029096261892353006,0.03519980048035704,0.13997304338278754,0.14036958956224843
|
5.0,0.0644090429507196,0.0517221181144123,0.06458281029539649,0.0160517606871274,0.08237909885676345,0.08237909091782057
|
||||||
15.0,0.17239818787681693,0.12749333352586661,0.17548648804419778,0.3057075884366212,0.029248349735797895,0.10412376981275459,0.23587541750084084,0.23652206338075601
|
7.5,0.08108708676882088,0.06272871624387336,0.0814530021866085,0.027431791894606004,0.1073888337527751,0.10738882329576882
|
||||||
20.0,0.2789011314185965,0.2156999450240525,0.29264116008861335,0.4510118978738174,0.029343304376527338,0.21990683440776934,0.37242277625984427,0.37307923116081904
|
10.0,0.10398115491552744,0.07848262153333053,0.10474200704193208,0.04139025118059202,0.14060123476258013,0.14060122084221802
|
||||||
25.0,0.41080176204708735,0.3530383192829985,0.45731712677712716,0.5840194131238486,0.02929760473668019,0.3162182821357606,0.5247271302425862,0.5245882651817437
|
12.5,0.1345052632171428,0.10035192567447666,0.13611418937449343,0.06825274948835351,0.18353674076730386,0.1835367217194289
|
||||||
30.0,0.5301073454886365,0.5306502765434139,0.6408057261877141,0.6726967507733389,0.029179666470356736,0.3661426990593047,0.6493871028835615,0.6479461262985481
|
15.0,0.17397624759352767,0.1299769427673891,0.1774134961643722,0.11022667550692919,0.23722848522273124,0.23722846306452994
|
||||||
|
17.5,0.22316362340701745,0.16911298831924795,0.2303875518660061,0.16441485880931841,0.30166534237214365,0.30166531551687514
|
||||||
|
20.0,0.28155444214702585,0.21956481272354722,0.296139236476738,0.21888792063296963,0.37473849680507554,0.3747384671261534
|
||||||
|
22.5,0.3466694929706864,0.2826504937937716,0.37431714535458016,0.27025579480204087,0.4521061575273052,0.45210612908937037
|
||||||
|
25.0,0.41391337811248374,0.35837042205035685,0.4623712573153898,0.31270788677551076,0.5278005284816026,0.5278005079459399
|
||||||
|
27.5,0.47757373259635644,0.4446330708428286,0.5553692922927439,0.34371633065177387,0.5959934616461396,0.5959934508893638
|
||||||
|
30.0,0.5326515504252165,0.5369720551883802,0.6469332071393729,0.36358971142016083,0.6525999860465527,0.6525999858789145
|
||||||
|
|||||||
|
+199
-199
@@ -1,199 +1,199 @@
|
|||||||
snr_db,beta,edma,oma,genie
|
snr_db,beta,edma,blind,oma,genie
|
||||||
10,0.0,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
10,0.0,0.054752877862610065,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.01,0.054747350279920316,0.028040940629869258,0.055811993139768964
|
10,0.01,0.05475820153789551,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.02,0.054730767346147666,0.028040940629869258,0.055811993139768964
|
10,0.02,0.05477417262711213,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.03,0.05470312850494755,0.028040940629869258,0.055811993139768964
|
10,0.03,0.054800791320353745,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.04,0.05466443283160872,0.028040940629869258,0.055811993139768964
|
10,0.04,0.054838057934443386,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.05,0.054614679036858765,0.028040940629869258,0.055811993139768964
|
10,0.05,0.05488597291295555,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.06,0.05455386547218096,0.028040940629869258,0.055811993139768964
|
10,0.06,0.054944536826228706,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.07,0.05448199013665998,0.028040940629869258,0.055811993139768964
|
10,0.07,0.055013750371386755,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.08,0.05439905068534405,0.028040940629869258,0.055811993139768964
|
10,0.08,0.05509361437236641,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.09,0.05430504443913251,0.028040940629869258,0.055811993139768964
|
10,0.09,0.055184129779950464,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.1,0.054199968396186245,0.028040940629869258,0.055811993139768964
|
10,0.1,0.05528529767180255,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.11,0.05408381924486196,0.028040940629869258,0.055811993139768964
|
10,0.11,0.05539711925250827,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.12,0.053956593378173205,0.028040940629869258,0.055811993139768964
|
10,0.12,0.055519595853624266,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.13,0.05381828690977572,0.028040940629869258,0.055811993139768964
|
10,0.13,0.05565272893372537,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.14,0.053668895691484,0.028040940629869258,0.055811993139768964
|
10,0.14,0.055796520078463425,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.15,0.05350841533231138,0.028040940629869258,0.055811993139768964
|
10,0.15,0.05595097100062803,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.16,0.0533368412190459,0.028040940629869258,0.055811993139768964
|
10,0.16,0.056116083540211255,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.17,0.05315416853834894,0.028040940629869258,0.055811993139768964
|
10,0.17,0.05629185966448005,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.18,0.0529603923003942,0.028040940629869258,0.055811993139768964
|
10,0.18,0.05647830146804995,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.19,0.052755507364029314,0.028040940629869258,0.055811993139768964
|
10,0.19,0.056675411172967774,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.2,0.05253950846347685,0.028040940629869258,0.055811993139768964
|
10,0.2,0.056883191128795564,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.21,0.05231239023656164,0.028040940629869258,0.055811993139768964
|
10,0.21,0.05710164381270159,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.22,0.0520741472544757,0.028040940629869258,0.055811993139768964
|
10,0.22,0.0573307718295557,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.23,0.05182477405307159,0.028040940629869258,0.055811993139768964
|
10,0.23,0.057570577912030435,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.24,0.05156426516568283,0.028040940629869258,0.055811993139768964
|
10,0.24,0.05782106492070458,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.25,0.051292615157482124,0.028040940629869258,0.055811993139768964
|
10,0.25,0.058082235844175524,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.26,0.05100981866135644,0.028040940629869258,0.055811993139768964
|
10,0.26,0.05835409379917405,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.27,0.05071587041531166,0.028040940629869258,0.055811993139768964
|
10,0.27,0.058636642030681585,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.28,0.05041076530139947,0.028040940629869258,0.055811993139768964
|
10,0.28,0.058929883912060506,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.29,0.050094498386152486,0.028040940629869258,0.055811993139768964
|
10,0.29,0.059233822945179315,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.3,0.04976706496254393,0.028040940629869258,0.055811993139768964
|
10,0.3,0.059548462760553325,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.31,0.04942846059343863,0.028040940629869258,0.055811993139768964
|
10,0.31,0.05987380711747824,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.32,0.04907868115655627,0.028040940629869258,0.055811993139768964
|
10,0.32,0.0602098599041811,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.33,0.04871772289091538,0.028040940629869258,0.055811993139768964
|
10,0.33,0.06055662513796847,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.34,0.04834558244476425,0.028040940629869258,0.055811993139768964
|
10,0.34,0.060914106965381805,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.35000000000000003,0.04796225692498555,0.028040940629869258,0.055811993139768964
|
10,0.35000000000000003,0.061282309662356316,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.36,0.04756774394795485,0.028040940629869258,0.055811993139768964
|
10,0.36,0.06166123763439134,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.37,0.047162041691850294,0.028040940629869258,0.055811993139768964
|
10,0.37,0.06205089541671533,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.38,0.04674514895039684,0.028040940629869258,0.055811993139768964
|
10,0.38,0.06245128767446481,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.39,0.046317065188023115,0.028040940629869258,0.055811993139768964
|
10,0.39,0.06286241920286531,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.4,0.04587779059641903,0.028040940629869258,0.055811993139768964
|
10,0.4,0.06328429492741498,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.41000000000000003,0.045427326152471775,0.028040940629869258,0.055811993139768964
|
10,0.41000000000000003,0.0637169199040789,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.42,0.04496567367756414,0.028040940629869258,0.055811993139768964
|
10,0.42,0.06416029931948275,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.43,0.04449283589819911,0.028040940629869258,0.055811993139768964
|
10,0.43,0.0646144384911171,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.44,0.044008816507942514,0.028040940629869258,0.055811993139768964
|
10,0.44,0.06507934286754048,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.45,0.04351362023064087,0.028040940629869258,0.055811993139768964
|
10,0.45,0.06555501802859463,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.46,0.04300725288489753,0.028040940629869258,0.055811993139768964
|
10,0.46,0.0660414696856211,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.47000000000000003,0.04248972144976068,0.028040940629869258,0.055811993139768964
|
10,0.47000000000000003,0.06653870368168054,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.48,0.04196103413160188,0.028040940629869258,0.055811993139768964
|
10,0.48,0.06704672599178685,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.49,0.041421200432142105,0.028040940629869258,0.055811993139768964
|
10,0.49,0.06756554272313225,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.5,0.040870231217584416,0.028040940629869258,0.055811993139768964
|
10,0.5,0.06809516011533256,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.51,0.04030813878880955,0.028040940629869258,0.055811993139768964
|
10,0.51,0.06863558454066575,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.52,0.03973493695259877,0.028040940629869258,0.055811993139768964
|
10,0.52,0.06918682250432519,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.53,0.039150641093819265,0.028040940629869258,0.055811993139768964
|
10,0.53,0.06974888064467029,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.54,0.03855526824853652,0.028040940629869258,0.055811993139768964
|
10,0.54,0.07032176573348846,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.55,0.03794883717799136,0.028040940629869258,0.055811993139768964
|
10,0.55,0.07090548467626023,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.56,0.03733136844337993,0.028040940629869258,0.055811993139768964
|
10,0.56,0.07150004451242854,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.5700000000000001,0.03670288448138829,0.028040940629869258,0.055811993139768964
|
10,0.5700000000000001,0.0721054524156766,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.58,0.036063409680404356,0.028040940629869258,0.055811993139768964
|
10,0.58,0.07272171569420816,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.59,0.035412970457347266,0.028040940629869258,0.055811993139768964
|
10,0.59,0.07334884179103472,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.6,0.034751595335041165,0.028040940629869258,0.055811993139768964
|
10,0.6,0.07398683828426894,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.61,0.03407931502005716,0.028040940629869258,0.055811993139768964
|
10,0.61,0.07463571288742164,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.62,0.033396162480946456,0.028040940629869258,0.055811993139768964
|
10,0.62,0.07529547344970607,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.63,0.03270217302678281,0.028040940629869258,0.055811993139768964
|
10,0.63,0.07596612795634762,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.64,0.03199738438593123,0.028040940629869258,0.055811993139768964
|
10,0.64,0.07664768452889742,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.65,0.03128183678494588,0.028040940629869258,0.055811993139768964
|
10,0.65,0.07734015142555628,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.66,0.030555573027513647,0.028040940629869258,0.055811993139768964
|
10,0.66,0.07804353704149611,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.67,0.02981863857334309,0.028040940629869258,0.055811993139768964
|
10,0.67,0.07875784990919524,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.68,0.02907108161689106,0.028040940629869258,0.055811993139768964
|
10,0.68,0.07948309869877611,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.6900000000000001,0.028312953165838792,0.028040940629869258,0.055811993139768964
|
10,0.6900000000000001,0.08021929221834728,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.7000000000000001,0.027544307119194162,0.028040940629869258,0.055811993139768964
|
10,0.7000000000000001,0.08096643941435333,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.71,0.026765200344916605,0.028040940629869258,0.055811993139768964
|
10,0.71,0.08172454937193066,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.72,0.02597569275694614,0.028040940629869258,0.055811993139768964
|
10,0.72,0.08249363131526735,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.73,0.025175847391522434,0.028040940629869258,0.055811993139768964
|
10,0.73,0.08327369460797196,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.74,0.024365730482666725,0.028040940629869258,0.055811993139768964
|
10,0.74,0.08406474875344346,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.75,0.023545411536702542,0.028040940629869258,0.055811993139768964
|
10,0.75,0.08486680339525016,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.76,0.022714963405684276,0.028040940629869258,0.055811993139768964
|
10,0.76,0.08567986831752004,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.77,0.02187446235961152,0.028040940629869258,0.055811993139768964
|
10,0.77,0.08650395344532251,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.78,0.021023988157275277,0.028040940629869258,0.055811993139768964
|
10,0.78,0.08733906884507195,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.79,0.0201636241156152,0.028040940629869258,0.055811993139768964
|
10,0.79,0.08818522472492742,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.8,0.019293457177440704,0.028040940629869258,0.055811993139768964
|
10,0.8,0.08904243143520407,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.81,0.018413577977365713,0.028040940629869258,0.055811993139768964
|
10,0.81,0.08991069946878359,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.8200000000000001,0.01752408090582169,0.028040940629869258,0.055811993139768964
|
10,0.8200000000000001,0.09079003946154299,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.8300000000000001,0.016625064170996434,0.028040940629869258,0.055811993139768964
|
10,0.8300000000000001,0.09168046219277223,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.84,0.015716629858541303,0.028040940629869258,0.055811993139768964
|
10,0.84,0.09258197858561873,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.85,0.014798883988911094,0.028040940629869258,0.055811993139768964
|
10,0.85,0.0934945997075168,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.86,0.013871936572160262,0.028040940629869258,0.055811993139768964
|
10,0.86,0.09441833677064365,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.87,0.012935901660068121,0.028040940629869258,0.055811993139768964
|
10,0.87,0.09535320113236508,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.88,0.011990897395407239,0.028040940629869258,0.055811993139768964
|
10,0.88,0.09629920429569758,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.89,0.011037046058227617,0.028040940629869258,0.055811993139768964
|
10,0.89,0.0972563579097737,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.9,0.010074474108977324,0.028040940629869258,0.055811993139768964
|
10,0.9,0.09822467377031467,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.91,0.009103312228316158,0.028040940629869258,0.055811993139768964
|
10,0.91,0.09920416382010676,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.92,0.008123695353459515,0.028040940629869258,0.055811993139768964
|
10,0.92,0.100194840149489,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.93,0.007135762710902627,0.028040940629869258,0.055811993139768964
|
10,0.93,0.10119671499684378,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.9400000000000001,0.006139657845366697,0.028040940629869258,0.055811993139768964
|
10,0.9400000000000001,0.10220980074909554,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.9500000000000001,0.0051355286448144695,0.028040940629869258,0.055811993139768964
|
10,0.9500000000000001,0.1032341099422143,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.96,0.004123527361384938,0.028040940629869258,0.055811993139768964
|
10,0.96,0.104269655261731,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.97,0.0031038106281055557,0.028040940629869258,0.055811993139768964
|
10,0.97,0.10531644954325302,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
10,0.98,0.002076539471223253,0.028040940629869258,0.055811993139768964
|
10,0.98,0.10637450577298989,0.054752877862610065,0.028040940629869258,0.055811993139768964
|
||||||
20,0.0,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
20,0.0,0.4366911765474922,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.01,0.4366440287117167,0.2688526404418522,0.5147756853853035
|
20,0.01,0.43672694031779324,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.02,0.43650257394341674,0.2688526404418522,0.5147756853853035
|
20,0.02,0.4368342357122561,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.03,0.43626677851363305,0.2688526404418522,0.5147756853853035
|
20,0.03,0.43701307498298886,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.04,0.4359365863873445,0.2688526404418522,0.5147756853853035
|
20,0.04,0.4372634785549242,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.05,0.4355119194934469,0.2688526404418522,0.5147756853853035
|
20,0.05,0.43758547503295236,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.06,0.43499267810292913,0.2688526404418522,0.5147756853853035
|
20,0.06,0.43797910121191785,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.07,0.43437874131546467,0.2688526404418522,0.5147756853853035
|
20,0.07,0.4384444020894803,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.08,0.433669967654663,0.2688526404418522,0.5147756853853035
|
20,0.08,0.4389814308818518,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.09,0.4328661957722866,0.2688526404418522,0.5147756853853035
|
20,0.09,0.4395902490424265,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.1,0.4319672452617536,0.2688526404418522,0.5147756853853035
|
20,0.1,0.44027092628330783,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.11,0.43097291758127854,0.2688526404418522,0.5147756853853035
|
20,0.11,0.44102354059974963,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.12,0.4298829970870116,0.2688526404418522,0.5147756853853035
|
20,0.12,0.441848178297537,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.13,0.42869725217652294,0.2688526404418522,0.5147756853853035
|
20,0.13,0.44274493402331877,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.14,0.42741543654296693,0.2688526404418522,0.5147756853853035
|
20,0.14,0.44371391079791206,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.15,0.4260372905402156,0.2688526404418522,0.5147756853853035
|
20,0.15,0.44475522005260776,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.16,0.424562542659194,0.2688526404418522,0.5147756853853035
|
20,0.16,0.4458689816685024,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.17,0.4229909111155674,0.2688526404418522,0.5147756853853035
|
20,0.17,0.4470553240188804,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.18,0.4213221055488418,0.2688526404418522,0.5147756853853035
|
20,0.18,0.4483143840146794,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.19,0.4195558288327915,0.2688526404418522,0.5147756853853035
|
20,0.19,0.4496463071530782,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.2,0.4176917789970004,0.2688526404418522,0.5147756853853035
|
20,0.2,0.4510512475692266,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.21,0.41572965125910694,0.2688526404418522,0.5147756853853035
|
20,0.21,0.45252936809117394,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.22,0.413669140167154,0.2688526404418522,0.5147756853853035
|
20,0.22,0.4540808402980178,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.23,0.411509941851192,0.2688526404418522,0.5147756853853035
|
20,0.23,0.4557058445813321,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.24,0.40925175638303946,0.2688526404418522,0.5147756853853035
|
20,0.24,0.4574045702099053,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.25,0.40689429024279106,0.2688526404418522,0.5147756853853035
|
20,0.25,0.4591772153978466,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.26,0.40443725889034393,0.2688526404418522,0.5147756853853035
|
20,0.26,0.461023987376106,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.27,0.40188038943985416,0.2688526404418522,0.5147756853853035
|
20,0.27,0.46294510246745635,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.28,0.399223423434633,0.2688526404418522,0.5147756853853035
|
20,0.28,0.46494078616500706,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.29,0.39646611971957335,0.2688526404418522,0.5147756853853035
|
20,0.29,0.46701127321428854,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.3,0.3936082574077306,0.2688526404418522,0.5147756853853035
|
20,0.3,0.4691568076989885,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.31,0.3906496389371964,0.2688526404418522,0.5147756853853035
|
20,0.31,0.4713776431303909,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.32,0.3875900932138665,0.2688526404418522,0.5147756853853035
|
20,0.32,0.4736740425405888,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.33,0.38442947883515566,0.2688526404418522,0.5147756853853035
|
20,0.33,0.4760462785795442,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.34,0.3811676873891227,0.2688526404418522,0.5147756853853035
|
20,0.34,0.4784946336160657,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.35000000000000003,0.37780464682285725,0.2688526404418522,0.5147756853853035
|
20,0.35000000000000003,0.4810193998427861,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.36,0.3743403248733226,0.2688526404418522,0.5147756853853035
|
20,0.36,0.4836208793852107,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.37,0.3707747325532069,0.2688526404418522,0.5147756853853035
|
20,0.37,0.48629938441493437,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.38,0.36710792768362743,0.2688526404418522,0.5147756853853035
|
20,0.38,0.4890552372671043,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.39,0.36334001846484065,0.2688526404418522,0.5147756853853035
|
20,0.39,0.4918887705622219,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.4,0.35947116707538496,0.2688526404418522,0.5147756853853035
|
20,0.4,0.49480032733238916,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.41000000000000003,0.35550159328936487,0.2688526404418522,0.5147756853853035
|
20,0.41000000000000003,0.49779026115208486,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.42,0.3514315781008482,0.2688526404418522,0.5147756853853035
|
20,0.42,0.5008589362735847,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.43,0.3472614673436184,0.2688526404418522,0.5147756853853035
|
20,0.43,0.5040067277671271,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.44,0.3429916752938002,0.2688526404418522,0.5147756853853035
|
20,0.44,0.5072340216659497,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.45,0.3386226882421745,0.2688526404418522,0.5147756853853035
|
20,0.45,0.5105412151162935,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.46,0.3341550680222958,0.2688526404418522,0.5147756853853035
|
20,0.46,0.5139287165325166,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.47000000000000003,0.32958945547987767,0.2688526404418522,0.5147756853853035
|
20,0.47000000000000003,0.517396945757436,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.48,0.3249265738682723,0.2688526404418522,0.5147756853853035
|
20,0.48,0.5209463342280231,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.49,0.32016723215429327,0.2688526404418522,0.5147756853853035
|
20,0.49,0.5245773251466092,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.5,0.3153123282180963,0.2688526404418522,0.5147756853853035
|
20,0.5,0.5282903736577237,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.51,0.3103628519303606,0.2688526404418522,0.5147756853853035
|
20,0.51,0.5320859470307273,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.52,0.3053198880896007,0.2688526404418522,0.5147756853853035
|
20,0.52,0.5359645248483909,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.53,0.3001846192021282,0.2688526404418522,0.5147756853853035
|
20,0.53,0.539926599201581,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.54,0.2949583280869223,0.2688526404418522,0.5147756853853035
|
20,0.54,0.5439726748902178,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.55,0.2896424002875374,0.2688526404418522,0.5147756853853035
|
20,0.55,0.5481032696306882,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.56,0.2842383262731147,0.2688526404418522,0.5147756853853035
|
20,0.56,0.5523189142698807,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.5700000000000001,0.27874770341065014,0.2688526404418522,0.5147756853853035
|
20,0.5700000000000001,0.5566201530060465,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.58,0.27317223769083826,0.2688526404418522,0.5147756853853035
|
20,0.58,0.5610075436166748,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.59,0.2675137451901349,0.2688526404418522,0.5147756853853035
|
20,0.59,0.5654816576935766,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.6,0.26177415325210973,0.2688526404418522,0.5147756853853035
|
20,0.6,0.570043080885417,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.61,0.25595550137174955,0.2688526404418522,0.5147756853853035
|
20,0.61,0.5746924131478852,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.62,0.2500599417670772,0.2688526404418522,0.5147756853853035
|
20,0.62,0.5794302690017478,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.63,0.24408973962332856,0.2688526404418522,0.5147756853853035
|
20,0.63,0.5842572777990267,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.64,0.238047272995916,0.2688526404418522,0.5147756853853035
|
20,0.64,0.5891740839975437,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.65,0.23193503235958426,0.2688526404418522,0.5147756853853035
|
20,0.65,0.5941813474440859,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.66,0.22575561979243286,0.2688526404418522,0.5147756853853035
|
20,0.66,0.5992797436664702,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.67,0.21951174778494328,0.2688526404418522,0.5147756853853035
|
20,0.67,0.6044699641747866,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.68,0.21320623766571534,0.2688526404418522,0.5147756853853035
|
20,0.68,0.609752716772098,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.6900000000000001,0.20684201763731608,0.2688526404418522,0.5147756853853035
|
20,0.6900000000000001,0.6151287258749181,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.7000000000000001,0.20042212041749688,0.2688526404418522,0.5147756853853035
|
20,0.7000000000000001,0.6205987328437688,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.71,0.1939496804829589,0.2688526404418522,0.5147756853853035
|
20,0.71,0.6261634963241505,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.72,0.18742793091491083,0.2688526404418522,0.5147756853853035
|
20,0.72,0.6318237925982698,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.73,0.1808601998477949,0.2688526404418522,0.5147756853853035
|
20,0.73,0.6375804159478764,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.74,0.17424990652476743,0.2688526404418522,0.5147756853853035
|
20,0.74,0.643434179028581,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.75,0.16760055696580017,0.2688526404418522,0.5147756853853035
|
20,0.75,0.6493859132560444,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.76,0.16091573925657646,0.2688526404418522,0.5147756853853035
|
20,0.76,0.6554364692044342,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.77,0.15419911846869444,0.2688526404418522,0.5147756853853035
|
20,0.77,0.6615867170175782,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.78,0.147454431224025,0.2688526404418522,0.5147756853853035
|
20,0.78,0.667837546833235,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.79,0.14068547991839878,0.2688526404418522,0.5147756853853035
|
20,0.79,0.6741898692209654,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.8,0.13389612662207573,0.2688526404418522,0.5147756853853035
|
20,0.8,0.6806446156340422,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.81,0.12709028667666042,0.2688526404418522,0.5147756853853035
|
20,0.81,0.6872027388759366,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.8200000000000001,0.12027192201028448,0.2688526404418522,0.5147756853853035
|
20,0.8200000000000001,0.6938652135818649,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.8300000000000001,0.11344503419488466,0.2688526404418522,0.5147756853853035
|
20,0.8300000000000001,0.7006330367159468,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.84,0.10661365727133493,0.2688526404418522,0.5147756853853035
|
20,0.84,0.707507228084549,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.85,0.0997818503699352,0.2688526404418522,0.5147756853853035
|
20,0.85,0.7144888308663817,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.86,0.09295369015536699,0.2688526404418522,0.5147756853853035
|
20,0.86,0.7215789121599784,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.87,0.0861332631266301,0.2688526404418522,0.5147756853853035
|
20,0.87,0.7287785635491948,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.88,0.07932465780369294,0.2688526404418522,0.5147756853853035
|
20,0.88,0.7360889016873875,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.89,0.07253195683359023,0.2688526404418522,0.5147756853853035
|
20,0.89,0.7435110689009868,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.9,0.06575922904947452,0.2688526404418522,0.5147756853853035
|
20,0.9,0.7510462338131872,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.91,0.059010521516665373,0.2688526404418522,0.5147756853853035
|
20,0.91,0.7586955919885129,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.92,0.052289851600038885,0.2688526404418522,0.5147756853853035
|
20,0.92,0.7664603665990705,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.93,0.04560119908714468,0.2688526404418522,0.5147756853853035
|
20,0.93,0.7743418091133101,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.9400000000000001,0.03894849840124009,0.2688526404418522,0.5147756853853035
|
20,0.9400000000000001,0.7823412000081834,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.9500000000000001,0.03233563093797358,0.2688526404418522,0.5147756853853035
|
20,0.9500000000000001,0.7904598495055949,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.96,0.025766417558755906,0.2688526404418522,0.5147756853853035
|
20,0.96,0.7986990983341251,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.97,0.019244611272917996,0.2688526404418522,0.5147756853853035
|
20,0.97,0.807060318516999,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
20,0.98,0.012773890139589456,0.2688526404418522,0.5147756853853035
|
20,0.98,0.8155449141873803,0.4366911765474922,0.2688526404418522,0.5147756853853035
|
||||||
|
|||||||
|
@@ -0,0 +1,3 @@
|
|||||||
|
beta,aware_mc,aware_pred,blind_mc,blind_pred
|
||||||
|
0.311,0.7251058104634285,0.7244273905766959,0.7074751788377762,0.7071067811865476
|
||||||
|
0.8,0.8371337348222733,0.8366600265340756,0.7081796124577522,0.7071067811865476
|
||||||
|
+7
-7
@@ -1,8 +1,8 @@
|
|||||||
sigma_h2,edma,sic
|
sigma_h2,edma,sic
|
||||||
0.0,0.5445012038424076,0.5460929325736039
|
0.0,0.5985892848856748,0.5827705618180334
|
||||||
0.01,0.5445012038424075,0.5432828884753359
|
0.01,0.5970788184367121,0.5824256975366734
|
||||||
0.02,0.5445012038424075,0.5408883972120776
|
0.02,0.5956342787574976,0.5820832186681218
|
||||||
0.05,0.5445012038424076,0.536040175102482
|
0.05,0.5913892493443563,0.5813290306786075
|
||||||
0.1,0.5445012038424076,0.5277163316448914
|
0.1,0.5849188896268607,0.5799057619913947
|
||||||
0.2,0.5445012038424075,0.5169782457463995
|
0.2,0.5753242927324027,0.5776647866773419
|
||||||
0.3,0.5445012038424076,0.5125870168901699
|
0.3,0.5690016979491338,0.5756815607612953
|
||||||
|
|||||||
|
+35
-35
@@ -1,35 +1,35 @@
|
|||||||
d,snr_db,mse_mc,mse_theory,mse_ideal
|
d,snr_db,mse_mc,mse_theory,mse_blind
|
||||||
256,0.0,283.9142603214685,284.4533071258869,283.41188049318094
|
256,0.0,0.9958906187265965,0.9957520371754321,0.9961240310077519
|
||||||
256,2.5,160.10089036917105,160.41563908393022,159.37421245122425
|
256,2.5,0.9926509086327597,0.9924951337006896,0.993148778755109
|
||||||
256,5.0,90.47776215634474,90.66413246369561,89.62270583098966
|
256,5.0,0.9869671196373861,0.9868069561728815,0.9879451709874938
|
||||||
256,7.5,51.32748447743017,51.439977796849504,50.398551164143555
|
256,7.5,0.9771456527581006,0.9770064578879146,0.9789579793127183
|
||||||
256,10.0,29.312928645832216,29.38261468202405,28.3411880493181
|
256,10.0,0.9605855179298334,0.9605076750198117,0.9637681159420289
|
||||||
256,12.5,16.934181412329476,16.978847877828375,15.937421245122422
|
256,12.5,0.9337484810109989,0.9337823722702523,0.9390092836053628
|
||||||
256,15.0,9.973810638369487,10.00369721580492,8.962270583098967
|
256,15.0,0.8928736458420425,0.8930612771894957,0.9009452871484813
|
||||||
256,17.5,6.060239200519523,6.081281749120308,5.039855116414356
|
256,17.5,0.8360494261292735,0.8363998816883345,0.8473840548704382
|
||||||
256,20.0,3.85987571082472,3.8755454376377614,2.8341188049318093
|
256,20.0,0.7661668636283875,0.7666566714783413,0.7807017543859648
|
||||||
256,22.5,2.622819942039895,2.6351687572181945,1.5937421245122423
|
256,22.5,0.691947677239615,0.6925661718278007,0.709267994905624
|
||||||
256,25.0,1.9273969939302285,1.9376536910158488,0.8962270583098966
|
256,25.0,0.6243632968967908,0.6251571720537481,0.6440702380534542
|
||||||
256,27.5,1.5365003821408372,1.5454121443473878,0.5039855116414356
|
256,27.5,0.5709153641061163,0.571972710197798,0.5927077630509127
|
||||||
256,30.0,1.3168093834480725,1.3248385131991331,0.28341188049318095
|
256,30.0,0.5331897043219835,0.53458472828743,0.5567375886524822
|
||||||
256,32.5,1.1933627827422904,1.2008008451571766,0.15937421245122424
|
256,32.5,0.5086536205122679,0.5104122867933932,0.5335732525163734
|
||||||
256,35.0,1.1240146926635879,1.131049338536942,0.08962270583098966
|
256,35.0,0.4935273743565432,0.4956303135714446,0.5194512459464362
|
||||||
256,37.5,1.085070664488797,1.0918251838700959,0.05039855116414356
|
256,37.5,0.4844975136532381,0.48689966319840416,0.5111276997838433
|
||||||
256,40.0,1.0632107739660197,1.0697678207552703,0.028341188049318098
|
256,40.0,0.4792009242590312,0.48184935117050987,0.5063191153238548
|
||||||
768,0.0,853.4623064741292,851.2770681122488,850.2356414795429
|
768,0.0,0.9986765012793098,0.9985760128125698,0.9987012987012988
|
||||||
768,2.5,480.3951698733645,479.1640639863787,478.12263735367276
|
768,2.5,0.9976163216681129,0.9974733083167204,0.9976952053744985
|
||||||
768,5.0,270.60393697803266,269.9095441256749,268.86811749296896
|
768,5.0,0.9957307732307438,0.9955242936982399,0.9959160824250755
|
||||||
768,7.5,152.62953339008442,152.23708012513663,151.19565349243067
|
768,7.5,0.9923981843904192,0.992095537514675,0.9927835275542491
|
||||||
768,10.0,86.28755819977675,86.06499078066025,85.0235641479543
|
768,10.0,0.9865629253484912,0.9861129415585025,0.9873096446700508
|
||||||
768,12.5,48.98065441173488,48.85369036807322,47.81226373536727
|
768,12.5,0.9764985106901773,0.9758221660225336,0.9778701398348755
|
||||||
768,15.0,28.001388546341435,27.928238382002856,26.886811749296903
|
768,15.0,0.9595662490049409,0.9585462259188507,0.9619573584726929
|
||||||
768,17.5,16.203841270734593,16.160991981949017,15.119565349243066
|
768,17.5,0.9322122252329521,0.9306888249982047,0.9361315623151921
|
||||||
768,20.0,9.569563575405624,9.543783047501382,8.502356414795429
|
768,20.0,0.8907470407123728,0.8885385986762078,0.8966942148760331
|
||||||
768,22.5,5.838813072859685,5.822653006242679,4.781226373536727
|
768,22.5,0.8334967999962878,0.8304680517855016,0.8417416365176289
|
||||||
768,25.0,3.7408413998745558,3.730107807635642,2.6886811749296897
|
768,25.0,0.7637208092945489,0.759888721537542,0.7741964962231777
|
||||||
768,27.5,2.5610528622492597,2.553383167630259,1.5119565349243067
|
768,27.5,0.6903787748107578,0.6859650675890866,0.7028866275721191
|
||||||
768,30.0,1.8975997387446928,1.8916622741854952,0.8502356414795429
|
768,30.0,0.6242938905723492,0.6196325851274082,0.638728323699422
|
||||||
768,32.5,1.5245056756935615,1.519549270059625,0.4781226373536727
|
768,32.5,0.5725413154691661,0.5679130695479454,0.5887951848908111
|
||||||
768,35.0,1.314694250809021,1.3102947501989213,0.268868117492969
|
768,35.0,0.5363309035044117,0.5318795970416631,0.554141276684715
|
||||||
768,37.5,1.1967047053652895,1.1926222861983828,0.15119565349243066
|
768,37.5,0.5129687106701781,0.5087260331425658,0.5319605114462806
|
||||||
768,40.0,1.1303513753850125,1.1264501968539065,0.0850235641479543
|
768,40.0,0.498680130948561,0.4946227489687355,0.5184899845916795
|
||||||
|
|||||||
|
+10
-10
@@ -1,10 +1,10 @@
|
|||||||
snr_db,haar,wh
|
snr_db,haar,wh,wh_exact_mse
|
||||||
0,0.05647200954133838,0.05310404690708958
|
0,0.056410143594257535,0.055201172281522305,0.9978637042641639
|
||||||
5,0.08330434028403662,0.07868202035026188
|
5,0.085697923428379,0.08462585555389524,0.9933106958866119
|
||||||
10,0.1362057604122267,0.1321506210735374
|
10,0.14458728155121206,0.14321016235277056,0.9794808036088943
|
||||||
15,0.22743813806699198,0.22553342842896307
|
15,0.24451895691454412,0.2423005321621895,0.9407034531235695
|
||||||
20,0.3620849406777639,0.36807222557624214
|
20,0.3882001306116581,0.3829878903925419,0.8522246733307839
|
||||||
25,0.5112067973087223,0.5367516728593701
|
25,0.540928793400526,0.5299757443368435,0.7177656385302543
|
||||||
30,0.6187704792155053,0.6693336605430739
|
30,0.6472152987122536,0.631390101313591,0.5997132909297943
|
||||||
35,0.670208963249346,0.7373274649462636
|
35,0.6973008319735527,0.6793428674340248,0.5366590532660485
|
||||||
40,0.689340654075078,0.7636921461142663
|
40,0.7159504926204682,0.6972508707642555,0.5119321745634079
|
||||||
|
|||||||
|
@@ -0,0 +1,8 @@
|
|||||||
|
beta_hat,cosine,mse
|
||||||
|
0.211,0.3896048231422901,0.8489142748713493
|
||||||
|
0.251,0.3904690830409527,0.8482141560316085
|
||||||
|
0.311,0.3909398098289967,0.8478092220425606
|
||||||
|
0.371,0.3904550792276859,0.8481874433159828
|
||||||
|
0.41100000000000003,0.38962371706962584,0.8488810566067696
|
||||||
|
0.31490625,0.3909368622303009,0.8478098925948143
|
||||||
|
0.0,0.37743803575634954,0.858243175148964
|
||||||
|
@@ -1,40 +1,40 @@
|
|||||||
U,snr_db,edma,oma
|
U,snr_db,edma_mc,blind,oma,mse_mc
|
||||||
2,0.0,0.005074924495401339,0.0028163887856167778
|
2,0.0,0.0067459622753358985,0.005619067173648297,0.0028163887856167778,0.9976647585630417
|
||||||
2,2.5,0.00900326092256961,0.005006425437490073
|
2,2.5,0.011675481754301935,0.009969612776119413,0.005006425437490073,0.9959617620706558
|
||||||
2,5.0,0.015943181620258408,0.008896821012114422
|
2,5.0,0.020286535908117426,0.017657570045582938,0.008896821012114422,0.9929938805103302
|
||||||
2,7.5,0.028141662406857754,0.015802100105602065
|
2,7.5,0.035291135414103295,0.03117756291292608,0.015802100105602065,0.9878435188531876
|
||||||
2,10.0,0.04939420068532773,0.028040940629869258
|
2,10.0,0.06125380524795852,0.054752877862610065,0.028040940629869258,0.978994796872139
|
||||||
2,12.5,0.08585687636915751,0.04967759953004671
|
2,12.5,0.10554787426027339,0.09526158699989311,0.04967759953004671,0.9640808624029159
|
||||||
2,15.0,0.14680246472845263,0.08775733805059951
|
2,15.0,0.17922846076711016,0.16314404591732876,0.08775733805059951,0.9397740066051483
|
||||||
2,17.5,0.24437407492333546,0.15425664820473364
|
2,17.5,0.29671520331202866,0.27228552723458505,0.15425664820473364,0.9022770518064499
|
||||||
2,20.0,0.39036168250847997,0.2688526404418522
|
2,20.0,0.47207515868714434,0.4366911765474922,0.2688526404418522,0.8490741294622421
|
||||||
2,22.5,0.5882403211652596,0.46202930580118473
|
2,22.5,0.7100570759041679,0.6617728169555368,0.46202930580118473,0.7818541771173477
|
||||||
2,25.0,0.8236174091640396,0.7765249721523131
|
2,25.0,0.9952787609812811,0.9331238669104754,0.7765249721523131,0.708264736533165
|
||||||
2,27.5,1.0639633374340793,1.2629750132730075
|
2,27.5,1.290911785811443,1.2146443868700316,1.2629750132730075,0.639290742278099
|
||||||
2,30.0,1.2740371164829405,1.9659871493886203
|
2,30.0,1.5545191724506118,1.4647566493411088,1.9659871493886203,0.5834740561246872
|
||||||
3,0.0,0.007166121727981404,0.002816846908845676
|
3,0.0,0.008221550750832831,0.008412218630107837,0.002816846908845676,0.9981022214889527
|
||||||
3,2.5,0.012688743558228709,0.005007872928745025
|
3,2.5,0.015313679039211471,0.014902926454674073,0.005007872928745025,0.9964680409431458
|
||||||
3,5.0,0.022393454021796717,0.00890139152557443
|
3,5.0,0.028029675597543307,0.026325253299532562,0.00890139152557443,0.9935446953773499
|
||||||
3,7.5,0.03929335948023371,0.015816514922095765
|
3,7.5,0.050514313628626004,0.04626641612972433,0.015816514922095765,0.988396560549736
|
||||||
3,10.0,0.0682640356183996,0.028086309611073952
|
3,10.0,0.08952942310946198,0.08059981755804599,0.028086309611073952,0.9795267921686173
|
||||||
3,12.5,0.11661479903052363,0.04981987507531682
|
3,12.5,0.15534005610649262,0.13832515321163041,0.04981987507531682,0.9647452771663666
|
||||||
3,15.0,0.19381754610825597,0.08820067087182441
|
3,15.0,0.2615951480089572,0.2316168228614546,0.08820067087182441,0.9413490122556687
|
||||||
3,17.5,0.3087986357540208,0.15562283620381148
|
3,17.5,0.4221435294251369,0.3731878021467334,0.15562283620381148,0.9070698082447052
|
||||||
3,20.0,0.46347315369044484,0.27298359666177824
|
3,20.0,0.6428146293469728,0.5688074586563354,0.27298359666177824,0.8619812881946564
|
||||||
3,22.5,0.6453865207846086,0.4741321857975819
|
3,22.5,0.9107931284704225,0.8069275801266587,0.4741321857975819,0.8102293717861175
|
||||||
3,25.0,0.8284280872854691,0.8102498992888099
|
3,25.0,1.192151455674711,1.0559460071626627,0.8102498992888099,0.7592338293790817
|
||||||
3,27.5,0.9858586691638921,1.3502134677042328
|
3,27.5,1.4460078396289984,1.2782661617838726,1.3502134677042328,0.7159830737113952
|
||||||
3,30.0,1.1039774302731393,2.1701295882547527
|
3,30.0,1.6453250009668556,1.4503691419311937,2.1701295882547527,0.6837582939863205
|
||||||
4,0.0,0.009176956996801149,0.002817076044986573
|
4,0.0,0.015142645594341335,0.011194533410694072,0.002817076044986573,0.9973794192075729
|
||||||
4,2.5,0.01621312884680335,0.005008597092951442
|
4,2.5,0.02657168051302456,0.01980238285260359,0.005008597092951442,0.9954060631990432
|
||||||
4,5.0,0.028502070980983823,0.008903679130992838
|
4,5.0,0.04649602868391863,0.03488813263113353,0.008903679130992838,0.9919752240180969
|
||||||
4,7.5,0.04967547887822116,0.015823735486660634
|
4,7.5,0.0808285062062145,0.0610360844265235,0.015823735486660634,0.9860911220312119
|
||||||
4,10.0,0.08531654320798115,0.028109067575874017
|
4,10.0,0.1387823700129495,0.10550166169718982,0.028109067575874017,0.9762377244234085
|
||||||
4,12.5,0.14302271741867906,0.04989142100177373
|
4,12.5,0.23327828100624443,0.17872115676402342,0.04989142100177373,0.9603821069002152
|
||||||
4,15.0,0.2308213082888609,0.08842458349643963
|
4,15.0,0.3790651258653871,0.29313196378582485,0.08842458349643963,0.9364239370822907
|
||||||
4,17.5,0.3525340922014516,0.15631809220986412
|
4,17.5,0.5861777540534772,0.458064715640174,0.15631809220986412,0.9034117364883423
|
||||||
4,20.0,0.5011822600084102,0.27511311194165045
|
4,20.0,0.8490808651568857,0.6702163879182615,0.27511311194165045,0.8631778705120087
|
||||||
4,22.5,0.6570342137422986,0.4805054388299137
|
4,22.5,1.1397156040760281,0.9064855445133952,0.48050543882991376,0.8207820576429367
|
||||||
4,25.0,0.7963620296794736,0.8286132554549862
|
4,25.0,1.4160565809869674,1.1309122590875245,0.8286132554549861,0.7824041104316711
|
||||||
4,27.5,0.9042441392584162,1.4000909956579182
|
4,27.5,1.6433747432527392,1.3140736832668964,1.4000909956579182,0.752183369398117
|
||||||
4,30.0,0.9788428109037877,2.294588749973288
|
4,30.0,1.808776977801607,1.4458968914537418,2.294588749973288,0.7309303051233291
|
||||||
|
|||||||
|
+83
-32
@@ -1,32 +1,83 @@
|
|||||||
snr_db,edma,edma_ideal,oma,genie,mac
|
snr_db,edma,blind,oma,genie,mac
|
||||||
0.0,0.005074922224889888,0.005085968590195728,0.0028163887856167778,0.0056300312141080765,0.005624549193878107
|
0.0,0.0061610171386374275,0.005619067173648297,0.0028163887856167778,0.0056300312141080765,0.005624549193878107
|
||||||
1.0,0.006383905773418096,0.00640139527831988,0.003545175584028836,0.007086000682366226,0.007077321020140645
|
0.5,0.00691010417674122,0.0063024511854892495,0.003159852086906414,0.006316247537633628,0.006309349361561283
|
||||||
2.0,0.008028883565814418,0.008056567110301317,0.004462402142875826,0.008917913609859949,0.008904174704705635
|
1.0,0.007749905158458553,0.007068641357914831,0.003545175584028836,0.007086000682366226,0.007077321020140645
|
||||||
3.0,0.010095150934059762,0.010138955836487416,0.005616707528960678,0.01122250279942868,0.011200762797452897
|
1.5,0.00869131183087741,0.007927592484830619,0.003977454409125839,0.007949433521018416,0.00793851300292445
|
||||||
4.0,0.012689107038928529,0.01275839279457609,0.007069235608353175,0.014121193837328306,0.014086807264803002
|
2.0,0.00974649960657886,0.008890435799551143,0.004462402142875826,0.008917913609859949,0.008904174704705635
|
||||||
5.0,0.015943159211639874,0.016052690844464874,0.008896821012114422,0.017766293841720057,0.017711931943651758
|
2.5,0.010929072665281737,0.009969612776119413,0.005006425437490073,0.010004179295885398,0.009986896036002313
|
||||||
6.0,0.02002158323181113,0.02019462550149604,0.011195969967589819,0.022348664887473,0.022262779372211397
|
3.0,0.012254223859673589,0.011179022795476752,0.005616707528960678,0.01122250279942868,0.011200762797452897
|
||||||
7.0,0.025127416528746203,0.025400572273952007,0.014087824481532864,0.028107199678235918,0.02797162021400105
|
3.5,0.013738910514711638,0.012534185756127438,0.006301301667732704,0.012588872126580048,0.012561528941353725
|
||||||
8.0,0.0315103938374857,0.03194114344476364,0.017724337286238952,0.03534046212793969,0.03512665200704765
|
4.0,0.01540204717058254,0.014052420692277471,0.007069235608353175,0.014121193837328306,0.014086807264803002
|
||||||
9.0,0.03947581013823077,0.040154209208400245,0.022295928433737136,0.044420892444668104,0.044084138042602035
|
4.5,0.017264716236363182,0.015753041409356024,0.007930628420075834,0.015839518874396368,0.015796280141876264
|
||||||
10.0,0.049393985592843845,0.05046071565802713,0.028040940629869258,0.055811993139768964,0.0552824355011896
|
5.0,0.019350397380995952,0.017657570045582938,0.008896821012114422,0.017766293841720057,0.017711931943651758
|
||||||
11.0,0.06170967643915826,0.0633837099689487,0.03525725553198444,0.07008888995333985,0.0692577754750065
|
5.5,0.02168521627394186,0.01978996930424075,0.009980521909443284,0.019926640307263106,0.019858304805751847
|
||||||
12.0,0.0769502860361166,0.07957092682607385,0.04431647029951141,0.08796257073317358,0.08666134967423425
|
6.0,0.024298212980174518,0.022176893856949428,0.011195969967589819,0.022348664887473,0.022262779372211397
|
||||||
13.0,0.09573105092136092,0.0998211434335674,0.05568105080659391,0.11030790336846401,0.10827678933608055
|
6.5,0.02722162988947048,0.024847961072149566,0.012559115877317157,0.025063803043938227,0.02495588205804394
|
||||||
14.0,0.11875450818829247,0.12511422236562836,0.06992485602776169,0.13819516297913534,0.13503645793865676
|
7.0,0.030491218490760343,0.027836040749765856,0.014087824481532864,0.028107199678235918,0.02797162021400105
|
||||||
15.0,0.14680056444078776,0.1566442653623848,0.08775733805059951,0.17292418580683266,0.1680341158620806
|
7.5,0.0341465635567491,0.03117756291292608,0.015802100105602065,0.03151812973760773,0.03134784632526704
|
||||||
16.0,0.18070258576377174,0.19585451834583373,0.11005152164455634,0.21605933241156736,0.20853051118575192
|
8.0,0.03823142234629086,0.034912841886155954,0.017724337286238952,0.03534046212793969,0.03512665200704765
|
||||||
17.0,0.22130451408346616,0.24447152199498445,0.13787549850403957,0.26946211915160523,0.2579474779472346
|
8.5,0.04279407522246475,0.03908641383789467,0.019879599469816586,0.039623170253689395,0.03935479204579221
|
||||||
18.0,0.26939472678854465,0.3045344507753753,0.17252656142846565,0.3353166538092753,0.31784551311517
|
9.0,0.04788768258092579,0.043747383640535986,0.022295928433737136,0.044420892444668104,0.044084138042602035
|
||||||
19.0,0.3256150019555273,0.3784136758834648,0.21556617256790578,0.41614100494016715,0.38988005918955787
|
9.5,0.053570641143065464,0.04894977525797977,0.02500468735797887,0.049794545359324184,0.049372160308651776
|
||||||
20.0,0.3903482286678335,0.4688105525777229,0.2688526404418522,0.5147756853853035,0.47573343096639775
|
10.0,0.05990693045153535,0.054752877862610065,0.028040940629869258,0.055811993139768964,0.0552824355011896
|
||||||
21.0,0.4635964354662514,0.578728779073748,0.3345666611396269,0.6343391981725063,0.577022932441223
|
10.5,0.0669664377781569,0.061221577467185394,0.03144387359248828,0.06254877459459882,0.06188517603089207
|
||||||
22.0,0.5448699198657065,0.7114072599088519,0.415222874482676,0.7781410805176758,0.6951911159367629
|
11.0,0.0748252465960363,0.06842666099667345,0.03525725553198444,0.07008888995333985,0.0692577754750065
|
||||||
23.0,0.6331155105059729,0.8702063713693562,0.5136586334498267,0.949546269308418,0.8313903238477779
|
11.5,0.08356587028013787,0.07644507639991947,0.03952994922373971,0.07852564771453559,0.07748536205722763
|
||||||
24.0,0.7267127428215634,1.0584449667589202,0.6329899409936198,1.1517917856752415,0.9863786311250137
|
12.0,0.09327740881804818,0.085360128615295,0.04431647029951141,0.08796257073317358,0.08666134967423425
|
||||||
25.0,0.8235572044540542,1.279194773017329,0.7765249721523131,1.3877675181776066,1.160445692544041
|
12.5,0.1040556021156975,0.09526158699989311,0.04967759953004671,0.09851435888929258,0.09688797294459299
|
||||||
26.0,0.9212304756826651,1.535050886559065,0.9476289515595221,1.6597852620892968,1.3533832196252402
|
13.0,0.11600274911459842,0.10624567530369669,0.05568105080659391,0.11030790336846401,0.10827678933608055
|
||||||
27.0,1.0172315400901657,1.8279087143109145,1.1495412900125348,1.9693701773560432,1.5645062768096216
|
13.5,0.12922745762077448,0.11841491058649742,0.06240219710982095,0.12348334468228564,0.12094912763439147
|
||||||
28.0,1.1092250066402953,2.158784275832778,1.385156635171699,2.3171116947925556,1.7927209139328206
|
14.0,0.14384418580218838,0.13187775289817832,0.06992485602776169,0.13819516297913534,0.13503645793865676
|
||||||
29.0,1.1952558858426987,2.5277120709526093,1.656793870330709,2.702603452084613,2.0366245350378795
|
14.5,0.15997253317558566,0.14674802345073423,0.07834213536920213,0.15461328486468107,0.15068065415770782
|
||||||
30.0,1.273891696882788,2.9337415407944656,1.9659871493886203,3.1244848484421452,2.294620748891627
|
15.0,0.17773623713261566,0.16314404591732876,0.08775733805059951,0.17292418580683266,0.1680341158620806
|
||||||
|
15.5,0.19726183132739222,0.18118746406341277,0.09828492364037603,0.19333196120884794,0.18725971263613045
|
||||||
|
16.0,0.2186769253440418,0.2010016899599364,0.11005152164455634,0.21605933241156736,0.20853051118575192
|
||||||
|
16.5,0.24210807182326322,0.2227099414890049,0.12319698872821615,0.24134854631350017,0.23202924390125249
|
||||||
|
17.0,0.26767819847782004,0.2464328367428638,0.13787549850403957,0.26946211915160523,0.2579474779472346
|
||||||
|
17.5,0.29550359887341515,0.27228552723458505,0.15425664820473364,0.3006833665641031,0.286484446899344
|
||||||
|
18.0,0.3256904979371402,0.3003743724210648,0.17252656142846565,0.3353166538092753,0.31784551311517
|
||||||
|
18.5,0.35833123589614085,0.33079318537477825,0.19288896017297896,0.373687292568455,0.35224023897161644
|
||||||
|
19.0,0.3935001471563058,0.36361911343894837,0.21556617256790578,0.41614100494016715,0.38988005918955787
|
||||||
|
19.5,0.4312492471566523,0.39890825744125635,0.24080003515655363,0.46304287205402317,0.4309755647476398
|
||||||
|
20.0,0.47160387826934685,0.4366911765474922,0.2688526404418522,0.5147756853853035,0.47573343096639775
|
||||||
|
20.5,0.5145585022781102,0.47696846992857833,0.3000068719913712,0.5717376246277998,0.5243530472781891
|
||||||
|
21.0,0.5600728580354036,0.5197066667099397,0.3345666611396269,0.6343391981725063,0.577022932441223
|
||||||
|
21.5,0.608068724285634,0.5648346868062688,0.37285689185605564,0.7029994019650798,0.6339170443856742
|
||||||
|
22.0,0.6584275350393116,0.6122411513558497,0.415222874482676,0.7781410805176758,0.6951911159367629
|
||||||
|
22.5,0.7109890845273154,0.6617728169555368,0.46202930580118473,0.8601855102446063,0.7609791636000716
|
||||||
|
23.0,0.765551528064256,0.713234378387138,0.5136586334498267,0.949546269308418,0.8313903238477779
|
||||||
|
23.5,0.8218728332902462,0.7663898279130165,0.5705087483681691,1.0466225079410099,0.9065061679270134
|
||||||
|
24.0,0.8796737646698733,0.8209654765747858,0.6329899409936198,1.1517917856752415,0.9863786311250137
|
||||||
|
24.5,0.9386423967077436,0.8766546390433925,0.7015210764944273,1.265402692864754,1.071028665954073
|
||||||
|
25.0,0.9984400543762295,0.9331238669104754,0.7765249721523131,1.3877675181776066,1.160445692544041
|
||||||
|
25.5,1.0587084809543992,0.9900204972902541,0.8584229962332282,1.5191552559366022,1.2545878766134282
|
||||||
|
26.0,1.119077943176341,1.0469811771611839,0.9476289515595221,1.6597852620892968,1.3533832196252402
|
||||||
|
26.5,1.179175910637804,1.1036409416090471,1.0445423566829937,1.80982186122357,1.4567314014163084
|
||||||
|
27.0,1.2386358989577517,1.1596423762632002,1.1495412900125348,1.9693701773560432,1.5645062768096216
|
||||||
|
27.5,1.29710604997724,1.2146443868700316,1.2629750132730075,2.1384734087219526,1.676558897795992
|
||||||
|
28.0,1.354257039699666,1.268330133073086,1.385156635171699,2.3171116947925556,1.7927209139328206
|
||||||
|
28.5,1.409788954299457,1.3204137546758452,1.516356108640114,2.5052026381166788,1.912808196396262
|
||||||
|
29.0,1.46343685117662,1.3706456179911464,1.656793870330709,2.702603452084613,2.0366245350378795
|
||||||
|
29.5,1.5149748174907736,1.4188159253438317,1.8066354251478791,2.9091146169321833,2.1639652711380073
|
||||||
|
30.0,1.5642184427865493,1.4647566493411088,1.9659871493886203,3.1244848484421452,2.294620748891627
|
||||||
|
30.5,1.611025724734185,1.5083418630206922,2.134893534015794,3.3484171235368767,2.4283794932787846
|
||||||
|
31.0,1.655296518212399,1.5494866278103396,2.3133360179346942,3.580575468601784,2.5650310482060616
|
||||||
|
31.5,1.69697071073413,1.5881446672671957,2.5012334757215813,3.8205922014764093,2.7043684343718026
|
||||||
|
32.0,1.7360253572646107,1.6243050934735594,2.6984443327894785,4.068075325449263,2.8461902094614113
|
||||||
|
32.5,1.7724710336003184,1.657988465829612,2.9047701920540088,4.322615799931558,2.990302132880585
|
||||||
|
33.0,1.8063476712179856,1.6892424524988017,3.1199607780022283,4.58379445293828,3.1365184527185406
|
||||||
|
33.5,1.8377201214872863,1.7181373382163942,3.3437199433889635,4.851188349616376,3.284662843916385
|
||||||
|
34.0,1.8666736682078067,1.7447615844356081,3.5757124449541577,5.124376483511814,3.434569033973711
|
||||||
|
34.5,1.8933096697926761,1.7692176044671448,3.8155711791720877,5.4029447084663,3.5860811564667223
|
||||||
|
35.0,1.917741470965885,1.7916178721312395,4.062904576010332,5.686489875468202,3.7390538737997208
|
||||||
|
35.5,1.940090682653944,1.8120814410975492,4.317303874670602,5.974623178146912,3.8933523096222302
|
||||||
|
36.0,1.96048389087427,1.8307309159245366,4.578350045500127,6.266972741742281,4.048851828833409
|
||||||
|
36.5,1.9790498228022666,1.8476898860934903,4.845620171250711,6.563185513116703,4.205437699605096
|
||||||
|
37.0,1.995916971802156,1.8630808114160524,5.118693153295247,6.862928524245812,4.363004667830932
|
||||||
|
37.5,2.0112116632055823,1.877023330764698,5.397154659675771,7.165889609632854,4.5214564701987765
|
||||||
|
38.0,2.025056528618942,1.8896329553932965,5.68060127841664,7.471777660490731,4.680705307942014
|
||||||
|
38.5,2.0375693477816395,1.901020102220074,5.968643879061808,7.7803224966316336,4.840671299425853
|
||||||
|
39.0,2.048862212555602,1.911289420316504,6.260910216711984,8.09127443203426,5.001281926175381
|
||||||
|
39.5,2.0590409665385074,1.9205393645088147,6.557046835743057,8.404403603108598,5.162471483808707
|
||||||
|
40.0,2.0682048751549056,1.9288619725928229,6.856720345408583,8.71949912064466,5.324180546618741
|
||||||
|
40.5,2.076446484100768,1.936342806471171,7.1596181476676515,9.036368098013284,5.486355452242227
|
||||||
|
|||||||
|
@@ -0,0 +1,3 @@
|
|||||||
|
snr_db,aware_mean,aware_median,blind_mean,blind_median
|
||||||
|
10,0.9795477778116862,0.9844803214073181,0.9812235805193583,0.9864863753318787
|
||||||
|
20,0.86083795551459,0.8848964273929596,0.8715663189888001,0.8971874713897705
|
||||||
|
+14
-8
@@ -1,8 +1,14 @@
|
|||||||
snr_db,edma,oma,genie,sic
|
snr_db,edma,blind,oma,genie,sic
|
||||||
0,0.05294439072634817,0.04744227546406637,0.05379261851424639,0.05389018816321296
|
0.0,0.05578717951430008,0.05400461608078331,0.04721722166286781,0.05396917013451457,0.05426549927797168
|
||||||
5,0.07594817329319892,0.06247051502646607,0.07880139316120491,0.07881668500992306
|
2.5,0.065774643314071,0.06321258225478232,0.052756696401629596,0.06320590722374618,0.06361642193980516
|
||||||
10,0.12217900552930536,0.09554048483563253,0.12869653017833063,0.12780141614005225
|
5.0,0.08065654144156724,0.07687171540223062,0.06147742178989574,0.07694214591756462,0.07748856123536825
|
||||||
15,0.20186260353988977,0.15862477653551696,0.21655865548824185,0.210747933448543
|
7.5,0.10187424055300653,0.09648836613399908,0.07444818876450882,0.09673152786213905,0.09735255000414327
|
||||||
20,0.3172937611389947,0.2656884406371917,0.3525261215672996,0.32788756860888746
|
10.0,0.13085299325641245,0.12340473086107523,0.0929846009076573,0.1241416653757915,0.12454899992793798
|
||||||
25,0.44561602112223075,0.4226203227111401,0.5255728405808201,0.45184034211813306
|
12.5,0.16899134901352228,0.15893537403084337,0.11866934722289443,0.1608496064506471,0.1604155235271901
|
||||||
30,0.5477712579317904,0.6069297656726085,0.6947138682844006,0.542792955511582
|
15.0,0.2173447159398347,0.2041423544753343,0.15335392403416337,0.20866850532591344,0.20602014526724816
|
||||||
|
17.5,0.27592357981950044,0.2591604423709214,0.19881520241498948,0.26905467864125965,0.2615451134555042
|
||||||
|
20.0,0.34281544568017125,0.32233451675623653,0.25661767227575183,0.34233618564903734,0.32547976134344936
|
||||||
|
22.5,0.4138438655436039,0.38978456068784,0.3273876936547458,0.4268909978121519,0.394242920614779
|
||||||
|
25.0,0.4831898649036884,0.45591997236013415,0.4098757527023554,0.5186095271632075,0.462635233476758
|
||||||
|
27.5,0.5450719533115626,0.5151139491051435,0.5004852302744984,0.6114595555514097,0.5252878930792213
|
||||||
|
30.0,0.5955657368898392,0.5634874982386827,0.593484514914453,0.6988957175612449,0.5781986298412085
|
||||||
|
|||||||
|
@@ -1,5 +1,5 @@
|
|||||||
beta,user1_mc_over_theory,user2_mc_over_theory,max_dev_pct
|
beta,user1_mc_over_theory,user2_mc_over_theory,max_dev_pct
|
||||||
0.0,1.0,1.0,0.0
|
0.0,1.0003971986044795,0.9997756167547166,0.03971986044795095
|
||||||
0.311,1.0007005180677906,0.9999999999999998,0.07005180677905898
|
0.311,1.003449173346779,1.0016398632768944,0.34491733467789665
|
||||||
0.5,0.9964527822308402,0.9999999999999998,0.3547217769159783
|
0.5,1.0004382526911781,0.9996516691448926,0.04382526911781426
|
||||||
0.7,0.9981870510670983,1.0,0.18129489329017368
|
0.7,0.9986337430756431,0.9983924640367988,0.16075359632011788
|
||||||
|
|||||||
|
Binary file not shown.
@@ -0,0 +1,66 @@
|
|||||||
|
% Standalone TikZ source for the EDMA block diagram (Fig. 1).
|
||||||
|
% Compile: latexmk -pdf block_diagram_src.tex; copy PDF to block_diagram.pdf
|
||||||
|
\documentclass[tikz,border=2pt]{standalone}
|
||||||
|
\usepackage{amsmath,amssymb,bm}
|
||||||
|
\newcommand{\mb}[1]{\mathbf{#1}}
|
||||||
|
\usetikzlibrary{arrows.meta,positioning,fit,calc}
|
||||||
|
\begin{document}
|
||||||
|
\begin{tikzpicture}[
|
||||||
|
font=\footnotesize,
|
||||||
|
node distance=3.2mm and 4.5mm,
|
||||||
|
blk/.style={draw, semithick, minimum height=5.5mm, minimum width=9mm,
|
||||||
|
inner sep=1.5pt, align=center},
|
||||||
|
sum/.style={draw, semithick, circle, inner sep=0pt, minimum size=3.6mm},
|
||||||
|
arr/.style={-{Latex[length=1.6mm]}, semithick},
|
||||||
|
dsh/.style={-{Latex[length=1.6mm]}, densely dashed, thin},
|
||||||
|
lbl/.style={inner sep=1pt}
|
||||||
|
]
|
||||||
|
% ---------------- user 1 chain ----------------
|
||||||
|
\node[lbl] (b1) {$b_1$};
|
||||||
|
\node[blk, right=of b1] (pe1) {$\mathrm{PE}_1$};
|
||||||
|
\node[blk, right=of pe1] (m1) {$\mb{M}_1$};
|
||||||
|
\node[sum, right=7mm of m1] (h1) {$\times$};
|
||||||
|
\node[lbl, above=1.2mm of h1] {$h_1$};
|
||||||
|
% ---------------- user U chain ----------------
|
||||||
|
\node[lbl, below=11mm of b1] (bU) {$b_U$};
|
||||||
|
\node[blk, right=of bU] (peU) {$\mathrm{PE}_U$};
|
||||||
|
\node[blk, right=of peU] (mU) {$\mb{M}_U$};
|
||||||
|
\node[sum, right=7mm of mU] (hU) {$\times$};
|
||||||
|
\node[lbl, below=1.2mm of hU] {$h_U$};
|
||||||
|
% vdots between chains
|
||||||
|
\path (pe1) -- (peU) node[midway] {$\vdots$};
|
||||||
|
\path (m1) -- (mU) node[midway] {$\vdots$};
|
||||||
|
% ---------------- channel sum ----------------
|
||||||
|
\path (h1) -- (hU) node[midway] (mid) {};
|
||||||
|
\node[sum] (sig) at ($(h1)!0.5!(hU)+(11mm,0)$) {$+$};
|
||||||
|
\node[lbl, left=3.5mm of sig] (nn) {$\mb{n}$};
|
||||||
|
% ---------------- receiver ----------------
|
||||||
|
\node[blk, right=5.5mm of sig, minimum height=13mm] (mf)
|
||||||
|
{matched\\ filters\\ $\mb{M}_u^{\top}/h_u$};
|
||||||
|
\node[blk, right=5mm of mf, minimum height=13mm] (wnr)
|
||||||
|
{affinity-aware\\ MMSE\\ $\mb{W}_u(\mb{B})$};
|
||||||
|
\node[lbl, right=4.5mm of wnr] (out) {$\hat{\mb{e}}_1,\ldots,\hat{\mb{e}}_U$};
|
||||||
|
% ---------------- affinity measurement ----------------
|
||||||
|
\coordinate (tap1) at ($(pe1.east)!0.8!(m1.west)$);
|
||||||
|
\coordinate (tapU) at ($(peU.east)!0.8!(mU.west)$);
|
||||||
|
\node[blk] (bm) at ($(tapU)+(3mm,-9.5mm)$)
|
||||||
|
{$B_{uv}=|\langle\mb{e}_u,\mb{e}_v\rangle|$};
|
||||||
|
% ---------------- edges ----------------
|
||||||
|
\draw[arr] (b1) -- (pe1);
|
||||||
|
\draw[arr] (pe1) -- node[above, lbl] {$\mb{e}_1$} (m1);
|
||||||
|
\draw[arr] (m1) -- node[above, lbl] {$\mb{x}_1$} (h1);
|
||||||
|
\draw[arr] (bU) -- (peU);
|
||||||
|
\draw[arr] (peU) -- node[above, lbl, pos=0.42] {$\mb{e}_U$} (mU);
|
||||||
|
\draw[arr] (mU) -- node[below, lbl] {$\mb{x}_U$} (hU);
|
||||||
|
\draw[arr] (h1) -| (sig);
|
||||||
|
\draw[arr] (hU) -| (sig);
|
||||||
|
\draw[arr] (nn) -- (sig);
|
||||||
|
\draw[arr] (sig) -- node[above, lbl] {$\mb{r}$} (mf);
|
||||||
|
\draw[arr] (mf) -- node[above, lbl] {$\mb{t}_u$} (wnr);
|
||||||
|
\draw[arr] (wnr) -- (out);
|
||||||
|
\fill (tap1) circle (0.5pt);
|
||||||
|
\fill (tapU) circle (0.5pt);
|
||||||
|
\draw[dsh] (tap1) -- ($(tap1 |- bm.north)$);
|
||||||
|
\draw[dsh] (bm.east) -| (wnr.south);
|
||||||
|
\end{tikzpicture}
|
||||||
|
\end{document}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user