LEACH协议python仿真及分析改进
wf
1.修改及测试代码
1.1 LEACH路由场景文件的生成
绿色小圆圈代表站点,随机生成100个
1.2 SINK结点
蓝色代表SINK结点,中间位置
1.3 设置簇头
紫色代表簇头结点,根据T(n)阈值进行选取,第一轮时簇头选取情况
1.4 一般节点加入簇
第一轮时结点加入簇
1.4 死亡节点
当能量小于0,节点死亡。
1.5 簇头数目
随着节点能量的减少,节点进入死亡期,可活动的节点越来越少,产生簇头越来越难。大多时间都是0簇头,其他非死亡节点不能正常工作。
1.6 死亡节点
1.7 能量消耗
1.7.1
1.7.2
2. 改进
2.1 上述算法
在(1/p)轮每阶段中簇头不重复的节点上产生,使每个节点多有机会成为簇头,使能量消耗均分。(1/p)后,每个非死亡节点有都会有机会成为簇头,这样可以避免,有的节点成为簇点后,能量依然充足,还可以胜任簇头工作。
2.2 缺点
由于簇头的产生就有随机性,产生的簇头不一定是最优的。
可能会出现在偏僻的地方,周围没有站点。或者簇头产生
过于密集,导致其他站点与簇头通信距离增加,需要消耗更大的能量。或者生成的簇头不合理,出现在一个簇的偏远地方。
从能量消耗的图中看出,总能量出现负值。这是由于一个节点本身能量很少,有选为簇头,致使在模拟中出现负值,在实际中,就会出现,由于组头死亡,整个不簇能正常通信。
从簇头数目图中看出,当节点稀疏且少时,选取簇头算法非常不利。
2.3 改进
2.3.1 负能量问题
设置能量阈值,当低于一定能量时,不可再选为簇头。
与1.6图相比,图中可以看出可以减缓死亡数目。
2.3.2 簇头节点密集问题
簇头之间加入距离阈值,在一个簇头范围内不可再产生簇头。
阈值设置为4个单位。
阈值设置为8个单位。
2.3.3 簇头孤立点
当一定时间段内(即所有节点都加入到簇后),簇头检测加入本簇的节点数目,当少于一定数目时,将此簇解散,令簇头变成普通节点,加入邻近的簇头。
参考
- 基于NS2的LEACH协议仿真与分析
附录
- 仿真环境 jupyter notebook
- 仿真代码
import matplotlib.pyplot as plt
import random
import math
import numpy as np
import cv2 as cv
xm=500;
ym=500;
sink_x=round(0.5*xm);
sink_y=round(0.5*ym);
n=100;
p=0.2;#20%的簇头
E0=0.02;
ETX=50*0.000000000001;
ERX=50*0.000000000001;
Efs=10*0.000000000001;
EDA=5*0.000000000001;
cc=0.6;
rmax=1000;
CM=32;
DM=4000;
class S:
def __init__(self):
pass
img0 = np.ones((500, 500, 3), np.uint8)*255 #生成一个空灰度图像
img=img0.copy()
Sc=[]
s_x=[]
s_y=[]
for i in range(0,n,1):
s=S()
s.xd=round(random.random()*xm);
s.yd=round(random.random()*ym);
s.G=0;
s.E=E0;
s.type='N';
#plt.plot(s.xd,s.yd,'o');
s_x.append(s.xd)
s_y.append(s.yd)
Sc.append(s)
cv.circle(img,(Sc[i].xd,Sc[i].yd), 3, (0,255,0), 4);
# plt.scatter(s_x,s_y,color=['blue'])
plt.imshow(img)
s=S()
s.xd=sink_x;
s.yd=sink_y;
Sc.append(s)
cv.circle(img,(Sc[n].xd,Sc[n].yd), 4, (0,0,255), 8);
plt.imshow(img)
img1=img.copy()
flag_first_dead=0;
Dead=[0 for i in range(rmax)]
CH_Num=[0 for i in range(rmax)]
dead=0
img=img1.copy()
C=[]#存储簇头信息
packet_To_BS=[]
flag_first_dead=0;
Dead=[0 for i in range(rmax)]
CH_Num=[0 for i in range(rmax)]
img=img1.copy()
C=[]#存储簇头信息
R=[]#存储每轮每个节点的剩余能量
for r in range(0,rmax,1):
# r+1 #显示轮数
print('r:',r)
if r%round(1/p)==0:
for i in range(0,n,1):
Sc[i].G=0;
cluster=0;#%初始簇頭數為0
dead=0;#%初始死亡節點數為0
packet_To_BS=[]
img=img0.copy()
for i in range(0,n,1):
if Sc[i].E<=0 :
# plt.plot(Sc[i].xd,Sc[i].yd,'red .');
# print((Sc[i].xd,Sc[i].yd))
cv.circle(img,(Sc[i].xd,Sc[i].yd), 3, (255,0,0),4);
dead=dead+1;
Sc[i].type='D'
else:
Sc[i].type='N';
# plt.plot(Sc[i].xd,Sc[i].yd,'o');
cv.circle(img, (Sc[i].xd,Sc[i].yd),3, (0,255,0),4)
# ## 记录第一个死亡的结点
# if dead==1:
# if flag_first_dead==0:
# first_dead=r;
# flag_first_dead=1;# save ltest, first_dead;
# else:
# Sc[i].type='N';
# # plt.plot(Sc[i].xd,Sc[i].yd,'o');
# cv.circle(img, (Sc[i].xd,Sc[i].yd),1, (0,255,0),4)
# plt.plot(Sc[n].xd,Sc[n].yd,'x');#%繪製基站
cv.circle(img, (Sc[n].xd,Sc[n].yd),4, (0,0,255),8)
Dead[r]=dead;# %每輪有死亡節點數
# print('r:dead',r,':',Dead[r]);
#save ltest, Dead(r+1);%將此數據存入ltest文件
###设置簇头
for i in range(0,n,1):
if Sc[i].E>0:
if Sc[i].G<=0:
temp_rand=random.random();
# print(temp_rand,'----------------',(p/(1-p*(r%round(1/p)))))
if temp_rand<=(p/(1-p*(r%round(1/p)))):
Sc[i].type='C';#%此節點為此輪簇頭
Sc[i].G=round(1/p)-1;#%S(i).G設置為大於0,此週期不能再被選擇為簇頭
cluster=cluster+1;#%簇頭數加1
c=S()
c.xd=Sc[i].xd;
c.yd=Sc[i].yd;#%將此節點標誌為簇頭
# print((c.xd,c.yd),'设置为簇头');
#plot(Sc[i].xd,Sc[i].yd,'k*');#%繪製此簇頭
cv.circle(img,(Sc[i].xd,Sc[i].yd), 3, (255,0,255),4);
distance=math.sqrt((Sc[i].xd-(Sc[n].xd))**2+(Sc[i].yd-(Sc[n].yd))**2);#%簇頭到基站的距離
c.distance=distance;#%標誌為此簇頭的距離
c.id=i; #%此簇頭的節點id
C.append(c);
packet_To_BS.append(1);#%發送到基站的數據包數為1
CH_Num[r]=cluster; #%每輪的簇頭數
#save ltest,CH_Num(r+1);#%保存每輪簇頭數到ltest
img1=img.copy()
for i in range(0,n,1):
if Sc[i].type=='N' and Sc[i].E>0 and cluster>0:#%對每個能量大於0且非簇頭節點
min_dis=math.sqrt((Sc[i].xd-(C[0].xd))**2+(Sc[i].yd-(C[0].yd))**2);#%計算此節點到簇頭1的距離
min_dis_cluster=0;
for c in range(1,cluster,1):
temp=math.sqrt((Sc[i].xd-(C[c].xd))**2+(Sc[i].yd-(C[c].yd))**2);
if temp<min_dis:
min_dis=temp;
min_dis_cluster=c;
cv.line(img1, (Sc[i].xd, Sc[i].yd), (C[min_dis_cluster].xd, C[min_dis_cluster].yd), (0,125,0), 1)
# if min_dis_cluster>=len(packet_To_BS):
# packet_To_BS.append(1);
# else:
# print('cu',min_dis_cluster)
# print('len:',len(packet_To_BS))
packet_To_BS[min_dis_cluster]=packet_To_BS[min_dis_cluster]+1;#%將此節點加入的簇
Er1=ERX*CM*(cluster+1);#%此節點接收各個簇頭的控制信息
#%此節點加入的簇的簇頭時隙控制信息的總接收能耗
Et1=ETX*(CM+DM)+Efs*(CM+DM)*min_dis*min_dis;#%此節點發送加入信息和發送數據信息
# #%到簇頭的能耗
Sc[i].E=Sc[i].E-Er1-Et1;#%此輪後的剩餘能量
for c in range(0,cluster,1):#%各個簇頭
# packet_To_BS(c);#%簇頭需發送到基站的數據包個數
CEr1=ERX*CM*(packet_To_BS[c]-1);#%收到此簇各個節點加入信息的能耗
CEr2=ERX*DM*(packet_To_BS[c]-1);#%收到此簇各個節點數據信息的能耗
CEt1=ETX*CM+Efs*CM*(math.sqrt(xm*ym/25.0))*(math.sqrt(xm*ym/25.0));#%此簇頭廣播成簇信息的能耗
CEt2=(ETX+EDA)*DM*cc*packet_To_BS[c]+Efs*DM*cc*packet_To_BS[c]*C[c].distance*C[c].distance/25.0;#%簇頭將所以數據融合後發往基站的能耗
Sc[C[c].id].E=Sc[C[c].id].E-CEr1-CEr2-CEt1-CEt2;#%此輪後簇頭的剩餘能量
for i in range(0,n,1):
# if Sc[i].type=='N':
# print('站点_',i,":",Sc[i].E)
# else:
# print('簇头_',i,":",Sc[i].E)
R.append(Sc[i].E);# %每輪每節點的剩餘能量
# #% save ltest,R(r+1,i);%保存此數據到ltest
- 负能量改进
flag_first_dead=0;
Dead=[0 for i in range(rmax)]
CH_Num=[0 for i in range(rmax)]
img=img1.copy()
C=[]#存储簇头信息
R=[]#存储每轮每个节点的剩余能量
for r in range(0,rmax,1):
# r+1 #显示轮数
print('r:',r)
if r%round(1/p)==0:
for i in range(0,n,1):
Sc[i].G=0;
cluster=0;#%初始簇頭數為0
dead=0;#%初始死亡節點數為0
packet_To_BS=[]
img=img0.copy()
for i in range(0,n,1):
if Sc[i].E<=0 :
# plt.plot(Sc[i].xd,Sc[i].yd,'red .');
# print((Sc[i].xd,Sc[i].yd))
cv.circle(img,(Sc[i].xd,Sc[i].yd), 3, (255,0,0),4);
dead=dead+1;
Sc[i].type='D'
else:
Sc[i].type='N';
# plt.plot(Sc[i].xd,Sc[i].yd,'o');
cv.circle(img, (Sc[i].xd,Sc[i].yd),3, (0,255,0),4)
# ## 记录第一个死亡的结点
# if dead==1:
# if flag_first_dead==0:
# first_dead=r;
# flag_first_dead=1;# save ltest, first_dead;
# else:
# Sc[i].type='N';
# # plt.plot(Sc[i].xd,Sc[i].yd,'o');
# cv.circle(img, (Sc[i].xd,Sc[i].yd),1, (0,255,0),4)
# plt.plot(Sc[n].xd,Sc[n].yd,'x');#%繪製基站
cv.circle(img, (Sc[n].xd,Sc[n].yd),4, (0,0,255),8)
Dead[r]=dead;# %每輪有死亡節點數
# print('r:dead',r,':',Dead[r]);
#save ltest, Dead(r+1);%將此數據存入ltest文件
###设置簇头
for i in range(0,n,1):
if Sc[i].E>0.005:
if Sc[i].G<=0:
temp_rand=random.random();
# print(temp_rand,'----------------',(p/(1-p*(r%round(1/p)))))
if temp_rand<=(p/(1-p*(r%round(1/p)))):
Sc[i].type='C';#%此節點為此輪簇頭
Sc[i].G=round(1/p)-1;#%S(i).G設置為大於0,此週期不能再被選擇為簇頭
cluster=cluster+1;#%簇頭數加1
c=S()
c.xd=Sc[i].xd;
c.yd=Sc[i].yd;#%將此節點標誌為簇頭
# print((c.xd,c.yd),'设置为簇头');
#plot(Sc[i].xd,Sc[i].yd,'k*');#%繪製此簇頭
cv.circle(img,(Sc[i].xd,Sc[i].yd), 3, (255,0,255),4);
distance=math.sqrt((Sc[i].xd-(Sc[n].xd))**2+(Sc[i].yd-(Sc[n].yd))**2);#%簇頭到基站的距離
c.distance=distance;#%標誌為此簇頭的距離
c.id=i; #%此簇頭的節點id
C.append(c);
packet_To_BS.append(1);#%發送到基站的數據包數為1
CH_Num[r]=cluster; #%每輪的簇頭數
#save ltest,CH_Num(r+1);#%保存每輪簇頭數到ltest
img1=img.copy()
for i in range(0,n,1):
if Sc[i].type=='N' and Sc[i].E>0 and cluster>0:#%對每個能量大於0且非簇頭節點
min_dis=math.sqrt((Sc[i].xd-(C[0].xd))**2+(Sc[i].yd-(C[0].yd))**2);#%計算此節點到簇頭1的距離
min_dis_cluster=0;
for c in range(1,cluster,1):
temp=math.sqrt((Sc[i].xd-(C[c].xd))**2+(Sc[i].yd-(C[c].yd))**2);
if temp<min_dis:
min_dis=temp;
min_dis_cluster=c;
cv.line(img1, (Sc[i].xd, Sc[i].yd), (C[min_dis_cluster].xd, C[min_dis_cluster].yd), (0,125,0), 1)
# if min_dis_cluster>=len(packet_To_BS):
# packet_To_BS.append(1);
# else:
# print('cu',min_dis_cluster)
# print('len:',len(packet_To_BS))
packet_To_BS[min_dis_cluster]=packet_To_BS[min_dis_cluster]+1;#%將此節點加入的簇
Er1=ERX*CM*(cluster+1);#%此節點接收各個簇頭的控制信息
#%此節點加入的簇的簇頭時隙控制信息的總接收能耗
Et1=ETX*(CM+DM)+Efs*(CM+DM)*min_dis*min_dis;#%此節點發送加入信息和發送數據信息
# #%到簇頭的能耗
Sc[i].E=Sc[i].E-Er1-Et1;#%此輪後的剩餘能量
for c in range(0,cluster,1):#%各個簇頭
# packet_To_BS(c);#%簇頭需發送到基站的數據包個數
CEr1=ERX*CM*(packet_To_BS[c]-1);#%收到此簇各個節點加入信息的能耗
CEr2=ERX*DM*(packet_To_BS[c]-1);#%收到此簇各個節點數據信息的能耗
CEt1=ETX*CM+Efs*CM*(math.sqrt(xm*ym/25.0))*(math.sqrt(xm*ym/25.0));#%此簇頭廣播成簇信息的能耗
CEt2=(ETX+EDA)*DM*cc*packet_To_BS[c]+Efs*DM*cc*packet_To_BS[c]*C[c].distance*C[c].distance/25.0;#%簇頭將所以數據融合後發往基站的能耗
Sc[C[c].id].E=Sc[C[c].id].E-CEr1-CEr2-CEt1-CEt2;#%此輪後簇頭的剩餘能量
for i in range(0,n,1):
# if Sc[i].type=='N':
# print('站点_',i,":",Sc[i].E)
# else:
# print('簇头_',i,":",Sc[i].E)
R.append(Sc[i].E);# %每輪每節點的剩餘能量
# #% save ltest,R(r+1,i);%保存此數據到ltest
- 簇头密集问题
flag_first_dead=0;
Dead=[0 for i in range(rmax)]
CH_Num=[0 for i in range(rmax)]
img=img1.copy()
C=[]#存储簇头信息
R=[]#存储每轮每个节点的剩余能量
for r in range(0,1,1):
# r+1 #显示轮数
print('r:',r)
if r%round(1/p)==0:
for i in range(0,n,1):
Sc[i].G=0;
cluster=0;#%初始簇頭數為0
dead=0;#%初始死亡節點數為0
packet_To_BS=[]
img=img0.copy()
for i in range(0,n,1):
if Sc[i].E<=0 :
# plt.plot(Sc[i].xd,Sc[i].yd,'red .');
# print((Sc[i].xd,Sc[i].yd))
cv.circle(img,(Sc[i].xd,Sc[i].yd), 3, (255,0,0),4);
dead=dead+1;
Sc[i].type='D'
else:
Sc[i].type='N';
# plt.plot(Sc[i].xd,Sc[i].yd,'o');
cv.circle(img, (Sc[i].xd,Sc[i].yd),3, (0,255,0),4)
# ## 记录第一个死亡的结点
# if dead==1:
# if flag_first_dead==0:
# first_dead=r;
# flag_first_dead=1;# save ltest, first_dead;
# else:
# Sc[i].type='N';
# # plt.plot(Sc[i].xd,Sc[i].yd,'o');
# cv.circle(img, (Sc[i].xd,Sc[i].yd),1, (0,255,0),4)
# plt.plot(Sc[n].xd,Sc[n].yd,'x');#%繪製基站
cv.circle(img, (Sc[n].xd,Sc[n].yd),4, (0,0,255),8)
Dead[r]=dead;# %每輪有死亡節點數
# print('r:dead',r,':',Dead[r]);
#save ltest, Dead(r+1);%將此數據存入ltest文件
###设置簇头
for i in range(0,n,1):
if Sc[i].E>0.0001:
if Sc[i].G<=0:
temp_rand=random.random();
# print(temp_rand,'----------------',(p/(1-p*(r%round(1/p)))))
if temp_rand<=(p/(1-p*(r%round(1/p)))):
min_dis=40
for c in range(0,cluster,1):
temp=math.sqrt((Sc[i].xd-(C[c].xd))**2+(Sc[i].yd-(C[c].yd))**2);
if temp<min_dis:
min_dis=temp;
if min_dis<40:
continue;
Sc[i].type='C';#%此節點為此輪簇頭
Sc[i].G=round(1/p)-1;#%S(i).G設置為大於0,此週期不能再被選擇為簇頭
cluster=cluster+1;#%簇頭數加1
c=S()
c.xd=Sc[i].xd;
c.yd=Sc[i].yd;#%將此節點標誌為簇頭
# print((c.xd,c.yd),'设置为簇头');
#plot(Sc[i].xd,Sc[i].yd,'k*');#%繪製此簇頭
cv.circle(img,(Sc[i].xd,Sc[i].yd), 3, (255,0,255),4);
distance=math.sqrt((Sc[i].xd-(Sc[n].xd))**2+(Sc[i].yd-(Sc[n].yd))**2);#%簇頭到基站的距離
c.distance=distance;#%標誌為此簇頭的距離
c.id=i; #%此簇頭的節點id
C.append(c);
packet_To_BS.append(1);#%發送到基站的數據包數為1
CH_Num[r]=cluster; #%每輪的簇頭數
#save ltest,CH_Num(r+1);#%保存每輪簇頭數到ltest
img1=img.copy()
for i in range(0,n,1):
if Sc[i].type=='N' and Sc[i].E>0 and cluster>0:#%對每個能量大於0且非簇頭節點
min_dis=math.sqrt((Sc[i].xd-(C[0].xd))**2+(Sc[i].yd-(C[0].yd))**2);#%計算此節點到簇頭1的距離
min_dis_cluster=0;
for c in range(1,cluster,1):
temp=math.sqrt((Sc[i].xd-(C[c].xd))**2+(Sc[i].yd-(C[c].yd))**2);
if temp<min_dis:
min_dis=temp;
min_dis_cluster=c;
cv.line(img1, (Sc[i].xd, Sc[i].yd), (C[min_dis_cluster].xd, C[min_dis_cluster].yd), (0,125,0), 1)
# if min_dis_cluster>=len(packet_To_BS):
# packet_To_BS.append(1);
# else:
# print('cu',min_dis_cluster)
# print('len:',len(packet_To_BS))
packet_To_BS[min_dis_cluster]=packet_To_BS[min_dis_cluster]+1;#%將此節點加入的簇
Er1=ERX*CM*(cluster+1);#%此節點接收各個簇頭的控制信息
#%此節點加入的簇的簇頭時隙控制信息的總接收能耗
Et1=ETX*(CM+DM)+Efs*(CM+DM)*min_dis*min_dis;#%此節點發送加入信息和發送數據信息
# #%到簇頭的能耗
Sc[i].E=Sc[i].E-Er1-Et1;#%此輪後的剩餘能量
for c in range(0,cluster,1):#%各個簇頭
# packet_To_BS(c);#%簇頭需發送到基站的數據包個數
CEr1=ERX*CM*(packet_To_BS[c]-1);#%收到此簇各個節點加入信息的能耗
CEr2=ERX*DM*(packet_To_BS[c]-1);#%收到此簇各個節點數據信息的能耗
CEt1=ETX*CM+Efs*CM*(math.sqrt(xm*ym/25.0))*(math.sqrt(xm*ym/25.0));#%此簇頭廣播成簇信息的能耗
CEt2=(ETX+EDA)*DM*cc*packet_To_BS[c]+Efs*DM*cc*packet_To_BS[c]*C[c].distance*C[c].distance/25.0;#%簇頭將所以數據融合後發往基站的能耗
Sc[C[c].id].E=Sc[C[c].id].E-CEr1-CEr2-CEt1-CEt2;#%此輪後簇頭的剩餘能量
for i in range(0,n,1):
# if Sc[i].type=='N':
# print('站点_',i,":",Sc[i].E)
# else:
# print('簇头_',i,":",Sc[i].E)
R.append(Sc[i].E);# %每輪每節點的剩餘能量
# #% save ltest,R(r+1,i);%保存此數據到ltest
- 簇孤立点
flag_first_dead=0;
Dead=[0 for i in range(rmax)]
CH_Num=[0 for i in range(rmax)]
img=img1.copy()
C=[]#存储簇头信息
R=[]#存储每轮每个节点的剩余能量
for r in range(0,1,1):
# r+1 #显示轮数
print('r:',r)
if r%round(1/p)==0:
for i in range(0,n,1):
Sc[i].G=0;
cluster=0;#%初始簇頭數為0
dead=0;#%初始死亡節點數為0
packet_To_BS=[]
img=img0.copy()
for i in range(0,n,1):
if Sc[i].E<=0 :
# plt.plot(Sc[i].xd,Sc[i].yd,'red .');
# print((Sc[i].xd,Sc[i].yd))
cv.circle(img,(Sc[i].xd,Sc[i].yd), 3, (255,0,0),4);
dead=dead+1;
Sc[i].type='D'
else:
Sc[i].type='N';
# plt.plot(Sc[i].xd,Sc[i].yd,'o');
cv.circle(img, (Sc[i].xd,Sc[i].yd),3, (0,255,0),4)
# ## 记录第一个死亡的结点
# if dead==1:
# if flag_first_dead==0:
# first_dead=r;
# flag_first_dead=1;# save ltest, first_dead;
# else:
# Sc[i].type='N';
# # plt.plot(Sc[i].xd,Sc[i].yd,'o');
# cv.circle(img, (Sc[i].xd,Sc[i].yd),1, (0,255,0),4)
# plt.plot(Sc[n].xd,Sc[n].yd,'x');#%繪製基站
cv.circle(img, (Sc[n].xd,Sc[n].yd),4, (0,0,255),8)
Dead[r]=dead;# %每輪有死亡節點數
# print('r:dead',r,':',Dead[r]);
#save ltest, Dead(r+1);%將此數據存入ltest文件
###设置簇头
for i in range(0,n,1):
if Sc[i].E>0.0001:
if Sc[i].G<=0:
temp_rand=random.random();
# print(temp_rand,'----------------',(p/(1-p*(r%round(1/p)))))
if temp_rand<=(p/(1-p*(r%round(1/p)))):
min_dis=40
for c in range(0,cluster,1):
temp=math.sqrt((Sc[i].xd-(C[c].xd))**2+(Sc[i].yd-(C[c].yd))**2);
if temp<min_dis:
min_dis=temp;
if min_dis<40:
continue;
Sc[i].type='C';#%此節點為此輪簇頭
Sc[i].G=round(1/p)-1;#%S(i).G設置為大於0,此週期不能再被選擇為簇頭
cluster=cluster+1;#%簇頭數加1
c=S()
c.xd=Sc[i].xd;
c.yd=Sc[i].yd;#%將此節點標誌為簇頭
# print((c.xd,c.yd),'设置为簇头');
#plot(Sc[i].xd,Sc[i].yd,'k*');#%繪製此簇頭
cv.circle(img,(Sc[i].xd,Sc[i].yd), 3, (255,0,255),4);
distance=math.sqrt((Sc[i].xd-(Sc[n].xd))**2+(Sc[i].yd-(Sc[n].yd))**2);#%簇頭到基站的距離
c.distance=distance;#%標誌為此簇頭的距離
c.id=i; #%此簇頭的節點id
C.append(c);
packet_To_BS.append(1);#%發送到基站的數據包數為1
CH_Num[r]=cluster; #%每輪的簇頭數
#save ltest,CH_Num(r+1);#%保存每輪簇頭數到ltest
img1=img.copy()
for i in range(0,n,1):
if Sc[i].type=='N' and Sc[i].E>0 and cluster>0:#%對每個能量大於0且非簇頭節點
min_dis=math.sqrt((Sc[i].xd-(C[0].xd))**2+(Sc[i].yd-(C[0].yd))**2);#%計算此節點到簇頭1的距離
min_dis_cluster=0;
for c in range(1,cluster,1):
temp=math.sqrt((Sc[i].xd-(C[c].xd))**2+(Sc[i].yd-(C[c].yd))**2);
if temp<min_dis:
min_dis=temp;
min_dis_cluster=c;
cv.line(img1, (Sc[i].xd, Sc[i].yd), (C[min_dis_cluster].xd, C[min_dis_cluster].yd), (0,125,0), 1)
# if min_dis_cluster>=len(packet_To_BS):
# packet_To_BS.append(1);
# else:
# print('cu',min_dis_cluster)
# print('len:',len(packet_To_BS))
packet_To_BS[min_dis_cluster]=packet_To_BS[min_dis_cluster]+1;#%將此節點加入的簇
Er1=ERX*CM*(cluster+1);#%此節點接收各個簇頭的控制信息
#%此節點加入的簇的簇頭時隙控制信息的總接收能耗
Et1=ETX*(CM+DM)+Efs*(CM+DM)*min_dis*min_dis;#%此節點發送加入信息和發送數據信息
# #%到簇頭的能耗
Sc[i].E=Sc[i].E-Er1-Et1;#%此輪後的剩餘能量
img2=img1.copy()
for c in range(0,cluster,1):
if packet_To_BS[c]<=1:
C[c].type='N'
min_dis=500;
for c0 in range(0,cluster,1):
if c0==c:
continue;
temp=math.sqrt((C[c].xd-(C[c0].xd))**2+(C[c].yd-(C[c0].yd))**2);
if temp<min_dis:
min_dis=temp;
min_dis_cluster=c0;
print(min_dis_cluster)
print(c)
cv.circle(img2, (C[c].xd,C[c].yd),3, (0,255,0),4)
cv.line(img2, (C[c].xd, C[c].yd), (C[min_dis_cluster].xd, C[min_dis_cluster].yd), (0,125,0), 1)
for c in range(0,cluster,1):#%各個簇頭
# packet_To_BS(c);#%簇頭需發送到基站的數據包個數
CEr1=ERX*CM*(packet_To_BS[c]-1);#%收到此簇各個節點加入信息的能耗
CEr2=ERX*DM*(packet_To_BS[c]-1);#%收到此簇各個節點數據信息的能耗
CEt1=ETX*CM+Efs*CM*(math.sqrt(xm*ym/25.0))*(math.sqrt(xm*ym/25.0));#%此簇頭廣播成簇信息的能耗
CEt2=(ETX+EDA)*DM*cc*packet_To_BS[c]+Efs*DM*cc*packet_To_BS[c]*C[c].distance*C[c].distance/25.0;#%簇頭將所以數據融合後發往基站的能耗
Sc[C[c].id].E=Sc[C[c].id].E-CEr1-CEr2-CEt1-CEt2;#%此輪後簇頭的剩餘能量
for i in range(0,n,1):
# if Sc[i].type=='N':
# print('站点_',i,":",Sc[i].E)
# else:
# print('簇头_',i,":",Sc[i].E)
R.append(Sc[i].E);# %每輪每節點的剩餘能量
# #% save ltest,R(r+1,i);%保存此數據到ltest
CEr2=ERXDM(packet_To_BS[c]-1);#%收到此簇各個節點數據信息的能耗
CEt1=ETXCM+EfsCM*(math.sqrt(xmym/25.0))(math.sqrt(xmym/25.0));#%此簇頭廣播成簇信息的能耗
CEt2=(ETX+EDA)DMccpacket_To_BS[c]+EfsDMcc*packet_To_BS[c]C[c].distanceC[c].distance/25.0;#%簇頭將所以數據融合後發往基站的能耗
Sc[C[c].id].E=Sc[C[c].id].E-CEr1-CEr2-CEt1-CEt2;#%此輪後簇頭的剩餘能量
for i in range(0,n,1):
if Sc[i].type==‘N’:
print(‘站点_’,i,":",Sc[i].E)
else:
print(‘簇头_’,i,":",Sc[i].E)
R.append(Sc[i].E);# %每輪每節點的剩餘能量
#% save ltest,R(r+1,i);%保存此數據到ltest