一、理论基础
LEACH(Low-Energy Adaptive Clustering Hierarchy)是由Wendi Rabiner Heinzelman、Anantha Chandrakasan和Hari Balakrishnan三人于2000年提出的一种无线传感器网络路由协议,它利用簇头的随机轮换在网络中的传感器之间均匀地分配能量负载。LEACH使用局部协调来实现动态网络的可伸缩性和健壮性,并将数据融合纳入路由协议中,以减少必须传输到基站的信息量。仿真结果表明,与传统的路由协议相比,LEACH协议的能耗降低了8倍。此外,LEACH能够在传感器中均匀地分配能量耗散,使网络的有效系统的生命周期延长一倍。
二、方法描述
1、节点分簇
簇头选举初始阶段,每个节点根据所建议网络簇头的百分比(事先确定)和节点已经成为簇头的次数来确定自己是否当选为簇头。每个节点产生一个0-1的随机数字,如果该数字小于阈值,节点成为当前轮的簇头。阈值定义为:
T
(
n
)
=
{
p
1
−
p
×
(
r
m
o
d
1
p
)
,
n
∈
G
0
,
e
l
s
e
(1)
T(n)=\begin{dcases} \frac{p}{1-p×(r mod \frac1p)},\quad n∈G\\0, \quad \quad \quad \quad \quad \quad \quad \quad else\end{dcases}\tag{1}
T(n)=⎩
⎨
⎧1−p×(rmodp1)p,n∈G0,else(1)其中,
n
n
n为当前节点,
p
p
p为预期的簇头百分比,
r
r
r为当前轮数,
G
G
G是最近
1
/
p
1/p
1/p轮里没有成为簇头的节点的集合。
2、节点能量消耗
传感器节点在传输 k k kbit数据到距离该传感器节点 d d d的邻接传感器节点时需消耗的能量如式(2)所示: E T x ( k , d ) = { E e l e c ⋅ k + ε f s ⋅ k ⋅ d 2 , d < d 0 E e l e c ⋅ k + ε m p ⋅ k ⋅ d 4 , d ≥ d 0 (2) E_{Tx}(k,d)=\begin{dcases} E_{elec}\boldsymbol ·k+\varepsilon_{fs}\boldsymbol ·k\boldsymbol ·d^2,d<d_{0}\\E_{elec}\boldsymbol ·k+\varepsilon_{mp}\boldsymbol ·k\boldsymbol ·d^4,d\geq d_0\end{dcases}\tag{2} ETx(k,d)={Eelec⋅k+εfs⋅k⋅d2,d<d0Eelec⋅k+εmp⋅k⋅d4,d≥d0(2)节点接收到 k k kbit数据需消耗的能量如式(3)所示: E R x ( k ) = E e l e c ⋅ k (3) E_{Rx}(k)=E_{elec}\boldsymbol ·k\tag{3} ERx(k)=Eelec⋅k(3)其中, E e l e c E_{elec} Eelec是传感器处理单位bit的数据时所需要的能量值, ε f s \varepsilon_{fs} εfs和 ε m p \varepsilon_{mp} εmp是通信能量参数, d 0 d_0 d0是阈值。如果距离 d d d小于 d 0 d_0 d0,则使用自由空间传播(free space communication)模型; 否则,使用多路径衰减信道(multipath fading channel)模型。阈值 d 0 d_0 d0的计算方法如式(4) 所示: d 0 = ε f s ε m p (4) d_0=\sqrt {\frac {\varepsilon_{fs}}{\varepsilon_{mp}}}\tag{4} d0=εmpεfs(4)
三、仿真分析
节点分布如图1所示。
1、节点分簇
仿真程序如下:
%% 清空环境变量
clear;
clc;
%% 初始化参数
xmin = 0; xmax = 100; % 区域x轴范围
ymin = 0; ymax = 100; % 区域y轴范围
sink.x = 50; % 基站x轴 50
sink.y = 200; % 基站y轴 200
n = 100; % 节点总数
p = 0.05; % 簇头概率
Eelec = 50*10^(-9);
Efs=10*10^(-12);
Emp=0.0013*10^(-12);
ED=5*10^(-9);
d0 = sqrt(Efs/Emp);
packetLength = 4000;
ctrPacketLength = 100;
rmax = 2000;
figure;
%% 节点随机分布
for i = 1:n
Node(i).xd = rand*(xmax-xmin)+xmin;
Node(i).yd = rand*(ymax-ymin)+ymin; % 随机产生100个点
Node(i).type = 'N'; % 进行选举簇头前先将所有节点设为普通节点
Node(i).E = 0.5; % 初始能量
Node(i).CH = 0; % 保存普通节点的簇头节点,-1代表自己是簇头
Node(i).d = sqrt((Node(i).xd-sink.x)^2+(Node(i).yd-sink.y)^2);
Node(i).G = 0; % 候选集标志
plot(Node(i).xd, Node(i).yd, 'o', sink.x, sink.y, 'p', 'LineWidth', 2);
hold on;
end
legend('节点', '基站');
xlabel 'x'; ylabel 'y'; title 'WSN分布图';
%%
alive = zeros(rmax, 1); % 每轮存活节点数
re = zeros(rmax, 1); % 每轮节点总能量
ce = zeros(rmax, 1); % 每轮节点消耗总能量
for r = 1:10
figure;
if mod(r, round(1/p)) == 0
for i = 1:n
Node(i).G=0;
end
end
for i = 1:n
if Node(i).E > 0
Node(i).type = 'N';
Node(i).CH = 0;
alive(r) = alive(r)+1;
re(r) = re(r)+Node(i).E;
end
end
if alive(r) == 0
break;
end
%% 簇头选举
cluster = 0;
for i = 1:n
if Node(i).E > 0
temp_rand = rand;
if Node(i).G <= 0 && temp_rand < p/(1-p*mod(r,round(1/p)))
Node(i).type = 'C'; % 节点类型为簇头
Node(i).G = 1;
cluster = cluster + 1;
% 簇头节点存入C数组
C(cluster).xd = Node(i).xd;
C(cluster).yd = Node(i).yd;
C(cluster).dist = Node(i).d;
C(cluster).id = i;
plot(C(cluster).xd, C(cluster).yd, '*');
text(Node(i).xd, Node(i).yd, num2str(i));
hold on;
CH = C;
Node(i).CH = -1;
% 广播自成为簇头
distanceBroad = sqrt((xmax-xmin)^2+(ymax-ymin)^2);
if distanceBroad > d0
Node(i).E = Node(i).E- (Eelec*ctrPacketLength + Emp*ctrPacketLength*distanceBroad^4);
ce(r) = ce(r)+Eelec*ctrPacketLength + Emp*ctrPacketLength*distanceBroad^4;
else
Node(i).E = Node(i).E- (Eelec*ctrPacketLength + Efs*ctrPacketLength*distanceBroad^2);
ce(r) = ce(r)+Eelec*ctrPacketLength + Efs*ctrPacketLength*distanceBroad^2;
end
% 簇头自己发送数据包能量消耗
if Node(i).d > d0
Node(i).E = Node(i).E- ((Eelec+ED)*packetLength+Emp*packetLength*Node(i).d^4);
ce(r) = ce(r)+(Eelec+ED)*packetLength+Emp*packetLength*Node(i).d^4;
else
Node(i).E = Node(i).E- ((Eelec+ED)*packetLength+Efs*packetLength*Node(i).d^2);
ce(r) = ce(r)+(Eelec+ED)*packetLength+Efs*packetLength*Node(i).d^2;
end
end
end
end
% 判断最近的簇头结点,如何去判断,采用距离矩阵
for i = 1:n
if Node(i).type == 'N' && Node(i).E > 0
if cluster > 0
Length = zeros(cluster, 1);
for c = 1:cluster
Length(c) = sqrt((Node(i).xd - C(c).xd)^2+(Node(i).yd-C(c).yd)^2);
end
[min_dis, min_dis_cluster] = min(Length); % 找到距离簇头最近的簇成员节点
plot(Node(i).xd, Node(i).yd, 'o');
text(Node(i).xd, Node(i).yd, num2str(i));
hold on;
plot([Node(i).xd; Node(C(min_dis_cluster).id).xd], [Node(i).yd; Node(C(min_dis_cluster).id).yd]);
hold on;
% 接收簇头发来的广播的消耗
Node(i).E = Node(i).E - Eelec*ctrPacketLength;
ce(r) = ce(r)+Eelec*ctrPacketLength;
% 加入这个簇,并发送数据给簇头
if min_dis < d0
Node(i).E = Node(i).E-(Eelec*(ctrPacketLength+packetLength)+Efs*(ctrPacketLength+packetLength)*min_dis^2);
ce(r) = ce(r)+Eelec*(ctrPacketLength+packetLength)+Efs*(ctrPacketLength+packetLength)*min_dis^2;
else
Node(i).E = Node(i).E-(Eelec*(ctrPacketLength+packetLength)+Emp*(ctrPacketLength+packetLength)*min_dis^4);
ce(r) = ce(r)+Eelec*(ctrPacketLength+packetLength)+Emp*(ctrPacketLength+packetLength)*min_dis^4;
end
Node(i).CH = C(min_dis_cluster).id;
% 簇头接收簇成员数据包消耗能量,接收加入消息和确认加入消息
if min_dis > 0
Node(C(min_dis_cluster).id).E = Node(C(min_dis_cluster).id).E - (Eelec+ED)*packetLength; %接受簇成员发来的数据包
Node(C(min_dis_cluster).id).E = Node(C(min_dis_cluster).id).E - Eelec*ctrPacketLength; %接收加入消息
ce(r) = ce(r)+(Eelec+ED)*packetLength+Eelec*ctrPacketLength;
if min_dis > d0 % 簇头向簇成员发送确认加入的消息
Node(C(min_dis_cluster).id).E = Node(C(min_dis_cluster).id).E - (Eelec*ctrPacketLength+Emp*ctrPacketLength*min_dis^4);
ce(r) = ce(r)+Eelec*ctrPacketLength+Emp*ctrPacketLength*min_dis^4;
else
Node(C(min_dis_cluster).id).E = Node(C(min_dis_cluster).id).E - (Eelec*ctrPacketLength+Efs*ctrPacketLength*min_dis^2);
ce(r) = ce(r)+Eelec*ctrPacketLength+Efs*ctrPacketLength*min_dis^2;
end
end
else
if Node(i).d < d0
Node(i).E = Node(i).E-(Eelec*packetLength+Efs*packetLength*Node(i).d^2);
ce(r) = ce(r)+Eelec*packetLength+Efs*packetLength*Node(i).d^2;
else
Node(i).E = Node(i).E-(Eelec*packetLength+Emp*packetLength*Node(i).d^4);
ce(r) = ce(r)+Eelec*packetLength+Emp*packetLength*Node(i).d^4;
end
end
end
end
clear C;
end
随机选取4幅分簇图,如图2~5所示。
2、节点能量消耗
代码如下:
%% 清空环境变量
clear;
clc;
xmin = 0; xmax = 100; % 区域x轴范围
ymin = 0; ymax = 100; % 区域y轴范围
sink.x = 50; % 基站x轴 50
sink.y = 200; % 基站y轴 200
n = 100; % 节点总数
p = 0.05; % 簇头概率
Eelec = 50*10^(-9);
Efs=10*10^(-12);
Emp=0.0013*10^(-12);
ED=5*10^(-9);
d0 = sqrt(Efs/Emp);
packetLength = 4000;
ctrPacketLength = 100;
rmax = 1500;
figure;
%% 节点随机分布
for i = 1:n
Node(i).xd = rand*(xmax-xmin)+xmin;
Node(i).yd = rand*(ymax-ymin)+ymin; % 随机产生100个点
Node(i).type = 'N'; % 进行选举簇头前先将所有节点设为普通节点
Node(i).E = 0.5; % 初始能量
Node(i).CH = 0; % 保存普通节点的簇头节点,-1代表自己是簇头
Node(i).d = sqrt((Node(i).xd-sink.x)^2+(Node(i).yd-sink.y)^2);
Node(i).G = 0; % 候选集标志
plot(Node(i).xd, Node(i).yd, 'o', sink.x, sink.y, 'p', 'LineWidth', 2);
hold on;
end
legend('节点', '基站');
xlabel 'x'; ylabel 'y'; title 'WSN分布图';
%%
alive = zeros(rmax, 1); % 每轮存活节点数
re = zeros(rmax, 1); % 每轮节点总能量
ce = zeros(rmax, 1); % 每轮节点消耗总能量
for r = 1:rmax
if mod(r, round(1/p)) == 0
for i = 1:n
Node(i).G=0;
end
end
for i = 1:n
if Node(i).E > 0
Node(i).type = 'N';
Node(i).CH = 0;
alive(r) = alive(r)+1;
re(r) = re(r)+Node(i).E;
end
end
if alive(r) == 0
break;
end
%% 簇头选举
cluster = 0;
for i = 1:n
if Node(i).E > 0
temp_rand = rand;
if Node(i).G <= 0 && temp_rand < p/(1-p*mod(r,round(1/p)))
Node(i).type = 'C'; % 节点类型为簇头
Node(i).G = 1;
cluster = cluster + 1;
% 簇头节点存入C数组
C(cluster).xd = Node(i).xd;
C(cluster).yd = Node(i).yd;
C(cluster).dist = Node(i).d;
C(cluster).id = i;
CH = C;
Node(i).CH = -1;
% 广播自成为簇头
distanceBroad = sqrt((xmax-xmin)^2+(ymax-ymin)^2);
if distanceBroad > d0
Node(i).E = Node(i).E- (Eelec*ctrPacketLength + Emp*ctrPacketLength*distanceBroad^4);
ce(r) = ce(r)+Eelec*ctrPacketLength + Emp*ctrPacketLength*distanceBroad^4;
else
Node(i).E = Node(i).E- (Eelec*ctrPacketLength + Efs*ctrPacketLength*distanceBroad^2);
ce(r) = ce(r)+Eelec*ctrPacketLength + Efs*ctrPacketLength*distanceBroad^2;
end
% 簇头自己发送数据包能量消耗
if Node(i).d > d0
Node(i).E = Node(i).E- ((Eelec+ED)*packetLength+Emp*packetLength*Node(i).d^4);
ce(r) = ce(r)+(Eelec+ED)*packetLength+Emp*packetLength*Node(i).d^4;
else
Node(i).E = Node(i).E- ((Eelec+ED)*packetLength+Efs*packetLength*Node(i).d^2);
ce(r) = ce(r)+(Eelec+ED)*packetLength+Efs*packetLength*Node(i).d^2;
end
end
end
end
% 判断最近的簇头结点,如何去判断,采用距离矩阵
for i = 1:n
if Node(i).type == 'N' && Node(i).E > 0
if cluster > 0
Length = zeros(cluster, 1);
for c = 1:cluster
Length(c) = sqrt((Node(i).xd - C(c).xd)^2+(Node(i).yd-C(c).yd)^2);
end
[min_dis, min_dis_cluster] = min(Length); % 找到距离簇头最近的簇成员节点
% 接收簇头发来的广播的消耗
Node(i).E = Node(i).E - Eelec*ctrPacketLength;
ce(r) = ce(r)+Eelec*ctrPacketLength;
% 加入这个簇,并发送数据给簇头
if min_dis < d0
Node(i).E = Node(i).E-(Eelec*(ctrPacketLength+packetLength)+Efs*(ctrPacketLength+packetLength)*min_dis^2);
ce(r) = ce(r)+Eelec*(ctrPacketLength+packetLength)+Efs*(ctrPacketLength+packetLength)*min_dis^2;
else
Node(i).E = Node(i).E-(Eelec*(ctrPacketLength+packetLength)+Emp*(ctrPacketLength+packetLength)*min_dis^4);
ce(r) = ce(r)+Eelec*(ctrPacketLength+packetLength)+Emp*(ctrPacketLength+packetLength)*min_dis^4;
end
Node(i).CH = C(min_dis_cluster).id;
% 簇头接收簇成员数据包消耗能量,接收加入消息和确认加入消息
if min_dis > 0
Node(C(min_dis_cluster).id).E = Node(C(min_dis_cluster).id).E - (Eelec+ED)*packetLength; %接受簇成员发来的数据包
Node(C(min_dis_cluster).id).E = Node(C(min_dis_cluster).id).E - Eelec*ctrPacketLength; %接收加入消息
ce(r) = ce(r)+(Eelec+ED)*packetLength+Eelec*ctrPacketLength;
if min_dis > d0 % 簇头向簇成员发送确认加入的消息
Node(C(min_dis_cluster).id).E = Node(C(min_dis_cluster).id).E - (Eelec*ctrPacketLength+Emp*ctrPacketLength*min_dis^4);
ce(r) = ce(r)+Eelec*ctrPacketLength+Emp*ctrPacketLength*min_dis^4;
else
Node(C(min_dis_cluster).id).E = Node(C(min_dis_cluster).id).E - (Eelec*ctrPacketLength+Efs*ctrPacketLength*min_dis^2);
ce(r) = ce(r)+Eelec*ctrPacketLength+Efs*ctrPacketLength*min_dis^2;
end
end
else % 无簇头选出,直接发送数据包到基站
if Node(i).d < d0
Node(i).E = Node(i).E-(Eelec*packetLength+Efs*packetLength*Node(i).d^2);
ce(r) = ce(r)+Eelec*packetLength+Efs*packetLength*Node(i).d^2;
else
Node(i).E = Node(i).E-(Eelec*packetLength+Emp*packetLength*Node(i).d^4);
ce(r) = ce(r)+Eelec*packetLength+Emp*packetLength*Node(i).d^4;
end
end
end
end
clear C;
end
%% 绘图显示
figure;
plot(1:rmax, alive, 'r', 'LineWidth', 2);
xlabel '轮数'; ylabel '每轮存活节点数';
figure;
plot(1:rmax, re, 'b', 'LineWidth', 2);
xlabel '轮数'; ylabel '每轮剩余总能量';
figure;
plot(1:rmax, ce, 'm', 'LineWidth', 1);
xlabel '轮数'; ylabel '每轮消耗总能量';
每轮节点存活个数如图6所示。
每轮节点总剩余能量如图7所示。
每轮节点总消耗能量如图8所示。
四、参考文献
[1] W. R. Heinzelman, A. Chandrakasan, H. Balakrishnan. Energy-efficient communication protocol for wireless microsensor networks[C]. Proceedings of the 33rd Annual Hawaii International Conference on System Sciences, 2000, 2: 1-10.
[2] kkzhang. LEACH分簇算法实现和能量控制算法实现. 博客园.
[3] 喻小惠, 张晶, 陶涛, 等. 基于蚁群策略的无线传感器网络能耗均衡分簇算法[J]. 计算机工程与科学, 2019, 41(7): 1197-1202.