python数据分析:生命游戏

来源:互联网 发布:linux配置dns解析 编辑:程序博客网 时间:2024/05/29 18:44

在学习了python的numpy库之后,了解到了细胞自动机,其中比较典型的就是生命游戏这个模型,生命游戏非常地类似之前我学习的ndarry数组对象,我将在这里对其简单的实现一下,因为初学numpy可能谬误较多,望指正。

生命游戏的简单介绍

生命游戏 (Came of Life)是J. H. Conway在20世纪60年代末设计的一种单人玩的计算机游戏(Garclner,M.,1970、1971)。他与现代的围棋游戏在某些特征上略有相似:围棋中有黑白两种棋子。生命游戏中的元胞有{“生”,”死”}两个状态 {0,1};围棋的棋盘是规则划分的网格,黑白两子在空间的分布决定双方的死活,而生命游戏也是规则划分的网格(元胞似国际象棋分布在网格内。而不象围棋的棋子分布在格网交叉点上)。根据元胞的局部空间构形来决定生死。只不过规则更为简单。下面介绍生命游戏的构成及规则:
(1)元胞分布在规则划分的网格上;
(2)元胞具有0,1两种状态,0代表”死”,l代表”生”;
(3)元胞以相邻的8个元胞为邻居。即Moore邻居形式;
(4)一个元胞的生死由其在该时刻本身的生死状态和周围八个邻居的状态 (确切讲是状态的和)决定:
·在当前时刻,如果一个元胞状态为”生”,且八个相邻元胞中有两个或三个的状态为”生”,则在下–时刻该元胞继续保持为”生”,否则”死”去;
·在当前时刻。如果一个元胞状态为”死”。且八个相邻元胞中正好有三个为”生”。则该元胞在下一时刻 “复活”。否则保持为”死”。
尽管它的规则看上去很简单。但生命游戏是具有产生动态图案和动态结构能力的元胞自动机模型。它能产生丰富的、有趣的图案。生命游戏的优化与初始元胞状态值的分布有关,给定任意的初始状态分布。经过若干步的运算,有的图案会很快消失。而有的图案则固定不动,有的周而复始重复两个或几个图案,有的婉蜒而行。有的则保持图案定向移动,形似阅兵阵……,其中最为著名的是”滑翔机 (叫Glider)”的图案。
这里写图片描述
生命游戏模型已在多方面得到应用。他的演化规则近似地描述了生物群体的生存繁殖规律:在生命密度过小(相邻元胞数之2)时,由于孤单、缺乏配种繁殖机会、缺乏互助也会出现生命危机,元胞状态值由1变为0;在生命密度过大 (相邻元胞数>3)时,由于环境恶化、资源短缺以及相互竞争而出现生存危机,元胞状态值由1变为0;只有处于个体适中(相邻元胞数为2或3)位置的生物才能生存(保持元胞的状态值为1)和繁衍后代(元胞状态值由0变为1)。正由于它能够模拟生命活动中的生存、灭绝、竞争等等复杂现象,因而得名”生命游戏”。J·H·Conway还证明,这个元胞自动机具有通用图灵机的计算能力(谢惠民,1994;李才伟,1997),与图灵机等价,也就是说给定适当的初始条件,生命游戏模型能够模拟任何一种计算机。
从数学模型的角度看,该模型将平面划分成方格棋盘,每个方格代表一个元胞。
元胞状态:0 死亡,1- 活着
领域半径:1

也就是说,我们可以用一个ndarray对象来表示生命游戏中每个细胞的生死,然后下一状态新生成的的ndarray数组的每个元素也基于原来的数组,满足生命游戏的规则

粗略的实现

import numpy as np

先导入numpy模块

lifepoint=np.random.randint(2,size=(18,18)).astype(np.uint8)print lifepointnewlifepoint=np.zeros_like(lifepoint)print '++++++++++++++++++++++++++++++++++++++++++++++++++++++++'print '                                                        'rows,cols=lifepoint.shapefor i in range(rows-1):    for  j in range(cols-1):        lifestate=lifepoint[i,j]        area=lifepoint[i-1:i+2,j-1:j+2]        d=np.sum(area)-lifestate        if lifestate:            if d==2 or d==3:                newlifepoint[i,j]=1            else:                newlifepoint[i,j]=0        else:            if d==3:                newlifepoint[i,j]=1print newlifepoint

这段代码简单实现了下一个状态的图像,但是需要考虑的是首先得注意下标,因为在切片的时候要遍历每个元素,切片与其距离为1的部分求和,所以得+1或者-1,所以不能从零开始也不能大于ndarray数组行列的值。而且,还没有解决边界上的元素的问题。
我将其写进一个迭代器里头,然后粗略的解决了一下边界的问题,可能有点粗暴(毕竟是初学orz)

class lifegame(object):    def __init__(self):        self.lifepoint=np.random.randint(2,size=(18,18)).astype(np.uint8)        self.cols,self.rows=self.lifepoint.shape    def __iter__(self):        return self    def next(self):        newcopy=self.lifepoint.copy()        for i in range(1,self.cols):            for j in range(1,self.rows):                lifestate=self.lifepoint[i,j]                area=self.lifepoint[i-1:i+2,j-1:j+2]                d=np.sum(area)-lifestate                if lifestate:                    if d==3 or d==2:                        self.lifepoint[i,j]=1                    else:                        self.lifepoint[i,j]=0                else:                    if d==3:                        self.lifepoint[i,j]=1        for j in range(1,self.rows):            edgelifestate1=newcopy[0,j]            area1=newcopy[0:2,j-1:j+2]            d1=np.sum(area1)-edgelifestate1            if edgelifestate1:                if d1==3 or d1==2:                    self.lifepoint[0,j]=1                else:                    self.lifepoint[0,j]=0            else:                if d1==3:                    self.lifepoint[0,j]=1        for j in range(1, self.rows):            edgelifestate2 = newcopy[self.cols-1, j]            area2 = newcopy[self.cols-2:self.cols, j - 1:j + 2]            d2 = np.sum(area2) - edgelifestate2            if edgelifestate2:                if d2 == 3 or d2 == 2:                    self.lifepoint[self.cols-1, j] = 1                else:                    self.lifepoint[self.cols-1, j] = 0            else:                if d2 == 3:                    self.lifepoint[self.cols-1, j] = 1        for i in range(1, self.cols):            edgelifestate3 = newcopy[i, 0]            area3 = newcopy[i-1:i+2, 0:2]            d3 = np.sum(area3) - edgelifestate2            if edgelifestate3:                if d3 == 3 or d3 == 2:                    self.lifepoint[i, 0] = 1                else:                    self.lifepoint[i, 0] = 0            else:                if d3 == 3:                    self.lifepoint[i, 0] = 1        for i in range(1, self.cols):            edgelifestate4 = newcopy[i,self.rows-1]            area4 = newcopy[i :i+2, self.rows-2:self.rows]            d4 = np.sum(area4) - edgelifestate4            if edgelifestate3:                if d4 == 3 or d4 == 2:                    self.lifepoint[i, 0] = 1                else:                    self.lifepoint[i, 0] = 0            else:                if d4 == 3:                    self.lifepoint[i, 0] = 1        coner1=newcopy[0,0]        areacorner1=newcopy[0:2,0:2]        c1=np.sum(areacorner1)        if coner1:            if c1==3 or c1==2:                self.lifepoint[0,0]=1            else:                self.lifepoint[0,0]=0        else:            if c1==3:                self.lifepoint[0,0]=1        corner2=newcopy[0,self.cols-1]        areacorner2=newcopy[0:2,self.cols-2:self.cols]        c2=np.sum(areacorner2)        if corner2:            if c2==3 or c2==2:                self.lifepoint[0,self.cols-1]=1            else:                self.lifepoint[0,self.cols-1]=0        else:            if c2==3:                self.lifepoint[0,self.cols-1]=1        corner3=newcopy[self.cols-1,0]        areacorner3=newcopy[self.cols-2:self.cols,0:2]        c3=np.sum(areacorner3)        if corner3:            if c3==3 or c3==2:                self.lifepoint[self.cols-1,0]=1            else:                self.lifepoint[self.cols-1,0]=0        else:            if c3==3:                self.lifepoint[self.cols-1, 0]=1        corner4 = newcopy[self.cols - 1, self.cols-1]        areacorner4 = newcopy[self.cols - 2:self.cols, self.rows-2:self.rows]        c4 = np.sum(areacorner4)        if corner4:            if c4 == 3 or c4 == 2:                self.lifepoint[self.cols - 1, self.rows-1] = 1            else:                self.lifepoint[self.cols - 1, self.rows-1] = 0        else:            if c3 == 3:                self.lifepoint[self.cols - 1, self.rows-1] = 1        return self.lifepointa=lifegame()for i in range(10):    print a.next()    print '============================================'

然后大概就可以实现生命游戏,但是问题在于边缘和四个角上的点解决起来有点困难,所以我们需要进一步的考虑,待我后面的学习比较全面以后再回来修改一下吧。。。

0 0
原创粉丝点击