1. 程式人生 > 其它 >【優化求解】基於 Sobol 序列和縱橫交叉策略的麻雀搜尋演算法(SSASC) Matlab原始碼

【優化求解】基於 Sobol 序列和縱橫交叉策略的麻雀搜尋演算法(SSASC) Matlab原始碼

一、基於分簇拓撲節點休眠排程演算法

1、無線感測器網路執行概述

無線感測器網路是按照輪數來執行的,在網路的執行過程中,包括網路建立節點和節點穩定工作階段兩部分,如圖1所示。

圖1 網路執行輪次示意圖

在網路建立階段,對整個無線感測器網路進行分簇,節點按照某一概率成功獲選成為簇頭,然後向其鄰居節點發送邀請加入簇結構的訊息,而鄰居節點通過訊號的強弱來判斷,就近的加入簇結構中並且按照TDMA時間片的傳送資料給簇首。然後簇內中的節點進入穩定工作階段,簇首節點和其他普通節點穩定工作,每個簇內節點將對監測區域覆蓋感進行資料採集和資料融合,最後轉發給簇首節點,而冗餘節點是休眠的,不消耗能量。圖2是一個無線感測器網路中一個簇結構的節點狀態圖,圖中的簇首節點、休眠節點以及普通節點分別表示為C H CHCH節點、白色節點和黑色節點。

圖2 無線感測器網路部分示意圖

2、NDSCT演算法設計

(1)簇首的選擇

對整個無線感測器網路進行簇首的選取,首先節點會隨機生成( 0 , 1 ) (0,1)(0,1)之間的一個隨機值,若預先設定的閾值是大於該隨機值的,則它成功獲選為簇首節點,然後將其成功獲選為簇首的訊息廣播給周圍其他節點。T ( n ) T(n)T(n)的計算公式如下:

在公式(1)中,p pp為簇首節點佔整個網路節點的比列,E 0 E_0E0​為節點初始能量,E r e s i d u a l E_{residual}Eresidual​為節點的剩餘能量,n nn為當前的輪數,G GG為競選簇首失敗的節點集合。由公式(1)可知,節點剩餘能量越多,其閾值就越大,因此就更容易獲選成為簇首節點。

(2)簇的形成

當簇首節點向其他節點廣播已當選簇首的訊息後,那麼其他的周圍鄰居節點將根據簇首廣播訊息的訊號強弱來決定加入距離相對比較近的簇結構中,並向簇首發訊息確認。當簇首節點收到請求加入訊息後,採用 TDMA 方法將傳送資料的時間片分配傳送至簇結構中的每一個節點,簇的建立完成。

(3)排程簇內節點

在每一輪簇結構形成後,處於啟用狀態的所有簇內節點將依次按照自己的I D IDID大小來進行一個覆蓋冗餘的判定,判定冗餘覆蓋節點的條件為:
① 如果簇內節點的感知覆蓋區域內的鄰居節點數是小於四個的,那麼此節點將繼續處於活躍狀態,進行工作;
② 如果簇內節點的感知覆蓋區域內的鄰居節點數是大於或等於四個並且滿足如圖3中覆蓋條件,即該節點的感知覆蓋區域被其鄰居節點所完全覆蓋,那麼該節點就為冗餘覆蓋節點,它所感知到的資料都是鄰居節點所感知到的,則使該節點在此輪中進行休眠,下一輪從新進行判定。

圖3 冗餘節點O覆蓋範圍內的節點分佈圖

NDSCT演算法流程圖如圖4所示。

圖4 NDSCT演算法流程圖

二、模擬分析

1、模擬環境

通過M a t l a b MatlabMatlab作為實驗模擬平臺來對分簇拓撲節點休眠排程演算法進行模擬實驗,將模擬結果與LEACH演算法比較。所有感測器節點在100 m × 100 m 100m×100m100m×100m的目標監測區域範圍內是隨機分佈的,匯聚節點即基站是處於整個網路的中間位置,感測器節點的總數取值為100,感測器的通訊半徑為感知半徑的兩倍即 R c = 2 R s Rc=2RsRc=2Rs,R c RcRc為30m,R s RsRs為15m。實驗的引數設定與文獻[1]相同。

2、休眠節點數

NDSCT演算法每輪休眠節點數量如圖5所示。

圖5 NDSCT演算法每輪休眠節點數

3、存活節點數

NDSCT和LEACH演算法每輪存活節點數量如圖6所示。

圖6 存活節點數

3、網路剩餘總能量

NDSCT和LEACH演算法每輪網路剩餘總能量如圖7所示。

圖6 網路剩餘總能量

4、節點消耗總能量

NDSCT和LEACH演算法每輪節點消耗總能量如圖8所示。

圖8 節點消耗總能量

5、演示程式碼

%% 清空環境變數
clear;
clc;

%% 初始化引數
xm = 100;                  % x軸範圍
ym = 100;                  % y軸範圍
sink.x = 50;               % 基站x軸 50
sink.y = 50;               % 基站y軸 50
n = 100;                   % 節點總數
p = 0.05;                  % 簇頭概率
Rs = 15;                   % 感知半徑
Rc = 2*Rs;                 % 通訊半徑
Eelec = 50*10^(-9);
Efs=10*10^(-12);
Emp=0.0013*10^(-12);
ED=5*10^(-9);
d0 = sqrt(Efs/Emp);
E0 = 0.5;                  % 初始能量
packetLength = 4000;
ctrPacketLength = 100;
rmax = 6000;

figure;
%% 節點隨機分佈
for i = 1:n
    Node(i).xd = rand(1,1)*xm;
    Node(i).yd = rand(1,1)*ym;   % 隨機產生100個點
    Node(i).type = 'N';          % 進行選舉簇頭前先將所有節點設為普通節點
    Node(i).E = E0;              % 初始能量
    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;                  % 候選集標誌
    Node(i).Nbr = zeros(n, 1);      % 鄰居節點集
    Node(i).NumNbr = 0;             % 鄰居節點個數
    Node(i).status = 1;             % 節點的狀態:1  啟用狀態;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分佈圖';
save data1;
%%%%%%%%%%%%%%%%%NDSCT%%%%%%%%%%%%%%%
alive_ndsct = zeros(rmax, 1);        % 每輪存活節點數
re_ndsct = zeros(rmax, 1);           % 每輪節點總能量
ce_ndsct = zeros(rmax, 1);           % 每輪節點消耗總能量
sleep = zeros(rmax, 1);              % 每輪休眠節點數
for r = 1:rmax
    r
%     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;
            Node(i).status = 1;
            Node(i).NumNbr = 0;
            alive_ndsct(r) = alive_ndsct(r)+1;
            re_ndsct(r) = re_ndsct(r)+Node(i).E;
        end
    end
    if alive_ndsct(r) == 0
        break;
    end
    % 計算鄰居節點
    for i = 1:n
        if Node(i).E > 0
            count = 0;
            for j = 1:n
                if Node(j).E > 0
                    dist = sqrt((Node(i).xd-Node(j).xd)^2+(Node(i).yd-Node(j).yd)^2);
                    if j ~= i && dist < Rs
                        count = count + 1;
                        Node(i).Nbr(count) = j;
                    end
                end
                if j == n
                    Node(i).NumNbr = count;
                end
            end
        end
    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).E/E0)
                Node(i).type = 'C';      % 節點型別為簇頭
                Node(i).G = round(1/p)-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;
%                 X(cluster) = Node(i).xd;
%                 Y(cluster) = Node(i).yd;
%                 plot(Node(i).xd, Node(i).yd, 'r*');
%                 hold on;
                CH = C;
                Node(i).CH = -1;
                % 廣播自成為簇頭
                distanceBroad = sqrt(xm*xm+ym*ym);
                if distanceBroad > d0
                    Node(i).E = Node(i).E- (Eelec*ctrPacketLength + Emp*ctrPacketLength*distanceBroad^4);
                    ce_ndsct(r) = ce_ndsct(r)+Eelec*ctrPacketLength + Emp*ctrPacketLength*distanceBroad^4;
               else
                    Node(i).E = Node(i).E- (Eelec*ctrPacketLength + Efs*ctrPacketLength*distanceBroad^2);
                    ce_ndsct(r) = ce_ndsct(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_ndsct(r) = ce_ndsct(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_ndsct(r) = ce_ndsct(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_ndsct(r) = ce_ndsct(r)+Eelec*ctrPacketLength;
                % 加入這個簇
                if min_dis < d0
                    Node(i).E = Node(i).E-(Eelec*ctrPacketLength+Efs*ctrPacketLength*min_dis^2);
                    ce_ndsct(r) = ce_ndsct(r)+Eelec*ctrPacketLength+Efs*ctrPacketLength*min_dis^2;
                else
                    Node(i).E = Node(i).E-(Eelec*ctrPacketLength+Emp*ctrPacketLength*min_dis^4);
                    ce_ndsct(r) = ce_ndsct(r)+Eelec*ctrPacketLength+Emp*ctrPacketLength*min_dis^4;
                end
                Node(i).CH = C(min_dis_cluster).id;
%                 plot(Node(i).xd, Node(i).yd, 'ko');
%                 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;
                % 簇頭接收簇成員接收加入訊息
                 if min_dis > 0
                    Node(C(min_dis_cluster).id).E = Node(C(min_dis_cluster).id).E - Eelec*ctrPacketLength; %接收加入訊息
                    ce_ndsct(r) = ce_ndsct(r)+Eelec*ctrPacketLength;
                 end
            end
        end
    end
    %% 判斷冗餘節點,進行休眠排程
    for i = 1:n
        if Node(i).E > 0 && Node(i).type == 'N'     % 非簇頭節點
            if Node(i).NumNbr >= 4          % 鄰居節點個數≥4
                if isFullCover(Node, i) == 1
                    Node(i).status = 0;     % 冗餘節點,狀態調整為休眠狀態
                    sleep(r) = sleep(r)+1;
%                     plot(Node(i).xd, Node(i).yd, 'go');
%                     hold on;
                end         
            end
        end
    end
    %% 資料傳輸
    for i = 1:n
        if Node(i).E > 0 && Node(i).status ~= 0         % 節點存活且狀態為啟用態
            if Node(i).type == 'N'      % 普通節點
                if cluster > 0   % 簇頭節點存在
                    dist = sqrt((Node(i).xd-Node(Node(i).CH).xd)^2+(Node(i).yd-Node(Node(i).CH).yd)^2);
                    % 向簇頭髮送資料
                    if dist < d0
                        Node(i).E = Node(i).E-(Eelec*packetLength+Efs*packetLength*dist^2);
                        ce_ndsct(r) = ce_ndsct(r)+Eelec*packetLength+Efs*packetLength*dist^2;
                    else
                        Node(i).E = Node(i).E-(Eelec*packetLength+Emp*packetLength*dist^4);
                        ce_ndsct(r) = ce_ndsct(r)+Eelec*packetLength+Emp*packetLength*dist^4;
                    end
                else                    % 無簇頭選出
                    % 直接傳送資料到基站
                    dist = Node(i).d;
                    if dist < d0
                        Node(i).E = Node(i).E-(Eelec*packetLength+Efs*packetLength*dist^2);
                        ce_ndsct(r) = ce_ndsct(r)+Eelec*packetLength+Efs*packetLength*dist^2;
                    else
                        Node(i).E = Node(i).E-(Eelec*packetLength+Emp*packetLength*dist^4);
                        ce_ndsct(r) = ce_ndsct(r)+Eelec*packetLength+Emp*packetLength*dist^4;
                    end
                end
            end
        end
    end
end
load data1.mat;
%%%%%%%%%%%%%%LEACH%%%%%%%%%%%%%%%
%%
alive_leach = zeros(rmax, 1);        % 每輪存活節點數
re_leach = zeros(rmax, 1);           % 每輪節點總能量
ce_leach = zeros(rmax, 1);           % 每輪節點消耗總能量
for r = 1:rmax
%     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_leach(r) = alive_leach(r)+1;
            re_leach(r) = re_leach(r)+Node(i).E;
        end
    end
    if alive_leach(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 = round(1/p)-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;
                X(cluster) = Node(i).xd;
                Y(cluster) = Node(i).yd;
                CH = C;
                Node(i).CH = -1;
                % 廣播自成為簇頭
                distanceBroad = sqrt(xm*xm+ym*ym);
                if distanceBroad > d0
                    Node(i).E = Node(i).E- (Eelec*ctrPacketLength + Emp*ctrPacketLength*distanceBroad^4);
                    ce_leach(r) = ce_leach(r)+Eelec*ctrPacketLength + Emp*ctrPacketLength*distanceBroad^4;
               else
                    Node(i).E = Node(i).E- (Eelec*ctrPacketLength + Efs*ctrPacketLength*distanceBroad^2);
                    ce_leach(r) = ce_leach(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_leach(r) = ce_leach(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_leach(r) = ce_leach(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_leach(r) = ce_leach(r)+Eelec*ctrPacketLength;
                % 加入這個簇,併發送資料給簇頭
                if min_dis < d0
                    Node(i).E = Node(i).E-(Eelec*(ctrPacketLength+packetLength)+Efs*(ctrPacketLength+packetLength)*min_dis^2);
                    ce_leach(r) = ce_leach(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_leach(r) = ce_leach(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_leach(r) = ce_leach(r)+(Eelec+ED)*packetLength+Eelec*ctrPacketLength;
                end
            else                 % 無簇頭選出,直接傳送資料包到基站
                if Node(i).d < d0
                    Node(i).E = Node(i).E-(Eelec*packetLength+Efs*packetLength*Node(i).d^2);
                    ce_leach(r) = ce_leach(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_leach(r) = ce_leach(r)+Eelec*packetLength+Emp*packetLength*Node(i).d^4;
                end
            end
        end
%         [vx, vy] = voronoi(X, Y);
%         plot(X, Y, 'r*', vx, vy, 'g-');
%         hold on;
%         voronoi(X, Y);
%         axis([0 xm 0 ym]);
    end
end
%% 繪圖顯示
figure;
plot(1:rmax, sleep, 'r', 'linewidth', 1);
xlabel '輪數'; ylabel '每輪休眠節點數';
legend('NDSCT');
figure;
plot(1:rmax, alive_ndsct, 'r', 1:rmax, alive_leach, 'g', 'LineWidth', 2);
xlabel '輪數'; ylabel '每輪存活節點數';
legend('NDSCT', 'LEACH');
figure;
plot(1:rmax, re_ndsct, 'r', 1:rmax, re_leach, 'g', 'LineWidth', 2);
xlabel '輪數'; ylabel '每輪剩餘總能量';
legend('NDSCT', 'LEACH');
figure;
plot(1:rmax, ce_ndsct, 'r', 1:rmax, ce_leach, 'g', 'LineWidth', 1);
xlabel '輪數'; ylabel '每輪消耗總能量';
legend('NDSCT', 'LEACH');

三、參考文獻及程式碼私信博主

[1] 張雷.基於分簇拓撲的無線感測器網路節點休眠排程演算法研究[D]. 2019.