烏鴉搜索算法(Python)



title: 烏鴉搜索算法
author: 張寧
tags: 元啟發式優化, 烏鴉搜索算法, 約束工程優化
date: 2020-10-27


烏鴉搜索算法

摘要

這篇論文提出了一個新穎的元啟發式優化器,基於烏鴉的智能行為命名為烏鴉搜索算法(CSA)。CSA是一種基於群體的技術,它的工作原理是烏鴉把多余的食物儲存在隱蔽的地方,需要食物時再取出來。CSA被應用於對目標函數、約束條件和決策變量性質不同的六種不同的受約束工程設計問題進行優化。將CSA所獲得的結果與各種算法的結果進行比較。仿真結果顯示使用CSA或許會比其他算法更可能找到有希望的結果。

1. 介紹

工程設計的定義是構建滿足特定需求的產品的決策過程。常見的工程設計問題具有復雜的目標函數和大量的決策變量。可行解是所有設計的集合,其特征是在所有可能的設計參數(決策變量)。一種優化技術是嘗試從所有可行解中找到最佳解。

傳統搜索方法一直以來被應用到去解決工程設計問題。盡管這些方法在許多實際問題中找到了希望的結果,但是在許多復雜的設計問題中可能會失敗。在實際設計問題中,決策變量的數量可能非常的大並且它們在目標函數中的影響可能非常復雜。目標函數或許會有許多局部最優解,而設計師更感興趣的是全局最優解。這些問題不能被只能找到局部最優解的傳統方法來處理。在這些情況下,有效的優化方法是被需要的。
元啟發式算法對於解決許多現實世界的非常非線性和多峰優化問題可以顯示很好的性能。所有元啟發式算法都使用隨機化和局部搜索的一定權衡。這些算法可以為困難的優化問題找到最佳解決方案,但是並不能保證是最優解。希望這些算法大部分時間都能工作,但不是一直工作。元啟發式算法可以適用於全局優化。基於Glover's公約,所有現代自然啟發方法被稱為元啟發式。

目前的趨向是利用自然啟發元啟發式算法去解決困難的問題,它已經顯示出元啟發式是令人驚訝的有效。元啟發式的文獻在過去20年中得到了巨大的擴展。 一些著名的元啟發式算法如下:基於自然選擇的遺傳算法(GA) ,基於鳥群和魚類教育的社會行為的粒子群優化(PSO),基於音樂即興創作過程的和諧搜索(HS), 基於布谷鳥寄生的布谷鳥搜索算法,基於微型蝙蝠回聲定位行為的蝙蝠算法(BA),基於動物搜索行為的群搜索優化器(GSO),基於熱帶螢火蟲閃爍光模式的螢火蟲算法(FA)等。到目前為止,研究人員只使用了受自然啟發的非常有限的特性,並且有更多算法的發展空間。 本文的主要動機之一是開發一種方便用戶的(簡單的概念和易於實現)元啟發式技術,通過它我們可以在解決優化問題時獲得有希望的結果。
烏鴉是廣泛分布的鳥類屬,現在被認為是世界上最聰明的動物之一。作為一個群體,烏鴉表現出非凡的智力例子,在智力測試中往往得分很高。它們可以記住面容,使用工具,使用復雜的方法去交流和在不同的季節隱藏與取回食物。

在烏鴉群中,有一種行為和優化過程有許多相似之處。根據這個行為,烏鴉隱藏它們過量的食物在環境的某些位置(隱藏地),並且在需要時取回儲存的食物。烏鴉是貪婪的鳥,因為它們跟隨彼此為了獲得更好的食物來源。找到被烏鴉隱藏的食物來源不是件容易的事,因為烏鴉發現有另一個跟隨他,烏鴉會嘗試通過另一個環境的位置去愚弄烏鴉。從優化的角度來看,烏鴉是搜索者,環境是搜索空間,環境的每個位置是一個可行的解決方案,食物來源的質量是目的(適應度)函數,環境的最佳食物來源是問題的全局解決方案。基於這些相似點,CSA試圖模擬烏鴉的智能行為,去找到優化問題的解決方案。

2. 烏鴉搜索算法

烏鴉(烏鴉科或科)被認為是最聰明的鳥類。它們所含的大腦相對於他們的體型最大。根據腦體比,他們的大腦比人腦略低。烏鴉聰明的證據很多。他們在鏡像測試中展示了自我意識,並具有工具制作能力。當一個不友好的人走近時,烏鴉可以記住面孔並互相警告。而且,它們可以使用工具,以復雜的方式交流,並在幾個月后回憶起他們食物的隱藏地。
已知烏鴉觀察其他鳥,觀察其他鳥把食物藏在哪里,一旦主人離開,就把它偷走。如果烏鴉犯了偷竊罪,它將采取額外的預防措施,如移動隱藏地,以避免成為未來的受害者。事實上,他們利用自己的小偷經驗來預測小偷的行為,並能確定最安全的路線,以保護他們的緩存不被竊取。

在這篇論文中,基於上述智能行為,開發了一種基於種群的元啟發式算法CSA。 CSA的原則如下:

  • 烏鴉以群居的形式生活。
  • 烏鴉會記住它們隱藏地的位置。
  • 烏鴉們互相跟隨為了偷竊。
  • 烏鴉保護他們的緩存不被偷的概率。

假設有一個d維環境,包括一些烏鴉。烏鴉的數量(群大小)是 N ,烏鴉i在時間(迭代) item 在搜索空間中由向量 $x^{i,iter}(i=1,2,...,N;iter=1,2,...,iter_{max})$ 指定,其中 $x{i,iter}=[x_1{i,iter},x_2{i,iter},...,x_d{i,iter}]$ ,$iter_{max}$是最大迭代次數。每只烏鴉都會記住它們的隱藏地的位置。在每次迭代$iter$中,烏鴉i的隱藏地為$m^{i,iter}$.這是烏鴉i目前為止獲得的最好的位置。事實上,在每只烏鴉的記憶中,它的位置都被最好的經歷記住了。烏鴉在環境中移動,尋找更好的食物來源(隱藏的地方)。

假設在迭代$iter$中,烏鴉j想去他的隱藏地$m^{j,iter}$。在這個迭代中,烏鴉i決定跟隨烏鴉j接近烏鴉j的隱藏地。在這種情況下,可能會發生兩種情況:

  • 情況1:烏鴉j不知道烏鴉i在跟蹤它。因此烏鴉i將接近烏鴉j的隱藏地。 在這種情況下,得到烏鴉i的新位置如下:
    $x^{i,iter+1} = x^{i,iter} + r_i \times fl^{i,iter} \times (m^{j,iter} - x^{i,iter}) \tag{1}$

    其中$r_i$是一個在0到1之間均勻分布的隨機數,$fl^{i,iter}$表示烏鴉i在迭代迭代時的飛行長度。

圖1給出了這種狀態的原理圖和$fl$對搜索能力的影響。小的$fl$數值導致局部搜索(接近$x{i,iter}$),大的$fl$數值導致全局搜索(遠離$x{i,iter}$)。在圖1(a)顯示,如果$fl$的值小於1, 烏鴉i的下一個位置在$x{i,iter}$和$m{i,iter}$之間的虛線上。圖1(b)顯示,如果$fl$的值大於1,烏鴉i的下一個位置在可能超過$m^{i,iter}$的虛線上

  • 情況2:烏鴉j知道烏鴉i在跟蹤它。 因此,為了保護其緩存不被竊取,烏鴉j將通過前往搜索空間的另一個位置來欺騙烏鴉i。

狀態1和狀態2可以表示如下:

$$f(n) = \begin{cases}
x^{i,iter+1} = x^{i,iter} + r_i \times fl^{i,iter} \times (m^{j,iter} - x^{i,iter}) & r_j \geq AP^{j,iter} \
\text{a random position} & \text{otherwise}
\end{cases}
\tag{2}$$

其中$r_j$是一個在0到1之間均勻分布的隨機數嗎,$AP^{j,iter}$表示烏鴉j在迭代迭代時的感知概率。

元啟發式算法應在多樣化和集約化之間提供良好的平衡。在烏鴉搜索算法中,集約化和多樣化主要受感知概率($AP$)參數的控制。通過降低感知概率值,CSA傾向於在該區域找到當前良好解決方案的局部區域進行搜索。因此,使用較小的($AP$)值,會增加集約化。另一方面,隨着感知概率值的增加,搜索當前良好解附近的概率降低,CSA傾向於在全局尺度上探索搜索空間(隨機化)。 因此,使用較大的($AP$)值,會增加多樣化

圖1. CSA情況1流程圖,烏鴉i可以去到虛線上的任意一個位置

3. 對CSA實現進行優化

CSA的偽碼如圖(2)所示。本節給出了實現CSA的逐步程序。

  • 步驟1:初始化問題和可調參數

    定義優化問題,決策變量和約束條件。設置CSA(群落大小$N$)、最大迭代次數($iter_{max}$)、飛行長度($fl$)和感知概率($AP$)的可調參數。

  • 步驟2:初始化烏鴉的位置和記憶

    N只烏鴉被隨機定位在d維搜索空間中作為群成員。每個烏鴉表示問題的可行解,d表示決策變量的個數。

    $$ Crows =
    \begin{bmatrix}
    x_1^1 & x_2^1 & \cdots & x_d^1 \
    x_1^2 & x_2^2 & \cdots & x_d^2 \
    \vdots & \vdots & \vdots & \vdots \
    x_1^N & x_2^N & \cdots & x_d^N \
    \end{bmatrix} \tag{3}$$

    初始化每個烏鴉的內存。 由於在最初的迭代中,烏鴉沒有經驗,所以假設它們把食物隱藏在它們的初始位置。
    $$ Memory =
    \begin{bmatrix}
    m_1^1 & m_2^1 & \cdots & m_d^1 \
    m_1^2 & m_2^2 & \cdots & m_d^2 \
    \vdots & \vdots & \vdots & \vdots \
    m_1^N & m_2^N & \cdots & m_d^N \
    \end{bmatrix} \tag{4}$$

  • 步驟3:評估適應度(目標)功能

    對於每個烏鴉,通過將決策變量值插入目標函數來計算其位置的質量。

  • 步驟4:生成新位置

    烏鴉在搜索空間中生成新的位置如下:假設烏鴉i想生成一個新的位置。 為此目的,這只烏鴉隨機選擇一只烏鴉(例如烏鴉j),並跟隨它來發現這只烏鴉隱藏地($m^j$)。 用方程(2)得到了烏鴉i的新位置。 對於所有的烏鴉來說,這個過程是重復的。

  • 步驟5:檢查新位置的可行性

    檢查各烏鴉新位置的可行性。 如果烏鴉的新位置是可行的,烏鴉就會更新它的位置。 否則,烏鴉停留在當前位置,不會移動到生成的新位置。

  • 步驟6:評估新位置的適應度功能

    計算每個烏鴉新位置的適應度值$f(\cdot)$。

  • 步驟7:更新記憶

    烏鴉更新記憶如下:
    $$ m^{i,iter+1} = \begin{cases}
    x^{i,iter+1} & f(x^{i,iter+1})\text{ is better than }f(m^{i,iter})\
    m^{i,iter} & Otherwise
    \end{cases} \tag{5}$$
    其中$f(\cdot)$表示目標函數值。

    可見,如果烏鴉的新位置的適應度函數值優於記憶位置的適應度函數值,烏鴉就會通過新位置更新它的記憶。

  • 步驟8:檢查終止標准

    步驟4-7被重復,直到到達$iter_{max}$。 當滿足終止准則時,存儲器在目標函數值方面的最佳位置作為優化問題的解決方案。

烏鴉搜索算法偽碼

圖(2):烏鴉搜索算法偽碼

烏鴉搜索算法流程圖

圖(3):烏鴉搜索算法流程圖

4. CSA與GA、PSO和HS的比較

與其他著名的算法(如GA、PSO和HS)一樣,CSA利用一群尋求者來探索搜索空間。通過使用種群,找到一個好的解決方案並從局部最優逃逸的概率增加。優化算法除了種群大小和最大迭代次數(代)外,還有一些其他參數需要調整。參數設置是優化算法的缺點之一,因為它是一項耗時的工作。調整參數較少的算法更容易實現。在CSA中,可以調整的有飛行長度和感知概率(2個參數)。在PSO算法中,可調參數為慣性權重,速度最大值,個體學習因子和社會學習因子(4個參數)。HS可調參數為和諧記憶的價值考慮率,俯仰調節率和產生帶寬(3個參數)。在GA中,應確定選擇方法,交叉方法,交叉概率,變異方法,變異概率和替換方法(6個參數)。

與GA和PSO一樣,CSA不是一個貪婪的算法,因為如果烏鴉產生一個不比其當前位置更好的新位置,它將移動到新位置。 非貪婪算法可以增加生成的解的多樣性。 在HS中,如果它的適應度值優於記憶最差和諧的適應度,則接受一種新的解決方案。
像HS和PSO一樣,CSA包括記憶,在記憶中記住好的解決方案。 在粒子群算法中,每個粒子都被吸引到自己找到的最佳位置和該組找到的最佳位置。 因此,在每次迭代時,都直接使用到目前為止找到的最佳解決方案。 在CSA的每一次迭代中,每只烏鴉隨機選擇一只烏鴉(它可能是它自己),並向其隱藏的地方移動(烏鴉找到的最佳解決方案)。 這意味着在CSA的每一次迭代中,到目前為止發現的最佳位置被直接用於尋找更好的位置。

5. 數值例子

事實證明,在一定的假設下,沒有一種單一的搜索算法是所有問題的平均最佳搜索算法。換句話說,一個算法可能比其他算法更好地解決一些問題和一些問題。 為了在沒有偏差結論的情況下評估所提出的CSA的優化功率,考慮並解決了六個工程設計問題,包括三桿桁架、壓力容器、拉伸/壓縮彈簧、焊接梁、齒輪傳動和蝶形彈簧。所有考慮的問題都具有目標函數、約束和決策變量的不同性質。 CSA已經在MATLAB環境中使用奔騰4CPU2.1G2GB RAM在PC上執行。圖(3)顯示CSA實現的流程圖。表(1)顯示了CSA用於解決這些問題的參數設置。 值得提及的是,沒有嘗試優化CSA的參數設置。

本文對每個問題直接處理約束。 這意味着不能完全滿足約束條件的每個解決方案都將被認為是不可行的和廢棄的。 然而,拒絕不可行的解決方案可能對包括許多設計變量的問題和(或)其設計空間嚴重受約束的問題有嚴重的缺點,因為在這些問題中生成可行的設計可能需要大量的連續試驗。 約束優化問題的約束處理方法之一是使用懲罰函數。 利用罰函數,將約束優化問題轉化為無約束優化問題。 由於CSA的結果與文獻報道的結果進行了比較,並且大多數方法都使用了直接控制約束,因此這里沒有使用懲罰方法。

5.1 工程優化問題

5.1.1 三桿桁架設計問題

5.1.2 壓力容器設計問題

5.1.3 張力/壓縮彈簧設計問題

5.1.4 焊接梁設計問題

5.1.5 齒輪傳動設計問題

5.1.6 蝶形彈簧設計問題

5.2 基准函數

雖然工程問題的結果證明了CSA與文獻中現有的方法具有競爭力,但在較大的問題中,CSA的性能仍然存在一個問題。為了評估CSA在大規模優化問題上的性能,在10個維度中求解了表(16)所示的五個著名的基准函數。在CSA中,與以前一樣,AP和fl值分別設置為0.1和2。 在PSO中,速度被控制,學習因素(個體和社會)被設置為2。

此外,在迭代過程中,慣性權重從0.9線性下降到0.4。 在GA中,采用凸交叉(系數為0.25和0.75)、均勻變異和錦標賽選擇。 交叉概率和突變概率分別設置為0.9和0.005。 在CSA、PSO和GA中,種群大小設置為20,最大迭代次數選擇2000次。 因此,在調查中,健康評估的數量為40,000。

表(17)顯示了CSA獲得的結果與PSO和GA在30次獨立運行中發現的結果相比。 在所有函數上,CSA在最佳指數方面都優於其他算法。 在此表中,顯示了運行的平均時間。 結果表明,在相同的適應度評價中,CSA比PSO和GA消耗的計算時間更少。

作為另一項研究,研究了不同參數設置對CSA性能的影響。 表(18)和表(19)顯示了不同AP和fl值對Sphere function ($f_1$)Rosenbrock function ($f_2$)Griewank function ($f_3$)的結果的影響。從表18可以看出,AP=0導致CSA的性能弱,因為算法的多樣化能力已經被消除。考慮到最佳指標,從所研究的參數設置來看,$f_1$、$f_2$和$f_3$的最佳指標分別是($AP$=0.05和$fl$=1.5),($AP$=0.05和$fl$=2.5)和($AP$=0.2和$fl$=2)。考慮平均指數,從所研究的參數設置來看,$f_1$、$f_2$和$f_3$的最佳參數設置分別是($AP$=0.05和$fl$=2)、($AP$=0.05和$fl$=2.5)和($AP$=0.3和$fl$=2)。在測試函數中,f1和f2是單峰的,而f3是多峰的。對於單峰函數,$AP$的小值導致更好的結果,而對於多模態函數,最好使用較大的$AP$值來逃避局部最優。如果使用$AP$的固定值($AP$=0.05),並且$fl$的值從1.5增加到2.5,則CSA在$f_1$、$f_2$和$f_3$上的性能平均有所提高。如果$AP$的值設置為0.2,$fl$的值從1.5增加到2.5,平均而言,CSA在$f_1$上的性能沒有改善,而在$f_3$上,CSA的性能有所改善。因此,與其他優化技術一樣,CSA的細化是一個需要通過試驗來解決的問題

6. 結論

基於烏鴉的智能行為,提出了一種新的元啟發式算法CSA。CSA是一種基於種群的優化算法,它非常簡單,僅有兩個可調參數(飛行長度和感知概率),這反過來又使其在不同工程領域的應用非常有吸引力。在CSA中,感知概率參數直接用於控制算法的多樣性。 與GA、PSO和HS相比,CSA的參數調整較少,因此更容易實現。通過求解具有不同性質的目標函數、約束和決策變量的不同工程設計問題來評價CSA的有用性。仿真結果表明,與其他算法相比,該算法具有較好的性能,具有較好的競爭效果。在一組基准函數上,雖然PSO是基於種群的算法中的一種快速技術,但它的性能優於CSA。結果表明,CSA的收斂速度較好,該算法在1s左右找到了所研究問題的解。

7. 代碼示例

7.1 問題說明

計算(-100 : 100)范圍內10個維度(變量)的平方和最小

7.2 仿真顯示

  • 從i到n隨機生成跟蹤烏鴉序號

    從i到n跟蹤仿真圖

  • 從0到n隨機生成跟蹤烏鴉序號

從0到n跟蹤仿真圖

7.3 代碼展示(Python)

import random
import numpy
import math
from matplotlib import pyplot as plt

# 初始化變量值(烏鴉搜索算法)
n = 20  # 烏鴉數量
iter_max = 500  # 迭代次數
fl = 2  # 飛行長度
ap = 0.1  # 感知概率
# l-u范圍內d維求平方最小值
d = 10
l = -100
u = 100


# init(n, d, l, u)
# 初始化d維范圍矩陣中烏鴉的位置,返回矩陣x
def init(n, d, l, u):
    x = []
    for i in range(n):  # 生成n個烏鴉
        x.append([])
        for j in range(d):
            x[i].append(l - ((l - u) * random.random()))
    return x


# fitness(x,d)
# 評估該位置適合度,並返回列表fit
# 該程序適合度為將d個變量分別平方相加即為該問題適合度,值越小適合度越高
def fitness(x, d):
    fit = []
    for i in range(len(x)):  # 遍歷每只烏鴉
        fit.append(0)  # 初始化適合度為0
        for j in range(d):
            fit[i] = fit[i] + pow(x[(i, j)], 2)
    return fit


# random_follow_num(n)
# 生成n個隨機編號,編號范圍為0 : (n-1),返回列表rfn
def random_follow_num(n):
    rfn = []
    for i in range(n):
        rfn.append(int(math.ceil(n * random.random()) - 1))  # math.ceil() 向上取整
    return rfn


x = numpy.matrix(init(n, d, l, u))
mem_x = x.copy()  # 儲存記憶位置
fit = numpy.array(fitness(x, d))
mem_fit = fit.copy()  # 儲存記憶位置適合度
new_fit = numpy.array([0])  # 初始化新適合度
ffit_iter = numpy.array([])  # 每次迭代中的最小適合度

# print(x)
# print(fit)
# print(new_fit)

# 文獻中說為從i到n隨機選擇烏鴉,該次方法為隨機生成未有判斷

# 開始迭代
for iter in range(iter_max):
    # rfn = numpy.array(random_follow_num(n))  # 生成隨機跟蹤烏鴉下標
    new_x = numpy.empty((n, d))  # 隨機生成各烏鴉新位置
    for i in range(n):  # 遍歷每個烏鴉
        rfn_num = int(math.ceil(n - (n - i) * random.random()) - 1)
        if random.random() > ap:  # 烏鴉跟蹤未被發現
            for j in range(d):  # 公式1,num[i]為跟蹤的烏鴉編號
                new_x[(i, j)] = x[(i, j)] + (random.random() * fl * (mem_x[(rfn_num, j)] - x[(i, j)]))
                # new_x[(i, j)] = x[(i, j)] + (random.random() * fl * (mem_x[(rfn[i], j)] - x[(i, j)]))
        else:
            for j in range(d):  # 被發現,生成隨機位置
                new_x[(i, j)] = l - ((l - u) * random.random())
    fit = numpy.array(fitness(new_x, d))

    #     print(new_x)
    #     print(ft)
    #     print()

    # 更新位置信息以及記憶
    for i in range(n):
        ctd = 0
        if l < new_x.all() < u:  # 判斷生成位置是否在范圍內
            ctd = ctd + 1
            x[i] = new_x[i].copy()  # 更新烏鴉的位置
            if fit[i] < mem_fit[i]:  # 若有更小的適合度
                mem_x[i] = new_x[i].copy()  # 更新記憶位置
                mem_fit[i] = fit[i]  # 更新記憶適合度
    print(mem_x)
    print(mem_fit)
    print()
    ffit_iter = numpy.append(ffit_iter, numpy.amin(mem_fit))  # 從給定數組中的元素沿指定軸返回最小值
d_ffit = numpy.amin(mem_fit)  # 從給定數組中的元素沿指定軸返回最小值

print("ffit_iter: ")
print(ffit_iter[-100:]) # 每次迭代下的最小適合度
print()

print("d_ffit: " + str(d_ffit)) # 迭代完畢后的最小適合度
print()

# 繪圖
x = numpy.arange(0, iter_max)
y = ffit_iter[x]
plt.title("Crow Search Algorithm \n" + "d: {0} n: {1} fl: {2} ap: {3} l: {4} u: {5}"
          .format(d, n, fl, ap, l, u))
plt.ylabel("y axis fitness ")
plt.xlabel("x axis iteration")
plt.plot(x, y)
plt.show()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM