元胞自動機理論
許多複雜的問題都可以通過元胞自動機來建立模型,元胞自動機實質上是定義在一個具有離散、有限狀態的元胞組成的元胞空間上,並按照一定的局部規則,在離散的時間維度上演化的動力學系統。
元胞又可稱爲單元、細胞,是元胞自動機的最基本的組成部分。
元胞具有以下特點:
1)元胞自動機最基本的單元。
2)元胞有記憶貯存狀態的功能。
3)所有元胞狀態都按照元胞規則不斷更新。
演化規則
中心元胞的下一個狀態由中心元胞的當前狀態和其鄰居的當前狀態按照一定的規則確定。
對於這個專題,主要研究了兩個問題,來學習元胞自動機,第一、森林火災的模擬,第二、單車道交通流的模擬。
對於森林火災的模擬:
森林火災的元胞自動機模型有三種狀態:空位,燃燒着的樹木及樹木。則某元胞下一時刻狀態由該時刻本身的狀態和周圍四個鄰居的狀態以一定的規則確定,規則如下:
1)如果某樹木元胞的4個鄰居有燃燒着的,那麼該元胞下一時刻的狀態是燃燒着的。
2)一個燃燒着的元胞在下一時刻變成空位。
3)所有樹木元胞以一個低概率開始燃燒(模擬閃電引起的火災)
4)所有空元胞以一個低概率變成樹木(以模擬新的樹木的生長)
Matlab代碼:
close;
clear;
clc;
n = 300; %元胞矩陣大小
Plight = 0.000001; Pgrowth = 0.001;
UL = [n 1:n-1];
DR = [2:n 1];
veg = zeros(n,n); %初始化
% The value of veg:
% empty == 0
% burning == 1
% green == 2
imh = image(cat(3,veg,veg,veg));
m=annotation('textbox',[0.1,0.1,0.1,0.1],'LineStyle','-','LineWidth',1,'String','123');
for i = 1:100000
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);
a=find(veg==2);
b=find(veg==1);
aa=length(a);
bb=length(b);
shu(i)=aa;
fire(i)=bb*30;
if (bb>=0&&bb<=10)
str1='森林正常';
elseif (bb>10&&bb<=100)
str1='火災發展';
elseif (bb>100)
str1='森林大火';
end
if ((aa>48000)||(bb>=10))
str2='火災預警:紅色預警';
elseif (aa>42000&&aa<=48000)
str2='火災預警:黃色預警';
elseif (aa>35000&&aa<=42000)
str2='火災預警:藍色預警';
elseif (aa>=0&&aa<=35000)
str2='火災預警:安全';
end
str=[str1 10 str2];
set(imh, 'cdata', cat(3, (veg == 1), (veg == 2), zeros(n)) )
drawnow
figure(2)
delete(m)
plot(shu);
hold on
plot(fire);
legend(['綠樹的數量',num2str(aa)],['火的數量',num2str(bb)]);
title(['時間T=',num2str(i),'天']);
m=annotation('textbox',[0.15,0.8,0.1,0.1],'LineStyle','-','LineWidth',1,'String',str);
hold off
% pause(0.0001)
end
運行截圖:
matlab代碼:
clc
clear;
%build the GUI
%define the plot button
plotbutton=uicontrol('style','pushbutton','string','Run', 'fontsize',12,'position',[100,400,50,20],'callback','run=1;');
%define the stop button
erasebutton=uicontrol('style','pushbutton','string','Stop','fontsize',12,'position',[200,400,50,20],'callback','freeze=1;');
%define the Quit button
quitbutton=uicontrol('style','pushbutton','string','Quit','fontsize',12,'position',[300,400,50,20],'callback','stop=1;close;');
number=uicontrol('style','text','string','1','fontsize',12,'position',[20,400,50,20]);
%CAsetup
n=1000; %數據初始化
z=zeros(1,n); %元胞個數
z=roadstart(z,200); %道路狀態初始化,路段上隨機分佈200輛
cells=z;
vmax=5; %最大速度
v=speedstart(cells,vmax); %速度初始化x=1; %記錄速度和車輛位置
x=1;
memor_cells=zeros(3600,n);
memor_v=zeros(3600,n);
imh=imshow(cells); %初始化圖像白色有車,黑色空元胞
set(imh,'erasemode','none')
axis equal
axis tight
stop=0; %wait for a quit button push
run=0; %wait for a draw
freeze=0; %wait for a freeze (凍結)
while (stop==0 && x<1102)
if(run==1)
%邊界條件處理,搜素首末車,控制進出,使用開口條件
a=searchleadcar(cells);
b=searchlastcar(cells);
% [cells,v]=border_control(cells,a,b,v,vmax);
i=searchleadcar(cells); %搜索首車位置
for j=1:i
if (i-j+1==n)
[z,v]=leadcarupdate(z,v);
continue;
else
%==========================加速、減速、隨機慢化
if cells(i-j+1)==0 %判斷當前位置是否非空
continue;
else
v(i-j+1)=min(v(i-j+1)+1,vmax); %加速
%=======================減速
k=searchfrontcar((i-j+1),cells); %搜素前方首個非空元胞位置
if(k==0) %確定與前車之間的元胞數
d=n-(i-j+1);
else
d=k-(i-j+1)-1;
end
v(i-j+1)=min(v(i-j+1),d);%減速
%隨機慢化
v(i-j+1)=randslow(v(i-j+1));
new_v=v(i-j+1);
%更新車輛位置
z(i-j+1)=0;
z(i-j+1+new_v)=1;
%更新速度
v(i-j+1)=0;
v(i-j+1+new_v)=new_v;
end
end
end
cells=z;
memor_cells(x,:)=cells; %記錄速度和車輛位置
memor_v(x,:)=v;
x=x+1;
set(imh,'cdata',cells) %更新圖像
%update the step number diaplay
pause(0.0001);
stepnumber=1+str2num(get(number,'string'));
set(number,'string',num2str(stepnumber))
end
if (freeze==1)
run=0;
freeze=0;
end
drawnow
end
figure(2)
for l=1:1:200
for k=500:1:1000
if memor_cells(l,k)>0
plot(k,l,'k.');
hold on;
end
end
end
xlabel('空間位置');
ylabel('時間(s)');
title('時空圖');
for i=1:1:500
density(i)=sum(memor_cells(i,:)>0)/1000;
flow(i)=sum(memor_v(i,:))/1000;
end
figure(3)
plot(density,flow,'k.');
title('流量密度圖')
xlabel('density')
ylabel('flow')
% 函數: speedstart.m程序代碼
function [v_matixcells]=speedstart(matrix_cells,vmax)
%道路初始狀態車輛速度初始化
v_matixcells=zeros(1,length(matrix_cells));
for i=1:length(matrix_cells)
if matrix_cells(i)~=0
v_matixcells(i)=round(vmax* rand(1));
end
end
end
%函數: searchleadcar.m程序代碼
function [location_leadcar]=searchleadcar(matrix_cells)
i=length(matrix_cells);
for j=1:i
if matrix_cells(i-j+1)~=0
location_leadcar=i-j+1;
break;
else
location_leadcar=0;
end
end
end
%函數: leadcarupdate.m程序代碼
function [new_matrix_cells,new_v]=leadcarupdate(matrix_cells,v)
%第一輛車更新規則
n=length(matrix_cells);
if v(n)~=0
matrix_cells(n)=0;
v(n)=0;
end
new_matrix_cells=matrix_cells;
new_v=v;
end
%函數: randslow.m程序代碼
function[new_v]=randslow(v)
p=0.3;%慢化概率
rand('state',sum(100*clock)*rand(1));
p_rand=rand; %產生隨機概率
if p_rand<=p
v=max(v-1,0);
end
new_v=v;
end
%函數: roadstart.m 程序代碼
function [matrix_cells_start]=roadstart(matrix_cells,n)
%道路上的車輛初始化狀態,元胞矩陣隨機爲0或1, matrix_cells 初始矩陣,n初始車輛數
k=length(matrix_cells);
z=round(k*rand(1,n));
for i=1:n
j=z(i);
if j==0
matrix_cells(j)=0;
else
matrix_cells(j)=1;
end
end
matrix_cells_start=matrix_cells;
end
% 函數:searchfrontcar.m 程序代碼
function [location_frontcar]=searchfrontcar(current_location,matrix_cells)
i=length(matrix_cells);
if current_location==i
location_frontcar=0;
else
for j=current_location+1:i
if matrix_cells(j)~=0
location_frontcar=j;
break;
else
location_frontcar=0;
end
end
end
end
%函數: searchlastcar.m程序代碼
function [location_lastcar]=searchlastcar(matrix_cells)
%搜索尾車位置
for i=1:length(matrix_cells)
if matrix_cells(i)~=0
location_lastcar=i;
break;
else %如果路上無車,則空元胞數設定爲道路長度
location_lastcar=length(matrix_cells );
end
end
end
運行結果:
參考文獻:
[1] CSDN. MATLAB演示元胞自動機算法.
https://blog.csdn.net/qq_40287093/article/details/88095531.2019.8.3. 14:40
[2]百度文庫.2014美賽NaSch模型.
https://wenku.baidu.com/view/9047de71e45c3b3567ec8b66.html.2019.8.3.14:42
[3]葉冬,樊鐳.一維單車道交通流元胞自動機模型綜述[J].物聯網技術,2013,3(05):23-25.