简介:可重构智能表面(RIS)辅助多用户MIMO系统的无源波束成形与信息传输设计Matlab实现包,面向通信工程、电子信息及数学等专业学生,适用于课程设计、期末大作业或毕业设计。资源包共29个文件,包含23个.m主程序与仿真函数、2个.asv自动备份、1个.mat数据文件、1个Readme说明及License等,压缩包仅47KB,轻量且便于部署。已有50人学习浏览。代码采用参数化编程并附详细注释,支持Matlab2014a/2019b/2024b多版本运行,内置可直接运行的案例数据,便于调整参数以复现无源波束成形、信道估计(如SBL-GAMP、EM算法)及CVX优化等关键流程。通过动态调节RIS反射单元相位与幅度,在无需增加发射功率的前提下提升信号覆盖与传输可靠性,对研究智能超表面辅助通信、多用户MIMO资源分配具有直接参考价值。
1. 可重构智能表面辅助多用户MIMO:这个仿真包到底在算哪一步
拿到“可重构智能表面辅助多用户MIMO系统的无源波束成形和信息传输设计.zip”这类仿真包,很多人第一反应是解压后找入口文件,却面对一堆脚本不知道先打开哪个。先给结论:这类代码解决的是一个典型下行链路联合设计问题——基站用有源预编码同时服务K个单天线用户,部署在环境中的可重构智能表面(RIS)靠M个无源反射单元调整相位,把原本被遮挡、被散射的反射链路变成可控信号路径。你要做的核心计算只有一件事:怎么联合调节基站侧的有源波束成形矩阵和RIS侧的无源相移向量,让系统总频谱效率最大。对刚入门的研究生,这是进入RIS-MIMO的第一道完整阶梯;对做算法验证的工程师,这是理解信道建模、交替优化和功率分配相互耦合的最小可运行框架。下面按一条可复现的路线展开,从信道模型一路走到避坑。
2. 系统模型与信道建模:直连与级联信道的数值先把对
2.1 系统构成与仿真参数:一张表说清楚先验假设
RIS辅助多用户MIMO的模型自由度很多,参数设不对后面全是白算。我的习惯是先把坐标和距离写死:基站坐标为原点,RIS放在基站和用户簇之间偏一侧的位置,用户在RIS近场区域内随机撒点。
| 参数 | 常用值 | 说明 |
|---|---|---|
| 基站天线数 N | 4~8 | N 越大,有源波束成形的空间自由度越高 |
| 用户数 K | 2~4 | K 超过 N 后,用户间干扰会急剧上升 |
| RIS 单元数 M | 16~128 | M 决定无源波束成形的阵列增益上限 |
| 载频 fc | 2.4 GHz / 3.5 GHz | 决定波长,进而决定路径损耗参考值 |
| BS-RIS 距离 d_BR | 50 m | 反射链路的主路径 |
| RIS-用户距离 d_RU | 5~10 m | RIS 離用户越近,反射链路越强 |
| BS-用户距离 d_BU | 70~90 m | 直连链路通常比反射链路长 |
| 路径损耗指数 | 2~3.5 | 反射链路按两段独立计算 |
| 噪声功率 | -100 dBm | 带宽 10 MHz 下的典型热噪声底 |
路径损耗用参考距离 1 m 的自由空间模型乘上距离的负指数次方,即 β = (λ / 4πd₀)² · (d/d₀)^(-α),其中 d₀ 取 1 m。这是 RIS 仿真里最容易被低估的细节:反射链路要分段算,BS-RIS 算一次,RIS-用户再算一次,两部分乘起来才是级联链路的增益。有人图省事把 d_BR 和 d_RU 直接相加再用一个路径损耗算,结果是小规模下数值完全失真。
2.2 信道生成代码:瑞利衰落之外还要留好莱斯因子接口
下面这段 MATLAB 代码对应最常用的平坦瑞利衰落模型,同时在注释里留了加入莱斯因子和阵列导向矢量的位置。
% 系统参数 N = 8; % 基站天线数 K = 4; % 用户数 M = 64; % RIS 反射单元数 fc = 2.4e9; % 载频 lambda = 3e8 / fc; % 波长 P = 10^(30/10); % 基站总发射功率 30 dBm,转线性值 sigma2 = 10^(-100/10); % 噪声功率 -100 dBm,转线性值 % 距离与路径损耗(参考距离 1m) d_BR = 50; d_RU = 5; d_BU = 80; beta_BR = (lambda / (4*pi*d_BR))^2; beta_RU = (lambda / (4*pi*d_RU))^2; beta_BU = (lambda / (4*pi*d_BU))^2; % BS-RIS 信道 G:M×N 复高斯,按路径损耗缩放 G = sqrt(beta_BR) * (randn(M,N) + 1j*randn(M,N)) / sqrt(2); % RIS-用户 信道 Hr:K×M Hr = sqrt(beta_RU) * (randn(K,M) + 1j*randn(K,M)) / sqrt(2); % BS-用户 直连信道 Hd:K×N Hd = sqrt(beta_BU) * (randn(K,N) + 1j*randn(K,N)) / sqrt(2); % 如需加入莱斯 K 因子,视线分量用阵列导向矢量叠加: % a_steer = exp(1j*2*pi*(0:N-1)'*sin(phi)/lambda*dx)'; % G = sqrt(beta_BR)*( sqrt(Kfac/(Kfac+1))*a_steer*a_steer.' % + sqrt(1/(Kfac+1))*scatter_component );代码逻辑说明:这里的信道维度一定要盯死——G 是 M×N,代表从基站每个天线到 RIS 每个单元之间的复增益;Hr 是 K×M,是 RIS 每个单元到每个用户的链路;Hd 是 K×N,是基站到用户的直连。最后统一除以 sqrt(2) 是为了让复高斯变量的实部和虚部各占一半功率,保证 E[|h|²]=1,这样路径损耗系数就能独立反映距离衰减。
参数说明:d_RU 取 5 m 意味着 RIS 紧贴用户簇,这是 RIS 仿真里的典型假设——无源波束成形性能对 d_RU 极其敏感,如果用户离 RIS 超过 20 m,反射链路的贡献会肉眼可见地缩小。如果你发现仿真里 RIS 完全没带来增益,第一件事就查这三个 β 的数量级是不是合理。
2.3 等效信道与接收 SINR:把相移矩阵从信道中间抽出来
多用户系统的每个用户 k 的等效信道是直连加反射两条路径叠加:
h_k^H = h_d,k^H + h_r,k^H · Φ · G
其中 Φ = diag(θ) 是 RIS 的相移对角矩阵,θ ∈ ℂ^M 且每个元素模长为 1,G 是 BS-RIS 信道,h_r,k 是 RIS 到用户 k 的信道。发送信号 x = W s,W 是 N×K 的预编码矩阵,s 是 K×1 的数据符号。用户 k 接收:
y_k = h_k^H w_k s_k + Σ_{j≠k} h_k^H w_j s_j + n_k
对应的 SINR 表达式就是后面所有目标函数的地基:
SINR_k = |h_k^H w_k|² / (Σ_{j≠k} |h_k^H w_j|² + σ²)
仿真里最容易翻车的点藏在这个表达式的转置里:h_r,k^H Φ G w_k 要展开成 θ^T·diag(h_r,k^H)·G·w_k 的形式,才能把相移向量从级联信道里抽出来独立优化。注意这里是 θ 的转置而不是共轭转置,因为 h_r,k^H 本身已经带共轭,和 Φ = diag(θ) 相乘后,θ 以非共轭形式出现。这一小步的转置习惯决定了后面目标函数梯度的方向,错了只会让迭代越跑越偏。
3. 交替优化主循环:把预编码和相移拆成两个可解的子问题
3.1 联合设计的困难与交替优化的基本框架
直接把 W 和 θ 放进一个目标函数里求联合最优,是非凸的,没有闭合解。工程上最常用的做法是交替优化:固定 θ 求 W,再固定 W 求 θ,两个子问题交替迭代,直到总速率不再上升。这个框架本身不是新东西,但它在 RIS 场景下有一个特别的优势:两个子问题各自有成熟工具,RIS 单元数从 16 到 128 都只需要复用同一套主循环。
% 交替优化主循环 theta = exp(1j*2*pi*rand(M,1)); % 随机相移初始化 max_iter = 30; R_hist = zeros(max_iter,1); for iter = 1:max_iter % 步骤1:固定 theta,计算等效信道并更新预编码 H_eff = Hd + Hr * (diag(theta) * G); W = update_precoder(H_eff, P, sigma2, K, N); % 步骤2:固定 W,求解无源波束成形 theta [A, b] = build_theta_problem(Hd, Hr, G, W, K, M); theta = solve_theta_problem(theta, A, b, sigma2, K, M); % 记录本轮总速率 R_hist(iter) = compute_sum_rate(Hd, Hr, G, theta, W, sigma2, K); end代码逻辑说明:H_eff 的构建顺序不能改——diag(theta)*G 是先把 RIS 相移作用在 BS-RIS 信道上,再乘以 Hr 得到反射链路对每个用户的贡献,最后和 Hd 相加。update_precoder 和 solve_theta_problem 是两个独立函数,下面分别展开。
参数说明:max_iter 取 30 是因为交替优化前几步收益最大,后面往往进入平台期。初始化用随机单位模向量比全 1 向量更稳,因为全 1 相移在信道强相关时容易把系统锁在对称的次优点上。
3.2 有源预编码子问题:从 ZF 到正则化 RZF
固定 θ 之后,H_eff 变成已知的 K×N 等效信道矩阵,问题退化为传统多用户 MIMO 预编码。零迫零(ZF)在 N>K 时可用,但病态信道下会放大噪声,所以仿真里我更常用正则化 ZF(RZF),也叫 MMSE 预编码。
function W = update_precoder(H_eff, P, sigma2, K, N) % 正则化系数:低SNR时取大,高SNR时趋近于零 alpha = K * sigma2 / P; % RZF 预编码器:H' * (H H' + alpha I)^{-1} W = H_eff' / (H_eff * H_eff' + alpha * eye(K)); % 功率归一化:让 W 的总功率等于 P W = W * sqrt(P / trace(W' * W)); end代码逻辑说明:H_eff 是 K×N,H_eff' 是 N×K,中间括号里的矩阵是 K×K,求逆是每次子问题的最大计算开销。alpha 的取值直接对应信噪比:噪声大、功率小时,正则化项让预编码偏向抑制噪声而非完全迫零;P 远大于 σ² 时 alpha 退化为 0,RZF 自动变成 ZF。功率归一化是这步最容易漏的地方——如果不做 trace 归一化,下一轮无源波束成形的梯度幅度会被 W 的模长带偏,导致相移迭代不稳定。
参数说明:alpha = K·σ²/P 是经验且常用的一种设置,严格推导来自最小化均方误差的线性接收机。若你仿真的信噪比范围很大,可以让 alpha 变成可调参数而不是固定计算,观察它对高信噪比用户的影响。
3.3 把无源相移从目标函数里抽出来:预计算 A 和 b
固定 W 之后,每个用户 k 的期望信号和干扰都可以写成关于 θ 的线性函数嵌套二次形式。关键在于预先算好两组系数:
a_kj = diag(Hr(k,:)') · G · w_j ,维度 M×1 b_kj = Hd(k,:) · w_j ,标量
那么用户 k 收到来自数据流 j 的有效系数就是 θ^T a_kj + b_kj。
function [A, b] = build_theta_problem(Hd, Hr, G, W, K, M) A = zeros(M, K, K); % A(:,k,j):用户k的数据流j对应的相移线性系数 b = zeros(K, K); % b(k,j):直连部分的常数项 for k = 1:K for j = 1:K A(:,k,j) = diag(Hr(k,:)') * G * W(:,j); b(k,j) = Hd(k,:) * W(:,j); end end end代码逻辑说明:diag(Hr(k,:)') 把 1×M 向量变成 M×M 对角矩阵,再乘 G 和 w_j,得到 M×1 向量。这一步在数学上等价于把 h_k^H w_j 展开,其中 θ 作为线性因子出现。预先算好 A 和 b 的作用是让后续目标函数计算从每次重复做矩阵乘法变成直接查数组,几十个用户时看不出差别,但蒙特卡洛循环几千次后差别很明显。
参数说明:A 的三维数组结构容易记混。我的习惯是第 1 维永远是 RIS 单元下标,第 2 维是用户编号,第 3 维是数据流编号。A(:,k,j) 代表“用户 k 收到的来自数据流 j 的反射路径系数”,写注释比记脑内索引可靠得多。
3.4 无源子问题求解:极简黎曼梯度投影法
有了 A 和 b,用户 k 的 SINR 写成:
SINR_k = |θ^T a_kk + b_kk|² / (Σ_{j≠k} |θ^T a_kj + b_kj|² + σ²)
目标函数是 Sum log₂(1+SINR_k)。对 θ 求梯度时要用复 Wirtinger 导数,对 θ 的共轭方向求偏导。下面是解析梯度实现,完全没有工具箱依赖。
function g = obj_grad_theta(theta, A, b, sigma2, K, M) g = zeros(M,1); for k = 1:K f_kk = theta.' * A(:,k,k) + b(k,k); % 期望信号复数幅度 interf = sigma2; for j = 1:K if j ~= k interf = interf + abs(theta.' * A(:,k,j) + b(k,j))^2; end end % 对 score = log2(1 + |f|^2/interf) 求梯度 % 分子部分梯度:a_kk * conj(f_kk) / (interf + |f_kk|^2) % 分母部分梯度:- sum_j a_kj * conj(f_kj) / interf num_grad = A(:,k,k) * conj(f_kk) / (interf + abs(f_kk)^2); den_grad = zeros(M,1); for j = 1:K if j ~= K f_kj = theta.' * A(:,k,j) + b(k,j); den_grad = den_grad + A(:,k,j) * conj(f_kj); end end g = g + (num_grad - den_grad / interf) / log(2); end end梯度算出来后,在单位圆流形上做投影上升:先投影到切空间,再沿切方向走一步,最后归一化回到单位圆。
function theta = solve_theta_problem(theta, A, b, sigma2, K, M) mu = 0.1; % 初始步长,小步慢走更稳 for it = 1:200 g = obj_grad_theta(theta, A, b, sigma2, K, M); % 投影到切空间:去掉径向分量 g_tan = g - real(conj(theta) .* g) .* theta; theta_new = theta + mu * g_tan; % 归一化回单位圆 theta_new = theta_new ./ abs(theta_new); if norm(theta_new - theta) < 1e-5 theta = theta_new; break; end theta = theta_new; end end代码逻辑说明:obj_grad_theta 里的梯度公式不用背,理解它的结构即可——分子的梯度想把信号放大,分母的梯度想压低干扰,两者方向相反,最后的梯度是叠加结果。/ log(2) 来自对 log₂ 求导。外部循环的步长 mu 取 0.1 是为了避免目标函数在非凸地形上震荡;如果目标函数一直不涨,把 mu 减半再跑。
参数说明:200 次迭代是上限,实际在 20~50 次内基本收敛。收敛判据用的是 θ 自身的欧式距离变化而非目标函数变化,因为目标函数在平坦区域可能变化很小但 θ 还没找到真正的最优点。
3.5 更高级的路线与选型:SDR、流形工具箱、闭式解
梯度投影法够用,但不是唯一选择。SDR(半定松弛)是经典路线:把 |θ^T a + b|² 展开成关于 V = θθ^H 的线性函数,松弛掉秩一约束后用 CVX 求解,最后用高斯随机化恢复。它的优点是全局性比梯度法好,缺点是 M 超过 64 时 V 是 64×64 的半定矩阵,内点法跑一轮就要分钟级,蒙特卡洛循环里基本不现实。Manopt 工具箱的 complexcirclefactory 是更专业的流形优化实现,带 Armijo 线搜和共轭梯度,收敛速度比手写梯度快,也省去手推勒让德变换。
| 路线 | 适合规模 | 工具箱依赖 | 精度 | 每次迭代开销 |
|---|---|---|---|---|
| 闭式相移对齐 | 单用户或强干扰近似 | 无 | 中 | 极低 |
| 黎曼梯度投影 | M ≤ 512 | 无 | 高 | 低 |
| SDR + 随机化 | M ≤ 64 | CVX | 极高 | 高 |
| Manopt 流形 | M ≤ 2048 | Manopt | 极高 | 中 |
闭式解只在单用户时严格成立:用户 k 的数据流系数确定后,θ_m 的最优相位让反射项与直连项同相叠加,即 θ_m = exp(j(angle(b_kk) - angle(a_kk(m))))。多用户场景没有这种简单形式,但可以用这个闭式值作为交替优化的初始化,比随机初始化更靠近好解的区域。
4. 信息传输设计:不只调波束,还要分配功率和选择用户
4.1 功率分配:等功率是基线,注水不是银弹
预编码矩阵 W 的列范数本质上就是各用户的发射功率。上面的 RZF 代码做了整体功率归一化,但没分配——每个用户的功率是均等的。等功率是几乎所有论文的基线,因为公平性最好且实现零成本。注水功率分配在理论上能提升和速率,但多用户场景没有闭合解,需要迭代注水:每次按当前有效信道的奇异值重新分配功率,更新预编码后再算一次,循环十几轮。你的仿真包里可能已经有功率分配模块,但我的建议是先跑通等功率,确认交替优化的趋势正确,再考虑迭代注水——否则功率分配和相移更新耦合在一起,出问题很难定位。
% 等功率分配:给每个用户的数据流分到相同的功率 P_stream = P / K; % 将 RZF 的各列做列归一化,再乘上每流功率 for k = 1:K W(:,k) = W(:,k) / norm(W(:,k)) * sqrt(P_stream); end % 检查总功率:trace(W'*W) 应等于 P代码逻辑说明:这里用了列归一化而不是整体 trace 归一化。区别在于整体归一化只保证总功率正确,但不保证每列功率一致;列归一化则把每个用户的发射功率锁在 P/K。在 RIS-MIMO 场景里,用户信道差异很大,列归一化能让弱用户不至于被强用户抢走全部功率,仿真结果更稳定。
参数说明:如果你切换到迭代注水,需要每一步都重新计算 H_eff 的特征结构,注意注水目标是等效信道而非物理信道。这个细节常被忽略,导致注水效果反而不如等功率。
4.2 用户调度:RIS 增益对用户相关性极其敏感
信息传输设计里的第二件事是选谁在这个时隙被服务。K=4 固定激活是最简单的做法,但在用户全部随机撒点、有些用户离得很近的情况下,两个强相关用户的信道向量几乎平行,无源波束成形难以同时满足两边的相位对齐。这会直接拉低和速率。常见做法是贪心调度:从候选用户里逐个挑,每次都选让当前系统总速率增量最大的那个。
% 贪心用户调度伪代码:候选用户集 C,目标服务用户集 S S = []; remaining = 1:K; while length(S) < K_active best_user = 0; best_R = -inf; for k = remaining S_try = [S, k]; R_try = evaluate_sum_rate(S_try, theta, W, Hd, Hr, G); if R_try > best_R best_R = R_try; best_user = k; end end S = [S, best_user]; remaining(remaining == best_user) = []; end代码逻辑说明:evaluate_sum_rate 要重新计算选出用户集合对应的等效信道子矩阵和预编码,不能直接复用上一轮的全用户矩阵。贪心调度的复杂度是 K² 量级,K 在 4 到 10 之间完全可接受。仿真里如果你希望看到 RIS 的增益更明显,可以让 d_RU 最小的用户优先入选——离 RIS 近的用户反射链路强,调度它更能体现无源波束成形的价值。
参数说明:K_active 常用 2 或 3。K_active 越少,无源波束成形的自由度越充裕,总速率通常单调下降但公平性上升,这个折衷建议在你的仿真报告里单独画一条曲线。
4.3 速率与能量效率:瞬时、遍历和 EE 的口径别搞混
信息传输设计的最终输出通常是一组速率曲线。这里最容易犯的错是:把一次信道实现下的瞬时速度直接画成折线图,却没说明这是哪一次随实现。规范做法是先做蒙特卡洛平均——每次信道生成后运行交替优化和功率分配,记录该次总速率,循环 1000 到 5000 次后取平均值。能量效率(EE)是另一套口径:EE = R_total / (P + M·P_RIS + P_circuit),P_RIS 是每个 RIS 单元的相移功耗,典型取 5 mW 量级,P_circuit 是基站电路功耗约 10 W。
% 蒙特卡洛平均遍历速率 num_mc = 2000; R_sum = 0; for mc = 1:num_mc % 在这里生成信道 G, Hr, Hd,运行交替优化和功率分配 % R = compute_sum_rate(...) R_sum = R_sum + R; end R_avg = R_sum / num_mc;代码逻辑说明:你的仿真包里如果对每个信噪比点都跑完整蒙特卡洛,耗时主要由 SDR 或高精度流形优化决定。一个实用优化是对小规模做精确计算,对大规模只用梯度投影法——论文里如果同时报两条曲线,一定要在注释里标明各自用了什么求解器,否则别人复现时对不上数。
参数说明:蒙特卡洛循环的随机种子要每隔 200 次重设一次,防止长循环里的随机数状态漂移导致前后段不可比。很多复现踩坑最后都查到这一条。
5. RIS仿真的常见问题排查:五个必查细节
5.1 现象:交替优化的总速率不升反降
原因:无源相移更新后的 theta 没有做单位模归一化,或者预编码 W 在迭代中被整体 trace 归一化和列归一化重复施加,导致功率逐轮漂移。另一个常见原因是梯度投影里的切空间投影符号写反。
解决:在每次迭代末尾加一行断言代码,检查 abs(theta) 是否全等于 1,以及 trace(W'*W) 是否等于 P。两者都通过但速率还在掉,就得检查目标函数实现是否一致——用同一个函数去计算 R_hist 和用于梯度的值,别搞成两套口径。
5.2 现象:SDR 的结果反而比随机相移还差
原因:SDR 松弛后得到的 V 是满秩矩阵,高斯随机化只采样十几次,远不足以逼近被丢弃的秩一最优解,尤其是 M 较大时,随机化的效果完全取决于采样次数。
解决:把高斯随机化次数提高到 200 次以上,每次采样后归一化到单位模并重算目标函数,保留最高的那个。还有一个前置检查:看 V 的特征值分布,如果最大特征值与次大特征值之比小于 10,说明松弛解本身离秩一很远,这类信道下 SDR 天然不占优。
5.3 现象:加上 RIS 之后系统速率没有明显提升
原因:反射链路的路径损耗乘积远大于直连链路。例如 d_BR=100 m、d_RU=50 m 时,β_BR·β_RU 的数量级比 β_BU 小很多,RIS 再怎么调相位也只是杯水车薪。这是仿真里最常见的“没有效果”假象。
解决:检查三个 β 的相对大小。RIS 辅助系统的关键几何条件是 d_BR·d_RU 要明显小于 d_BU·d_ref 的等效关系。把 d_RU 从 50 m 改成 10 m,曲线立刻不一样。仿真报告里必须写明几何参数,否则你得到的结论对硬件实验毫无参考价值。
5.4 现象:梯度投影法在某一轮迭代后卡住,速率长期不变
原因:步长 mu 太大,越过最优点后在鞍点附近震荡;或步长太小,200 次迭代走不到盆地底部。非凸目标函数对步长极其敏感,这是典型的玄学调参区。
解决:改用回溯线搜索——每轮从 mu=0.5 开始,如果目标函数没上升就减半,直到上升为止。另外换多个随机初值跑取最优。如果换了初值曲线差异很大,说明目标函数地形很碎,这时可以考虑加大 RIS 单元数的散射随机性,让信道更“丰富”一点。
5.5 现象:蒙特卡洛跑完结果和论文对不上
原因:信道生成里的随机数种子顺序不对。很多人习惯在循环内动态生成信道,导致不同信噪比点的信道不是同一组实现,平均结果天然不可比。
解决:把信道生成移到蒙特卡洛循环外层,事先存好所有信道实现,内层循环只读取和使用。这样跑信噪比扫描时,每个信噪比点的信道集合完全一致,曲线平滑度也更好。这个坑是我复现别人论文时最深的血泪经验——对不上的原因七成在随机种子管理。
6. 验证方法与进阶方向:先跑通单用户曲线再谈扩展
收到这个仿真包,第一件事不是直接跑 K=4 的多用户结果,而是先缩到单用户做一次穷举校验。取 M=4、N=4、K=1,把每个 RIS 单元的相位限定在 QPSK 集合 {±1, ±j},穷举 4⁴=256 种相移组合,遍历后找出最大速率的那个 θ。然后把你的交替优化代码跑同一个信道实例,如果交替优化的结果差出穷举值几个百分点以上,说明代码里有 bug,修好再继续。
第二个验证点是闭式解对比:单用户情形下,用 θ_m = exp(j(angle(b_kk) - angle(a_kk(m)))) 得到的闭式相移应该和交替优化结果非常接近。两者差异可以评估梯度投影法离最优解有多远,也是一个有用的 debug 信号。
第三个必做验证是随机相移基线。把 theta 初始化为随机单位模向量并固定不迭代,测一条速率曲线,作为下界。任何迭代算法如果跑不出比这更高的速率,直接说明求解器实现有问题。
进阶方向上,这个仿真包可以往三个方向扩展:宽带 OFDM 子载波下的无源波束成形,每个子载波的相移都要协调;非理想 CSI 下的鲁棒设计,用信道估计误差的统计量来约束最小 SINR;双 RIS 协作,两个反射面之间还会形成第二条级联路径。每个方向都是把这里的交替优化框架改一步子问题求解器。
我做这类仿真初期最常犯的错就是 H_eff 和转置符号搞混,后来养成用 M=4 穷举校验的习惯,所有时间成本都花得值。希望帮到你。
本文还有配套的精品资源,点击获取