粒子羣優化算法(Partical Swarm Algorithm,pso)這個算法的原理很簡單,思路就是不斷地迭代,直到尋得最優解爲止,很多書上都有該算法的介紹,此外matlab也自帶了算法的函數:pso(),這裏我自己寫了一個小小的程序來實現算法。
算法的應用背景:對於函數 y=1-cos(3x)*exp(-x), 函數曲線如下,觀察可知在橫軸約爲 x=0.9350~0.9450的地方出現曲線的極值 y=1.3706,現在我要做的是:首先在 x 區間[0,4]範圍內隨機放進去 num 個粒子(xi),目的是找到最大的(yi),他們不斷地改變自己的位置,直到有一天,他們找了很久覺得很累了(達到迭代上限),或者經過反覆比較終於找到最心愛的 y值(尋優結果滿足精度要求),然後這個結果就認爲是最優的。
程序是我自己寫的,很簡單,只要搞明白pso基本算法的原理就能夠理解
function[Pg,n,e]=pso_2(num,ranX,ranV,N,E)
%num代表粒子個數,設定在20~60之間,每個粒子都是一維
%ranX,ranV表示位置、速度的範圍,均爲二維行向量
%N,E搜索終止條件
%%初始化粒子的位置與速度,粒子就像美麗可愛的小鳥一樣,它們時而在左,時而在右,時而快時而慢
x=zeros(num,1);v=zeros(num,1);
for i=1:1:num
x(i,1)=ranX(1,1)+(ranX(1,2)-ranX(1,1))*rand();
v(i,1)=ranV(1,1)+(ranV(1,2)-ranV(1,1))*rand();
end
%%計算初始化以後的局部最優和全局最優
f=zeros(num,1);%%適應度函數
Pl=zeros(num,1);Pg=0;%%局部、全局最優
for i=1:1:num
f(i,1)=1-cos(3*x(i,1))*exp(-x(i,1));
Pl(i,1)=f(i,1);
end
Pg=max(max(Pl));
n=0;e=5;
while n<N&e>E
PGold=Pg;
for i=1:1:num%%計算新一輪的位置與速度
v(i,1)=0.8*v(i,1)+2*rand()*(Pl(i,1)-x(i,1))+2*rand()*(Pg-x(i,1));
if v(i,1)<ranV(1,1)%防止速度太小
v(i,1)=ranV(1,1);
else
if v(i,1)>ranV(1,2)%防止速度太大
v(i,1)=ranV(1,2);
end
end
x(i,1)=x(i,1)+v(i,1);
if x(i,1)<ranX(1,1)%防止位置太小
x(i,1)=ranX(1,1);
else
if x(i,1)>ranX(1,2)%防止位置太大
x(i,1)=ranX(1,2);
end
end
end
for i=1:1:num%%計算新一輪的適應度函數
f(i,1)=1-cos(3*x(i,1))*exp(-x(i,1));
%%更新局部最優和全局最優
if Pl(i,1)<f(i,1)
Pl(i,1)=f(i,1);
end
end
if Pg<max(max(Pl))
Pg=max(Pl);
end
n=n+1;
e=abs(Pg-PGold);
end
下面對算法的可行性做一個演示:
num=2;%只有兩個粒子
X=[0,4];% x 軸(位置)的範圍
V=[-0.5,0.5];%速度範圍
N=100;%終止條件
E=0.001;
[Pg,n,e]=pso_2(num,X,V,N,E);
運行結果顯示,只有2個粒子的情況下每次只需要迭代2或3次,但是每次得到的最優值並不總是接近於1.3706,效果不理想,然而如果設置成20個粒子,那麼經過1次尋找就能輕鬆找到1.3706附近。函數的運行效果依賴於粒子個數num,速度範圍ranV,誤差精度E ,這三個主要參數。