☰
LEACH与HEED协议对比仿真:Matlab实现与能耗分析
2026/10/22 14:40:39 网站建设 项目流程

简介:面向无线传感器网络研究者的Matlab仿真资源,聚焦LEACH与HEED两种经典分簇路由协议的性能对比。资源适用于本科、硕士阶段教研学习,可帮助理解不同协议在能耗、存活节点、吞吐量等核心指标上的差异,并可借助MATLAB 2021a环境复现结果。压缩包共7个文件,包含6个M脚本与1个操作演示录像,M脚本用于参数配置、运行仿真及结果统计分析,录像则完整展示从启动到出图的操作流程,便于对照实操。已有240人学习下载。除代码与录屏外,资源还打包了完整对比实验的组织方式,可支撑课程设计、毕业设计或论文仿真环节,降低上手门槛,缩短调试验证时间。

1. 单轮随机选簇头就是LEACH的命门:为什么WSN性能对比总把它当基准

无线传感器网络WSN的论文和课程设计里,LEACH和HEED这对老对手出现频率极高:LEACH靠单轮随机轮换簇头成名,HEED则想在能量均衡上更进一步。很多人以为这是一场新旧协议的对决,实际拉开差距的往往是仿真参数和统计口径。用Matlab跑完整个对比工程你会发现,能耗、存活节点、吞吐量三条曲线里,哪条先出现拐点、哪个协议先死透,背后全是簇头选举概率和能量阈值在起作用。这份资源自带matlab2021a可跑的完整脚本和操作录像0033.avi,适合本硕教研中做协议对比但不想从零搭仿真的人。

2. LEACH与HEED的协议机制:簇头选举和能耗模型的三个关键差异

2.1 LEACH的簇头选举流程:从随机阈值到轮次推进

LEACH把网络生命周期切成很多轮,每轮先选簇头再传数据。簇头选举的核心是那个阈值公式:节点生成一个0到1之间的随机数,如果小于当前轮次对应的阈值T(n),这轮就当簇头。T(n)的常见写法是:

% LEACH每轮簇头选举:阈值随机判定的核心逻辑 % p是期望簇头比例,r是当前轮次,G是本轮未担任过簇头的节点集合 function isCH = leach_decision(r, p, isMember, randVal) % 只有没当过簇头的节点才参与选举 if isMember Tn = p / (1 - p * mod(r, round(1/p))); isCH = (randVal < Tn); else isCH = false; end end

这里的关键参数是p,也就是簇头占节点总数的期望比例。常规取值是0.05到0.1。如果p设成0.1,每轮大约有10%的节点会成为簇头;但注意mod(r, round(1/p))会让阈值周期性重置,保证每个节点在1/p轮内至少有一次机会。随机数randVal是均匀分布的,所以每次仿真结果都会带有随机性——这既是LEACH的机制特点,也是后面对比仿真里最大的变量来源。

LEACH的簇头一旦选出,就要向全网广播自己当选的消息,普通节点选择最近的簇头加入,簇头给成员分配TDMA时隙。数据传递阶段,节点在自己的时隙内把感知数据发给簇头,簇头做数据聚合后再发给基站。整个过程中簇头的能耗远大于普通节点,所以LEACH用周期轮换来均摊这个高能耗角色。

2.2 HEED的迭代选簇头:把剩余能量和簇内代价写进概率

HEED对LEACH的改进点在于选簇头时不再只靠随机数,而是分主从两个指标。主指标是节点剩余能量与初始能量的比值,决定节点进入候选簇头集合的概率;从指标是簇内通信代价,通常是节点到候选簇头的平均最小可达功率。HEED的迭代过程要跑好几轮,每轮候选簇头按照概率决定是否成为最终簇头,直到达到停止条件。

% HEED候选簇头概率初始化:主指标用剩余能量比值 % Eresidual是节点剩余能量,Einit是初始能量 % CH_prob是候选簇头概率,Cprob是初始概率阈值参数 CH_prob = max(Cprob * (Eresidual / Einit), pmin); % 然后进入迭代:CH_prob低于阈值或邻居簇头数量满足条件即停止

这里的pmin是概率下限,防止剩余能量极低的节点彻底丧失当选资格,Cprob则控制初始参与迭代的候选规模。HEED选出的簇头数量比LEACH更稳定,簇头空间分布也更均匀,代价是每轮要多跑好几轮迭代消息,控制开销相应上升。

2.3 能耗模型与对比实验的公平性设置

对比LEACH和HEED,必须把能耗模型统一成同一个公式,否则对比不成立。常见做法是第一版无线通信能耗模型:发送l比特数据到距离d的节点,能耗分两种情况,d小于阈值d0时走自由空间模型,d大于等于d0时走多径衰落模型。接收数据时只算电路能耗。下面的代码是这套模型的标准实现:

% 无线传感器网络WSN统一能耗模型:发送和接收分开计算 % Eelec是电路能耗系数,Efs是自由空间能量系数,Emp是多径能量系数 % d0是两种传播模型的切换阈值,一般取sqrt(Efs/Emp) function Etx = energy_tx(l, d, Eelec, Efs, Emp, d0) if d < d0 Etx = l * Eelec + l * Efs * d * d; % 自由空间:距离平方衰减 else Etx = l * Eelec + l * Emp * d * d * d * d; % 多径:距离四次方衰减 end end function Erx = energy_rx(l, Eelec) Erx = l * Eelec; % 接收只算电路能耗,不收传播损耗 end

做对比时,两个协议必须使用完全相同的能耗参数、节点初始能量、基站位置以及数据包大小,否则对比结果没有说服力。通常还需要把节点部署的位置固定成同一个随机种子生成的拓扑,这样两套协议跑的是同一片网络,差异才能归因于协议本身。

3. 在Matlab2021a里复现对比工程:Runme.m的主流程与参数落点

3.1 目录结构与Runme.m的入口定位

这份资源的目录结构不复杂,核心是Runme.m脚本和操作录像0033.avi。先看入口脚本的组织方式:通常包含参数初始化、网络拓扑生成、主循环执行、结果统计与绘图四个部分。点开Runme.m直接跑是能出结果的,但为了不把它当黑匣子,最好从参数区开始逐段读。

3.2 参数初始化表与网络部署

仿真区域、节点数量、初始能量、基站位置这些参数集中在文件的起始区域。常见默认配置如下:

参数名常见取值作用
numNodes100无线传感器网络节点总数
networkSize100x100仿真区域边长
Einit0.5J每个节点初始能量
packetLength4000bit数据包长度
numRounds2000仿真最大轮数
baseStation(50, 175)基站位置

节点坐标通常用均匀随机分布生成,部署一次之后固定下来,保证LEACH和HEED在同一个网络里跑。基站放区域外是常见做法,这样所有节点到基站的距离差异比较明显,簇头聚合后的长距离传输能耗也不会糊成一团。

% 节点部署:固定随机种子生成同一拓扑,保证对比公平 rng(42); % 固定随机数发生器种子 for i = 1:numNodes node(i).x = rand * networkSize(1); node(i).y = rand * networkSize(2); node(i).energy = Einit; node(i).role = 'N'; % N代表普通节点,后续会被替换成CH node(i).alive = 1; end % 基站位置单独指定,不参与随机部署 base.x = 50; base.y = 175;

这段代码的rng(42)非常关键:没有固定种子的话,每跑一次仿真节点分布都不一样,两组协议的网络起点就不同了。固定种子之后,后续所有对比都建立在同一个部署上。

3.3 主循环框架:能耗、死亡判定与数据聚合的每轮推进

主仿真循环是Runme.m的核心。每轮先执行协议对应的簇头选举,再让普通节点向簇头发数据、簇头聚合后发往基站,最后更新每个节点的剩余能量并统计存活节点数。伪代码级别的流程如下:

for r = 1:numRounds % LEACH: 按阈值公式逐节点判定是否成为簇头 % HEED: 按迭代机制选出簇头,并处理簇内和簇间通信 % 每轮开始前先统计存活节点,节点能量小于等于0时标记死亡 alive = sum([node.alive]); stats(r).alive = alive; % 数据传输阶段:按协议规则计算发送和接收能耗 % 能量扣减后判断本轮是否有节点能耗尽 for i = 1:numNodes if node(i).energy <= 0 node(i).alive = 0; end end % 累计本轮汇总到基站的数据包数量,用于吞吐量指标 stats(r).throughput = stats(r).throughput + deliveredPackets; end

主循环里有个容易忽略的细节:死亡判定发生在能耗更新之后,节点能量第一次变为小于等于0的那一轮才标记为死亡,而不是在曲线里出现负值才开始统计。每轮都要对存活节点做一次广播、成簇和数据传输,计算量在节点数较多时会明显增加,所以轮数上限和节点数要匹配。

3.4 操作录像怎么用:复现时对录像找差异

操作录像0033.avi记录的是整套仿真从头跑到尾的画面。复现时先跑一遍Runme.m,再打开录像对照:如果录像里出现的曲线数值和你的结果差距很大,优先检查随机种子、能耗参数这两处,绝大多数不一致都出在rng没固定或者Einit/Eelec的大小没对上。录像不是用来逐帧看的,而是充当结果校验的参照物。

4. 能耗、存活节点与吞吐量:三条曲线怎么对应真实网络状态

4.1 总能耗与生命周期:从曲线斜率看网络平衡程度

仿真输出的总能耗曲线通常是单调递增的,但斜率变化很能说明问题。LEACH的曲线往往前期和HEED差别不大,中后期随着部分节点死亡,簇头选举可选的节点变少,剩余节点承担更多的数据传输任务,曲线斜率会变陡。HEED因为每轮簇头选举更均衡,节点能耗速度更平均,总能耗曲线的尾部通常更平滑。

观察能耗数据时,不要只看最终值,要看每百轮的平均能耗增量。LEACH在中后期可能出现某一段曲线几乎走平——这是大量节点死亡导致的实际参与传输节点变少的信号,不代表网络效率变高。注意区分这两种情况就是做对比分析时该有的基本意识。

4.2 存活节点的三个拐点:FND、HND与LND

存活节点曲线能直观反映协议的网络生命周期。通常记录三个关键时间点:第一个节点死亡轮次FND,一半节点死亡的轮次HND,以及最后一个节点死亡的轮次LND。LEACH的典型特征是第一个节点死亡较早但全部节点死完较晚,HEED则相反,首节点死亡晚但节点耗尽后的收尾速度快。

% 从stats结构体里提取存活节点曲线的关键拐点 % 返回第一个节点死亡、半数死亡、全部死亡的轮次 stats_vector = [stats.alive]; FND = find(stats_vector < numNodes, 1); % 首节点死亡 HND = find(stats_vector <= numNodes/2, 1); % 半数节点死亡 LND = find(stats_vector == 0, 1); % 全部节点死亡 % 绘图时把三条线画在一起,便于判断协议差异 plot(1:numRounds, stats_vector, 'LineWidth', 1.5);

这三个拐点分别刻画不同层面的性能:FND衡量网络对首个故障的敏感度,LND衡量网络的总寿命,两者的差距则反映能耗均衡程度。差距越大说明能耗越不均衡,节点先后死亡的时间差越大。

4.3 吞吐量的统计口径:聚合后数据量而不是感知包数量

吞吐量在WSN仿真里有多种统计口径。有的算所有节点发送的感知数据包总数,有的只算基站成功接收到的聚合后数据量。这份资源里的吞吐量曲线,统计的是最终到达基站的数据包数量,也就是只有簇头发给基站、且基站成功接收的才算数。这个口径能反映协议的端到端数据交付能力,不受簇内转发次数干扰。

统计时要注意别把节点发给簇头的过程包也计入,否则数值会明显偏高,和录像结果对不上。做法是在发送函数里区分data_type,只有发往基站的数据包才累加到throughput变量。

5. 仿真避坑清单:五个能让你白跑一整天的参数与随机性问题

5.1 存活节点曲线中期出现平台期后突然崩塌

现象:LEACH和HEED的存活节点曲线在前半段下降缓慢,到达某个点后突然快速掉到0,中间几乎没有过渡。 原因:簇头选举的阈值周期性重置,导致每个节点在每轮参与到网络传输中的概率存在周期性波动,实际通信链路分布不均匀,部分节点持续承担高负载而提前耗尽。 解决:检查p值是否过大或过小,p越大曲线越容易在后期出现集体死亡,p过小则节点死亡时间拖得很长。通常把p调整到0.05到0.1之间,再观察曲线过渡是否自然。

5.2 能耗曲线出现负增长或回退

现象:总能耗曲线不是单调递增,出现明显回退,甚至有的轮次能耗为负。 原因:节点能量扣减时用了绝对值而没有检查能量是否足够,或者接收能耗和发送能耗的系数不一致,导致能量更新时出现计算错误。 解决:每次能耗计算后加一行断言,确保节点能量不小于0。同时把所有能量系数统一到同一单位里,比如全部使用焦耳J,避免混用毫焦和微焦导致数值逻辑混乱。

5.3 HEED迭代不收敛,每轮簇头数量忽多忽少

现象:HEED跑出来的簇头数量每轮波动非常大,有时候簇头比普通节点还多,曲线完全无法对比。 原因:候选概率初始值Cprob和迭代停止阈值pmin设置不合理,节点在迭代中没有达到停止条件就提前退出,或者一直在候选状态里循环。 解决:把Cprob设成0.05,pmin设成0.0001,并保证迭代次数上限存在。我一般还会在迭代记录里增加一步调试输出,打印每轮簇头数量,确认收敛后再去跑完整对比。

5.4 换了电脑跑出来的结果和录像差很远

现象:同一份代码,在自己电脑上跑出的曲线和录像里完全不同,存活节点拐点差几十轮。 原因:代码里没有固定随机种子,两个协议各自的随机数序列在不同环境下生成不同的节点部署和簇头选举结果。 解决:在脚本最前面加rng(seed),seed取一个固定整数。再用这个种子分别跑LEACH和HEED,保证对比条件一致。录像里显示的曲线大概率是某个固定种子的结果,和它对不上时先换几个种子试试,直到趋势一致。

5.5 吞吐量数值异常大,动辄几万

现象:最终吞吐量比预期高出数倍,数据包总数看起来不像WSN该有的量级。 原因:统计时把普通节点发给簇头的过程包、簇头之间的转发包都计入了吞吐量,实际到达基站的数据反而没被单独统计。 解决:只统计最终发往基站的数据包,且只有基站确认接收才累加。做法是给数据包加一个类型标记,在接收端判断目标地址是不是基站地址,是才计入吞吐量。这个坑我不只一次踩过,每次以为跑出了优秀结果,仔细一看统计逻辑就发现问题。

6. 用固定随机种子还原完整对比,验证协议边界的几个习惯

复现这套仿真时,我最先做的事是建立一个固定随机种子的运行基线。调好参数后先跑三组:节点数50、100、150,每组的两种协议都固定同一个种子,记录FND、HND、LND和最终吞吐量四个值。接下来验证工作分三步走。

第一步,看FND轮的序位是否稳定。跑5次完全相同的参数,如果FND轮次波动超过20轮,说明随机性影响太大,对比结论不可靠。我一般会把种子固定在偶数编号,用rs1到rs5跑五轮,取中位数作为代表结果。

第二步,调整关键参数观察曲线移动方向。把LEACH的p从0.05调到0.15,看FND是提前还是延后;把HEED的Cprob从0.05调到0.1,看簇头数量曲线是变密集还是变稀疏。这一步能帮你确认代码写的是协议而不是抄了个名字,因为LEACH的簇头比例和存活曲线拐点存在明确的联动关系。

第三步,检查统计口径的一致性。跑完对比后,把吞吐量除以存活节点数再除以轮数,看单节点平均交付量是否在合理范围内。这个数值太大说明统计里混入了过程包,太小说明能量耗尽后节点停止发包的机制提前生效。

这套验证习惯帮我抓出过不少玄学问题,最典型的就是换了节点数量之后HEED的曲线反而比LEACH还差——排查下来是簇头迭代次数上限没跟着节点数调整,节点多了迭代没跑完就被截断。从那以后我每次跑对比都强制走一遍三步验证:固定种子建立基线,改参数看曲线方向,核对统计口径。这套操作做完,结果基本就能拿上台面了。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询