粒子群优化算法-Particle Swarm Optimization
背景
Kennedy和Eberhart于1995年提出。
特点:简单易行;收敛速度快;设置参数少。
核心
信息的社会共享。生物学对鸟/鱼群捕食的行为研究:社会行为(Social-Onlyl Model)+个体认知(Cognition-Only Model)
问题
问题的解被想象为一只鸟,称为“粒子”。
所有粒子都在一个D维空间进行搜索。
粒子
每个粒子赋予记忆功能,记住所搜寻到的最佳位置。
速度:决定飞行的距离和方向。
速度调整:动态,本身的飞行经验和同伴的飞行经验。
判定
fitness function确定适应值,判断目前位置好坏。
公式
粒子速度更新公式
1.粒子先前的速度。
2.“认知”部分:粒子i当前位置与自己最好位置之间的距离。
3.“社会”部分:粒子i当前位置与群体最好位置之间的距离。
粒子位置更新公式
基本思想
PSO实现-C++
以解决4维Rosenbrock函数为例。
// PSO.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <cstdlib>
using namespace std;
double rnd(double dbLow, double dbUpper)
{
double dbTemp = rand() / ((double)RAND_MAX + 1.0);
return dbLow + dbTemp * (dbUpper - dbLow);
}
//4维的解
#define D 4
//5个粒子
#define M 5
//迭代次数
#define TIME 10000
//速度上限
double Vmax = 60;
//速度下限
double Vmin = -60;
//位置上限
double Xmax = 30;
//位置下限
double Xmin = -30;
//粒子群速度更新公式常数
double c0 = 0.7;
double c1 = 2;
double c2 = 2;
//用随机函数生成值
double r1;
double r2;
//要记录的变量
//粒子自己的fitness最强记录表,记录的是位置,M个,D维
double pbest[M][D];
//群体的fitness最强记录表,记录的是位置,D维
double gbest[D];
//群体的fitness最强记录表,记录的是fitness值
double gbestfitness;
//粒子自己的fitness最强记录表,记录的是fitness值
double pbestfitness[M];
//位置坐标
double x[M][D] = {
{21.721, -9.13677, 6.62244, 3.84079},
{-13.5001, -23.6131, 17.4462, -29.0515},
{-29.6563, -0.871811, -27.8912, 17.7425},
{23.6218, -16.4885, -22.7019, 25.4033},
{-28.0992, 22.6482, 0.675616, -8.43752}
};
//速度
double v[M][D] = {
{-19.9048, 29.562, -22.104, -5.45346},
{-20.5922, -28.6944, -26.3216, 19.0615},
{-7.83576, -55.7173, -40.9177, 28.255},
{-11.6373, -41.0138, 17.7311, -14.87},
{17.561, -13.5365, 51.2722, -56.098}
};
//fitness function
double fitnessFunction(double t[D])
{
double value = 0;
//方程计算
for (int i = 0; i < D; i++)
{
value += 100 * pow((t[i + 1] - pow(t[i], 2)), 2) + pow((t[i] - 1), 2);
}
//求最小值
//所以取了倒数
return 1.0 / value;
}
int main()
{
double fitnessFunction(double t[D]);
//初始化每个粒子的适应度记录表
double pfitness[M];
//记录初值
for (int i = 0; i < M; i++)
{
pfitness[i] = fitnessFunction(x[i]);
}
//假定目前的最大fitness为第一个
double fitnessbest=pfitness[0];
//迭代
for (int t = 0; t < TIME; t++)
{
//更新粒子位置
for (int i = 0; i < M; i++)
{
for (int j = 0; j < D; j++)
{
//先加
x[i][j] += v[i][j];
//如果小于位置规定的最小值
if (x[i][j] < Xmin)
{
//赋为边界值
x[i][j] = Xmin;
}
//如果大于位置规定的最大值
else if (x[i][j] > Xmax)
{
//赋为边界值
x[i][j] = Xmax;
}
}
}
//更新粒子速度
for (int i = 0; i < M; i++)
{
for (int j = 0; j < D; j++)
{
//随机数
r1 = rnd(0.0, 1.0);
r2 = rnd(0.0, 1.0);
//速度更新
v[i][j] = c0 * v[i][j] + c1 * r1 * (pbest[i][j] - x[i][j]) + c2 * r2 * (gbest[j] - x[i][j]);
//如果小于速度规定的最小值
if (v[i][j] < Vmin)
{
//赋为边界值
v[i][j] = Vmin;
}
//如果大于速度规定的最大值
else if (v[i][j] > Vmax)
{
//赋为边界值
v[i][j] = Vmax;
}
}
}
for (int i = 0; i < M; i++)
{
//更新粒子们的fitness表
pfitness[i] = fitnessFunction(x[i]);
//更新粒子们的最强fitness表
//找出fitness最大的粒子
//如果本轮出现了fitness比之前记录的个体best最高的记录
if (pfitness[i] > pbestfitness[i])
{
pbestfitness[i] = pfitness[i];
//更新粒子们最好成绩的位置坐标
for (int j = 0; j < D; j++)
{
pbest[i][j] = x[i][j];
}
}
}
//更新群体fitness最优解
for (int i = 0; i < M; i++)
{
if (pbestfitness[i] > gbestfitness)
{
gbestfitness = pbestfitness[i];
for (int j = 0; j < D; j++)
{
gbest[j] = x[i][j];
}
}
}
cout << t << "times, FUNCTION smallest value is:" << 1/gbestfitness << endl;
}
for (int i = 0; i < D; i++)
{
cout << gbest[i] << endl;
}
return 0;
}
// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
// Debug program: F5 or Debug > Start Debugging menu
// Tips for Getting Started:
// 1. Use the Solution Explorer window to add/manage files
// 2. Use the Team Explorer window to connect to source control
// 3. Use the Output window to see build output and other messages
// 4. Use the Error List window to view errors
// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file