【问题标题】:Seeking advice on trying to read a moore neighbourhood for a 2D cellular automata in MATLAB for an epidemic simulator寻求有关尝试在 MATLAB 中为流行病模拟器读取 2D 元胞自动机的摩尔邻域的建议
【发布时间】:2019-06-13 16:06:35
【问题描述】:

我目前正在编写一个代码,该代码利用 2D 元胞自动机作为 MATLAB 中的流行病模拟器。我试图实现的主要基本规则是,如果摩尔社区内任何一个半径为 1 个单元格的邻居被感染,则该单元格将被感染。但我似乎无法得到一个好的代码。

基本上我要做的是,对于一个单元格半径为摩尔邻域的单元格,如果该邻域中的任何值 = 2,那么初始单元格将变为 2。

我尝试使用 Rosetta 代码上的森林火灾代码作为代码行为的基础,但效果不佳。将其应用于我的规则时,这些规则并不能很好地发挥作用。我尝试使用 mod 函数和一系列 if 循环来附加。我将在每个代码中添加一些代码以提供上下文。

说实话,这个例子并不能很好地作为流行病模拟器。

    matlab
    clear; clc;
    n = 200;
    N = n/2;
    E = 0.001; % Creating an arbitrary number for population exposed to                 
                 the disease but not infected
    p = 1 + (rand(n,n)<E);
    %p = ceil(rand(n,n)*2.12) - 1;
    % ratio0 = sum(p(:)==0)/n^2;
    % ratio1 = sum(p(:)==1)/n^2;
    % ratio2 = sum(p(:)==2)/n^2;
    % ratio3 = sum(p(:)==3)/n^2;
    S = ones(3); S(2,2) = 0;
    ff = 0.00000000002;
    p(N,N) = 3;
    %% Running the simulation for a set number of loops
    colormap([1,1,1;1,0,1;1,0,0]); %Setting colourmap to Green, red and 
    grey
    count = 0;
    while(count<365) % Running the simulation with limited number of runs
    count = count + 1;
    image(p); pause(0.1); % Creating an image of the model
    P = (p==1); % Adding empty cells to new array
    P = P + (p==2).*((filter2(S,p==3)>0) + (rand(n,n)<ff) + 2); % Setting         
              2 as a tree, ignites based on proximity of trees and random 
              chance ff
    P = P + (p==3); % Setting 3 as a burning tree, that becomes 1,
    p = P;
    end

第二个想法。这基本上什么都不返回

    matlab
    clear;clf;clc;
    n = 200;
    pos = mod((1:n),n) + 1; neg = mod((1:n)-2,n) + 1;
    p = (ceil(rand(n,n)*1.0005));
    for t = 1:365
        if p(neg,neg) ==2 
           p(:,:) = 2;
        end
        if p(:,neg)==2 
           p(:,:) = 2;
        end
        if p(pos,neg)==2
           p(:,:) = 2;
        end
        if p(neg,:)==2
           p(:,:) = 2;
        end   
        if p(pos,:)==2
           p(:,:) = 2;
        end
        if p(neg,pos)==2
           p(:,:) = 2;
        end
        if p(:,pos)==2
           p(:,:) = 2;
        end
        if p(pos,pos)== 2
           p(:,:) = 2;
        end
        image(p)
        colormap([1,1,1;1,0,1])
    end

第三,我尝试使用逻辑门来查看是否可行。我不知道逗号是否可以代替。

    matlab
    clear;clf;clc;
    n = 200;
    pos = mod((1:n),n) + 1; neg = mod((1:n)-2,n) + 1;
    p = (ceil(rand(n,n)*1.0005));
    %P = p(neg,neg) + p(:,neg) + p(pos,neg) + p(neg,:) + p(:,:) + p(pos,:)         
       + p(neg,pos) + p(:,pos) + p(pos,pos)

    for t=1:365
        if p(neg,neg)|| p(:,neg) || p(pos,neg) || p(neg,:) ||  p(pos,:) ||         
           p(neg,pos) || p(:,pos) || p(pos,pos) == 2
           p(:,:) = 2;
        end
        image(p)
        colormap([1,1,1;1,0,1])
    end

我预计矩阵会逐渐变得更加洋红色,但在第二个矩阵中没有任何反应。我第三次收到此错误。

“|| 和 && 运算符的操作数必须可转换为逻辑标量值。”

我只是不知道该怎么办!

【问题讨论】:

  • 所以单元格可以是12。如果邻居是2,则单元格变为2。它会变成1吗?自己细胞的状态重要吗? 2 单元格是否始终保持为 2
  • 嗨 Luis,你是对的,有 2 个状态,如果邻居是 2,则单元格变为 2。经过几次迭代,单元格将恢复 (3),但我还没有确定如何编码。一旦单元格变为 (3),就不可能再变为 2。
  • 恢复是另一回事,应该作为不同的问题发布,因为它完全改变了问题。我要做的是:将单元格定义为 `0 表示未感染和正整数表示感染,并在每个单元格中保留一个计数器,该计数器在每次迭代时都会增加。当细胞达到给定值时,它就会被治愈
  • "|| 和 && 运算符的操作数必须可转换为逻辑标量值。" 解决了 herehere 的问题。
  • @Luis Mendo 当您说在每个单元格中保留一个计数器时,您的意思是使用 1 和 0 来将周围单元格中 1 的数量相加吗?例如,使用我的代码,P = p(neg,neg) + p(:,neg) + p(pos,neg) + p(neg,:) + p(:,:) + p(pos,:) + p(neg,pos) + p(:,pos) + p(pos,pos) p =' P==3 | P==4 或类似的东西?

标签: matlab cellular-automata


【解决方案1】:

细胞不愈合

我认为

  • 被感染的是2,未感染的是1
  • 被感染的细胞仍然被感染;
  • 如果有任何邻居感染,则未感染的细胞会被感染。

实现此目的的一种简单方法是使用 2-D 卷积:

n = 200;
p = (ceil(rand(n,n)*1.0005));
neighbourhood = [1 1 1; 1 1 1; 1 1 1]; % Moore plus own cell
for t = 1:356
    p = (conv2(p-1, neighbourhood, 'same')>0) + 1; % update
    image(p), axis equal, axis tight, colormap([.4 .4 .5; .8 0 0]), pause(.1) % plot
end

细胞在特定时间后愈合

  • 要对此建模,最好将0 用于未感染的细胞,使用正整数表示受感染的细胞,这表明它已被感染了多长时间。
  • 细胞在被感染指定的迭代次数后会愈合(但可以立即再次被感染...)

代码和之前一样使用卷积,但现在已经感染的细胞需要与新感染的细胞分开处理,因此使用了真正的摩尔邻域。

n = 200;
p = (ceil(rand(n,n)*1.0005))-1; % 0: non-infected. 1: just infected
T = 20; % time to heal
neighbourhood = [1 1 1; 1 0 1; 1 1 1]; % Moore
for t = 1:356    
    already_infected = p>0; % logical index
    p(already_infected) = p(already_infected)+1; % increase time count for infected
    newly_infected = conv2(p>0, neighbourhood, 'same')>0; % logical index
    p(newly_infected & ~already_infected) = 1; % these just became infected
    newly_healed = p==T; % logical index
    p(newly_healed) = 0; % these are just healed
    image(p>0), axis equal, axis tight, colormap([.4 .4 .5; .8 0 0]), pause(.1) % plot
    % infected / non-infected state
end

【讨论】:

  • 哇,这太棒了!我有点理解 conv2 函数的工作原理,它就像图像卷积,对吧?你能解释一下为什么在 p = (conv2(p-1, neighbourhood, 'same')>0) + 1;您使用 p-1 然后在最后使用 + 1 吗?是加 1,所以你有一个包含 1 和 2 值的最终矩阵?
  • 是的,这就是卷积,用于图像处理。我使用p-1,所以未感染的是0,而不是1。这样,如果卷积结果是任何正数,则意味着细胞现在已被感染。要将“任何正数”转换为1,我使用的是&gt;0。然后,正如你所说,我加 1 将 0,1 转换为 1,2
  • 酷,还有一个问题。你为什么用 [1 1 1; 1 1 1; 1 1 1] 为邻里?为邻域做卷积时,不考虑自己的cell不是更好吗?
  • 我将中心单元格包括在内以表示“如果该单元格被感染,它仍然被感染”。它使代码更紧凑。或者,您可以将其保留为 0,然后在卷积输出和输入之间应用逻辑 OR
  • 非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2020-01-26
  • 1970-01-01
  • 2011-04-25
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
相关资源
最近更新 更多