首頁 > 軟體

Python和Matlab實現蝙蝠演演算法的範例程式碼

2022-03-04 13:00:14

1 前言

蝙蝠演演算法是2010年楊教授基於群體智慧提出的啟發式搜尋演演算法,是一種搜尋全域性最優解的有效方法。該演演算法基於迭代優化,初始化為一組隨機解,然後迭代搜尋最優解,且在最優解周圍通過隨機飛行產生區域性新解,加強區域性搜尋速度。該演演算法具有實現簡單、引數少等特點

該演演算法主要用於目標函數尋優,基於蝙蝠種群利用產生的聲波搜尋獵物和控制飛行方向的特徵來實現函數的尋優。以一隻蝙蝠作為基本單元,且每隻蝙蝠都有一個適應值來對函數解空間進行優化。每隻蝙蝠可以調整自身發射聲波的響度、頻率等對空間進行搜尋,使整個種群的活動逐步由無序變為有序。但蝙蝠演演算法在尋優末段容易陷入區域性的極值,本文引入變速度權重因子修正係數(和粒子群引數調整的自適應過程相似),儘可能避免區域性極值的困境,從而達到全域性尋優的效果。

2 蝙蝠演演算法原理細講

首先在自變數範圍內產生蝙蝠的隨機位置;

然後每個蝙蝠向周圍某處移動,飛行靠聲波反饋來更變方向,又向周圍移動是隨機的,蝙蝠下一時刻移動到某一位置有一定的出現頻率,所以本文在運動公式中加了聲波和頻率兩個因素。每一時刻的位移看作是一次飛行,每次飛行的距離很短(距離長短反映出搜素精度)。

每隻蝙蝠初始位置是隨機的,在初始位置時刻其中一隻蝙蝠對應的函數最值,演演算法開始會記錄該位置,然後所有蝙蝠逐漸向該位置靠近,飛行方向大致向當前最值方向(即該方向的位置該蝙蝠的出現頻率更高),但是在飛行方向也是隨機飛行的,相當於逐步搜尋過去。蝙蝠飛行過程中不會因為當前飛行出現的最大值位置而改變種群的飛行趨勢,這樣可以儘量避免演演算法陷入區域性極值。

演演算法每飛行一次就記錄一次種群所處位置的最值,最後找出記錄中的最值。

演演算法有兩個引數可以影響最終的結果:種群數量和飛行次數。其中種群數量的影響是最大的。 

詳細步驟

3.1 初始化相關引數

蝙蝠的位置為Xi,飛行速度Vi,聲音響度為Ai,頻率yi範圍,設有目標函數為 :

3.2 更改脈衝頻率產生的解並更變蝙蝠位置與飛行速度

蝙蝠i在t-1時的位置和飛行速度分別表示為,群體當前找到的最優位置為。接著根據自身發出不同的音響搜尋獵物,通過接受反饋資訊來調整位置xi和飛行速度v(i)。其飛行的速度更變公式如下:

 w(t)其中為時刻變速慣性權重因子,作用是使蝙蝠的前期搜尋對後期搜尋提供參照,wmax為w(t)的最大值、wmin為w(t)的最小值;,一般取2,Tmax為最大迭代次數;為當前位置最優解;y(i)為頻率滿足正態均勻分佈的一個亂數,β是一個隨機變數,且。開始執行時,蝙蝠在隨機進行頻率分配。

為控制蝙蝠所處位置在自變數範圍內,本文針對該情況設定了邊界規則:如果下次運動的位置超出了自變數範圍,那麼下次飛行的位置為投影在的邊界上的位置。

3.3 搜尋區域性最優解

3.4 通過蝙蝠多次飛行產生多個新解,進行全域性搜尋,若得到的新解

那麼接受該解。

3.5 排列所有蝙蝠的位置,並找出當前最優值及對應的位置

3.6 設當前最優解為,然後使所有蝙蝠繼續向下一時刻運動,並返回步驟2重新計算。

3.7 時刻結束,輸出:最優解

4 Python實現

4.1 程式碼

#=========匯入相關庫===============
import numpy as np
from numpy.random import random as rand
 
#========引數設定==============
# objfun:目標函數 
# N_pop: 種群規模,通常為10到40
# N_gen: 迭代數
# A: 響度(恆定或降低) 
# r: 脈衝率(恆定或減小) 
# 此頻率範圍決定範圍
# 如有必要,應更改這些值 
# Qmin: 頻率最小值
# Qmax: 頻率最大值
# d: 維度
# lower: 下界
# upper: 上界
 
def bat_algorithm(objfun, N_pop=20, N_gen=1000, A=0.5, r=0.5,
    Qmin=0, Qmax=2, d=10, lower=-2, upper=2):
 
    N_iter = 0 # Total number of function evaluations
 
    #=====速度上下限================
    Lower_bound = lower * np.ones((1,d))
    Upper_bound = upper * np.ones((1,d))
 
    Q = np.zeros((N_pop, 1)) # 頻率
    v = np.zeros((N_pop, d)) # 速度
    S = np.zeros((N_pop, d))
 
    #=====初始化種群、初始解=======
    # Sol = np.random.uniform(Lower_bound, Upper_bound, (N_pop, d))
    # Fitness = objfun(Sol)
    Sol = np.zeros((N_pop, d))
    Fitness = np.zeros((N_pop, 1))
    for i in range(N_pop):
        Sol[i] = np.random.uniform(Lower_bound, Upper_bound, (1, d))
        Fitness[i] = objfun(Sol[i])
 
    #====找出初始最優解===========
    fmin = min(Fitness)
    Index = list(Fitness).index(fmin)
    best = Sol[Index]
 
    #======開始迭代=======
    for t in range(N_gen):
 
        #====對所有蝙蝠/解決方案進行迴圈 ======
        for i in range(N_pop):
            # Q[i] = Qmin + (Qmin - Qmax) * np.random.rand
            Q[i] = np.random.uniform(Qmin, Qmax)
            v[i] = v[i] + (Sol[i] - best) * Q[i]
            S[i] = Sol[i] + v[i]
 
            #===應用簡單的界限/限制====
            Sol[i] = simplebounds(Sol[i], Lower_bound, Upper_bound)
            # Pulse rate
            if rand() > r:
                # The factor 0.001 limits the step sizes of random walks
                S[i] = best + 0.001*np.random.randn(1, d)
 
            #====評估新的解決方案 ===========
            # print(i)
            Fnew = objfun(S[i])
            #====如果解決方案有所改進,或者聲音不太大,請更新====
            if (Fnew <= Fitness[i]) and (rand() < A):
                Sol[i] = S[i]
                Fitness[i] = Fnew
 
            #====更新當前的最佳解決方案======
            if Fnew <= fmin:
                best = S[i]
                fmin = Fnew
 
        N_iter = N_iter + N_pop
 
    print('Number of evaluations: ', N_iter)
    print("Best = ", best, 'n fmin = ', fmin)
 
    return best
 
 
def simplebounds(s, Lower_bound, Upper_bound):
 
    Index = s > Lower_bound
    s = Index * s + ~Index * Lower_bound
    Index = s < Upper_bound
    s = Index * s + ~Index * Upper_bound
 
    return s
 
 
#====目標函數=============
def test_function(u):
    a = u ** 2
    return a.sum(axis=0)
 
 
if __name__ == '__main__':
    # print(bat_algorithm(test_function))
    bat_algorithm(test_function)

4.2 結果

5 Matlab實現

5.1 程式碼

clear
wmax=0.9;%慣性權重最大值
wmin=0.4;%慣性權重最小值
n=10000; % 群體大小
A=rand(1,n); % 聲音響度 (不變或者減小)
%% 頻率範圍
Qmin=0; % 最低頻率
Qmax=1; % 最高頻率
d=2;% 搜尋變數的維數(即頻率和速度)
%% 初始矩陣
Q=zeros(n,1); % 頻率矩陣初始化
v=zeros(n,d); % 速度矩陣初始化,初始化意義就是產生一個初始矩陣
%% x自變數範圍
u=-3;
o=12.1;
% y自變數範圍
p=4.1;
l=5.8;
%% 初始化群體/解
for i=1:n
    Sol(i,1)=-3+(12.1+3)*rand(1,1);%x自變數範圍【-3,12.1】
    Sol(i,2)=4.1+(5.8-4.1)*rand(1,1);%y自變數【4.1,5.8範圍】
    %將隨機生成的兩個自變數帶入函數式
    Fitness(i)=Fun(Sol(i,:));%函數值
end
%% 尋找當前最優解
[fmax,I]=max(Fitness);
best=Sol(I,:);
T=100;%飛行次數
%% 開始飛行
for t=1:T
    for i=1:n,
        Q(i)=Qmin+(Qmin-Qmax)*rand;%rand均勻分佈的亂數
        %v(i,:)=v(i,:)+(Sol(i,:)-best)*Q(i);(原速度)
        w=(wmax-wmin)*exp(-2*(t/T)^2)+wmin;%慣性權重因子
        v(i,:)=w*v(i,:)+(Sol(i,:)-best)*A(i)*Q(i);%更改後的速度
        S(i,:)=Sol(i,:)+v(i,:);%位置移動
       %% 邊界問題,如果下次飛行超出自變數範圍外了,那麼下次飛行的位置為投影在的邊界上的位置
        %x軸
        if S(i,1)>o
            S(i,1)=o;
        end
        if S(i,1)<u
            S(i,1)=u;
        end
        %y軸
        if S(i,2)>l
            S(i,2)=l;
        end
        if S(i,2)<p
            S(i,2)=p;
        end
        %% 評估該次飛行後產生的新解
        Fnew(i)=Fun(S(i,:));
    end
    [Fmax,Z]=max(Fnew);%找出該次飛行後產生的最大值
    C(t,:)=S(Z,:);
    FFnew(t)=Fmax;
end
[Ffmax,N]=max(FFnew);%找出整個飛行過程中的最大值
M=C(N,:)
Ffmax
%目標函數
function z=Fun(u)
   z=21.5+u(1)*sin(4*pi*u(1))+u(2)*sin(20*pi*u(2));

5.2 結果 

5.3 展望

如果是其他函數怎麼辦呢?

函數z=21.5+u(1)*sin(4*pi*u(1))+u(2)*sin(20*pi*u(2))中的兩個自變數對應程式中的是Sol(i,1)=-3+(12.1+3)*rand(1,1);%x自變數範圍【-3,12.1】和Sol(i,2)=4.1+(5.8-4.1)*rand(1,1);%y自變數【4.1,5.8範圍】,兩自變數產生的是列矩陣,而程式中Sol(i,:) 提取的是矩陣中的行,所以如果對該函數增減自變數,或者想求其他含有多個自變數的函數,程式中只用修改以下程式部分,其他引數也可以自行更改(注:自變數的範圍和個數增加了,那麼種群個數和飛行次數務必要增加):

Sol(i,1)=-3+(12.1+3)*rand(1,1);%x自變數範圍【-3,12.1】

Sol(i,2)=4.1+(5.8-4.1)*rand(1,1);%y自變數【4.1,5.8範圍】

% x自變數範圍

u=-3;

o=12.1;

% y自變數範圍

p=4.1;

l=5.8;

到此這篇關於Python和Matlab實現蝙蝠演演算法的範例程式碼的文章就介紹到這了,更多相關Python和Matlab蝙蝠演演算法內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com