粒子群算法及C++实现

article/2025/10/1 10:08:19

参考博客

https://www.cnblogs.com/alan666/p/8311804.html
https://blog.csdn.net/weixin_39059031/article/details/103723843
https://blog.csdn.net/weixin_40679412/article/details/80571854
https://blog.csdn.net/daaikuaichuan/article/details/81382794
https://blog.csdn.net/luotuo44/article/details/33690179
https://www.cnblogs.com/esCharacter/p/9564660.html
https://blog.csdn.net/weixin_39059031/article/details/103723843

一、原理

1. 鸟群捕食行为

一个鸟群在某区域寻找食物,且这一区域仅有一份食物。鸟群不知道这份食物在哪里,但知道食物距离他们多远以及同伴的位置。鸟群怎样尽快找到食物?搜索目前离食物最近的鸟所在区域,并向这片区域靠拢。
把食物所在位置当做最优点,鸟离食物的距离作为函数适应度,则可以把鸟群寻找食物的过程看做函数寻优的过程。由此受到启发,提出了粒子群算法。

2. 粒子群算法

粒子群算法,又称粒子群优化算法(Partical Swarm Optimization),是近年发展起来的一种新的进化算法(Evolutionary Algorithm - EA),由Eberhart 博士和kennedy 博士于1995年提出,其源于对鸟群捕食的行为研究。 这种算法模拟了人类的社会行为。个体在学习自身经验的同时相互交换信息,由此,种群成员可以逐渐移到问题空间中较好的区域。

2.1 抽象

  1. 粒子:把每只鸟抽象成一个无质量无体积的微粒,优化寻找最优解的过程相当于鸟群寻找食物的过程。
  2. 速度:粒子在问题的搜索空间中以一定的速度飞行,这个速度决定它的飞行方向和距离,速度根据粒子本身的飞行经验和同伴的飞行经验来动态调整。
  3. 适应值:粒子需要一个由目标函数所确定的适应值,来评价粒子的“好坏”程度。 PSO算法先将一群粒子初始化(位置随机),然后通过迭代寻找最优解。每次迭代中,粒子通过跟踪两个“极值”来更新自身位置。这两个极值一个是粒子本身找到的最优解,称为个体极值pBest,另一个是整个种群目前找到的最优解,称为全局极值gBest

2.2 算法流程

  1. 初始化每个粒子群:群体规模N,每个粒子的位置xi 和速度Vi 。
  2. 计算每个粒子的适应度值F[i]。
  3. 对每个粒子,用它的适应度值F[i] 和个体极值Pbest(i) 比较,如果F[i] > Pbest(i),则用F[i]替换Pbest(i)。
  4. 对每个粒子,用它的适应度值F[i] 和全局极值gbest(i) 比较,如果F[i] > gbest(i),则用F[i]替换gbest(i)。
  5. 根据公式 2.3 中公式更新粒子位置x与速度Vi 。如果满足结束条件(误差达到要求或达到最大循环次数)则退出,否则返回步骤 2。
    在这里插入图片描述

2.3 相关公式

将粒子延伸到N维空间,则N维空间中粒子的位置、飞行速度为矢量,粒子根据如下公式更新速度与位置:
在这里插入图片描述
其中w是惯性权重(加权系数),代表粒子上一轮速度对本轮的影响程度;
c1和c2是学习因子(加速度系数),代表粒子向自身最优(自我总结)和群体最优学习的能力。
rand()为0~1的随机数。

2.4 参数设置

  1. 粒子数量:一般取1~40. 其实对于大部分的问题10个粒子已经足够可以取得好的结果;
  2. 粒子的维度:由优化问题决定,如本次实验为二元函数的优化问题,所以维度为2;
  3. 粒子的范围::即粒子的移动区间范围,由优化问题决定,每一维可以设定不同的范围;
  4. W:一般取值在0.1~0.9之间,对优化影响较大,w取值较大时,有利于跳出局部最优点,w取值较小时有利于算法收敛;
  5. 学习因子:通常设c1 = c2 = 2,范围为0~4;
  6. 粒子的速度:表示粒子在一次迭代中可移动的最大距离,通常根据函数自变量取值范围来设定,例如x 属于 [-10, 10], 那么 Vmax 的大小就是 20;

二、例子

1. 题目

在这里插入图片描述

2. 关键代码

2.1 数据结构

本次实验数据结构设置较为简单,粒子的位置、速度和最优位置均设置为二维数组,行为粒子数量,列为函数维度。除此之外粒子群对应的适应度设为一维数组,粒子群整体最优位置设为长度为维度的数组,具体代码片如下:

double P[N][dim];       //粒子位置
double V[N][dim];       //粒子速度
double fitness[N];      //粒子适应度
double pbest[N][dim];   //粒子最优位置double gbest[dim];      //粒子群最优位置

2.2 粒子速度与位置的更新

使用2.3中公式对粒子位置与状态进行更新。本次实验中粒子维度为2,所以需要对每个粒子的位置与速度的两个分量分别进行更新。然后更新粒子适应值,若新的适应值大于粒子的个体最优位置,则更新粒子的个体最优位置,最后再比较是否获得更优的群体最优位置,若更优则更新群体最优位置,具体代码片如下:

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;}

2.3 随机数生成(新接触)

C++11 : default_random_engine
是C++11提供了新的随机数生成器,随机数引擎default_random_engine,使用时包含头文件#include<random>;默认情况下,default_random_engine的生成范围是一个unsigned,可以通过方法min()和max()获取生成范围;与rand()类似,default_random_engine也需要通过随机数种子改变生成的序列,设置方法可以通过调用方法seed();随机数引擎可以通过分布对象设置生成范围,uniform_int_distribution<unsigned>或uniform_real_distribution<double>;相对rand(),可以使用uniform_real_distribution<>生成随机浮点数,并且不用担心精度问题,使用方法如下:

    default_random_engine e;//定义随机数引擎uniform_int_distribution<unsigned> id(1, 10);//整型分布uniform_real_distribution<double> dd(0, 1.0);//浮点型分布e.seed(10);//设置随机数种子for (size_t i = 0; i < 10; i++){cout << id(e) << " ; " << dd(e) << endl;}

3. 结果

  1. 当w设为0.6时,算法收敛较快,经过多次运行,大约在80代左右收敛。
    在这里插入图片描述

  2. 当w设为0.9时,收敛较慢,大于要到280代左右才可收敛:
    在这里插入图片描述

  3. 分析
    在代码实现的具体过程中,遇到的问题主要是参数设置的问题。其中粒子速度与位置范围的设定一直不合适,导致粒子群在第二轮迭代时,大多数粒子会超过设定的边界,虽然将超出边界的粒子速度与位置设为边界值,但因为是大数粒子越界,所以后面的迭代也就没有了意义。通过在网络上查询相关博客,得到的解决办法是粒子速度与位置边界设定与函数的自变量和值域相关,经过分析,大概得出本次实验要优化的函数,在(0,0)位置时取得最优解,所以将粒子速度范围设为(-0.5,0.5),最终得到了较好的效果,不会再出现大量粒子越界的情况。
    回想此次实验,应该还是不对,如果提前知道收敛点大概在哪,再设置参数,算法还有意义吗?

4. 源代码

#include <iostream>
#include<time.h>
#include <random>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: yuzeweiconst 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<double> rand1(pmin, pmax);uniform_real_distribution<double> 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<double> 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<<"第"<<gbestGen<<"代得到最优位置:(" << gbest[0] << "," << gbest[1] << ")" << endl;cout << "此位置对应的函数值为:" << func(gbest) << endl;
}int main()
{init();PSOiterator();printResult();return 0;
}

http://chatgpt.dhexx.cn/article/INt8oXVb.shtml

相关文章

粒子群算法详解

一.产生背景 ❃粒子群算法(particleswarm optimization&#xff0c;PSO)由Kennedy和Eberhart在1995年提出&#xff0c;该算法对于Hepper的模拟鸟群(鱼群)的模型进行修正&#xff0c;以使粒子能够飞向解空间&#xff0c;并在最好解处降落&#xff0c;从而得到了粒子群优化算法。…

高铁列车粒子群算法及改进粒子群算法多目标单目标运行优化设计

问题介绍 根据表1、2、3 所列数据&#xff0c;以能耗、运行时间、舒适性为目标分别设计列车运行速度—距离曲线&#xff1b;完成单目标以及多目标优化下的列车运行对比&#xff1b;选择其中一种方案&#xff0c;设计列车速度跟踪控制算法并进行性能分析。 1 列车参数设置表优化…

智能优化算法之粒子群算法

1、粒子群优化算法概述 粒子群优化算法(PSO&#xff1a;Particle swarm optimization) 是一种进化计算技术&#xff08;evolutionary computation&#xff09;。源于对鸟群捕食的行为研究。粒子群优化算法的基本思想&#xff1a;是通过群体中个体之间的协作和信息共享来寻找最优…

基于群智能的三维路径规划算法 2 —— 粒子群算法

目录 1 PSO算法的基本理论2 PSO算法程序设计流程3 MATLAB编程实现4 算法举例5 函数1 unifrnd函数 1 PSO算法的基本理论 将三个散点看做一个粒子 惯性分量就是 v i − 1 d v^d_{i-1} vi−1d​ 粒子群&#xff08;PSO&#xff09;算法是依托群鸟觅食的模型寻找最优解。群体特征…

粒子群算法(2)

上一期&#xff1a;粒子群算法&#xff08;1&#xff09; 线性递减惯性权重 惯性权重w体现的是粒子继承先前的速度的能力&#xff0c;Shi,Y最先将惯性权重w引入到粒子群算法中&#xff0c;并分析指出一个较大的惯性权值有利于全局搜索&#xff0c;而一个较小的权值则更利于局部…

粒子群算法简介

粒子群算法简介 前言 本文内容借鉴于 刘衍民的博士论文:“粒子群算法的研究及应用”. 现有的大多数群智能算法,如:乌鸦算法、鸽子算法、蚁群算法、萤火虫算法和灰狼优化算法等&#xff0c;都可以归类为粒子群算法.(个人觉得,这些算法就是整个稀奇古怪的名字,颇有舞文弄墨,强…

粒子群算法(1)

粒子群算法 1.入门 粒子群算法&#xff0c;其全称为粒子群优化算法(Particle Swarm Optimization,PsO)。它是通过模拟鸟群觅食行为而发展起来的一种基于群体协作的搜索算法。 2.什么是启发式算法&#xff1f; 启发式算法百度百科上的定义:一个基于直观或经验构造的算法,在可…

粒子群优化算法

背景 1995 年&#xff0c;Kennedy 和 Eberhart 两位博士共同 提出了粒子群优化算法 (Particle swarm optimization&#xff0c; PSO) PSO 算法中&#xff0c;将鸟群的个体位置或食物当作优化问题的解&#xff0c;利用群体中个体与最优个体以及个体之间的信息交互&#xff0c;引…

粒子群算法

粒子群算法简介 粒子群算法&#xff0c;其全称为粒子群优化算法(Particle Swarm Optimization,PSO) 。它是通过模拟鸟群觅食行为而发展起来的一种基于群体协作的搜索算法。粒子群算法属于启发式算法也叫智能优化算法&#xff0c;其基本思想在于通过群体中个体之间的协作和信息…

粒子群(PSO)算法的理解与应用

最近在学习粒子群算法&#xff0c;看了很多资料都有点摸不清头脑&#xff0c;直到看了一篇博客中超级简洁的粒子群C实现代码&#xff0c;才明白粒子群算法的原理&#xff0c;真心感谢博主&#xff0c;在此贴出博主的博客地址&#xff1a; http://blog.sina.com.cn/s/blog_4ed02…

6套粒子群算法(内含matlab代码)

粒子群算法(1)----粒子群算法简介 一、粒子群算法的历史 粒子群算法源于复杂适应系统&#xff08;Complex Adaptive System,CAS&#xff09;。CAS理论于1994年正式提出&#xff0c;CAS中的成员称为主体。比如研究鸟群系统&#xff0c;每个鸟在这个系统中就称为主体。主体有适…

粒子群算法(PSO)详解

1 粒子群PSO算法简介 1.1 维基百科的解释 粒子群算法&#xff08;Particle Swarm Optimization&#xff0c;简称PSO&#xff09;&#xff0c;或称粒子群优化&#xff0c;是属于人工智能算法&#xff0c;公元1995年由肯尼迪&#xff08;Kennedy&#xff09;与埃伯哈特&#xf…

优化算法——粒子群算法(PSO)

一、粒子群算法的概述 粒子群算法(PSO)属于群智能算法的一种&#xff0c;是通过模拟鸟群捕食行为设计的。假设区域里就只有一块食物&#xff08;即通常优化问题中所讲的最优解&#xff09;&#xff0c;鸟群的任务是找到这个食物源。鸟群在整个搜寻的过程中&#xff0c;通过相互…

粒子群算法(PSO) 介绍

算法理解 粒子群算法&#xff0c;又叫鸟群算法&#xff0c;可见是受鸟群捕食行为的启发。它属于遗传算法、群智算法。粒子群算法关注于粒子的两个属性&#xff1a;位置和速度。每个粒子在空间中单独搜寻&#xff0c;它们记得自己找到的过最优解&#xff0c;也知道整个粒子群当…

【优秀作业】粒子群算法

粒子群优化算法 一、概述 粒子群优化算法&#xff08;Particle Swarm Optimization&#xff0c;PSO&#xff09;的思想来源于对鸟捕食行为的模仿&#xff0c;最初&#xff0c;Reynolds.Heppner 等科学家研究的是鸟类飞行的美学和那些能使鸟群同时突然改变方向&#xff0c;分散…

Dex加固与反编译

编译与反编译 编译 将java代码转换为Dalvik字节码 将res资源文件、AndroidManifest.xml等配置文件编译为二进制文件 反编译 将DEX文件转换为jar包或者Smali文件 将二进制资源文件还原为资源源码文件 编译与反编译是相对的过程&#xff0c;转换过程分别由编译器和反编译器实…

编译与反编译

编译&#xff1a;高级语言转换成计算机认识的低级语言 编译的主要的目的是将便于人编写、阅读、维护的高级语言所写作的源代码程序&#xff0c;翻译为计算机能解读、运行的低级语言的程序&#xff0c;也就是可执行文件。 反编译&#xff1a;Java的反编译&#xff0c;一般是将…

反编译网站

最近帮一个公司反编译了一个他们在用的网站&#xff0c;是一个印照片&#xff0c;然后群(384389229)里面的伙伴们&#xff08;专指&#xff1a;魂牵悲梦&#xff09;&#xff0c;叫我写个反编译的教程出来&#xff0c;由于前面时间很忙&#xff0c;一拖再拖到了现在终于有空就写…

编译/反编译

1.Android APK 1.软件 1.apktool 1.作用&#xff1a;反编译apk或重新打包apk 2.dex2jar 1.作用&#xff1a;将Android的可执行文件.dex转换为.jar 3.jd-gui 1.作用&#xff1a;方便阅读jar文件的代码工具 2.步骤 1.通过apktool将apk软件反编译2.使用dex2jar将classes.dex文件转…

反编译(Decompilers)

工具下载 调试工具反汇编工具反编译工具PE相关工具编译工具编辑工具.NET工具脱壳工具加壳工具补丁工具监视软件代码计算 密码学工具其它 反编译&#xff08;Decompilers&#xff09; VFP程序 UnFoxAll 3.0专业增强版  优点&#xff1a;界面和功能较实用缺点&#xff1a;支持到…