AnyMath 文档
Notebook

2X2MIMO空间复用:ZF和MMSE探测器的比较

该示例演示了具有瑞利衰落的2x2MIMO信道中的空间复用系统的操作。 在两个天线上发送两个独立的QPSK流,并且在接收侧应用线性流分离。 两个经典线性检波器,迫零(ZF)和最小均方误差(MMSE),根据MSE和BER标准进行比较,并具有星座可视化。

接收模型看起来像:

哪里 -传输字符的向量, -信道矩阵(), -复白高斯噪声。

迫零(ZF)通过反转通道完全抑制流间失真:

缺点:单数较小 噪声被放大了一个因子 ,这极大地恶化了MSE。

MMSE最大限度地减少RMS误差 考虑噪声方差 :

规则化者 防止噪声向弱特征值方向爆炸式增长 以小偏差为代价。 这就是为什么在低和中度Snr以及较差的通道调节条件下,MMSE的性能明显优于采埃孚。

实现;实现

该脚本由以下步骤组成:

  1. 数据生成-生成QPSK字符矩阵(2个流×N个字符)和随机信道矩阵 . 通道被人为调节(通过固定矩阵的乘法),以证明MMSE的优势。
  2. 信道和噪声-信号通过 ,之后使用系统对象将AWGN添加到其中 EngeeComms.AWGN (参数 EbNo, BitsPerSymbol, SignalPower).
  3. 检测矩阵计算 和 通过稳定的LU分解(运算符 \),并被施加到接收信号。
  4. 质量评估-计算两个探测器的MSE,并输出调节数 .
  5. 可视化-6星座被构造:两个天线上的接收信号(流的混合物),每个流的ZF和MMSE的结果。
  6. BER-swipe-在Monte Carlo SNR周期中,评估BER,并通过系统对象执行错误计数 EngeeComms.ErrorRateCalculation.

使用AnyMath系统对象(EngeeComms.AWGN, EngeeComms.ErrorRateCalculation)确保按照库标准正确计算能量参数和错误统计,消除了常规操作,使代码适合迁移到成熟的通信模型。

In [ ]:
# Pkg.add(["LinearAlgebra", "Random", "Statistics"])
using LinearAlgebra, Random, Statistics, EngeeComms

首先,我们来执行系统的初始化:

  • Random.seed!(2024) -固定rng以实现重现性。
    -参数: N=4000 字符/流, SNR=8 дБ,信号强度1。 重新计算 对于AWGN块和 为MMSE。
    -QPSK:星座归一化为单次方,形成符号矩阵 .
    -频道 :瑞利矩阵 它是通过固定矩阵的乘法来人为调节的,以便 —这将清楚地表明MMSE优于ZF的优势。
  • y_ideal = H * s -信号通过通道(无噪声):流混合,探测器的任务是将它们分开。
In [ ]:
Random.seed!(2024)

N = 4000
SNR_dB = 8.0
bits_per_symbol = 2
SignalPower = 1.0

EbNo_dB = SNR_dB - 10 * log10(bits_per_symbol)
σ² = 1.0 / (10^(SNR_dB / 10))

qpsk = ComplexF64[1+1im, -1+1im, -1-1im, 1-1im] ./ sqrt(2)
s = qpsk[rand(1:4, 2, N)]

H = (randn(2,2) .+ 1im .* randn(2,2)) ./ sqrt(2)
H = H * [1.0 0.3; 0.0 0.15] * [1.0 0.0; 0.4 1.0]

y_ideal = H * s
Out[0]:
2×4000 Matrix{ComplexF64}:
 -0.286017+1.34245im   0.833343-1.40624im   …  -1.88977-0.222226im
  0.179459-0.60078im  -0.512083+0.458318im     0.933405+0.321921im

接下来,添加噪声:

  • EngeeComms.AWGN(...)-创建模拟加性白高斯噪声的系统对象。 参数: EbNo (比特能量与噪声之比), BitsPerSymbol=2 (适用于QPSK), SignalPower=1.0 (信号强度)。
  • awgn_channel(vec(y_ideal))-通过带噪声的通道传递信号。 功能 vec() 变换矩阵 成列向量,因为AnyMath API接受一维数组。
  • reshape(y_vec, size(y_ideal))-恢复矩阵的原始形状 供探测器进一步处理。
In [ ]:
awgn_channel = EngeeComms.AWGN(
    EbNo = EbNo_dB,
    BitsPerSymbol = bits_per_symbol,
    SignalPower = SignalPower
)

y_vec = awgn_channel(vec(y_ideal))
y = reshape(y_vec, size(y_ideal))
Out[0]:
2×4000 Matrix{ComplexF64}:
 -0.233481+1.91278im    0.304577-1.46275im  …  -1.90713-0.316705im
  0.363028-0.816211im  -0.842276+1.09409im     0.553998+0.858639im

下一阶段是检测和质量评估。 这是怎么回事:

  1. 探测器阵列的计算 W_zf 和 W_mmse 根据伪循环和维纳-霍普夫公式。
  2. 对接收到的信号施加检测器 y -混合流的分离。
  3. MSE计算是对两种方法的字符重建准确性的定量评估。
In [ ]:
W_zf = (H' * H) \ H'
ŝ_zf = W_zf * y

W_mmse = (H' * H + σ² * I) \ H'
ŝ_mmse = W_mmse * y

mse_zf = mean(abs2, ŝ_zf - s)
mse_mmse = mean(abs2, ŝ_mmse - s)

println("MIMO 2×2: ZF vs MMSE")
println("SNR (Es/N0) = $SNR_dB дБ  |  Eb/No = $(round(EbNo_dB, digits=2)) дБ")
println("cond(H)     = $(round(cond(H), digits=2))")
println("MSE  ZF     = $(round(mse_zf, digits=5))")
println("MSE  MMSE   = $(round(mse_mmse, digits=5))")
MIMO 2×2: ZF vs MMSE
SNR (Es/N0) = 8.0 дБ  |  Eb/No = 4.99 дБ
cond(H)     = 23.17
MSE  ZF     = 11.04402
MSE  MMSE   = 0.50019

之后,星座被可视化。

  • draw(x; ...)-在两层中构建星座的辅助功能:
    -接受点的半透明云(I/Q);
    -红色交叉-比较的理想QPSK位置。
    -6图:在两个天线(灰色,流的混合物)接收信号,ZF(蓝色)和MMSE(绿色)的结果为每两个流。
In [ ]:
function draw(x; title="", color=:blue)
    p = scatter(real.(x), imag.(x);
                markersize=3, alpha=0.35, color=color, title=title,
                xlabel="I", ylabel="Q",
                xlims=(-2.5, 2.5), ylims=(-2.5, 2.5),
                aspect_ratio=:equal, legend=:topright, grid=true)
    scatter!(p, real.(qpsk), imag.(qpsk);
             markersize=8, color=:red, marker=:xcross)
    return p
end

p_y1 = draw(y[1,:]; title="Rx天线1", color=:gray)
p_y2 = draw(y[2,:]; title="Rx天线2", color=:gray)
p_z1 = draw(ŝ_zf[1,:]; title="ZF后的第1流", color=:blue)
p_z2 = draw(ŝ_zf[2,:]; title="ZF后的第2流", color=:blue)
p_m1 = draw(ŝ_mmse[1,:]; title="MMSE后的第1流", color=:green)
p_m2 = draw(ŝ_mmse[2,:]; title="MMSE后第2流", color=:green)

plot(p_y1, p_y2, p_z1, p_z2, p_m1, p_m2;
     layout=(3,2), size=(900, 1100),
     plot_title="MIMO 2×2: ZF vs MMSE (SNR = $SNR_dB дБ)",
     left_margin=8Plots.mm, bottom_margin=8Plots.mm)
Out[0]:

图表输出:

顶行-4簇在天线上可见(流的混合物),2在天线上更加模糊。

平均范围(ZF)是灾难性的传播:

-流1:一个巨大的蓝色云,点填充整个领域
-流2:更糟糕的是-点均匀涂抹,QPSK结构完全丢失

底行(MMSE)明显更好:

-流1:4清除绿色集群,完美恢复
-流2:一个集群合并在中心。

初始化 ErrorRateCalculation

  • snrs_dB = 0:2:20-用于构建BER曲线的信噪比范围(以2为增量从0到20dB)。
  • ber_zf, ber_mmse-空阵列,用于为ZF和MMSE探测器的每个SNR累积BER结果。
  • Nsym = 20_000-一次运行(迭代)中的字符数,以确保统计可靠性。
  • **n_iterations = 50**是每个SNR点的蒙特卡洛迭代次数(各种随机信道实现)。
  • err_calc = EngeeComms.ErrorRateCalculation()-创建AnyMath系统对象,该对象将用于计算循环后续步骤中的错误数。
In [ ]:
snrs_dB = 0:2:20
ber_zf, ber_mmse = Float64[], Float64[]
Nsym = 20_000
n_iterations = 50

err_calc = EngeeComms.ErrorRateCalculation()
Out[0]:
ErrorRateCalculation:
    ReceiveDelay=0
    ComputationDelay=0
    ComputationMode=Entire frame
    OutputData=Port
    ResetPort=false
    StopSimulation=false

下面的代码中有两个嵌套循环。 外部迭代通过SNR值从0到20dB在增量2,初始化错误计数器,并且创建对象。 EngeeComms.AWGN 使用当前步骤的重新计算值 . 内部蒙特卡洛循环执行50个独立的实现:每个生成一个新的随机瑞利信道矩阵。 和传输字符的块 ,信号通过噪声通道,之后使用ZF和MMSE检测器。 硬解将每个恢复的字符分配给最近的QPSK点,系统对象 ErrorRateCalculation 计算在所有迭代中累积的错误数。

在内循环结束时,ser被计算为错误总数与传输的字符总数的比率,然后转换为BER,考虑到对于具有灰色编码的QPSK . 生成的值将添加到数组中 ber_zf 和 ber_mmse.

最后的图形是用两条曲线—ZF和MMSE沿纵坐标轴以对数标度绘制的。

In [ ]:
for snr_db in snrs_dB
    err_zf_total = 0
    err_mmse_total = 0
    
    ebno_db_sweep = snr_db - 10 * log10(bits_per_symbol)
    awgn_sweep = EngeeComms.AWGN(EbNo = ebno_db_sweep, BitsPerSymbol = bits_per_symbol, SignalPower = SignalPower)
    
    for _ in 1:n_iterations
        H_ = (randn(2,2) .+ 1im.*randn(2,2)) ./ sqrt(2)
        s_ = qpsk[rand(1:4, 2, Nsym)]
        
        y_ideal_sweep = H_ * s_
        y_sweep_vec = awgn_sweep(vec(y_ideal_sweep))
        y_sweep = reshape(y_sweep_vec, size(y_ideal_sweep))

        σ2_sweep = 1.0 / (10^(snr_db / 10))
        ŝz = ((H_'*H_) \ H_') * y_sweep
        ŝm = ((H_'*H_ + σ2_sweep*I) \ H_') * y_sweep

        decide(x) = sign(real(x))/sqrt(2) + 1im*sign(imag(x))/sqrt(2)
        bits_zf = decide.(ŝz)
        bits_mmse = decide.(ŝm)
        
        stats_zf = err_calc(vec(bits_zf), vec(s_))
        stats_mmse = err_calc(vec(bits_mmse), vec(s_))
        
        err_zf_total += stats_zf[2]
        err_mmse_total += stats_mmse[2]
    end
    
    ser_zf = err_zf_total / (n_iterations * Nsym)
    ser_mmse = err_mmse_total / (n_iterations * Nsym)
    
    push!(ber_zf, ser_zf / 2.0)
    push!(ber_mmse, ser_mmse / 2.0)
end

p_ber = plot(snrs_dB, ber_zf; yscale=:log10, marker=:circle, lw=2, label="ZF",
             xlabel="SNR (Es/N0), дБ", ylabel="BER", title="BER: ZF vs MMSE (2×2 MIMO)",
             grid=true, legend=:bottomleft)
plot!(p_ber, snrs_dB, ber_mmse; marker=:square, lw=2, label="MMSE", color=:green)
Out[0]:

为什么图形匹配。 不像星座的示范,其中通道被人为调节(),BER使用"纯"瑞利通道。 对于随机矩阵 对于复杂的高斯元素,得到一个条件差的实现的概率是低的—平均 不多。 具有良好的调理和适中的信噪比,正则化器 在MMSE中,它变得可以忽略不计,并且两个检测器实际上都减少到伪循环。 . 因此,ZF和MMSE曲线实际上在图上合并:这里MMSE的理论增益在各种有利的信道实现上"涂抹",并且在统计平均的背景下不可见。 为了确定BER曲线上的差异,需要修复一个条件差的信道(如示例的第一部分),或者将信噪比范围移到非常低的值。

结论

该示例清楚地表明了MIMO系统中两个经典线性检测器之间的基本折衷。

迫零完全消除了线程间干扰,但代价是灾难性的噪声放大和较差的信道调理。 在我们的实验中,当 并且ZF探测器的SNR=8dB MSE为11.04—星座变成均匀云,QPSK结构完全丢失。

为了控制噪声,MMSE牺牲了完全的MSI抑制. 规则化者 防止色散在弱通道特征值方向上的爆炸式增长。 结果:MSE=0.50,比ZF好22倍。 在星座中,这表现为围绕理想QPSK位置的清晰紧凑的簇。

关键见解:MMSE优于ZF的优势在于低Snr和较差的通道调理-正是在噪声占主导地位的信号条件下。 具有高信噪比或良好的调理 两个探测器会聚到一个伪环流 ,并且它们的性能几乎相同(如随机瑞利通道在0-20dB范围内的BER曲线的重合所证实的)。

实用建议:在实际通信系统中,其中信道可能暂时变得较差(衰落,天线相关性),MMSE优选ZF作为更鲁棒的检测器。 两种方法的计算复杂度相当(都需要矩阵求逆 ),因此,有利于MMSE的选择不会产生额外的成本。