AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 应用
  • 更多
    • 题解
    • 分享
    • 商店
    • 问答
    • 吐槽
  • App
  • 登录/注册

PSO的C++算法实现

作者: 作者的头像   Daysgone ,  2023-03-19 19:43:37 ,  所有人可见 ,  阅读 45


0


实验目的

实现并实验掌握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的最优位置在:,此处的函数值(全局最小值)为:

0 评论

你确定删除吗?
1024
x

© 2018-2023 AcWing 版权所有  |  京ICP备17053197号-1
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标
请输入绑定的邮箱地址
请输入注册信息