基于2D元胞自动机的人工生命模拟:扩散算法实现问询
2D元胞自动机分子扩散算法优化方案
当前方法的问题
你当前的实现直接遍历修改原数组,且固定传递1个分子的方式过于刚性:
- 实时修改原数组会导致后续细胞计算使用已更新的值,破坏状态同步性;
- 固定传值无法根据浓度梯度调整,若饱和细胞因“无法接收”就停止输出,会直接导致扩散停滞。
可行优化方案
1. 双数组同步更新(核心基础)
所有细胞的扩散计算必须基于同一时刻的状态,因此需要维护两个数组:
old_grid:存储当前时刻的分子分布,仅用于读取;new_grid:存储下一时刻的计算结果,初始复制old_grid的全部值。
所有计算完成后,将new_grid替换为old_grid进入下一帧迭代。
2. 梯度驱动的比例扩散(推荐)
基于细胞与邻居的浓度差分配分子,保证总数量基本守恒,且自动向均匀分布靠拢:
- 设定扩散系数
rate(如0.1,控制扩散速度,取值范围0~1); - 对每个细胞
(i,j),计算周围8个邻居的平均分子数avg_neighbor; - 浮点数版更新公式(完全守恒):
new_grid[i][j] = (1 - rate) * old_grid[i][j] + rate * avg_neighbor - 整数版(处理舍入误差):
这种方式下,饱和细胞只要分子数高于邻居,就会持续向外传递,直到浓度平衡。transfer_per_neighbor = int(old_grid[i][j] * rate / 8) # 每个邻居传递的分子数 total_transfer = transfer_per_neighbor * 8 new_grid[i][j] = old_grid[i][j] - total_transfer for (x, y) in 获取8个有效邻居坐标: if new_grid[x][y] < 饱和值: new_grid[x][y] += transfer_per_neighbor
3. 修正你的3x3卷积实现
如果想保留类似当前的传递逻辑,只需调整规则:
- 允许饱和细胞向外传递分子(饱和仅限制接收,不限制输出);
- 遍历
old_grid,对每个有分子的细胞,尝试给每个未饱和的邻居传递1个分子,直到自己无剩余或邻居都饱和:
以你给出的初始状态为例,调整后第一次迭代会变成:for i in range(grid_size): for j in range(grid_size): curr = old_grid[i][j] if curr == 0: continue neighbors = 获取8个有效邻居坐标 available_neighbors = [n for n in neighbors if new_grid[n[0]][n[1]] < 饱和值] transfer_count = min(curr, len(available_neighbors)) new_grid[i][j] -= transfer_count for (x, y) in available_neighbors[:transfer_count]: new_grid[x][y] += 1
总分子数100保持不变,后续会持续向周围扩散直到均匀。92, 1, 1 1, 1, 1 1, 1, 1
关键规则明确
- 饱和机制:仅限制细胞接收的分子数不超过饱和值,不影响细胞向外传递分子;
- 守恒保证:所有传递操作都遵循“从一个细胞减少的数量等于其他细胞增加的数量”,仅在整数舍入时产生微小误差。
内容的提问来源于stack exchange,提问作者codymanix
相关产品推荐
相关产品推荐

