智能优化算法——粒子群算法原理(附代码)

目录

基本概念

算法实现

粒子群算法的构成要素分析  

C++程序测试Sphere函数

总结

visual studio2017c++源代码

源文件下载地址


  • 基本概念

           粒子群优化算法(particle swarm optimization,PSO)属于进化算法的一种,它源于鸟群捕食的行为研究。基本思想是通过群体中个体之间的协作和信息共享来寻找最优解。在PSO中,每个优化问题的潜在解都是搜索空间中的一只鸟,抽象为粒子,每个粒子都有一个由目标函数决定的适应值(fitness value),以及决定它们飞行的方向和距离。 PSO具有实现容易、精度高、收敛快等优点。

  • 算法实现

   在我编写的程序里可以这样理解,我们需要定义基本粒子类粒子群类,每个粒子含有固有的属性,比如速度、位置以及储存更新的变量,粒子群类似,含有个体极值、全局极值以及计算函数。

   假设在一个D维的目标搜索空间中,有N个粒子组成一个群落,其中第i个粒子表示为一个D维的向量,简单来说每个粒子都会对应优化问题相应的优化变量

           X_{i}=\left ( x_{i1}, x_{i2},\cdots x_{iD}\right ) \qquad i=1,2,\cdots N                           (1)

   第i个粒子的飞行速度也是一个D维的向量:

           VV_{i}=\left ( v_{i1}, v_{i2},\cdots v_{iD}\right ) \qquad i=1,2,\cdots NV_{i}=\left ( v_{i1}, v_{i2},\cdots v_{iD}\right ) \qquad i=1,2,\cdots NX_{i}=\left ( x_{i1}, x_{i2},\cdots x_{iD}\right ) \qquad i=1,2,\cdots NV_{i}=\left ( x_{i1}, x_{i2},\cdots x_{iD}\right ) \qquad i=1,2,\cdots NV_{i}=\left ( v_{i1}, v_{i2},\cdots v_{iD}\right ) \qquad i=1,2,\cdots N                              (2)

           第i个粒子迄今为止搜索到的最优V位置称为个体极值

                                   p_{best}\left ( p_{i1}, p_{i2},\cdots p_{iD}\right ) \qquad i=1,2,\cdots N                               (3)

           整个粒子群迄今为止搜索到的最优位置为全局极值

                                             g_{best}=\left ( p_{g1}, p_{g2},\cdots p_{gD}\right )                                              (4)

          个体极值与全局极值寻优时,粒子根据下式更新位置速度

                      V_{id}^{k}=w*V_{id}^{k-1}+c_{1}r_{1}\left ( p_{id}-x_{id}^{k-1} \right )+c_{2}r_{2}\left ( p_{gd}-x_{id}^{k-1} \right )                   (5)

                                                x_{id}^{k}=x_{id}^{k-1}+V_{id}^{k}                                                      (6)

式中:w为惯性权重,非负数,调节对解空间的搜索范围,c1、c2为学习因子,也称为加速常数,r1、r2增加随机搜索性。

式(5)由三部分组成:

第一部分:惯性部分,反映了粒子的运动习惯,代表粒子有维持自己先前速度的趋势;

第二部分:自我认知,反映了粒子对自身历史经验的记忆,代表粒子有向自身最佳位置逼近的趋势;

第三部分:社会认知,反映了粒子间协同与知识共享的群体历史经验,代表粒子有向群体或领域历史最佳位置逼近的趋势。

算法实现流程图如下:

  • 粒子群算法的构成要素分析  

1.种群大小N

        N过小,陷入局优的可能性很大; N过大,优化能力很好,但计算时间大幅提高收敛速度慢。N一般取20-60,较难的问题取100-200。

2. 最大速度V_{m}

       作用在于维护算法的探索能力开发能力的平衡, V_{m}较大时,增强了全局搜素能力,但粒子容易飞过目标区域,导致局部搜索能力下降。较小时,开发能力增强,但会极大地增加全局搜索的时间,容易陷入局部最优。速度取值一般为优化变量范围的10-30%。

3.权重因子w

      w较大,有利于跳出局部极小点,增强粒子的勘探能力全局搜索能力)。w较小,利于粒子的开发能力局部搜索能力)。线性递减权重法:

                              w=w_{max}-\frac{t*\left ( w_{max}-w_{min} \right )}{t_{max}}                                                    (7)    

式中:w_{max}表示权重最大值,w_{min}表示权重最小值,t表示当前迭代步数,t_{max}表示最大迭代步数。

4.学习因子c1、c2

     c1=0,“只有社会,没有自我”迅速丧失群体多样性,易陷入局优而无法跳出。c2=0,“只有自我,没有社会”完全没有信息的社会共享,导致算法收敛速度缓慢 。一般、都不为0,更容易保持收敛速度和搜索效果的均衡,是较好的选择。

  • C++程序测试Sphere函数

                                                    f\left ( x \right )=\sum_{i=1}^{D}x_{i}^{2}

通过程序计算,迭代400步,用origin整理如下:

我们可以看出粒子群优化算法收敛速度非常快,在迭代100步左右就以及寻找到最优值,用时也非常少,下图为种群为20的粒子子寻优走向图。

  • 总结

PSO算法的优点:

  1. 算法通用性强,不依赖于问题信息。
  2. 群体搜索,并具有记忆功能,保留局部个体和全局种群的最优信息,无需梯度信息。
  3. 原理结构简单,设置参数少,容易实现。
  4. 协同搜索,同时利用个体局部信息和群体全局信息指导搜索,收敛速度快

PSO算法的缺点:

  1. 算法局部搜索能力较差,搜索精度不够高。
  2. 算法不能够绝对保证搜索到全局最优解,容易陷入局部极小解
  3. 算法搜索性能对参数具有一定的依赖性。
  • visual studio2017c++源代码

pch.h头文件:

// Particle_swarm.cpp : 粒子群算法实现过程。
//开发人员:陈帅    开发日期:2019年8月4日-29日   邮箱:[email protected]
#ifndef PCH_H
#define PCH_H
#include <iostream>
# include <fstream>
#include <iomanip>
#include <math.h>
#include <vector>
#include<random>
#include<ctime>
//定义粒子的各种性质
using namespace std;
//产生随机小数或整数
class RandomNumber {
public:
	RandomNumber() {
		srand(time(0));    //析构函数,在对象创建时数据成员执行初始化操作
	}
	int integer(int begin, int end)
	{
		return rand() % (end - begin + 1) + begin;
	}
	double decimal(double a, double b)
	{
		return double(rand() % 10000) / 10000 * (b - a) + a;
	}
};
//定义粒子群
class pso
{
private:
	double c1_particle = 2.0; //c1学习因子1,自我认知
	double c2_particle = 2.0; //c2学习因子2,社会认知
	double w_max = 0.9;       //最大惯性权重因子,影响着全局搜索
	double w_min = 0.6;       //最小惯性权重因子,局部深度搜索能力
	int M_particle = 400;     //最大迭代次数,
	int D_particle = 2;       //搜索空间的维数也叫变量个数
	int  N_particle = 20;     //初始化群体的个体,N很小容易陷入局部优化,N很大优化能力很好,优化的寻优精度和运行时间
public:
	vector <vector <double>>x_i;     //粒子群位置
	vector<vector <double>>v_i;      //粒子群速度
	vector<vector<double>>xp_best;   //个体最优位置
	vector<double> xg_best;          //全局最优位置
	vector<double>fp_best;           //个体最优值
	double fg_best;                  //全局最优值
	double w_particle;               //权重更新
	vector<double>x_low = { -100 };   //优化变量下限值
	vector<double>x_high = { 100 };   //优化变量上限值
	vector<double>v_low = { -5 };     //飞行速度下限值
	vector<double>v_high = { 5 };     //飞行速度上限值
	double r1, r2;                    //r1、r2为增加随机搜索性
	void Initialize_fit_extremum();	//给定初始化粒子群速度和位置,计算粒子群适应度,初始化个体极值和全局极值
	void Optimization_iteration();//寻优迭代
};
double function(vector<double> x); //目标函数
#endif //PCH_H

Particle_swarm.cpp主函数

#include "pch.h"
RandomNumber r;       //随机数
int main()
{	clock_t startTime, endTime; //定义程序开始运行时间和结束时间
	startTime = clock();  //计时开始
	pso PSO;  //定义PSO相关参数和函数
	
	//给定初始化粒子群速度和位置,计算粒子群适应度,初始化个体极值和全局极值
	PSO.Initialize_fit_extremum();
	//进入主要循环,按照公式依次迭代,直到满足精度要求
	PSO.Optimization_iteration();
	endTime = clock();//计时结束
	cout << "run time:" << (double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << endl;
}

pso_function.cpp源文件:

#include "pch.h"
double function(vector<double> x)
{
	double fx = 0;
	int n = size(x);
	//============================测试函数=============================
	//1.Sphere函数  变量[-100,100]  
	for (int i = 0; i < n; i++)
	{
	    fx = fx + pow(x[i], 2);
	}
	return fx;
}
void pso::Initialize_fit_extremum()
{
	//===================给定初始化粒子群速度和位置==========
	extern RandomNumber r;       //定义全局随机数
	xp_best.resize(N_particle, vector<double>(D_particle));
	xg_best.resize(D_particle);
	fp_best.resize(N_particle);
	x_i.resize(N_particle, vector<double>(D_particle));
	v_i.resize(N_particle, vector<double>(D_particle));
	for (int i = 0; i < N_particle; i++)
	{
		for (int j = 0; j < D_particle; j++)
		{
			x_i[i][j] = r.decimal(x_low[0], x_high[0]);    //随机初始化位置
			v_i[i][j] = r.decimal(v_low[0] , v_high[0] );    //随机初始化速度
		}
	}
	//================计算粒子群适应度,初始化个体极值和全局极值=========
	for (int j = 0; j < N_particle; j++)
	{
		fp_best[j] = function(x_i[j]);  //先计算各个粒子的适应度
		xp_best[j] = x_i[j];
	}
	xg_best =x_i[0];
	fg_best = function(xg_best);
	for (int j = 1; j < N_particle ; j++)
	{
		if (function(x_i[j]) < fg_best)
		{
			xg_best = x_i[j];   //更新最优值对应的优化变量
			fg_best = function(x_i[j]);
		}                   //找到全局最优变量
	}
}
//**************************************
//粒子群寻优迭代
//*************************************
void pso::Optimization_iteration()
{
	extern RandomNumber r;       //定义全局随机数
	ofstream out1("粒子最优值走向.txt");
	ofstream out("粒子群算法优化结果.txt");
	double f;
	for (int k = 0; k <M_particle; k++)
	{
		w_particle = w_max - k * (w_max - w_min) / M_particle;  //更新权重
		for (int j = 0; j < N_particle; j++)
		{
			r1 = r.decimal(0, 1.0), r2 = r.decimal(0, 1.0);    //r1、r2产生随机数
			for (int i = 0; i < D_particle; i++)
			{
				v_i[j][i] = w_particle * v_i[j][i] + c1_particle * r1*(xp_best[j][i]- x_i[j][i]) + c2_particle * r2*(xg_best[i] - x_i[j][i]);  //更新位置
			//速度越界处理,取边界值	
				if (v_i[j][i] < v_low[0])
				{
					v_i[j][i] = v_low[0];//越界更新为边界值
				}
				if (v_i[j][i] > v_high[0])
				{
					v_i[j][i] =v_high[0];//越界更新为边界值
				}
				x_i[j][i] = x_i[j][i] + v_i[j][i];   //更新速度
			//位置越界处理,取边界值
				if (x_i[j][i]< x_low[0] )
				{
					x_i[j][i] = x_low[0];//越界更新为最优值
				}
				if ( x_i[j][i] >x_high[0])
				{
					x_i[j][i] = x_high[0];//越界更新为边界值
				}
			}
			f = function(x_i[j]);
			if ( f< fp_best[j])   //个体选优
			{
				fp_best[j] = f;
				xp_best[j] = x_i[j];
			}
			if (fp_best[j] < fg_best)           //全局选优
			{
                                xg_best = xp_best[j];
				fg_best = fp_best[j];

			}
			for (int i = 0; i < D_particle; i++)
			{
				out1 << fixed << setw(12) << setprecision(5) << x_i[j][i];
			}
			fg_best = function(xg_best);
		}
		out1 << endl;
		fg_best = function(xg_best);
		out << k << fixed << setw(12) << setprecision(5) << fg_best << endl;
	}
	out << "最优变量:" << endl;
	for (int i = 0; i < D_particle; i++)
	{
		out << "x" << i << "=" << fixed << setw(12) << setprecision(5) << xg_best[i] << endl;//输出最优变量
	}
	out << "最优值=" << fixed << setw(12) << setprecision(5) << fg_best << endl;
	out.close();
	out1.close();
}
  • 源文件下载地址

https://download.csdn.net/download/weixin_41788456/11828583

各位阅读文章的朋友觉得文章不错可以给个好评或者点赞,觉得有问题可以指出来或者发邮箱[email protected]联系我!如需要转载请附上链接,谢谢各位朋友!

(更新于2020.05.05)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章