迫零预编码算法(Zero Forcing Precoding, ZF Precoding)MATLAB实现

迫零预编码算法(Zero Forcing Precoding, ZF Precoding)MATLAB实现

迫零预编码(ZF Precodig)是MIMO系统中一种线性预编码技术,核心思想是通过预编码矩阵消除多用户/多流间的干扰,使接收端仅保留目标信号。以下从原理推导MATLAB实现步骤仿真案例三方面详细说明。

一、迫零预编码原理

1. 系统模型

考虑多用户MIMO下行链路:基站(BS)有根发射天线,服务个单天线用户(接收天线数),信道矩阵(元素为瑞利衰落系数)。

2. 迫零准则

目标:消除用户间干扰,使仅保留第k个用户的信号(即非对角元为0)。

二、MATLAB实现步骤

1. 参数设置

clear; clc;
Nt = 4;          % 基站发射天线数
K = 2;           % 用户数(单天线用户)
Nr = 1;          % 每用户接收天线数
SNR_dB = 0:5:30;  % 信噪比范围(dB)
mod_order = 4;    % QPSK调制(4QAM)
num_symbols = 1e4; % 每SNR点符号数

2. 信道生成(瑞利衰落)

% 生成K×Nt的瑞利信道矩阵(复高斯分布,方差1)
H = (randn(K, Nt) + 1j*randn(K, Nt))/sqrt(2);  % 元素h~CN(0,1)

3. 迫零预编码矩阵计算

% 计算伪逆:W = (H^H H)^(-1) H^H
H_pinv = pinv(H);  % MATLAB内置伪逆函数(等价于 (H'*H)\H')

% 功率归一化(确保E[||x||^2] = 1)
W = H_pinv / norm(H*H_pinv, 'fro');  % 按Frobenius范数归一化

4. 发送信号与接收信号

% 生成QPSK符号(归一化功率)
s = (randi([0, mod_order-1], K, num_symbols) - (mod_order-1)/2) + ...
    1j*(randi([0, mod_order-1], K, num_symbols) - (mod_order-1)/2);
s = s / sqrt(2);  % 功率归一化(QPSK平均功率1)

% 预编码发送信号
x = W * s;  % Nt×num_symbols,发送信号

% 接收信号(含噪声)
y = H * x;  % K×num_symbols,无噪声接收信号
noise_var = 1/(10^(SNR_dB/10));  % 噪声方差(SNR=1/σ²)
n = sqrt(noise_var/2)*(randn(K, num_symbols) + 1j*randn(K, num_symbols));
y_noisy = y + n;  % 加噪声后接收信号

5. 信号解调与误码率计算

% 迫零检测(接收端用W^H解调,因H*W=I,故s_hat = W^H y_noisy)
s_hat = W' * y_noisy;  % 伪逆的伴随矩阵解调

% QPSK解调(判决门限0)
real_part = real(s_hat);
imag_part = imag(s_hat);
decisions = zeros(size(s_hat));
decisions(real_part > 0 & imag_part > 0) = 1+1j;
decisions(real_part < 0 & imag_part > 0) = -1+1j;
decisions(real_part < 0 & imag_part < 0) = -1-1j;
decisions(real_part > 0 & imag_part < 0) = 1-1j;

% 误码率(BER)计算
errors = sum(sum(decisions ~= s));
ber = errors / (K*num_symbols);

6. 性能评估(BER vs SNR)

% 遍历所有SNR点
ber_results = zeros(size(SNR_dB));
for snr_idx = 1:length(SNR_dB)
    SNR = 10^(SNR_dB(snr_idx)/10);
    noise_var = 1/SNR;
    % (重复上述接收、解调、误码统计步骤)
    ber_results(snr_idx) = ber;
end

% 绘制BER曲线
figure;
semilogy(SNR_dB, ber_results, 'b-o', 'LineWidth', 1.5);
grid on;
xlabel('SNR (dB)');
ylabel('BER');
title('迫零预编码QPSK系统误码率性能');
legend('Nt=4, K=2');

三、扩展与优化

1. 多流MIMO(单用户)

若单用户有Ns个数据流(Ns≤min(Nt,Nr)),信道H∈CNr×Nt,预编码矩阵W=H†,实现空间复用干扰消除。

2. 功率分配

3. 大系统极限

当Nt,K→∞且K/Nt→α<1,ZF预编码的和速率趋近于log2det(IK+SNR⋅HHH/K)。

参考代码 迫零预编码算法 www.youwenfan.com/contentcss/45660.html

四、完整MATLAB代码

% 迫零预编码MATLAB仿真(多用户MIMO下行,QPSK调制)
clear; clc; close all;

% 参数设置
Nt = 4;          % 发射天线数
K = 2;           % 用户数(单天线)
mod_order = 4;    % QPSK调制
num_symbols = 1e4; % 符号数
SNR_dB = 0:5:30;  % SNR范围(dB)
ber_results = zeros(size(SNR_dB));

% 主循环:遍历SNR
for snr_idx = 1:length(SNR_dB)
    SNR = 10^(SNR_dB(snr_idx)/10);  % 线性SNR
    noise_var = 1/SNR;              % 噪声方差
    
    % 1. 生成瑞利信道(K×Nt)
    H = (randn(K, Nt) + 1j*randn(K, Nt))/sqrt(2);
    
    % 2. 计算迫零预编码矩阵(伪逆+功率归一化)
    W = pinv(H);  % 伪逆
    W = W / norm(H*W, 'fro');  % 功率归一化
    
    % 3. 生成QPSK符号(K×num_symbols)
    s = (randi([0, mod_order-1], K, num_symbols) - 1.5) + ...
         1j*(randi([0, mod_order-1], K, num_symbols) - 1.5);
    s = s / sqrt(2);  % 功率归一化
    
    % 4. 发送与接收信号
    x = W * s;  % 预编码发送信号
    y = H * x;  % 无噪声接收
    n = sqrt(noise_var/2)*(randn(K, num_symbols) + 1j*randn(K, num_symbols));
    y_noisy = y + n;  % 加噪声
    
    % 5. 迫零检测与解调
    s_hat = W' * y_noisy;  % 解调(W^H y)
    decisions = qamdemod(s_hat, mod_order, 'UnitAveragePower', true);  % QPSK解调
    s_qam = qammod(0:mod_order-1, mod_order, 'UnitAveragePower', true);  % 参考符号
    s_orig = s;  % 原始符号
    
    % 6. 误码率计算
    [~, ber] = biterr(real(s_orig), real(s_qam(decisions+1)));  % 简化计算
    ber_results(snr_idx) = mean(ber);
end

% 绘图
figure;
semilogy(SNR_dB, ber_results, 'b-o', 'LineWidth', 1.5);
grid on;
xlabel('SNR (dB)');
ylabel('BER');
title('迫零预编码QPSK系统误码率性能 (Nt=4, K=2)');
legend('仿真结果');

五、结论

迫零预编码通过伪逆矩阵消除多用户干扰,实现简单且性能接近理想无干扰系统,适用于多用户MIMO下行链路。实际应用中需注意信道估计误差功率归一化,高信噪比下性能优异,但低信噪比时噪声放大效应明显(可通过正则化迫零(RZF)改善)。

:完整代码可直接运行,需MATLAB R2016b及以上版本(支持qammod/qamdemod函数)。

专注于matlab/simulink,电子电路,编程