python 实现蚁群算法(simpy带绘图)

这里使用了蚁群算法求解了旅行商问题,同时结合了simpy来绘图

选择下一个食物的函数为:

probability[i] = pheromone[self.now][self.not_to_foods[i]] ** pheromone_w + (1 / distance[self.now][self.not_to_foods[i]]) ** distance_w

该条路概率权重=该点信息素^信息素权重*(1/路径长)^路径权重/总和,这里后面会用random.choices就不用除了

信息素更新为:

new_pheromone[self.route[i]][self.route[i + 1]] += pheromone_Q / self.sum_len
pheromone = np.add((1 - volatilize) * pheromone, new_pheromone)

总信息素会挥发volatilize比例,然后所有蚂蚁路径每一段加上固定释放的信息量/路径总长度

话不多说,都在代码注释里了

import random
import simpy
import matplotlib.pyplot as plt
import numpy as np# 在这里我们尝试用蚁群算法求解旅行商问题,简而言之,就是寻找一条链接所有点的最短路径最后要回到初始点
# 我想绘制一下每只蚂蚁的行走过程,所以使用上次的simpy包来模拟一下,
# 这个simpy包主要是为了更好的可视化模拟训练过程,你也可以给每只蚂蚁单独线程代替,
# 或者干脆不用管过程,只用一轮一轮的上蚂蚁,在信息素部分做点处理,光看结果也可以。总之大多要比simpy快class Ant(object):  # 蚂蚁类# 说一下训练过程,有很多只蚂蚁,从随机位置出发,# 每次遵从信息素的指引,选择下一个城市,直到没有可选城市,回到初始位置然后根据路径总长度在路径上散播信息素def __init__(self):  # 蚂蚁构造函数# 一只蚂蚁,只需要保存走过的食物就可以,# 这里我们为了以后整信息素时不用遍历,顺便保存一下走过的长度self.route = []  # 到达食物路径,一个例子是:[2,1,3,2]self.not_to_foods = []  # 未到达的食物点self.sum_len = 0  # 走过路径总长度self.now = 0  # 当前所在位置self.next_food = 0  # 下一个所在位置self.Initial_Position(random.randint(0,foods_n-1))  # 设定初始位置# 绘图参数self.now_position = [0, 0]  # 起始到终点的向量self.proportion = env.now  # 走的时间,画图就是找到起始食物点,然后加上(起始和终点的向量乘以(当前时间-出发时间)/路长)就是蚂蚁位置,def Initial_Position(self, n):  # 选择初始位置'self.now = n  # 当前所在的食物self.next_food = n  # 下一个要到的食物self.route = []self.not_to_foods = [i for i in range(foods_n)]  # 未到达的食物点self.sum_len = 0self.route.append(n)  # 添加到路径self.not_to_foods.remove(n)  # 初始点不会在未到的食物点def Set_Now(self, next_food):  # 到下一个点self.next_food = next_food  # 下一个要到的食物self.route.append(next_food)  # 添加到路径self.sum_len += distance[self.now][next_food]  # 总路径增加if next_food in self.not_to_foods:self.not_to_foods.remove(next_food)  # 移出未到的食物点self.now_position = foods[next_food] - foods[self.now]  # 走的方向self.proportion = env.now  # 出发时间def Next_Food(self):  # 根据信息素和路径寻找下一个食物len_not_to_foods = len(self.not_to_foods)  # 没选择的食物个数probability = np.zeros(len_not_to_foods)  # 选择食物的概率for i in range(len_not_to_foods):# 选一个路径的概率是该点信息素^信息素权重*(1/路径长)^路径权重/总和,这里后面会用random.choices就不用除了probability[i] = pheromone[self.now][self.not_to_foods[i]] ** pheromone_w + (1 / distance[self.now][self.not_to_foods[i]]) ** distance_wnext_food = random.choices(self.not_to_foods, probability)  # 根据权重选择下一个点return next_fooddef Change_Pheromone(self):  # 更新信息素矩阵,先添加到一个临时变量中,信息素矩每隔一段时间后自己会挥发并将这个变量添加进去。for i in range(foods_n):new_pheromone[self.route[i]][self.route[i + 1]] += pheromone_Q / self.sum_lennew_pheromone[self.route[i + 1]][self.route[i]] = new_pheromone[self.route[i]][self.route[i + 1]]def run(self):  # 蚂蚁出动global min_distance, min_routewhile True:while self.not_to_foods:  # 未空还能找食物next_food = self.Next_Food()[0]self.Set_Now(next_food)  # 根据信息素和路径去下一个食物位置yield env.timeout(distance[self.now][next_food])  # 等待到达终点self.now = next_food  # 到达位置# 没有食物可以去了next_food = self.route[0]self.Set_Now(next_food)  # 去初始点yield env.timeout(distance[self.now][next_food])  # 等待到达终点self.now = next_food  # 到达位置self.Change_Pheromone()  # 到了初始点之后,更新信息素if min_distance > self.sum_len:min_distance = self.sum_lenmin_route = self.routeself.Initial_Position(random.randint(0,foods_n-1))  # 重新初始化,再来一轮def Change_Pheromone(env):global pheromone, new_pheromonewhile True:# 每隔一段时间,挥发,更新信息素,# 我想要平均走完一波蚂蚁更新一波,那么,我大概需要等待平均总路长的时间(因为假设蚂蚁1m/s)这里就用(foods_n+1)/2,两点间平均距离大概是0.5yield env.timeout((foods_n + 1) / 2)pheromone = np.add((1 - volatilize) * pheromone, new_pheromone)new_pheromone = np.zeros((foods_n, foods_n))# 初始化函数,初始化蚁群,食物,信息素矩阵,
def Initialization(ants_n, foods_n, dimension):''':param ants_n:  蚁群大小:param foods_n: 食物数目:param dimension: 维度:return: 初始化蚁群,食物,信息素矩阵,距离矩阵'''ants = [Ant() for _ in range(ants_n)]  # 蚁群np.random.seed(0)  # 随机数种子,让生成的位置一致,你可以删去foods = np.random.rand(foods_n, dimension)  # 所有食物位置,支持高维,不过绘图只有二维(python三维图太卡了),只测试二维pheromone = np.zeros((foods_n, foods_n))+2  # 信息素矩阵初始为路径长度平均数的倒数之类的distance = np.zeros((foods_n, foods_n))  # 距离矩阵for i in range(foods_n):  # 计算欧氏距离for j in range(foods_n):if i > j:  # 以前算过了,抄过来distance[i][j] = distance[j][i]continueif i == j:  # 一样的位置就是0,不算了continuedistance[i][j] = np.sqrt(np.sum((foods[i] - foods[j]) ** 2))return ants, foods, pheromone, distancedef plt_Refresh():  # 绘图while True:plt.clf()  # 清屏plt.xlim(0, 1)plt.ylim(-0.1, 1)# 绘图plt.text(0.05, -0.05, "now_time = " + str(env.now))for i in range(foods_n):  # 所有的食物点for j in range(i):plt.plot([foods[i][0],foods[j][0]],[foods[i][1],foods[j][1]],linewidth=pheromone[i][j]/100)plt.scatter(foods[i][0], foods[i][1], 100)plt.text(foods[i][0], foods[i][1], i)for i in range(ants_n):  # 所有的蚂蚁点# 到起始食物点,然后加上(起始和终点的向量乘以(当前时间-出发时间)/路长)就是蚂蚁位置,if ants[i].now == ants[i].next_food:position = foods[ants[i].now]else:position = foods[ants[i].now] + ants[i].now_position * (env.now - ants[i].proportion) / \distance[ants[i].now][ants[i].next_food]plt.scatter(position[0], position[1])plt.text(position[0], position[1], i)# 刷新图形plt.draw()plt.pause(time_particles)yield env.timeout(time_particles)def Firing(env):  # env启动env.process(Change_Pheromone(env))  # 启动信息素矩阵env.process(plt_Refresh())  # 启动绘图for i in range(ants_n):  # 启动所有蚂蚁env.process(ants[i].run())ants_n = 15  # 蚂蚁数目,一般1.5*foods_n
foods_n = 10  # 食物数目
dimension = 2  # 维度,建议2,因为绘图只搞了2
min_distance = float("inf")  # 最小距离
min_route = []  # 最小路径
# 一些超参数
pheromone_w = 1  # 信息素权重
distance_w = 6  # 距离权重
volatilize = 0.5  # 信息素挥发比例
pheromone_Q = 10  # 总信息素
run_time = 100  # 模拟时间
time_particles = 0.05  # 绘图间隔
new_pheromone = np.zeros((foods_n, foods_n))
# 绘图
plt.figure()
plt.pause(10)    # 方便我录屏,等10s再出画面你们要删去
env = simpy.Environment()  # 设置环境并启动模拟
ants, foods, pheromone, distance = Initialization(ants_n, foods_n, dimension)  # 初始化,通常,蚁群数目是食物数目1.5倍
print(foods)
Firing(env)  # 开火,启动(添加要模拟的函数)
env.run(until=run_time)  # 运行模拟print(min_route,min_distance)
plt.show()  # 遍历完成后不消失

自己用建议删去 plt.pause(10)这一行,同时,可以调大time_particles,

这是结果:

视频审核还没通过,通过了就放出来

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

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

相关文章

排序算法--插入排序

实现逻辑 ① 从第一个元素开始,该元素可以认为已经被排序 ② 取出下一个元素,在已经排序的元素序列中从后向前扫描 ③如果该元素(已排序)大于新元素,将该元素移到下一位置 ④ 重复步骤③,直到找到已排序的元…

【数据结构】树与二叉树(十八):树的存储结构——Father链接结构、儿子链表链接结构

文章目录 5.1 树的基本概念5.1.1 树的定义5.1.2 森林的定义5.1.3 树的术语 5.2 二叉树5.3 树5.3.1 树的存储结构1. 理论基础2. 典型实例 5.3.2 Father链接结构a. 定义树节点结构b. 创建新节点c. 主函数d. 代码整合 5.3.3 儿子链表链接结构a. 定义树节点结构b. 创建新节点c. 添加…

为什么录屏没声音?实用技巧大放送!

录屏已成为我们在数字时代记录和分享内容的重要方式之一。但有时,您可能会遇到录制视频却没有声音的问题。这个问题可能出现在不同的录屏软件中,导致许多人感到疑惑。在本文中,我们将探讨为什么录屏没声音,并提供两种解决方案&…

C语言实现堆栈和队列(动态)

行路难!行路难!多歧路,今安在?长风破浪会有时,直挂云帆济沧海。————李白 一 .堆栈 1 什么是堆栈 堆栈是一种特殊的线性表,堆栈中的元素以及元素之间的逻辑关系和线性表完全相同。在操作上的差别是线性…

springboot+jsp+bootstrap+java问卷调查系统

系统功能需求包含业务需求和功能需求,系统功能需求分析是在了解用户习惯、开发人员技术和实力等各个因素的前提下,对其进行深入分析,了解系统基本需求后,基本功能如下: 本课题要求实现优质的问卷调查系统,就…

安全框架springSecurity+Jwt+Vue-2(后端开发)

一、创建项目及配置 ①&#xff1a;创建新的项目及常用包 ②&#xff1a;引入依赖和配置 devtools&#xff1a;项目的热加载重启插件 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId&…

如何配置ESB单据集成接口

ESB企业服务总线在实际项目中主要用于各业务系统之间的集成&#xff0c;集成包括数据集成、应用集成以及业务单据集成等&#xff0c;ESB企业服务总线主要包含三部分&#xff1a;ESB设计器、SMC管理控制台以及Server运行环境&#xff0c;ESB设计器用于服务以及集成流程的开发&am…

【C++ 设计模式】面向对象设计原则 Template Method 模式 Strategy 策略模式

一、面向对象设计原则 重新认识面向对象 理解隔离变化 • 从宏观层面来看&#xff0c;面向对象的构建方式更能适应软件的变化&#xff0c; 能将变化所带来的影响减为最小 各司其职 • 从微观层面来看&#xff0c;面向对象的方式更强调各个类的“责任” • 由于需求变化导…

Tesco EDI需求分析

Tesco&#xff0c;成立于1919年&#xff0c;是一家全球领先的综合性零售企业&#xff0c;总部位于英国。公司致力于提供高质量、多样化的商品和服务&#xff0c;以满足客户的需求。Tesco的使命是通过创新和卓越的客户服务&#xff0c;为客户创造更美好的生活。多年来&#xff0…

【idea】解决idea 执行maven build总下载 Downloading maven-metadata.xml文件

可以看到如下日志中打印了执行的命令行&#xff0c;其中包含 --update-snapshots&#xff0c;是强制更新的意思。 日志内容如下&#xff1a; D:\env\jdk1.8.0_261\bin\java.exe --update-snapshots -s D:\env\apache-maven-3.8.6\conf\settings.xml -Dmaven.repo.localD:\env\…

【开源】基于Vue.js的天然气工程业务管理系统的设计和实现

项目编号&#xff1a; S 021 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S021&#xff0c;文末获取源码。} 项目编号&#xff1a;S021&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、使用角色3.1 施工人员3.2 管理员 四…

tomcat (SCI)ServletContainerInitializer 的加载原理

问题&#xff1a;使用WebScoket的时候发现通过ServerEndpoint方式注册上去的url无法访问&#xff0c;报错404 经过排查发现在WsServerContainer这个类中的addEndpoint方法一直没有触发ServerEndpoint注解的扫描 通过该方法来源于StandardContext.startInternal()方法的调用如下…

CSS特效015:7个小球转圈圈加载效果

CSS常用示例100专栏目录 本专栏记录的是经常使用的CSS示例与技巧&#xff0c;主要包含CSS布局&#xff0c;CSS特效&#xff0c;CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点&#xff0c;CSS特效主要是一些动画示例&#xff0c;CSS花边是描述了一些CSS…

ERP对接淘宝/天猫/京东/拼多多商品详情数据API接口

引言 今天&#xff0c;我们时代变化非常快&#xff0c;传统行业做法&#xff0c;已经无法完全适应时代的发展。互联网的发展&#xff0c;造成了一股网购热。京东&#xff0c;天猫&#xff0c;淘宝&#xff0c;易购……网购&#xff0c;给我们生活带来了方便&#xff0c;消费者…

人工智能:科技之光,生活之美

在科技飞速发展的今天&#xff0c;人工智能已经深入到我们的生活中&#xff0c;它如同一束璀璨的科技之光&#xff0c;照亮我们生活的每一个角落&#xff0c;使我们的生活更加美好。下面我将从人工智能的领域、应用以及对人工智能的看法三个方面来谈谈它对我们生活的影响。 一、…

最新红盟云卡个人自动发卡开源系统源码+全开源无加密+虚拟商品在线售卖平台

源码简介&#xff1a; 最新红盟云卡个人自动发卡开源系统源码全开源无加密虚拟商品在线售卖平台&#xff0c;支持多个接口的个人免签功能。 红盟云卡系统是一款基于PHP和MySQL开发的虚拟商品在线售卖平台。它具备美观且功能丰富的发卡网站特性&#xff0c;并可与社区进行无缝…

【量化】一个简版单档tick数据回测框架

这是一个简易的模拟实际交易流程的回测框架&#xff0c;所使用的行情数据是单档的tick成交数据。为了实现调用者可以实现自己的交易逻辑&#xff0c;本框架预留了几个函数予以调用者能够继承类后在子类中重写以实现买入卖出信号的生成&#xff08;check_sell()和check_buy()&am…

Docker Swarm总结

1、swarm 理论基础 1.1 简介 Docker Swarm 是由 Docker 公司推出的 Docker 的原生集群管理系统&#xff0c;它将一个 Docker 主机池变成了一个单独的虚拟主机&#xff0c;用户只需通过简单的 API 即可实现与 Docker 集群的通 信。Docker Swarm 使用 GO 语言开发。从 Docker 1.…

Ajax基础(应用场景|jquery实现Ajax|注意事项|Ajax发送json数据|Ajax携带文件数据)

文章目录 一、Ajax简介二、基于jquery实现Ajax三、使用Ajax注意的问题1.Ajax不要与form表单同时提交2.后端响应格式问题3、使用了Ajax作为请求后的注意事项 四、前后端数据传输的编码格式(content-Type)1.urlencoded2.formdata3.application/json 五、Ajax携带文件数据六、Ajax…

代码随想录第六十三天 | 单调栈:寻找 左边 / 右边 距离当前元素最近的 更小 元素的 下标(暴力,双指针,单调栈)(84);代码随想录主要题目结束

1、寻找 左边 / 右边 距离当前元素最近的 更小 元素的 下标 1.1 leetcode 84&#xff1a;柱状图中最大的矩形 第一遍代码思路错了&#xff0c;如&#xff1a;输入[2,1,2]&#xff0c;对于2&#xff0c;因为比栈顶元素1大&#xff0c;然后就会直接得出2&#xff08;1&#xff…