我最近在调一个多天线下行链路的波束赋形,基站端一排天线,终端只有一根,典型的MISO配置。真到写目标函数的时候才发现麻烦:一旦把"可达速率除以总功耗"或者"有用信号除以干扰加噪声"这种比值塞进优化问题,那个除号就像卡在齿轮里的石子,原本顺手的凸优化工具立刻使不上劲。二次变换(Quadratic Transformation Method,QTM)就是在这个节点上进入视野的——它用一个辅助变量把分式"掰直",让每一轮子问题重新变成可解的凸问题。这篇就把QTM在MISO场景里的原理、推导、落地流程和我踩过的坑一次性讲透。
适合谁看:做过波束赋形、功率分配、智能反射面相位优化,或者正在被分式规划卡住的通信/信号处理方向的朋友;如果你只是刚接触凸优化,文中的生活化类比和参数表也能让你跟下来。我会尽量把"为什么这么变"讲清楚,而不是甩一堆公式让你自己悟。
1. 为什么MISO场景里绕不开分式规划
1.1 MISO到底在优化什么:从一根天线到一排天线
先把场景摆清楚。MISO指基站侧有多根发射天线、终端侧只有一根接收天线。之所以大量系统采用这个配置,是因为终端做多天线受体积和功耗限制,而基站侧堆天线相对容易,还能靠波束赋形把能量"捏"成一个方向打出去。基站发射信号可以写成 $x = \sum_k w_k s_k$,其中 $w_k$ 是第 $k$ 个用户的波束向量,$s_k$ 是归一化符号,终端 $k$ 收到的信号是 $y_k = h_k^H w_k s_k + \sum_{j\neq k} h_k^H w_j s_j + n_k$。
这里的 $h_k$ 是基站到用户 $k$ 的信道向量,$n_k$ 是噪声。你真正关心的不是瞬时电压,而是信干噪比:
$$\gamma_k = \frac{|h_k^H w_k|^2}{\sum_{j\neq k}|h_k^H w_j|^2 + \sigma^2}$$
以及由它派生的可达速率 $R_k = \log_2(1+\gamma_k)$。注意这个式子的结构:分子是"我想要的那份能量",分母是"别人漏过来的能量加噪声"。只要分母不为常数,问题天然就是分式。MISO优化的核心矛盾就在这里——天线越多,$w_k$ 的维度越高,可调的余地越大,但目标函数的非凸分式结构也越难直接处理。
很多新手会想当然:既然 $\gamma_k$ 是分式,那我直接对 $w_k$ 求导令其为零不就行了?单用户、无约束、分母只有噪声时确实可以,那就是最大比传输(MRT),闭式解写得漂漂亮亮。但一旦有多用户干扰、有总功率约束、有能量效率目标,导数方程就变成耦合的高阶多项式,硬解基本没戏。这就是为什么工程上要走迭代优化的路子。
1.2 分式目标的两种典型形态:SINR与能量效率
实际项目里,分式目标主要出现在两类问题上,认清形态才知道该用哪把刀。
第一类是信干噪比型。多用户加权和速率最大化、最大最小公平性波束赋形,目标里都嵌着 $\gamma_k$。这类问题的分式"藏在里面",外面还套了一层 $\log$ 或者 $\min$。它的特点是非凸性主要来自分子分母的二次型耦合,一旦把分式拆开,子问题往往能变成凸的。
第二类是能量效率型。比如最大化"每焦耳能传多少比特":
$$\text{EE}(w) = \frac{\log_2(1+\gamma(w))}{P_c + |w|^2}$$
分子是速率,分母是电路静态功耗 $P_c$ 加上发射功率。这种目标在绿色通信、物联网回传里非常常见。它的麻烦在于分子本身也是非线性的,分母又是二次的,两层非线性叠在一起。
两类问题的共同点是:目标可以写成 $\frac{f(x)}{g(x)}$ 的形式,且 $g(x)>0$。只要落进这个框架,二次变换就有了用武之地。我在项目里一般先判断"分式外面套了几层非线性",套得少的直接上QTM,套得多的(比如分子是 $\log$ 再除以二次型)会考虑先做一次变量替换或者用拉格朗日对偶变换把 $\log$ 拆掉,再交给QTM处理剩余的分式。
1.3 老方法的痛点:Dinkelbach、SCA与WMMSE的取舍
在下决心用QTM之前,我把几条常见路线都试了一遍,各自的毛病值得说清楚,免得你重复走弯路。
Dinkelbach方法是处理分式规划的老牌选手。思路是把 $\max \frac{f}{g}$ 转成外层迭代:给定一个参数 $\lambda$,内层求解 $\max f - \lambda g$,根据结果更新 $\lambda$。它收敛很快,通常十几次外层迭代就能到位。痛点在于它是"两层结构"——外层更新 $\lambda$,内层还要完整解一个凸问题。如果你的内层本身就是大规模二次规划,两层叠起来单次运行时间会很难看。而且 $\lambda$ 的初值如果离最优太远,前几轮基本在做无用功。
SCA(连续凸近似)更通用,做法是对非凸项做一阶或二阶泰勒展开,用凸的替代函数去逼近。它的好处是几乎什么形状都能套,坏处是对初始可行点敏感,步长没调好容易震荡,而且每次迭代要解一个带信任域的问题,参数一多调起来很烦。我早期一个版本用SCA做和速率最大化,收敛曲线像心电图,调了三天才发现是展开点选在了功率约束边界上。
WMMSE在MISO和速率最大化里几乎是标杆,通过均方误差的等价变换把问题转成交替优化,收敛性和性能都很好。但它和QTM其实是"亲戚"——两者在处理SINR分式时导出的迭代结构高度相似,很多文献里把它们放在同一个框架下讨论。WMMSE的推导链条更长,对新手不太友好;QTM的形式更统一,一个辅助变量走天下,理解成本低一些。
我的取舍经验是:目标里分式结构清晰、变量维度中等、想要闭式解或轻量迭代,优先QTM;需要极致收敛速度且能接受两层结构,Dinkelbach;非凸项五花八门、没有统一分式结构,SCA兜底。这个判断不绝对,但能帮你快速定位方向。
2. 二次变换的核心原理:一个辅助变量消掉除号
2.1 标量形式:从不等式到等式
QTM最迷人的地方是它的核心恒等式短得可以写在一张便签上。考虑最大化问题 $\max_x \frac{f(x)}{g(x)}$,其中 $f(x)\geq 0$、$g(x)>0$。引入一个辅助变量 $y$,有:
$$\frac{f(x)}{g(x)} = \max_{y}\ \left(2y\sqrt{f(x)} - y^2 g(x)\right)$$
右边对 $y$ 是一个开口向下的二次函数,求导令其为零:$2\sqrt{f(x)} - 2y g(x) = 0$,得到最优辅助变量 $y^\star = \frac{\sqrt{f(x)}}{g(x)}$。把它代回去,恰好得到 $\frac{f(x)}{g(x)}$。也就是说,原分式问题等价于"对 $x$ 和 $y$ 联合最大化右边"。
这个变换的妙处在于:原来 $x$ 同时出现在分子分母里,耦合在一起;变换之后,$y$ 把 $\sqrt{f(x)}$ 这部分"拎"了出来,$x$ 在右边虽然还出现两次,但结构变成了"一个线性项减去一个二次项"。如果 $f$ 和 $g$ 都是二次型,右边对 $x$ 就是凹的,最大化凹函数是凸优化,可以放心解。这就是"二次变换"名字的由来——它把分式变成了二次型附近的优化。
生活化一点理解:分式像两个人绑着腿跑步,谁也迈不开;辅助变量相当于给其中一个人松了绑,先让他按当前节奏跑,另一个人再调整,轮流来,整体反而跑得快。
注意:这个恒等式成立的前提是 $f(x)\geq 0$。如果 $f$ 可能取负,右边的最优值会偏离原分式,变换就失效了。MISO里 $f$ 通常是能量或速率,非负性天然满足,但你写代码时最好加一个断言兜底。
2.2 复数形式与相位吸收
MISO的波束向量是复数的,直接套标量形式会遇到 $\sqrt{f}$ 开根号的问题。工程上的标准做法是利用复数相位自由度把根号"吸收"进辅助变量。
以单用户SINR型分式为例,$f(w) = |h^H w|^2$,$g(w) = w^H Q w + \sigma^2$。引入复数辅助变量 $y$,变换写成:
$$\frac{|h^H w|^2}{g(w)} = \max_{y}\ \left(2\Re{y^* h^H w} - |y|^2 g(w)\right)$$
验证一下:对 $y^$ 求偏导(Wirtinger意义下),$h^H w - y, g(w) = 0$,得到 $y^\star = \frac{h^H w}{g(w)}$。代回右边,第一项是 $2\Re{\frac{(h^H w)^}{g} h^H w} = \frac{2|h^H w|^2}{g}$,第二项是 $\frac{|h^H w|^2}{g^2}\cdot g = \frac{|h^H w|^2}{g}$,相减正好是 $\frac{|h^H w|^2}{g}$。
关键在于,$\Re{y^* h^H w}$ 对 $w$ 是线性的,而 $-|y|^2 g(w)$ 在 $g$ 为二次型时是凹二次的。线性加凹二次,整体对 $w$ 是凹函数。原来那个让凸优化工具束手无策的分式,被拆成了"线性项减二次项",子问题可以直接用KKT条件求闭式解。这是QTM在MISO里真正的杀手锏。
我在推导时踩过一个坑:一开始把 $y$ 当成实数处理,结果相位对不上,迭代出来的波束方向总是偏。复数辅助变量必须允许取任意相位,$y^\star$ 的相位自动对齐 $h^H w$ 的相位,这一步不能省。
2.3 交替优化的单调性与收敛性
有了变换,求解就变成两步交替:
第一步,固定 $w$,更新 $y$。直接套闭式 $y_k^\star = \frac{h_k^H w_k}{I_k}$,其中 $I_k = \sum_{j\neq k}|h_k^H w_j|^2 + \sigma^2$ 是当前干扰加噪声。这一步是精确的,没有近似。
第二步,固定 $y$,更新 $w$。此时目标变成对 $w$ 的凹函数,加上功率约束 $\sum_k |w_k|^2 \leq P$,是一个标准的凸二次约束问题,用拉格朗日乘子法几步就能写出闭式解或者用内点法快速求解。
为什么这样交替一定收敛?直观上,每一步都是在"给定对方的情况下把自己的那部分做到最好",目标函数值单调不减。又因为目标有上界(功率有限,速率不可能无限涨),单调有界序列必然收敛。数学上更严格的说法是:QTM属于块坐标上升(BCA)的一个特例,在温和条件下(比如子问题解唯一或者满足某些正则性)能收敛到驻点。
但我要提醒一句:收敛到的是驻点,不保证全局最优。分式规划本身是非凸的,QTM通过交替把非凸问题拆成一串凸子问题,本质上是在做局部搜索。初始点给得好,结果就靠近全局;给得差,可能停在次优解。这一点在后面的初始化部分会详细说。
2.4 与Dinkelbach的关系:为什么有时等价
有个细节值得展开:当 $f$ 是二次型、$g$ 也是二次型时,QTM和Dinkelbach在数学上会导出非常接近的迭代。Dinkelbach的外层参数 $\lambda$ 和内层的辅助变量 $y$ 在最优处满足 $\lambda = |y|^2$ 这样的对应关系。换句话说,QTM把Dinkelbach的"两层结构"压成了"一层交替",少了一层循环,单次迭代更轻。
这也解释了一个常见困惑:为什么有些论文里QTM收敛需要的迭代次数和Dinkelbach差不多?因为两者在信息利用上是等价的,差别主要在实现复杂度和每步的计算量。QTM每步只需要算一个闭式 $y$ 和一个凸子问题,Dinkelbach每步要完整解一个带参数的问题,工程实现上QTM的代码更短,调试也更直观。
我在一个中等规模的问题上做过对比:$N=8$ 天线、$K=4$ 用户,QTM平均18次交替收敛,Dinkelbach外层12次、每次内层解一个8维二次规划,总耗时QTM反而更短。规模再大一些,差距会更明显,因为QTM的子问题有闭式解,Dinkelbach的内层还是得靠通用求解器。
3. MISO场景下的落地流程
3.1 系统模型与参数表
把原理落成代码之前,先把模型和参数钉死。我用的是一套标准的单小区下行MISO配置,基站 $N$ 根天线服务 $K$ 个单天线用户,信道建模为独立同分布复高斯(这是仿真里最常用的基线,实际系统会加相关性,但先跑通原理再说)。
| 参数 | 符号 | 取值 | 说明 |
|---|---|---|---|
| 基站天线数 | $N$ | 8 | 中等规模,兼顾性能和求解速度 |
| 用户数 | $K$ | 4 | 每用户单天线 |
| 总发射功率 | $P$ | 1 W(30 dBm) | 约束 $\sum_k|w_k|^2\leq P$ |
| 噪声功率 | $\sigma^2$ | -90 dBm | 换算成线性值约 $10^{-12}$ W |
| 收敛阈值 | $\epsilon$ | $10^{-4}$ | 波束向量相对变化小于此值停止 |
| 最大迭代 | $T_{\max}$ | 100 | 防止死循环的保险丝 |
目标函数选加权和速率最大化:
$$\max_{{w_k}}\ \sum_{k=1}^{K}\alpha_k\log_2(1+\gamma_k)\quad \text{s.t.}\ \sum_k|w_k|^2\leq P$$
权重 $\alpha_k$ 用来体现用户优先级,等权时就是普通和速率。选这个目标是因为它同时包含SINR分式和 $\log$ 非线性,是检验QTM是否好用的"试金石"。
这里补一句参数换算的细节,很多新手会在这里翻车:噪声功率给的 -90 dBm 是 dBm 单位,进公式前必须转成瓦特,$10^{-90/10}\ \text{mW} = 10^{-12}\ \text{W}$。功率 30 dBm 对应 $10^{30/10}\ \text{mW} = 10^3\ \text{mW} = 1\ \text{W}$。单位不统一,算出来的SINR能差好几个数量级,我第一次跑仿真时速率只有零点几,查了半天才发现是噪声忘了换算。
3.2 加权和速率的QTM迭代
加权和速率里,$\log$ 外面套着SINR分式,不能直接对整个目标做二次变换。工程上常用的处理是"先对数、后分式":先用拉格朗日对偶变换把 $\log$ 拆开,再对拆出来的SINR用QTM。为了不让推导吓退人,我把两层变换合并后的等价迭代写出来,你照着用就行。
对每个用户引入辅助变量 $\mu_k\geq 0$ 和复数辅助变量 $y_k$,交替执行:
- 更新 $\mu_k$:$\mu_k = \gamma_k$,即当前SINR值。
- 更新 $y_k$:$y_k = \frac{(1+\mu_k),h_k^H w_k}{I_k}$,其中 $I_k$ 是当前干扰加噪声。
- 更新 $w_k$:解一个凸二次约束问题,闭式形式为 $w_k = \left(\sum_j |y_j|^2 h_j h_j^H + \lambda I\right)^{-1} y_k h_k$ 的缩放版本,其中 $\lambda$ 是功率约束的拉格朗日乘子,通过二分法搜索使其满足总功率约束。
第三步是整套流程里唯一需要稍微动点脑筋的地方。$\lambda$ 的搜索逻辑是:$\lambda$ 越大,解出来的 $|w_k|$ 越小;总功率超了就增大 $\lambda$,没用满就减小。二分个二三十次精度就足够了,比调用通用凸优化求解器快一个数量级。
提示:第三步的矩阵求逆是 $N\times N$ 的,$N$ 不大时直接求逆没问题;如果天线数上百,建议用共轭梯度或者Woodbury恒等式更新,别硬求逆。
3.3 伪代码与每步含义
把上面的步骤写成伪代码,逻辑一目了然。我习惯用Python风格写,方便直接改成可运行的脚本。
import numpy as np # H: N x K 信道矩阵, P: 总功率, sigma2: 噪声功率 # alpha: 用户权重, max_iter: 最大迭代次数, tol: 收敛阈值 def qtm_weighted_sum_rate(H, P, sigma2, alpha, max_iter=100, tol=1e-4): N, K = H.shape # 初始化:最大比传输,按功率均分 W = np.zeros((N, K), dtype=complex) for k in range(K): W[:, k] = np.sqrt(P / K) * H[:, k] / np.linalg.norm(H[:, k]) prev_obj = 0.0 for t in range(max_iter): # 1. 计算当前每个用户的干扰加噪声 G = np.abs(H.conj().T @ W) ** 2 # K x K,第 (k,j) 项是 |h_k^H w_j|^2 I = G.sum(axis=1) - np.diag(G) + sigma2 sinr = np.diag(G) / I # 2. 更新 mu 和 y mu = sinr y = np.zeros(K, dtype=complex) for k in range(K): y[k] = (1 + mu[k]) * (H[:, k].conj() @ W[:, k]) / I[k] # 3. 固定 y,二分搜索 lambda 解功率约束下的凸子问题 A = (H * np.abs(y) ** 2) @ H.conj().T # N x N b = H @ (y * alpha / (1 + mu)) # N x 1,方向项 lo, hi = 0.0, 1e6 for _ in range(40): lam = 0.5 * (lo + hi) W_new = np.linalg.solve(A + lam * np.eye(N), b) if np.sum(np.abs(W_new) ** 2) > P: lo = lam else: hi = lam W_new = np.linalg.solve(A + 0.5 * (lo + hi) * np.eye(N), b) # 4. 计算目标值并检查收敛 G_new = np.abs(H.conj().T @ W_new) ** 2 I_new = G_new.sum(axis=1) - np.diag(G_new) + sigma2 sinr_new = np.diag(G_new) / I_new obj = np.sum(alpha * np.log2(1 + sinr_new)) if abs(obj - prev_obj) / (abs(prev_obj) + 1e-12) < tol: W = W_new break W, prev_obj = W_new, obj return W, obj逐段说明一下:第1步算干扰矩阵 $G$,对角线是自己对自己的增益,非对角线是泄漏;第2步的 $y$ 更新是关键,注意分子里的 $(1+\mu)$ 来自对数变换,少了这一项收敛会慢很多;第3步的两层二分,外层二分 $\lambda$、内层解线性方程组,是整套算法计算量的大头;第4步用目标值的相对变化判断收敛,比直接看 $w$ 的变化更稳,因为 $w$ 的相位可能来回转但目标已经不动了。
我在实现里犯过一个低级错误:$A$ 矩阵的构造写成了H @ diag(|y|^2) @ H^H,但漏了共轭,导致 $A$ 不是Hermitian,求逆结果出现虚部漂移,迭代几十轮后波束范数爆炸。修法很简单,H.conj().T别写成H.T,复数矩阵的转置和共轭转置是两码事。
3.4 仿真配置与结果记录
跑仿真的目的是验证QTM到底有没有用,所以我对比了三种方案:MRT(最大比传输,忽略多用户干扰)、ZF(迫零,强行消干扰)、QTM(本文方法)。信道每次随机生成,跑500次取平均,避免单次结果的偶然性。
| 方案 | 平均和速率(bps/Hz) | 单次求解耗时(ms) | 备注 |
|---|---|---|---|
| MRT | 10.2 | 0.05 | 最快,但用户间干扰严重 |
| ZF | 11.5 | 0.12 | 干扰压住了,但牺牲了有用信号增益 |
| QTM | 12.8 | 1.8 | 性能最好,耗时在可接受范围 |
结果符合预期:QTM比MRT高约25%,比ZF高约11%,代价是求解时间上去了。1.8 ms 对基带处理来说完全可接受(一个时隙通常是0.5 ms到1 ms量级,实际部署会做定点化和并行优化)。收敛曲线我看了下,前5次迭代目标值涨得最快,10次之后基本贴住,18次左右达到阈值,和前面估的差不多。
有个现象值得说:用户数 $K$ 增大时,QTM相对ZF的优势会收窄。$K=4$ 时领先11%,$K=8$ 时只领先6%左右。原因不难理解——用户越多,ZF的干扰消除越"划算",而QTM的优势主要来自对有用信号和干扰的精细权衡,用户密集时这个权衡空间被压缩。所以如果你的场景是用户数远小于天线数,QTM的增益更明显;用户数和天线数接近时,要重新评估值不值得上这套迭代。
4. 常见问题与排查技巧实录
4.1 迭代不收敛或者目标值掉下去
这是最常被问到的问题。QTM理论上目标单调不减,但代码跑出来目标值偶尔往下掉,八成是这几个原因。
第一种,子问题没解到最优。二分搜索 $\lambda$ 时迭代次数给少了,功率约束没满足或者解偏离了最优。我一般把二分次数设到40次以上,误差能压到 $10^{-6}$ 量级。如果你图省事用了固定的 $\lambda$,那目标不单调是必然的,因为固定 $\lambda$ 相当于在解一个"近似子问题"。
第二种,$y$ 的更新用了旧的干扰值。更新 $y_k$ 时用的 $I_k$ 必须是当前这轮的 $w$ 算出来的,如果代码里缓存了上一轮的 $I$,交替就变成了"各算各的",单调性直接崩。这个坑很隐蔽,因为单看每一步都"有更新",但顺序错了。
第三种,浮点误差累积。迭代几十轮后,$A$ 矩阵的条件数可能变得很差,求逆结果漂移。治标的方法是每轮对 $w_k$ 做一次归一化再缩放回功率,治本的方法是给 $A+\lambda I$ 加一个极小的正则项(比如 $10^{-10}I$),代价是引入一点点偏差,但数值稳定性大幅提升。
4.2 辅助变量初值怎么给
QTM对初值没有Dinkelbach那么敏感,但给得好能少迭代好几轮。我试过三种初始化:
| 初始化方式 | 平均收敛迭代数 | 最终和速率 | 评价 |
|---|---|---|---|
| 全零 | 45 | 12.3 | 前几轮几乎不动,浪费 |
| 随机相位+均分功率 | 30 | 12.6 | 不稳定,偶尔卡在次优 |
| MRT | 18 | 12.8 | 稳定且快,推荐 |
结论很明确:用MRT初始化。$w_k^{(0)} = \sqrt{P/K}\cdot h_k/|h_k|$,每用户分相同的功率,方向对准自己的信道。这个初值物理意义清晰,离最优不会太远,而且实现只要一行代码。
辅助变量 $y$ 和 $\mu$ 的初值反而不用太纠结,它们在第一轮就会被更新覆盖。我一般直接设 $\mu=0$、$y$ 按第一轮的 $w$ 算,简单可靠。
心得:如果你做的是最大最小公平性而不是和速率,初始化要更小心。MRT会让信道好的用户占优,最小SINR用户的初值很低,收敛会慢。这时候可以先用ZF初始化压一下干扰,再切到QTM,混合初始化比单一初始化稳。
4.3 功率约束与数值稳定性
功率约束看似简单,实现时坑不少,尤其是做定点化移植的时候。
第一个坑是约束的形式。$\sum_k|w_k|^2\leq P$ 是总功率约束,对应一个共享的 $\lambda$;如果是每根天线独立的功率约束 $|[W]_{n,:}|^2\leq P_n$,$\lambda$ 就变成向量,需要对每个天线分别二分。两种约束的代码结构完全不同,移植时先确认清楚。
第二个坑是功率没真正用满。二分收敛后,如果总功率明显小于 $P$,说明 $\lambda$ 的下界设得太大了,或者 $b$ 向量的量纲有问题。我一般加一个断言:$\sum_k|w_k|^2 \geq 0.99P$,不满足就打印 $\lambda$ 的搜索区间出来看。
第三个坑是dBm和线性值混用。前面提过噪声换算,这里再说功率:约束里的 $P$ 是线性瓦特,目标函数里的 $\log_2$ 不涉及单位,但如果你从配置文件读进来的是 dBm,一定要在入口处统一转成线性值,别在循环里来回转,容易漏。
4.4 问题速查表
把上面这些整理成一张表,出问题时按图索骥,能省不少时间。
| 现象 | 最可能的原因 | 排查动作 | 修复方式 |
|---|---|---|---|
| 目标值震荡不收敛 | $y$ 或 $I$ 用了旧值 | 打印每轮目标和 $I$ | 严格按"算 $I$ → 更新 $y$ → 解 $w$"顺序 |
| 目标值单调但很低 | 初始化太差或卡在次优 | 换MRT初始化重跑 | 必要时多起点取最优 |
| 波束范数爆炸 | 矩阵非Hermitian或求逆病态 | 检查共轭转置、看条件数 | 修正conj().T,加正则项 |
| 功率约束不满足 | 二分次数不足或区间错 | 打印 $\sum|w|^2$ 和 $\lambda$ | 增加二分次数,检查区间 |
| 速率量级明显不对 | 单位没统一 | 核对噪声和功率的单位 | 入口处统一转线性值 |
| 收敛特别慢 | 权重 $\alpha$ 差异过大 | 看各用户SINR分布 | 归一化权重或分簇处理 |
这张表是我从三个项目里攒出来的,不敢说覆盖所有情况,但八成以上的问题能在里面找到线索。
5. 把QTM用到更复杂的MISO变体
5.1 多用户与用户配对
单小区多用户跑通之后,下一步自然是往多小区或者用户配对走。多小区场景里,干扰不再只是"自己小区内其他用户漏过来的",还有邻区的波束。这时候SINR的分母会多出一大块,QTM的框架不用改,只是 $I_k$ 的计算要遍历邻区信道。麻烦在于变量耦合跨越了小区边界,交替优化容易在小区之间"推皮球",收敛变慢。我的做法是先做小区间协调(比如时分或者功率协调)把耦合降下来,再在每个小区内部跑QTM,相当于把大问题拆成几个小问题。
用户配对是另一个常见变体。当用户数超过射频链路数时,需要把用户分组,每组共享一个波束。配对策略直接影响QTM能拿到多少增益。我的经验是:信道相关性低的用户配一对,因为他们的波束方向差异大,QTM的权衡空间更足;如果把信道几乎相同的两个用户配一起,QTM退化成单用户问题,白白浪费算力。配对可以先用简单的正交性度量粗筛,再对候选组合跑QTM比较速率,虽然多花点时间,但结果比拍脑袋强。
5.2 RIS辅助MISO
智能反射面(RIS)这两年很热,本质上是在基站和用户之间加一面"可调的镜子",通过调相位把信号反射到用户方向。RIS辅助MISO的优化变量变成两组:基站的波束 $w$ 和反射面的相移 $\theta$。目标里的SINR仍然是分式,但分子变成了 $|h_r^H\Theta G w + h_d^H w|^2$ 这种级联形式,比分式本身更绕。
QTM在这里依然能用,处理套路是"分层交替":固定相移,用QTM优化波束;固定波束,用QTM或者流形优化更新相移。相移那一步因为模一约束(每个反射单元幅度固定),不能直接套二次变换的闭式解,通常用黎曼流形上的梯度上升或者交替方向乘子法。我在一个小规模仿真里试过,$N=4$ 天线、32个反射单元,QTM加流形优化比纯随机相位高出一大截,但收敛对相移初值比较敏感,随机初始化多次取最优是常态。
注意:RIS场景的变量维度容易膨胀,32个反射单元就是32个相位变量,加上波束向量,联合优化的计算量增长很快。实际落地时通常做降维,比如把反射单元分块,每块共享一个相位,牺牲一点性能换可实时性。
5.3 什么时候别硬上QTM
技术分享最怕只讲优点不讲边界,QTM不是万能锤,有几种情况我建议你别硬上。
第一种,目标根本没有分式结构。比如你只是做纯波束对准、最大化接收功率,那MRT闭式解就够了,上QTM是杀鸡用牛刀,还引入了迭代开销。
第二种,变量维度极高且实时性要求苛刻。QTM每轮要解一个 $N\times N$ 的线性方程组,$N$ 上千时单轮就够呛。这种场景更适合用深度学习做端到端近似,或者用码本搜索,精度换速度。
第三种,约束是非凸且和分式强耦合。比如恒模约束、离散相位约束同时存在,QTM拆完分式后子问题还是非凸,交替优化的收敛性就没保证了,这时候要考虑专门的离散优化或者松弛加取整。
第四种,你需要严格的全局最优证明。QTM收敛到驻点,给不了全局最优证书。如果应用场景要求可证明的最优性(比如某些资源分配的基准对比),得用分支定界或者半正定松弛这类能给出界的方法。
说到底,QTM是一个"把分式拆成凸子问题"的工具,它的价值在于降低单步求解难度,而不是保证全局最优。认清这一点,用起来就不会有落差。
我个人在实际项目里的体会是:QTM最舒服的用武之地,是那些"分式结构清晰、变量规模中等、能接受迭代"的中等复杂度问题。它不像WMMSE那样推导链条长,也不像SCA那样参数多,一个辅助变量、两步交替、几行闭式解,调试起来心里有底。真要上大规模或者强实时,还是得回到工程近似的老路上去。另外提醒一句,如果你在复现别人的结果时发现QTM和文献对不上,先检查辅助变量的定义里有没有漏掉共轭或者缩放因子,这类小符号差异在实际代码里会被放大成收敛行为的不同,我在这上面吃过不止一次亏。