做多用户 MIMO 干扰信道的研究生,十有八九都卡过这个问题:预编码矩阵明明算出来了,干扰怎么还是压不下去?后来我在组会上看到“超对角 RIS 辅助 MIMO 干扰信道中的干扰最小化”这个课题,才把思路理顺——干扰信道里加入可重构智能表面,然后把 RIS 的反射矩阵建构成带超对角项的结构,用交替优化同时调发射预编码和超表面相位,仿真结果比单纯扩天线数好得多。这篇文章就把整套模型、推导、Matlab 实现思路和调试经验拆开讲,适合正在做无线通信物理层仿真、刚接触 RIS 或者打算复现这片方向代码的同学。
1. 项目定位与核心目标解析
1.1 这个仿真到底在解决什么问题
先看场景本身。MIMO 干扰信道指的是多个发射-接收对同时工作在同一时频资源上,第 k 个接收机除了收到自己的期望信号外,还会收到来自其他发射机的干扰信号。“干扰最小化”要解决的就是:设计所有发射端的预编码矩阵和 RIS 的反射系数,让各接收端的干扰功率总和降到最低。
可能有人会问:为什么不直接做“和速率最大化”?因为干扰最小化和和速率最大化在工程上有本质区别。速率最大化需要依赖完整的 SINR 表达式,目标函数是 log 函数,和预编码矩阵、RIS 相位的耦合非常强,解起来极不稳定,还容易被局部最优困住。而干扰最小化只要盯着干扰泄露功率,目标函数是二次型,结构和梯度都好处理,尤其适合用“交替优化+投影”这种成熟套路。实践中我发现,先把干扰压下去,再配合功率分配迭代几步,最终可达速率往往比直接去优化非凸的 SINR 更稳,尤其在高信噪比区间优势更明显。
1.2 为什么引入超对角 RIS 而不是普通对角 RIS
大部分 RIS 论文里,反射系数矩阵都被建模为严格的对角矩阵,每个单元只独立调整自己的反射相位。这种模型入门的门槛低、推导方便,但物理上丢了一件事:相邻单元之间的电磁互耦。真实超表面单元靠得越近,单元间的耦合越不可能忽略。如果只保留对角项,仿真结果会和实测有偏差,特别是在高频大阵列的场景。
超对角 RIS 的建模思路,是把反射矩阵从严格对角扩展到包含主对角线相邻位置元素的带状结构。也就是除了每个单元自身的反射系数,还允许相邻单元之间存在一个相对较小的耦合系数,用数学语言描述就是:
Θ = diag(θ₁, θ₂, … , θ_N) + ε · superdiag(φ₁, φ₂, … , φ_{N-1})
其中 superdiag 表示主对角线右上方一条对角线上的非零项。这个 ε 控制耦合强度,一般取 0.1 这个量级,用来模拟单元间互耦的次级反射路径。好处很明显:比全矩阵 RIS 的可实现性高得多(全矩阵结构在当前硬件上基本做不出来),又比严格对角模型多了一维控制和建模精度,在仿真里能看到干扰功率明显比普通对角模型更低。
2. 系统建模与信号分析
2.1 MIMO 干扰信道的完整信号模型
为了把问题说清楚,我先把记号定下来。假设系统里有 K 个用户对,每个发射机配 Nt 根天线,每个接收机配 Nr 根天线,RIS 含有 N 个可调反射单元。用户 k 接收到的信号可以写成:
y_k = H_k V_k s_k + Σ_{l≠k} H_{kl} V_l s_l + n_k
其中 H_k 是用户 k 的直连等效信道,H_{kl} 是发射机 l 到接收机 k 的干扰信道,V_k 是用户 k 的预编码矩阵,s_k 是发射符号,n_k 是零均值复高斯噪声。加了 RIS 之后,等效信道变成了直连路径加级联路径:
H_kl^eff = H_kl^d + H_r,k Θ H_t,l
这里 H_r,k 是 RIS 到接收机 k 的信道矩阵,维度是 Nr×N,H_t,l 是发射机 l 到 RIS 的信道矩阵,维度是 N×Nt,Θ 就是前面提到的超对角反射矩阵。
一开始我总把这三个矩阵的维度搞混,尤其是 H_r 和 H_t 都带角标 k、l,特别容易绕进去。后来我给自己定了个规矩:看维度而不是看名字。从发射机出来先碰 H_t(N×Nt),再碰 Θ(N×N),再碰 H_r(Nr×N),最后到接收机,维度一路传递下来,保证最终结果落在 Nr×Nt 就对了。
2.2 超对角结构的数学本质与物理含义
“超对角”这个词乍一听很吓人,其实就是线性代数里矩阵主对角线上面的那一条对角线。为什么要在 RIS 里引入超对角结构?我个人的理解是,把 RIS 的反射行为拆成两个层次:
第一个层次是“自反射”,也就是每个单元对自己入射信号的相位调整,对应主对角线元素。第二个层次是“邻元耦合反射”,入射信号首先被某个单元接收,但由于单元间的互耦,一部分能量会串到相邻的单元再反射出去,这样就出现了一条“主对角线上方的路径”。如果用张成的空间来看,严格对角 RIS 的等效信道自由度是 N,全连接 RIS 是 N²,而超对角 RIS 是 2N-1,虽然没有全连接那么夸张,但已经足够给干扰最小化提供额外的调节维度。
这个结构放到代码里的实现方式也很直接:先建一个 N×N 的复数零矩阵,主对角线填上 exp(j·θ_i),再在超对角位置填上 ε·exp(j·φ_i)。注意超对角矩阵并不对称,也就是说第 i 行第 i+1 列和第 i+1 行第 i 列的值可以不一样,这两个方向分别对应前向和后向耦合。
2.3 干扰最小化问题的完整数学刻画
把上面的模型汇总,干扰最小化问题可以写成如下形式:
min_{V, Θ} J(V, Θ) = Σ_{k=1}^{K} Σ_{l≠k} || H_kl^eff V_l ||_F²
s.t. || V_l ||F² ≤ P_l, l = 1, …, K |Θ_ii| = 1, i = 1, …, N |Θ{i,i+1}| = ε, i = 1, …, N-1
这里第一个约束是每个发射机的功率限制,第二个约束是 RIS 单元的相位单位模约束,第三个约束是超对角耦合系数的幅度限制。注意问题是非凸的:V 和 Θ 在目标函数里是相乘的关系,单位模约束又把可行域限制在一个环面上,整个问题没法直接求全局最优,只能用数值迭代方法。
有一点我必须强调:干扰最小化不追求“把信号打到用户最强方向”,而是追求“让信号不泄漏到其他用户方向上”。这是两个不同的哲学。前者看的是信号增强,后者看的是干扰规避。在多用户干扰受限的场景里,后一种思路往往更有效,因为当干扰功率被压到零度附近时,每个用户的 SINR 自然就上去了,不需要刻意追求功率增益。
3. 联合优化算法设计
3.1 整体算法框架:交替优化的基本思路
这个非凸问题的最常用解法就是交替优化:固定一组变量,优化另一组;再反过来,直到目标函数收敛。具体展开就是:
第一步,固定 RIS 相位矩阵 Θ,把所有涉及 Θ 的等效干扰信道算出来,这时候目标函数只跟预编码矩阵 V 有关。第二步,固定所有 V,目标函数展开成只跟 Θ 相关的形式,再对相位进行逐坐标或梯度式更新。第三步,检查收敛条件,没达到就回到第一步继续循环。
我用这个框架跑下来的最大体会是:别一上来就追求一步到位的联合优化,交替优化虽然看起来“笨”,但它最大的优势是每一半问题都有成熟的求解工具。只要每半个子问题的目标函数单调下降,整个算法的收敛性就有保证,实际操作里 30 到 50 次迭代基本都能看到明显下降。
3.2 固定 RIS 相移时:发射预编码的闭式解怎么拿
固定 Θ 之后,目标函数变成:
J(V) = Σ_{k=1}^{K} Σ_{l≠k} || H_kl^eff V_l ||_F²
这个结构看着眼熟——每个用户的预编码只出现在和它相关的干扰项里,所以可以分解成 K 个独立子问题。对于第 l 个发射机,它的干扰贡献完全由等效干扰信道矩阵的“聚合协方差”决定:
R_l = Σ_{k≠l} (H_kl^eff)^H H_kl^eff
我们要做的是让 || H_kl^eff V_l || 对所有 k≠l 都尽量小,所以 V_l 的列应该放在 R_l 最小的几个特征值对应特征向量张成的子空间里。换句话说,取 eig(R_l),把 d 个最小特征值对应的特征向量拼成预编码矩阵,再做功率归一化:
V_l = sqrt(P_l / trace(U_min^H U_min)) · U_min
这一步我一直跟学生强调:千万别下意识去取最大特征向量,那是做波束成形增强信号的思路,不是做干扰抑制的思路。判断标准就一条——看目标函数是在最小化什么,如果目标是干扰功率,闭式解一定来自最小特征子空间。
3.3 固定预编码时:RIS 相位优化的张量化操作
固定 V 之后再优化 Θ,麻烦程度上升一个量级。这里的关键是把目标函数写成 Θ 的显式函数。用向量化技巧,级联信道 H_r Θ H_t 可以改写为对相位向量线性依赖的形式:
vec(H_r Θ H_t) = (H_t^T ⊗ H_r) · vec(Θ)
其中 vec(Θ) 是一个 N² 维向量,但由于我们的 Θ 只有主对角和超对角位置非零,vec(Θ) 实际只有大约 2N 个自由变量。把这些自由变量抽出来组成向量 θ,那么每一对干扰信道项都能写成 A_k θ + b_k 的形式,其中 A_k 是降维后的等效干扰矩阵,b_k 是直连信道部分。于是目标函数变成:
J(θ) = Σ_k || A_k θ + b_k ||²
这是一个关于 θ 的四次展开化简成二次型的过程,展开后是 θ^H Q θ + 2·Re(q^H θ) + const 的标准复二次型。接下来的处理办法有两条路:
一条是做逐坐标下降,每次固定其他相位,更新第 i 个相位时,目标函数对 θ_i 是一个三角函数,可以直接求出闭式更新公式,再把幅度投影回单位模约束。另一条是做黎曼流形梯度下降,把单位模约束看成一个环面流形,每步在切空间上走梯度,再指数映射回来。
我个人的建议是:如果 N 比较小(64 以下),逐坐标下降更好用,因为它每一轮都是精确更新,不需要调步长;如果 N 超过 256 了,逐坐标下降的循环开销太大,优先用流形梯度下降,配合 Armijo 步长准则,稳定性足够。
3.4 收敛性分析和复杂度权衡
交替优化的收敛性建立在两个半子问题都能被精确求解的基础上。预编码子问题是最小特征子空间闭式解,目标函数一定不升;RIS 子问题不管是坐标下降还是梯度下降,只要内部迭代能够让目标函数下降,整个算法就会收敛到一个稳定点。这里说的稳定点是指没有任何一个单侧更新能让目标函数继续下降的点,无法保证全局最优,所以初始点选择很重要。
关于复杂度,预编码部分的主成本是对每个用户做一次 d 维特征值分解,复杂度约 O(K · Nt³)。RIS 部分如果做 L 轮坐标下降,每轮要计算 2N 个相位更新,每个相位更新要重新计算部分梯度,总复杂度约 O(L · 2N · K · Nt · Nr)。这个开销比全矩阵 RIS 的 O(N²) 算法低得多,这也是超对角结构在实际仿真里的价值体现——它用接近纯对角 RIS 的复杂度,拿到了接近全矩阵 RIS 的性能。
4. 仿真参数设置与 Matlab 源码详解
4.1 照着能跑通的仿真参数配置参考
讲完算法,直接落到代码上。刚接触这个领域,我建议直接把仿真环境固定下来,不要一上来就追求大系统,否则变量维度一多,矩阵尺寸出错根本排查不过来。下面这套参数是我的日常起步配置,稳定且能清楚看到各方案差距。
| 参数项 | 取值 | 说明 |
|---|---|---|
| 用户对数 K | 4 | 4 个发射-接收对,干扰关系足够复杂 |
| 发射天线数 Nt | 4 | 每用户 4 根发射天线 |
| 接收天线数 Nr | 4 | 每用户 4 根接收天线 |
| RIS 单元数 N | 64 | 8×8 平面阵列排列 |
| 数据流数 d | 2 | 每用户传输 2 路数据流 |
| 信道模型 | 瑞利/莱斯混合 | RIS 级联信道用莱斯因子 3dB |
| 信噪比范围 | 0~20 dB | 间隔 5dB |
| 蒙特卡洛次数 | 500 | 每次独立生成信道 |
| 迭代上限 | 50 | 交替优化最大迭代次数 |
| 收敛门限 | 1e-4 | 目标函数相对变化量 |
信道生成这块我踩过一个坑:直连信道和 RIS 级联信道如果用同样的分布,仿真结论会被“天线多的那边”主导,看不出来 RIS 的真实贡献。正确做法是把直连信道的路径损耗设高一些(比如差 10dB),RIS 相关信道走莱斯衰落,模拟视距路径,再让莱斯因子从 0 调到 5dB 观察性能变化。这样调参能让“超对角结构带来的增益”稳定出现在结果里。
4.2 Matlab 代码核心循环拆解:交替优化怎么落地
整个项目源码的骨架其实很短,核心就是一个迭代循环里依次调两个更新函数。我在这里把主干逻辑写出来:
% 初始化:随机相位 + 随机预编码 theta = exp(1i * 2 * pi * rand(N, 1)); theta_c = exp(1i * 2 * pi * rand(N-1, 1)); % 超对角耦合相位 V = cell(K, 1); for k = 1:K V{k} = randn(Nt, d) + 1i * randn(Nt, d); V{k} = V{k} / norm(V{k}, 'fro') * sqrt(P); end J_hist = zeros(maxIter, 1); for iter = 1:maxIter % Step 1: 固定 Theta,更新预编码 Theta = build_superdiag_matrix(theta, theta_c, epsilon); H_eff = cell(K, K); for k = 1:K for l = 1:K H_eff{k, l} = H_d{k, l} + H_r{k} * Theta * H_t{l}; end end for l = 1:K R_l = zeros(Nt, Nt); for k = 1:K if k ~= l R_l = R_l + H_eff{k, l}' * H_eff{k, l}; end end [E, D] = eig(R_l); [~, idx] = sort(real(diag(D)), 'ascend'); V{l} = E(:, idx(1:d)); V{l} = V{l} / norm(V{l}, 'fro') * sqrt(P); end % Step 2: 固定 V,更新 Theta(逐坐标下降简化版) [J_val, grad] = interference_gradient(theta, theta_c, V, H_d, H_r, H_t); theta = unit_modulus_projection(theta - step * grad(1:N)); theta_c = unit_modulus_projection(theta_c - step * grad(N+1:end)); J_hist(iter) = J_val; if iter > 1 && abs(J_hist(iter) - J_hist(iter-1)) / abs(J_hist(iter-1)) < 1e-4 break; end end这段代码里 build_superdiag_matrix 是超对角矩阵的构造函数,interference_gradient 是目标函数的梯度计算,unit_modulus_projection 就是把向量每个元素归一化到单位圆上。关键点我在注释里标出来了:预编码部分用的是最小特征子空间,RIS 部分是“梯度下降+投影”。写完第一版的时候我犯过一个错——忘了对 V 做功率归一化,结果干扰功率曲线看起来在下降,实际是因为发射功率被悄悄降了,而不是算法真的有效。加上归一化之后,曲线才有可比性。
4.3 目标函数与梯度计算的 MatlaLab 实现细节
梯度计算函数是整个代码里最容易写错的地方。正确的做法是把目标函数先表示成对所有相位变量的实值标量,然后用复梯度公式展开。目标函数:
J = Σ_{k,l≠k} || (H_d_{kl} + H_r,k Θ H_t,l) V_l ||_F²
展开后,其中有 Θ 的部分可以写成关于相位向量 φ 的二次型。用矩阵求导的链式法则可以得到对第 i 个主对角相位的梯度分量:
grad_i = 2 · Re( Σ_{k,l≠k} V_l^H (H_t,l)^H (diag(e_i) 对应项) H_r,k^H ( (H_d_{kl} + H_r,k Θ H_t,l) V_l ) )
代码实现时我不建议手写这个复杂梯度,直接用一个小的数值差分函数验证手写梯度是否正确,确认无误后再替换成解析梯度,能省下大量排查公式的时间。具体写法就是用实部扰动计算有限差分梯度,跟解析梯度做相对误差对比,误差在 1e-6 以内就可以放心用解析梯度了。
还有一个小技巧:目标函数 J 是实值的,但中间变量全是复数的,gradient descent 在复数域里直接更新 theta 会不稳定。我的做法是把相位变量拆成实部虚部两段各自更新,或者直接用相位本身的实值更新公式——这在地铁里跑代码时是最高效的稳键做法。归一化投影那一步注意要用 abs 而不是 norm,否则会把整个向量长度压断。
4.4 对比方案要怎么设置才能体现超对角优势
仿真里不能只跑一种方案,否则结果出来没有参照物。我通常会同时跑四条曲线:
第一,无 RIS 方案,也就是把 Θ 设为零,干扰最小化完全靠预编码完成。第二,纯对角 RIS 方案,超对角耦合项设为零,这是最常规的对照。第三,超对角 RIS 方案,也就是本仿真的目标方案,ε 取 0.15。第四,全矩阵 RIS 方案,所有 N² 个元素都能独立优化,性能上界,但复杂度高很多。
四个方案用相同的信道实现跑同一个蒙特卡洛循环,最后画干扰功率和可达和速率随 SNR 变化的曲线。实测下来,超对角方案比纯对角方案能多压 3~5dB 的干扰功率,而复杂度几乎没有明显增长,非常能说明问题。
5. 常见问题与排查技巧实录
5.1 三个最容易逼退新手的坑
第一个坑是矩阵维度不匹配。具体表现在报错信息是 dimensions must agree,而且出现在内层循环里,你根本不知道是哪一对矩阵的问题。我的排查方法只有一个:在进入主循环之前,把 H_d、H_r、H_t、V 所有矩阵的 size 全部打印一遍,用注释标清楚它们的对应关系,花两分钟对这五分钟,能省下后半天的排查时间。
第二个坑是迭代不收敛,干扰功率曲线来回震荡。原因是步长设得太大,更新后的相位投影到单位圆上绕远了。解决办法是加一条回溯线搜索:从初始步长开始,如果这一步导致目标函数不降反升,就把步长乘以 0.5,最多回溯 20 次。这个技巧对梯度下降和流形方法都通用,我在代码里一直保留着。
第三个坑是初始点选得不好,导致算法收敛到极差的局部最优。RIS 相位优化这个子问题对初始点特别敏感,单一随机初始点很容易掉进次优陷阱。我推荐做多起点初始化:随机生成 5 组初始相位,从每组开始迭代 10 轮,选目标函数最低的一组继续跑到收敛。成本增加不大,稳定性提升非常明显。
5.2 调参经验与三条关键心得
调参时最先看的行为不是最终收敛值,而是前 10 轮迭代的下降曲线。如果曲线前几步下降很陡,后面平缓,说明问题已经稳住了,可以放心输出。如果曲线一开始就是平的,大概率是目标函数写错了,让预编码更新部分没有真正把干扰压下去,先回头看闭式解是不是取了最小特征向量。
第二个心得是关于超对角耦合系数 ε 的取值。这个值代表充分建模时单元间的耦合强度,太小(小于 0.01)退化到普通对角模型,看不出差异;太大(大于 0.5)会让整个系统接近全矩阵 RIS,但单元间在物理上根本不可能耦合那么强,结果反而失真。我在仿真里常用的是 0.1 到 0.2 这个区间,既能体现结构增益,又属于物理可实现范围。
第三个心得是要特别注意信道矩阵的随机性。如果固定一组信道把结果调好了,别高兴太早,一定要用另一组随机信道复试。我遇到过一种情况:在某组特别“幸运”的信道下,超对角方案比纯对角方案压掉了 8dB 干扰,换一组信道就只剩 2dB。后来靠 500 次蒙特卡洛平均才拿到了稳定的 3~5dB 增益。做这一行,永远别用单次仿真结论定方案好坏。
这套“预编码取最小特征子空间 + RIS 相位做流形投影”的代码我后来稍微改了一下,就搬到 RIS 辅助的认知无线电干扰抑制场景里用了。新版代码在收敛轮数、干扰泄露功率和运行时间这几项指标上的表现都在预期范围内。我个人的体会是,别指望改几个参数就能跑通所有场景,最值得花时间的反而是把信号模型和矩阵维度关系彻底捋清楚。模型理解了,换任何场景都只是改参数和边界条件的事。