本文将深入探讨粒子群优化(PSO)算法的实现及其在多维函数优化中的应用。通过完整的C++实现和数学分析,展示如何利用PSO解决复杂优化问题。
算法原理与实现
粒子群优化算法模拟鸟群觅食行为,通过群体智能寻找最优解。每个粒子代表一个潜在解,在搜索空间中移动,根据个体经验和群体经验调整运动方向。

核心数据结构
cpp
// PSO.h
#pragma once
#include <stdlib.h>
#include <iostream>
#include <vector>
// 适应度优化方向定义
#define MAXIMIZE_FITNESS
// PSO参数结构体
struct PSOPara {
int dim_; // 参数维度
int particle_num_; // 粒子个数
int max_iter_num_; // 最大迭代次数
double *dt_ = nullptr; // 时间步长
double *wstart_ = nullptr; // 初始权重
double *wend_ = nullptr; // 终止权重
double *C1_ = nullptr; // 个体学习因子
double *C2_ = nullptr; // 社会学习因子
double *upper_bound_ = nullptr; // 搜索空间上限
double *lower_bound_ = nullptr; // 搜索空间下限
double *range_interval_ = nullptr; // 搜索空间范围
int results_dim_ = 0; // 结果维度
PSOPara(){}
PSOPara(int dim, bool hasBound = false) {
dim_ = dim;
dt_ = new double[dim_];
wstart_ = new double[dim_];
wend_ = new double[dim_];
C1_ = new double[dim_];
C2_ = new double[dim_];
if (hasBound) {
upper_bound_ = new double[dim_];
lower_bound_ = new double[dim_];
range_interval_ = new double[dim_];
}
}
~PSOPara() { /* 内存释放代码 */ }
};
// 粒子结构体
struct Particle {
int dim_; // 参数维度
double fitness_; // 当前适应度
double *position_ = nullptr;// 当前位置
double *velocity_ = nullptr;// 当前速度
double *best_position_ = nullptr; // 个体历史最优位置
double best_fitness_; // 个体历史最优适应度
Particle(){}
~Particle() { /* 内存释放代码 */ }
};
// 适应度函数类型定义
typedef double(*ComputeFitness)(Particle& particle);
// PSO优化器类
class PSOOptimizer {
public:
// 构造函数和核心方法
PSOOptimizer(PSOPara* pso_para, ComputeFitness fitness_fun);
void InitialAllParticles();
void UpdateAllParticles();
private:
// 内部实现方法
void InitialParticle(int i);
void UpdateParticle(int i);
void GetInertialWeight();
double GetDoubleRand(int N = 9999);
double GetFitness(Particle& particle);
// 算法状态变量
int particle_num_;
int max_iter_num_;
int curr_iter_;
int dim_;
Particle *particles_ = nullptr;
double all_best_fitness_;
double *all_best_position_ = nullptr;
ComputeFitness fitness_fun_;
// ... 其他成员变量
};
算法核心实现
cpp
// PSO.cpp
#include "PSO.h"
// 构造函数:初始化PSO参数
PSOOptimizer::PSOOptimizer(PSOPara* pso_para, ComputeFitness fitness_fun) {
// 参数初始化(详细代码见原始文件)
// ...
fitness_fun_ = fitness_fun;
}
// 初始化所有粒子
void PSOOptimizer::InitialAllParticles() {
// 初始化第一个粒子
InitialParticle(0);
all_best_fitness_ = particles_[0].best_fitness_;
// 初始化其余粒子并更新全局最优
for (int i = 1; i < particle_num_; i++) {
InitialParticle(i);
#ifdef MAXIMIZE_FITNESS
if (particles_[i].best_fitness_ > all_best_fitness_)
#else
if (particles_[i].best_fitness_ < all_best_fitness_)
#endif
{
all_best_fitness_ = particles_[i].best_fitness_;
// 更新全局最优位置
}
}
}
// 更新所有粒子状态
void PSOOptimizer::UpdateAllParticles() {
GetInertialWeight(); // 计算当前惯性权重
for (int i = 0; i < particle_num_; i++) {
UpdateParticle(i); // 更新单个粒子
// 更新全局最优解
#ifdef MAXIMIZE_FITNESS
if (particles_[i].best_fitness_ > all_best_fitness_)
#else
if (particles_[i].best_fitness_ < all_best_fitness_)
#endif
{
all_best_fitness_ = particles_[i].best_fitness_;
// 更新全局最优位置
}
}
curr_iter_++;
}
// 单个粒子更新逻辑
void PSOOptimizer::UpdateParticle(int i) {
for (int j = 0; j < dim_; j++) {
// 速度更新公式:
// $v_{ij}(t+1) = w_j \cdot v_{ij}(t) +
// c1_j \cdot rand() \cdot (pbest_{ij} - x_{ij}(t)) +
// c2_j \cdot rand() \cdot (gbest_j - x_{ij}(t))$
particles_[i].velocity_[j] = w_[j] * particles_[i].velocity_[j] +
C1_[j] * GetDoubleRand() * (particles_[i].best_position_[j] - particles_[i].position_[j]) +
C2_[j] * GetDoubleRand() * (all_best_position_[j] - particles_[i].position_[j]);
// 位置更新公式:
// $x_{ij}(t+1) = x_{ij}(t) + \Delta t_j \cdot v_{ij}(t+1)$
particles_[i].position_[j] += dt_[j] * particles_[i].velocity_[j];
// 边界处理逻辑
if (upper_bound_ && lower_bound_) {
// 越界处理策略
}
}
// 计算新位置的适应度
particles_[i].fitness_ = GetFitness(particles_[i]);
// 更新个体最优
#ifdef MAXIMIZE_FITNESS
if (particles_[i].fitness_ > particles_[i].best_fitness_)
#else
if (particles_[i].fitness_ < particles_[i].best_fitness_)
#endif
{
particles_[i].best_fitness_ = particles_[i].fitness_;
// 更新个体最优位置
}
}
// 惯性权重计算(线性递减策略)
void PSOOptimizer::GetInertialWeight() {
double temp = curr_iter_ / (double)max_iter_num_;
temp *= temp; // 二次变化
for (int i = 0; i < dim_; i++) {
// $w_i = w_{start,i} - (w_{start,i} - w_{end,i}) \cdot (t/T)^2$
w_[i] = wstart_[i] - (wstart_[i] - wend_[i]) * temp;
}
}
应用实例:多维函数优化
目标函数
我们优化以下复杂多峰函数:
f ( x , y ) = sin ( x 2 + y 2 ) x 2 + y 2 + e 1 2 cos ( 2 π x ) + 1 2 cos ( 2 π y ) − 2.71289 f(x,y) = \frac{\sin(\sqrt{x^2 + y^2})}{\sqrt{x^2 + y^2}} + e^{\frac{1}{2}\cos(2\pi x) + \frac{1}{2}\cos(2\pi y)} - 2.71289 f(x,y)=x2+y2 sin(x2+y2 )+e21cos(2πx)+21cos(2πy)−2.71289
该函数在原点(0,0)处有全局最大值≈1.00539,同时包含多个局部极大值点。
cpp
// FitnessFunction.h
#pragma once
#include "PSO.h"
#include <math.h>
#define PI 3.1415926
double FitnessFunction(Particle& particle) {
double x = particle.position_[0];
double y = particle.position_[1];
double temp = sqrt(x * x + y * y);
// 避免除零错误
if (temp < 1e-10) temp = 1e-10;
// 目标函数计算
double fitness = sin(temp) / temp +
exp(0.5 * cos(2 * PI * x) +
0.5 * cos(2 * PI * y)) - 2.71289;
return fitness;
}
主程序实现
cpp
// main_test.cpp
#include <iostream>
#include "PSO.h"
#include "FitnessFunction.h"
#include <time.h>
int main() {
// 配置PSO参数(2维问题)
PSOPara psopara(2, true);
psopara.particle_num_ = 20; // 粒子数量
psopara.max_iter_num_ = 300; // 最大迭代次数
// 设置算法参数(各维度独立)
psopara.dt_[0] = 1.0; psopara.dt_[1] = 1.0;
psopara.wstart_[0] = 0.9; psopara.wstart_[1] = 0.9;
psopara.wend_[0] = 0.4; psopara.wend_[1] = 0.4;
psopara.C1_[0] = 1.49445; psopara.C1_[1] = 1.49445;
psopara.C2_[0] = 1.49445; psopara.C2_[1] = 1.49445;
// 设置搜索空间 [-1, 1]×[-1, 1]
psopara.lower_bound_[0] = -1.0; psopara.lower_bound_[1] = -1.0;
psopara.upper_bound_[0] = 1.0; psopara.upper_bound_[1] = 1.0;
// 初始化优化器
PSOOptimizer psooptimizer(&psopara, FitnessFunction);
std::srand((unsigned int)time(0));
psooptimizer.InitialAllParticles();
// 迭代优化过程
for (int i = 0; i < psooptimizer.max_iter_num_; i++) {
psooptimizer.UpdateAllParticles();
// 输出当前最优解
std::cout << "Iter " << i << ": x = "
<< psooptimizer.all_best_position_[0] << ", y = "
<< psooptimizer.all_best_position_[1]
<< ", fitness = " << psooptimizer.all_best_fitness_
<< std::endl;
}
return 0;
}
算法特点与优势
-
维度独立性:支持任意维度的优化问题,各维度可独立配置参数
cpp// 各维度独立参数配置 psopara.dt_[0] = 1.0; psopara.dt_[1] = 0.8; psopara.wstart_[0] = 0.9; psopara.wstart_[1] = 0.85;
-
自适应惯性权重 :采用非线性递减策略平衡探索与开发
w i ( t ) = w s t a r t , i − ( w s t a r t , i − w e n d , i ) ⋅ ( t T ) 2 w_i(t) = w_{start,i} - (w_{start,i} - w_{end,i}) \cdot \left(\frac{t}{T}\right)^2 wi(t)=wstart,i−(wstart,i−wend,i)⋅(Tt)2 -
边界处理策略:多种越界处理方法防止粒子逃逸搜索空间
cpp// 边界处理策略 if (particles_[i].position_[j] > upper_bound_[j]) { // 随机重置或边界吸附 }
-
灵活适应度方向:通过宏定义切换最大化/最小化优化目标
cpp// 切换优化方向 // #define MINIMIZE_FITNESS #define MAXIMIZE_FITNESS
数学分析
速度更新公式
粒子速度更新是PSO的核心,包含三个部分:
v i j ( t + 1 ) = w j ⋅ v i j ( t ) ⏟ 惯性部分 + c 1 j ⋅ r 1 ⋅ ( p b e s t i j − x i j ( t ) ) ⏟ 认知部分 + c 2 j ⋅ r 2 ⋅ ( g b e s t j − x i j ( t ) ) ⏟ 社会部分 v_{ij}(t+1) = \underbrace{w_j \cdot v_{ij}(t)}{\text{惯性部分}} + \underbrace{c1_j \cdot r1 \cdot (pbest{ij} - x_{ij}(t))}{\text{认知部分}} + \underbrace{c2_j \cdot r2 \cdot (gbest_j - x{ij}(t))}_{\text{社会部分}} vij(t+1)=惯性部分 wj⋅vij(t)+认知部分 c1j⋅r1⋅(pbestij−xij(t))+社会部分 c2j⋅r2⋅(gbestj−xij(t))
其中:
- w j w_j wj:第j维的惯性权重,控制历史速度的影响
- c 1 j , c 2 j c1_j, c2_j c1j,c2j:学习因子,平衡个体与群体经验
- r 1 , r 2 ∼ U ( 0 , 1 ) r1, r2 \sim U(0,1) r1,r2∼U(0,1):随机数增加探索性

位置更新
位置更新考虑时间步长参数 Δ t j \Delta t_j Δtj:
x i j ( t + 1 ) = x i j ( t ) + Δ t j ⋅ v i j ( t + 1 ) x_{ij}(t+1) = x_{ij}(t) + \Delta t_j \cdot v_{ij}(t+1) xij(t+1)=xij(t)+Δtj⋅vij(t+1)
Δ t j \Delta t_j Δtj允许对不同维度采用不同的更新步长,在处理各向异性问题时特别有效。
应用扩展
本实现可扩展至各类优化问题:
- 神经网络训练:替代梯度下降法优化网络权重
- 工程优化:机械结构参数优化、电路设计
- 经济学模型:投资组合优化、风险最小化
- 多目标优化:扩展为多目标PSO(MOPSO)
总结
本文实现了通用高效的粒子群优化算法,具有以下特点:
- 支持任意维度的优化问题
- 各维度独立参数配置
- 自适应惯性权重策略
- 鲁棒的边界处理机制
- 灵活的适应度方向选择
通过复杂多峰函数的优化实例,展示了算法在寻找全局最优解方面的强大能力。该实现代码结构清晰,模块化设计便于扩展和集成到各类优化系统中。