粒子群优化(Particle Swarm Optimization,PSO)是一种模拟生物群体行为的优化算法,其灵感来源于鸟群捕食的行为。每个“粒子”(或“鸟”)在搜索空间中飞翔,寻找优化目标的最优解(个体认知(Cognition-only model))。粒子之间可以分享彼此的信息(社会行为(Social-only model)),从而找到全局最优解。它与其他优化算法的不同之处在于,它只需要目标函数,不依赖于目标的梯度或任何微分形式。它也有很少的超参数。
PSO的优势:在于简单容易实现并且没有许多参数的调节。目前已被广泛应用于函数优化、神经网络训练、模糊系统控制以及其他遗传算法的应用领域。
粒子群算法通过设计一种无质量的粒子来模拟鸟群中的鸟,粒子仅具有两个属性:速度和位置,速度代表移动的快慢,位置代表移动的方向。每个粒子在搜索空间中单独的搜寻最优解,并将其记为当前个体极值,并将个体极值与整个粒子群里的其他粒子共享,找到最优的那个个体极值作为整个粒子群的当前全局最优解,粒子群中的所有粒子根据自己找到的当前个体极值和整个粒子群共享的当前全局最优解来调整自己的速度和位置。
PSO初始化为一群随机粒子(随机解)。然后通过迭代找到最优解。在每一次的迭代中,粒子通过跟踪两个“极值”(pbest,gbest)来更新自己。在找到这两个最优值后,粒子通过下面的公式来更新自己。
公式 (1):
公式 (2):
在公式(1))中, =1,2,...,
,
是此群中粒子的总数;
:粒子速度,最大值为
,如果
大于
,则
=
;
:介于(0,1)之间的随机数;
:粒子的当前位置;
和
:学习因子,通常均为2。
公式(1)的第一部分称为【记忆项】,表示上次速度大小和方向的影响;公式(1)的第二部分称为【自身认知项】,是从当前点指向粒子自身最好点的一个矢量,表示粒子的动作来源于自己经验的部分;公式(1)的第三部分称为【群体认知项】,是一个从当前点指向种群最好点的矢量,反映了粒子间的协同合作和知识共享。粒子就是通过自己的经验和同伴中最好的经验来决定下一步的运动。以上面两个公式为基础,形成了PSO的标准形式。
公式(2)和 公式(3)被视为标准PSO算法。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
//使用c++实现粒子群算法
//需要寻优的非线性函数为:
//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)附近取得极大值
// Author: yuzewei
const int N = 20; //粒子群数量
const int dim = 2; //粒子群维度
const int gen = 300;//100; //迭代次数
const double PI = 3.1415926;
const double w = 0.9;//0.6; //惯性权重
const double c1 = 2;// 1.49445; //自学习,学习因子
const double c2 = 2; // 1.49445; //群体最优学习,学习因子
const double pmin = -2.0; //粒子的移动区间范围
const double pmax = 2.0;
const double vmin = -0.8;// -0.5; //粒子的移动速度范围
const double vmax = 0.8;// 0.5;
double P[N][dim]; //粒子位置
double V[N][dim]; //粒子速度
double fitness[N]; //粒子适应度
double pbest[N][dim]; //粒子最优位置
double gbest[dim]; //粒子群最优位置
int gbestGen = -1; //记录达到最优位置时的迭代次数
double func(double *p)
{
double x = *p;
double y = *(p + 1);
double result = sin(sqrt(x * x + y * y)) / (sqrt(x * x + y * y))
+ exp((cos(2 * PI * x) + cos(2 * PI * y)) / 2) - 2.71289;
return result;
}
int getGbestIndex(double *fit)
{
int index = -1;
double max = *fit;
for (int i = 0; i < N; i++)
{
if (*(fit + i) > max)
{
max = *(fit + i);
index = i;
}
}
return index;
}
void init()
{
int index = -1; //记录位置最佳的粒子编号
default_random_engine e;
uniform_real_distribution rand1(pmin, pmax);
uniform_real_distribution rand2(vmin, vmax);
e.seed(time(0));
for (int i = 0; i < N; i++)
{
for (int j = 0; j < dim; j++)
{
P[i][j] = rand1(e);
V[i][j] = rand2(e);
pbest[i][j] = P[i][j];
}
fitness[i] = func(P[i]);
}
index = getGbestIndex(fitness);
gbest[0] = pbest[index][0];
gbest[1] = pbest[index][1];
gbestGen = 0;
}
void printParticles()
{
/*for (int i = 0; i < N; i++)
{
cout << "第" << i << "个粒子" << endl;
cout << " 位置:(" << P[i][0] << "," << P[i][1] << ")" << endl;
cout << " 速度:(" << V[i][0] << "," << V[i][1] << ")" << endl;
cout << " 适应度:" << fitness[i] << endl;
cout << " 个体最优:(" << pbest[i][0] << "," << pbest[i][1] << ")" << endl;
}*/
//cout << endl;
cout<<"群体最优:(" << gbest[0] << "," << gbest[1] << ")" << endl;
cout << "适应度为:" << func(gbest) << endl;
}
void PSOiterator()
{
cout << "开始迭代!" << endl;
cout << "第1代粒子群:" << endl;
printParticles();
for (int g = 0; g < gen - 1; g++)
{
cout << "第" << g + 2 << "代粒子群:" << endl;
int index = -1; //记录最优粒子个体编号
default_random_engine e;
uniform_real_distribution rand(0, 1.0);
e.seed(time(0));
for (int i = 0; i < N; i++)
{
for (int j = 0; j < dim; j++)
{
//更新速度
V[i][j] = w * V[i][j] + rand(e) * (pbest[i][j] - P[i][j])
+ rand(e) * (gbest[j] - P[i][j]);
if (V[i][j] < vmin)
V[i][j] = vmin;
if (V[i][j] > vmax)
V[i][j] = vmax;
//更新位置
P[i][j] = P[i][j] + V[i][j];
if (P[i][j] < pmin)
P[i][j] = pmin;
if (P[i][j] > pmax)
P[i][j] = pmax;
}
fitness[i] = func(P[i]); //更新适应度
//更新个体最优
if (fitness[i] > func(pbest[i]))
{
pbest[i][0] = P[i][0];
pbest[i][1] = P[i][1];
}
}
//更新整体最优
index = getGbestIndex(fitness);
if (func(P[index]) > func(gbest))
{
gbest[0] = P[index][0];
gbest[1] = P[index][1];
gbestGen = g + 1;
}
printParticles();
}
}
void printResult()
{
cout << "迭代结束!" << endl;
cout << "总共进行了" << gen << "次迭代,";
cout<<"第"<
算法优点:
粒子群算法是一门新兴算法,此算法与遗传算法有很多相似之处,其收敛于全局最优解的概率很大(全局最优概率大)。
相较于传统算法计算速度非常快,全局搜索能力很强(收敛速度快);
PSO对于种群大小不十分敏感,所以初始种群设为500-1000,速度影响也不大;
粒子群算法适用于连续函数极值问题,对于非线性、多峰问题均有较强的全局搜索能力;
设置参数少。