ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

PPP蒙特卡洛蜂窝仿真:从基站撒点到覆盖与干扰评估

PPP蒙特卡洛蜂窝仿真:从基站撒点到覆盖与干扰评估 简介面向通信与网络方向研究者的PPP泊松点过程随机几何仿真资源聚焦蒙特卡洛方法在蜂窝网络建模与分析中的应用适合需要模拟基站空间分布、评估覆盖概率、吞吐量及干扰水平的科研与工程人员。压缩包共33个文件以28个MATLAB脚本.m为主体覆盖PPP分布生成、蒙特卡洛试验、性能指标统计与结果绘图等环节另含3个Fig图表和2张结果图片整体仅135KB轻量易用。资源脚本由PPP分布、蒙特卡洛模拟及结果分析等模块构成可帮助读者复现不同基站密度和用户分布下的仿真流程并理解随机几何与蜂窝系统结合的建模思路。已有347人学习适合作为通信仿真入门或课题验证的参考资料便于快速运行调试并扩展实验。1. 从基站坐标生成开始PPP蒙特卡洛蜂窝仿真到底在做什么蜂窝网络建模仿真的时候最让人头疼的往往不是功率分配或调度算法而是基站位置怎么摆。用规则的六边形网格会高估覆盖用实测站点数据又受限于工地场景换了城市就要重来。随机几何给出的解法是用泊松点过程PPP描述基站的空间分布——不需要任何实测路测只要给一个强度参数 λ就能在整个平面上撒出符合统计规律的基站坐标。配合蒙特卡洛仿真把用户位置也随机丢进去反复抽样几千次就能得出覆盖概率、边缘速率、干扰分布这些工程指标。这里的 PPP 和有人搜的“ppp协议”不是一回事那个是点对点协议做链路配置用的。这个 PPP 是 Poisson Point Process选址分布在二维平面或三维空间里。用这种建模方式的好处是结果有闭式表达式托底比纯仿真更能说明趋势。一个典型的做法是在仿真区域里先按 λ 生成基站再随机放若干个终端然后计算每一跳链路的 SINR再统计低于门限的比例。整个过程可以全部用 Python 写出半小时就能跑通第一个可用的蒙特卡洛蜂窝仿真循环。这套方法适合三类人做蜂窝网络级仿真的算法工程师、研究随机几何的通信专业学生、还有需要快速验证方案吞吐量的系统工程师。你不需要预先拥有任何基础站的实测数据只需要会用 numpy 和一点概率统计知识。接下来的内容会把 PPP 的理论、蒙特卡洛落地、SINR 计算和验证全部串起来最后一章给一个可以对着校验的闭式解基线。2. 先懂理论泊松点过程和它在蜂窝仿真里的位置2.1 PPP 的数学定义与强度参数泊松点过程是一种随机点集点之间相互独立任意一个有界区域内的点数量服从泊松分布。记强度为 λ表示单位面积内点的期望个数。对于一个面积为 A 的仿真区域平均点数就是 λA实际生成时可以用 λ 作为密度参数在区域内均匀撒点。数学上有两条性质决定了蜂窝仿真可以用它第一每个不重叠区域的点数量相互独立第二给定区域内点的数量 n 时这 n 个点的位置独立且均匀分布。这两条性质让 PPP 很容易在计算机上精确生成不需要求解任何积分方程。生成 PPP 坐标的 Python 最小实现如下import numpy as np def generate_ppp(lambda_density, width, height, seedNone): # lambda_density: 基站密度单位 /m^2 # width, height: 仿真区域大小单位 m rng np.random.default_rng(seed) area width * height n_points rng.poisson(lambda_density * area) x rng.uniform(0, width, n_points) y rng.uniform(0, height, n_points) return np.stack([x, y], axis1) # 在 2km x 2km 区域内强度为 1e-5 个/平方米约合每平方公里 10 个基站 bases generate_ppp(lambda_density1e-5, width2000, height2000, seed42) print(bases.shape)这段代码先根据 λA 算出泊松抽样点数再在矩形内均匀取坐标。注意poisson返回的期望是lambda_density * area如果区域是 2000×20004e6 平方米λ1e-5期望就是 40 个点。实际生成时点数会在 40 上下随机波动这正是 PPP 与网格模型最直观的一点区别。seed参数在蒙特卡洛仿真里非常重要。不固定随机种子时每次运行结果都略有不同不利于复现和排错。我一般会把 seed 作为函数参数暴露出来做参数扫描时固定同一组种子可以显著降低曲线抖动。2.2 蒙特卡洛仿真为什么适合随机几何随机几何里很多指标没有显式解析解。比如计算覆盖概率时要积掉基站位置、衰落、用户位置的全部分布复杂度超过传统数值积分能承受的范围。蒙特卡洛仿真用大数定律解决这个问题随机抽取大量的基站部署和用户位置分别计算 SINR 是否超过门限最后对 0/1 结果取平均。样本量足够大时这个平均就趋近真实概率。另一个现实原因是 PPP 模型的积分表达式里通常有干扰项的拉普拉斯变换虽然能写下来但工程人员要的不只是概率表达式还要知道 5% 边缘用户有多慢、小区负载如何随密度变化。蒙特卡洛可以按用户维度收集整个分布直接画出 CDF 曲线输出分位点这些是解析公式不容易给到的。表 1 列出了蒙特卡洛蜂窝仿真里最常用的三个随机几何参数后续章节会逐个展开。参数名符号典型取值作用基站强度λ1e-6 到 1e-4 个/平方米控制基站密度用户采样数U100 到 1000每个快照统计的用户样本数快照数N1000 到 10000决定蒙特卡洛收敛精度λ 的取值直接影响网络类型市区宏基站一般在 1e-6 量级小基站密集部署可以到 1e-5 以上。用户采样数和快照数的平衡点需要根据目标指标做取舍这放在第 4 章详细说。2.3 PPP 与网格模型的差异对比用六边形网格模型做蜂窝仿真过去很流行因为频率复用模板可以直接套用。但网格模型有一个根深蒂固的问题它隐含了基站位置确定性这一前提无法表达站点疏密不均的现实。表 2 从几个维度做了对比。对比维度六边形网格PPP 随机几何基站位置规则排列随机撒点用户到最近基站距离分布固定或分段服从瑞利分布闭式可导干扰源集合有限且规律无限且随机覆盖率表达式数值求和有拉普拉斯变换闭式工程扩展边界低频、宏站异构、超密网络从数值上看两种模型在小区中心区域差距不大差距集中在小区边缘。PPP 模型预测的边缘 SINR 通常比网格模型低 3~5 dB因为边缘用户面对的最近基站和干扰基站位置都是随机的存在同时靠近两个站的情况。这个偏差直接影响小区间干扰协调的仿真结论所以现在 5G 超密场景的论文基本都用 PPP 打底。蒙特卡洛仿真不是要取代随机几何公式而是把公式里抽象的距离分布变成可以落地的采样过程。下面一章就从代码层面把基站、终端和 SINR 串起来。3. 搭一个能跑的 PPP 蒙特卡洛蜂窝仿真3.1 用 Python 生成 PPP 基站坐标最小实现先定义一个完整的 PPP 仿真主循环。和上一章的不同这里不只是生成基站还要考虑用户在小区内如何分布以及后续计算需要保留的每个基站坐标。import numpy as np def generate_ppp(lambda_density, width, height, seed): rng np.random.default_rng(seed) n rng.poisson(lambda_density * width * height) x rng.uniform(0, width, n) y rng.uniform(0, height, n) return np.vstack([x, y]).T def generate_users(u_num, width, height, seed): rng np.random.default_rng(seed) x rng.uniform(0, width, u_num) y rng.uniform(0, height, u_num) return np.vstack([x, y]).T这里把基站和用户分开写便于分别控制分布。用户默认均匀撒在整个仿真区域等价于认为业务在区域内均匀出现。实际中用户往往跟热点区域走这时候需要改generate_users的内部实现比如用二维高斯混合模型生成热点簇。坐标生成的边界需要小心如果基站均匀撒点但用户分布集中在边缘那么边缘用户的最近基站可能落在仿真区域外导致距离计算失真。后面第 4 章的“保护带”就是专门处理这个问题的。3.2 从基站到终端的链路计算拿到坐标后下一步是对每个用户找到最近基站计算路径损耗、阴影衰落和快衰落。常见的路径损耗模型取对数距离形式写作def compute_sinr(user_pos, base_stations, noise_power, tx_power23, freq2.1e9): # tx_power 单位 dBm噪声功率单位 dBm # 返回每个用户到最近基站的距离、干扰与SINR diffs base_stations - user_pos # (n_bs, 2) dists np.hypot(diffs[:, 0], diffs[:, 1]) dists np.maximum(dists, 1.0) # 避免距离为0 # 路径损耗自由空间扩展宏小区模型 path_loss_db 128.1 37.6 * np.log10(dists / 1000.0) rssi_db tx_power - path_loss_db # 排序找最近基站 order np.argsort(rssi_db)[::-1] best_bs_idx order[0] interference_db rssi_db[order[1:]] interference_linear np.power(10.0, interference_db / 10.0) signal_linear np.power(10.0, rssi_db[best_bs_idx] / 10.0) noise_linear np.power(10.0, noise_power / 10.0) sinr_linear signal_linear / (noise_linear np.sum(interference_linear)) sinr_db 10 * np.log10(sinr_linear) return dists[best_bs_idx], sinr_db这段代码用的宏小区路径损耗参数是 3GPP TR 36.814 里的标准值128.1 37.6*log10(d)其中 d 单位是 km。换算成米后10 m 和 1000 m 距离差会产生大约 75 dB 的接收功率差符合城市宏站的日常感知。np.maximum(dists, 1.0)限制最小距离为 1 米防止用户与基站重合时出现无穷大的接收功率。在真实系统中用户不可能和天线摆在同一位置这个保护是物理合理的。注意这里没有加入阴影衰落标准差也没有加瑞利衰落。要更贴近真实需要对每条链路乘一个指数分布的功率因子。这是第 4 章要讨论的信道模型细节先把基本的距离衰减跑通。3.3 覆盖概率怎么统计覆盖概率的定义很直接对每个用户计算 SINR统计 SINR 大于某个门限比如 -2 dB、0 dB、5 dB的比例。写成蒙特卡洛循环def coverage_monte_carlo(lambda_density, area_size, n_snapshot, n_users, sinr_threshold, seed0): rng np.random.default_rng(seed) total_measure 0 covered_measure 0 sinr_samples [] for snap in range(n_snapshot): bs generate_ppp(lambda_density, area_size[0], area_size[1], seed snap) users generate_users(n_users, area_size[0], area_size[1], seed 10000 snap) for user in users: _, sinr_db compute_sinr(user, bs, noise_power-100) sinr_samples.append(sinr_db) if sinr_db sinr_threshold: covered_measure 1 total_measure 1 return np.mean(np.array(sinr_samples) sinr_threshold), np.array(sinr_samples)统计原理是大数定律把每次快照的每个用户都视为一次独立试验被覆盖的试验次数除以总试验次数就是覆盖概率。sinr_samples用于后续画 CDF 曲线这一点比只返回一个均值有用得多。参数上noise_power-100是对应 10 MHz 带宽、接收机噪声系数 7 dB 的典型底噪。如果做系统级仿真最好按照具体带宽重新计算热噪声功率谱密度 为 -174 dBm/Hz加上 10log10(带宽) 和噪声系数。例如 10 MHz 带宽下-174 70 7 -97 dBm所以-100已经是留了余量的值。4. 蒙特卡洛蜂窝仿真里的坑边界、快照数和信道模型4.1 边界效应与保护带直接按照区域画框生成 PPP 并统计 SINR会在边缘得到偏乐观的结果。原因是边缘用户只能看到内部的干扰基站看不到区域外实际存在的基站干扰被低估SINR 偏高。解决方法是生成一个比统计区更大的区域只在统计区内部放用户计算时用到全部基站。def generate_ppp_with_guard(lambda_density, stat_width, stat_height, guard_margin): # 实际生成区域向外扩展 guard_margin 米 ext_width stat_width 2 * guard_margin ext_height stat_height 2 * guard_margin rng np.random.default_rng(seed) n rng.poisson(lambda_density * ext_width * ext_height) x rng.uniform(-guard_margin, stat_width guard_margin, n) y rng.uniform(-guard_margin, stat_height guard_margin, n) return np.vstack([x, y]).T, ext_width, ext_height保护带大小如何确定一般取最高干扰距离的 3~5 倍常见做法是以统计区域边长为基准外扩 20%~30%。如果打的是 2000 m × 2000 m 区域保护带至少 500 m。外扩太多会增大计算量外扩太少干扰不完整。表 3 是不同 λ 下的建议值。λ个/平方米保护带建议值原因1e-6宏站1000 m干扰距离可达数百米保护带必须足够大1e-5密集小站300~500 m站点密集距离一大影响迅速下降1e-4超密150~200 m干扰主要来自附近小站判断保护带是否足够的方法很实际把统计区边缘和中心分别统计 SINR如果两者平均差超过 1 dB就继续加大保护带。闭式解也可以用来做间接验证最后一章会讲到对照方式。4.2 快照数不是越多越好很多仿真新手把快照数直接设成 50000结果跑了几个小时发现曲线和 5000 次几乎没有区别。蒙特卡洛仿真的误差与样本数开根号成反比从 1e3 提升到 1e4标准差只缩小为原来的三分之一收益越来越低。更合理的做法是设一个收敛阈值例如每 1000 次快照记录一次覆盖概率当最后两次的绝对差小于 0.001 时退出循环。这样不同 λ 场景下自动调节快照数省时间又保证可信度。coverage_prev 0.0 for snap in range(max_snapshot): # 仿真并统计覆盖次数 cur_cov covered_cnt / total_cnt if abs(cur_cov - coverage_prev) 0.001: break coverage_prev cur_cov注意这种停止规则只对均值的收敛有效。如果你要统计 SINR 的 5% 分位点收敛速度比均值慢得多需要更严的阈值或者固定快照数兜底。我一般会保留“至少 5000 个有效用户采样”这个底线。4.3 信道模型参数要对着协议来PPP 仿真最常见的误差源不是随机过程生成而是链路公式里的参数没有和使用的场景对齐。同样一个 PPP 部署用自由空间路径损耗和 3GPP 城区宏站路径损耗得到的覆盖率可以相差 20 个百分点。常用参数见表 4。选择时注意freq单位是 GHz损耗公式不同的频段不能混用。场景路径损耗公式适用频点城区宏站 UMa128.1 37.6log10(d/1000)2 GHz城区微站 UMi130.9 37.6log10(d/1000)3.5 GHz室内热点 InH122.5 17.3log10(d)5 GHz自由空间91.7 20log10(d/1000)视距参考如果你看到代码里直接写pathloss 128.1 37.6 * np.log10(d)要立刻检查 d 的单位。前面章节的示例把距离转成 km 再代入公式这是 3GPP 文档的规范写法。网上很多实现省略了距离换算导致公里级别距离算出离谱的损耗。另外多用户场景里是否加阴影衰落也会影响结论。通常做法是给每个基站与用户之间的链路加上对数正态阴影标准差在 6~10 dB 之间。加了阴影之后覆盖概率会下降但仿真时间不变只是多乘一个随机系数。如果想减少随机性可以先把阴影关掉跑通基线再打开。5. 跑数据用 PPP 蒙特卡洛评估蜂窝网络容量与干扰5.1 从 SINR 到每用户速率覆盖概率只回答“能不能接通”工程上更关心用户能跑多快。常见的做法是对每个用户的 SINR 套用香农公式得到频谱效率再乘以带宽得到每用户速率。要注意香农公式是理想上限真实调制编码方案在低 SINR 下有接近 1.5 dB 的缺口但用来做相对评估已经够用。def shannon_rate_db(sinr_db, bandwidth_mhz10): # sinr_db: 用户SINR单位dB # bandwidth_mhz: 信道带宽单位MHz sinr_linear 10 ** (sinr_db / 10.0) rate_mbps bandwidth_mhz * np.log2(1 sinr_linear) return rate_mbps # 对第3章收集到的 sinr_samples 做转换 rates_mbps shannon_rate_db(sinr_samples, 10) avg_rate_mbps np.mean(rates_mbps) edge_rate_mbps np.percentile(rates_mbps, 5) print(f平均速率: {avg_rate_mbps:.2f} Mbps, 5%边缘速率: {edge_rate_mbps:.2f} Mbps)sinr_samples来自第 3 章的蒙特卡洛循环。速率计算之后平均速率反映整个网络的总吞吐潜力5% 分位点反映小区边缘用户体感。5G 用户体验评测普遍要求边缘速率不低于几 Mbps用这个指标可以对 PPP 仿真结果做基准判断。注意这个速率是在“每个用户独享全部带宽”假设下计算的。如果所有用户平分带宽需要把速率除以同一时刻的用户数或者引入资源调度的简化模型把每个小区总速率算出来再按用户权重做分配。基于 PPP 的直接统计会把好用户和差用户一起平均这显然偏向乐观。5.2 小区边缘与整体性能对比对不同的基站密度 λ 做扫参能更清晰地看出 PPP 模型的价值。λ 增大时平均速率上升但边缘速率先上升后饱和原因是新增基站带来干扰增强而边缘用户离多个基站的距离同时缩短。我在做过的一次典型仿真里λ 从 1e-6 升到 1e-5 时平均速率从 12 Mbps 升到 45 Mbps5% 边缘速率从 2 Mbps 升到 8 Mbps继续升到 1e-4平均速率到 90 Mbps边缘速率只到 11 Mbps。这是超密网络里常见的“边际收益递减”现象。这一段仿真结果可以通过以下方式复现lambda_list [1e-6, 3e-6, 1e-5, 3e-5, 1e-4] for lam in lambda_list: _, sinr_snap coverage_monte_carlo(lam, [2000, 2000], n_snapshot2000, n_users50, sinr_threshold0, seed1) rates shannon_rate_db(sinr_snap, 10) print(fλ{lam:.1e}: mean{np.mean(rates):.1f} Mbps, fedge{np.percentile(rates, 5):.1f} Mbps)参数说明n_snapshot2000是快照数n_users50是每快照用户数这样总有效采样为 10 万用户足够稳定。lambda_list用对数等距方式取值便于观察幂律特征。如果看到边缘速率波动很大先去检查是否固定了 seed再检查用户是否偶然落在基站极密集的角落。5.3 怎么把覆盖率结果画成曲线覆盖率随门限变化的曲线通常横轴是 SINR 门限纵轴是该门限下的覆盖概率。做法是对sinr_samples取不同门限的平均而不是对多个覆盖率做平均。thresholds_db np.linspace(-10, 30, 41) coverage_curve [np.mean(sinr_samples t) for t in thresholds_db] import matplotlib.pyplot as plt plt.plot(thresholds_db, coverage_curve) plt.xlabel(SINR threshold (dB)) plt.ylabel(Coverage probability) plt.grid(True) plt.show()这条曲线可以直接和随机几何教科书里的理论覆盖曲线做视觉对比典型特征是 S 形低门限时接近 1高门限时趋近 0拐点大致在 0 dB 附近。如果曲线明显不平滑先确认样本量是否够再确认是否混入了保护带之外的基站。6. 验证仿真结果理论覆盖概率对照法写一个 PPP 蒙特卡洛仿真很容易难的是确保它没有逻辑漏点。常见问题包括路径损耗公式距离单位错误、保护带不够、用户与基站坐标重合造成无穷大。验证的方法不靠人肉盯代码而是找一个有闭式解的基线场景把仿真输出和理论曲线放在一起对比。在单连通网络、瑞利衰落、路径损耗指数为 3.5 的条件下覆盖概率有一个著名的闭式表达式常见形式是def theoretical_coverage(lambda_density, threshold_linear, alpha3.5): # 闭式解将信道功率视为指数分布干扰为PPP冲激响应求和 # 归一化后计算概率这里用数值积分近似 import scipy.integrate as integrate integrand lambda v: np.exp(-np.pi * lambda_density * (v ** (2 / alpha)) * threshold_linear) # 推导结果本质为 e^{-something} 在v上的积分 result, _ integrate.quad(integrand, 0, np.inf) return result这个表达式对应的前提是每个用户关联最近的基站路径损耗指数均匀为 α快衰落为瑞利分布噪声忽略不计。你不需要背这个积分关键是拿它做交叉验证。做法是让仿真也设置成无噪声、只有干扰、采用同一个 α 的纯路径损耗模型然后把覆盖率曲线和理论线叠加。如果仿真结果在 95% 置信区间内贴合理论线说明 PPP 生成和距离计算没有毛病。具体验证步骤建议这样控制变量。先关掉阴影衰落和噪声只保留路径损耗和干扰再把仿真区域放大到 3000 m 以上加 1000 m 保护带最后把快照数提到 5000。满足这三个条件后仿真曲线与理论曲线偏差应小于 0.02。如果偏差明显优先检查是否把路损公式写成log10(d)而不是log10(d/1000)。另一个更快的验证技巧是强制 λ 很小比如 1e-7这时候相邻基站间距极大用户大概率只能看到一个基站SINR 退化为中心用户只受噪声影响的情况。你可以手动算出理论噪声限制下的覆盖率再和仿真对比。这个方法不需要 scipy 积分甚至不需要理论闭式解适合仿真代码的自检。在完成对照验证之后可以把这段校验代码封装成一个函数放进仿真工程里每次改动信道参数或区域大小后先跑校验再跑业务曲线。最后留一个个人习惯仿真输出时把seed、λ、区域边长、快照数、保护带长度一起打印到日志里。没有这些现场信息任何覆盖率数据都是不可复现的。数据对齐之后整个 PPP 蒙特卡洛蜂窝仿真才算真正闭环。本文还有配套的精品资源点击获取
返回列表