粒子群优化算法实现与多维函数优化应用

本文将深入探讨粒子群优化(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;
}

算法特点与优势

  1. 维度独立性:支持任意维度的优化问题,各维度可独立配置参数

    cpp 复制代码
    // 各维度独立参数配置
    psopara.dt_[0] = 1.0; psopara.dt_[1] = 0.8;
    psopara.wstart_[0] = 0.9; psopara.wstart_[1] = 0.85;
  2. 自适应惯性权重 :采用非线性递减策略平衡探索与开发
    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

  3. 边界处理策略:多种越界处理方法防止粒子逃逸搜索空间

    cpp 复制代码
    // 边界处理策略
    if (particles_[i].position_[j] > upper_bound_[j]) {
        // 随机重置或边界吸附
    }
  4. 灵活适应度方向:通过宏定义切换最大化/最小化优化目标

    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允许对不同维度采用不同的更新步长,在处理各向异性问题时特别有效。

应用扩展

本实现可扩展至各类优化问题:

  1. 神经网络训练:替代梯度下降法优化网络权重
  2. 工程优化:机械结构参数优化、电路设计
  3. 经济学模型:投资组合优化、风险最小化
  4. 多目标优化:扩展为多目标PSO(MOPSO)

总结

本文实现了通用高效的粒子群优化算法,具有以下特点:

  • 支持任意维度的优化问题
  • 各维度独立参数配置
  • 自适应惯性权重策略
  • 鲁棒的边界处理机制
  • 灵活的适应度方向选择

通过复杂多峰函数的优化实例,展示了算法在寻找全局最优解方面的强大能力。该实现代码结构清晰,模块化设计便于扩展和集成到各类优化系统中。

相关推荐
秋风&萧瑟1 小时前
【C++】C++中的友元函数和友元类
c++
梁诚斌1 小时前
使用OpenSSL接口读取pem编码格式文件中的证书
开发语言·c++
2301_803554525 小时前
c++中的绑定器
开发语言·c++·算法
海棠蚀omo6 小时前
C++笔记-位图和布隆过滤器
开发语言·c++·笔记
消失的旧时光-19436 小时前
c++ 的标准库 --- std::
c++·jni
GiraKoo7 小时前
【GiraKoo】C++11的新特性
c++·后端
不午睡的探索者7 小时前
告别性能瓶颈!Python 量化工程师,进击 C++ 高性能量化交易的“必修课”!
c++·github
OpenC++7 小时前
【C++】观察者模式
c++·观察者模式·设计模式
myloveasuka7 小时前
信号操作集函数
linux·运维·服务器·c语言·c++·vscode