简介可重构智能表面辅助多用户多输入多输出系统的无源波束成形与信息传输设计是一套基于MATLAB的完整仿真工程面向无线通信与信号处理方向尤其适合电子信息工程、计算机科学与技术、数学与应用数学等专业学生开展课程设计、期末大作业或毕业设计。工程采用参数化编程关键参数均便于修改代码注释详细包含信道估计、稀疏贝叶斯学习、协同波束成形等核心模块同时附有案例数据可直接运行能帮助使用者快速掌握智能反射面辅助多天线系统的建模与优化流程。资源包共29个文件主体为23个m脚本并配有自动保存备份、程序输出文本、说明文档、许可证和数据集压缩包约47KB结构紧凑、分类清晰。目前已有50人学习下载所附数据与脚本可在多个MATLAB版本中稳定运行对于初学者而言是一份兼具教学意义与工程参考价值的实践资料。1. 重构智能表面为什么“被动反射”能让多用户MIMO凭空多出一维自由度第一次在 matlab 里对比 RIS 辅助多用户 MIMO 的有源链路和无源链路时我盯着仿真结果愣了很久发射功率没加、天线没加只是把一组可调反射单元从随机相位换成优化相位用户 SINR 却能明显回升。反直觉的地方在于反射面没有放大器、没有射频链路只靠相位对齐就“凭空”改写了信道。原因在于传统 MIMO 把多径当作统计损耗而 RIS 把反射路径变成可编程变量整体信道从给定的 H 变成 H(θ)。搞懂这个设计动机才能真正理解无源波束成形为什么能 work也是后面读懂代码、修改参数、做课程设计或毕业设计时最值得花时间的底层门槛。2. 从信道到目标函数无源波束成形到底在优化什么2.1 复合信道一根天线传出去却被“编辑”了两段路径RIS 辅助系统里信号从基站发出后至少走了两条路一条是基站到用户的直射路径另一条是基站到 RIS、再由 RIS 反射到用户的级联路径。RIS 本身不放大信号它只调整每个反射单元的相位让反射波在用户端尽量同相叠加。用下行链路的复基带模型来写第 k 个用户的接收信号可以表示为y_k (h_d,k h_r,k^H · diag(φ) · G) · x n_k其中 G 是基站到 RIS 的 M×Nt 维信道矩阵h_r,k 是 RIS 到第 k 个用户的 M 维信道向量h_d,k 是基站到该用户的直射信道向量φ 是 M 个反射单元的相移向量且每个元素满足 |φ_i| 1。这个式子里的 diag(φ) 是整个设计的核心它把“信道”从固定参数变成了可优化变量。在这个项目的 Generate_H.m 里这三段信道通常分别生成再组合。常见的做法是让直射路径和 RIS 级联路径都走瑞利或莱斯衰落模型再按路径损耗折算功率。示意代码大概长这样% Generate_H.m 中的信道生成思路示意 Nt 4; M 64; K 2; % 发射天线、RIS单元数、用户数 H_br sqrt(0.5) * (randn(M, Nt) 1i*randn(M, Nt)); % 基站-RIS H_ru sqrt(0.5) * (randn(K, M) 1i*randn(K, M)); % RIS-用户 H_d sqrt(0.5) * (randn(K, Nt) 1i*randn(K, Nt)); % 直射路径这里的 randn 是标准复高斯随机数sqrt(0.5) 是为了让实部虚部各占一半功率信道的总功率被归一化后续所有 SNR 仿真都在这组归一化信道上进行。你可能会问M 取 64但用户只有 2 个反射单元是不是浪费实际上 M 越大可调的相位自由度越多多用户之间的干扰就越有可能被“错开”到不同的空间方向上这正是 RIS 与普通天线阵列的差别它不新增收发链路却新增了几十个可编程相位自由度。2.2 恒模约束是第一个真正的难点无源波束成形的设计变量 φ 不是任意复向量它必须满足恒模约束每个反射单元只能改变相位不能改变幅度所以 |φ_i|² 1。这个约束看起来简单却是整个优化问题变难的根本原因。常见的目标函数有这么几类最大化加权和速率max Σ w_k log2(1 SINR_k)最小化用户间均方误差max 或 min 用户 MSE 的最大值保证最差用户 SINR 不低于某个阈值无论选哪一种目标里都会出现 φ 的二次型比如 |h_r,k^H diag(φ) G w_k|² 这一项。把它展开后φ 是以 φφ^H 的形式出现在目标里的而且所有用户通过同一个 φ 耦合在一起。因此你没法像单用户场景那样逐个相位贪心对齐必须把所有用户的信道状态信息拿到一起做联合优化。恒模约束还带来一个直接后果单位模约束的可行集是非凸的。如果直接把 φ 丢给 CVX 求解求解器根本不知道“每个元素模长为 1”该怎么处理。这也是为什么后面要做半定松弛先把非凸约束“放松”成凸约束再把丢掉的秩一约束用随机化方法补回来。2.3 为什么简单相位对齐在多用户场景失效单用户场景下RIS 的最优相移几乎可以闭式得到只要让每个反射单元的相位等于级联信道相位的负值让所有反射信号在用户端同相叠加即可。但多用户场景不是“多个单用户问题的叠加”因为同一个反射单元对用户 A 友好可能正对用户 B 制造干扰。举个例子用户 A 处在某个反射波的增强方向用户 B 恰好也在这个方向附近如果你想同时增强 A、削弱 B就需要在两个目标之间找平衡。这种平衡不是靠启发式能简单试出来的所以才需要把“所有用户的等效信道矩阵”拼在一起统一写成优化问题再用 SDR、SAA、EM 这些工具去逼近最优解。理解这一点再看项目里的 CVX_Optimal_SAA.m 和 CVX_Optimal_Simplify.m就会明白为什么它们都在围绕一个大的复矩阵做处理而不是直接调整某个相移值。3. 算法骨架半定松弛、EM 与贝叶斯估计各自管哪一段3.1 半定松弛把恒模约束拆开再补上秩一约束半定松弛SDR是处理 RIS 相位优化最经典的思路。原始问题里φ 以 φφ^H 的形式出现所以可以先构造一个矩阵 W φφ^H把问题重写成关于 W 的线性目标。但 W 必须满足两个条件一是对角元全为 1对应每个反射单元的恒模约束二是秩必须为 1对应 W 确实能分解成单个向量乘自身共轭转置。问题在于秩一约束也是非凸的。SDR 的做法是把 rank(W) 1 直接丢掉只保留“W 是半正定矩阵、对角元为 1”这两个约束。丢掉的约束虽然让问题变松弛了但换来的是一个凸的半定规划可以用 CVX 高效求解。求解完再通过高斯随机化从 W 里提取候选的 φ 向量。核心建模片段如下% CVX_Optimal_Simplify.m / CVX_Optimal_SAA.m 的相似建模 cvx_begin sdp variable W(M1, M1) hermitian semidefinite maximize(real(trace(C * W))) subject to W(M1, M1) 1; % 辅助变量块 diag(W(1:M, 1:M)) 1; % 恒模约束 W 0; % 半正定 cvx_end phi randomize_rank1(W, 500); % 高斯随机化取最优代码里 W 取 M1 维是因为目标中往往还有一个与发射功率或辅助变量相关的常数项需要把它也放进矩阵里统一求解。diag(W(1:M,1:M)) 1 对应的是“每个反射单元只转相位、不放大信号”。求解完成后randomize_rank1 会生成大量随机候选向量再从这些向量里挑出使目标函数最大且满足恒模约束的一个。随机化次数直接决定效果次数太少可能找不到足够好的秩一近似次数太多仿真时间明显变长这是 SDR 方法绕不开的代价。3.2 GAMP把估计问题拆成“输入模型输出模型”前面说的是波束成形设计而 RIS 系统里还有一个更实际的问题接收端怎么在不知道完整信道和符号的情况下恢复数据。这就要用到广义近似消息传递GAMP。GAMP 把观测模型 y A x w 中的估计问题拆成两个部分输入估计器和输出估计器。输入估计器根据 x 的先验分布比如星座点等概率分布给出当前均值估计输出估计器根据噪声模型把残差转换成下一次迭代需要的伪观测。项目里的 EstimIn.m、EstimOut.m 是这两个接口的定义AwgnEstimIn.m、CAwgnEstimIn.m、CAwgnEstimOut.m 是复高斯噪声假设下的具体实现。CA 开头的文件专门处理复数域因为无线通信的基带信号天然是复信号不能简单地把实部虚部分开处理。迭代结构可以抽象成下面这段伪代码% GAMP 主循环结构示意 for iter 1 : maxIter r y - A * xhat corr; % 伪观测残差加修正项 tau tau_obs tau_prior; % 噪声方差和后验方差之和 xhat EstIn(r, tau, prior); % 输入估计器从星座先验得到后验均值 corr EstOut(r, xhat, tau); % 输出估计器给出下一步修正 end这里 tau 的作用非常关键。tau 太小估计器会把噪声误当成信号结果符号估计剧烈抖动tau 太大估计器又偏向先验均值无法分辨星座点。GAMP 的优势在于它把高维线性估计的问题分解成多个标量估计的循环计算量远小于直接做矩阵求逆而且对大规模 M 天线和 RIS 单元数更友好。3.3 EM 在什么时候真正介入GAMP 本身假设噪声方差已知但实际系统里这个参数也是未知的。EM 算法在这里的角色就是在外层循环里不断更新这些未知超参数。典型做法是每轮 GAMP 迭代结束后根据当前的符号估计残差重新估计噪声方差M 步的更新公式本质上是在做最大似然估计。项目里的 MIMO_EM.m、MIMO_EMX.m、MIMO_EMS.m 是 EM 与不同变量组合的版本有的重点估计符号有的重点估计信道有的同时估计信道和噪声参数。SparseScaEstim.m 处理稀疏信号的收缩估计SBL_GAMP_S.m 和 SBL_GAMP_X.m 则是把稀疏贝叶斯学习与 GAMP 结合用来估计稀疏信道或者稀疏的发射符号。它们之间的关系可以这样理解SBL 负责“信道的结构”GAMP 负责“信号恢复的迭代”EM 负责“未知参数的自动更新”三者共同组成一条完整的估计链路。4. 常见问题与排查CVX 求解失败、恒模约束失效、低信噪比翻车4.1 CVX 报错或者显示 Solved 之后结果比 MMSE 还差现象cvx_status 显示 Solved但最终 BER 或 MSE 比传统 MMSE 还差看起来“优化了个寂寞”。原因SDR 丢弃秩一约束后松弛出的上界在 RIS 单元数较少或者用户空间相关较强时可能过松。另外高斯随机化样本数不足也会导致无法找到足够好的可实现向量。解决先把随机化次数从 100 提到 500 到 1000观察目标值是否还在上升。如果上升明显说明是随机化样本不够如果样本翻倍后目标值纹丝不动再检查 CVX 建模里是否把恒模约束写成了连续约束比如误用了 norm(W) 之类的写法。4.2 恒模约束悄悄失效现象仿真没有报错也能跑完但最后输出的 φ 向量里某些元素模长明显不是 1比如 0.87 或 1.13。原因很多代码在得到 SDR 解后会对 φ 做归一化处理但在计算目标函数时却沿用了未归一化的向量导致“约束只在形式上成立数值上不成立”。解决在每次迭代或随机化结束后强制加一行 phi phi ./ abs(phi);然后再代入目标函数。要注意这种后处理只能修复数值误差不能替代建模阶段对恒模约束的显式表达两者必须同时做。4.3 低信噪比下 EM 收敛到星座之外现象在 SNR 接近 0 dB 时星座估计结果既不落在 QPSK 的四个点上也不是合理的软概率分布而是偏向某个非星座点。原因很可能是接收端的输入估计器用了高斯先验而不是离散星座先验。高斯先验会让估计值落在连续复平面上EM 更新噪声方差后也不会自己修正到星座点因为先验根本没有提供“信号来自有限星座”的信息。解决检查估计链路里是否真的调用了 Constell_Modulate.m 或 Constell_Mapping.m 来生成离散先验并在输入端使用对应的估算器。如果只用了 AwgnEstimIn.m那默认假设就是高斯输入低信噪比下翻车几乎是必然的。4.4 matlab 版本兼容性问题现象在 matlab 2014a 里运行正常换到 matlab 2024b 后提示“未定义函数或变量”或者 CVX 布局报错。原因CVX 本身对 matlab 版本敏感旧版 CVX 的某些语法在新版 matlab 里已经被调整另外项目里的 .asv 文件是编辑器自动备份如果误把它当成 .m 文件运行也会出现奇怪的作用域问题。解决不要直接双击 .asv 文件以 .m 脚本为入口运行前先用 addpath 把项目目录和 CVX 目录加进搜索路径。如果条件允许用 matlab 2019b 作为折中版本它既能兼容大多数旧脚本又不会太老。4.5 随机种子不一致导致结果不可复现现象同一份代码、同一组参数跑两次得到的 MIMO_result.txt 内容差别很大却找不出代码改动。原因Generate_H.m 里用了 randn 生成信道main.m 没有在开头固定随机种子。RIS 信道矩阵只要变一点点后续的波束成形和估计结果就会完全不同这不是 bug而是随机种子的问题。解决在 main.m 的第一行加 rng(2024, twister);并把生成的信道矩阵保存到 matlab.mat。之后每次对比实验结果都从 matlab.mat 重新加载同一组信道而不是重新生成。5. 代码地图六个核心脚本分别对应哪条设计链路5.1 从 main.m 到 Generate_H.m先造一个可复现信道main.m 是整个项目的入口它的任务不是实现算法而是把所有模块串起来。通常它会先定义系统参数比如发射天线数 Nt、RIS 单元数 M、用户数 K、调制阶数、SNR、信道衰落类型然后调用 Generate_H.m 生成三段信道再依次进入波束成形优化和信号估计流程。参数化编程在这里的价值体现得最明显你要做的不是改代码逻辑而是改参数。比如想从 4 天线变 8 天线只需要修改 Nt后面的矩阵维度会自动适应想看 RIS 单元数从 32 到 128 带来的增益变化也只需要循环修改 M。Generate_H.m 的返回值决定了后续所有仿真结果所以每次实验前先确认信道是否归一化、随机种子是否固定否则后面的一切都是玄学。5.2 发射端与接收端Constell_Modulate 与星座映射Constell_Modulate.m 负责把二进制比特流映射到复平面星座点常见的是 QPSK 或 16QAM。Constell_Mapping.m 则承担反向任务把我们常见的软信息映射回星座概率。这两者是估计链路中最重要的“先验来源”。GAMP 的输入估计器必须知道发送符号来自哪个星座、每种符号概率多大否则只能把信号当连续高斯变量处理性能会损失一大截。5.3 优化链路CVX_Text.m 与 CVX_Optimal_* 脚本CVX_Optimal_Simplify.m 和 CVX_Optimal_SAA.m 都是 CVX 建模脚本。从命名方式看前者倾向于直接求解单次信道实现下的最优相移后者用样本均值近似SAA处理随机信道实现下的期望性能。两者的共同点是都围绕半定松弛建模区别在于对“信道随机性”的处理粒度。CVX_Text.m 更像是中间输出脚本用于打印或保存 CVX 的状态信息和中间矩阵。调参时建议同时打开 CVX 的 log 输出和 MIMO_result.txt确认每一次优化是“真收敛”还是“被 CVX 判定为不可行”。很多看起来像算法问题的情况实际是建模约束前后不一致。5.4 估计链路SBL_GAMP_S、SBL_GAMP_X 与 MIMO_EMSBL_GAMP_S.m 和 SBL_GAMP_X.m 负责稀疏贝叶斯学习和 GAMP 的结合一个侧重信道相关的稀疏估计一个侧重符号或状态变量的稀疏恢复。MIMO_EM.m、MIMO_EMX.m、MIMO_EMS.m 是 EM 框架下的不同变体它们的共同点是都依赖 EstimIn.m、EstimOut.m 以及 CAwgnEstimIn.m 这类基础估计器。如果只是想跑通流程主线路径并不需要全部调用这些脚本。你可以先跑一段不经过 EM 的 GAMP得到一个基线再打开 EM 更新噪声方差观察性能提升幅度。这样能清楚看到每一段代码到底贡献了多少增益而不是把它们绑在一起然后只看最后的 BER 曲线。5.5 结果回读MIMO_result.txt 与 matlab.matMIMO_result.txt 保存的是历次实验的数值结果比如不同 SNR 下的 MSE、BER、目标值或运行时间。matlab.mat 保存的是信道矩阵和中间变量方便在多次实验之间复用同一组信道。下面这张表只列最核心的文件角色避免一开始就在十几个文件里迷路文件主要角色main.m参数定义与模块调度入口Generate_H.m生成直射和 RIS 级联信道CVX_Optimal_SAA.m样本平均近似下的相移优化SBL_GAMP_S.m稀疏贝叶斯 GAMP 的信道/信号估计MIMO_EM.mEM 超参数更新与符号恢复MIMO_result.txt实验结果的持久化输出实际下载后你会发现项目里另外还有 Xestim.m、SparseScaEstim.m、CAwgnEstimOut.m 等文件。它们不是装饰而是上述主流程的“零件”。比如 Xestim.m 负责对某种未知量做整体估计SparseScaEstim.m 为稀疏信号提供收缩型的估计器。把这个零件表放进 main.m 的调用顺序里整条链路就清晰了。6. 收敛与取舍为什么设计动机比迭代次数更影响最终增益看到 SDR 能给出稳定的上界后很多人会以为“只要迭代次数足够多最终性能就会逼近上界”。实际情况并不是这样影响最终增益的主要是设计取舍。第一个取舍是松弛带来的损失。半定松弛丢掉了秩一约束高斯随机化能弥补一部分但补不回来的那部分 gap 与信道结构强相关。RIS 单元数很小时可用的相位自由度本来就少松弛边界和可实现边界之间的差距会被放大单元数增大后随机化更容易找到近似秩一的解gap 反而缩小。所以“单元数越多越好”不只是在信道增益层面成立在算法可解性层面同样成立。第二个取舍是 EM 的复杂度。EM 每轮都要更新噪声方差和其他超参数但如果初始值离真实值太远EM 会收敛到很差的局部极值。实际调试时先固定一组合理初值比如把噪声方差设成接收信号的 10%能显著提高稳定性。这与迭代次数无关而是初值设计的问题。第三个取舍是离散相位带来的工程代价。仿真里可以把 φ 当作连续变量优化但真实 RIS 硬件通常只能提供 1 位或 2 位的离散相移。把连续解量化到离散集后性能会有明显下降。因此在做课程设计或毕设时我会额外关心“连续设计到离散量化”之间的差距而不是只看理想曲线。从那以后我每次跑 RIS 相关的 matlab 仿真都会强制走一遍固定随机种子、确认恒模约束、查看 CVX 收敛状态、再用离散相位做一次量化对比这样调试出来的结果才真正能说明算法本身的优劣而不是噪声和偶然性的产物。希望帮到你。本文还有配套的精品资源点击获取