实验目的
实现并实验掌握PSO算法,用c++、java、c编程语言来实现。
实验内容
通过c++编程实现对一下两个函数的全局最小值的具体数值以及N维空间中的位置。
其中本次实验N = 2;
他们分别是:
func1;
func2;
实验过程
在描述实验过程之前需要说明一个问题即:
在最优化问题中输入变量X是一个N维向量,最终优化的结果也是一个位置即N维变量。
实验步骤:
1、整理并声明变量
首先整理我们需要的变量:
粒子速度、位置的最大最小值;一个粒子群的群规模大小p_size;一个存储粒子群位置的变量;一个存储粒子群速度的变量;
一个保存粒子群个体历史最优位置的变量;一个保存粒子群全局最优位置的变量;
接着整理我们需要使用到的参数:
速度衰减常数;速度改变使用到的两个参数div1,div2;加速度的个体和社会权重self_weight,social_weight;
2、初始化变量
使用C++随机数生成引擎std::random_engine,生成满足范围要求的随机数字;
3、进行适应度评估并更新速度和位置
此次实验仅评估函数的数值,故函数适应度即为自己当前位置值与最优位置(使得函数值最小)的距离。
简单点来说即现在自己的函数值和SOCIAL_BEST以及SELF_BEST的大小关系。此处还应该更新每个粒子的
个体最优位置和粒子群的社区最优位置。
4、迭代循环
如果当前epoch(it_times)是否达到规定次数(it_max),如果达到退出循环并且输出社区最优位置和该位置对应的函数值。
5、实现代码:
#include <iostream>
#include <vector>
#include <random>
using std::cin;
using std::cout;
using std::vector;
constexpr double vmin = -5;
constexpr double vmax = 5;
constexpr double Area_l = -50;
constexpr double Area_r = 50;
constexpr int it_max = 100;
constexpr double self_scale = 1.3;
constexpr double social_scale = 1.3;
//收敛常数
constexpr double alpha = 0.729;
constexpr double dv1 = 0.5;
constexpr double dv2 = 0.5;
int demension = 2;
int p_size = 30;
int it_times = 0;
vector<double>social_best_position(demension);
vector<vector<double>>per_best_position(p_size);
//输入一个X向量,返回一个实数值
double func(vector<double>&X)
{
//X向量是一个输入向量表示一个点的在各维度的位置
double sum = 1;
for(auto xi:X)sum += xi * xi / 4000;
double tem = 1;
//此处注意公式里的i从1开始,我们是0基的
for(int i = 0;i < X.size(); i ++)tem *= cos(X[i] / sqrt(i + 1));
sum -= tem;
return sum;
}
double func2(vector<double>&X)
{
double sum = 20;
for(int i = 0;i < X.size(); i ++)
{
sum += X[i]*X[i] - 10*cos(M_PI*2*X[i]);
}
return sum;
}
void iterate(vector<vector<double>>&p_x, vector<vector<double>>&p_v)
{
//特殊初始化social_best
for(int i = 0; i < p_size; i ++)
{
if (func(p_x[i]) < func(social_best_position))social_best_position = p_x[i];
if (func(p_x[i]) < func(per_best_position[i]))per_best_position[i] = p_x[i];
}
std::random_device rd;
std::default_random_engine engine(rd());
std::uniform_real_distribution<>weight1_rand(0,self_scale);
std::uniform_real_distribution<>weight2_rand(0,social_scale);
for(int i = 0;i < p_size - 1; i ++)
{
for(int j = 0; j < demension; j ++)
{
//更新pi的速度
if (it_times > 0)
{
p_v[i][j] = p_v[i][j]*alpha + dv1*weight1_rand(engine)*(per_best_position[i][j] - p_x[i][j])
+ dv2*weight2_rand(engine)*(social_best_position[j] - p_x[i][j]);
}
else
{
p_v[i][j] = p_v[i][j]*alpha + dv1*weight1_rand(engine)*p_x[i][j]
+ dv2*weight2_rand(engine)*(social_best_position[j] - p_x[i][j]);
}
if (p_v[i][j] < vmin)p_v[i][j] = vmin;
if (p_v[i][j] > vmax)p_v[i][j] = vmax;
//更新X的位置
if (p_x[i][j] + p_v[i][j] < Area_l)
{
p_x[i][j] = Area_l;
p_v[i][j] *= -1;
}
else if (p_x[i][j] + p_v[i][j] > Area_r)
{
p_x[i][j] = Area_r;
p_v[i][j] *= -1;
}
else p_x[i][j] = p_x[i][j] + p_v[i][j];
}
}
}
int main()
{
//def the particle set
vector<vector<double>>p_set(p_size);
//def the speed vector of each particle the speed should be the same demension with X
vector<vector<double>>pv_set(p_size);
//target is to minimize the func value
//初始化粒子初始位置和初始速度
std::random_device rd;
std::default_random_engine eng(rd());
std::uniform_real_distribution<>x_dis(-10,10);
std::uniform_real_distribution<>v_dis(vmin,vmax);
for(int i = 0; i < p_size; i ++)
{
for(int j = 0; j < demension; j ++)
{
p_set[i].push_back(x_dis(eng));
}
}
for(int i = 0; i < p_size; i ++)
{
for(int j = 0; j < demension; j ++)
{
pv_set[i].push_back(v_dis(eng));
}
}
//初始化social_best
social_best_position = p_set[0];
//初始化per_best
for(int i = 0; i < p_size; i ++)
{
per_best_position[i] = p_set[i];
}
// cout << "\n";
for(it_times = 0; it_times < it_max; it_times ++)
{
iterate(p_set, pv_set);
if (it_times%5 == 0)cout << "now best is x:" << social_best_position[0] << " y: " << social_best_position[1] << "\n";
if (it_times%5 == 0)cout << "the func value is " << func(social_best_position) << "\nthe " << it_times << " epoch\n";
}
cout << "the best position is:\n";
for(auto i:social_best_position)cout << i << " ";
cout << "\nthe least function value is " << func(social_best_position) << '\n';
return 0;
}
实验结果
由代码运行结果:
func1的最优位置在:,此处的函数值(全局最小值)为:
func2的最优位置在:,此处的函数值(全局最小值)为: