定义
元胞自动机(Cellular Automata,CA)是一种时空离散的局部动力学模型,是研究复杂系统的一种典型方法,特别适合用于空间复杂系统的时空动态模拟研究。 元胞自动机不是由严格定义的物理方程或函数确定,而是用一系列模型构造的规则构成。凡是满足这些规则的模型都可以算作是元胞自动机模型。因此,元胞自动机是一类模型的总称,或者说是一个方法框架。
元胞自动机最基本的组成: 元胞、元胞空间、邻居及规则四部分。简单讲,元胞自动机可以视为由一个元胞空间和定义于该空间的变换函数所组成。
构成
1. 元胞
元胞自动机的最基本组成部分。它分布在离散的一维、二维或多维欧几里德空间的晶格点上。
2. 状态
状态可以是{0,1}的二进制形式,或是{s0,s1,s2,…,si}整数形式的离散集。严格意义上,元胞只能有一个状态变量,但在实际应用中,往往将其进行扩展。
3.元胞空间
元胞所分布在的空间网点集合就是元胞空间
三角网格
拥有较少的邻居数目,这在某些时候很有用。缺点是计算机的表达与显示不方便。
四边形网格
直观简单,特别适合于计算机环境下进行表达显示。
六边形网格
能较好的模拟各向同性的现象,因此,模型能更加自然而真实。其缺点同正三角网格一样,在表达显示上较为困难和复杂。
边界条件
理论上,元胞空间在各个维向上是无限延展的。实际应用过程中,无法在计算机上实现这一理想条件。
构形
在某个时刻,在元胞空间上所有元胞状态的空间分布组合。在数学上,它通常可以表示为一个多维的整数矩阵。
4.邻居
邻居、元胞和元胞空间只表示了系统的静态成分,为了将动态引入系统,必须加入演化规则。这些规则是定义在局部空间范围内的,即一个元胞下一时刻的状态决定于本身的状态和它的邻居元胞的状态。因此,在指定规则之前,必须定义一定的邻居规则,明确哪些元胞属于该元胞的邻居。 一维元胞自动机中,通常以半径r来确定邻居,距离一个元胞r内的所有元胞都属于该元胞的邻居。 二维元胞自动机的邻居定义较为复杂,但通常有以下几种(以正方形网格为例 )
5.规则
根据元胞当前状态及其邻居状况确定下一时刻该元胞状态的动力学函数,简单讲,就是状态转移函数。这个函数构造了一种简单的离散的时间和空间范围的局部物理成分。状态的变化可以由状态转移函数表示:
f: stt+1=f (sit, ……,stN) stN为t时刻的邻居状态组合。
6.时间
元胞自动机是一个动态系统,它在时间维上的变化是离散的,即时间t是一个整数值,而且连续且等间距。在上述转换函数中,一个元胞在t+1时刻的状态只直接决定于t 时刻的该元胞及其邻居的状态。
元胞自动机的基本特征
离散性:元胞自动机是高度离散的。它不仅仅空间离散时间离散,而且在函数值,即元胞的状态值也是离散的。
动力学演化的同步性:元胞自动机具有利用简单的,局部规则的和离散的方法,描述复杂的,全部的和连续系统的能力。
相互作用的局部性:元胞自动机的规则是局部的,而动力学行为规则是全局的,在模拟的过程中,具体的演化过程也是局部的,即仅同周围的元胞有关系。
Wolfram将元胞自动机的演化行为归纳为四大类:
I、平稳型(homogeneous):自任何初始状态开始,经过一定时间演化后,经过若干步运算便停留在一个固定的状态。
II、周期型(periodic):经过一定时间演化后,在几种状态之间周期循环。
III、混沌型(chaos):自任何初始状态开始,经过一定时间演化后,处于一种完全无序随机的状态,几乎找不到任何规律。
IV、复杂型(edge of chaos):在演化的过程中可能产生复杂的结构,这种结构既不是完全的随机混乱,又没有固定的周期和状态。
稳定型:当其初始条件为中心一个元胞状态为生时,在经过有限步演化后生的元胞比率趋于平稳.
周期型 :当其在初始条件为中心一个元胞状态为生时,在经过有限步演化后生的元胞比率趋于某一周期性的变化。
复杂型 :不属于以上两种类型的统称复杂型,即其动态统计图是无规则波动的曲线。
例题
假设有一个二维网格,每个格子可以表示一个城市的街区。每个街区可以被标记为两种状态之一:健康(H)或感染(I)。感染状态可以传播给相邻的健康街区。我们的目标是模拟这种感染过程,并预测最终有多少街区会感染。
- 感染只能从感染状态传播给健康状态。
- 每个街区在每一时间步都会更新其状态。
- 感染不会在时间步之间消失。
import numpy as np
import matplotlib.pyplot as plt
# 初始化网格
n = 100 # 网格大小
grid = np.zeros((n, n))
grid[n // 2, n // 2] = 1 # 初始感染点
# 定义传播规则
def update(grid):
new_grid = np.zeros((n, n))
for i in range(n):
for j in range(n):
if grid[i, j] == 1: # 感染状态
if j > 0 and grid[i, j - 1] == 0: # 左方
new_grid[i, j - 1] = 1
if j < n - 1 and grid[i, j + 1] == 0: # 右方
new_grid[i, j + 1] = 1
if i > 0 and grid[i - 1, j] == 0: # 上方
new_grid[i - 1, j] = 1
if i < n - 1 and grid[i + 1, j] == 0: # 下方
new_grid[i + 1, j] = 1
elif grid[i, j] == 0: # 健康状态
if j > 0 and grid[i, j - 1] == 1: # 左方
new_grid[i, j - 1] = 1
if j < n - 1 and grid[i, j + 1] == 1: # 右方
new_grid[i, j + 1] = 1
if i > 0 and grid[i - 1, j] == 1: # 上方
new_grid[i - 1, j] = 1
if i < n - 1 and grid[i + 1, j] == 1: # 下方
new_grid[i + 1, j] = 1
return new_grid
# 模拟过程
for t in range(100):
grid = update(grid)
plt.imshow(grid, cmap='gray')
plt.pause(0.05)
plt.clf()
plt.show()
首先,我们定义了一个100x100的网格,并用np.zeros
函数初始化为全零。然后,我们在网格的中心放置了一个感染点。
接着,update
函数定义了感染状态的传播规则。对于每个网格点,如果它是感染状态(值为1),它会尝试将其状态传播给周围的健康状态网格点(值为0)。同样,如果一个网格点是健康状态,它也会尝试将其状态更新为感染状态,如果其相邻的网格点是感染状态。
然后,我们使用一个循环来模拟感染过程,其中update
函数在每个时间步被调用,以更新网格的状态。使用matplotlib
库,我们绘制了感染过程的动画,其中plt.imshow
函数用于显示网格的当前状态,而plt.pause
函数用于暂停绘图,以便我们可以看到感染如何传播。
最后,我们使用plt.show()
函数来显示模拟的最终状态。
这个代码是一个基本的元胞自动机模型,用于模拟二维网格中的感染过程。在实际应用中,我们可能需要根据具体问题的要求调整模型参数和传播规则。
运行结果展示