2019美赛D题人员疏散模拟(错误解答,仅记录)

2021年3月21号编辑内容

特此说明:笔主写这篇文章的时候还是大三上学期结束,认知、技术都完全不过关,此时再回看这篇文章,着实有很多问题,甚至是误导。特此说明
笔主从学习Python,也就是写下这篇文章的时期,目前从事前端开发工作,也开始学习C++,也没有那种机会进入相关算法研发工作。今时看来,此文的编码、思想都略显幼稚甚至荒唐。
毕竟是自己踩下的脚印,不忍抹去,此段话放在开头,希望刷到的同学谨慎参考,谢谢各位。
———————————————————————————————————————————

有幸参加了2019年美国大学生数学建模比赛。比赛过程中担任的角色中有编程任务,现将当时的代码和大家分享。比赛结束后抽空将代码完善了一下,仍然有诸多不足之处。

一、我们团队的想法

我们团队怎么也找不到卢浮宫的建筑平面图,有找到的吗????不能精确定位模拟,所以就基于疏散问题建立了自己的平面图。
1、假设(部分)
(1)场馆内无障碍物(这样简化了很多)
(2)场馆内人员单位时间内最多能移动一个元胞距离(很关键,不然非常)
2、馆内人员移动分析

即单位时间内可以移动八个方向,每次一个元胞距离
3、安全出口数量以及安全出口的考虑
如果考虑多个安全出口,仅仅比赛那点时间,我这点水平编程是不够的,所以指定只有一个安全出口;在考虑安全出口位置的时候,我们也指定出口位置为墙上的一个开口,比赛结束后,我将代码优化补全,现在支持安全出口的位置在室内任何地方。

二、代码部分

因为不是一篇写这次比赛解决方法的博客,下面我重点展示代码实现。先展示各个点的实现,最后在附送上完整代码。
运用到matplotlib库进行可视化,所以就不提基础部分,主要展示怎么将现实问题抽象成代码
1、创建房间、创建人员及初始位置生成、安全出口

N, row, column = 250, 20, 20  #室内人数,矩阵的行数,矩阵的列数
room = np.zeros((row + 2, column + 2))  # 创建房间
export = [(6, 11, 'E')]  # 设定出口位置和开门方向,此处为坐标轴坐标

** 注意:**出口的坐标表示为二维直角坐标系的定位方式,并非出口在矩阵中的索引,出口方向分别为‘N’‘S’‘W’‘E’,对应四个方位。

def initial_room():'''生成初始人员并进行随机分配'''coordinates = []  # 室内人员坐标for i in range(N):generated_data = [random.randint(1, row), random.randint(1, column)]if not generated_data in coordinates:  # 去掉重复数据coordinates.append(generated_data)for i in range(len(coordinates)):room[coordinates[i][0]][coordinates[i][1]] = 1# 创建围墙、创建出口for i in range(len(room)):for j in range(len(room)):if i == 0 or i == len(room) - 1 or j == 0 or j == len(room[i]) - 1:room[i][j] = 9for i in range(len(export)):room[export[i][1]][export[i][0]] = 8return

人员随机分配,对应矩阵中的索引,设置删除重复的位置,即得一个人对应一个位置。围墙使用数值9表示,出口使用数值8表示。
2、可视化

for i in range(1, len(room) - 1):for j in range(1, len(room[i]) - 1):if room[i][j] == 1:rect = mpathes.Circle((j + 0.5, i + 0.5), 0.3, color='grey')ax.add_patch(rect)
plt.show()

将矩阵索引与二维坐标Y轴一一对应,即矩阵索引为0的列表对应坐标轴Y方向最小的坐标,便于后续编程

完整代码

代码半完整写下来将近300行,还有一些没有完善,下文会提到

import matplotlib.pyplot as plt
import matplotlib.patches as mpathes
import numpy as np
import random# 初始位置生成
def initial_room():'''生成初始人员并进行随机分配'''coordinates = []  # 室内人员坐标for i in range(N):generated_data = [random.randint(1, row), random.randint(1, column)]if not generated_data in coordinates:  # 去掉重复数据coordinates.append(generated_data)for i in range(len(coordinates)):room[coordinates[i][0]][coordinates[i][1]] = 1# 创建围墙、创建出口for i in range(len(room)):for j in range(len(room)):if i == 0 or i == len(room) - 1 or j == 0 or j == len(room[i]) - 1:room[i][j] = 9for i in range(len(export)):room[export[i][1]][export[i][0]] = 8return# 创建平台
def create_flat():# fig, ax = plt.subplots()plt.xticks(np.arange(0, column + 3, 1.0))plt.yticks(np.arange(0, row + 3, 1.0))plt.grid(linestyle='--')wall_botton = mpathes.Rectangle((0, 0), column + 2, 1, color='grey')wall_left = mpathes.Rectangle((0, 0), 1, row + 2, color='grey')wall_top = mpathes.Rectangle((0, row + 1), column + 2, 1, color='grey')wall_right = mpathes.Rectangle((column + 1, 0), 1, row + 2, color='grey')ax.add_patch(wall_botton)ax.add_patch(wall_top)ax.add_patch(wall_left)ax.add_patch(wall_right)for i in range(len(export)):ax.add_patch(mpathes.Rectangle((export[i][0], export[i][1]), 1, 1, color='green'))# 更新状态
def update_state():'''搜寻距离出口同一层的人,记录坐标:return:'''# 记录坐标tem=[]for i in range(len(export)):tem.append(column-export[i][0])tem.append(row-export[i][1])tem.append(export[i][0]-1)tem.append(export[i][1]-1)n = max(tem)total_around_people = []for i in range(1, n + 1):  # 总循环次数n,从1开始around_people = []if export[0][1] + i < row + 1:  # 上左(有这一行)在范围内if export[0][0] - i > 0:  # 上左(列)在范围内if export[0][0] + i < column + 1:  # 上右(列)在范围内for j in range(export[0][0] - i, export[0][0] + i + 1):   #列的变化范围if room[export[0][1]+i][j] == 1:around_people.append((export[0][1]+i, j))else:  # 上右(列)不再范围内for j in range(export[0][0] - i, column + 1):if room[export[0][1]+i][j] == 1:around_people.append((export[0][1]+i, j))else:  # 上左(列)不在范围内if export[0][0] + i < column + 1:  # 上右(列)在范围内for j in range(1, export[0][0]+i+1):if room[export[0][1]+i][j] == 1:around_people.append((export[0][1]+i, j))else:  # 上右(列)不再范围内for j in range(1, column + 1):if room[export[0][1]+i][j] == 1:around_people.append((export[0][1], j))if export[0][1] - i > 0:  # 下左在范围内(有这一行)if export[0][0] - i > 0:  # 下左(列)在范围内if export[0][0] + i < column + 1:  # 下右(列)在范围内for j in range(export[0][0] - i, export[0][0] + i + 1):if room[export[0][1]-i][j] == 1:around_people.append((export[0][1]-i, j))else:  # 下右(列)不在范围内for j in range(export[0][0] - i, column + 1):if room[export[0][1]-i][j] == 1:around_people.append((export[0][1]-i, j))else:  # 下左(列)不在范围内if export[0][0] + i < column + 1:  # 下右(列)在范围内for j in range(1, export[0][0] + i + 1):if room[export[0][1]-i][j] == 1:around_people.append((export[0][1]-i, j))else:  # 下右(列)不在范围内for j in range(1, column + 1):if room[export[0][1]-i][j] == 1:around_people.append((export[0][1]-i, j))if export[0][0] - i > 0:  # 上左(列)存在if export[0][1] + i < row + 1:  # 上左(行)存在if export[0][1] - i > 0:  # 下左(行)存在for j in range(export[0][1]- i +1, export[0][1] + i):if room[j][export[0][0]-i] == 1:around_people.append((j, export[0][0] - i))else:  # 下左(行)不存在for j in range(1, export[0][1] + i):if room[j][export[0][0] - i] == 1:around_people.append((j, export[0][0] - i))else:  # 上左(行)不存在if export[0][1] - i > 0:  # 下左(行)存在for j in range(export[0][1]+1,len(room)-1):if room[j][export[0][0] - i] == 1:around_people.append((j, export[0][0] - i))else:  # 下左(行)不存在for j in range(1, len(room)-1):if room[j][export[0][0] - i] == 1:around_people.append((j, export[0][0] - i))if export[0][0] + i < len(room[i])-1:  # 上右(列)存在if export[0][1] + i < len(room)-1:  # 上右(行)存在if export[0][1] - i > 0:  # 下右(行)存在for j in range(export[0][1] - i + 1, export[0][1] + i):if room[j][export[0][0] + i] == 1:around_people.append((j, export[0][0] + i))else:  # 下右(行)不存在for j in range(1, export[0][1] + i):if room[j][export[0][0] + i] == 1:around_people.append((j, export[0][0] + i))else:  # 上右(行)不存在if export[0][1] - i > 0:  # 下右(行)存在for j in range(export[0][1]-i, len(room)-1):if room[j][export[0][0] + i] == 1:around_people.append((j, export[0][0] + i))else:  # 下右(行)不存在for j in range(1, len(room)-1):if room[j][export[0][0] + i] == 1:around_people.append((j, export[0][0] + i))total_around_people.append(around_people)newlist = [x for x in total_around_people if x]  # 删除空格项distance = []dic = {}for i in range(len(newlist)):subdis = []for j in range(len(newlist[i])):dis = ((newlist[i][j][0] - export[0][1] + 1) ** 2 + (newlist[i][j][1] - export[0][0] + 1) ** 2)dic[newlist[i][j]] = dissubdis.append(dis)distance.append(subdis)tourists_move(dic, distance)  # 引用移动函数def tourists_move(dic, distance):for k in range(len(distance)):order = sorted(distance[k])order_dis = []  # 排序存放了周围元素距离坐标for i in order:for key, val in dic.items():if val == i:order_dis.append(key)del dic[key]breakif export[0][2] == 'E':  # 出口朝向for i in range(len(order_dis)):  # 一次判断每个点x, y, xdoor, ydoor = order_dis[i][0], order_dis[i][1], export[0][1], export[0][0]if x < xdoor and y > ydoor:  # 右下角if room[x+1][y-1] == 8:  #斜角room[x][y] = 0elif room[x + 1][y - 1] == 0 and y-1>ydoor :  # 斜角room[x + 1][y - 1] = 1room[x][y] = 0elif room[x][y - 1] == 0:  # 往左room[x][y - 1] = 1room[x][y] = 0elif room[x + 1][y] == 0:  # 往下room[x + 1][y] = 1room[x][y] = 0else:continueelif x > xdoor and y > ydoor:  # 右上角if room[x-1][y-1]==8:room[x][y] = 0elif room[x - 1][y - 1] == 0 and y-1>ydoor:  # 斜角room[x - 1][y - 1] = 1room[x][y] = 0elif room[x][y - 1] == 0:  # 往左room[x][y - 1] = 1room[x][y] = 0elif room[x - 1][y] == 0:  # 往下room[x - 1][y] = 1room[x][y] = 0else:continueelif x == xdoor and y > ydoor:  #(右)正前面if room[x][y - 1] == 8:  #往前8room[x][y] = 0elif room[x][y - 1] == 0:  #往前room[x][y - 1] = 1room[x][y] = 0else:if room[x+1][y-1]==0:room[x + 1][y - 1] = 1room[x][y]=0elif room[x-1][y-1]==0:room[x-1][y-1]=1room[x][y]=0else:continueelif x < xdoor and y <= ydoor:   #左下if room[x + 1][y + 1] == 0:  #斜角room[x + 1][y + 1] = 1room[x][y] = 0elif room[x + 1][y] == 0:    #往上room[x + 1][y] = 1room[x][y] = 0elif room[x][y + 1] == 0:    #往右room[x][y + 1] = 1room[x][y] = 0else:continueelif x > xdoor and y <= ydoor:   #左上if room[x - 1][y + 1] == 0:  #斜角room[x - 1][y + 1] = 1room[x][y] = 0elif room[x][y + 1] == 0:   #往右room[x][y + 1] = 1room[x][y] = 0elif room[x - 1][y] == 0:   #往下room[x - 1][y] = 1room[x][y] = 0else:continue# elif x == xdoor and y <ydoor:else: #(左)正对if room[x][y+1]==0:room[x][y+1]=1room[x][y]=0else:if room[x+1][y+1]==0:room[x+1][y+1]=1room[x][y]=0elif room[x-1][y+1]==0:room[x-1][y+1]=1room[x][y]=0else:continueelif export[2] == 'W':  # 出口朝向continueelif export[2] == 'N':  # 出口朝向continueelif export[2] == 'S':  # 出口朝向continue# 可视化def visualization():for i in range(1, len(room) - 1):for j in range(1, len(room[i]) - 1):if room[i][j] == 1:rect = mpathes.Circle((j + 0.5, i + 0.5), 0.3, color='grey')ax.add_patch(rect)plt.show()def main():create_flat()#visualization()  # 调用可视化函数update_state()visualization()   #调用可视化函数if __name__ == '__main__':'''N:室内游客总数column:室内水平方向元胞个数,代表列数量row:室内竖直方向元胞个数,代表行数量'''N, row, column = 5, 20, 20room = np.zeros((row + 2, column + 2))  # 创建房间export = [(0, 11, 'E')]  # 设定出口位置和开门方向,此处为坐标轴坐标initial_room()  # 创建人员while 1 in room:fig, ax = plt.subplots()main()

不足之处

1、目前只完成了出口方向面朝东面的编程

2、对出口正对上下左右四个方向的逻辑设计不够严谨与完美,具体感兴趣的朋友可以复制完整代码运行查看,有好想法的朋友可以交流下哈哈哈哈

总结

美赛结束之后,回家过年各种事情在忙,期间利用碎片时间来整理代码,这个结束也很仓促,想深入了解,交流的朋友可以留言,非常欢迎~~~~

2019美赛D题,元胞自动机模拟游客疏散过程相关推荐

  1. GIS实战应用案例100篇(二)-元胞自动机模拟城市扩张过程

    前言 CA模型:CA(Cellular Automat)即元胞自动机模型,元胞自动机是一种具有时空计算特征的模型框架,从局部到整体的建模思想被广泛的应用于空间上离散.时间上也离散的复杂性系统模拟.标准 ...

  2. 笔记丨元胞自动机模拟城市扩张过程

    忙啊忙啊....实验数据来自翁敏老师的空间分析.我是初次接触,为了熟悉操作,参照课本进行粗浅记录,很粗糙,不具备参考价值,请各位仔细甄别. CA模型:CA(Cellular Automat)即元胞自动 ...

  3. 【元胞自动机】元胞自动机地铁火灾疏散模型【含Matlab源码 246期】

    ⛄一.元胞自动机简介 1 元胞自动机发展历程 最初的元胞自动机是由冯 · 诺依曼在 1950 年代为模拟生物 细胞的自我复制而提出的. 但是并未受到学术界重视. 1970 年, 剑桥大学的约翰 · 何 ...

  4. 【元胞自动机】基于元胞自动机模拟3D森林火灾模型含Matlab源码

    1 简介 森林火灾威胁森林安全,导致生命财产与环境损失,动态模拟森林火灾对于预判森林火灾发展趋势,减少森林火灾危害,科学开展森林火灾灭火工作具有重要理论与现实意义.为更加形象,直观地展示林火三维可视化 ...

  5. python元胞自动机模拟交通_基于立体网格的放射性污染物扩散过程模拟与表达

    作 者 信 息 施加松1,余接情2,常芸芬1,童晓冲3 (1.防化研究院,北京 102205:2.中国矿业大学 环境与测绘学院,江苏 徐州 221116:3.信息工程大学,河南 郑州 450001) ...

  6. 【元胞自动机】基于matlab元胞自动机模拟交通路况(含超车)【含Matlab源码 2389期】

    ⛄一.元胞自动机简介 1 元胞自动机发展历程 最初的元胞自动机是由冯 · 诺依曼在 1950 年代为模拟生物 细胞的自我复制而提出的. 但是并未受到学术界重视. 1970 年, 剑桥大学的约翰 · 何 ...

  7. 【元胞自动机】基于元胞自动机模拟双车道交通流模型含靠右行驶matlab源码

    元胞自动机的初步理解 对元胞自动机的初步认识\ 元胞自动机(CA)是一种用来仿真局部规则和局部联系的方法.典型的元\ 胞自动机是定义在网格上的,每一个点上的网格代表一个元胞与一种有限的状\ 态.变化规 ...

  8. 澳洲森林火灾蔓延数学建模,基于元胞自动机模拟多模式下火灾蔓延(附部分源码)

    前言 本文篇幅较长,希望各位小伙伴能够耐心看完. 元胞自动机模型可以用来模拟交通流.火灾蔓延情况.高速收费站交通情况,有利于我们更好地改善交通状况,更好地控制火灾蔓延,合理地设置收费站的数量等. 关于 ...

  9. python元胞自动机模拟交通_大师兄带你复现 -gt; 难度超高的二维CA元胞自动机模型...

    最近过上了在家躺着就为祖国做贡献的生活. 然而,热心的知友们找我私信,询问"怎么画二维CA(元胞自动机)模型的仿真界面呀?""菜鸟如何做CA仿真?" 刚交完稿子 ...

  10. python元胞自动机模拟交通_结构专栏 | 解析DEFORM软件中的元胞自动机法

    点击上方蓝色字体,关注我们 导语 金属材料的性能取决于内部的微观组织结构,而好的材料性能和价格是产品最大的优势.随着现代物理冶金.热成形技术.热处理技术和计算机技术的兴起与发展,使预测和控制金属材料热 ...

最新文章

  1. android代码混淆笔记
  2. Linux查看CPU信息、机器型号等硬件信息
  3. ps 2c语言程序,C语言基础(二)
  4. 浅谈HTML5中canvas中的beginPath()和closePath()的重要性
  5. 发现了拯救“文献多的一团麻”的工具
  6. PyTorch 1.6 发布:原生支持自动混合精度训练并进入稳定阶段
  7. python输入字符串str_python字符串String模块
  8. 一念心动,一生绵延——如何修复min pulse width?
  9. BZOJ 1507 [NOI2003]Editor
  10. 尚学堂马士兵Oracle教程 笔记
  11. C语言——定积分的计算
  12. 瑞昱rtl8168网卡支持Linux吗,我的集成网卡RTL8111/8168B终于搞定(非常感谢ubuntu中文论坛)...
  13. 页面置换算法之 LRU算法
  14. 《前端框架Vue.js》
  15. 深入剖析ReentrantLock公平锁与非公平锁源码实现
  16. Windows自带录屏
  17. JAVA SE (14)
  18. Unity之创建文件报错
  19. RYU+mininet——RYU
  20. 2020CCFBDCI通用音频分类CNN方案(0.90+方案)

热门文章

  1. [论文总结] 智慧农业论文摘要阅读概览
  2. 基于javaweb的音乐网站
  3. Linux_ppc下软件包安装,LINUX2000PPC安装手册
  4. android开发 自我优势_android开发简历自我评价填写样本
  5. linux命令行安装qq,在Linux上使用mojoqq来实现命令行QQ
  6. protel99se中文版
  7. sql优化的几种方法
  8. ESP32 之 ESP-IDF 教学(十一)WiFi篇—— WiFi两种模式
  9. 【TCP/IP】【测试】常用抓包软件一览
  10. mac开发工具清单java