元胞自动机
元胞自动机 (Celluar Automata
) 是一种广泛应用的模型理论, 由元胞, 元胞状态, 邻域和状态更新规则所构成.
元胞空间是构成元胞自动机的最基本单元-元胞所分布的空间网点集合.
正常情况下, 同一时刻, 每个元胞有且仅有一种元胞状态.
在空间位置上与某个元胞相邻的元胞称为它的邻元. 邻域是由所有邻元所组成的.
元胞自动机使用离散的空间布局和时间间隔, 将元胞分成有限种状态, 每一个元胞个体状态的演变仅与它的当前状态和其某个局部邻域的状态相关.
[注]
在 MATLAB 中, 若要动态展示元胞空间内元胞的变化过程, 至少需要掌握以下三条语句:
h = imagesc(元胞矩阵)
for i = 1:N(按照某种规则进行的循环)
set(h,'cdata',更新后的元胞矩阵)
drawnow
end
[例]
Conway 的生命游戏:
在给定的二维矩形空间内, 每个方格均由一个元胞所占据, 它只有两种状态: 活/死. 一个元胞在下一个时刻的生死取决于它相邻一圈八个方格中活细胞或死细胞的数量. 假定, 状态-存活对应
1
1
1, 死亡对应
0
0
0. 具体规则如下:
- 若对某个元胞的周围八个邻接元胞状态求和总和为 2 2 2, 则在下一时刻不改变其状态.
- 若总和为 3 3 3, 则认定下一时刻该细胞为活细胞 (状态为 1 1 1).
- 若总和不满足上述两种情况, 则下一时刻该元胞为死的.
MATLAB 代码实现如下:
%% Cell Automama
clc; clear all;
%% Build interface
plotbutton=uicontrol('style','pushbutton','string','运行', 'fontsize',12, 'position',[150,400,50,20], 'callback', 'run=1;');
erasebutton=uicontrol('style','pushbutton','string','停止','fontsize',12,'position',[250,400,50,20],'callback','freeze=1;');
quitbutton=uicontrol('style','pushbutton','string','退出','fontsize',12,'position',[350,400,50,20],'callback','stop=1;close;');
number = uicontrol('style','text','string','1','fontsize',12, 'position',[20,400,50,20]);
%% Initialize Cell Automata
n = 200; % Define The size of the world
% Initialize every cell
z = zeros(n,n);
sum = z;
cells = (rand(n,n))<.6;
% Construct The Image
imh = image(cat(3,cells,z,z));
set(imh, 'erasemode', 'none')
% Set column/row of cell updating
x = 2:n-1;
y = 2:n-1;
%% Main Event cycling
stop = 0; run = 0;freeze = 0;
while stop == 0
if run == 1
% Compute the number of living neighbors of every cell
sum(x,y) = cells(x,y-1) + cells(x,y+1) + cells(x-1,y) + cells(x+1,y) + cells(x-1,y-1) + cells(x-1,y+1) + cells(x+1,y-1) + cells(x+1,y+1);
%Update folling the rule
cells = (sum == 3) | (sum == 2 & cells);
set(imh, 'cdata', cat(3,cells,z,z))
stepnum = 1 + str2double(get(number, 'string'));
set(number, 'string', num2str(stepnum))
end
drawnow
end
[例]
森林火灾: 视给定的二维空间为森林区域, 每一个元胞代表一棵树木. 元胞状态分为三种: 空地, 燃烧树木, 和树木. 具体演化规则如下:
- 若某个树木元胞至少有四个邻居正在燃烧, 则下一时刻它也开始燃烧.
- 任何当前正在燃烧的树木均会在下一时刻变为空地.
- 每一个树木元胞都会以一个低概率燃烧.
- 所有的空地均以一个低概率变成树木.
MATLAB 代码实现如下:
%0为空位
%1为燃烧的树
%2为正常的树
n = 500; %构造森林大小
Plight = 5e-6; %被雷击中的概率
Pgrowth = 1e-2;%生长的概率
UL = [n 1:n-1]; %上左邻居
DR = [2:n 1];%下右邻居
veg=zeros(n,n);%森林
imh = image(cat(3,veg,veg,veg));
% veg = empty=0 burning=1 green=2
for i=1:3000 %循环
%观察每一个空位其上下左右邻居正在燃烧的树的个数(sum为300*300矩阵,每一个值对应森林的每一个空位)
sum = (veg(UL,:)==1) + (veg(:,UL)==1) + (veg(:,DR)==1) + (veg(DR,:)==1);
%现存的树=树-被烧毁的树+新生的树
veg = 2*(veg==2) - ( (veg==2) & (sum>0 | (rand(n,n)<Plight)) ) + 2*((veg==0) & rand(n,n)<Pgrowth) ;
set(imh, 'cdata', cat(3,(veg==1),(veg==2),zeros(n)) )%画图
drawnow
end