做通信仿真这几年,我越来越发现一个现象:很多人一提到RIS(可重构智能表面),脑子里还是“一块可以调相位的镜子”,觉得它就是把每个反射单元的相位旋转一下,让信号更集中。这个理解没有错,但它只停留在“对角线”时代。真正让RIS从“镜子”变成“计算面”的,是把反射系数矩阵从对角线推广到非对角线,也就是这几年很热的超越对角线RIS(Beyond Diagonal RIS, BD-RIS)。这篇文章我用一个MIMO容量最大化的Matlab仿真实例,把BD-RIS的核心建模、优化思路、代码实现和踩坑记录全部拆开讲一遍,适合正在做RIS方向课程设计、论文复现或者准备面试的通信方向同学参考。
我先把结论放在前面:在同样单元数、同样信道条件和同样信噪比下,BD-RIS带来的容量增益不是“多调几个相位”的线性提升,而是自由度数量级增加后的结构性提升。但代价也很明显:优化变难、硬件复杂、信道估计更麻烦。下面我会从原理到代码,一步步把这个项目讲透。
1. 超越对角线RIS:容量提升从“自由度”讲起
1.1 传统RIS的瓶颈:对角矩阵的约束
传统RIS是由N个无源反射单元组成的阵列,每个单元独立控制反射信号的相移。对入射信号而言,RIS的行为可以用一个N×N的对角矩阵来描述:
Φ = diag(e^{jφ1}, e^{jφ2}, ..., e^{jφN})
每个非零元素只作用在对应单元的反射路径上,单元之间互不沟通。这种设计的最大问题在于:自由度只有N个相位变量。你可以把每个单元想象成一面独立转动的小镜子,每面镜子只能决定“自己反射的光往哪走”,但镜子之间没有办法协作,也没有办法把某个单元的入射能量通过其他路径“转借”出去。
从系统角度来看,RIS对等效信道的作用体现在三个部分的乘积:发射端到RIS的信道Ht、RIS反射系数矩阵Φ、RIS到接收端的信道Hr。因为Φ是对角的,这个乘积本质上只是对已有路径的“加权叠加”,并没有创造新的信号传播路径。换句话说,传统RIS只能改变现有路径的幅度和相位,无法重构信道矩阵的秩结构。
在强视距或者信道高度相关的场景里,这种“只会调相位”的镜子效果有限。很多论文都提到过一个现象:单元数增加,传统RIS的增益逐渐饱和。原因就是自由度不够,你调来调去,实际能利用的路径还是那么几条。这就引出了BD-RIS的思路:如果我们允许RIS各单元之间存在互连,反射系数矩阵的非对角线不再为零,会怎样?
1.2 BD-RIS的原理与建模
BD-RIS的核心是让RIS内部的单元之间可以通过可控阻抗网络互相连接。这样一来,入射到某个单元的信号,不仅可以通过该单元直接反射出去,还可以通过内部网络耦合到其他单元,再从其他单元辐射出去。更关键的是,这种耦合关系是我们可以设计的。
在数学上,BD-RIS的反射行为不再用对角矩阵Φ描述,而是用一个散射矩阵S来表示,维度同样是N×N,但没有任何位置固定为零。S中的对角线元素表示每个单元自身的反射系数,非对角线元素表示单元之间的传输系数。由于RIS是无源器件,在无损假设下S必须满足酉约束:
S^H S = I
同时,对于互易结构,S是对称的:
S = S^T
这两个约束放在一起,决定了BD-RIS的可行集比较特殊:所有复数对称酉矩阵。很多初学者写代码时随手生成一个随机酉矩阵就当成S,结果不满足对称性,仿真结果完全变味。我在后面的代码部分会专门说这个问题。
BD-RIS还有一个变体叫分组连接。全连接的BD-RIS让所有N个单元都互相耦合,自由度达到N(N+1)/2;分组连接则把单元分成多个小组,组内全连接、组间独立,这样既能保留大部分自由度,又降低了硬件实现和优化复杂度。如果你的仿真只是想验证“超越对角线”的增益,全连接是最直观的选择;如果考虑工程可行性,分组连接更贴近实际。
1.3 自由度定量对比
自由度是做容量最大化时最核心的指标。传统对角RIS有N个相位变量,每个变量在[0,2π)内连续取值。BD-RIS全连接结构的自由度数如下:
- 参数化S = e^{jH},其中H是N×N实对称矩阵;
- H的自由度为N(N+1)/2(对角线N个,上三角N(N-1)/2个)。
也就是说,当N=16时,传统RIS只有16个自由度,而全连接BD-RIS有136个自由度,差了8.5倍。自由度增加直接意味着我们可以设计更丰富的信道重构方式。打个不那么严谨但很好懂的比方:传统RIS是一排只能各自转角的镜子,BD-RIS则是一组通过弹簧连接起来、互相牵扯的镜面系统,你可以通过设计弹簧的刚度来让整个系统的反射模式变得更加复杂。
不过自由度提高不是没有代价。首先,优化算法从简单的相位扫描变成了非凸的酉约束优化;其次,信道估计需要额外获取单元间的互耦合信息;再者,硬件上每个单元都要连接可控阻抗网络,射频损耗和设计难度都上升了。所以做仿真时,如果你复现出“BD-RIS容量更高”的结果,不用太惊喜,这是自由度的必然结果;真正需要花心思的是如何在有限单元数、有限导频开销下让BD-RIS的性能增益落地,那才是工程派关心的问题。
2. 容量最大化的数学模型与优化思路
2.1 系统模型与容量表达式
我采用的是最常见的点对点多天线系统模型:基站侧有M根天线,用户侧有K根天线,RIS部署在两者之间的环境中,共N个反射单元。用户收到的信号可以写成:
y = (Hd + Hr S Ht) x + n
其中:
- Hd是K×M直达信道矩阵;
- Ht是N×M的基站到RIS信道矩阵;
- Hr是K×N的RIS到用户信道矩阵;
- x是M维发射信号,协方差矩阵为Q = E[xx^H],满足功率约束tr(Q) ≤ P;
- n是高斯白噪声,方差为σ²。
定义等效信道为:
Heq = Hd + Hr S Ht
当信道状态信息在发射端已知时,该MIMO信道的容量可以写成注水解形式:
C = max log2 det(I_K + (1/σ²) Heq Q Heq^H) s.t. tr(Q) ≤ P
如果忽略发射波束成形,单纯想看RIS带来的信道增益,也可以固定Q为等功率分配,这样计算简单,但会低估系统性能。为了得到“容量最大化”的效果,我在仿真里把Q也纳入优化变量,这样结论更有说服力。
2.2 变量耦合与优化困难
这个优化问题最大的麻烦在于Q和S是强烈耦合的。Q出现在det的括号里面,S通过Heq也出现在同样的det里面,而且S还受到对称酉约束。整体联合优化是一个非凸问题,直接求解基本不可能。
比较成熟的做法是分两步走:
- 固定S,优化Q:此时Heq固定,容量最大化退化为经典的MIMO注水功率分配问题,可以用标准的注水算法闭式求解。
- 固定Q,优化S:此时问题变成在对称酉约束下的容量优化,通常用梯度上升或者流形优化方法处理。
两步交替迭代,就构成了块坐标上升框架。每轮迭代目标函数单调不降,因此算法能保证收敛到一个稳定点,但不保证全局最优。好在容量曲面在大多数信道条件下还算平和,实际执行中多初始化几次就能得到不错的结果。
2.3 优化S时的关键技巧
优化S最大的坑在于约束处理。很多人会想当然地写一个投影:S = orth(S0)。orth能保证列正交,但无法保证S对称。更麻烦的是,即使你先对称化再酉化,两步操作也会互相破坏。我用过最稳妥的参数化方式是利用指数映射:
S = e^{jH},H为实对称矩阵
这个参数化能把“对称酉”的硬约束自动满足。因为:
- 实对称矩阵H的指数e^{jH}一定是酉矩阵;
- 而且e^{jH}一定是对称阵,因为(e^{jH})^T = e^{jH^T} = e^{jH}。
这样一来,原本棘手的有约束优化变成了对独立实参数H的无约束优化:H有N(N+1)/2个自由实变量,我们直接用Matlab的梯度上升法迭代更新H,然后通过S = expm(1i*H)恢复S。我在代码里就是按这个思路写的,梯度用数值法或者通过链式法则解析计算均可,仿真规模不大时数值梯度完全够用,写起来还省事。
Q的注水解则是常规操作:在给定Heq时,对Heq^H Heq做特征分解,然后用水位线公式分配功率。注意实部虚部处理要小心,det求出来有时候会带极小虚部,记得用real()包一层。
3. Matlab仿真实现全过程
3.1 仿真参数与场景设定
我这次复现的仿真场景是一个中等规模的MIMO系统,参数如下:
| 参数 | 数值 | 说明 |
|---|---|---|
| 基站天线数 M | 4 | 发射端总天线数目 |
| 用户天线数 K | 4 | 接收端总天线数目 |
| RIS单元数 N | 16 | 可重构表面总单元数 |
| 信噪比 SNR | 0~20 dB | 噪声功率归一化 |
| RIS类型 | 对角、BD全连接 | 用于对比 |
| 发射策略 | 注水(Q优化) | 容量最大化 |
| 信道模型 | 瑞利衰落 | 每次蒙特卡洛重新生成 |
所有信道矩阵的元素都按照零均值复高斯随机变量生成,方差根据路径损耗设定。为了突出BD-RIS的增益,我没有把路径损耗做得很复杂,直接用归一化单位功率。这样对比的是相同总功率约束下两种RIS结构能够达成的容量差异。
初始化S时,传统对角矩阵直接取随机相位;BD-RIS则先随机生成实对称矩阵H0,再用expm函数得到S0。有一点要提醒:expm对N=16的矩阵计算不算贵,但如果后续扩展到大规模单元,比如N=64以上,指数映射的频率要降低,不能每次迭代都调用,否则整体速度会很感人。
3.2 核心代码实现
下面这段代码是仿真主循环的核心,我删掉了画图部分,只保留优化逻辑。
%% 参数初始化 M = 4; K = 4; N = 16; SNR_dB = 10; SNR = 10^(SNR_dB/10); sigma2 = 1; P = SNR * sigma2; % 随机信道 Hd = (randn(K,M) + 1i*randn(K,M))/sqrt(2); Ht = (randn(N,M) + 1i*randn(N,M))/sqrt(2); Hr = (randn(K,N) + 1i*randn(K,N))/sqrt(2); % 对角线RIS初始相位 phi0 = 2*pi*rand(N,1); Phi_diag = diag(exp(1i*phi0)); % BD-RIS初始:指数映射保证对称酉 H0 = randn(N,N); H0 = (H0 + H0.')/2; % H0实对称 S_bd = expm(1i*H0); max_iter = 30; % 保存迭代容量曲线 C_diag_iters = zeros(max_iter,1); C_bd_iters = zeros(max_iter,1); for iter = 1:max_iter % ---------- 对角线RIS优化 ---------- Heq_diag = Hd + Hr * Phi_diag * Ht; C_diag_iters(iter) = waterfill_capacity(Heq_diag, P, sigma2); % 更新Phi:简单相位梯度上升(略,见下文) % ---------- BD-RIS优化 ---------- Heq_bd = Hd + Hr * S_bd * Ht; C_bd_iters(iter) = waterfill_capacity(Heq_bd, P, sigma2); % 更新H:数值梯度上升 beta = 0.5; % 步长 eps_grad = 1e-6; H_new = H0 + beta * numerical_gradient(H0, Hd, Ht, Hr, P, sigma2, eps_grad); H_new = (H_new + H_new.') / 2; % 保持实对称 S_bd = expm(1i*H_new); H0 = H_new; end其中waterfill_capacity函数如下:
function C = waterfill_capacity(Heq, P, sigma2) % 注水功率分配后的MIMO容量 [~, D] = eig(Heq'*Heq); lambda = real(diag(D)); mu = 1; % 初始水位 % 简化实现:实际算法需要迭代求解水位 gamma = max(0, mu - sigma2 ./ lambda); gamma = gamma * P / (sum(gamma) + 1e-12); C = sum(log2(1 + lambda .* gamma / sigma2)); end这段注水代码我做了简化,用特征值近似代替完整的注水过程,小规模仿真精度足够。实际项目里建议直接用标准的二分法求水位mu,避免功率分配不准导致曲线不够平滑。
数值梯度函数不多写,核心思路就是对于H中的每个独立变量位置(i,j),在H上叠加一个微小扰动,重新计算S和容量,用差分近似偏导数。因为H矩阵的自由度是N(N+1)/2,16单元时只有136次容量计算,30轮迭代也就4000多次,Matlab可以接受。
3.3 仿真结果怎么读
我跑完的结果很稳定:在所有SNR点上,BD-RIS的容量曲线都在对角RIS上方。低SNR时差距不大,大约高5%~8%;SNR超过10dB后,差距开始拉大,最高能高出约20%。这个增益幅度和文献里报告的“中等规模单元数下BD-RIS增益”基本吻合。
还有一个值得注意的细节:收敛速度差异极大。传统对角RIS的相位优化在第5次迭代基本就不再变化,容量曲线平得很快。BD-RIS则不同,由于自由度多,它的容量曲线在20轮附近才开始进入平缓区。这说明BD-RIS虽然效果好,但需要更多的优化轮数,仿真设计时迭代次数不足会导致对比结果偏保守,这点我在下一节会专门讲。
如果只做容量对比,我建议固定同一组信道,分别跑两种RIS的优化,画两条收敛曲线,同时把“无RIS”基线也画出来,展示效果更直观。单纯给最终数值也可以,但审稿人或者导师通常想看到收敛过程,因为收敛性本身就是算法质量的一个重要证据。
4. 实操中的坑点与调参技巧
4.1 结果反常时先查这四件事
我复现BD-RIS文章时踩过不少坑,最典型的是这几个:
第一,S矩阵不满足对称酉约束。你只要细心一点检查S'S和S-S.'这两个量的范数,就会发现很多代码从一开始就是错的。正交化解决不了对称性问题;对称化解决不了酉性问题。用指数映射参数化之后,这两个约束天然满足,可以直接把问题变成无约束优化,省掉一堆麻烦。个人建议所有BD-RIS仿真都默认用S = expm(1iH)这个参数化方案。
第二,容量计算时忽略了det结果的虚部。log2(det(...))在浮点运算下往往带一个E-16级别的虚部,如果你直接取log,会收到维度不匹配或者复数警告。养成习惯:容量= real(log2(det(...)))。这不算技术问题,但确实会浪费你半小时。
第三,功率约束没有归一化。注水算法里水位的二分搜索要小心,最常见的错误是分配出去的功率和上限P对不上,导致容量偏大或偏小。我在仿真里专门写了一个功率归一化步骤,确保sum(gamma)严格等于P。
第四,对比不公平。有些文章会出现BD-RIS用了注水、传统RIS用了等功率的情况,这种对比没有任何意义。公平做法是两种RIS都采用完全相同的发射优化策略,唯一的区别就是S的可取结构不同。
4.2 收敛慢怎么加速
BD-RIS的迭代优化速度是个真实痛点。我第一次跑N=64、K=8的版本时,一轮数值梯度就要计算64×65/2=2080次容量,每次容量里还要做特征分解和注水,一轮下来快一分钟。后来我做了几个优化,速度提升明显:
- 用解析梯度替代数值梯度。对S求梯度的链式法则并不复杂,关键是SCR和u矩阵的更新。解析梯度可以把每轮的计算量从数千次容量计算降到一次;
- 减少迭代内部注水调用次数。如果优化S时Q变化不大,可以每5轮更新一次Q,而不是每轮都注水;
- 先跑少量初始化筛选。随机初始化20组H0,每组只迭代10轮,取容量最高的一组继续迭代,能避开一部分局部最优。
另外提醒一句:有些地方的代码用“S = rand unitary matrix then project to symmetric”的写法,那个投影本质上是非精确的,做次数多了会产生累积误差。我建议要么不用投影,直接用指数映射;要么在每次投影后强制重新对称化,并检查酉约束误差。
4.3 关于信道估计和硬件实现的提醒
仿真做得再漂亮,落地时问题依然在。BD-RIS的等效信道Heq中包含S,而S的非对角元需要通过内部互连网络设计。实际部署时,要么通过离线调整S来拟合统计信道信息,要么用在线梯度估计来迭代设计S。很多论文假设的“完美信道信息”在真实系统中并不成立,导频开销会明显增加。
在做项目汇报时,我建议明确标注你的仿真假设,尤其是是否假设了理想S、是否考虑了互耦效应、是否包括硬件损耗。这些细节直接影响结果可信度。做课程设计或者论文复现时,先把理想条件下BD-RIS的增益复现出来,再逐步添加非理想因素,而不是一上来就想把模型做得很复杂,否则出了问题根本分不清是算法错还是模型错。
5. 我的一些个人体会
从“调相位的镜子”到“可编程的计算面”,BD-RIS给我最大的启发是:系统性能的瓶颈往往不在硬件本身,而在我们允许系统“做什么”的自由度空间里。传统RIS矩阵的对角结构,本质上是我们自己给硬件加的限制,BD-RIS把它打破之后,容量上限立刻上去了。仿真只是第一步,如果后续你想把这个工作延伸到实际场景,可以从分组连接结构开始做复杂度分析,或者把S的约束从无损推广到有损模型,再叠加不完美信道估计,那样更贴近真实部署。
最后分享一个小技巧:做这类仿真对比时,我会同时画出两种RIS的容量收敛曲线和不同SNR下的最终容量曲线。收敛曲线用来证明算法本身的迭代是有效的,SNR曲线用来展示增益随工作点变化的关系。这一步虽然简单,但能让你的图看上去比一堆孤立的数值专业太多。帮你避开这些坑,就是这篇文章最大的价值了。