QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1472|回复: 0
打印 上一主题 下一主题

[其他资源] 元胞自动机与疏散模型的matlab算法,元胞自动机模拟多出口疏散模型的matlab实现...

[复制链接]
字体大小: 正常 放大

1158

主题

15

听众

1万

积分

  • TA的每日心情
    开心
    2023-7-31 10:17
  • 签到天数: 198 天

    [LV.7]常住居民III

    自我介绍
    数学中国浅夏
    跳转到指定楼层
    1#
    发表于 2021-11-25 21:25 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    元胞自动机与疏散模型的matlab算法,元胞自动机模拟多出口疏散模型的matlab实现...- L* u: t& n- r* ~7 j

    2019美赛D题算法之一~

    元胞自动机模拟多出口疏散模型的matlab实现

    通过设定危险度规则,使用基于双端队列的01bfs算法快速计算每个格子的危险度,使元胞自发地倾向危险度更低的方向来模拟人员疏散模型。

    设定规则:自发,社会力,网络

    计算危险度:

    元胞模拟:概率,社会力

    规定

    地图:每个小方格对应真实空间中0.4m*0.4m的空间;

    地图元素值:0代表墙壁,1代表行人,2代表空格,3及以上的数字代表出口,连续的出口方格具有相同的值,不同的出口值不同。

    危险度:按八个方向连通的走法,走到任一出口处所需的步数记为该方格的危险度。

    算法流程

    读入地图;

    计算危险度:以每个出口为起点进行基于双端队列的01bfs算法,使用这种做法可以在O ( 空 方 格 数 ∗ 出 口 个 数 ) O(空方格数*出口个数)O(空方格数∗出口个数)内计算出每个空格的危险度。

    算法:

    将所有方格的危险度记为-1.

    记当前出口编号为3;

    初始化队列,将属于该出口的任一方格加入队列头部,记录其危险度为0.

    取出队列头所存储的下标,记为当前格。遍历扫描当前格周围的8个格子,记为目标格。

    如果目标格与当前格同属于当前出口的方格,那么目标格的预期危险度是0,否则目标格的预期危险度是当前格的危险度+1.

    如果目标格的现有危险度是-1或者现有危险度大于预期危险度,就将其的现有危险度置为预期危险度,并将其加入队列:如果预期危险度是0,将其加入队列头,否则加入队列尾。

    如果队列不为空,返回4.

    如果还有没有访问过的出口,就将出口编号+1然后返回3,否则结束。

    通过排序得出危险度从低到高的格子顺序,方便遍历;

    依据既定规则向地图内的空格子加入人,产生位置随机,越珍贵的展品附件产生概率越大;

    按危险度从低到高的顺序扫描所有格子,如果当前格子内是人,就计算它周围9个格子(包括自身)中未被占据的空格的前进概率,计算方法是β ∗ ( D m − D i ) \beta*(D_m-D_i)β∗(Dm​−Di​),其中β \betaβ是归一化系数。按这个概率进行决定人下一时刻的位置。到达出口后不再变化。

    显示当前时刻的地图状态。

    统计未到达出口的人的数量,如果不为0,返回5.。

    代码

    注:代码已修改。修改后的代码和输入数据见https://download.csdn.net/download/m0_37809890/10945394

    % 元胞自动机

    clc; clear;

    map = map_read();

    colormap([0.8 0.8 0.8;1 1 1;1 0 0;0 1 1;0 1 1]);

    danger = cal_danger(map);

    danger_order = cal_danger_oreder(danger);

    map = add_people(map, 0.20);

    [K,t] = move(map, danger, danger_order);

    function [K,t] = move(map, danger, danger_order)

    % 移动

    K = zeros(4000,3); t = 0;

    map_show(map);

    sel = zeros(1,27);

    while(size(find(map==1),1))

    t=t+1;

    K(t,1)=size(find(map(30:110, 340:360 )==1),1);

    K(t,2)=size(find(map(3:25, 210:280 )==1),1);

    K(t,3)=size(find(map(110:162,420:460 )==1),1);

    go = [0,-1; 0,1; -1,0; 1,0; 1,1; 1,-1; -1,1; -1,-1; 0,0];

    % flag = 0;

    for i = 1:size(danger_order,1)

    ua = danger_order(i,1); ub = danger_order(i,2);

    if map(ua,ub)~=1

    continue;

    end

    mx = 0; cnt = 0;

    for j = 1:size(go,1)

    va = ua+go(j,1); vb = ub+go(j,2);

    if(map_at(map,va,vb)>1)

    mx = max(mx,danger(va,vb));

    end

    end

    for j = 1:size(go,1)

    va = ua+go(j,1); vb = ub+go(j,2);

    if(map_at(map,va,vb)>1)

    for k = 1:mx+1-danger(va,vb)

    cnt = cnt+1; sel(cnt)=j;

    end

    end

    end

    if(cnt==0)

    continue;

    end

    target = sel(unidrnd(cnt));

    va = ua+go(target,1); vb = ub+go(target,2);

    map(ua,ub)=2;

    if(map(va,vb)==2)

    map(va,vb)=1;

    end

    end

    map_show(map);

    pause(0.01);

    end

    end

    function res = map_at(map,a,b)

    % 如果(a,b)在map内,返回map(a,b),否则返回0

    if(a>0&&b>0&&a<=size(map,1)&&b<=size(map,2))

    res = map(a,b);

    else

    res = 0;

    end

    end

    function map = map_read()

    % 读入地图

    load("./floor_1/map2_2.mat",'A');

    map = A';

    % map = [

    % 0, 0, 0, 0, 0, 0

    % 0, 2, 2, 1, 2, 0

    % 3, 2, 0, 2, 1, 0

    % 0, 2, 2, 2, 1, 0

    % 0, 0, 0, 0, 0, 0

    % ];

    end

    function map = add_people(map,rate)

    % 向地图里面加人

    rnd = rand(size(map));

    for i = 1:size(map,1)

    for j = 1:size(map,2)

    if rnd(i,j)=0)

    flag = 0;

    for k=size(go,1)

    va=ua+go(k,1); vb=ub+go(k,2);

    if(map_at(map,va,vb)==0)

    flag=1;

    break;

    end

    end

    if(flag)

    danger(ua,ub)=danger(ua,ub)+0;

    end

    end

    end

    end

    end

    function danger = bfs_01(map,danger,st)

    % 01bfs计算单种出口影响的复杂度

    n = numel(find(map~=0));

    lef=n; rig=n; que = zeros(n*2,2); % 初始化双端队列

    que(rig,:)=st; rig = rig+1; %push_back

    danger(st(1),st(2)) = 0;

    while(lef=1)

    nd = danger(ua,ub)+2;

    if(danger(ua,ub)==0 && map(ua,ub)==map(va,vb))

    nd = 0;

    end

    if(danger(va,vb)==-1 || danger(va,vb)>nd)

    danger(va,vb) = nd;

    if(nd==0)

    lef=lef-1; que(lef,:)=[va,vb];%push_front

    else

    que(rig, :)=[va,vb]; rig=rig+1; % push_back

    end

    end

    end

    end

    end

    end

    function danger_order = cal_danger_oreder(danger)

    % 将危险度进行排序

    n = numel(find(danger~=-1));

    danger_order = zeros(n,3); k = 1;

    for i = 1:size(danger,1)

    for j = 1:size(danger,2)

    if(danger(i,j)~=-1)

    danger_order(k,1) = i;

    danger_order(k,2) = j;

    danger_order(k,3) = danger(i,j);

    k = k + 1;

    end

    end

    end

    [~, pos] = sort(danger_order(:,3));

    danger_order = danger_order(pos,1:2);

    end

    + ?! C9 ^4 k9 v. g' E$ |" p
      P: O6 S# D6 M1 t* O' \
    0 i, v, E: `- Q: V& c% e, E
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2024-4-26 02:23 , Processed in 0.401443 second(s), 50 queries .

    回顶部