最优化算法之粒子群算法(PSO)

最优化算法之粒子群算法(PSO)一、粒子群算法的概念  粒子群优化算法(PSO:Particleswarmoptimization)是一种进化计算技术(evolutionarycomputation)。源于对鸟群捕食的行为研究。粒子群优化算法的基本思想:是通过群体中个体之间的协作和信息共享来寻找最优解.  PSO的优势:在于简单容易实现并且没有许多参数的调节。目前已被广泛应用于函数优化、神经网络训练、模糊系统控制…

大家好,又见面了,我是你们的朋友全栈君。

一、粒子群算法的概念

  粒子群优化算法(PSO:Particle swarm optimization) 是一种进化计算技术(evolutionary computation)。源于对鸟群捕食的行为研究。粒子群优化算法的基本思想:是通过群体中个体之间的协作和信息共享来寻找最优解.
  PSO的优势:在于简单容易实现并且没有许多参数的调节。目前已被广泛应用于函数优化、神经网络训练、模糊系统控制以及其他遗传算法的应用领域。

二、粒子群算法分析

1、基本思想

  粒子群算法通过设计一种无质量的粒子来模拟鸟群中的鸟,粒子仅具有两个属性:速度和位置,速度代表移动的快慢,位置代表移动的方向。每个粒子在搜索空间中单独的搜寻最优解,并将其记为当前个体极值,并将个体极值与整个粒子群里的其他粒子共享,找到最优的那个个体极值作为整个粒子群的当前全局最优解,粒子群中的所有粒子根据自己找到的当前个体极值和整个粒子群共享的当前全局最优解来调整自己的速度和位置。下面的动图很形象地展示了PSO算法的过程:
这里写图片描述

2、更新规则

  PSO初始化为一群随机粒子(随机解)。然后通过迭代找到最优解。在每一次的迭代中,粒子通过跟踪两个“极值”(pbest,gbest)来更新自己。在找到这两个最优值后,粒子通过下面的公式来更新自己的速度和位置。
这里写图片描述
公式(1)的第一部分称为【记忆项】,表示上次速度大小和方向的影响;公式(1)的第二部分称为【自身认知项】,是从当前点指向粒子自身最好点的一个矢量,表示粒子的动作来源于自己经验的部分;公式(1)的第三部分称为【群体认知项】,是一个从当前点指向种群最好点的矢量,反映了粒子间的协同合作和知识共享。粒子就是通过自己的经验和同伴中最好的经验来决定下一步的运动。以上面两个公式为基础,形成了PSO的标准形式
这里写图片描述
公式(2)和 公式(3)被视为标准PSO算法

3、PSO算法的流程和伪代码

这里写图片描述

4、PSO算法举例

这里写图片描述
这里写图片描述

5、PSO算法的demo

#include <iostream>
#include <vector>
#include <cmath>
#include <map>
#include <algorithm>
#include <random>
#include <ctime>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;

const int dim = 1;//维数
const int p_num = 10;//粒子数量
const int iters = 100;//迭代次数
const int inf = 999999;//极大值
const double pi = 3.1415;
//定义粒子的位置和速度的范围
const double v_max = 4;
const double v_min = -2;
const double pos_max = 2;
const double pos_min = -1;
//定义位置向量和速度向量
vector<double> pos;
vector<double> spd;
//定义粒子的历史最优位置和全局最优位置
vector<double> p_best;
double g_best;
//使用eigen库定义函数值矩阵和位置矩阵
Matrix<double, iters, p_num> f_test;
Matrix<double, iters, p_num> pos_mat;

//定义适应度函数
double fun_test(double x)
{
    double res = x * x + 1;
    return res;
}

//初始化粒子群的位置和速度
void init()
{
    //矩阵中所有元素初始化为极大值
    f_test.fill(inf);
    pos_mat.fill(inf);
    //生成范围随机数
    static std::mt19937 rng;
    static std::uniform_real_distribution<double> distribution1(-1, 2);
    static std::uniform_real_distribution<double> distribution2(-2, 4);
    for (int i = 0; i < p_num; ++i)
    {
        pos.push_back(distribution1(rng));
        spd.push_back(distribution2(rng));
    }
    vector<double> vec;
    for (int i = 0; i < p_num; ++i)
    {
        auto temp = fun_test(pos[i]);//计算函数值
        //初始化函数值矩阵和位置矩阵
        f_test(0, i) = temp;
        pos_mat(0, i) = pos[i];
        p_best.push_back(pos[i]);//初始化粒子的历史最优位置
    }
    std::ptrdiff_t minRow, minCol;
    f_test.row(0).minCoeff(&minRow, &minCol);//返回函数值矩阵第一行中极小值对应的位置
    g_best = pos_mat(minRow, minCol);//初始化全局最优位置
}

void PSO()
{
    static std::mt19937 rng;
    static std::uniform_real_distribution<double> distribution(0, 1);
    for (int step = 1; step < iters; ++step)
    {
        for (int i = 0; i < p_num; ++i)
        {
            //更新速度向量和位置向量
            spd[i] = 0.5 * spd[i] + 2 * distribution(rng) * (p_best[i] - pos[i]) +
                2 * distribution(rng) * (g_best - pos[i]);
            pos[i] = pos[i] + spd[i];
            //如果越界则取边界值
            if (spd[i] < -2 || spd[i] > 4)
                spd[i] = 4;
            if (pos[i] < -1 || pos[i] > 2)
                pos[i] = -1;
            //更新位置矩阵
            pos_mat(step, i) = pos[i];
        }
        //更新函数值矩阵
        for (int i = 0; i < p_num; ++i)
        {
            auto temp = fun_test(pos[i]);
            f_test(step, i) = temp;
        }
        for (int i = 0; i < p_num; ++i)
        {
            MatrixXd temp_test;
            temp_test = f_test.col(i);//取函数值矩阵的每一列
            std::ptrdiff_t minRow, minCol;
            temp_test.minCoeff(&minRow, &minCol);//获取每一列的极小值对应的位置
            p_best[i] = pos_mat(minRow, i);//获取每一列的极小值,即每个粒子的历史最优位置
        }
        g_best = *min_element(p_best.begin(), p_best.end());//获取全局最优位置
    }
    cout << fun_test(g_best);
}

int main()
{
    init();
    PSO();
    system("pause");
    return 0;
}

参考:https://blog.csdn.net/myarrow/article/details/51507671
https://blog.csdn.net/google19890102/article/details/30044945
https://wenku.baidu.com/view/65c600b9294ac850ad02de80d4d8d15abe230048.html
https://blog.csdn.net/darin1997/article/details/80675933

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/132684.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • MongoDb的ConnectionString链接字符串解析

    MongoDb的ConnectionString链接字符串解析MongoDb的ConnectionString链接字符串解析,如下图所示。

  • Eclipse最新最简最详细安装教程

    Eclipse最新最简最详细安装教程1、首先打开官方地址(见下面)Eclipse官方下载地址:点击打开官方链接2、点击红箭头指向的红框中的“DownloadPackages”。3、出现新的页面之后往下翻找到并点击红箭头指向的红色矩形的部分EclipseIDEforJavaEEDevelopers项的最右边,点击“64-bit”。4、进入到新的页面之后点击红色箭头指向…

  • TDD与FDD技术对比

    TDD与FDD技术对比双工(Duplex)是一种在单一通信信道上实现双向通信的过程,包括两种类型,分别为半双工和全双工。  在半双工系统中,通信双方使用单一的共享信道轮流发送数据。双向广播就采用了这种方式。在一方发送数据时,另一方只能收听。数据发送方通常会发出“Over”的信号,表明本方数据发送结束,对方可以开始发送数据。在实际网络中,两台计算机可以使用一根通信电缆来轮流收发数据。  全双工则是指同时的双向通信

  • CentOS 7 安装 LNMP 环境(PHP7 + MySQL5.7 + Nginx1.10)

    CentOS 7 安装 LNMP 环境(PHP7 + MySQL5.7 + Nginx1.10)

    2021年10月18日
  • matlab画图常用符号,matlab画图特殊符号[通俗易懂]

    matlab画图常用符号,matlab画图特殊符号[通俗易懂]在MATLAB中使用LaTex字符1.Tex字符表在text对象的函数中(函数title、xlabel、ylabel、zlabel或text),说明文字除使用标准的ASCII字符外,还可……matlab特殊字符_工学_高等教育_教育专区。本文说明了matlab中如何输入特殊字符,如希腊字母字符映射表C:\\WINDOWS\\system32\\charmap….

  • 俞敏洪与新东方_新东方俞敏洪现状

    俞敏洪与新东方_新东方俞敏洪现状俞敏洪与新东方“江阴模式”助俞敏洪考上北大  俞敏洪,1962年出生于江苏省江阴。  俞敏洪出生在一个普通的农村家庭里,父亲是一名木匠,母亲则是当地生产队的妇女队长,她有与这一职位对应果敢的作风。俞敏洪还有一个姐姐,是一名赤脚医生。作为一个农家孩子,俞敏洪回忆:我从小就在农田里干活,插秧、割稻、撒猪粪,样样都干……  母亲希望他的人生能有某种意义上的改变,希望…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号