LEACH、LEACH-C与TS-I-LEACH的Matlab仿真对比分析
2026/9/17 4:49:58 网站建设 项目流程

处理无线传感器网络仿真的朋友,多半绕不开LEACH这个名字。作为WSN路由协议里教科书级别的存在,LEACH从2000年被提出到现在,已经被反复引用、改造、吐槽、再改造了二十多年。我自己在Matlab里复现LEACH、LEACH-C以及一批改进协议时,感触最深的是:网上能下载到的代码不少,能讲清楚算法为什么这么设计、参数为什么这么取、曲线为什么长成这样的文章却不多。这篇博客就围绕LEACH、LEACH-C和TS-I-LEACH三种协议,把协议机制、Matlab复现思路、结果对比和踩坑经验一次说透,给正准备做传感器网络方向课程设计、论文复现或者工程预研的读者一条能直接照着走的路。

1. 项目背景与整体研究思路拆解

1.1 为什么研究LEACH:无线传感器网络的能量困境

无线传感器网络的基本工作方式很直白:大量廉价节点被撒在一片区域内,各自采集温度、湿度、振动或者位置数据,然后把数据送到基站。问题在于节点是用电池供电的,一旦部署到野外或者楼宇夹层里,换电池基本不可能。因此“省电”就成了整个网络设计的第一目标,比延迟、带宽都更优先。

如果什么都不做,每个节点直接把数据发给放在区域外边的基站,会怎么样?用下面的能耗模型算一下就知道了。这里可以套用一个非常经典的无线电能耗模型:

发送设备要消耗两部分能量:一部分是电路运行需要的固定成本,另一部分是信号放大器的发射成本,后者跟距离的平方甚至四次方成正比。也就是说,一个离基站100米以上的节点发包,消耗的能量会比把数据先交给身边20米远的簇头、再让簇头统一转发高出一个数量级。直接传输模式下,外围节点很快就没电,网络会从边缘开始快速崩溃。

LEACH的核心思想就是“分簇+轮换+聚合”。它在每一轮里选一小部分节点当簇头,普通节点把数据发给离自己近的簇头,簇头把收到的数据压缩、融合之后统一发给基站。同时簇头是随机轮换的,不让某个节点一直当“出头鸟”。这套机制在能耗均衡上比直传有了质的提升,正好解决了传感器网络最难受的能量困境。

1.2 LEACH、LEACH-C、TS-I-LEACH的技术演进逻辑

LEACH是分布式思路:每个节点自己判断要不要当簇头,判断依据是一个和轮数、历史当选次数相关的随机阈值。优点是协议开销小、扩展简单,缺点是簇头分布完全靠“运气”,有时两个簇头挨在一起,有时某片区域一个簇头都没有,区域边缘的节点不得不跨越很远的距离找簇头,反而更费电。

LEACH-C在这个基础上做了集中式改造,C全称是Centralized。每轮开始时,所有节点把自己的位置和剩余能量发给基站,基站掌握全局信息后,用模拟退火之类的优化方法计算出一组“位置分散、剩余能量靠前”的簇头组合,再广播给全网。因为基站看到了所有节点,簇头分布通常比LEACH均匀,网络寿命也更好看。代价是每一轮多出一次全网收集信息的过程,而且基站挂掉或者通信受阻时整个网络就没法工作了。

TS-I-LEACH这一类协议,是后来的研究者针对LEACH和LEACH-C各自的短板做的改进。TS一般可以理解成Two-Stage,即“两阶段”,一阶段把剩余能量和到基站的距离引入簇头选举,避免低能量节点继续硬撑;二阶段在数据传输时引入中继、副簇头或者动态时隙分配,减少簇头长距离单跳发送的能耗。不同论文里具体细节会有差异,但大方向基本一致:要让高能量节点多干活,让低能量节点少背书,让远距离的传输走台阶而不是一步跨过去。

1.3 公平对比的实验设计思路

研究协议改进时,最忌讳的是拿自己的改进协议和别处抄来的“原版”代码比,因为两套代码可能用了完全不同的能耗系数、包长度或者死亡判定标准,比出来的差距根本说不清是哪一步造成的。

我这次对比实验的总体设计原则是:固定一切外部条件,只切换路由策略层。仿真区域统一100米×100米,100个节点随机撒点,基站放在(50, 175)的区域外上方,初始能量统一0.5焦耳,数据包4000比特,控制包200比特,信道模型和能量参数严格套用LEACH原始论文里的经典配置。这样LEACH、LEACH-C、TS-I-LEACH三种协议跑完,差异只可能来自协议本身。

在指标层面,我同时记录三组数据:第一死亡节点轮数(FND,First Node Dies)、半数节点死亡轮数(HND,Half Node Dies)和最后一个节点死亡轮数(LND,Last Node Dies)。只看LND容易被少数续航特别长的节点误导,一定要三个指标结合起来看,才能知道协议到底是把能量用得更均匀,还是单纯让个别节点苟得更久。

2. 三种协议的核心机制与差异点解析

2.1 LEACH的运行流程与阈值公式

LEACH把时间划分成轮,每一轮分成两个阶段:成簇阶段和数据稳定传输阶段。成簇阶段里,每个节点根据阈值公式决定自己是否竞选簇头:

T(n) = p / (1 - p * (r mod (1/p))),当 n ∈ G T(n) = 0,其他情况

其中p是期望的簇头比例,通常取0.05;r是当前轮数;G是最近1/p轮里没有当过簇头的节点集合。这个公式为什么长这样?可以这样理解:每一轮中当过簇头的节点不再参选,剩下的节点把概率“瓜分”掉,所以随着这一轮周期推进,剩余节点的当选概率会越来越大。比如p=0.05时,每20轮一个周期,第0轮每个节点当选概率是0.05,到第18轮左右,最后几个没当过簇头的节点阈值会接近1,几乎“强制”当选。

提交论文或者做仿真时的一个通用配置如下:

参数数值说明
节点数量100经典仿真规模
区域100m × 100m方形区域
基站位置(50, 175)区域外部上方
初始能量0.5J每个节点一致
数据包长度4000bit每轮发一个包
控制包长度200bit广播/应答
簇头比例p0.05期望簇头数约5个
Eelec50nJ/bit电路耗能
Efs10pJ/(bit·m²)自由空间功放
Emp0.0013pJ/(bit·m⁴)多径功放
EDA5nJ/bit聚合耗能

稳定传输阶段会把时间分成若干帧,簇内所有节点按TDMA时隙轮流把数据发给簇头,发完就进入睡眠状态,簇头收齐后做一次数据聚合,再统一发给基站。这里有个容易漏掉的细节:TDMA时隙是簇头在成簇阶段分配的,仿真里如果只看逻辑不看时隙,就会发现所有节点“同时”向簇头发包,能量计算没什么差别,但如果后面要做改进协议,比如动态时隙分配,这一步就必须显式建模。

2.2 距离阈值d0与能耗模型的正确使用

通信能耗模型有一个重要的分支判断:

d0 = sqrt(Efs / Emp) 发送k比特到距离d: 如果 d < d0,E = k * Eelec + k * Efs * d^2 否则 E = k * Eelec + k * Emp * d^4 接收k比特: E = k * Eelec 聚合k比特: E = k * EDA

把上面的数值代进去,d0约等于87.7米。也就是说,距离小于87.7米时按自由空间模型,信号衰减随着距离按平方增长;超过87.7米后按多径衰落模型,按四次方增长,能耗会迅速膨胀。

我经常拿一组数字给人演示分簇的价值。发4000比特数据到50米外的簇头,耗能大约是:

电路部分:4000 × 50e-9 = 0.0002 J 功放部分:4000 × 10e-12 × 2500 = 0.0001 J 合计:0.0003 J

同样4000比特,如果直接发到125米外的基站:

电路部分:4000 × 50e-9 = 0.0002 J 功放部分:4000 × 0.0013e-12 × (125^4) ≈ 0.00127 J 合计:约0.00147 J

两者差了将近5倍。这就是分簇协议能省电的根源——它把绝大多数长距离传输压缩成了少数几个簇头承担,其余节点基本都在小范围短距离通信。簇头虽然额外背了聚合和转发的能量开销,但因为总数少、轮换快,整体能量消耗曲线反而比“各发各的”平滑得多。

2.3 LEACH-C:基站集中式簇头分配

LEACH-C和LEACH的分水岭在簇头选举上。LEACH-C每一轮先执行一个“收集阶段”:所有节点把当前坐标和剩余能量发到基站。基站先计算全网平均剩余能量,只有能量高于平均值的节点才有资格进入候选簇头集合,这一步直接排除了低能量节点继续当簇头的可能性。

接下来基站用模拟退火算法寻找最优组合。目标函数通常是让所有非簇头节点到最近簇头的距离平方和最小,这样选出来的簇头会比较均匀地铺满整个区域。计算完成后,基站把簇头集合广播出去,普通节点选择距离最近的簇头加入,后续的数据传输阶段和LEACH保持一致。

我需要提醒一点:LEACH-C在仿真中很容易看起来比LEACH“好看”,但这背后有隐含成本。每轮全网节点都要向基站报告位置和能量,这个控制开销在真实系统中不可忽视。如果仿真时只计算数据包的能耗、漏掉控制包,就会在对比结果里人为抬高LEACH-C的优势。严谨的实验中,收集阶段的上行控制和下行的广播分配消息都应该计入节点和基站的能耗。

2.4 TS-I-LEACH类改进协议的常见设计框架

TS-I-LEACH在我看到的多数版本里,思路是“两阶段优化”,而不是推翻LEACH重来。第一阶段改选举,第二阶段改传输。

选举阶段的常见改法是把剩余能量和位置信息加权进阈值公式,比如:

T(n) = p / (1 - p * (r mod (1/p))) * (E_current / E_initial) * (d_max / d_to_BS)

这样做有一个很明显的变化:能量高的节点和离基站近的节点,当选概率更大。离基站远、又快没电的节点,会尽量避开簇头身份,保住自己那点能量用于发送普通数据。

传输阶段的改法常见有三种:一是簇头到基站距离较远时,找中间位置的簇头做中继,让长距离单跳变成两跳或三跳;二是引入副簇头,主簇头负责接收和聚合,副簇头负责转发;三是重新设计TDMA时隙,让数据量大的节点获得更长时隙,避免低负载节点空等。具体选哪种,要结合应用场景。如果区域小、基站距离近,副簇头的收益有限;如果区域很大,中继转发往往更直接有效。

2.5 三种协议的定位对比

协议成簇方式簇头选举依据全局信息主要开销优势短板
LEACH分布式自选举随机阈值不需要实现简单、扩展性好簇头分布不均,远距离节点易早死
LEACH-C基站集中决策剩余能量+位置优化需要每轮一次全网收集簇头分布更均匀,寿命更长依赖基站,控制开销大
TS-I-LEACH类分布式+加权能量/距离等多因素通常不需要中等兼顾能量均衡和生命周期额外判断逻辑,参数调优成本高

这张表在论文的引言和相关工作部分非常好用,直接拿来当“机制对比表”也不算注水。

3. Matlab仿真环境与完整实现过程

3.1 环境准备与参数初始化

Matlab做这种离散事件仿真不需要额外工具箱,纯脚本就能跑。我自己用的是R2021b之后的版本,但说实话,这套代码从R2016a到R2023b都能跑,因为没用到什么新语法特性。唯一要注意的是保持向量化写法,不要让100个节点×3000轮的仿真跑出“等待十分钟”的体验。

初始化代码直接给出一个可用的模板:

% 参数定义 N = 100; % 节点个数 areaL = 100; % 仿真区域边长 BS = [50, 175]; % 基站坐标 E0 = 0.5; % 初始能量 p = 0.05; % 簇头比例 rmax = 3000; % 最大轮数 Eelec = 50e-9; % 电路耗能,J/bit Efs = 10e-12; % 自由空间功放系数 Emp = 0.0013e-12; % 多径功放系数 EDA = 5e-9; % 聚合耗能 d0 = sqrt(Efs / Emp); % 距离阈值,约87.7m packetLen = 4000; % 数据包,bit ctrlLen = 200; % 控制包,bit % 节点初始化 rng(2021); % 固定随机种子,保证结果可复现 S.x = rand(1, N) * areaL; S.y = rand(1, N) * areaL; S.E = E0 * ones(1, N); S.type = repmat("N", 1, N); % 节点身份:N普通节点,C簇头 S.G = zeros(1, N); % 是否在本周期内当过簇头 S.dist2BS = sqrt((S.x - BS(1)).^2 + (S.y - BS(2)).^2);

固定随机种子这一步千万别省。没有rng固定种子的话,每跑一次结果都不同,你根本没法判断一个改动是真实提升还是运气好。我自己习惯仿真一次就换一个不同种子跑30遍取平均。

3.2 能量更新函数与坐标距离计算

发送能耗计算最好封装成函数,后面三种协议共用,避免改一处忘一处:

function E_tx = txEnergy(k, d, Eelec, Efs, Emp, d0) if d < d0 E_tx = k * Eelec + k * Efs * d^2; else E_tx = k * Eelec + k * Emp * d^4; end end

接收函数更简单,直接返回 k * Eelec,聚合则返回 k * EDA。一个经验是:所有节点坐标从初始化开始就不要动,距离矩阵在循环外面预先算好,否则每一轮都重新算一万次sqrt,纯属浪费时间。

% 预计算任意两节点之间的距离矩阵 distMat = zeros(N, N); for i = 1:N for j = 1:N if i ~= j distMat(i, j) = sqrt((S.x(i)-S.x(j))^2 + (S.y(i)-S.y(j))^2); end end end

节点数量到几千的时候,这种双循环会卡,但100个节点完全没问题。

3.3 主循环框架:三种协议如何切换

主循环的大体结构是固定的:每轮开始,先按协议类型确定本轮簇头,然后普通节点找最近的簇头,按TDMA顺序发数据,簇头收数据、聚合、转发,最后统计本轮死亡节点数和基站收到的数据包数。

LEACH的簇头选举部分:

for r = 0:rmax % 每轮开始时,恢复所有节点身份为普通节点 S.type(:) = "N"; clusterHeadList = []; % 新周期开始时重置G集合 if mod(r, round(1/p)) == 0 S.G(:) = 0; end % LEACH簇头自选举 for i = 1:N if S.G(i) == 0 && S.E(i) > 0 threshold = p / (1 - p * mod(r, 1/p)); if rand < threshold S.type(i) = "C"; S.G(i) = 1; clusterHeadList(end+1) = i; end end end % 给没有簇头的节点兜底:如果全网一个簇头都没选出来,强制选能量最高节点 if isempty(clusterHeadList) [~, idx] = max(S.E); S.type(idx) = "C"; S.G(idx) = 1; clusterHeadList = idx; end % 稳定传输阶段... end

LEACH-C的切换只需要替换“确定簇头”这一段:先把所有节点位置和能量发给基站,基站筛选候选集,再调用一个简化模拟退火或者贪心分配来定簇头,最后把簇头ID广播回各节点。仿真里最省事的做法是每轮维护一个localData结构体,把网络状态传给一个selectCHByProtocol(protocol, localData)函数,让不同协议各自实现selectCH接口。

TS-I-LEACH类改进协议的代码和LEACH很像,只是阈值公式换成带能量和距离因子的版本,并且数据传输阶段最后多一步“判断簇头到基站距离是否超过某个阈值,如果超过就找另一簇头中继”。

3.4 数据传输阶段的能耗更新逻辑

稳定传输阶段的关键点在于严格区分“谁在发、谁在收、谁在聚合”。普通节点只发送一次数据;簇头要接收簇内所有节点数据,做一次聚合,再发送一次聚合后的数据到基站。忽略接收能耗会严重高估网络寿命。

% 普通节点发送给簇头:功耗由发送和接收双方共同承担 for i = 1:N if S.E(i) <= 0 continue; end if S.type(i) == "N" % 找到最近的簇头 [dmin, chIdx] = min(distMat(i, clusterHeadList)); if dmin < d0 S.E(i) = max(0, S.E(i) - (packetLen*Eelec + packetLen*Efs*dmin^2)); else S.E(i) = max(0, S.E(i) - (packetLen*Eelec + packetLen*Emp*dmin^4)); end % 簇头接收也耗能 S.E(chIdx) = max(0, S.E(chIdx) - packetLen*Eelec); end end % 簇头发送聚合数据到基站 for c = clusterHeadList if S.E(c) <= 0 continue; end % 聚合耗能:按簇内数据量计算 numMembers = sum(S.type == "N" & S.E > 0); S.E(c) = max(0, S.E(c) - numMembers * packetLen * EDA); d = S.dist2BS(c); if d < d0 S.E(c) = max(0, S.E(c) - (packetLen*Eelec + packetLen*Efs*d^2)); else S.E(c) = max(0, S.E(c) - (packetLen*Eelec + packetLen*Emp*d^4)); end % 该轮基站成功收到一个聚合包 if S.E(c) > 0 packetsReceived = packetsReceived + 1; end end

这段代码里有个容易出错的细节:计算簇内成员数量时,必须排除已经死亡的节点。如果死节点还继续向簇头发包,簇头接收能耗会被严重高估,结果会出现后期节点“突然集体暴毙”的假象。

3.5 结果统计与绘图

每轮结束之后记录三步:存活节点数、剩余总能量、基站累计收到的数据包数。

aliveCount(r+1) = sum(S.E > 0); totalEnergy(r+1) = sum(S.E); packetsToBS(r+1) = packetsReceived; % 记录三个关键轮数 if firstDeadRound == 0 && aliveCount(r+1) < N firstDeadRound = r; end if halfDeadRound == 0 && aliveCount(r+1) <= N/2 halfDeadRound = r; end

画图我习惯用四联图放在一起看:存活节点数随轮数变化、每轮死亡节点数、总剩余能量、基站收到的数据包数。四个图一对比,协议的寿命和吞吐量关系一目了然。

figure; subplot(2,2,1); plot(0:rmax, aliveCount, 'LineWidth', 1.5); xlabel('轮数'); ylabel('存活节点数'); grid on; subplot(2,2,2); plot(0:rmax, totalEnergy, 'LineWidth', 1.5); xlabel('轮数'); ylabel('剩余总能量(J)'); grid on; subplot(2,2,3); plot(0:rmax, packetsToBS, 'LineWidth', 1.5); xlabel('轮数'); ylabel('基站累计接收包数'); grid on; subplot(2,2,4); plot(0:rmax, aliveCount, 'LineWidth', 1.5); hold on; plot([firstDeadRound firstDeadRound], [0 N], 'r--'); plot([halfDeadRound halfDeadRound], [0 N], 'g--'); xlabel('轮数'); ylabel('存活节点数'); legend('存活节点', 'FND', 'HND', 'Location', 'best'); grid on;

如果要做正式的对比图,建议把三种协议画在同一张图里,用不同线型和颜色区分,图例里明确标注协议名。同一个随机种子下直接对比,差异会很直观。

4. 仿真结果对比分析与协议取舍建议

4.1 网络生命周期:FND、HND、LND三个维度

在固定随机种子的单次仿真里,我的典型结果大致是这样一个趋势:LEACH在300到500轮之间出现第一个死亡节点,LEACH-C通常能把这个数字推到700轮上下,而TS-I-LEACH类改进版本在把能量因子加进选举后,第一个死亡节点的出现时间往往能进一步延后。HND指标上的差距也很类似。

这里必须强调一点:以上数字是“典型趋势”,不同随机撒点、不同参数下具体值可能差别很大,重点看趋势而不是死记数字。做课程报告或者论文时,最好把三种协议放在同一张存活节点曲线图里,再标注FND和HND的垂直线,阅卷人和审稿人能一眼抓住要点。

从曲线形态上还能看出另一个有意思的现象:LEACH在中期会出现“断崖式”下跌,也就是某段时间节点陆续死亡后突然加速崩塌。原因是随机选举导致能量分布逐渐失衡,低能量节点被选成簇头后迅速耗尽,耗尽后又拖累所在簇的成员无法传输,形成连锁反应。LEACH-C和TS-I-LEACH的曲线整体更缓,这就是能量均衡带来的直接效果。

4.2 能耗曲线与节点剩余能量分布

直接把“总剩余能量”画出来,三种协议前期的曲线其实是重合的,因为大家都是同样的节点、同样的数据量,总能耗速率差异不大。真正的分化发生在FND之后。

更有价值的是看“能量分布的方差”。仿真结束时,把存活节点的剩余能量做成柱状图或者箱线图,LEACH往往会出现“少数节点剩余能量很高、大量节点已经归零”的两极分化;TS-I-LEACH因为有能量权重,低能量节点被保护起来,剩余能量的分布会平坦很多。这也是改进协议最有说服力的证据:它不光是让节点活得更久,而是让节点活得更“平均”。

4.3 基站接收数据量:寿命长不等于吞吐量高

很多初学者只盯着节点存活曲线,忽略吞吐量。实际上,网络寿命延长不等于每个节点都在有效工作。如果一个协议让节点“挂”得很晚,但后期存活节点一直在等簇头出现、没有把数据发出去,那延迟死亡就只是数字游戏。

基站累计收到的数据包数是最直接的吞吐量指标。LEACH因为簇头选举快,早期每轮的包数比较稳定;LEACH-C每轮要额外收集信息,但选出来的簇头位置更合理,单位能量的“有效包”往往更高。TS-I-LEACH如果在中继设计上没做好,会出现包经由两跳后重复计数的“假吞吐”,统计时要注意按基站实际收到的最终聚合包计数。

我自己的习惯是同时记录“平均每轮收到的包数”和“每焦耳能量产出的包数”,前者反映协议实时性,后者反映能量效率。写完论文再从这两个指标里提炼对比结论,会扎实很多。

4.4 这几种协议到底怎么选

如果只是做教学实验或者验证性仿真,LEACH是最稳妥的基线,它简单、快、代码好调试。如果你要说明集中式调度的价值,LEACH-C是课堂级示范,它能清楚展示“全局信息换性能提升”的权衡。如果你做的是论文改进方向,TS-I-LEACH这类两阶段加权策略则提供了更现实的思路:真实系统往往没有完美基站,但节点可以利用本地信息做更聪明的决策。

选型建议可以归纳成一句话:追求简单和可解释性,选LEACH;证明全局优化的上限,选LEACH-C;探索轻量级、去中心化的能量均衡方案,往TS-I-LEACH这类改进方向走。

5. 实操中常见的坑与排查技巧

5.1 随机数种子与结果复现问题

Matlab的rand默认每次运行都会重新生成随机序列,这是对比仿真最大的隐形杀手。你辛辛苦苦调好代码,跑一次发现改进协议比LEACH好,再跑一次发现反而更差,这时候很容易怀疑算法,其实只是随机性在捣乱。

解决办法很简单:每次仿真开头调用rng(固定整数),或者在脚本里设置一个可配置的种子变量。做正式实验时,至少跑30次独立重复,取均值并记录标准差或者绘制箱线图。我在第一次跑完整组仿真时就用这个办法,避免了很多“伪结论”。

5.2 包长度与能耗系数单位混乱

能耗模型里最容易翻车的点是把“比特”和“字节”混用。4000bit是500字节,如果代码里不小心把包长度写成4000字节,能耗直接放大8倍,网络寿命会出现成片坍塌。这一类问题很难靠肉眼排查,我建议写一个打印函数,把第一轮每个节点的收发能耗、剩余能量逐项打印出来,和手算结果对照一次。

单位方面也可以用一个快速自检:节点初始能量0.5J,发送4000bit到50m外,理想耗能大约0.0003J。如果你算出来的第一轮能耗是0.003J甚至更高,多半是系数单位写错了。先跑通这个手算对照,再去做协议对比。

5.3 簇头数量异常与阈值公式边界

LEACH阈值公式里r从0开始,mod(r, 1/p)在p=0.05时是mod(r, 20)。有些版本是从1开始计数,就变成mod(r-1, 1/p),两种写法都能得到正确结果,但混着用就会出问题。症状是:第一轮一个簇头都没有,或者第一轮之后几乎所有节点连续当选。

另一个常见边界问题是G集合的复位。G集合应该在每一个新周期开始时全部清零,如果在主循环里忘写这个复位,整场仿真可能只有第一批节点当过簇头,后面的轮次全是空转。遇到簇头数为0或者簇头数爆炸,优先检查这三行:阈值公式的轮数基准、G集合清零时机、死亡节点是否在选举前被排除。

5.4 能量越界与“死而复生”的节点

能耗更新时没有做max(0, E)保护,就会让节点能量出现负数。负能量节点在下一轮判断S.E > 0时被认为已经死亡,但在累计总能量时又会被计算成负值,导致总能量曲线莫名其妙往上抬。更隐蔽的是,如果你用S.E == 0判死,那么一个被扣成-0.001的节点实际上还在“活着”工作,出现统计数据异常。

比较稳妥的做法是:所有能量更新统一用E = max(0, E - cost),死亡判定统一用S.E <= 0或者S.E == 0,别混用。我自己吃过这个亏,某版代码里阴性能量让曲线在后期出现了“平台期”,排查了很久才发现。

5.5 仿真速度优化建议

100个节点跑3000轮,Matlab纯for循环大约需要十几秒,这个规模其实不用太担心性能。但如果你把节点数调到几百甚至上千,就要注意三点:

一是把节点间距离矩阵预先算好,不要在每轮里算500万次两点距离;二是用向量化操作更新整个节点的能量数组,少写逐节点for循环;三是减少结构体字段访问,把常用的状态量拆成独立数组,比如S.ES.xS.y分别存,访问速度会比塞进一个结构体数组快很多。大型网络到万级节点时,Matlab就不再合适了,直接考虑NS-3或者Python的SimPy,效率会高很多。

5.6 常见问题速查表

异常现象可能原因排查方法
第一个死节点出现在前几轮能耗系数单位写错,或包长度字节/比特混淆手算第一轮能耗,和打印输出对比
第一轮没有簇头阈值公式轮数基准错误,或死亡节点未排除打印每个节点的threshold和rand值逐项检查
某个节点连续多次当簇头G集合没有在新周期清零检查mod(r, 1/p)==0时的G复位逻辑
存活节点曲线后期出现平台负能量节点干扰统计统一用max(0, E),死亡判定用E==0
每次仿真结果差异过大没有固定随机种子使用rng()固定种子,正式实验多次重复取平均
基站收到的包突然剧增中继包被重复统计只统计最终到达基站的聚合包,不统计中间转发包
仿真跑得很慢距离反复计算或循环太多预计算距离矩阵,用向量化替代部分for循环

6. 写在最后的个人体会

把这三种协议完整跑通之后,我自己最大的体会是:仿真里的“改进”从来不是一句口号式的算法描述,而是要落到具体哪一行的能量消耗变了、变了多少、代价是什么。很多改进协议论文看起来花哨,其实拆开看只是在阈值公式里乘了一个权重,或者在传输路径上多加了一个判断,真正的价值判断标准还是那几条基础曲线。

如果现在有人要复现类似的研究,我给的建议是别急着直接写TS-I-LEACH。先用最朴素的LEACH把生命周期曲线画出来,把这个版本的每个能量分支都手算验证一遍,再逐步加集中式调度、加能量权重、加中继转发。每加一个模块就固定随机种子跑一次,和基线对比,看到有真实收益再往下走。这个习惯帮我排除了很多“加了东西反而变差”的伪优化,也让最终的对比图经得起推敲。

最后分享一个特别实用的小技巧:在代码里加一个verbose开关,每次只打印当前轮数、存活节点数、簇头ID列表。调试阶段打开它,跑完整轮仿真只要几十秒,但你能直接看到协议在每一轮到底做了什么选择,比事后从曲线上猜原因高效得多。这套仿真做下来,你会对无线传感器网络里“能量即生命”这句话有很具体的体感。

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

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

立即咨询