粒子群算法的核心的两个公式为:
速度更新公式:
Vid(k+1)=wVid(k)+c1r1*(Pid(k)-Xid(k))+c2r2(Pgd(k)-Xid(k))
位置更新公式:
Xid(k+1) = Xid(k) + Vid(k+1)
w称之为惯性权重,体现的是粒子继承先前速度的能力。 经验表明:一个较大的惯性权重有利于全局搜索,而一个较小的惯性权重则更有利于局部搜索。
为了更好地平衡算法的全局搜索能力与局部搜索能力,Shi.Y提出了线性递减惯性权重(LDIW)
即:w(k) = w_end + (w_start- w_end)*(Tmax-k)/Tmax。*其中w_start 为初始惯性权重,w_end 为迭代至最大次数时的惯性权重;k为当前迭代次数, Tmax为最大迭代次数。
一般来说,w_start=0.9,w_end=0.4时,算法的性能最好。这样随着迭代的进行,惯性权重从0.9递减到0.4,迭代初期较大的惯性权重使算法保持了较强的全局搜索能力。而迭代后期较小的惯性权重有利于算法进行更精确的局部搜索。线性惯性权重,只是一种经验做法,常用的惯性权重还包括 以下几种。*
(3) w(k) = w_start - (w_start-w_end)(k/Tmax)^2
(4) w(k) = w_start + (w_start-w_end)(2k/Tmax - (k/Tmax)^2)
(5) w(k) = w_end(w_start/w_end)^(1/(1+c*k/Tmax)) ,c为常数,比如取10等。
本例的目的就是比较这5种不同的w取值,对于PSO寻优的影响。比较的方法为每种w取值,重复实验若干次(比如100次),比较平均最优解的大小,陷入次优解的次数,以及接近最优解的次数。 这样对于5种方法的优劣可以有一个直观的比较。
代码:
/*
* 本例的寻优非线性函数为
* 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
* 该函数有很多局部极大值点,而极限位置为(0, 0), 在(0, 0)附近取得极大值
*/
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#define c1 1.49445 //加速度因子一般是根据大量实验所得
#define c2 1.49445
#define maxgen 300 // 迭代次数
#define repeat 100 // 重复实验次数
#define sizepop 20 // 种群规模
#define popmax 2 // 个体位置最大取值
#define popmin -2 // 个体位置最小取值
#define Vmax 0.5 // 速度最大值
#define Vmin -0.5 //速度最小值
#define dim 2 // 粒子的维数
#define w_start 0.9
#define w_end 0.4
#define PI 3.1415926 //圆周率
double pop[sizepop][dim]; // 定义种群数组
double V[sizepop][dim]; // 定义种群速度数组
double fitness[sizepop]; // 定义种群的适应度数组
double result[maxgen]; //定义存放每次迭代种群最优值的数组
double pbest[sizepop][dim]; // 个体极值的位置
double gbest[dim]; //群体极值的位置
double fitnesspbest[sizepop]; //个体极值适应度的值
double fitnessgbest; // 群体极值适应度值
double genbest[maxgen][dim]; //每一代最优值取值粒子
double func(double * arr); //适应度函数
void pop_init(void); // 种群初始化
double * max(double * fit, int size); // max()函数定义
void PSO_func(int n); // 迭代寻优,传入的参数为一个整数,取值为1到5,分别代表5种不同的计算w的方法
int main(void)
{
clock_t start, finish; //程序开始和结束时间
start = clock(); //开始计时
srand((unsigned)time(NULL)); // 初始化随机数种子
for (int i = 1; i <= 5; i++)