Python探索生命起源 matplotlib细胞自动机动画演示


Posted in Python onApril 21, 2022

维基百科上有个有意思的话题叫细胞自动机:https://en.wikipedia.org/wiki/Cellular_automaton

在20世纪70年代,一种名为生命游戏的二维细胞自动机变得广为人知,特别是在早期的计算机界。由约翰 · 康威发明,马丁 · 加德纳在《科学美国人》的一篇文章中推广,其规则如下:

  1. Any live cell with fewer than two live neighbours dies, as if caused by underpopulation.
  2. Any live cell with two or three live neighbours lives on to the next generation.
  3. Any live cell with more than three live neighbours dies, as if by overpopulation.
  4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

总结就是:任何活细胞在有两到三个活邻居时能活到下一代,否则死亡。任何有三个活邻居的死细胞会变成活细胞,表示繁殖。

在Conway’s Game of Life中,展示了几种初始状态:

Python探索生命起源 matplotlib细胞自动机动画演示

下面我们用python来模拟,首先尝试表示Beacon:

import numpy as np
import matplotlib.pyplot as plt
universe = np.zeros((6, 6), "byte")
# Beacon
universe[1:3, 1:3] = 1
universe[3:5, 3:5] = 1
print(universe)
im = plt.imshow(universe, cmap="binary")
[[0 0 0 0 0 0]
 [0 1 1 0 0 0]
 [0 1 1 0 0 0]
 [0 0 0 1 1 0]
 [0 0 0 1 1 0]
 [0 0 0 0 0 0]]

Python探索生命起源 matplotlib细胞自动机动画演示

可以看到已经成功的打印出了Beacon的形状,下面我们继续编写细胞自动机的演化规则:

def cellular_auto(universe):
    universe_new = universe.copy()
    h, w = universe.shape
    for y in range(h):
        for x in range(w):
            neighbor_num = universe[x-1:x+2, y-1:y+2].sum()-universe[x, y]
            # 任何有三个活邻居的死细胞都变成了活细胞,繁殖一样。
            if universe[x, y] == 0 and neighbor_num == 3:
                universe_new[x, y] = 1
            # 任何有两到三个活邻居的活细胞都能活到下一代,否则就会死亡。
            if universe[x, y] == 1 and neighbor_num not in (2, 3):
                universe_new[x, y] = 0
    return universe_new
universe = cellular_auto(universe)
print(universe)
plt.axis("off")
im = plt.imshow(universe, cmap="binary")
[[0 0 0 0 0 0]
 [0 1 1 0 0 0]
 [0 1 0 0 0 0]
 [0 0 0 0 1 0]
 [0 0 0 1 1 0]
 [0 0 0 0 0 0]]

Python探索生命起源 matplotlib细胞自动机动画演示

ArtistAnimation动画

基于此我们可以制作matplotlib的动画,下面直接将Blinker、Toad、Beacon都放上去:

from matplotlib import animation
import numpy as np
import matplotlib.pyplot as plt
%matplotlib notebook

def cellular_auto(universe):
    universe_new = universe.copy()
    h, w = universe.shape
    for y in range(h):
        for x in range(w):
            neighbor_num = universe[x-1:x+2, y-1:y+2].sum()-universe[x, y]
            # 任何有三个活邻居的死细胞都变成了活细胞,繁殖一样。
            if universe[x, y] == 0 and neighbor_num == 3:
                universe_new[x, y] = 1
            # 任何有两到三个活邻居的活细胞都能活到下一代,否则就会死亡。
            if universe[x, y] == 1 and neighbor_num not in (2, 3):
                universe_new[x, y] = 0
    return universe_new
universe = np.zeros((12, 12), "byte")
# Blinker
universe[2, 1:4] = 1
# Beacon
universe[4:6, 5:7] = 1
universe[6:8, 7:9] = 1
# Toad
universe[8, 2:5] = 1
universe[9, 1:4] = 1
fig = plt.figure()
plt.axis("off")
im = plt.imshow(universe, cmap="binary")
frame = []
for _ in range(2):
    frame.append((plt.imshow(universe, cmap="binary"),))
    universe = cellular_auto(universe)
animation.ArtistAnimation(fig, frame, interval=500, blit=True)

Python探索生命起源 matplotlib细胞自动机动画演示

然后我们画一下Pulsar:

# Pulsar
universe = np.zeros((17, 17), "byte")
universe[[2, 7, 9, 14], 4:7] = 1
universe[[2, 7, 9, 14], 10:13] = 1
universe[4:7, [2, 7, 9, 14]] = 1
universe[10:13, [2, 7, 9, 14]] = 1
fig = plt.figure()
plt.axis("off")
im = plt.imshow(universe, cmap="binary")
frame = []
for _ in range(3):
    frame.append((plt.imshow(universe, cmap="binary"),))
    universe = cellular_auto(universe)
animation.ArtistAnimation(fig, frame, interval=500, blit=True)

Python探索生命起源 matplotlib细胞自动机动画演示

FuncAnimation动画

另一种创建matplotlib动画的方法是使用FuncAnimation,完整代码:

from matplotlib import animation
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import HTML
# %matplotlib notebook

def cellular_auto(universe):
    universe_new = universe.copy()
    h, w = universe.shape
    for y in range(h):
        for x in range(w):
            neighbor_num = universe[x-1:x+2, y-1:y+2].sum()-universe[x, y]
            # 任何有三个活邻居的死细胞都变成了活细胞,繁殖一样。
            if universe[x, y] == 0 and neighbor_num == 3:
                universe_new[x, y] = 1
            # 任何有两到三个活邻居的活细胞都能活到下一代,否则就会死亡。
            if universe[x, y] == 1 and neighbor_num not in (2, 3):
                universe_new[x, y] = 0
    return universe_new
def update(i=0):
    global universe
    im.set_data(universe)
    universe = cellular_auto(universe)
    return im,
# Pulsar
universe = np.zeros((17, 17), "byte")
universe[[2, 7, 9, 14], 4:7] = 1
universe[[2, 7, 9, 14], 10:13] = 1
universe[4:7, [2, 7, 9, 14]] = 1
universe[10:13, [2, 7, 9, 14]] = 1
fig = plt.figure()
plt.axis("off")
im = plt.imshow(universe, cmap="binary")
plt.show()
anim = animation.FuncAnimation(
    fig, update, frames=3, interval=500, blit=True)
HTML(anim.to_jshtml())

Python探索生命起源 matplotlib细胞自动机动画演示

这种动画生成速度较慢,好处是可以导出html文件:

with open("out.html", "w") as f:
    f.write(anim.to_jshtml())

还可以保存MP4视频:

anim.save("out.mp4")

或gif动画:

anim.save("out.gif")

注意:保存MP4视频或GIF动画,需要事先将ffmpeg配置到环境变量中

ffmpeg下载地址:

链接: https://pan.baidu.com/s/1aioB_BwpKb6LxJs26HbbiQ?pwd=ciui 
提取码: ciui

随机生命游戏

接下来,我们创建一个50*50的二维生命棋盘,并选取其中1500个位置作为初始活细胞点,我们看看最终生成的动画如何。

完整代码如下:

from matplotlib import animation
import numpy as np
import matplotlib.pyplot as plt
%matplotlib notebook

def cellular_auto(universe):
    universe_new = universe.copy()
    h, w = universe.shape
    for y in range(1, h-1):
        for x in range(1, w-1):
            neighbor_num = universe[x-1:x+2, y-1:y+2].sum()-universe[x, y]
            # 任何有三个活邻居的死细胞都变成了活细胞,繁殖一样。
            if universe[x, y] == 0 and neighbor_num == 3:
                universe_new[x, y] = 1
            # 任何有两到三个活邻居的活细胞都能活到下一代,否则就会死亡。
            if universe[x, y] == 1 and neighbor_num not in (2, 3):
                universe_new[x, y] = 0
    # 边缘置零
    universe[[0, -1]] = 0
    universe[:, [0, -1]] = 0
    return universe_new
boardsize, pad = 50, 2
universe = np.zeros((boardsize+pad, boardsize+pad), "byte")
# 随机选取1500个点作为初始活细胞
for i in range(1500):
    x, y = np.random.randint(1, boardsize+1, 2)
    universe[y, x] = 1
    
fig = plt.figure()
plt.axis("off")
im = plt.imshow(universe, cmap="binary")
frame = []
for _ in range(200):
    frame.append((plt.imshow(universe, cmap="binary"),))
    universe = cellular_auto(universe)
animation.ArtistAnimation(fig, frame, interval=50, blit=True)

Python探索生命起源 matplotlib细胞自动机动画演示

到此这篇关于Python实现的matplotlib动画演示之细胞自动机的文章就介绍到这了!


Tags in this post...

Python 相关文章推荐
python简单获取本机计算机名和IP地址的方法
Jun 03 Python
Python利用前序和中序遍历结果重建二叉树的方法
Apr 27 Python
Python实现对字符串的加密解密方法示例
Apr 29 Python
python爬虫使用cookie登录详解
Dec 27 Python
PyQt5每天必学之带有标签的复选框
Apr 19 Python
解决Django migrate No changes detected 不能创建表的问题
May 27 Python
Django使用AJAX调用自己写的API接口的方法
Mar 06 Python
Python 通过打码平台实现验证码的实现
May 13 Python
Python面向对象之类的封装操作示例
Jun 08 Python
Python一键安装全部依赖包的方法
Aug 12 Python
pyinstaller打包opencv和numpy程序运行错误解决
Aug 16 Python
解决python3安装pandas出错的问题
May 20 Python
使用python绘制横竖条形图
python多次执行绘制条形图
Apr 20 #Python
Python 数据可视化工具 Pyecharts 安装及应用
python画条形图的具体代码
Python中的matplotlib绘制百分比堆叠柱状图,并为每一个类别设置不同的填充图案
Apr 20 #Python
Pandas 数据编码的十种方法
Apr 20 #Python
Python读取和写入Excel数据
You might like
JAVA/JSP学习系列之六
2006/10/09 PHP
PHP正则的Unknown Modifier错误解决方法
2010/03/02 PHP
整理php防注入和XSS攻击通用过滤
2015/09/13 PHP
PHP编程实现微信企业向用户付款的方法示例
2017/07/26 PHP
JavaScript 学习笔记(十二) dom
2010/01/21 Javascript
jquery 实现表单验证功能代码(简洁)
2012/07/03 Javascript
将文本输入框内容加入表中的js代码
2013/08/18 Javascript
jQuery制作仿Mac Lion OS滚动条效果
2015/02/10 Javascript
一个php+js实时显示时间问题
2015/10/12 Javascript
angularjs创建弹出框实现拖动效果
2020/08/25 Javascript
Bootstrap CSS组件之下拉菜单(dropdown)
2016/12/17 Javascript
JavaScript登录验证基础教程
2017/11/01 Javascript
原生JS+HTML5实现跟随鼠标一起流动的粒子动画效果
2018/05/03 Javascript
对angular2中的ngfor和ngif指令嵌套实例讲解
2018/09/12 Javascript
ES6 Class中实现私有属性的一些方法总结
2019/07/08 Javascript
[08:47]DOTA2每周TOP10 精彩击杀集锦vol.6
2014/06/25 DOTA
详解Python中的__new__、__init__、__call__三个特殊方法
2016/06/02 Python
Python爬取网易云音乐热门评论
2017/03/31 Python
Python实现读取及写入csv文件的方法示例
2018/01/12 Python
Tensorflow卷积神经网络实例
2018/05/24 Python
python pandas写入excel文件的方法示例
2019/06/25 Python
为什么python比较流行
2020/06/19 Python
基于python实现计算两组数据P值
2020/07/10 Python
北美最大的零售退货翻新商:VIP Outlet
2019/11/21 全球购物
mysql的最长数据库名,表名,字段名可以是多长
2014/04/21 面试题
介绍Ibatis的核心类
2013/11/18 面试题
Java里面如何创建一个内部类的实例
2015/01/19 面试题
swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?
2013/03/30 面试题
移动通信行业实习自我鉴定
2013/09/28 职场文书
大型活动策划方案
2014/01/12 职场文书
索桥的故事教学反思
2014/02/06 职场文书
廉政承诺书
2015/01/19 职场文书
离婚被告代理词
2015/05/23 职场文书
珍爱生命主题班会
2015/08/13 职场文书
python 逐步回归算法
2021/04/06 Python
分享很少见很有用的SQL功能CORRESPONDING
2022/08/05 MySQL