粒子群算法(Particle Swarm Optimization,简称PSO)是一种基于群体协作的启发式优化算法,最早由James Kennedy和Russell Eberhart于1995年提出,灵感来自于模拟鸟群等自然界群体行为的观察。PSO算法通过模拟群体中粒子的行为来寻找最优解,通常用于解决优化问题,特别是连续空间中的优化问题。
一 粒子群算法的基本思想和工作原理
-
粒子表示: 在PSO中,问题的解被表示为粒子,每个粒子都有一个位置(表示解的候选值)和速度。每个粒子的位置和速度都是问题的一个潜在解决方案。
-
群体的初始化: 初始化一群粒子,每个粒子随机初始化其位置和速度。这些粒子会在搜索空间中进行探索。
-
适应度评估: 对每个粒子的位置进行适应度评估,即计算其对应解的目标函数值。这个目标函数通常是需要最小化或最大化的问题的评价标准。
-
更新个体和群体最佳位置: 每个粒子会根据其个体历史最佳位置和群体历史最佳位置来调整自己的速度和位置。这一步通过比较个体最佳和群体最佳位置来更新粒子的速度和位置。
-
迭代搜索: 粒子群算法会不断迭代,每一轮迭代都会更新粒子的速度和位置。通过多次迭代,粒子群逐渐朝着全局最优解的方向移动,以寻找最佳解决方案。
-
终止条件: 算法会在达到一定的迭代次数或满足某个收敛条件时终止。
粒子群算法的核心思想是通过模拟粒子在解空间中的移动来找到最优解。每个粒子根据自身经验和群体的经验来调整自己的位置,从而实现在解空间中的搜索和优化。它通常被用于解决连续优化问题,但也可以应用于一些离散优化问题的变种。
粒子群算法的优点包括易于实现、收敛速度较快以及对问题的初始条件不敏感。然而,它也存在着可能陷入局部最优解的问题,因此在实际应用中需要仔细调整参数和采用一些改进的策略来提高全局搜索能力。
二 流程图
三 基本公式
i:下标为i的粒子
d:粒子在d方向上的分量
x:粒子的位置
v:粒子的速度
w:粒子的惯性权重
,
:粒子向个体最优和全局最优的加速系数
,
:随机数,介于0和1之间
pBest,gBest:当前个体最优点,当前全局最优点
四 代码实现
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
// 定义粒子结构体
struct Particle {
double x[2];
double v[2];
double pBest[2];
double fitness;
};
// 定义常量
const int POP_SIZE = 50;
const int MAX_ITER = 100;
const double W = 0.729; // 惯性权重
const double C1 = 1.4; // 学习因子
const double C2 = 1.4; // 学习因子
const double V_MAX = 5.0; // 粒子最大速度
const double MIN_POS = -5.12; // 变量最小值
const double MAX_POS = 5.12; // 变量最大值
double griewank(double x[2]) // Griewank函数
{
double a1 = 0.0, a2 = 1.0;
for (int i = 0; i < 2; i++) {
a1 += x[i] * x[i];
a2 *= cos(x[i] / sqrt(i + 1));
}
return 1.0 + a1 / 4000.0 - a2;
}
// 计算Rastrigin函数的值
double rastrigin(double x[2]) {
double sum = 0.0;
for (int i = 0; i < 2; i++) {
sum += x[i] * x[i] - 10.0 * cos(2.0 * 3.1415926 * x[i]) + 10.0;
}
return sum;
}
// 初始化粒子群
void initialize(Particle p[POP_SIZE]) {
for (int i = 0; i < POP_SIZE; i++) {
for (int j = 0; j < 2; j++) {
double pos = (double)rand() / RAND_MAX * (MAX_POS - MIN_POS) + MIN_POS;
p[i].x[j] = pos;
/*p.position.push_back(pos);*/
p[i].v[j] = 0;
p[i].pBest[j] = pos;
}
p[i].fitness = rastrigin(p[i].x);
}
}
// 更新粒子速度和位置
void update(Particle particles[POP_SIZE], double gBest[2]) {
for (int i = 0; i < POP_SIZE; i++) {
for (int j = 0; j < 2; j++) {
// 更新速度
double r1 = (double)rand() / RAND_MAX;
double r2 = (double)rand() / RAND_MAX;
particles[i].v[j] = W * particles[i].v[j] +
C1 * r1 * (particles[i].pBest[j] - particles[i].x[j]) + C2 * r2 * (gBest[j] - particles[i].x[j]);
if (particles[i].v[j] > V_MAX) {
particles[i].v[j] = V_MAX;
}
else if (particles[i].v[j] < -V_MAX) {
particles[i].v[j] = -V_MAX;
}
// 更新位置
particles[i].x[j] += particles[i].v[j];
if (particles[i].x[j] > MAX_POS) {
particles[i].x[j] = MAX_POS;
}
else if (particles[i].x[j] < MIN_POS) {
particles[i].x[j] = MIN_POS;
}
}
// 更新个体最优解
double fitness = rastrigin(particles[i].x);
if (fitness < particles[i].fitness) {
particles[i].fitness = fitness;
particles[i].pBest[0] = particles[i].x[0];
particles[i].pBest[1] = particles[i].x[1];
}
}
}
// 找到全局最优解
void findGlobalBest(Particle particles[], double gBest[2]) {
double bestFitness = particles[0].fitness;
for (int i = 1; i < POP_SIZE; i++) {
if (particles[i].fitness < bestFitness) {
bestFitness = particles[i].fitness;
gBest[0] = particles[i].x[0];
gBest[1] = particles[i].x[1];
}
}
}
int main() {
srand((unsigned)time(NULL));
Particle particles[POP_SIZE];
double gBest[2];
initialize(particles);
findGlobalBest(particles, gBest);
for (int i = 0; i < MAX_ITER; i++) {
update(particles, gBest);
findGlobalBest(particles, gBest);
}
cout << "Rastrigin函数最佳适应度:" << rastrigin(gBest)<<endl;
cout << "最佳位置:(" << gBest[0] << "," << gBest[1] << ")" << endl;
return 0;
}