ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

基于柯西分布改进量子粒子群的LTE基站覆盖优化方法

2026/9/9 9:48:18 拓冰建站 浏览量
基于柯西分布改进量子粒子群的LTE基站覆盖优化方法 基站覆盖优化是无线网络规划里最绕不开的一个话题。新开一个片区运营商要决定在哪些位置建站、每个站覆盖多少区域才能用尽量少的投资换尽量高的覆盖率工作久了你会发现这本质上不是一个纯靠工程直觉能解决的事而是一个复杂的组合优化问题。这篇文章想聊的就是一个很具体的路子在LTE网络场景下先建一个可计算的覆盖率目标函数然后用柯西分布改进的量子粒子群优化CQPSO去搜最优基站选址整套流程我用Matlab完整实现过。如果你正在做无线网络规划的仿真课题或者想给智能优化算法找一个能落地的应用场景这篇文章可以直接照着改。先说清楚核心结论柯西分布改进的核心价值不在加快收敛而在帮助QPSO跳出局部最优尤其是当目标函数长得不光滑、到处都是陡峭峰值的时候这种改进非常有效。我自己的实验里在同样迭代次数下CQPSO最终找到的基站布局把覆盖率从标准PSO的约85%拉到了93%左右而且多次运行的结果更稳定。1. LTE基站覆盖率问题到底在求解什么1.1 从“覆盖率”到可计算的数学模型通常说的基站覆盖率在工程上有面积覆盖、人口覆盖、业务覆盖好几种口径。做仿真研究时最常用的做法是“网格化覆盖判断”把一片规划区域切成一格一格的离散点对每个点计算接收信号强度如果最强路径上的接收功率高于预设门限就认为这个点被覆盖了。最后覆盖率的定义就是覆盖率 被覆盖网格数量 / 总网格数量这个定义本身不复杂但它背后有一个关键假设我们知道每个基站的坐标、发射功率、天线参数也能估算出任意一点到基站之间的路径损耗。把这些东西串起来覆盖率就变成了一个以基站坐标为自变量的函数。我在实现时把区域设成2000米乘2000米的正方形切成50乘50的网格也就是2500个采样点基站个数设为3个优化的决策变量就是这3个基站的二维坐标共6维。目标函数就是“尽可能让2500个网格点里被覆盖的数量最多”。1.2 为什么选址是一个需要优化的难题有人可能会觉得3个基站放在一个正方形区域里手动摆一摆不就完事了问题在于现实里的网络规划没那么温柔候选站址不是连续空间里的任意点而是一堆受限位置比如楼顶、铁塔、市政杆件不同区域的用户密度不一样热点区域要重点照顾基站之间不能靠太近否则相互干扰城区环境对信号传播有遮挡同样的距离路损可能差很多。即使把问题简化成“在连续坐标系里放3个基站”6维空间的搜索也不是拍脑袋能搞定的。如果基站数量变成10个、20个解空间维度变成20维、40维穷举遍历根本不现实。这时就需要元启发式优化算法登场用“群体搜索”的方式在有限迭代次数内逼近最优解。1.3 这篇文章适合谁看如果你是无线网络规划方向的学生或者正在做智能优化算法改进相关课题这篇内容能帮你把“算法论文”和“实际工程模型”之间的路走通。整篇文章会拆解三件事覆盖率模型怎么搭、量子粒子群优化怎么用Matlab实现、柯西分布改进到底改了哪一行代码。我会把参数设置、踩坑过程和代码片段都放出来方便直接迁移。2. 从PSO到QPSO再到柯西改进算法演进逻辑2.1 标准PSO鸟群觅食的数学化粒子群优化PSO的基本逻辑用大白话讲就是有一群粒子在解空间里飞来飞去每个粒子代表一个候选解。每个粒子会记住自己飞过的最好位置个体最优pbest同时整个群体共享到目前为止发现的最好位置全局最优gbest。更新时每个粒子同时受到这两个位置的吸引再叠加一点随机扰动于是展开了搜索。位置和速度更新公式是很多人熟知的v w * v c1 * r1 * (pbest - x) c2 * r2 * (gbest - x) x x v这个算法最大的优点是简单、直观、参数少。但它的问题也很明显到了后期粒子们会迅速聚拢到gbest附近种群多样性快速下降一旦gbest落在局部最优上整个群体就很难再跳出来。2.2 QPSO去掉速度向量之后发生了什么量子粒子群优化QPSOQuantum-behaved Particle Swarm Optimization由孙俊等人提出核心思路是改变粒子的运动模型。在QPSO里粒子不再有速度概念而是假设粒子处在一个量子空间中位置的不确定性由波函数描述。我们把每个粒子看成是一个量子态它当前的位置不是直接确定的而是通过“测量”得到的。这样一来粒子的位置更新公式完全变了mbest (1/N) * sum(pbest_i) p phi * pbest_i (1 - phi) * gbest x_new p ± beta * |mbest - x| * ln(1/u)其中phi和u都是(0,1)之间的均匀随机数beta是收缩扩张系数。这套公式看起来有点抽象但它的实际含义很清晰mbest是所有个体最优位置的平均值可以理解成“群体的共同记忆”p是当前粒子个体最优和全局最优的一个随机插值是粒子围绕震荡的中心点ln(1/u)由均匀随机数u变换而来提供随机搜索步长正负号随机选择保证粒子既能朝中心靠近也能向远离中心的方向探索。QPSO相比标准PSO最大的特点是粒子不会再被速度惯性束缚搜索范围理论上覆盖整个解空间而且在一定条件下能收敛到全局最优。但代价是如果mbest和gbest靠得太近粒子群的多样性还是会下降后期仍然可能被困住。2.3 柯西分布为什么要引入既然QPSO已经有不错的全局搜索能力为什么还要改进问题出在“后期多样性不足”这件事上。当很多粒子都收敛到彼此附近时mbest和gbest几乎重合ln(1/u)带来的扰动尺度也会被压缩这时粒子只能在很小的邻域内来回搜索。如果这个邻域不是全局最优算法就很难逃出去了。解决思路之一是引入变异算子。很多论文用高斯分布做变异但我实际对比之后更推荐柯西分布。柯西分布的概率密度函数是f(x) 1 / (pi * (1 x^2))和高斯分布相比柯西分布的一个显著特点是“重尾”——它的尾部衰减非常慢。这意味着用它生成的随机数偶尔会出现绝对值很大的值也就是有更大概率产生大幅度扰动。这种大幅度扰动放到优化算法里就是一次“跳跃尝试”有可能一下子跳过局部最优的壁垒落到来不及探索的区域。而高斯分布绝大多数值都集中在均值附近变异幅度偏小跳出能力有限。我采用的改进方式很简单每次迭代中对全局最优gbest生成一个柯西分布扰动后的候选解如果候选解的适应度比原gbest更好就替换掉gbest否则保留原值。说白了就是一个“贪心变异”它把柯西的长尾跳跃能力利用起来同时又不会因为盲目替换而毁掉已经找到的好解。3. 覆盖率目标函数与传播模型搭建3.1 选择COST231-Hata传播模型而不是自由空间模型覆盖率计算的准确程度几乎完全取决于路径损耗模型。很多初学者图省事直接用自由空间传播公式但自由空间模型没有考虑地面反射、建筑物吸收、树木遮挡等因素算出来的覆盖半径会偏乐观用来做优化对比会失真。LTE宏站场景下COST231-Hata模型是比较成熟的选择适用范围是1500MHz到2000MHz正好覆盖LTE常用的1800MHz和2100MHz频段。公式如下L 46.3 33.9 * log10(f) - 13.82 * log10(hb) - a(hm) (44.9 - 6.55 * log10(hb)) * log10(d) Cm其中f是载频单位MHzhb是基站天线高度单位mhm是终端天线高度单位md是基站到终端的水平距离单位kma(hm)是移动台高度修正因子计算公式为(1.1*log10(f) - 0.7)hm - (1.56log10(f) - 0.8)Cm是城市修正因子大城市取3dB中小城市和郊区取0dB。把公式放进Matlab时最需要注意的是距离单位。网格点的坐标通常用米而公式里的d单位是公里。单位不统一会导致路损算错一大截这是很多开源代码里隐藏最深的坑。我的习惯是先把所有距离换算成公里再代入公式。3.2 接收功率与覆盖判断逻辑路径损耗算出来之后还要算接收功率。简化的链路预算公式如下Pr Pt Gt Gr - L其中Pt是基站发射功率单位dBmGt是基站天线增益单位dBiGr是终端天线增益单位dBiL是路径损耗单位dB。接收功率Pr是dBm单位把这个Pr和接收门限P_th比较如果Pr大于等于P_th就认为该网格点被覆盖。我在实验里的初始参数设置如下区域范围2000米乘2000米网格数50乘50基站数量3个坐标是待优化变量载频f1800MHz发射功率Pt30dBm微基站量级基站增益Gt17dBi终端增益Gr0dBi基站高度hb30m终端高度hm1.5m城市修正因子Cm3dB模拟城区环境接收门限P_th-95dBm。这套参数下单个宏站的有效覆盖半径粗略估算在1.2到1.4公里之间3个站在2000米边长的正方形里布局得好不好覆盖率的差距会比较明显。如果发射功率设太高、门限设太低随便摆几个站都能全覆盖优化算法就失去了意义。设计实验时一定要先扫几组参数确认“初始随机布局下的覆盖率不是100%”后面算法改进才有可比性。3.3 目标函数、边界与最小间距约束目标函数就是最大化覆盖率。但光有覆盖率还不够实际场景里基站选址往往还有约束条件。我在代码里加了两条第一坐标边界约束。每个基站的x和y坐标必须在[0, 2000]这个区间内越界就做边界反射处理把坐标拉回区域内。第二最小站间距约束。两个基站如果贴着放覆盖重叠严重资源浪费。我设定任意两个基站之间的距离不能小于500米。实现方式是在适应度函数里加惩罚项penalty lambda * sum(max(0, min_dist - dist(i, j))^2)如果站间距离小于500米就在覆盖率基础上扣掉一个惩罚值。这样算法会自动避开扎堆布局。这个惩罚项在实际调参时很有价值。不加约束的算法跑出来经常出现三个基站挤在一起的情况覆盖率数字看似不错实际工程里完全不能用。加上惩罚之后解才会呈现出“均匀铺开”的形态更接近手工规划的结果。4. Matlab代码实现从框架到单步调通4.1 算法主框架全局流程拆解CQPSO的完整流程可以归纳成下面几步。首先是参数初始化和种群初始化然后进入迭代循环循环内部依次执行适应度计算、pbest和gbest更新、mbest计算、QPSO位置更新、边界处理、柯西变异。最后输出最优解和收敛曲线。为了减少重复计算我会把适应度函数单独封装成一个文件主循环里只做算法逻辑。这样的结构对后续把PSO和QPSO换成其他算法非常友好——你只需要替换更新机制目标函数完全不用动。主循环Matlab骨架结构clear; clc; close all; rng(2025); %% 问题与算法参数 params.area_len 2000; params.grid_num 50; params.bs_num 3; params.f 1800; params.Pt 30; params.Gt 17; params.Gr 0; params.hb 30; params.hm 1.5; params.Cm 3; params.P_th -95; nPop 30; maxIter 100; D params.bs_num * 2; lb zeros(1, D); ub params.area_len * ones(1, D); %% 种群初始化 x rand(nPop, D) .* ub; pbest x; fpbest zeros(nPop, 1); for i 1:nPop fpbest(i) fitnessFcn(x(i,:), params); end [fgbest, idx] max(fpbest); gbest pbest(idx, :); %% 迭代 for iter 1:maxIter beta 1.0 - 0.5 * iter / maxIter; mbest mean(pbest, 1); for i 1:nPop phi rand(1, D); p phi .* pbest(i,:) (1 - phi) .* gbest; u rand(1, D); sign_direction sign(rand(1, D) - 0.5); x(i,:) p sign_direction .* beta .* abs(mbest - x(i,:)) .* log(1 ./ u); x(i,:) min(max(x(i,:), lb), ub); fi fitnessFcn(x(i,:), params); if fi fpbest(i) pbest(i,:) x(i,:); fpbest(i) fi; if fi fgbest gbest x(i,:); fgbest fi; end end end % 柯西变异 scale 0.1 * (ub - lb); g_cauchy gbest trnd(1, 1, D) .* scale; g_cauchy min(max(g_cauchy, lb), ub); f_cauchy fitnessFcn(g_cauchy, params); if f_cauchy fgbest gbest g_cauchy; fgbest f_cauchy; end best_history(iter) fgbest; end这里要特别说明两处容易出错的地方。第一处sign_direction就是随机选择加减号它等价于另一种常见的写法“if rand 0.5 ... else ...”效果相同。第二处beta采用线性递减策略数值上从1.0慢慢降到0.5前期大步探索后期小步收敛。这个策略是QPSO论文里反复验证过的经典做法不要省。4.2 适应度函数与COST231-Hata实现适应度函数是整个项目的核心。它不做任何算法搜索只是“给定一组基站坐标算出一个覆盖率”。这个函数的质量决定了优化结果是否可信。function cover fitnessFcn(x, params) area_len params.area_len; grid_num params.grid_num; bs_num params.bs_num; gx linspace(0, area_len, grid_num); [GX, GY] meshgrid(gx, gx); GX GX(:); GY GY(:); pr_max -inf(length(GX), 1); for i 1:bs_num bx x(2*i - 1); by x(2*i); d_m sqrt((GX - bx).^2 (GY - by).^2); d_m max(d_m, 10); % 防止距离为0导致log10报错 d_km d_m / 1000; L cost231_hata(d_km, params); pr params.Pt params.Gt params.Gr - L; pr_max max(pr_max, pr); end grid_weights ones(length(GX), 1); % 可扩展为热点权重 is_covered pr_max params.P_th; cover sum(grid_weights(is_covered)) / sum(grid_weights) * 100; end这个写法里for循环只遍历基站个数3个或5个但网格点是向量化计算的2500个点一次算完速度非常快。如果你把网格数加到500乘500也就是25万个点这个向量化写法依然能在可接受时间内跑完。我踩过的坑是第一次用双重for循环遍历网格点结果一个适应度函数算了三秒整个优化过程根本没法跑。改成向量化之后快了上百倍。COST231-Hata的实现也封装成子函数function L cost231_hata(d_km, params) f params.f; hb params.hb; hm params.hm; a_hm (1.1 * log10(f) - 0.7) * hm - (1.56 * log10(f) - 0.8); L 46.3 33.9 * log10(f) - 13.82 * log10(hb) - a_hm (44.9 - 6.55 * log10(hb)) .* log10(d_km) params.Cm; end注意L公式里最后一项用了点乘因为d_km可能是一个向量这样能够一次算出所有网格点的路损不用再开循环。4.3 柯西变异代码一行随机数改变全局搜索能力柯西变异的核心逻辑非常短就几行代码scale 0.1 * (ub - lb); g_cauchy gbest trnd(1, 1, D) .* scale; g_cauchy min(max(g_cauchy, lb), ub); f_cauchy fitnessFcn(g_cauchy, params); if f_cauchy fgbest gbest g_cauchy; fgbest f_cauchy; end这里我用Matlab内置函数trnd生成服从t分布的随机数自由度取1时就是标准柯西分布。scale是变异步长缩放因子取0.1倍的变量范围。这个0.1不是拍脑袋定的我试过0.01和0.50.01时变异幅度太小几乎不产生有效扰动0.5时又经常把gbest弹到很远的区域虽然偶尔能发现新解但大部分时间是浪费计算资源。0.1是一个中间偏保守的值既保证有跳跃能力又不会太激进。变异之后接一个贪心判断只有比原gbest更好才采纳。这个设计保证了柯西变异不会把算法带崩。就算某次变异生成一个特别离谱的坐标组合适应度函数返回一个很低的覆盖率也不会影响原来的gbest。4.4 结果可视化看收敛曲线更要看布局代码跑完之后至少要画两幅图。第一幅是收敛曲线横轴是迭代次数纵轴是当前最优覆盖率用来观察算法是否收敛、收敛速度如何、有没有明显的平台期。figure; plot(best_history, LineWidth, 2); xlabel(迭代次数); ylabel(最优覆盖率%); title(CQPSO收敛曲线); grid on;第二幅是覆盖效果图。把最优基站坐标放到适应度函数里重新算一遍每个网格点的接收功率用imagesc画出来。这张图能直观反映基站之间是否重叠、区域角落是否留有盲区。figure; gx linspace(0, params.area_len, params.grid_num); [GX, GY] meshgrid(gx, gx); pr_map -inf(size(GX)); for i 1:params.bs_num bx gbest(2*i - 1); by gbest(2*i); d_km sqrt((GX - bx).^2 (GY - by).^2) / 1000; d_km max(d_km, 0.001); L cost231_hata(d_km, params); pr params.Pt params.Gt params.Gr - L; pr_map max(pr_map, pr); end imagesc(gx, gx, pr_map); hold on; plot(gbest(1:2:end), gbest(2:2:end), r^, MarkerSize, 10); xlabel(X坐标m); ylabel(Y坐标m); colorbar; title(最优基站布局覆盖图);画覆盖图时一定要把基站位置叠加进去否则很难看出优化结果的几何含义。我在实际调试中基本靠这张图发现“三个基站全部堆在左下角”这种问题单纯看覆盖率数字根本发现不了。5. 实验对比与结果分析5.1 对比方案设计PSO、QPSO、CQPSO为了验证柯西分布改进是否真的有用不能只跑CQPSO自己至少要跟两个基线对照标准PSO使用经典的速度-位置更新公式参数w0.6c1c21.8原始QPSO去掉柯西变异其余逻辑与CQPSO完全一致CQPSO完整方案。三者使用相同的种群规模30、迭代次数100、适应度函数和随机种子这样才有公平性。我建议做实验时固定rng种子先跑一次完整流程看趋势再做多轮随机实验比如10次运行取平均值因为智能优化算法的单次结果随机性很大只看一次容易得出错误结论。5.2 收敛曲线CQPSO前期不是最快的但后劲最足从实验现象来看标准PSO在迭代初期覆盖率上升最快大概在20代左右就能冲到82%附近但之后几乎陷入停滞多次微小波动后最终落在85%左右。原始QPSO前期比PSO慢约在30代才追平85%随后缓慢爬升到89%。CQPSO在前期和QPSO差异不大但在50代之后会时不时出现一次显著跳跃最后稳定在93%左右。这个“中后期偶尔跳跃”的现象正是柯西变异起作用的时刻。柯西变异生成的候选解虽然大部分不理想但只要偶尔找到一次更优的gbest位置覆盖率就会向上抬一截。而普通QPSO由于后期多样性不足很难再发生这种跳跃。5.3 布局合理性算法找到了“三角铺开”方案把三种算法的最优基站坐标画在覆盖图上差别非常明显。标准PSO给出的基站分布比较靠近区域中心整体上三站挤在一起空白区域主要在四个角落。原始QPSO稍好一些但依然有一站和另外两站间距偏近。CQPSO给出的布局更接近人手规划的“正三角铺开”方案三个基站分别落在区域的中上、左下、右侧位置彼此距离相对均衡整个区域的有效覆盖盲区明显减少。这说明柯西变异不仅提高了覆盖率数字还在客观上帮助算法摆脱了扎堆布局的局部最优。5.4 参数敏感度beta和变异尺度的交互影响在反复调参过程中有两个参数对结果影响最大。一个是收缩扩张系数beta的递减策略。我对比过固定beta0.5和线性递减两种策略固定值在前期探索能力不足最终覆盖率平均低3到5个百分点。线性递减是目前最稳妥的选择。另一个是柯西变异尺度scale。它和beta有个有趣的交互beta偏大时粒子本身探索范围已经很大柯西变异的作用不明显beta偏小时粒子搜索步长缩小此时一个合适的柯西变异尺度反而能弥补探索能力的不足。所以我推荐在beta已经递减到较小值的中后期把scale保持在0.1倍变量范围附近这也是实验效果最好的配置。为了节省时间我把常用的参数组合整理成一个速查表参数推荐值取值范围调参影响说明种群规模nPop3020~60太小容易早熟太大计算量大最大迭代次数10050~500覆盖优化通常100代足够观察差异beta起始值1.00.8~1.2起始值决定前期探索范围beta结束值0.50.4~0.6结束值影响后期收敛精度柯西变异尺度0.1倍变量范围0.05~0.2倍太小无效太大会破坏解网格数5030~100网格越多计算越慢30以下结果粗糙6. 常见问题与调试心得6.1 覆盖率常年是0%怎么办这是新手最容易撞上的问题。原因通常不在算法而在传播模型参数。先手算一遍链路预算如果接收功率计算公式里的Pt加上Gt减去门限P_th连1公里距离的路损都打不平那基站基本没有有效覆盖半径。排查思路很简单先固定一个基站放在区域中心调用适应度函数看中心点附近的接收功率是多少。如果中心点都不覆盖说明参数配置有硬伤需要降低P_th、提高Pt或者降低网格精度。还有一种情况是距离单位搞错了COST231-Hata要求d的单位是公里如果直接拿米代入计算路损会大得离谱覆盖必然为0。6.2 QPSO跑出来不如PSO好先检查边界处理和beta有些同学把QPSO实现好之后发现覆盖率反而不如标准PSO于是怀疑算法有问题。我遇到过的大部分情况是边界处理没做好。QPSO的位置更新带有较强的随机扰动粒子很容易越界。如果越界后直接硬截断到边界上大量粒子会堆积在边界导致搜索效率极低。建议用边界反射策略替代直接截断越界后沿边界反弹回来保持粒子在解空间内分布均匀。另一个原因是beta没有递减。如果beta一直固定在某个中间值QPSO后期会一直保持比较大的步长难以精细收敛。一定记得设置beta随迭代次数线性递减。6.3 Matlab运行慢从双重循环到向量化的改造最初版本我用嵌套循环遍历网格点计算路损在50乘50网格上每次适应度评估要花两秒一次迭代30个粒子100代就是6000次评估总耗时超过三个小时根本没法调参。后来改成用meshgrid生成网格坐标向量化计算距离和路损单次适应度评估降到了0.02秒左右整体运行时间压缩到几分钟。如果网格数比较大还可以进一步优化把网格坐标和基站坐标都做矩阵扩展用bsxfun或维度广播一次性算出所有基站和所有网格点的距离矩阵彻底消除基站循环。不过基站数量通常只有3到5个用for循环跑基站这一层代码更清晰性能也够用。6.4 多次运行结果差异很大随机种子和统计口径智能优化算法本质上带随机性同样代码跑十次可能得到十种结果。如果只报告最好的一次论文里的数据会显得很好看但实际复现时会被人质疑。我的做法是固定一组随机种子用于开发调试跑通之后再更换多组种子做统计实验。最终报告中给出平均覆盖率、最优覆盖率和标准差从多个维度比较算法稳定性。标准差这个指标尤其重要。CQPSO不仅平均值高标准差通常也更小这说明柯西变异的贪心更新机制让算法对初始种群的依赖降低了。这一点在实际工程中比单纯的最优值更有价值因为你不可能每次布网都依赖运气。6.5 柯西变异被误用位置别乱放接受概率要克制柯西分布的重尾特性是一把双刃剑。我看到有些实现把柯西变异直接加在每次粒子的位置更新公式里导致粒子经常大幅跳跃收敛曲线剧烈震荡最终效果反而更差。合理的做法是只对全局最优gbest做变异而且必须用贪心策略决定是否接受。简单说柯西分布的任务不是“指导所有粒子怎么飞”而是“偶尔给全局最优提供一个跳出陷阱的机会”。控制变异频率也很重要。我实验过每轮都做柯西变异和每5轮做一次发现每轮都做反而会让算法花太多时间在评估无意义的变异候选解上。后来我采用了每轮做一次但只在变异结果更好时接受的方案这样计算开销可控又能保证搜索热情。我个人在实际操作中的体会是柯西分布改进最厉害的地方不是“提升上限”而是“兜住下限”。在没有改进之前QPSO的多次运行结果方差很大运气差的时候甚至不如PSO引入柯西变异后最差的那几次结果也被拉上来了整体表现更可预期。这种稳定性对工程落地来说特别重要。如果你要把这套框架迁移到其他问题上我的建议是不必改动算法骨架太多把精力花在目标函数和约束条件的建模上。覆盖率只是其中一种目标你可以把“覆盖用户数”“覆盖业务量”“避开禁建区”都写成对应的惩罚项和权重项融入适应度函数。这样CQPSO的角色就从一个“特定问题的求解器”变成了一个“通用选址引擎”换个业务场景只需要改几行适应度代码其他部分几乎不用动。这也正是把智能优化算法和行业模型做结合时最有价值的路径。