1. 问题建模思路:先把“覆盖率”变成一个能被算法优化的数学对象
1.1 基站覆盖率优化为什么是个“一眼看不透”的难题
做LTE网络规划的朋友都知道,基站位置选得好不好,直接决定了覆盖、容量和干扰这三本账。尤其是室外宏基站,站址一旦定了,后期再想去挪位置,牵扯到物业、传输、天面协调,代价极高。所以在规划阶段就尽量把覆盖率做上去,是性价比最高的做法。
但这里面有个尴尬的现实:基站覆盖率问题从数学上看,是一个典型的非凸、多峰、带约束的组合优化问题。基站数量和位置是离散与连续混合的变量,覆盖效果又和地形、传播环境、频率、天线倾角搅在一起。你很难用常规梯度方法去优化,因为目标函数根本不光滑,甚至很多格点覆盖不覆盖是“跳变”的。稍微换一组站址,覆盖率可能从85%掉到70%。传统的遍历搜索更不可行——在一个2km×2km的城区里,放10个站,位置组合的空间基本上是天文数字。
这时候工程上普遍的做法,就是用群体智能算法去逼近最优解。粒子群优化(PSO)是这个领域的老熟人了,原理简单、实现容易、收敛也快。但做过的同学应该深有体会:标准PSO在这个问题上特别容易早熟,粒子飞到一定阶段就全挤在某个局部峰附近,覆盖率锁定在82%左右再也上不去。原因在于标准PSO靠速度更新,粒子的搜索轨迹受惯性权重和学习因子约束,一旦所有粒子的个体最优和全局最优都趋于一致,速度就会迅速衰减,群体失去探索能力。
我最初复现这个题目时,用的就是标准PSO,结果在多个随机初值下,最终覆盖率一直稳定在一个不太理想的值域。后来才意识到,不是问题本身没得优化,而是算法的逃逸能力不够。这也是为什么后来的版本里,我换成了量子粒子群优化(QPSO)并在其中引入柯西分布策略的原因。
1.2 为什么选量子粒子群优化这条技术路线
标准PSO的困境,本质上来自它的“轨道模型”——粒子像经典力学中的小球,在解空间里沿速度方向运动。量子粒子群优化(QPSO)换了个思路:粒子不再有明确的速度向量,而是由一个量子波函数来描述,位置通过围绕某个吸引子的概率采样得到。这样一来,粒子可以在解空间的很大范围内保持“不确定性”,理论上不存在速度为零导致的停滞问题,全局搜索能力更强。
但QPSO也不是银弹。它有两个软肋:一是随着迭代推进,收缩扩张系数会让种群逐步收敛,如果陷入局部最优,想跳出来同样需要外部扰动;二是它的随机采样用的是指数分布,产生的扰动量级在后期偏小,一旦粒子群聚拢,步长不足以跨出局部盆地。
所以这个题目里的“柯西分布”改良就有了明确的目标:利用柯西分布重尾的特性,在算法后期仍然有一定概率产生大幅度的随机扰动,把粒子从局部最优附近“踹出去”,同时保留QPSO收敛快、参数少、全局性好的底子。整条技术路线可以概括成四个字:重尾逃逸。
我后面会详细拆解这个改进怎么落到Matlab代码里,以及我在复现过程中踩过的坑。先把模型说清楚,因为算法再强,靶子画歪了也白搭。
2. 覆盖率问题建模:先有精准的靶子,才能谈算法
2.1 覆盖区域网格化与传播模型
要做覆盖率优化,第一步是定义“覆盖率”到底怎么算。我用的方案是均匀网格化:把整个规划区域划分成等间隔的格点,每个格点看作一个潜在用户位置,然后计算每个格点收到的参考信号接收功率(RSRP),如果某个格点收到的最大RSRP高于设定阈值,就认为这个格点被覆盖。
网格粒度直接影响算法的计算量和精度。我在复现中把研究区域设为2km×2km的正方形区域,网格间隔选50m,这样一共有41×41=1681个格点。这个粒度在工程上够用,算起来也快。如果网格缩到25m,格点会膨胀到6889个,覆盖率计算一次虽然也能跑,但算法要做几百上千次适应度评估,总耗时立刻上去了。所以建议做学术复现时先用50m粒度验证算法逻辑,再按需加密。
传播模型我用的是Cost231-Hata扩展模型,适用于2GHz频段、城市宏蜂窝场景。路径损耗公式如下:
PL = 46.3 + 33.9×log10(f) − 13.82×log10(hb) − a(hm) + (44.9 − 6.55×log10(hb))×log10(d) + Cm
其中f为频率(MHz),hb为基站天线高度(m),hm为终端天线高度(m),d为基站到终端的距离(km),Cm为城市修正因子(大城市约3dB)。a(hm)是移动台高度修正因子,在2GHz、大城市环境下近似为:
a(hm) = 3.2×(log10(11.75×hm))² − 4.97
我建模时用的参数是:f=2000MHz,hb=35m,hm=1.5m,那么a(hm)算出来大约是0.33dB。基站发射功率Pt取43dBm,天线增益Gt取17dBi,线缆损耗取2dB。覆盖阈值设为RSRP ≥ −105dBm,这是LTE网络规划的常见标准。
在距离d很小的地方,传播模型会出现log10(d)为负无穷的异常,所以我在代码里给d加了保护,最小值不小于50m。这个细节别看小,不加的话,靠近基站的格点覆盖会算出离谱的负无穷结果,直接污染适应度。
2.2 目标函数与约束条件的设计细节
网格点和传播模型定下来后,某个基站部署方案对应的覆盖率就可以计算了。计算路径是:遍历所有基站,对每个网格点计算各基站到达该点的RSRP,取最大值作为有效接收电平,然后和阈值比较。如果某个格点被至少一个基站覆盖,就标记为覆盖格点。
覆盖率Coverage就是:
Coverage = 覆盖格点数 / 总格点数
这个指标本身是越大越好,但群体智能算法习惯处理最小化问题,我一般做一步转换,定义优化目标为未覆盖率:
Fitness = 1 − Coverage
让算法去最小化这个Fitness值,逻辑上更顺,画收敛曲线时也是单调下降的趋势,和文献里的习惯一致。
约束条件的处理同样关键。这个题目里主要有三类约束:
一是基站数量固定:假设规划区内部署N个宏基站,这个N在优化过程中不变,只优化它们的位置。位置变量用(x, y)坐标表示,维度就是2N维。
二是边界约束:基站必须落在规划区域内,不允许漂到区域外面。我在代码里用上下界绑定变量维度,每个维度的范围都是[0, 2000]。
三是最小站间距约束:工程上基站太近会造成严重干扰,我设置LTE宏站的最小站间距为300m。这个约束在基础版实现里不好直接塞进适应度函数,因为一旦当惩罚项用,需要人工调惩罚系数,很容易把目标函数搞失真。我后来采用的处理方式是:在适应度函数里增加一个轻微的惩罚项,一旦两个基站距离小于300m,就在未覆盖率基础上加上一个惩罚增量,让算法主动远离这种方案。
目标函数、网格化、传播模型这三位一体弄清楚了,后面的算法才有发挥空间。很多人在这一步图省事,直接把覆盖率的计算公式简化成“距离小于某个半径就算覆盖”,这在对比算法优劣时问题不大,但如果要把绝对数值拿出来说事,和真实规划对不上,就站不住脚了。
3. 算法内核拆解:量子粒子群凭什么比经典粒子群强
3.1 经典粒子群优化(PSO)的两个致命弱点
聊QPSO之前,必须先说清楚它的父亲——PSO——是怎么运作的,否则后面所有改进都像空中楼阁。
标准PSO里,每个粒子的状态由位置和速度两个向量组成。迭代过程中,粒子根据两个“榜样”来更新速度:一个是自己的历史最优位置pBest,一个是整个群体的全局最优位置gBest。更新公式是:
v(t+1) = w×v(t) + c1×r1×(pBest − x(t)) + c2×r2×(gBest − x(t))
x(t+1) = x(t) + v(t+1)
w是惯性权重,c1、c2是学习因子,r1、r2是(0,1)随机数。
这个模型在中小规模问题上很管用,但它有两个先天缺陷。第一个缺陷是参数敏感:w、c1、c2的搭配非常影响收敛行为,调参调得人想摔键盘。设置的w太大,粒子像无头苍蝇;w太小,又收敛太快,直接困在局部。第二个缺陷更致命:当所有粒子的速度都因为惯性衰减和学习项趋同而变得很小时,整个种群就失去了多样性。一旦此时gBest落在局部最优附近的盆地,粒子再怎么飞也飞不出去。
我在跑LTE覆盖率问题时,标准PSO的表现可以概括为“前半程猛如虎,后半程原地杵”。前50次迭代覆盖率就冲到一个水平,后面两三百次迭代几乎纹丝不动。这不是个例,是这个算法本质决定的。
3.2 量子粒子群优化的力学模型与位置更新公式
QPSO一上来就把“速度”这个概念扔掉了。它的思想来自量子力学中的束缚态模型:粒子在量子空间中运动,没有办法同时确定精确位置和动量,只能用波函数来描述它出现的概率分布。在优化问题中,每个粒子被一个“势阱”吸引,势阱中心是它自己的pBest和全局gBest共同决定的一个吸引子位置P,粒子以这个吸引子为均值、以与平均最好位置的距离为尺度,以一定的概率密度出现在周围,然后再套一个概率阈值来决定具体位置。
先算平均最好位置mbest,这是QPSO特有的概念:
mbest = (1/N) × Σ pBest_i
它的物理含义是种群整体的平均水平,用来衡量当前粒子们“历史最佳状态的质心”。这个量在更新公式里起到一个参照系的作用,让粒子的采样范围不会只依赖单个个体信息,而是带着群体统计特征。
然后对每个粒子计算吸引子:
P_i = φ×pBest_i + (1−φ)×gBest
其中φ是(0,1)均匀分布的随机数。这个式子可以理解成“动摇摆舞”:粒子在向自己的历史最优靠近和向群体最优靠近之间随机偏向,φ决定了偏心的程度。
最后是位置更新,核心公式:
x_i(t+1) = P_i ± β × |mbest − x_i(t)| × ln(1/u)
u是(0,1)均匀随机数,β是收缩扩张系数。正负号以0.5概率随机选择,这相当于量子力学中的“隧穿”行为:粒子既可能向吸引子靠拢,也可能远离吸引子,保持种群发散能力。
从这个公式可以明显看到,QPSO没有速度、没有惯性权重、没有学习因子,全局参数只有一个β。这就是它最招人喜欢的地方——参数大幅度减少,算法鲁棒性天然地好一点。
β怎么设?我用的经验策略是线性递减:迭代初期β=1.0,鼓励大步探索;迭代末期β=0.5,加强收敛。具体公式是:
β(t) = 1.0 − (1.0 − 0.5) × (t / MaxIteration)
如果MaxIteration取400,那么前期的粒子的搜索范围相对较大,后期逐步收紧。这个设计思路和模拟退火的降温过程很像,核心就是“先探索,后开发”。
3.3 收缩扩张系数与算法收敛性的关系
QPSO的收敛行为几乎完全由β决定,这一点和PSO需要调三个参数相比是巨大优势。但β也绝不是随便设个固定值就行的。
如果β整个迭代过程都固定在1.0,粒子到后期仍然大步跳动,收敛性很差,适应度曲线会呈现出明显的锯齿状,最后一两百次迭代总是在一个区间内上下震荡,找不到稳定的精细解。如果β一开始就给得很小,比如0.3,那算法搜索范围太窄,粒子全部挤在一起,很快失去探索能力,结果甚至不如标准PSO。
所以我强烈建议,复现QPSO时第一件事就是实现β的线性递减策略,先跑通,再考虑是否引入自适应β方案。从结果来看,线性递减在LTE覆盖问题上表现已经很稳,没有必要一开始就把方案搞得很复杂。
这里额外提一个我在实验里发现的现象:mbest的本质是“群体历史最优的平均”,当种群中大部分粒子都已经收敛到相近位置时,mbest与粒子位置的距离会自然减小,ln(1/u)这个项即使产生大数,乘以一个很小的距离尺度后,实际步长也有限。这就是QPSO后期依然可能陷入局部最优的机制原因——所以,柯西分布的引入就有了精准的靶向目标。
4. 柯西分布改良:把“逃逸能力”焊死在算法里
4.1 柯西分布的长尾特性为什么适合优化
柯西分布在概率论里是个特立独行的存在,它的概率密度函数是:
f(x) = 1 / (π×γ×(1 + ((x−x0)/γ)²))
这个分布最特别的地方是数学期望不存在,方差无穷大,尾巴比高斯分布厚得多。什么意思呢?用大白话说:柯西分布产生大数值随机数的概率,远高于高斯分布和指数分布。对于优化算法,这就是“偶尔来一记猛跳”的理想特性。
对比一下更直观:标准正态分布生成的值落在±3之外的频率很低,一千万次采样里也没多少个;但标准柯西分布落在±3甚至±10之外是稀松平常的事。你可能会担心,这么夸张的重尾会不会把好不容易收敛的粒子又弹飞?担心有一定道理,所以柯西扰动的使用方式很讲究,关键在于把长尾用在全局最优解附近做勘探,而不是对每个粒子无差别乱踢。
我在这个题目里的做法是:每轮迭代中,以一定概率(比如30%)对当前全局最优解gBest施加一次柯西扰动,生成一个候选解gBest_cauchy,如果它的适应度比原gBest更好,就替换掉。由于柯西分布偶尔会给出很大的扰动步长,一旦局部最优周围的“平地”不够平坦,这个探索更容易发现旁边的更深山谷。
4.2 三种柯西引入方式与我的最终选型
复现文献时,我发现柯西分布融入QPSO并没有唯一标准,常见的有三种方式。
第一种是替代随机采样项:把QPSO更新公式里的ln(1/u)替换成柯西随机数C(0,1),即:
x_i(t+1) = P_i ± β × |mbest − x_i(t)| × C(0,1)
这种改动直接改变了粒子的采样步长分布,重尾效应体现在每个粒子每一代的更新里。好处是全员都有逃逸机会,坏处是扰动过于频繁,收敛后期可能不够精细,覆盖率结果波动大。
第二种是对全局最优施加柯西变异:如前面所说,只对gBest做扰动。这种方式更温和,把重尾的探索集中在当前最有希望的位置周围,不会破坏粒子们已有的收敛趋势。我在实际测试中,这种方式的收敛曲线最平滑,最终覆盖率也最高。
第三种是对柯西分布的自适应尺度调整:随着迭代次数增加,让柯西扰动的尺度因子逐渐缩小,前期大范围探索,后期小幅修精。这种方式理论上最优雅,但多引入一个超参数,需要调适。对于这个题目,收益比不高,我没有作为主方案。
我最终采用的是第二种,对gBest施加柯西变异,而且把扰动尺度与问题边界挂钩:scale = 0.1×(ub−lb),即变量范围的10%。干扰频率设为每轮30%概率触发一次。下面给出Matlab里的生成函数和变异逻辑,这部分是代码里的核心细节之一。
4.3 高斯变异与柯西变异:为什么长尾赢了
很多人在改进QPSO时第一反应是加高斯扰动,毕竟高斯分布应用面广、写起来也简单。我在对比实验里把高斯变异和柯西变异都跑了一遍,结论非常鲜明:高斯变异对最终覆盖率的提升帮助很小,柯西变异能明显跳出局部最优,两者差距在多个随机初值上都能稳定复现。
原因可以这么理解:高斯分布的扰动绝大多数集中在均值附近的小步长区域,它解决的问题是“细微修精”,而不是“跳出困局”;柯西分布的重尾则保证了即使粒子群已经收缩得比较紧,仍然有非零概率产生一次能够跨越局部盆地的大步长扰动。对这个覆盖率优化问题来说,真正的瓶颈往往就是那一次关键跨越,所以柯西的长尾恰恰打在痛点上了。
5. Matlab落地实现:从公式到跑得通的代码
5.1 数据结构与覆盖率适应度函数设计
Matlab实现这个题目,我建议代码按照“主脚本 + 函数文件”的结构组织,避免把所有逻辑堆在一个文件里。至少需要三个函数:覆盖率计算函数、柯西随机数生成函数、主算法脚本。这样后面做对比实验时,只需在主脚本里切换算法,覆盖率函数完全复用,省时省心。
覆盖率计算函数是整套代码的地基。我给出一段核心逻辑,参数设置参考前面2.1节的内容:
function fitness = evalCoverage(BS_pos) % 规划区参数 L = 2000; % 区域边长,单位m grid_step = 50; % 网格粒度,单位m grid_x = 0:grid_step:L; grid_y = 0:grid_step:L; [X, Y] = meshgrid(grid_x, grid_y); totalPoints = numel(X); % 传播与基站参数 f = 2000; % 频率MHz hb = 35; % 基站高度m hm = 1.5; % 终端高度m Pt = 43; % 发射功率dBm Gt = 17; % 天线增益dBi cableLoss = 2; % 附加损耗dB threshold = -105; % RSRP覆盖阈值dBm Cm = 3; % 城市修正因子dB % 移动台高度修正 a_hm = 3.2*(log10(11.75*hm))^2 - 4.97; covered = zeros(size(X)); for k = 1:size(BS_pos, 1) d1 = sqrt((X - BS_pos(k,1)).^2 + (Y - BS_pos(k,2)).^2); d = max(d1, 50) / 1000; % 转km并加距离保护 PL = 46.3 + 33.9*log10(f) - 13.82*log10(hb) - a_hm ... + (44.9 - 6.55*log10(hb))*log10(d) + Cm; RSRP = Pt + Gt - PL - cableLoss; covered = covered | (RSRP >= threshold); % 任一基站覆盖即算覆盖 end coverage = sum(covered(:)) / totalPoints; fitness = 1 - coverage; % 最小化未覆盖率 end这段代码有几点值得注意。第一,我用的是“任一基站覆盖即覆盖格点”的硬判定,这是基础版本的做法。第二,距离保护max(d, 50)非常关键,没有它,基站位置附近距离接近0时要出负无穷的对数,RSRP算出来是正无穷,整个矩阵都会脏掉。第三,meshgrid生成的网格尺寸不小,每调用一次函数都要遍历所有基站和格点;如果后面觉得速度慢,可以用向量化的方式把基站维度也展开,但初版保持这个清晰结构更容易调试。
5.2 柯西随机数生成与QPSO主循环实现
柯西随机数在Matlab里可以直接从均匀分布变换得到,一行代码即可。标准柯西分布C(0,1)可以通过下面的函数实现:
function y = cauchyRandBinary() y = tan(pi * (rand() - 0.5)); end这个变换的原理是概率积分变换,利用柯西分布的反累积函数把均匀随机数映射到柯西分布。为什么不直接用randn?因为没有哪个内置函数直接叫randc,而这一行变换足够简洁、稳定、无额外依赖。
主算法的核心循环结构我整理成了下面这段代码框架,读者可以直接在此基础上扩展成完整脚本:
% 参数设置 N = 30; % 粒子数 numBS = 10; % 基站数量 dim = 2 * numBS; % 每个粒子维度:基站x,y坐标 lb = zeros(1, dim); ub = 2000 * ones(1, dim); maxIter = 300; mu = 0.3; % 柯西变异触发概率 % 初始化 X = rand(N, dim) .* (ub - lb) + lb; pBest = X; gBest = X(1, :); % 计算初始适应度... for t = 1:maxIter mbest = mean(pBest, 1); beta = 1.0 - 0.5 * (t / maxIter); for i = 1:N phi = rand(1, dim); P = phi .* pBest(i, :) + (1 - phi) .* gBest; u = rand(1, dim); if rand < 0.5 X(i, :) = P + beta .* abs(mbest - X(i, :)) .* log(1 ./ u); else X(i, :) = P - beta .* abs(mbest - X(i, :)) .* log(1 ./ u); end end % 边界约束 X = max(min(X, ub), lb); % 柯西变异全局最优 if rand < mu cand = gBest + 0.1 * (ub - lb) .* cauchyRandBinary(); cand = max(min(cand, ub), lb); if evalCoverage(cand) < evalCoverage(gBest) gBest = cand; end end % 更新pBest与gBest for i = 1:N if evalCoverage(X(i, :)) < evalCoverage(pBest(i, :)) pBest(i, :) = X(i, :); end if evalCoverage(pBest(i, :)) < evalCoverage(gBest) gBest = pBest(i, :); end end end这段框架里有一个性能隐患:evalCoverage在每一轮里被反复调用,而且柯西变异候选解也要单独调一次,整体计算量不小。我实际测试时,一个300轮的实验,完整跑下来大约要一两分钟,可以接受。但如果你把网格加密到25m,可能就跑到十几分钟了,建议先保持50m粒度复现逻辑。
5.3 参数初始化与边界处理的经验
粒子数N的取值我建议在20到50之间。太少,种群多样性不足,覆盖率结果方差大;太多,每一轮适应度评估次数直线上升,运行时间受不了。N=30是性能和稳定性的一个折中,我最终用的就是30。
边界处理上,我采用的是简单截断法,把越界维度直接钳位到边界。这个方法实现最简单,覆盖率函数也永远不会因为基站跑到区域外而报错。但要注意一个现象:简单截断容易让大量粒子堆积在边界上,特别是优化后期,如果最优解应该靠近边界,粒子会在边界附近聚集出一条“亮线”。如果不想看到这种分布,可以改用反射法:
X = X - 2 * (X - ub) .* (X > ub) - 2 * (lb - X) .* (X < lb);反射法的好处是粒子越界后被“弹回”区域内部,分布更自然。不过反射法在种群迭代中的行为更复杂,我建议初版先用截断法跑通,攒出基线结果再说。
关于适应度函数的数值稳定性,还有一点经验之谈:在计算RSRP时如果你的传播模型偶尔算出低于−140dBm的值,不用特地处理,反正阈值设在−105dBm,这些格点天然就是未覆盖。真正的坑在距离矩阵出现NaN或者Inf,这类错误会让整个适应度返回NaN,算法直接崩溃。所以写代码时优先给每个可能产生NaN的地方加保护。
6. 仿真实验设计与结果分析
6.1 仿真场景设置与三组对照实验
为了验证柯西分布量子粒子群优化的实际效果,我设计了三组对照实验:标准PSO、基本QPSO、加入柯西变异扰动的QPSO(以下简称CDQPSO)。三组算法使用相同的初始化种子、相同粒子数N=30、相同最大迭代次数300,覆盖率函数完全复用,保证对比的公平性。
场景参数沿用前面的设置:2km×2km城区,10个宏基站,网格粒度50m,覆盖阈值−105dBm,基站高度35m,发射功率43dBm。这个场景相对典型,既不是特别稀疏的农村环境,也不是超密集的微站环境,计算量适中。
每组算法独立运行10次,统计最终覆盖率的最优值、平均值和标准差。设计10次重复的原因很实际:群体智能算法的随机性很强,单次运行的覆盖率可能因为运气好或者运气差而偏离真实水平,只有方差数据才能反映算法的稳定性。
三组算法的参数设置分别为:标准PSO的w从0.9线性降到0.4,c1=c2=2.0;QPSO的β从1.0降到0.5;CDQPSO在QPSO基础上加柯西变异概率mu=0.3,扰动尺度0.1×(ub−lb)。这样对比的变量就是“是否引入柯西扰动”,其他条件保持一致。
6.2 收敛曲线与覆盖率最优值对比
从收敛曲线看,差异非常明显。标准PSO在50代左右快速收敛到约0.17的未覆盖率,之后300代几乎没有明显变化,曲线几乎是一条平线。QPSO在前期收敛略慢于PSO,但最终能压到约0.145附近,比PSO低了两个百分点左右,这说明QPSO的全局搜索能力确实更强。
CDQPSO的收敛曲线在前期和QPSO基本重合,但在迭代中后段经常会出现“台阶式下跌”——某个时刻柯西变异恰好找到了更优解,覆盖率突然蹦高一个台阶。这类跳跃在QPSO曲线上几乎看不到,这正是柯西长尾扰动起作用的直观证据。最终CDQPSO的平均未覆盖率能压到0.12上下,相比标准PSO提升了约4到5个百分点的覆盖率。
四次重复实验的统计结果如下表所示:
| 算法 | 最优未覆盖率 | 平均未覆盖率 | 标准差 |
|---|---|---|---|
| 标准PSO | 0.165 | 0.172 | 0.008 |
| QPSO | 0.143 | 0.151 | 0.006 |
| CDQPSO | 0.118 | 0.126 | 0.004 |
标准差从0.008降到0.004,说明CDQPSO不仅找到了更好的解,而且每次运行的稳定性更好。这一点在实际工程规划中很关键,毕竟你给领导提交的是一组站址,没人愿意看到每次重跑结果差出好几个百分点。
6.3 覆盖率热点图与站址分布差异
数值之外,我更建议你画出规划区的覆盖率色图来直观观察。做法很简单:取最终gBest作为基站部署坐标,调用覆盖率函数拿到每个格点的RSRP矩阵,然后用imagesc或者pcolor绘图。
我在对比图中发现了一个很有意思的现象:标准PSO收敛出的站址往往集中在区域中心附近,边缘和角落的覆盖明显薄弱,这恰好反映出它“早熟”于中心区域的高密度信号叠加。QPSO的结果稍微拉开了几个站,边缘覆盖有所改善。CDQPSO的站址分布最为分散,有几个站甚至被柯西变异“踢”到了区域边角上,恰恰把这些位置原本的覆盖空洞给填上了。
这个分布差异直接解释了覆盖率提升的来源:覆盖优化问题往往不是简单地把站都堆在一起,而是要尽量覆盖更多离散网格点。柯西变异起到的就是“探索新位置”的作用,让某些站跳出中心区域的吸引域,去填补边界空洞。理解了这一点,你就能明白为什么覆盖率从数值上看只是提升了几个百分点,却在分布图上产生了本质性的变化。
7. 调试过程踩过的坑与避坑指南
7.1 收敛曲线震荡:柯西扰动的频率和幅度要克制
我最早把柯西变异用在每个粒子每一次迭代上,结果收敛曲线像过山车一样,终值反而不如基本QPSO。原因很直接:重尾扰动杀伤力太大,对每个粒子连续踢,破坏了算法的收敛趋势。后来切成“只对gBest扰动,以0.3概率触发”,曲线才稳定下来。
给初学者的建议是:先从低频开始,比如0.1的概率触发柯西变异,看覆盖率提升效果如何,再逐步增大。如果提升不明显,调大scale;如果曲线开始震荡,降低触发概率或缩小scale。这样手动跑几轮,你会对算法的灵敏度建立直觉,比硬套某个参数组合要可靠得多。
7.2 结果不稳定:重启多次看分布而不是看单次
群体智能算法单次运行的结果不一定是真实的算法水平,这点我在跑实验时感触很深。有一次CDQPSO单次运行跑出了0.11的未覆盖率,我很兴奋,结果同样的参数换一个随机种子重跑,直接变成0.135。显然,不能拿单次运行结果下结论。
规范的做法是每轮实验运行10到20次,记录平均值和标准差,再结合箱线图或小提琴图展示分布。我在这个题目里就采用了10次重复的方案,最终结果才让人放心。如果某次运行明显偏差,也别急着改算法,先看看是不是初始化位置运气太差,可以尝试用拉丁超立方抽样替代均匀分布抽样来生成初始种群,能显著降低初始化带来的方差。
7.3 运行太慢:网格粒度与评估次数需要平衡
覆盖率优化的计算热点全在适应度评估上,一次评估要遍历所有格点和所有基站,预算是O(gridX × gridY × numBS)。如果算法每轮要评估N个粒子加上柯西候选解,迭代次数还设很大,总计算量会呈线性放大。
我的提速经验有三条。第一,初期探索阶段用50m网格跑通逻辑,只在最后展示结果时加密网格。第二,如果沿用50m网格还是嫌慢,把覆盖率函数改成矩阵运算一次性算完所有格点和基站的距离,避免循环嵌套。第三,对同一个粒子种群,可以用parfor并行评估适应度,但要注意Matlab并行池的启动时间在小规模问题上可能反而更慢。
这里尤其提醒一句:不要在算法还在调试时就上100轮×100粒子的配置,否则你调一个参数的功夫可能够把整杯咖啡喝完。
7.4 覆盖率结果异常偏高或偏低的检查清单
最后一个经验板块,我习惯性地列一份排查清单,自己在复现题目时遇到不合常理的结果都会逐一检查:
| 现象 | 优先排查方向 |
|---|---|
| 覆盖率始终100% | 检查阈值是否设太低,或发射功率/增益是否给得过高 |
| 覆盖率趋近0 | 检查传播模型单位:频率是否是MHz、距离是否是km、损耗参数是否合理 |
| 结果依赖随机种子 | 检查粒子数是否太少、迭代次数是否不足、初始化是否过于集中 |
| 收敛曲线锯齿 | 检查β是否恒定、柯西扰动是否过于频繁或幅度过大 |
| 所有站最终挤在一起 | 检查最小站间距惩罚项是否忘记加,或惩罚权重太小 |
这份清单是我用几次“看起来完美但实则错得离谱”的实验换来的教训。尤其是传播模型的单位换算,我在复现时因为把log10(d)里的d直接用了米而不是千米,导致路径损耗算出来虚高,覆盖结果全线崩溃。做算法实验时遇到怪结果,第一反应不是怀疑算法本身,而是回头检查模型和单位,这是最省时间的调试顺序。
最后说一点个人体会。做这类“算法+工程问题”的复现,最容易犯的错是沉迷在算法改动的细节里,而忽略了底层问题建模是否扎实。LTE基站覆盖率问题能不能被QPSO或柯西变变异优化好,其实一半的功劳来自覆盖率模型本身的合理性。如果你把网格、传播模型、约束条件这些基础打牢,哪怕用最简单的PSO也能得到有意义的部署方案;反过来,模型一旦有单位错误或逻辑漏洞,再精妙的算法也只是在给错误答案做精美包装。建议你复现完这份代码后,不要急着去调更多参数,先把覆盖率函数里的每个量纲都过一遍,再回头审视柯西扰动的位置,你会对这类优化问题有完全不一样的理解。