1. 程式人生 > >果蠅優化演算法MATLAB實現

果蠅優化演算法MATLAB實現

果蠅優化演算法--Matlab實現

1果蠅優化演算法原理介紹

果蠅是一種廣泛存在於溫帶和熱帶地區的昆蟲,具有優於其他物種的嗅覺和視覺能力. 在尋找食物時,果蠅個體先利用自身嗅覺器官嗅到食物的氣味,並向周圍的果蠅傳送氣味資訊,或者從周圍的果蠅接收氣味資訊;之後果蠅利用其視覺器官,通過比較得出當前群體中收集到最好氣味資訊的果蠅位置,群體中的其他果蠅均飛向該位置,並繼續展開搜尋. 圖 1展示了果蠅群體搜尋食物的簡要過程.
果蠅優化演算法圖

1.1步驟分析

根據果蠅群體覓食的行為特點,標準 FOA尋優
大致分為以下幾個步驟.
Step 1:初始化.
設定種群規模(popsize),最大迭代次數(maxgen),果蠅群體位置範圍(LR)和果蠅的單次飛行範圍(FR)等相關引數值. 果蠅群體中每個個體的位置資訊由其對應的(X; Y )二維座標給出,其初始位置由下面的公式定義:

\left \ X_a_x_i_s=rand(LR) \right.
Y_a_x_i_s=rand(LR)

Step 2:嗅覺搜尋過程.
Step 2.1:當群體中的每一隻果蠅利用其嗅覺搜尋時,賦予它一個隨機的飛行方向和距離. 果蠅個體 新的位置由下式給出:
X_i=X_a_x_i_s+rand(FR)

Y_i=Y_a_x_i_s+rand(FR)

Step 2.2:因為食物味道的來源位置是未知的,因此先利用下式計算果蠅個體距離原點的距離DISTi:
Dist_i=\sqrt{X_i^{2}+Y_i^{2}}

然後通過下式計算其味道濃度判定值Si:
S_i=1/Dist_i

Step 2.3:通過下式計算當前群體中每個果蠅個體的味道濃度值Smelli:
Smell_i=fitness(S_i)

fitness表示味道濃度判斷函式,在利用FOA進行優化問題求解時,它是目標函式或適應度函式.
Step 2.4:選擇當前群體中具有最佳味道濃度值的果蠅,記錄其味道濃度值和相應位置
[bestSmell,bestIndex]=min(Smell)

Step 3:視覺搜尋過程.
保持最佳味道濃度值和對應果蠅位置資訊,群體中的其他果蠅均利用視覺飛向此位置,即
Smellbest=bestSmell

X_a_x_i_s=X(bestIndex)

Y_a_x_i_s=Y(bestIndex)

Step 4:重複Step 2和Step 3,直到演算法迭代次數達到maxgen.
由 FOA的計算步驟可知,標準 FOA採用基於種群的全域性隨機搜尋策略,通過跟蹤當前最優解的資訊來指導種群的下一步搜尋,使得種群能夠以當前最優解為中心開展區域性隨機搜尋,並朝著更優的方向搜尋前進.
 

2果蠅優化演算法程式設計

根據果蠅演算法步驟,設計MATlab程式如下

%% FOA封裝程式
clc;
clear;
for gen=1:30
%% 初始化引數
maxgen=100; %最大迭代次數
sizepop=50;
dim=30;
L=1;
%% 初始化矩陣
X_best=zeros(maxgen,dim);
Y_best=zeros(maxgen,dim);
Smell_best=zeros(1,maxgen);
%% 初始化果蠅座標;
X_axis=10*rand(1,dim);
Y_axis=10*rand(1,dim);
%% 生成果蠅群
[Si,X,Y]=gengrate_foa(X_axis,Y_axis,sizepop,dim,L);
%% 尋找最優個體
[BestSmell,Index]=find_Sum_Square(Si);
SmellBest=BestSmell;               %SmellBest為全域性最優
%% 取出最優個體的兩個維度的X,Y座標
X_axis=X(Index,:);
Y_axis=Y(Index,:);
for g=1:maxgen
    %% 生成果蠅群
    [Si,X,Y]=gengrate_foa(X_axis,Y_axis,sizepop,dim,L);
    %% 尋找最優個體
    [BestSmell,Index]=find_Sum_Square(Si);
    if BestSmell<SmellBest
        X_axis=X(Index,:);
        Y_axis=Y(Index,:);    
        %更新極值
        SmellBest=BestSmell;
    end
    Smell_best(g)=SmellBest;
    X_best(g,:)=X_axis;
    Y_best(g,:)=Y_axis;
end
    S(gen)=SmellBest;
end
%% 輸出最終值
SmellBest
%% 繪製圖像
figure(1)
plot(Smell_best,'b');   %繪製每一代最優濃度值
figure(2)
hold on
plot(X_best(:,1),Y_best(:,1),'r.');%繪製果蠅群X_axis,Y_axis的變化
plot(X_best(:,2),Y_best(:,2),'b.');
plot(X_best(:,3),Y_best(:,3),'k.');
figure(3)
plot(X(:,1),Y(:,1),'b.');%繪製最後一代的果蠅群;
mean(S)
min(S)
std(S)

將FOA果蠅群生成,和計算果蠅味道濃度值Smill_{i}封裝成函式,輸入的是種群座標,種群個數,維度和步長值,輸出的是每個果蠅的座標和果蠅的味道濃度判定值S_i

function [Si,X,Y]=gengrate_foa(X_axis,Y_axis,sizepop,dim,L)
    Di=zeros(sizepop,dim);
    Si=zeros(sizepop,dim);
    
    X_axis=repmat(X_axis,sizepop,1);    %將種群座標擴充;
    Y_axis=repmat(Y_axis,sizepop,1);
    X=X_axis+2*L*rand(sizepop,dim)-L;%求出每個果蠅的座標矩陣;
    Y=Y_axis+2*L*rand(sizepop,dim)-L;
    Di1=X.^2;   %求出X^2和Y^2;
    Di2=Y.^2;
    Di=Di1+Di2; %X^2+Y^2;
    Di=Di.^0.5; %開根號;
    
    Si=1./Di;   %Si=1/Di;

end

求果蠅味道濃度值Smill_{i},對每個測試函式都不同,此處用了SumSquare函式,這個函式的表示式是

                                                                                 F(x)=\sum_{i=1}^{n}ix^2

其三維函式影象如下圖

                                                   SumSquare函式影象

其函式編寫如下,函式輸入只需要果蠅個體的味道判定值S_i,帶入函式中解出最優的味道濃度值和其索引,就能對應著找到最優的果蠅個體了。

%% 果蠅濃度判定函式;
%Function:Sum Square
%表示式:f(x)=Sum(i*(Xi)^2);
function [BestSmell,Index]=find_Sum_Square(Si)

[si_m,si_n]=size(Si);
sum_2=zeros(1,si_n);
for d=1:si_n
    sum_2(d)=d;
end

Si_2=Si.^2;         %所有元素平方;
Smell=Si_2.*sum_2;
Smell=sum(Smell,2);
[BestSmell,Index]=min(Smell);
end

 


對函式進行測試

試驗設定獨立執行30次,並記錄每次的尋優結果,最後求一下30次尋優結果的均值,最小值和均方差。

對測試結果繪製圖片,figure(1)繪製的是每次迭代的種群最優值,可以看到最優值一直在降低,最終趨向於收斂於0(函式最優值),這就說明果蠅群每一次迭代都在向最優值前進,一點點尋優。

迭代曲線

figure(2)繪製的是果蠅群座標隨著迭代次數增長的變化,一點點在向外面擴散,這裡設定的函式為30維,畫圖的話只畫了其中3維,分別用紅色,藍色和黑色表示,每一維擴散的方向都不同。

果蠅群座標變化

figure(3)繪製的是最後一代果蠅群的座標分佈,這裡只畫了一維的座標分佈,可以看出是圍繞著中心點向四周隨機飛行的,因為這裡設定步長為1,所以上下幅度為最大為2。

果蠅群分佈 

要是想測試其他尋優函式,可以根據我的測試函式模板進行編寫,將Si作為變數X帶入,求出最小的Y值就是最優果蠅了,下面在放上兩個我已經編好的尋優函式,Ackley和Rastrigin。

%% 果蠅濃度判定函式;
%Function:Rastrigin
%表示式:f(x)=Sum[(Xi)^2-10cos(2pi*xi)+10];
function [BestSmell,Index]=find_Rastrigin(Si)
[si_m,si_n]=size(Si);
sum_2=zeros(si_m,1);
                    %第一部分:平方和
Si_2=Si.^2;         %所有元素平方;
sum_1=sum(Si_2,2);  %求各維度平方和;


%第二部分:cos(2pi*Xi)
for p=1:si_m        
    for d=1:si_n
        sum_2(p)=sum_2(p)+10*cos(2*pi*Si(p,d));
    end
end
Smell=sum_1-sum_2+10*si_n;
[BestSmell,Index]=min(Smell);
end

 

%Function:Ackley
%表示式:
function [BestSmell,Index]=find_Ackley(Si)
[si_m,si_n]=size(Si);
sum_2=zeros(si_m,1);
                    %第一部分:平方和
Si_2=Si.^2;         %所有元素平方;
sum_1=sum(Si_2,2);  %求各維度平方和;
sum_1=-0.2.*((sum_1/30).^0.5);    
sum_1=-20.*(exp(sum_1));


%第二部分:cos(2pi*Xi)
for p=1:si_m        %cos(Xi)/sqrt(i)部分
    for d=1:si_n
        sum_2(p)=sum_2(p)+cos(2*pi*Si(p,d)); 
    end
    sum_2(p)=sum_2(p)/30;
    sum_2(p)=-1*exp(sum_2(p));
end
Smell=sum_1+sum_2+20+exp(1);
[BestSmell,Index]=min(Smell);
end

程式碼已經經過測試了,可以直接拷貝到m檔案中,儲存在相同路徑執行,注意函式的名稱要和檔名稱相同。主函式裡面的引數sizepop,dim以及L,maxgen都是可以隨意設定的,可以設定觀測不同結果。