2023亚太杯数学建模思路 - 案例:粒子群算法

文章目录

  • 1 什么是粒子群算法?
  • 2 举个例子
  • 3 还是一个例子
  • 算法流程
  • 算法实现
  • 建模资料

# 0 赛题思路

(赛题出来以后第一时间在CSDN分享)

https://blog.csdn.net/dc_sinor?type=blog

1 什么是粒子群算法?

粒子群算法(Particle Swarm Optimization,PSO)是一种模仿鸟群、鱼群觅食行为发展起来的一种进化算法。其概念简单易于编程实现且运行效率高、参数相对较少,应用非常广泛。粒子群算法于1995年提出,距今(2019)已有24年历史。
  
  粒子群算法中每一个粒子的位置代表了待求问题的一个候选解。每一个粒子的位置在空间内的好坏由该粒子的位置在待求问题中的适应度值决定。每一个粒子在下一代的位置有其在这一代的位置与其自身的速度矢量决定,其速度决定了粒子每次飞行的方向和距离。在飞行过程中,粒子会记录下自己所到过的最优位置 P,群体也会更新群体所到过的最优位置G 。粒子的飞行速度则由其当前位置、粒子自身所到过的最优位置、群体所到过的最优位置以及粒子此时的速度共同决定。

在这里插入图片描述

2 举个例子

在这里插入图片描述
在一个湖中有两个人他们之间可以通信,并且可以探测到自己所在位置的最低点。初始位置如上图所示,由于右边比较深,因此左边的人会往右边移动一下小船。

在这里插入图片描述

现在左边比较深,因此右边的人会往左边移动一下小船

一直重复该过程,最后两个小船会相遇

在这里插入图片描述
得到一个局部的最优解
在这里插入图片描述将每个个体表示为粒子。每个个体在某一时刻的位置表示为,x(t),方向表示为v(t)

在这里插入图片描述

p(t)为在t时刻x个体的自己的最优解,g(t)为在t时刻所有个体的最优解,v(t)为个体在t时刻的方向,x(t)为个体在t时刻的位置

在这里插入图片描述

下一个位置为上图所示由x,p,g共同决定了

在这里插入图片描述

种群中的粒子通过不断地向自身和种群的历史信息进行学习,从而可以找到问题的最优解。

3 还是一个例子

粒子群算法是根据鸟群觅食行为衍生出的算法。现在,我们的主角换成是一群鸟。
在这里插入图片描述

小鸟们的目标很简单,要在这一带找到食物最充足的位置安家、休养生息。它们在这个地方的搜索策略如下:
  1. 每只鸟随机找一个地方,评估这个地方的食物量。
  2. 所有的鸟一起开会,选出食物量最多的地方作为安家的候选点G。
  3. 每只鸟回顾自己的旅程,记住自己曾经去过的食物量最多的地方P。
  4. 每只鸟为了找到食物量更多的地方,于是向着G飞行,但是呢,不知是出于选择困难症还是对P的留恋,或者是对G的不信任,小鸟向G飞行时,时不时也向P飞行,其实它自己也不知道到底是向G飞行的多还是向P飞行的多。
  5. 又到了开会的时间,如果小鸟们决定停止寻找,那么它们会选择当前的G来安家;否则继续2->3->4->5来寻找它们的栖息地。

在这里插入图片描述

上图描述的策略4的情况,一只鸟在点A处,点G是鸟群们找到过的食物最多的位置,点P是它自己去过的食物最多的地点。V是它现在的飞行速度(速度是矢量,有方向和大小),现在它决定向着P和G飞行,但是这是一只佛系鸟,具体飞多少随缘。如果没有速度V,它应该飞到B点,有了速度V的影响,它的合速度最终使它飞到了点C,这里是它的下一个目的地。如果C比P好那么C就成了下一次的P,如果C比G好,那么就成了下一次的G。

算法流程

在这里插入图片描述

算法实现

这里学长用python来给大家演示使用粒子群解函数最优解

在这里插入图片描述

import numpy as np
import matplotlib.pyplot as plt
import random


# 定义“粒子”类
class parti(object):
    def __init__(self, v, x):
        self.v = v                    # 粒子当前速度
        self.x = x                    # 粒子当前位置
        self.pbest = x                # 粒子历史最优位置

class PSO(object):
    def __init__(self, interval, tab='min', partisNum=10, iterMax=1000, w=1, c1=2, c2=2):
        self.interval = interval                                            # 给定状态空间 - 即待求解空间
        self.tab = tab.strip()                                              # 求解最大值还是最小值的标签: 'min' - 最小值;'max' - 最大值
        self.iterMax = iterMax                                              # 迭代求解次数
        self.w = w                                                          # 惯性因子
        self.c1, self.c2 = c1, c2                                           # 学习因子
        self.v_max = (interval[1] - interval[0]) * 0.1                      # 设置最大迁移速度
        #####################################################################
        self.partis_list, self.gbest = self.initPartis(partisNum)                 # 完成粒子群的初始化,并提取群体历史最优位置
        self.x_seeds = np.array(list(parti_.x for parti_ in self.partis_list))    # 提取粒子群的种子状态 ###
        self.solve()                                                              # 完成主体的求解过程
        self.display()                                                            # 数据可视化展示

    def initPartis(self, partisNum):
        partis_list = list()
        for i in range(partisNum):
            v_seed = random.uniform(-self.v_max, self.v_max)
            x_seed = random.uniform(*self.interval)
            partis_list.append(parti(v_seed, x_seed))
        temp = 'find_' + self.tab
        if hasattr(self, temp):                                             # 采用反射方法提取对应的函数
            gbest = getattr(self, temp)(partis_list)
        else:
            exit('>>>tab标签传参有误:"min"|"max"<<<')
        return partis_list, gbest

    def solve(self):
        for i in range(self.iterMax):
            for parti_c in self.partis_list:
                f1 = self.func(parti_c.x)
                # 更新粒子速度,并限制在最大迁移速度之内
                parti_c.v = self.w * parti_c.v + self.c1 * random.random() * (parti_c.pbest - parti_c.x) + self.c2 * random.random() * (self.gbest - parti_c.x)
                if parti_c.v > self.v_max: parti_c.v = self.v_max
                elif parti_c.v < -self.v_max: parti_c.v = -self.v_max
                # 更新粒子位置,并限制在待解空间之内
                if self.interval[0] <= parti_c.x + parti_c.v <=self.interval[1]:
                    parti_c.x = parti_c.x + parti_c.v
                else:
                    parti_c.x = parti_c.x - parti_c.v
                f2 = self.func(parti_c.x)
                getattr(self, 'deal_'+self.tab)(f1, f2, parti_c)             # 更新粒子历史最优位置与群体历史最优位置

    def func(self, x):                                                       # 状态产生函数 - 即待求解函数
        value = np.sin(x**2) * (x**2 - 5*x)
        return value

    def find_min(self, partis_list):                                         # 按状态函数最小值找到粒子群初始化的历史最优位置
        parti = min(partis_list, key=lambda parti: self.func(parti.pbest))
        return parti.pbest

    def find_max(self, partis_list):
        parti = max(partis_list, key=lambda parti: self.func(parti.pbest))   # 按状态函数最大值找到粒子群初始化的历史最优位置
        return parti.pbest

    def deal_min(self, f1, f2, parti_):
        if f2 < f1:                          # 更新粒子历史最优位置
            parti_.pbest = parti_.x
        if f2 < self.func(self.gbest):
            self.gbest = parti_.x            # 更新群体历史最优位置

    def deal_max(self, f1, f2, parti_):
        if f2 > f1:                          # 更新粒子历史最优位置
            parti_.pbest = parti_.x
        if f2 > self.func(self.gbest):
            self.gbest = parti_.x            # 更新群体历史最优位置

    def display(self):
        print('solution: {}'.format(self.gbest))
        plt.figure(figsize=(8, 4))
        x = np.linspace(self.interval[0], self.interval[1], 300)
        y = self.func(x)
        plt.plot(x, y, 'g-', label='function')
        plt.plot(self.x_seeds, self.func(self.x_seeds), 'b.', label='seeds')
        plt.plot(self.gbest, self.func(self.gbest), 'r*', label='solution')
        plt.xlabel('x')
        plt.ylabel('f(x)')
        plt.title('solution = {}'.format(self.gbest))
        plt.legend()
        plt.savefig('PSO.png', dpi=500)
        plt.show()
        plt.close()


if __name__ == '__main__':
    PSO([-9, 5], 'max')

效果
在这里插入图片描述

建模资料

资料分享: 最强建模资料
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/177712.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

被Linux之父称其为艺术品的WireGuard

简介 WireGuard 是一种极其简单但快速且现代的 VPN&#xff0c;它利用了最先进的加密技术。它的目标是比 IPsec 更快、更简单、更精简和更有用&#xff0c;同时避免令人头疼的问题。旨在提供比 OpenVPN 更高的性能。WireGuard 被设计为在嵌入式接口和超级计算机等上运行的通用 …

哈夫曼树你需要了解一下

哈夫曼树介绍哈夫曼数特点哈夫曼应用场景哈夫曼构建过程哈夫曼树示例拓展 哈夫曼树介绍 哈夫曼树&#xff08;Huffman Tree&#xff09;是一种特殊的二叉树&#xff0c;也被称为最优二叉树。在计算机科学中&#xff0c;它是由权值作为叶子节点构造出来的一种二叉树。哈夫曼树的…

【UE】用样条线实现测距功能(上)

目录 效果 步骤 一、创建样条网格体组件3D模型 二、实现点击连线功能 三、实现显示两点间距离功能 效果 步骤 一、创建样条网格体组件3D模型 创建一个圆柱模型&#xff0c;这里底面半径设置为10mm&#xff0c;高度设置为1000mm 注意该模型的坐标轴在如下位置&#xff1…

集团投融资大数据平台解决方案

一、项目背景 项目为集团型公司大数据平台项目&#xff0c;整个项目周期约为6个月&#xff0c;整体呈现了对外的数据大屏驾驶仓和对内的看板报表&#xff0c;减少了客户内部数据上报和报表制作的重复工作量&#xff0c;为集团数据决策奠定基础。 二、项目目标 战略层&#xff…

c++ std::variant用法

std::variant Union类型的问题&#xff1a; 无法知道当前使用的类型是什么union无法自动调用底层数据成员的析构函数。联合体无法对其内部的数据属性的生命周期的全面支持&#xff0c;因为当外部代码调用Union时在切换类型&#xff0c;它无法做到对当前使用的对象&#xff0c…

Java(五)(Object类,克隆,Objects类,包装类,StringBuilder,StringJoiner,BigDecimal)

目录 Object类 Object类的常见方法: 克隆 浅克隆 深克隆 Objects类 包装类 StringBuilder StringJoiner BigDecimal Object类 Object类是java中的祖宗类,因此,Java中所有的类的对象都可以直接使用object类提供的一些方法 Object类的常见方法: public String toStrin…

【黑马甄选离线数仓day01_项目介绍与环境准备】

1. 行业背景 1.1 电商发展历史 电商1.0: 初创阶段20世纪90年代&#xff0c;电商行业刚刚兴起&#xff0c;主要以B2C模式为主&#xff0c;如亚马逊、eBay等 ​ 电商2.0: 发展阶段21世纪初&#xff0c;电商行业进入了快速发展阶段&#xff0c;出现了淘宝、京东等大型电商平台&a…

Halcon Solution Guide I basics(3): Region Of Interest(有兴趣区域/找重点)

文章目录 文章专栏前言文章解读前言创建ROI案例1&#xff1a;直接截取ROI手动截取ROI 总结ROI套路获取窗口句柄截取ROI区域获取有效区域 Stop组合 文章专栏 Halcon开发 Halcon学习 练习项目gitee仓库 CSDN Major 博主Halcon文章推荐 前言 今天来看第三章内容&#xff0c;既然是…

忘记7-zip密码,如何解压文件?

7z压缩包设置了密码&#xff0c;解压的时候就需要输入正确对密码才能顺利解压出文件&#xff0c;正常当我们解压文件或者删除密码的时候&#xff0c;虽然方法多&#xff0c;但是都需要输入正确的密码才能完成。忘记密码就无法进行操作。 那么&#xff0c;忘记了7z压缩包的密码…

代码规范之-理解ESLint、Prettier、EditorConfig

前言 团队多人协同开发项目&#xff0c;困扰团队管理的一个很大的问题就是&#xff1a;无可避免地会出现每个开发者编码习惯不同、代码风格迥异&#xff0c;为了代码高可用、可维护性&#xff0c;需要从项目管理上尽量统一和规范代码。理想的方式需要在项目工程化方面&#xff…

力扣:175. 组合两个表(Python3)

题目&#xff1a; 表: Person ---------------------- | 列名 | 类型 | ---------------------- | PersonId | int | | FirstName | varchar | | LastName | varchar | ---------------------- personId 是该表的主键&#xff08;具有唯一值的列&#…

设计循环队列,解决假溢出问题

什么是假溢出&#xff1f; 当我们使用队列这种基本的数据结构时&#xff0c;很容易发现&#xff0c;随着入队和出队操作的不断进行&#xff0c;队列的数据区域不断地偏向队尾方向移动。当我们的队尾指针指向了队列之外的区域时&#xff0c;我们就不能再进行入队操作了&#xff…

【shell】循环语句(for、while、until)

目录 一、循环语句的特点 二、三种常用的循环 2.1 for循环 2.2 while循环 2.3 until循环 2.4 死循环 2.5 关于continue和break以及exit 三、实操案例 3.1 累加1到100&#xff08;5种办法&#xff0c;穿插多种运算习惯&#xff09; 3.2 批量修改文件名称 3.3 pi…

yapi==使用依赖包里的类作为入参/返回值导出后没有备注

比如模块A中有个MyDemoEntity类,在B中以依赖的形式引入了A,并在B的接口中以MyDemoEntity作为返回值,导出到YAPI发现MyDemoEntity的备注没了。 解决: 将A的内容安装到本地MAVEN仓库,并且需要将源码也一起安装 <build><resources><resource><director…

记录--手写一个 v-tooltip 指令

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 前言 日常开发中&#xff0c;我们经常遇到过tooltip这种需求。文字溢出、产品文案、描述说明等等&#xff0c;每次都需要写一大串代码&#xff0c;那么有没有一种简单的方式呢&#xff0c;这回我们用指…

第一百七十六回 如何创建渐变色边角

文章目录 1. 概念介绍2. 实现方法3. 代码与细节3.1 示例代码3.2 代码细节 4. 内容总结 我们在上一章回中介绍了"如何创建放射形状渐变背景"相关的内容&#xff0c;本章回中将介绍"如何创建渐变色边角".闲话休提&#xff0c;让我们一起Talk Flutter吧。 1.…

Axios使用方式

ajax是JQUERY封装的XMLHttprequest用来发送http请求 Axios简单点说它就是一个js库,支持ajax请求,发送axios请求功能更加丰富,丰富在哪不知道 1.npm使用方式 vue项目中 npm install axios 2.cdn方式 <script src"https://unpkg.com/axios/dist/axios.min.js">…

行情分析——加密货币市场大盘走势(11.22)

大饼昨日晚上打了止损&#xff0c;笔者入场了空单&#xff0c;目前来看上涨乏力&#xff0c;下跌是必然的&#xff0c;昨日的下跌跌破了蓝色上涨趋势线&#xff0c;而今日白天开始反弹&#xff0c;别着急抄底&#xff0c;下跌还没有结束。 空单策略&#xff1a;入场36500 止盈…

为UE和Unity开发者准备的Godot指南

为UE和Unity开发者准备的Godot指南 ——两位大哥打架&#xff0c;请带上我 这两天游戏行业又开始热闹了&#xff0c;昨天两条信息直接刷爆朋友圈&#xff0c;最大的两家游戏引擎公司怼起来了。 《为Unity开发者准备的虚幻引擎指南》&#xff1a; 为Unity开发者准备的虚幻引擎指…

Autocad2020切换经典界面

Autocad2020切换经典界面 1.更改1.1设置另存为 1.更改 1.1设置另存为