最近在溫習c語言,看的書是《c primer plus》,忽然想起來以前在參加數學建模的時候,用過的一些智慧型演算法,比如遺傳演算法、粒子群演算法、蟻群演算法等等。當時是使用matlab來實現的,而且有些matlab自帶了工具箱,當時有些只是利用工具箱求最優解問題,沒有自己動手親自去實現一遍,現在都忘的差不多了。我覺得那樣層次實在是很淺,沒有真正理解演算法的核心思想。本著「紙上得來終覺淺,絕知此事要躬行」的態度,我決定現在重新複習一遍演算法,然後手工用c語言重新實現一遍。說做就做,我第乙個實現的演算法是相對來說比較簡單的粒子群演算法(與遺傳演算法等相比,至少我自己覺得實現要簡單一些)。
首先簡單介紹一下啟發式演算法和智慧型演算法。粒子群演算法、遺傳演算法等都是從傳統的搜尋演算法演變而來的啟發式演算法。啟發式演算法(heuristic algorithm)是相對於最優化演算法提出的。乙個問題的最優演算法求得該問題每個例項的最優解。啟發式演算法可以這樣定義:乙個基於直觀或經驗構造的演算法,在可接受的花費(指計算時間和空間)下給出待解決組合優化問題每乙個例項的乙個可行解,該可行解與最優解的偏離程度一般不能被預計,但是通常情況下啟發式演算法可以給出接近最優解的不錯的解,但是無法保證每次它都可以得到很好的近似解。啟發式演算法中有一類被稱之為智慧型演算法,所謂"智慧型"二字,指的是這種演算法是通過模仿大自然中的某種生物或者模擬某種現象而抽象得到的演算法,比如遺傳演算法就是模擬自然界生物自然選擇,優勝劣汰,適者生存而得到的進化演算法,粒子群是源於對於鳥類捕食行為的研究,而模擬退火演算法則是根據物理學中固體物質的退火過程抽象得到的優化演算法。智慧型演算法興起於上個世紀80年代左右,之後就一直發展迅速,除了傳統的智慧型演算法之外,近幾年又湧現出了一些新的演算法比如魚群演算法、蜂群演算法等。
言歸正傳,下面來介紹今天的主角:粒子群演算法。粒子群演算法的基本原理如下(參考《matlab智慧型演算法30個案例分析》):
假設在乙個d維的搜尋空間中,由n個粒子組成的種群x=(x1,x2,..,xn),其中第i個粒子表示為乙個d維的向量xi=(xi1,xi2,xid),代表第i個粒子在d維搜尋空間中的位置,亦代表問題的乙個潛在解。根據目標函式即可以計算出每個粒子位置xi對應的適應度值。第i個粒子的速度為vi = (vi1,vi2,...,vid),其個體極值為pi=(pi1,pi2,...,pid),種群的群體極值為pg=(pg1,pg2,...,pgd)。在每次迭代的過程中,粒子通過個體極值和群體極值更新自身的速度和位置,即:
vid(k+1)=w*vid(k)+c1*r1*(pid(k)-xid(k))+c2*r2*(pgd(k)-xid(k))
xid(k+1) = xid(k) + vid(k+1)
其中w為慣性權重,如果不考慮可以預設為1,後面還會再詳細討論w對於pso的影響。d=1,2,..,d;i=1,2,...,n;k為當前迭代次數;vid為粒子的速度;c1和c2是非負的常數,稱為加速度因子;r1和r2是分布於[0,1]之間的隨機數。為了防止粒子的盲目搜尋,一般建議將其位置和速度限制在一定的區間內。
下面是我用c語言實現的求乙個二元函式最大值的粒子群演算法:
1/*2我執行c採用的是ubuntu16 下的gcc編譯器,執行結果截圖如下:* 使用c語言實現粒子群演算法(pso)
3* 參考自《matlab智慧型演算法30個案例分析》
4* update: 16/12/3
5* 本例的尋優非線性函式為
6* f(x,y) = sin(sqrt(x^2+y^2))/(sqrt(x^2+y^2)) + exp((cos(2*pi*x)+cos(2*pi*y))/2) - 2.71289
7* 該函式有很多區域性極大值點,而極限位置為(0,0),在(0,0)附近取得極大值8*/
9 #include10 #include11 #include12 #include13
#define c1 1.49445 //
加速度因子一般是根據大量實驗所得
14#define c2 1.49445
15#define maxgen 300 //
迭代次數
16#define sizepop 20 //
種群規模
17#define popmax 2 //
個體最大取值
18#define popmin -2 //
個體最小取值
19#define vmax 0.5 //
速度最大值
20#define vmin -0.5 //
速度最小值
21#define dim 2 //
粒子的維數
22#define pi 3.1415926 //
圓周率23
24double pop[sizepop][dim]; //
定義種群陣列
25double v[sizepop][dim]; //
定義種群速度陣列
26double fitness[sizepop]; //
定義種群的適應度陣列
27double result[maxgen]; //
定義存放每次迭代種群最優值的陣列
28double pbest[sizepop][dim]; //
個體極值的位置
29double gbest[dim]; //
群體極值的位置
30double fitnesspbest[sizepop]; //
個體極值適應度的值
31double fitnessgbest; //
群體極值適應度值
32double genbest[maxgen][dim]; //
每一代最優值取值粒子
3334
//適應度函式
35double func(double *arr)
36
43//
種群初始化
44void pop_init(void)45
53 fitness[i] = func(pop[i]); //
計算適應度函式值54}
55}56//
max()函式定義
57double * max(double * fit,int
size)
5868 best_fit_index[0] =index;
69 best_fit_index[1] =max;
70return
best_fit_index;
7172}73
//迭代尋優
74void pso_func(void)75
85//
個體極值位置
86for(int i=0;i)
8792}93
//個體極值適應度值
94for(int i=0;i)
9598
//群體極值適應度值
99double bestfitness = *(best_fit_index+1
);100 fitnessgbest =bestfitness;
101102
//迭代尋優
103for(int i=0;i)
104125 fitness[j] = func(pop[j]); //
新粒子的適應度值
126}
127for(int j=0;j)
128136 fitnesspbest[j] =fitness[j];
137}
138//
群體極值更新
139if(fitness[j] >fitnessgbest)
140145
}146
for(int k=0;k)
147150 result[i] = fitnessgbest; //
每代的最優值記錄到陣列
151}
152}
153154
//主函式
155int main(void
)156
多次執行結果差不多,基本每次都可以很接近最優解。而且發現c語言執行時間要遠快於matlab實現(我記得matlab要用好幾秒,這裡就不貼matlab**進行執行時間對比了),只需要耗時0.004秒左右。這裡只討論了基本的粒子群演算法,後面一篇我還會對於粒子群的引數w進行詳細的討論,討論不同的w引數的取法對於粒子群尋優能力的影響。
C語言 粒子群演算法(PSO)
for int i 0 ifor int j 0 j0,1 population i his best j population i location j c2 randvar 0,1 global best j population i location j population i locati...
粒子群(pso)演算法
一 粒子群演算法的概念 粒子群優化演算法 pso particle swarm optimization 是一種進化計算技術 evolutionary computation 源於對鳥群捕食的行為研究。粒子群優化演算法的基本思想 是通過群體中個體之間的協作和資訊共享來尋找最優解 pso的優勢 在於簡...
粒子群演算法 PSO
1995年美國社會心理學家kennedy和電氣工程師eberhart共同提出粒子群優化演算法 particle swarm optimization,pso pso演算法的基本思想利用生物學家heppner的生物群體模型,模擬鳥類覓食過程。鳥類飛行過程相互交流,當乙個鳥飛向棲息地時,其他鳥兒也會跟著...