2023年华数杯建模思路 - 案例:粒子群算法

news2024/11/25 14:52:30

# 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')

效果
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于元宇宙与 Web3 的虚拟世界:客户体验的颠覆与重生

随着科技的飞速发展&#xff0c;互联网已经逐渐融入了我们生活的方方面面。然而&#xff0c;传统的互联网体验在很多方面仍然存在局限性。客户需要花费大量时间和精力去实体店购买商品、在电商平台上筛选商品&#xff0c;或者在固定的时间和地点接受教育。这些问题在元宇宙与 W…

PHP最简单自定义自己的框架(一)

为啥要定义自己的框架&#xff1a; 定制化需求&#xff1a;每个项目都有不同的需求和特点&#xff0c;使用通用的框架可能无法满足所有的要求。自定义框架可以根据具体需求进行定制&#xff0c;提供更加灵活和符合项目需求的解决方案。学习和成长&#xff1a;自定义框架是一个很…

EasyRecovery15简体中文专业版电脑数据恢复软件

除常规数据恢复外&#xff0c;更有高级工具&#xff0c;恢复更多、更专业。Ontrack EasyRecovery 15是一款功能强大的硬盘数据恢复软件&#xff0c;支持恢复所有文件、文件夹、文档和其它有用数据&#xff0c;也支持恢复word、Excel、PPT文件办公文档&#xff0c;所有文件夹里的…

宋浩高等数学笔记(九)多元函数微分学及其应用

本章内容和知识点很多&#xff0c;有关多元微分学应用的部分&#xff1a;比如方向导数梯度&#xff0c;暂时不发布笔记&#xff0c;日后更新后会补齐。

精品桌游流量主微信小程序源码

在开发工具测试了下&#xff0c;能搭建出来&#xff0c;功能在7/25测试时正常使用 UI非常漂亮。看着也比较舒服&#xff0c;游戏重要有 1.谁是卧底 2.真心话大冒险

Android - 常见内存泄露问题盘点

1、内存泄漏的本质 内存泄漏的本质就是对象引用未释放&#xff0c;当对象被创建时&#xff0c;如果没有被正确释放&#xff0c;那么这些对象就会一直占用内存&#xff0c;直到应用程序退出。例如&#xff0c;当一个Activity被销毁时&#xff0c;如果它还持有其他对象的引用&am…

一张图像相当于 16×16 个单词:用于大规模图像识别的 Transformers(视觉 Transformers)

一张图片值多少字? 一张图片胜过千言万语?无法用言语完整地描述一幅图画。但论文告诉我们一张图像相当于 1616 个单词。在这篇博客中,我将解释使用 Transformer 进行图像识别。这是一篇非常有趣的论文, 这篇论文有什么特别之处? 它很特别,因为这里我们不会使用任何卷积网…

ctfshow----php特性

目录 web89 preg_match函数 、数组 web90 intval()函数、强比较 web91 正则修饰符 web92 intval()函数、弱比较 web93 八进制、小数点 web94 strpos() 函数、小数点 web95 小数点 web96 highlight_file() 下的目录路径 web97 数组 web98 三目运算符 web9…

LeetCode·每日一题·822. 翻转卡片游戏·哈希

作者&#xff1a;小迅 链接&#xff1a;https://leetcode.cn/problems/card-flipping-game/solutions/2368969/ha-xi-zhu-shi-chao-ji-xiang-xi-by-xun-ge-7ivj/ 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 著作权归作者所有。商业转载请联系作者获得授权&#xff…

【Redis】内存数据库Redis进阶(Redis哨兵集群)

目录 分布式缓存 Redis 四大问题搭建Redis哨兵集群哨兵原理Redis哨兵集群小结RedisTemplate集成哨兵机制 分布式缓存 Redis 四大问题 基于 Redis 集群解决单机 Redis 存在的四大问题&#xff1a; 搭建Redis哨兵集群 搭建一个三节点形成的 Sentinel 集群&#xff0c;来监管 R…

【数据结构与算法】二叉树

二叉树 二叉树的概念 树有很多种&#xff0c;每个节点最多只能有两个子节点的一种形式称为二叉树。二叉树的子节点分为左节点和右节点。 如果该二叉树的所有叶子节点都在最后一层&#xff0c;并且节点总数 2^n - 1&#xff0c;n 为层数&#xff0c;则我们称为满二叉树。如果…

python格式化地址信息

背景 最近在折腾一个好玩的库&#xff0c;capa 实现地址的格式化输出。我看的教程是这样的&#xff1a; location_str ["徐汇区虹漕路461号58号楼5楼", "泉州市洛江区万安塘西工业区"] import cpca df cpca.transform(location_str) df在正式的运行代码…

SI24R2H 2.4G+125K中长跑应用原理

一、中长跑计时系统应用背景 采用125KHZ低频唤醒高频射频识别系统和先进的技术、计算机信息处理等高新技术与体育竞赛相结合&#xff0c;便于运动员携带而不影响其跑步状态&#xff0c;当运 动员带着射频识别卡经过计时线圈时&#xff0c;读卡天线能够立即检测到通过的卡片信息…

Maven【入门笔记】

Maven 解决版本依赖的问题 https://www.liaoxuefeng.com/wiki/1252599548343744/1309301146648610 如果没有项目管理工具&#xff0c;在开发项目的时候&#xff0c;我们需要手动管理依赖包&#xff0c;需要管理依赖包的版本、去找到并下载依赖包、还有依赖包所依赖的包 等等。…

解决微服务调用 file文件传递出现的 Current request is not a multipart request 问题

在单体服务中通过使用RequestParam(“file”) MultipartFile multipartFile方式接收文件是没有问题的 多服务传递,如端层到服务层,上述方式就会出现Current request is not a multipart request问题 解决Current request is not a multipart request问题的步骤 将 RequestPar…

Java虚拟机在类加载阶段都做了些什么,才使得我们可以运行Java程序

前言&#xff1a; 今天和大家探讨一道Java中经典的面试题&#xff0c;这道面试题经常出现在各个公司的面试中&#xff0c;结合周志明&#xff0c;老师的《深入理解Java虚拟机》书籍&#xff0c;本篇文章主要讲解Java类加载机制的知识。该专栏比较适合刚入坑Java的小白以及准备秋…

一起学算法(栈篇)

1.栈的概念 1.栈的定义 栈是仅限在表尾进行插入和删除的线性表&#xff0c;栈又被称为先进后出的线性表&#xff0c;简称“LIFO” 我们这次用数组作为我们栈的底层数据结构&#xff0c;代码会放到结尾供大家参考使用 2.栈顶的定义 栈是一个线性表&#xff0c;我们允许插入…

I-STARIS国际演艺集团五洲女子组合练习生2023年度考核开启

I-STARIS国际演艺集团五洲女子组合举行了年度考核&#xff0c;从演员的形象管理、表演技巧、才艺水平及中文语言功底等多方面维度来评定。他们非常认真对待&#xff0c;通过不断的努力学习持续提升自己。 作为一年一度的年度考核&#xff0c;大家都非常紧张&#xff0c;除了专业…

tomcat限制IP访问

tomcat可以通过增加配置&#xff0c;来对来源ip进行限制&#xff0c;即只允许某些ip访问或禁止某些来源ip访问。 配置路径&#xff1a;server.xml 文件下 标签下。与同级 <Valve className"org.apache.catalina.valves.RemoteAddrValve" allow"192.168.x.x&…