|
本帖最后由 白冥 于 2025-2-4 02:32 编辑
目录
- 概述
- 安装与环境配置
- 类结构与方法
- 源代码
- 示例1-森林火灾
- 示例2-核污染扩散
- 康威的生命游戏
- Wire-World
概述
元胞自动机 (Cellular Automaton, CA),是一种离散动力学系统,由规则控制的状态单元(元胞)组成,其中的每个元胞都根据自身的状态和邻域内其他状态单元的状态来更新其状态。它是计算机科学中模拟复杂动态系统的一种方式,应用于模拟现实中的各种离散系统,例如森林火灾、生命游戏、扩散系统等。
本贴的代码均由本人写就。
安装与环境配置
本代码基于 Python 3,建议使用 Python 3.8 及以上版本。
代码中仅使用了标准库itertools, typing,无需安装额外的第三方库。
类结构与方法
CA 类
├ __init__ 方法
└ evolution 方法
Cell 类
├ __init__ 方法
├ get_state 方法
└ get_coordinate 方法
Space 类
├ __init__ 方法
├ __call__ 方法
├ _set_value 方法
├ get_value 方法
├ traverse 方法
├ _clear 方法
└ renew 方法
Status 类
├ __init__ 方法
├ in_status 方法
└ get_default 方法
Neighborhood 类
├ __init__ 方法
├ get_size 方法
├ _filter 方法
├ in_range 方法
├ moore 方法
└ get_neighbors 方法
Rule 类
├ __init__ 方法
└ apply 方法
源代码
源代码:源代码
示例1-森林火灾
背景:一片256×256的森林区域,覆盖了78%的树木。若森林某处出现一棵正在燃烧的树,模拟火灾的形势。
- if __name__ == "__main__":
- from random import random
- from random import choice
-
- def forest_fire(cell:Cell, neighbors: List[Cell]):
- state = cell.get_state()
- coordinate = cell.get_coordinate()
- burning_neighbors = sum([1 for n in neighbors if n.state == "burning"])
- tree_neighbors = sum([1 for n in neighbors if n.state == "tree"])
- if state == "tree" and burning_neighbors>0:
- return Cell("burning",*coordinate)
- elif state == "burning" and burning_neighbors<=3 and tree_neighbors ==0:
- return Cell("burnt",*coordinate)
- elif state == "burning" and burning_neighbors>3:
- if random()<0.25:
- return Cell("burning",*coordinate)
- else:
- return Cell("burnt",*coordinate)
- else:
- return cell
- def forest_fire_main():
- L = Space()
- forest_size = (256,256)
- status = ["empty", "tree", "burning", "burnt"]
- d = 2
- S = Status(default="empty", *status)
- N = Neighborhood(*forest_size)
- f = Rule(S, forest_fire)
- forest_fire_ca = CA(L, d, S, N,f)
- cells=[]
- for i in range(256):
- for j in range(256):
- if random()<0.78:
- cells.append(Cell("tree",*(i,j)))
- else:
- cells.append(Cell("empty",*(i,j)))
- trees = [cell for cell in cells if cell.state == "tree"]
- tree_num = len(trees)
- tree = choice(trees)
- coord=tree.get_coordinate()
- cells.remove(cells.index(tree))
- cells.append(Cell("burning",tuple(coord)))
- forest_fire_ca.evolution(cells,100)
- forest_fire_main()
复制代码
示例2-核污染扩散
背景:某处东西方向长900,南北方向宽600,深度为300的海域,存在从南向北的洋流。若海面东侧边缘某处发生核泄漏,模拟核污染的扩散形势。
- if __name__ == "__main__":
- from random import random
-
- def pollution_spread(cell: Cell, neighbors: List[Cell]):
- state = cell.get_state()
- coordinate = cell.get_coordinate()
- x, y, z = coordinate
- current_speed = {"north_south": 0.5, "east_west": 0.25, "up_down": 0.1}
- north_south_neighbors = sum([1 for n in neighbors if n.get_state() == "polluted" and n.get_coordinate()[1] > y])
- north_south_neighbors_reverse = sum([1 for n in neighbors if n.get_state() == "polluted" and n.get_coordinate()[1] < y])
- east_west_neighbors = sum([1 for n in neighbors if n.get_state() == "polluted" and n.get_coordinate()[0] != x])
- up_down_neighbors = sum([1 for n in neighbors if n.get_state() == "polluted" and n.get_coordinate()[2] != z])
- if state == "clean":
- if north_south_neighbors > north_south_neighbors_reverse:
- if random() < current_speed["north_south"]:
- return Cell("polluted", *coordinate)
- elif north_south_neighbors_reverse > north_south_neighbors:
- if random() < current_speed["north_south"] / 10:
- return Cell("polluted", *coordinate)
- elif east_west_neighbors > 0:
- if random() < current_speed["east_west"]:
- return Cell("polluted", *coordinate)
- elif up_down_neighbors > 0:
- if random() < current_speed["up_down"]:
- return Cell("polluted", *coordinate)
- return cell
-
- def pollution_simulation():
- L = Space()
- ocean_size = (900, 600, 300)
- status = ["clean", "polluted"]
- d = 3
- S = Status(default="clean", *status)
- N = Neighborhood(*ocean_size)
- f = Rule(S, pollution_spread)
- ocean_ca = CA(L, d, S, N, f)
- cells = []
- for x in range(900):
- for y in range(600):
- for z in range(300):
- cells.append(Cell("empty", x, y, z))
- source = Cell("polluted", 0, 300, 0)
- cells.remove(cells.index(source))
- cells.append(source)
- ocean_ca.evolution(cells, 100)
-
- pollution_simulation()
复制代码
康威的生命游戏
背景:事实上,元胞自动机在冯诺依曼研发之初并不受人们注视,真正把元胞自动机带到众人面前的,得归功于一个游戏。那就是剑桥大学数学教授约翰·何顿·康威开发的一款名叫“生命游戏”的游戏,由美国益智数学大师马丁·加德纳发现并刊登在《科学美国人》杂志上,元胞自动机才真正引起科学家的注意。
生命游戏中,对于任意细胞,规则如下:
(1)细胞有两种状态,生和死。
(2)一个细胞周围只有一个细胞或者没有细胞,这个细胞就会抑郁而死。
(3)一个细胞周围有超过三个细胞,这个细胞就会被挤死。
(4)对于一个空格,如果它周围恰好有三个细胞,就会繁殖一个细胞。
- if __name__ == "__main__":
-
- def game_of_life(cell:Cell, neighbors: List[Cell]):
- state = cell.get_state()
- coordinate = cell.get_coordinate()
- neighbors = sum([1 for n in neighbors if n.state == "alive"])
- if state == "alive":
- if neighbors<2:
- return Cell("dead",*coordinate)
- elif neighbors >4:
- return Cell("dead",*coordinate)
- elif state == "dead":
- if neighbors ==3:
- return Cell("alive",*coordinate)
- else:
- return cell
复制代码
游戏开始时,每个细胞将会随机地被设定为“生”或“死”之一的某个状态。游戏没有玩家,也没有输赢。
(滑翔机)
自从1970年马丁·加德纳在《科学美国人》杂志上介绍了这个游戏之后,它催生了数以百计的计算机程序、网站和文章,是趣味数学的常客,元胞自动机也正式成为一个重要的数学分支。
2020年,4月11日,康威死于新冠肺炎,享年83岁。
Wire-World
背景:说到元胞自动机就不得不提另外一位有趣的人,那就是布莱恩·西尔弗曼。布莱恩是益智编程的缔造者之一,也是一个元胞自动机这个概念火起来后投身研究的先驱,发明了许多经典的元胞自动机规则,其中就有我们要讲的Wire-World。
规则:
Wire-World的规则很简单,在一个“电路板”上放置“导体”,在导体上放置若干的“电子”。那么“电路板”上的细胞就有四种状态:“空”(empty)、“导体”(conductor)、“电流”(head)、“尾迹”(tail)。
empty → empty
tail → conductor
head → tail
如果相邻细胞中恰好有一个或两个head,conductor → head,否则 conductor → conductor
- if __name__ == "__main__":
-
- def wire_rule(cell:Cell, neighbors:List[Cell]):
- state = cell.get_state()
- coord = cell.get_coordinate()
- e_head_neighbors = sum([1 for n in neighbors if n.get_state() == "e_head"])
- if state == "e_tail":
- return Cell("conductor", *coord)
- if state == "e_head":
- return Cell("e_tail", *coord)
- if state == "conductor" and 1 <= e_head_neighbors <= 2:
- return Cell("e_head", *coord)
- return cell
复制代码
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
评分
-
查看全部评分
白冥
:求追随,求堕落,求血液
-
|