GameMale
登陆 / 注册 搜索

USERCENTER

SEARCHSITE

搜索

查看: 1348|回复: 10
收起左侧

[技术交流] 【Python】【原创】元胞自动机与动态扩散模型

[复制链接] |关注本帖

邪恶的面具海盗弯钩神秘的红茶冒险用绷带魔法石碑箭术卷轴质量效应三部曲

     楼主| 白冥 发表于 2025-2-1 17:59:45 | 显示全部楼层 |阅读模式 <
    本帖最后由 白冥 于 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%的树木。若森林某处出现一棵正在燃烧的树,模拟火灾的形势。


    1. if __name__ == "__main__":
    2.     from random import random
    3.     from random import choice
    4.    
    5.     def forest_fire(cell:Cell, neighbors: List[Cell]):
    6.         state = cell.get_state()
    7.         coordinate = cell.get_coordinate()
    8.         burning_neighbors = sum([1 for n in neighbors if n.state == "burning"])
    9.         tree_neighbors = sum([1 for n in neighbors if n.state == "tree"])
    10.         if state == "tree" and burning_neighbors>0:
    11.             return Cell("burning",*coordinate)
    12.         elif state == "burning" and burning_neighbors<=3 and tree_neighbors ==0:
    13.             return Cell("burnt",*coordinate)
    14.         elif state == "burning" and burning_neighbors>3:
    15.             if random()<0.25:
    16.                 return Cell("burning",*coordinate)
    17.             else:
    18.                 return Cell("burnt",*coordinate)
    19.         else:
    20.             return cell

    21.     def forest_fire_main():
    22.         L = Space()
    23.         forest_size = (256,256)
    24.         status = ["empty", "tree", "burning", "burnt"]
    25.         d = 2
    26.         S = Status(default="empty", *status)
    27.         N = Neighborhood(*forest_size)
    28.         f = Rule(S, forest_fire)
    29.         forest_fire_ca = CA(L, d, S, N,f)
    30.         cells=[]
    31.         for i in range(256):
    32.             for j in range(256):
    33.                 if random()<0.78:
    34.                     cells.append(Cell("tree",*(i,j)))
    35.                 else:
    36.                     cells.append(Cell("empty",*(i,j)))
    37.         trees = [cell for cell in cells if cell.state == "tree"]
    38.         tree_num = len(trees)
    39.         tree = choice(trees)
    40.         coord=tree.get_coordinate()
    41.         cells.remove(cells.index(tree))
    42.         cells.append(Cell("burning",tuple(coord)))
    43.         forest_fire_ca.evolution(cells,100)

    44.     forest_fire_main()
    复制代码

    示例2-核污染扩散      
            背景:某处东西方向长900,南北方向宽600,深度为300的海域,存在从南向北的洋流。若海面东侧边缘某处发生核泄漏,模拟核污染的扩散形势。


    1. if __name__ == "__main__":
    2.     from random import random
    3.    
    4.     def pollution_spread(cell: Cell, neighbors: List[Cell]):
    5.         state = cell.get_state()
    6.         coordinate = cell.get_coordinate()
    7.         x, y, z = coordinate
    8.         current_speed = {"north_south": 0.5, "east_west": 0.25, "up_down": 0.1}
    9.         north_south_neighbors = sum([1 for n in neighbors if n.get_state() == "polluted" and n.get_coordinate()[1] > y])
    10.         north_south_neighbors_reverse = sum([1 for n in neighbors if n.get_state() == "polluted" and n.get_coordinate()[1] < y])
    11.         east_west_neighbors = sum([1 for n in neighbors if n.get_state() == "polluted" and n.get_coordinate()[0] != x])
    12.         up_down_neighbors = sum([1 for n in neighbors if n.get_state() == "polluted" and n.get_coordinate()[2] != z])
    13.         if state == "clean":
    14.             if north_south_neighbors > north_south_neighbors_reverse:
    15.                 if random() < current_speed["north_south"]:
    16.                     return Cell("polluted", *coordinate)
    17.             elif north_south_neighbors_reverse > north_south_neighbors:
    18.                 if random() < current_speed["north_south"] / 10:
    19.                     return Cell("polluted", *coordinate)
    20.             elif east_west_neighbors > 0:
    21.                 if random() < current_speed["east_west"]:
    22.                     return Cell("polluted", *coordinate)
    23.             elif up_down_neighbors > 0:
    24.                 if random() < current_speed["up_down"]:
    25.                     return Cell("polluted", *coordinate)
    26.         return cell
    27.    
    28.     def pollution_simulation():
    29.         L = Space()
    30.         ocean_size = (900, 600, 300)
    31.         status = ["clean", "polluted"]
    32.         d = 3
    33.         S = Status(default="clean", *status)
    34.         N = Neighborhood(*ocean_size)
    35.         f = Rule(S, pollution_spread)
    36.         ocean_ca = CA(L, d, S, N, f)
    37.         cells = []
    38.         for x in range(900):
    39.             for y in range(600):
    40.                 for z in range(300):
    41.                     cells.append(Cell("empty", x, y, z))
    42.         source = Cell("polluted", 0, 300, 0)
    43.         cells.remove(cells.index(source))
    44.         cells.append(source)
    45.         ocean_ca.evolution(cells, 100)
    46.         
    47.     pollution_simulation()
    复制代码

    康威的生命游戏      
            背景:事实上,元胞自动机在冯诺依曼研发之初并不受人们注视,真正把元胞自动机带到众人面前的,得归功于一个游戏。那就是剑桥大学数学教授约翰·何顿·康威开发的一款名叫“生命游戏”的游戏,由美国益智数学大师马丁·加德纳发现并刊登在《科学美国人》杂志上,元胞自动机才真正引起科学家的注意。


            生命游戏中,对于任意细胞,规则如下:
            (1)细胞有两种状态,生和死。
            (2)一个细胞周围只有一个细胞或者没有细胞,这个细胞就会抑郁而死。
            (3)一个细胞周围有超过三个细胞,这个细胞就会被挤死。
            (4)对于一个空格,如果它周围恰好有三个细胞,就会繁殖一个细胞。

    1. if __name__ == "__main__":
    2.    
    3.     def game_of_life(cell:Cell, neighbors: List[Cell]):
    4.         state = cell.get_state()
    5.         coordinate = cell.get_coordinate()
    6.         neighbors = sum([1 for n in neighbors if n.state == "alive"])
    7.     if state == "alive":
    8.         if neighbors<2:
    9.             return Cell("dead",*coordinate)
    10.         elif neighbors >4:
    11.             return Cell("dead",*coordinate)
    12.     elif state == "dead":
    13.         if neighbors ==3:
    14.             return Cell("alive",*coordinate)
    15.     else:
    16.         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





    1. if __name__ == "__main__":
    2.    
    3.     def wire_rule(cell:Cell, neighbors:List[Cell]):
    4.         state = cell.get_state()
    5.         coord = cell.get_coordinate()
    6.         e_head_neighbors = sum([1 for n in neighbors if n.get_state() == "e_head"])
    7.         if state == "e_tail":
    8.             return Cell("conductor", *coord)
    9.         if state == "e_head":
    10.             return Cell("e_tail", *coord)
    11.         if state == "conductor" and 1 <= e_head_neighbors <= 2:
    12.             return Cell("e_head", *coord)
    13.         return cell
    复制代码



    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x

    评分

    参与人数 3血液 +2 追随 +2 收起 理由
    zhuovboyan + 2
    归北溟 + 1
    SweetUncle + 1 斯国一

    查看全部评分

    回复

    使用道具 举报

    男色时代达拉然骑兽之子月亮提灯夏之歌最终幻想XVI荒野大镖客:救赎 II黑神话:悟空莱因哈特·威尔海姆

      zhnlwwdzz 发表于 2025-3-2 13:52:09 | 显示全部楼层 <
      回复

      举报

      『厢庭望远』胡子贴纸万众瞩目神奇宝贝大师球神奇宝贝图鉴『搓粉团珠』雪王的心脏肉垫手套『落樱缤纷』里昂‧S‧甘乃迪

        zhuovboyan 发表于 2025-2-9 21:10:46 | 显示全部楼层 <
        回复

        举报

        胡子贴纸

          Sam30 发表于 2025-2-7 21:50:22 | 显示全部楼层 <
          感覺也是一些比較特別的模型呢, 论坛中比較少看的類型哦
          回复

          举报

          生金蛋的鹅猫咪点唱机和你一起飞行的皮卡丘裸体克里斯保卫领土【新春限定】果体 隆新神的赐福永远的克叔凯登‧阿兰科亚瑟‧摩根

            大河内太 发表于 2025-2-6 04:31:27 | 显示全部楼层 <
            可以计算母0包围猛1的情境模拟吗.JPG
              收起(2)
            回复

            举报

            吸血魔蝠阿努比斯信徒業火死鬥自定义男从Homunculus虚空之海的鲸璀璨闪蝶『搓粉团珠』『不败之花』

              归北溟 发表于 2025-2-3 22:24:43 | 显示全部楼层 <
              以前看《命运2》背景设定的时候接触过生命游戏,感觉还挺有意思的
              回复

              举报

              GM論壇進階勛章牧羊人【新手友好】昆進寻觅香喷喷的烤鸡青鸾蛋眼镜蛇图腾猎鹰图腾

                旋转菠萝07 发表于 2025-2-1 20:50:59 | 显示全部楼层 <
                不明觉厉……Python居然还能干这种事情?我只了解过数据处理,物联网还有绘图什么的说……
                  收起(3)
                回复

                举报

                夏日柯基自定义男从Homunculus璀璨闪蝶裸体克里斯吃饱金币的Doge永亘环青鸾林中松鼠

                  Yang羊 发表于 2025-2-1 20:50:43 | 显示全部楼层 <
                  大佬又来分享知识了,可惜本可现在心中只有瑟瑟
                  回复

                  举报

                  胡子贴纸裸体克里斯虚空之海的鲸黄粱一梦『厢庭望远』【新春限定】果体 隆都市:天际线2永远的克叔業火死鬥实现梦想

                    娱乐法师火布偶 发表于 2025-2-1 19:04:56 | 显示全部楼层 <
                    回复

                    举报

                    胡子贴纸远行『搓粉团珠』守卫: 坚守眼位邦尼尼吸血魔蝠苏格兰圆脸胖鸡和你一起飞行的皮卡丘兴奋的小伯月影狼

                      SweetUncle 发表于 2025-2-1 18:10:32 | 显示全部楼层 <
                      楼楼又来分享学习成果噜,不明觉厉只能说有点吊喵
                      回复

                      举报

                      闪耀的赫尔墨斯之杖神奇宝贝大师球璀璨闪蝶自定义男从Homunculus恶魔城石鬼面驯化黑龙幼崽

                        coldwolf 发表于 2025-2-1 18:06:51 | 显示全部楼层 <
                        哇,是大佬。
                        话说原来论坛还会分享这些嘛
                        回复

                        举报

                        您需要登录后才可以回帖 登录 | 立即注册

                        本版积分规则

                        关闭

                        站长公告

                        【抵制账号违规交易】
                        【抵制账号违规交易】
                        请珍惜自己的论坛账号! 本BBS论坛禁止任何形式的账号买卖, 本站亦没有任何账号贩售交易途径!经查证账号为购买/或无法证明账号归属的用户将会被永久封禁。

                        查看 »

                        文字版|手机版|小黑屋|GameMale

                        GMT+8, 2025-5-29 09:19 , Processed in 0.107253 second(s), 94 queries , Redis On.

                        Copyright © 2013-2025 GameMale

                        All Rights Reserved.

                        快速回复 返回列表