简介:面向无线传感器网络(WSN)节点覆盖优化问题的MATLAB仿真资源,适合通信工程、物联网方向的学生与科研人员,用于研究节点部署、覆盖盲区评估和优化算法实现。包内共9个文件,包括8份MATLAB脚本和1份FPGA与MATLAB交互说明文档。脚本按功能拆分为主仿真流程、条件约束设定、节点感知区域绘制、覆盖面积计算以及节点间距离求解等模块,结构清晰,便于按需调用和修改参数。压缩包仅2KB,轻量易读,无需复杂环境即可快速定位核心代码;目前已吸引828人学习下载,适合作为WSN覆盖优化仿真入门或课程设计参考。利用该资源可快速掌握从网络初始化、覆盖评估到图形化结果输出的完整仿真路径,并在此基础上扩展自身优化策略,例如调整节点数量、通信半径或部署方式。
1. 覆盖优化仿真不是撒点算覆盖率:先搞清楚优化的对象是什么
WSN无线传感器网络节点覆盖优化仿真,第一眼看上去像是“把传感器节点撒进区域、算算覆盖率”就算完事。实际跑过一版的人都知道,真正常见的翻车是:覆盖率明明算出来有90%,放大部署图一看,节点全堆在区域中心,边缘一大片盲区。这个仿真要解决的不是“覆盖率怎么算”,而是“覆盖率这个数字跟部署位置怎么挂钩、凭什么信它”。它把感知模型、覆盖率指标、优化算法放进同一个闭环里,给定节点数量和感知半径,自动输出一组更合理的部署坐标。适合两类人:一类是正在做WSN方向毕设或小论文、需要对比优化算法的研究生;另一类是在园区、农田、矿井这类场景做监测系统预研,想先评估节点数量和布局合理性的工程师。后面所有讨论都围绕这个闭环展开。
2. 感知模型与覆盖率量化:把模糊的“覆盖”翻译成可迭代的目标函数
覆盖仿真里的第一个分歧是:一个传感器节点在多大范围内能算作“覆盖了某个点”。真实射频环境里信号强度随距离衰减,还受遮挡、天气和多径影响,不存在绝对边界。但仿真不是越真实越好,而是要看它能不能为优化算法提供稳定、可计算的目标。这一章先定模型,再给一套能直接复用的覆盖率计算代码,最后解释为什么目标函数里只写覆盖率会翻车。
2.1 布尔感知与概率感知:两种主流感知模型的选取理由
布尔感知模型是最常见的圆盘假设:节点覆盖范围是一个以节点为圆心、感知半径R为半径的圆,网格点落在圆内覆盖率为1,圆外为0。它的优点是没有信道参数需要标定,计算量小,适合在大面积二维区域上做算法对比和部署方案评估,也是多数WSN覆盖优化论文的默认选择。如果目标是快速验证优化算法的相对提升幅度,布尔模型足够。
概率感知模型通常用一个随距离衰减的函数描述覆盖质量,例如覆盖概率p = exp(-α·d),其中d是网格点到节点的距离,α是衰减系数;或者设定一个最大感知半径,在半径内覆盖概率从1线性下降。这个模型更接近真实传感器特性,适合已经有具体传感器型号、需要评估检测概率或事件漏报的场景。代价是多了一个衰减系数要标定,而这个系数对优化结果的影响可能比节点位置还大,标定时要有实验数据支撑。
阴影衰落模型在概率感知基础上引入对数正态阴影项,需要路径损耗指数和阴影标准差两个额外参数。贴近实测但参数难调、重计算,通常只在做信道敏感类课题时才会用到。工程预研我会先用布尔模型做一轮粗筛,再用概率模型验证关键结论,不轻易上第三类模型。在MATLAB仿真里,这两类模型的切换只是把coverStat函数里的一段判定逻辑换掉,后面的粒子群优化框架完全不用动。
2.2 网格法算覆盖率:最小可复现代码与精度取舍
覆盖率计算的工程标准做法是网格法:把部署区域离散成均匀网格点,统计被至少一个节点覆盖的网格点占总网格点的比例。这个定义简单、可复现,也方便后续把覆盖率直接写进优化目标。下面这个函数同时输出覆盖率和冗余度,冗余度指的是被至少两个节点覆盖的网格点占比,后面优化目标要用。
function [coverage, redundancy] = coverStat(nodes, region, R, gridStep) % nodes: N x 2 矩阵,每行是一个节点的 [x, y] 坐标 % region: [xmin xmax ymin ymax],部署区域边界 % R: 感知半径 % gridStep: 网格步长,越小精度越高,计算量越大 xg = region(1) : gridStep : region(2); yg = region(3) : gridStep : region(4); [X, Y] = meshgrid(xg, yg); countMat = zeros(size(X)); % 记录每个网格点被几个节点覆盖 for i = 1 : size(nodes, 1) % 用平方距离比较,避免对每个点开根号,MATLAB矩阵运算会快很多 d2 = (X - nodes(i,1)).^2 + (Y - nodes(i,2)).^2; countMat(d2 <= R^2) = countMat(d2 <= R^2) + 1; end coverage = mean(countMat(:) > 0); % 至少被一个节点覆盖的网格点占比 redundancy = mean(countMat(:) > 1); % 至少被两个节点覆盖的网格点占比 end逻辑上就是三次遍历:先生成网格,再让每个节点对网格做一次“圆内标记”,最后统计覆盖占比。d2 <= R^2和d <= R完全等价,但省掉了sqrt这一步,在粒子群每轮要调用几千次这个函数时,节省的时间非常可观,这是仿真里一个实际影响速度的细节。
网格步长的选择是精度和计算量的直接权衡。100×100的区域,步长1会生成101×101共10201个网格点;步长0.1则生成约100万个点,计算量直接放大100倍。粒子群优化时每一步都要对每个粒子调用coverStat,几十个粒子迭代几百次,总调用次数上万,网格步长设得太细会让仿真时间从分钟级变成小时级。一般建议gridStep不超过R/10,感知半径15时步长取1即可。
提示:网格法计算的是“点覆盖率”,不是精确面积覆盖率。网格越细,数值越接近真实面积覆盖率;网格越粗,边界处误差越大。记录仿真结果时一定要同时记下gridStep,不同步长跑出来的覆盖率不能直接对比。
2.3 目标函数里加入冗余惩罚:为什么只算覆盖率会翻车
如果优化目标只写成“覆盖率最大化”,粒子群会快速找到一个看起来很好的解:所有节点往区域中心挤。原因是中心区域的网格点密度最高,节点堆在一起能同时覆盖同一批网格点,覆盖率数字很漂亮,但边缘大片区域完全裸露。这就是典型的“覆盖率会骗人”的场景。
解决办法是给目标函数加冗余惩罚,把覆盖率和冗余度合并成一个标量适应度。我的默认形式是:
fitness = coverage - lambda * redundancy
其中lambda是惩罚系数,取值一般在0.2到0.5之间。lambda太小起不到惩罚作用,节点还是会扎堆;lambda太大,粒子会过度追求分散,导致部分区域覆盖不足。经验上,N=30、R=15、区域100×100时,从lambda=0.4起步,看优化出的节点是否已经铺开,如果覆盖率比lambda=0时掉了超过三个百分点,就把lambda降到0.2再试。
这样处理后,粒子群会在“提高覆盖率”和“减少重叠覆盖”之间找平衡,节点的空间分布自然变得均匀,热力图里也不会出现大面积的深色高亮重叠区。如果课题要求做严格的多目标优化,可以把覆盖率和冗余度拆成两个目标,用NSGA-II或MOPSO跑Pareto前沿;但大多数覆盖优化仿真的目的只是得到一个合理的部署方案,带权重的单目标形式更省事,结果也更容易解释。
3. 用改进粒子群做覆盖优化:从标准PSO到自适应参数
覆盖优化的决策变量是N个节点的横纵坐标,这是一个2N维连续优化问题。粒子群算法的作用是找到一组坐标,让适应度值尽可能高。这一章先说明为什么选PSO,再给出粒子编码、速度位置更新和两个必调参数。
3.1 为什么选PSO而不是遗传算法或模拟退火
选优化算法时我主要看三个维度:决策变量是不是连续、实现成本高不高、收敛速度够不够。节点坐标天然是连续变量,粒子群的速度-位置更新直接作用在连续坐标上,不需要编码解码,几十行就能跑起来。遗传算法要把坐标编码成染色体,再做选择、交叉、变异,实现成本高,且在高维连续空间中交叉算子效率往往不如PSO。模拟退火是单点搜索,在这个问题里维度可能上百,单点搜索很难在有限迭代内覆盖足够大的解空间。
标准PSO本身是一个黑匣子,对学习因子、惯性权重、最大速度都很敏感。很多人直接套默认参数,结果跑出来的收敛曲线要么震荡发散,要么停在半路不动弹。我的做法是保留标准PSO的主干,只改两个地方:惯性权重随迭代线性递减,速度加一个上限钳制。既保留了和文献基准对比的公平性,又不容易跑一半发散。工具选择上,我一般用MATLAB脚本而不是Simulink来做这类迭代优化——Simulink更擅长连续系统仿真,粒子群是典型的离散迭代过程,脚本方式便于跟踪每个粒子的历史最优和绘制收敛曲线。
3.2 粒子编码与适应度计算:维度设计和坐标归一化
每个粒子用一行2N维向量表示,前N个分量是N个节点的x坐标,后N个分量是y坐标。解码时用reshape(pos, N, 2),一个操作就把向量还原成N行2列的坐标矩阵。粒子初始位置在部署区域内均匀随机生成,速度初始化为0。
function [pos, vel, lb, ub] = initPSO(popSize, N, region) % 初始化粒子群 % popSize: 粒子个数 % N: 传感器节点数 % region: [xmin xmax ymin ymax] dim = 2 * N; % 每个粒子是一个 2N 维向量 % 前N维是x坐标,后N维是y坐标,分别对应区域的横纵范围 lb = [region(1)*ones(1,N), region(3)*ones(1,N)]; ub = [region(2)*ones(1,N), region(4)*ones(1,N)]; % 在 [lb, ub] 内均匀随机生成初始位置 pos = rand(popSize, dim) .* (ub - lb) + lb; % 速度初始化为0,让第一代完全由个体最优和全局最优的差分驱动 vel = zeros(popSize, dim); end速度初始化为0而不是随机值,收敛过程会更平稳。如果初始速度给一组随机大值,前几代粒子会满场乱飞,适应度曲线前段会出现毛刺。坐标归一化方面,100×100这样的区域量级不归一化也能正常收敛;等到区域变成1000m×1000m或更大时,建议把坐标缩放到[0,1]区间,感知半径也同步除以区域边长,否则速度更新步长很难选到合适的量级,要么发散要么原地踏步。
维度是个容易被忽视的坑。N=50时dim=100,标准PSO在百维空间已经明显退化,收敛速度变慢,需要把种群规模加大到50~80个,或者把区域分成几块分别优化再做合并。节点数超过100时,建议直接考虑分块优化或改用其他算法,硬用标准PSO会浪费大量迭代时间。
3.3 线性递减惯性权重与边界钳制:两个直接影响收敛的参数
标准PSO的速度更新包含三项:惯性项带着粒子沿原方向前进,个体认知项把粒子拉向自己的历史最优,群体社会项把粒子拉向全局最优。惯性权重w的大小控制前一项的贡献:w大,粒子探索范围广,不容易陷入局部最优;w小,局部精修能力强,但容易早熟。实践中最稳的做法是让w随迭代线性递减,前期大范围探索,后期精细收敛。
for iter = 1 : maxIter % 线性递减惯性权重:探索向收敛过渡 w = 0.9 - 0.5 * (iter - 1) / (maxIter - 1); for p = 1 : popSize % 速度更新:惯性 + 个体记忆 + 群体引导三部分 v(p,:) = w .* v(p,:) ... + c1 * rand(1, dim) .* (pbest(p,:) - pos(p,:)) ... + c2 * rand(1, dim) .* (gbest - pos(p,:)); % 速度钳制:防止粒子速度无限累加导致发散 v(p,:) = max(min(v(p,:), vmax), -vmax); % 位置更新 pos(p,:) = pos(p,:) + v(p,:); % 位置边界钳制:直接把坐标拉回区域范围内 pos(p,:) = max(min(pos(p,:), ub), lb); % 解码成节点坐标,计算适应度 nodes = reshape(pos(p,:), N, 2); [cov, red] = coverStat(nodes, region, R, gridStep); fitness(p) = cov - lambda * red; % 更新个体历史最优和全局最优 if fitness(p) > pbestFit(p) pbest(p,:) = pos(p,:); pbestFit(p) = fitness(p); end if fitness(p) > gbestFit gbest = pos(p,:); gbestFit = fitness(p); end end % 记录本代全局最优的适应度,画收敛曲线用 trace(iter) = gbestFit; end参数上我的默认值是:惯性权重0.9线性降到0.4,学习因子c1=c2=1.5,速度上限vmax取区域对角线长度的5%到10%。100×100区域对角线约141.4,vmax取10左右比较合适。速度不钳制是仿真发散的常见原因——粒子速度一路累加,位置很快飞出区域,适应度断崖式下跌。位置边界用min/max直接复位比“反射”或“绕回”更稳,后两种方案会在区域边缘造成虚假的覆盖重叠,让覆盖率虚高。
如果迭代曲线前20代上升明显,之后长时间平稳甚至微降,多半是w后期减得不够或者vmax偏大。调小w_min到0.3或把vmax降到6,再观察曲线的尾部波动。这是粒子群调参里最日常的操作,没有玄学,就是看曲线改参数。
提示:连续30代全局最优没有更新时,给gbest加上一个均值为0、标准差为0.2R的高斯扰动,重新跑迭代,能救回不少“早熟”的粒子群。这个技巧比盲目调大c2稳定得多。
4. 完整仿真流程与参数标定:从随机部署到可复现的优化结果
这一章把前面所有模块拼成一个完整可运行的主脚本,并给出一组可以直接抄作业的默认参数。仿真的价值在于可以复现,所以实验条件和随机种子怎么定、结果怎么报告,都直接影响结论的可信度。
4.1 实验条件设计:区域大小、节点数、感知半径怎么搭配
设计仿真条件时,可以先用一个粗略的覆盖期望公式估算节点数量级。假设节点在区域内随机均匀部署,期望覆盖率约等于1 - exp(-N·π·R²/A),其中A是区域面积。这个公式源自泊松覆盖模型,在区域边界处会有偏差,但用来反推节点数量级非常实用。例如区域100×100,R=15,目标覆盖率85%,反推N约等于ln(10)×10000/(π×225)≈29个,仿真就从30个节点起步。
下面是一组常用的场景参数搭配,可以直接作为实验设计参考:
| 场景 | 区域大小 | 节点数 | 感知半径 | 网格步长 | 优化后预期覆盖率 |
|---|---|---|---|---|---|
| 开阔园区 | 100×100 | 30 | 15 | 1 | 92%~96% |
| 室内车间 | 50×50 | 20 | 10 | 1 | 85%~92% |
| 大规模分区 | 200×200 | 80 | 20 | 2 | 88%~94% |
仿真目标不是让覆盖率无限接近100%,而是在同样节点数下,优化后比随机部署提升多少、冗余度压到多少。我一般要求优化后覆盖率比随机部署高8到10个百分点,冗余度比随机部署明显下降。如果提升幅度不够,先检查感知半径和节点数是否匹配,再回头查适应度函数有没有写错,而不是急着换算法。
4.2 主仿真脚本结构:初始化、迭代、结果输出的完整代码框架
把前面几个函数串起来,就是一份完整的WSN覆盖优化仿真主脚本。代码里加了随机部署对照组,方便直接看出PSO带来了多少提升。
% WSNCoverOpt_demo.m 节点覆盖优化仿真主脚本 clear; clc; rng(42); % 固定随机种子,保证结果可复现 region = [0 100 0 100]; % 部署区域 [xmin xmax ymin ymax] N = 30; % 传感器节点数 R = 15; % 感知半径 gridStep = 1; % 覆盖率网格步长 popSize = 30; % 粒子群种群规模 maxIter = 200; % 最大迭代次数 lambda = 0.4; % 冗余惩罚系数 % 1. 随机部署作为对照组 nodes0 = [region(1) + (region(2)-region(1))*rand(N,1), ... region(3) + (region(4)-region(3))*rand(N,1)]; [cov0, red0] = coverStat(nodes0, region, R, gridStep); fprintf('随机部署: 覆盖率 %.2f%%, 冗余度 %.2f%%\n', cov0*100, red0*100); % 2. 粒子群初始化与迭代优化 [pos, vel, lb, ub] = initPSO(popSize, N, region); [gbest, trace] = runPSO(pos, vel, lb, ub, region, R, gridStep, lambda, maxIter); % 3. 结果输出 nodesOpt = reshape(gbest, N, 2); [covOpt, redOpt] = coverStat(nodesOpt, region, R, gridStep); fprintf('PSO优化后: 覆盖率 %.2f%%, 冗余度 %.2f%%\n', covOpt*100, redOpt*100); % 4. 对比图:左边随机部署,右边优化部署 subplot(1,2,1); plot(nodes0(:,1), nodes0(:,2), 'bo'); axis([region(1) region(2) region(3) region(4)]); title(sprintf('随机部署 覆盖率%.1f%%', cov0*100)); subplot(1,2,2); plot(nodesOpt(:,1), nodesOpt(:,2), 'ro'); axis([region(1) region(2) region(3) region(4)]); title(sprintf('PSO优化 覆盖率%.1f%%', covOpt*100));脚本结构很直接:固定随机种子,初始化粒子,跑迭代,输出结果。rng(42)这行很多人会忽略,但没有它,每次运行结果都不同,实验记录根本没法写。随机部署那两行生成坐标时,注意要写成region(1) + (region(2)-region(1))*rand,而不是region(2)*rand,否则坐标可能跑到区域外。
runPSO返回的trace是每一代全局最优适应度,画成曲线可以直观判断收敛情况。如果曲线尾部还在明显上升,说明maxIter不够,要加大迭代次数或调快收敛速度;如果曲线前20代就平坦得像直线,说明w下降太快或种群多样性不足,用3.3里的扰动技巧处理。
4.3 直接抄作业的默认参数表与预期结果
下面这组参数是100×100区域、直径级别感知半径场景下的默认配置,经过多轮实验验证,可以直接作为起点使用:
| 参数 | 取值 | 说明 |
|---|---|---|
| 部署区域 | [0 100 0 100] | 正方形区域,便于网格划分 |
| 节点数 | 30 | 由覆盖期望公式估算得到 |
| 感知半径 | 15 | 网格步长取1时,R/10=1.5,步长满足精度要求 |
| 网格步长 | 1 | 覆盖率计算精度与速度的平衡点 |
| 种群规模 | 30 | 一般取节点数的1倍左右 |
| 最大迭代 | 200 | 尾段应出现平稳收敛 |
| 惯性权重 | 0.9 → 0.4 | 线性递减,前期探索后期收敛 |
| 学习因子 | c1=1.5, c2=1.5 | 个体与群体引导均衡 |
| 速度上限 | 10 | 区域对角线长度的7%左右 |
| 冗余惩罚系数 | 0.4 | 让节点分散,避免扎堆 |
按这组参数运行,随机部署的覆盖率通常在85%到88%之间,PSO优化后能达到93%到96%,冗余度会从25%以上降到15%以下。注意具体数字会因随机种子浮动,正式实验时每个配置用10个不同种子跑10次,报告平均值和标准差。这个习惯在写论文时尤其重要,单次结果说明不了任何问题。
5. 覆盖优化仿真避坑指南:5个高频翻车点与排查方法
这一章列5个我做这个课题时真实踩过、或者帮别人排查过的高频问题。每条按现象、原因、处理的顺序写,可以直接对照自己的仿真结果排查。
5.1 优化过程发散:覆盖率先涨后崩
现象:适应度曲线前几十代稳步上升,中段以后突然断崖式下跌,甚至掉到0附近,然后又在下一轮恢复。整个曲线像锯齿一样,完全不收敛。
原因:绝大多数情况是节点坐标飞出了部署区域。粒子速度不断累加,位置更新后超出[0,100]的范围,coverStat统计的网格点落在区域外,覆盖率瞬间归零。位置被拉回边界后适应度又恢复,所以曲线反复剧烈波动。根本原因是速度没有钳制,或者vmax设得过大。
处理:按3.3的代码对速度和位置都做钳制。vmax取对角线长度的5%~10%,位置每代用min/max复位到区域内。这一步加上之后,发散问题基本绝迹。如果还在发散,检查coverStat里网格点生成方式,确认xg和yg没有把网格点生成到区域外。
5.2 适应度曲线阶梯状停滞:粒子群早熟
现象:曲线不是平滑上升,而是一段平台、一段跳升,有时候60代之后彻底不动,覆盖率明显低于同参数其他随机种子下的结果。
原因:粒子群早熟,所有粒子都挤到了同一个局部最优峰附近,失去了跳出能力。常见诱因是惯性权重w后期降得太低,线性递减到0.2以下后粒子几乎没有探索动力;也可能是种群规模相对维度太小,N=50时种群只有20个,多样性严重不足。
处理:把w_min从0.3以下调回0.4,先看曲线是否恢复活力。如果还不行,对gbest加高斯扰动重跑,或者每30代把适应度最差的20%粒子重新随机初始化。判断是否早熟的标准是全局最优连续多代不更新,单纯看“迭代次数到了”没有意义。
5.3 每次运行结果都不一样:随机种子与初始化
现象:同一套参数,第一次跑覆盖率94%,第二次91%,第三次又变成96%。写实验记录时根本不知道填哪个数。
原因:MATLAB的rand默认以系统时间作为种子,每次运行的初始粒子位置、速度随机数序列都不同。PSO本身有随机性,结果有方差是正常现象,但没有固定种子时,方差会掺杂进每次运行的初始条件差异里,让结果对比失去意义。
处理:正式实验前用rng(42)固定种子,确保每次运行拿到同一套随机数。做算法对比时,每个配置固定使用同一个种子序列,保证公平。报告结果时,用10个不同种子各跑一次,计算均值和标准差,写进论文里。这样得出的结论才能顶得住评审复现检查。
5.4 覆盖率对网格分辨率太敏感
现象:gridStep=1时覆盖率94%,把gridStep改成2再跑,覆盖率变成90.5%,改回1又恢复。结论随网格步长飘移,没法信。
原因:网格离散后,位于两个网格点之间的半覆盖区域要么被计入、要么被漏掉。尤其感知半径边界附近的网格点,步长一改覆盖判定就变。这不是覆盖率计算代码写错,是离散化固有的边界效应。
处理:让网格步长最多等于R/10,感知半径15时步长取1比较稳。记录结果时必须同时记下gridStep,不同网格分辨率下算出的覆盖率不能直接对比。上报实验结论时统一用同一个网格尺度,不要混着用。
5.5 覆盖率很高但节点扎堆:缺了冗余惩罚
现象:优化结束覆盖率97%,部署图里能明显看到节点坐标在中心区域几乎重合,边角却有大片空白。覆盖率数字很漂亮,但部署方案明显不合理。
原因:适应度函数里只有覆盖率,没有对“同一网格点被多个节点重复覆盖”做惩罚。粒子群里每个粒子都会发现一个作弊手段:把节点往中心集中,一遍遍覆盖同一批网格点,边缘区域离得远、贡献低,干脆不覆盖。
处理:把冗余度纳入适应度,用fitness = coverage - lambda * redundancy。lambda从0.3起步,观察节点是否分散开。如果覆盖率下降超过3个百分点,调小lambda到0.2。要彻底避开这个坑,优化后的部署图必须和热力图一起看,不能只看一个覆盖率数字。
6. 覆盖热力图与节点失效测试:让仿真结果更接近真实部署
优化结束不要只盯着一个覆盖率数字。两个手段能把仿真结果和真实部署需求对齐,也是我每次跑完必做的验证。
第一个是覆盖热力图。coverStat里生成的countMat记录了每个网格点被几个节点覆盖,直接用contourf画出来,盲区和重叠区一目了然:
% 用coverStat内部的countMat直接画图 xg = region(1) : gridStep : region(2); yg = region(3) : gridStep : region(4); [X, Y] = meshgrid(xg, yg); figure; contourf(X, Y, countMat, 20); colorbar; xlabel('x / m'); ylabel('y / m'); title('覆盖重数热力图');countMat值为0的区域就是盲区,等于1是单节点覆盖,大于等于3说明存在严重冗余。很多时候只看覆盖率数字不会发现边缘有一条带状盲区,热力图一画出来就暴露了。看到盲区后,优先检查是不是边界栅栏效应导致的网格点稀疏,其次再考虑增加节点或调感知半径。
第二个是节点失效测试。真实WSN里节点会坏、会掉电、会被遮挡,部署方案必须有一定冗余度。按比例随机移除节点,观察覆盖率衰减幅度:
% 从优化后的部署方案中随机移除节点,测试覆盖率保持能力 for removeNum = [round(N*0.1), round(N*0.2), round(N*0.3)] idx = randperm(N, removeNum); nodesLeft = nodesOpt; nodesLeft(idx,:) = []; % 移除被选中的节点 [covLeft, ~] = coverStat(nodesLeft, region, R, gridStep); fprintf('移除 %d 个节点: 覆盖率 %.2f%%\n', removeNum, covLeft*100); end一般要求移除10%节点后覆盖率下降不超过2到3个百分点。如果下降过大,说明少数节点承担了过重的覆盖任务,方案冗余度不足。这时回到第4章的参数表,把lambda调小一些、允许节点有一定重叠,或直接增加节点数,再重新优化。
我的习惯是每次跑完优化先画热力图,再跑失效测试,最后才把覆盖率数字写进实验报告。以前有一版结果覆盖率93%,热力图上边缘全是countMat等于1的薄覆盖区,失效测试移除5个节点后覆盖率直接掉到85%,方案脆弱性暴露无遗。从那以后我不再只信一个覆盖率数字。这个流程也同样适用于你的WSN无线传感器网络节点覆盖优化仿真课题,希望帮到你。
本文还有配套的精品资源,点击获取