Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
916693e5eb | ||
|
|
2aa8ee16ea | ||
|
|
675dada64c | ||
|
|
175a49033c | ||
|
|
551be6fb1c | ||
|
|
7d651c91bb | ||
|
|
25727afb5e | ||
|
|
eb7eb69c8b | ||
|
|
37114b11d0 | ||
|
|
5b51f8b41a |
@@ -8,7 +8,8 @@ Reproducibility package for
|
|||||||
|
|
||||||
This repository contains the simulation code, the raw result data, and
|
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.
|
publicly available during peer review so that the editors and
|
||||||
|
reviewers can inspect and rerun every experiment.
|
||||||
|
|
||||||
The design under test: each user applies an independent Haar
|
The design under test: each user applies an independent Haar
|
||||||
orthogonal mask, and the receiver runs a matched filter followed by
|
orthogonal mask, and the receiver runs a matched filter followed by
|
||||||
@@ -47,9 +48,10 @@ Run the scripts from inside `code/`. All plots are rendered from
|
|||||||
| Fig. 2 | Per-user MSE, aware vs blind floor | `revision_sims.py E1` | `floor_validation.csv` |
|
| 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` | `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 | Receiver comparison under Rayleigh fading | `revision_sims_gpu.py E2` | `sic_comparison.csv` |
|
| Fig. 5 | Top-1 retrieval with recovered embeddings | `retrieval_real.py` | `retrieval_real.csv` |
|
||||||
| Fig. 6 | Value of the measured affinity | `revision_sims.py E7a` | `beta_sweep_corrected.csv` |
|
| Fig. 6 | Receiver comparison under Rayleigh fading | `revision_sims_gpu.py E2` | `sic_comparison.csv` |
|
||||||
| Fig. 7 | Multi-user scaling (joint Wiener) | `revision_sims_gpu.py E7c` | `multiuser_corrected.csv` |
|
| Fig. 7 | Value of the measured affinity | `revision_sims.py E7a` | `beta_sweep_corrected.csv` |
|
||||||
|
| Fig. 8 | Multi-user scaling (joint Wiener) | `revision_sims_gpu.py E7c` | `multiuser_corrected.csv` |
|
||||||
|
|
||||||
Quantities quoted in the text but not plotted come from the same
|
Quantities quoted in the text but not plotted come from the same
|
||||||
drivers: `revision_sims.py E0` writes `theorem_check.csv` (Theorem 1
|
drivers: `revision_sims.py E0` writes `theorem_check.csv` (Theorem 1
|
||||||
@@ -59,7 +61,11 @@ Rayleigh MSE), `E4` writes `csi_error.csv` (imperfect-CSI
|
|||||||
robustness), `E5` writes `mask_family_rev.csv` (Walsh–Hadamard versus
|
robustness), `E5` writes `mask_family_rev.csv` (Walsh–Hadamard versus
|
||||||
Haar), `E8` writes `mismatch.csv` (affinity mismatch and
|
Haar), `E8` writes `mismatch.csv` (affinity mismatch and
|
||||||
quantization), and `E9` writes `cosine_ceiling.csv` (cosine-ceiling
|
quantization), and `E9` writes `cosine_ceiling.csv` (cosine-ceiling
|
||||||
corollary check).
|
corollary check). The empirical affinity statistics quoted in the
|
||||||
|
manuscript are recomputable from `clip_realdata_beta.csv` and
|
||||||
|
`bert_vit_beta.csv` (32 paired and 32 unpaired samples per encoder
|
||||||
|
family), and the trained refinement gates behind the capacity-check
|
||||||
|
claim are stored in `refine_gates.npz`.
|
||||||
|
|
||||||
## Verifying the analysis
|
## Verifying the analysis
|
||||||
|
|
||||||
@@ -85,5 +91,6 @@ drawn fresh on every realization.
|
|||||||
|
|
||||||
## Citation and license
|
## Citation and license
|
||||||
|
|
||||||
Citation details and a license will be added when the paper is
|
Until the paper is published, cite the submitted manuscript listed
|
||||||
published.
|
at the top of this file. A formal citation entry and a license
|
||||||
|
will be added upon publication.
|
||||||
|
|||||||
@@ -127,7 +127,14 @@ def train_refiners(epochs=220, steps=20, batch=48, lr=5e-4,
|
|||||||
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_single, [p.detach() for p in params]
|
P4 = [p.detach() for p in params]
|
||||||
|
rel = float((P_single - sum(P4) / 4).norm() / P_single.norm())
|
||||||
|
print(f" [diag] ||P1 - mean(P4)|| / ||P1|| = {rel:.3e}")
|
||||||
|
np.savez(DATA / "refine_gates.npz",
|
||||||
|
P1=P_single.cpu().numpy(),
|
||||||
|
**{f"P4_{i}": p.cpu().numpy() for i, p in enumerate(P4)})
|
||||||
|
print(" [diag] gates saved to data/refine_gates.npz")
|
||||||
|
return P_single, P4
|
||||||
|
|
||||||
|
|
||||||
def refine_apply(ps, z):
|
def refine_apply(ps, z):
|
||||||
|
|||||||
+51
-14
@@ -36,7 +36,7 @@ LBL = {
|
|||||||
"todma": "ToDMA-adapted",
|
"todma": "ToDMA-adapted",
|
||||||
"mac": "MAC sum capacity",
|
"mac": "MAC sum capacity",
|
||||||
"coop": "Full-cooperation bound",
|
"coop": "Full-cooperation bound",
|
||||||
"hybrid": "EDMA + refinement stage",
|
"hybrid": "EDMA + refinement",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -57,6 +57,7 @@ def save(fig, name):
|
|||||||
|
|
||||||
# ------------------------------------------------------ fig_floor
|
# ------------------------------------------------------ fig_floor
|
||||||
def fig_floor():
|
def fig_floor():
|
||||||
|
from matplotlib.lines import Line2D
|
||||||
rows = rows_of("floor_validation")
|
rows = rows_of("floor_validation")
|
||||||
fig, ax = plt.subplots()
|
fig, ax = plt.subplots()
|
||||||
colors = {"256": "C0", "768": "C3"}
|
colors = {"256": "C0", "768": "C3"}
|
||||||
@@ -66,12 +67,10 @@ def fig_floor():
|
|||||||
or float(r["d"]) == float(d)]
|
or float(r["d"]) == float(d)]
|
||||||
snr = col(rd, "snr_db")
|
snr = col(rd, "snr_db")
|
||||||
ax.plot(snr, col(rd, "mse_mc"), "o", ms=3.5, color=colors[d],
|
ax.plot(snr, col(rd, "mse_mc"), "o", ms=3.5, color=colors[d],
|
||||||
mfc="none", label=rf"Monte Carlo, $d={d}$")
|
mfc="none")
|
||||||
ax.plot(snr, col(rd, "mse_theory"), "-", color=colors[d],
|
ax.plot(snr, col(rd, "mse_theory"), "-", color=colors[d])
|
||||||
label=rf"Theorem 1, $d={d}$")
|
|
||||||
if d == "768":
|
if d == "768":
|
||||||
ax.plot(snr, col(rd, "mse_blind"), "--", color="C1", lw=1.2,
|
ax.plot(snr, col(rd, "mse_blind"), "--", color="C1", lw=1.2)
|
||||||
label=LBL["blind"])
|
|
||||||
g = 1.0 - beta**2
|
g = 1.0 - beta**2
|
||||||
ax.axhline(math.sqrt(g) / 2, color="gray", lw=0.8, ls="--")
|
ax.axhline(math.sqrt(g) / 2, color="gray", lw=0.8, ls="--")
|
||||||
ax.axhline(0.5, color="gray", lw=0.8, ls=":")
|
ax.axhline(0.5, color="gray", lw=0.8, ls=":")
|
||||||
@@ -79,10 +78,20 @@ def fig_floor():
|
|||||||
color="gray")
|
color="gray")
|
||||||
ax.annotate(r"aware floor $\sqrt{1-\beta^2}/2$", xy=(14.0, 0.432),
|
ax.annotate(r"aware floor $\sqrt{1-\beta^2}/2$", xy=(14.0, 0.432),
|
||||||
fontsize=7, color="gray")
|
fontsize=7, color="gray")
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
ax.set_xlabel("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.4, 1.05)
|
ax.set_xlim(0, 40); ax.set_ylim(0.4, 1.05)
|
||||||
ax.legend(loc="lower left", bbox_to_anchor=(0.02, 0.18))
|
# framed in-axes legend like every other result figure; composite
|
||||||
|
# handles (marker = Monte Carlo, line = Theorem 1; the convention
|
||||||
|
# is stated in the caption) keep it to three entries
|
||||||
|
handles = [
|
||||||
|
Line2D([], [], color="C0", marker="o", mfc="none", ms=3.5,
|
||||||
|
ls="-", label=rf"{LBL['edma']}, $d=256$"),
|
||||||
|
Line2D([], [], color="C3", marker="o", mfc="none", ms=3.5,
|
||||||
|
ls="-", label=rf"{LBL['edma']}, $d=768$"),
|
||||||
|
Line2D([], [], color="C1", ls="--", lw=1.2, label=LBL["blind"]),
|
||||||
|
]
|
||||||
|
ax.legend(handles=handles, loc="upper right")
|
||||||
save(fig, "fig_floor")
|
save(fig, "fig_floor")
|
||||||
|
|
||||||
|
|
||||||
@@ -97,7 +106,7 @@ def fig_rate():
|
|||||||
ax.plot(snr, col(rows, "oma"), "--", color="C1", label=LBL["oma"])
|
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, "genie"), "-.", color="C0", label=LBL["genie"])
|
||||||
ax.plot(snr, col(rows, "mac"), "-", color="k", lw=1.0, label=LBL["mac"])
|
ax.plot(snr, col(rows, "mac"), "-", color="k", lw=1.0, label=LBL["mac"])
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
ax.set_xlabel("SNR $\\rho$ [dB]")
|
||||||
ax.set_ylabel("Effective sum rate [bps/Hz]")
|
ax.set_ylabel("Effective sum rate [bps/Hz]")
|
||||||
ax.set_xlim(0, 40); 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")
|
||||||
@@ -121,10 +130,10 @@ def fig_beta_sweep():
|
|||||||
ax.plot([], [], ls="--", color="gray", label=LBL["oma"])
|
ax.plot([], [], ls="--", color="gray", label=LBL["oma"])
|
||||||
ax.plot([], [], ls="-.", color="gray", label=LBL["genie"])
|
ax.plot([], [], ls="-.", color="gray", label=LBL["genie"])
|
||||||
for b0 in (0.030, 0.311):
|
for b0 in (0.030, 0.311):
|
||||||
ax.axvline(b0, color="gray", ls=":", lw=0.9)
|
ax.axvline(b0, ymax=0.54, 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.0)
|
ax.set_xlim(0, 1); ax.set_ylim(0, 1.05)
|
||||||
ax.legend(loc="upper left")
|
ax.legend(loc="upper left")
|
||||||
save(fig, "fig_beta_sweep_corrected")
|
save(fig, "fig_beta_sweep_corrected")
|
||||||
|
|
||||||
@@ -140,7 +149,7 @@ def fig_sic():
|
|||||||
ax.plot(snr, col(rows, "oma"), "v--", color="C1", label=LBL["oma"])
|
ax.plot(snr, col(rows, "oma"), "v--", color="C1", label=LBL["oma"])
|
||||||
ax.plot(snr, col(rows, "genie"), "-", color="gray", lw=1.0,
|
ax.plot(snr, col(rows, "genie"), "-", color="gray", lw=1.0,
|
||||||
label=LBL["genie"])
|
label=LBL["genie"])
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
ax.set_xlabel("SNR $\\rho$ [dB]")
|
||||||
ax.set_ylabel("Mean cosine similarity")
|
ax.set_ylabel("Mean cosine similarity")
|
||||||
ax.set_xlim(snr[0], snr[-1]); ax.set_ylim(0, 0.7)
|
ax.set_xlim(snr[0], snr[-1]); ax.set_ylim(0, 0.7)
|
||||||
ax.legend(loc="upper left")
|
ax.legend(loc="upper left")
|
||||||
@@ -162,18 +171,46 @@ def fig_multiuser():
|
|||||||
mk = [i for i, s in enumerate(snr) if s % 5 == 0]
|
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],
|
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")
|
"o", color=colors[U], ms=4, mfc="none")
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
ax.set_xlabel("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_xlim(0, 30)
|
||||||
|
ax.set_ylim(bottom=0)
|
||||||
ax.legend(loc="upper left")
|
ax.legend(loc="upper left")
|
||||||
save(fig, "fig_multiuser_corrected")
|
save(fig, "fig_multiuser_corrected")
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------ fig_retrieval
|
||||||
|
def fig_retrieval():
|
||||||
|
rows = rows_of("retrieval_real")
|
||||||
|
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, "hybrid"), "^-", color="C2",
|
||||||
|
label=LBL["hybrid"])
|
||||||
|
ax.plot(snr, col(rows, "todma"), "d-.", color="C4",
|
||||||
|
label=LBL["todma"])
|
||||||
|
ax.plot(snr, col(rows, "oma"), "v:", color="C1", label=LBL["oma"])
|
||||||
|
# genie curve overlaps EDMA here; named in the caption, not the legend
|
||||||
|
ax.plot(snr, col(rows, "genie"), "-", color="gray", lw=1.0,
|
||||||
|
label="_nolegend_")
|
||||||
|
ax.axhline(1.0 / 16, xmax=0.48, color="gray", ls=":", lw=0.8)
|
||||||
|
ax.annotate("chance $1/16$", xy=(1.2, 1.0 / 16 + 0.015), fontsize=7,
|
||||||
|
color="gray")
|
||||||
|
ax.set_xlabel("SNR $\\rho$ [dB]")
|
||||||
|
ax.set_ylabel("Top-1 retrieval accuracy")
|
||||||
|
ax.set_xlim(snr[0], snr[-1]); ax.set_ylim(0, 1.0)
|
||||||
|
ax.legend(loc="lower right", borderaxespad=0.3,
|
||||||
|
handlelength=1.4, handletextpad=0.5,
|
||||||
|
labelspacing=0.35)
|
||||||
|
save(fig, "fig_retrieval")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
todo = set(sys.argv[1:])
|
todo = set(sys.argv[1:])
|
||||||
ALL = {"floor": fig_floor, "rate": fig_rate, "beta": fig_beta_sweep,
|
ALL = {"floor": fig_floor, "rate": fig_rate, "beta": fig_beta_sweep,
|
||||||
"sic": fig_sic, "multi": fig_multiuser}
|
"sic": fig_sic, "multi": fig_multiuser,
|
||||||
|
"retr": fig_retrieval}
|
||||||
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()
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from pathlib import Path
|
|||||||
import matplotlib
|
import matplotlib
|
||||||
matplotlib.use("Agg")
|
matplotlib.use("Agg")
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
from replot_all import LBL
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
plt.rcParams.update({
|
plt.rcParams.update({
|
||||||
@@ -25,17 +26,17 @@ 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")
|
ax.plot(snr, col("edma"), "o-", color="C3", label=LBL["edma"])
|
||||||
ax.plot(snr, col("edma_ref"), "^-", color="C2",
|
ax.plot(snr, col("edma_ref"), "^-", color="C2",
|
||||||
label="EDMA + refinement stage")
|
label=LBL["hybrid"])
|
||||||
ax.plot(snr, col("todma"), "d-.", color="C4", label="ToDMA-adapted")
|
ax.plot(snr, col("todma"), "d-.", color="C4", label=LBL["todma"])
|
||||||
ax.plot(snr, col("oma"), "v:", color="C1", label="OMA")
|
ax.plot(snr, col("oma"), "v:", color="C1", label=LBL["oma"])
|
||||||
ax.plot(snr, col("genie"), "-", color="gray", lw=1.0,
|
ax.plot(snr, col("genie"), "-", color="gray", lw=1.0,
|
||||||
label="Genie-aided SIC bound")
|
label=LBL["genie"])
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
ax.set_xlabel("SNR $\\rho$ [dB]")
|
||||||
ax.set_ylabel("Mean cosine similarity")
|
ax.set_ylabel("Mean cosine similarity")
|
||||||
ax.set_xlim(snr[0], snr[-1])
|
ax.set_xlim(snr[0], snr[-1])
|
||||||
ax.set_ylim(0, 0.85)
|
ax.set_ylim(0, 0.75)
|
||||||
ax.legend(loc="upper left")
|
ax.legend(loc="upper left")
|
||||||
fig.subplots_adjust(**AXES_RECT)
|
fig.subplots_adjust(**AXES_RECT)
|
||||||
fig.savefig(ROOT / "fig" / "fig_bertvit_merged.pdf")
|
fig.savefig(ROOT / "fig" / "fig_bertvit_merged.pdf")
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
"""
|
||||||
|
Task-level validation: nearest-neighbor retrieval with recovered
|
||||||
|
embeddings on the real BERT/ViT pairs.
|
||||||
|
===================================================================
|
||||||
|
For every recovered embedding, rank the 16 clean database embeddings
|
||||||
|
of the SAME modality by absolute cosine and score top-1 retrieval of
|
||||||
|
the transmitted item (chance level 1/16). This measures whether the
|
||||||
|
recovery preserves semantic identity, the operational question behind
|
||||||
|
the cosine metric of the manuscript.
|
||||||
|
|
||||||
|
Schemes: EDMA (aware Wiener), hybrid (EDMA + stored refinement gate
|
||||||
|
from data/refine_gates.npz), OMA (equivalent-bandwidth model),
|
||||||
|
genie-aided SIC bound, ToDMA-adapted (first 40 fading draws).
|
||||||
|
|
||||||
|
Same channel, energy, and seed conventions as fig_real_merged.py.
|
||||||
|
Writes data/retrieval_real.csv. Run under WSL (torch, CUDA).
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
import csv
|
||||||
|
import math
|
||||||
|
import time
|
||||||
|
import numpy as np
|
||||||
|
import torch
|
||||||
|
|
||||||
|
from fig_real_merged import (load_pairs, haar_t, aware_batch, todma_prepare,
|
||||||
|
omp_code, todma_run, SNRS, NFADE, NFADE_TOD,
|
||||||
|
D, DATA, DEV, SEED)
|
||||||
|
|
||||||
|
torch.manual_seed(SEED)
|
||||||
|
rng = np.random.default_rng(SEED)
|
||||||
|
|
||||||
|
|
||||||
|
def refine_apply_single(P1, z):
|
||||||
|
"""z: (b, D) real torch tensor; P1: (D, D) gate."""
|
||||||
|
return D * torch.softmax((z @ P1.T) / math.sqrt(D), dim=1) * z
|
||||||
|
|
||||||
|
|
||||||
|
def top1(rec, db, idx):
|
||||||
|
"""rec: (b, D) cfloat; db: (n, D) float; returns (b,) 0/1 hits."""
|
||||||
|
sims = (rec @ db.T.to(rec.dtype).conj()).abs() # (b, n)
|
||||||
|
sims = sims / (rec.norm(dim=1, keepdim=True)
|
||||||
|
* db.norm(dim=1).unsqueeze(0))
|
||||||
|
return (sims.argmax(dim=1) == idx).float().cpu().numpy()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
A, B, betas = load_pairs()
|
||||||
|
npairs = len(A)
|
||||||
|
gates = np.load(DATA / "refine_gates.npz")
|
||||||
|
P1 = torch.tensor(gates["P1"], dtype=torch.float32, device=DEV)
|
||||||
|
tod = todma_prepare()
|
||||||
|
codes = [(omp_code(tod[0], A[i], tod[3]),
|
||||||
|
omp_code(tod[0], B[i], tod[3])) for i in range(npairs)]
|
||||||
|
At = torch.tensor(A, dtype=torch.float32, device=DEV)
|
||||||
|
Bt = torch.tensor(B, dtype=torch.float32, device=DEV)
|
||||||
|
gen = torch.Generator(device=DEV).manual_seed(SEED)
|
||||||
|
nb = len(SNRS)
|
||||||
|
sigs = torch.tensor(10 ** (-SNRS / 20.0), dtype=torch.float32,
|
||||||
|
device=DEV)
|
||||||
|
keys = ("edma", "hybrid", "oma", "genie", "todma")
|
||||||
|
acc = {k: np.zeros(nb) for k in keys}
|
||||||
|
cnt = {k: np.zeros(nb) for k in keys}
|
||||||
|
t0 = time.time()
|
||||||
|
for i in range(npairs):
|
||||||
|
bi = float(betas[i])
|
||||||
|
e1, e2 = At[i], Bt[i]
|
||||||
|
c1c, c2c = codes[i]
|
||||||
|
for f in range(NFADE):
|
||||||
|
M = haar_t(2, gen)
|
||||||
|
M1, M2 = M[0], M[1]
|
||||||
|
Q = M1.T @ M2
|
||||||
|
h = (torch.randn(2, generator=gen, device=DEV)
|
||||||
|
+ 1j * torch.randn(2, generator=gen, device=DEV)) \
|
||||||
|
/ math.sqrt(2)
|
||||||
|
n = (torch.randn(D, generator=gen, device=DEV)
|
||||||
|
+ 1j * torch.randn(D, generator=gen, device=DEV)) \
|
||||||
|
/ math.sqrt(2)
|
||||||
|
n2 = (torch.randn(D, generator=gen, device=DEV)
|
||||||
|
+ 1j * torch.randn(D, generator=gen, device=DEV)) \
|
||||||
|
/ math.sqrt(2)
|
||||||
|
r0 = h[0] * (M1 @ e1).to(torch.cfloat) \
|
||||||
|
+ h[1] * (M2 @ e2).to(torch.cfloat)
|
||||||
|
r = r0.unsqueeze(0) + sigs.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**2 / h[0].abs()**2
|
||||||
|
v2 = sigs**2 / h[1].abs()**2
|
||||||
|
g1 = aware_batch(t1, Q, bi, c1, v1)
|
||||||
|
g2 = aware_batch(t2, Q.T, bi, c2, v2)
|
||||||
|
acc["edma"] += 0.5 * (top1(g1, At, i) + top1(g2, Bt, i))
|
||||||
|
hy1 = refine_apply_single(P1, g1.real.float()).to(torch.cfloat)
|
||||||
|
hy2 = refine_apply_single(P1, g2.real.float()).to(torch.cfloat)
|
||||||
|
acc["hybrid"] += 0.5 * (top1(hy1, At, i) + top1(hy2, Bt, i))
|
||||||
|
o1 = e1.to(torch.cfloat).unsqueeze(0) \
|
||||||
|
+ math.sqrt(2) * sigs.view(-1, 1) * n.unsqueeze(0) / h[0]
|
||||||
|
o2 = e2.to(torch.cfloat).unsqueeze(0) \
|
||||||
|
+ math.sqrt(2) * sigs.view(-1, 1) * n2.unsqueeze(0) / h[1]
|
||||||
|
acc["oma"] += 0.5 * (top1(o1, At, i) + top1(o2, Bt, i))
|
||||||
|
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]
|
||||||
|
acc["genie"] += 0.5 * (top1(ge1, At, i) + top1(ge2, Bt, i))
|
||||||
|
for kk in ("edma", "hybrid", "oma", "genie"):
|
||||||
|
cnt[kk] += 1
|
||||||
|
if f < NFADE_TOD:
|
||||||
|
hnp = (complex(h[0].item()), complex(h[1].item()))
|
||||||
|
nslots = [(rng.standard_normal(tod[4])
|
||||||
|
+ 1j * rng.standard_normal(tod[4]))
|
||||||
|
/ math.sqrt(2) for _ in range(tod[3])]
|
||||||
|
for k, s in enumerate(SNRS):
|
||||||
|
sig = 10 ** (-s / 20.0)
|
||||||
|
recs = todma_run(tod, (c1c, c2c), hnp, sig, nslots)
|
||||||
|
hit = 0.0
|
||||||
|
for j, (rec, db, ii) in enumerate(
|
||||||
|
((recs[0], A, i), (recs[1], B, i))):
|
||||||
|
if rec is None:
|
||||||
|
continue # failed detection: no hit
|
||||||
|
sims = np.abs(db @ rec) / (
|
||||||
|
np.linalg.norm(db, axis=1)
|
||||||
|
* np.linalg.norm(rec))
|
||||||
|
hit += 0.5 * float(int(np.argmax(sims)) == ii)
|
||||||
|
acc["todma"][k] += hit
|
||||||
|
cnt["todma"][k] += 1
|
||||||
|
print(f" pair {i+1}/{npairs} done ({time.time()-t0:.0f}s)",
|
||||||
|
flush=True)
|
||||||
|
for k in keys:
|
||||||
|
acc[k] /= np.maximum(cnt[k], 1)
|
||||||
|
|
||||||
|
with open(DATA / "retrieval_real.csv", "w", newline="") as f:
|
||||||
|
w = csv.writer(f)
|
||||||
|
w.writerow(["snr_db"] + list(keys))
|
||||||
|
for k, s in enumerate(SNRS):
|
||||||
|
w.writerow([s] + [acc[key][k] for key in keys])
|
||||||
|
print(f"[OK] wrote {DATA/'retrieval_real.csv'}")
|
||||||
|
for k, s in enumerate(SNRS):
|
||||||
|
print(f" {s:4.1f} dB EDMA {acc['edma'][k]:.3f} "
|
||||||
|
f"hybrid {acc['hybrid'][k]:.3f} ToDMA {acc['todma'][k]:.3f} "
|
||||||
|
f" OMA {acc['oma'][k]:.3f} genie {acc['genie'][k]:.3f}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -246,7 +246,7 @@ def E1_floor(beta=0.311, dims=(256, 768), snr_db=np.arange(0, 41, 2.5), ntr=120)
|
|||||||
ax.text(22.0, 0.40, r"aware floor $\sqrt{1-\beta^2}/2$",
|
ax.text(22.0, 0.40, r"aware floor $\sqrt{1-\beta^2}/2$",
|
||||||
fontsize=7, color="gray")
|
fontsize=7, color="gray")
|
||||||
ax.set_yscale("linear")
|
ax.set_yscale("linear")
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
ax.set_xlabel("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.4, 1.05)
|
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)
|
||||||
@@ -284,7 +284,7 @@ def E7_rates(beta=0.311, d=512):
|
|||||||
ax.plot(snr_db, To, "--", color="C1", label=LBL["oma"])
|
ax.plot(snr_db, To, "--", color="C1", label=LBL["oma"])
|
||||||
ax.plot(snr_db, Tg, "-.", color="C0", label=LBL["genie"])
|
ax.plot(snr_db, Tg, "-.", color="C0", label=LBL["genie"])
|
||||||
ax.plot(snr_db, Cm, "-", color="k", lw=1.0, label=LBL["mac"])
|
ax.plot(snr_db, Cm, "-", color="k", lw=1.0, label=LBL["mac"])
|
||||||
ax.set_xlabel("Per-block SNR $\\rho$ [dB]")
|
ax.set_xlabel("SNR $\\rho$ [dB]")
|
||||||
ax.set_ylabel("Effective sum rate [bps/Hz]")
|
ax.set_ylabel("Effective sum rate [bps/Hz]")
|
||||||
ax.set_xlim(0, 40); 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")
|
||||||
|
|||||||
@@ -405,11 +405,76 @@ def E9_ceiling(d=512, snr=60.0, ntr=200):
|
|||||||
'blind_mc', 'blind_pred'], rows)
|
'blind_mc', 'blind_pred'], rows)
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
def E10_whpad(beta=0.311, d=768, dpad=1024, ntr=200):
|
||||||
|
"""Zero-padded WH at d=768 (padded to 1024) vs dense Haar at 768.
|
||||||
|
|
||||||
|
The embedding (768) is zero-padded to 1024, masked by H_1024 D_u,
|
||||||
|
and the exact per-coordinate Wiener uses the true prior (signal
|
||||||
|
variance 1/768 on the active support, zero on the padding, so the
|
||||||
|
padded coordinates are discarded). Reference: Haar masks at the
|
||||||
|
native d=768 with the standard aware demultiplexer. Same per-block
|
||||||
|
energy E_b = 1 and the same noise PSD; the padded block occupies
|
||||||
|
dpad channel uses, a bandwidth cost of dpad/d."""
|
||||||
|
print(chr(10) + '=== E10: zero-padded WH (768->1024) vs native Haar 768 ===')
|
||||||
|
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] < dpad:
|
||||||
|
H = np.block([[H, H], [H, -H]])
|
||||||
|
Ht = torch.tensor(H / math.sqrt(dpad), dtype=torch.float32, device=DEV)
|
||||||
|
g = 1.0 - beta**2
|
||||||
|
res = {'haar': np.zeros(nb), 'whpad': np.zeros(nb)}
|
||||||
|
for _ in range(ntr):
|
||||||
|
e1, e2 = embed_pair(d, beta)
|
||||||
|
# ---- native Haar at 768 ----
|
||||||
|
M1, M2 = haar_g(d), haar_g(d)
|
||||||
|
Q = M1.T @ M2
|
||||||
|
n = cnoise_g(d)
|
||||||
|
r = (M1 @ e1 + M2 @ e2).to(torch.complex64).unsqueeze(0) \
|
||||||
|
+ sigs.view(-1, 1) * n.unsqueeze(0)
|
||||||
|
t1 = (M1.T.to(torch.complex64) @ r.unsqueeze(-1)).squeeze(-1)
|
||||||
|
g1 = aware_g(t1, Q, beta, 1.0, sigs**2)
|
||||||
|
res['haar'] += abscos(g1, e1)
|
||||||
|
# ---- zero-padded WH at 1024 ----
|
||||||
|
z = torch.zeros(dpad - d, device=DEV)
|
||||||
|
e1p = torch.cat([e1, z]); e2p = torch.cat([e2, z])
|
||||||
|
D1 = torch.tensor(np.sign(rng.standard_normal(dpad)),
|
||||||
|
dtype=torch.float32, device=DEV)
|
||||||
|
D2 = torch.tensor(np.sign(rng.standard_normal(dpad)),
|
||||||
|
dtype=torch.float32, device=DEV)
|
||||||
|
W1, W2 = Ht * D1.unsqueeze(0), Ht * D2.unsqueeze(0)
|
||||||
|
npad = cnoise_g(dpad)
|
||||||
|
rp = (W1 @ e1p + W2 @ e2p).to(torch.complex64).unsqueeze(0) \
|
||||||
|
+ sigs.view(-1, 1) * npad.unsqueeze(0)
|
||||||
|
tw = (W1.T.to(torch.complex64) @ rp.unsqueeze(-1)).squeeze(-1)
|
||||||
|
q = (D1 * D2)[:d] # active coordinates only
|
||||||
|
a = 1.0 + beta * q # (d,)
|
||||||
|
s_var = 1.0 / d # true signal variance
|
||||||
|
v = g / d + (sigs**2).view(-1, 1) # interference + noise
|
||||||
|
gains = (s_var * a.unsqueeze(0)) / (a.unsqueeze(0)**2 * s_var + v)
|
||||||
|
w1 = gains.to(torch.complex64) * tw[:, :d]
|
||||||
|
res['whpad'] += abscos(w1, e1)
|
||||||
|
for k in res:
|
||||||
|
res[k] /= ntr
|
||||||
|
rows = [[s, res['haar'][i], res['whpad'][i]]
|
||||||
|
for i, s in enumerate(snr_db)]
|
||||||
|
write_csv('wh_padding', ['snr_db', 'haar768', 'whpad1024'], rows)
|
||||||
|
dev = res['haar'] - res['whpad']
|
||||||
|
print(f' cosine delta (haar - whpad): max {dev.max():.4f}, '
|
||||||
|
f'at 20 dB {dev[list(snr_db).index(20)]:.4f}, '
|
||||||
|
f'at 40 dB {dev[-1]:.4f}')
|
||||||
|
print(f' bandwidth cost: {dpad}/{d} = {dpad/d:.3f}x uses '
|
||||||
|
f'(per-use rate factor {d/dpad:.3f})')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
todo = set(sys.argv[1:])
|
todo = set(sys.argv[1:])
|
||||||
ALL = {"E2": E2_sic, "E3": E3_unconditional, "E4": E4_csi,
|
ALL = {"E2": E2_sic, "E3": E3_unconditional, "E4": E4_csi,
|
||||||
"E5": E5_maskfam, "E7c": E7_multiuser, "E8": E8_mismatch,
|
"E5": E5_maskfam, "E7c": E7_multiuser, "E8": E8_mismatch,
|
||||||
"E9": E9_ceiling}
|
"E9": E9_ceiling, "E10": E10_whpad}
|
||||||
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()
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
scheme,beta
|
||||||
|
paired,0.027237803175426414
|
||||||
|
paired,0.012896661680831107
|
||||||
|
paired,0.010416352482946263
|
||||||
|
paired,0.048123426570364544
|
||||||
|
paired,0.02378884879050521
|
||||||
|
paired,0.08129956173740625
|
||||||
|
paired,0.019008848452584104
|
||||||
|
paired,0.008772706088568172
|
||||||
|
paired,0.005386448106588374
|
||||||
|
paired,0.04672583614390642
|
||||||
|
paired,0.02654219206213419
|
||||||
|
paired,0.008971354550608865
|
||||||
|
paired,0.006527803719580855
|
||||||
|
paired,0.0003781749165654546
|
||||||
|
paired,0.040345337710264106
|
||||||
|
paired,0.06631996053522116
|
||||||
|
paired,0.023303015182582845
|
||||||
|
paired,0.0036342242085544724
|
||||||
|
paired,0.01080984433510444
|
||||||
|
paired,0.05122711771786337
|
||||||
|
paired,0.02196780882017706
|
||||||
|
paired,0.027430766747928603
|
||||||
|
paired,0.05481789805580116
|
||||||
|
paired,0.09104140849083153
|
||||||
|
paired,0.01815058092411296
|
||||||
|
paired,0.03022733891851148
|
||||||
|
paired,0.007488021664737729
|
||||||
|
paired,0.0023511041567845174
|
||||||
|
paired,0.09862665895072077
|
||||||
|
paired,0.048736810747693156
|
||||||
|
paired,0.011754320764163387
|
||||||
|
paired,0.036121899180464434
|
||||||
|
unpaired,0.019374828604252024
|
||||||
|
unpaired,0.032440294233851884
|
||||||
|
unpaired,0.02378860498148811
|
||||||
|
unpaired,0.008587382855481418
|
||||||
|
unpaired,0.05651731568397114
|
||||||
|
unpaired,0.02403075688014663
|
||||||
|
unpaired,0.03458268967264902
|
||||||
|
unpaired,0.03784547767683299
|
||||||
|
unpaired,0.0027191357506518334
|
||||||
|
unpaired,0.06647789537369261
|
||||||
|
unpaired,0.028248259683892177
|
||||||
|
unpaired,0.02975719499694031
|
||||||
|
unpaired,0.002693260517757482
|
||||||
|
unpaired,0.00956545888624823
|
||||||
|
unpaired,0.018776037962855974
|
||||||
|
unpaired,0.01723862993724272
|
||||||
|
unpaired,0.003321530987236865
|
||||||
|
unpaired,0.026794936423899428
|
||||||
|
unpaired,0.005555610068283409
|
||||||
|
unpaired,0.02096161483617256
|
||||||
|
unpaired,0.029145082852780703
|
||||||
|
unpaired,0.008083174012553023
|
||||||
|
unpaired,0.009863492000612803
|
||||||
|
unpaired,0.016990287948247137
|
||||||
|
unpaired,0.009933587496519476
|
||||||
|
unpaired,0.06247402736383933
|
||||||
|
unpaired,0.020214432381559597
|
||||||
|
unpaired,0.06931381025435437
|
||||||
|
unpaired,0.02564802276256673
|
||||||
|
unpaired,0.04367255778838598
|
||||||
|
unpaired,0.01957917212315197
|
||||||
|
unpaired,0.06779897449994185
|
||||||
|
@@ -0,0 +1,65 @@
|
|||||||
|
scheme,beta
|
||||||
|
paired,0.2875853478908539
|
||||||
|
paired,0.33386528491973877
|
||||||
|
paired,0.3495585322380066
|
||||||
|
paired,0.2988513112068176
|
||||||
|
paired,0.3365963399410248
|
||||||
|
paired,0.28957056999206543
|
||||||
|
paired,0.3398767411708832
|
||||||
|
paired,0.2994540333747864
|
||||||
|
paired,0.3134581446647644
|
||||||
|
paired,0.2800610363483429
|
||||||
|
paired,0.33044949173927307
|
||||||
|
paired,0.3525742292404175
|
||||||
|
paired,0.28622955083847046
|
||||||
|
paired,0.3221920132637024
|
||||||
|
paired,0.34046676754951477
|
||||||
|
paired,0.3445603847503662
|
||||||
|
paired,0.3361469507217407
|
||||||
|
paired,0.315978467464447
|
||||||
|
paired,0.2871871590614319
|
||||||
|
paired,0.20464202761650085
|
||||||
|
paired,0.33651721477508545
|
||||||
|
paired,0.28726524114608765
|
||||||
|
paired,0.26744377613067627
|
||||||
|
paired,0.2686237692832947
|
||||||
|
paired,0.2603684663772583
|
||||||
|
paired,0.32788804173469543
|
||||||
|
paired,0.28169411420822144
|
||||||
|
paired,0.3227519690990448
|
||||||
|
paired,0.3319033086299896
|
||||||
|
paired,0.3185873031616211
|
||||||
|
paired,0.34493112564086914
|
||||||
|
paired,0.3604525923728943
|
||||||
|
unpaired,0.13933990895748138
|
||||||
|
unpaired,0.10618321597576141
|
||||||
|
unpaired,0.16058675944805145
|
||||||
|
unpaired,0.17256049811840057
|
||||||
|
unpaired,0.18050867319107056
|
||||||
|
unpaired,0.17393678426742554
|
||||||
|
unpaired,0.17463842034339905
|
||||||
|
unpaired,0.12813161313533783
|
||||||
|
unpaired,0.14834891259670258
|
||||||
|
unpaired,0.16522526741027832
|
||||||
|
unpaired,0.15986862778663635
|
||||||
|
unpaired,0.19971923530101776
|
||||||
|
unpaired,0.21379850804805756
|
||||||
|
unpaired,0.16859294474124908
|
||||||
|
unpaired,0.1630430519580841
|
||||||
|
unpaired,0.1932932436466217
|
||||||
|
unpaired,0.1589049994945526
|
||||||
|
unpaired,0.15467114746570587
|
||||||
|
unpaired,0.21967162191867828
|
||||||
|
unpaired,0.1271267682313919
|
||||||
|
unpaired,0.1379617303609848
|
||||||
|
unpaired,0.11341479420661926
|
||||||
|
unpaired,0.1405247300863266
|
||||||
|
unpaired,0.1693478673696518
|
||||||
|
unpaired,0.2000925987958908
|
||||||
|
unpaired,0.1594662368297577
|
||||||
|
unpaired,0.1274571418762207
|
||||||
|
unpaired,0.18167132139205933
|
||||||
|
unpaired,0.14616280794143677
|
||||||
|
unpaired,0.1484544575214386
|
||||||
|
unpaired,0.14663159847259521
|
||||||
|
unpaired,0.1430159956216812
|
||||||
|
Binary file not shown.
@@ -0,0 +1,14 @@
|
|||||||
|
snr_db,edma,hybrid,oma,genie,todma
|
||||||
|
0.0,0.1915625,0.2253125,0.1278125,0.190625,0.028125
|
||||||
|
2.5,0.278125,0.325,0.1884375,0.2840625,0.03671875
|
||||||
|
5.0,0.4065625,0.45375,0.2784375,0.4103125,0.05390625
|
||||||
|
7.5,0.5365625,0.5765625,0.3965625,0.54,0.0765625
|
||||||
|
10.0,0.6625,0.6940625,0.52375,0.6675,0.1390625
|
||||||
|
12.5,0.7646875,0.781875,0.6515625,0.76375,0.23359375
|
||||||
|
15.0,0.8296875,0.84875,0.7515625,0.833125,0.371875
|
||||||
|
17.5,0.8828125,0.8934375,0.828125,0.89,0.515625
|
||||||
|
20.0,0.9178125,0.926875,0.881875,0.925625,0.65859375
|
||||||
|
22.5,0.94625,0.9503125,0.9175,0.9565625,0.7703125
|
||||||
|
25.0,0.96125,0.9625,0.94625,0.9734375,0.84609375
|
||||||
|
27.5,0.970625,0.971875,0.9690625,0.983125,0.8921875
|
||||||
|
30.0,0.9796875,0.98,0.9809375,0.99125,0.91640625
|
||||||
|
@@ -0,0 +1,10 @@
|
|||||||
|
snr_db,haar768,whpad1024
|
||||||
|
0,0.04595265286625363,0.047847944343229754
|
||||||
|
5,0.07112330510281026,0.07224809597013518
|
||||||
|
10,0.1199369035474956,0.12063940849155187
|
||||||
|
15,0.20449634090065957,0.20457616232335568
|
||||||
|
20,0.33400419175624846,0.3319106823205948
|
||||||
|
25,0.48966493368148806,0.48235686495900154
|
||||||
|
30,0.6161512869596482,0.6032128128409385
|
||||||
|
35,0.6835479807853698,0.6678868445754051
|
||||||
|
40,0.7102783480286599,0.6937726792693139
|
||||||
|
Binary file not shown.
@@ -6,7 +6,7 @@
|
|||||||
\usetikzlibrary{arrows.meta,positioning,fit,calc}
|
\usetikzlibrary{arrows.meta,positioning,fit,calc}
|
||||||
\begin{document}
|
\begin{document}
|
||||||
\begin{tikzpicture}[
|
\begin{tikzpicture}[
|
||||||
font=\footnotesize,
|
font=\small,
|
||||||
node distance=3.2mm and 4.5mm,
|
node distance=3.2mm and 4.5mm,
|
||||||
blk/.style={draw, semithick, minimum height=5.5mm, minimum width=9mm,
|
blk/.style={draw, semithick, minimum height=5.5mm, minimum width=9mm,
|
||||||
inner sep=1.5pt, align=center},
|
inner sep=1.5pt, align=center},
|
||||||
@@ -58,8 +58,8 @@
|
|||||||
\draw[arr] (sig) -- node[above, lbl] {$\mb{r}$} (mf);
|
\draw[arr] (sig) -- node[above, lbl] {$\mb{r}$} (mf);
|
||||||
\draw[arr] (mf) -- node[above, lbl] {$\mb{t}_u$} (wnr);
|
\draw[arr] (mf) -- node[above, lbl] {$\mb{t}_u$} (wnr);
|
||||||
\draw[arr] (wnr) -- (out);
|
\draw[arr] (wnr) -- (out);
|
||||||
\fill (tap1) circle (0.5pt);
|
\fill (tap1) circle (1.1pt);
|
||||||
\fill (tapU) circle (0.5pt);
|
\fill (tapU) circle (1.1pt);
|
||||||
\draw[dsh] (tap1) -- ($(tap1 |- bm.north)$);
|
\draw[dsh] (tap1) -- ($(tap1 |- bm.north)$);
|
||||||
\draw[dsh] (bm.east) -| (wnr.south);
|
\draw[dsh] (bm.east) -| (wnr.south);
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
|
|||||||
Binary file not shown.
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