白冥 发表于 2025-2-1 17:59:45

【Python】【原创】元胞自动机与动态扩散模型

本帖最后由 白冥 于 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):
      state = cell.get_state()
      coordinate = cell.get_coordinate()
      burning_neighbors = sum()
      tree_neighbors = sum()
      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 =
      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):
      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( > y])
      north_south_neighbors_reverse = sum( < y])
      east_west_neighbors = sum( != x])
      up_down_neighbors = sum( != 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):
      state = cell.get_state()
      coordinate = cell.get_coordinate()
      neighbors = sum()
    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):
      state = cell.get_state()
      coord = cell.get_coordinate()
      e_head_neighbors = sum()
      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


rayyyyy 发表于 2025-6-27 10:14:57

本可终于完成python大作业了,现在对大佬教的python知识充满了兴趣惹

zhnlwwdzz 发表于 2025-3-2 13:52:09

大神又来传授知识咯,遗憾的是此刻我心里只想着些旖旎之事。

zhuovboyan 发表于 2025-2-9 21:10:46

0-0 每天的长脑子每日任务已经完成jpg 不明觉厉的时候只要默默评分就好jpg

Sam30 发表于 2025-2-7 21:50:22

感覺也是一些比較特別的模型呢, 论坛中比較少看的類型哦:loveliness:

大河内太 发表于 2025-2-6 04:31:27

可以计算母0包围猛1的情境模拟吗.JPG{:6_169:}

归北溟 发表于 2025-2-3 22:24:43

以前看《命运2》背景设定的时候接触过生命游戏,感觉还挺有意思的

旋转菠萝07 发表于 2025-2-1 20:50:59

不明觉厉……Python居然还能干这种事情?我只了解过数据处理,物联网还有绘图什么的说……

Yang羊 发表于 2025-2-1 20:50:43

大佬又来分享知识了,可惜本可现在心中只有瑟瑟

娱乐法师火布偶 发表于 2025-2-1 19:04:56

这个模型在模拟领域的应用肯定是很广泛了

SweetUncle 发表于 2025-2-1 18:10:32

{:6_194:}楼楼又来分享学习成果噜,不明觉厉只能说有点吊喵

coldwolf 发表于 2025-2-1 18:06:51

哇,是大佬。
话说原来论坛还会分享这些嘛:o
页: [1]
查看完整版本: 【Python】【原创】元胞自动机与动态扩散模型