前两天突然在微博上刷到了康威老爷子逝世的消息,突然想起久远的在神经网络原理课上的附录内容,有介绍原胞自动机的,神经鱼之类的有趣项目。
因为逻辑并不难(起码比当时SOM之类的小众网络好理解多),就一直想复现下。结果拖延到现在。。。。。 赶紧睡前试一试。
还遇到了些坑,百度百科上的生命游戏部分,阐述不清楚,对死亡的规则似乎是少了一条,结果我的种群疯狂膨胀。。。。
原理如下:假设世界是个200*200的二维世界,空白的地方都是资源,种群数量到达阈值就可以扩增,多了资源不够就要死亡。一个细胞就是一个格子,他的周围有八个格子。
三条规则:
- 若一个细胞周围有二~三个细胞则该细胞在下个迭代中则生;
- 若一个格子周围有三个细胞则该细胞在下个迭代中则出现细胞
- 若一个细胞周围超过三个细胞,在下个迭代中则死亡
基于这些规则,我使用R复现了这一过程,代码在结尾:
这个东东有趣就有趣在,简单的规则会得到非常复杂和有趣的群落特征。最终也会变成一个固定循环的稳态,在这次实验中大于是一千多个循环到稳态。间接证明了一个生命出现的基本逻辑,只需要简单的规则就可以得到复杂的世界结果,如果能在生死的过程中以概率的形式计算,那可能对更有趣。
大概写了一遍,发现这个项目真的好适合中途想转行coding的人,涉及到很多简单的矩阵操作,逻辑难度不高,结果又很好看,不容易劝退。
slide <- 200 CA <- matrix(0,slide,slide) set.seed(1234) n=3000 init_life <- cbind(sample(1:slide,n,replace = T),sample(1:slide,n,replace = T)) #init_life <- matrix(c(2,3,2,3,3,3,2,2),ncol = 2) #apply(init_life, 1, function(x) {CA[x[1],x[2]] <<- 1}) live_id <- (init_life) for (k in 1:5000) { print(k) live_id<- t(live_id) test_id <- cbind(live_id+c(0,0), live_id+c(1,0), live_id+c(1,1), live_id+c(1,-1), live_id+c(0,1), live_id+c(0,-1), live_id+c(-1,0), live_id+c(-1,1), live_id+c(-1,-1)) test_id <- test_id[,test_id[1,]>0] test_id <- test_id[,test_id[2,]>0] test_id <- test_id[,test_id[1,]<=slide] test_id <- test_id[,test_id[2,]<=slide] test_id <- (unique(t(test_id))) live_id<- t(live_id) #x <- test_id[1,] live_partner <- apply(test_id,1, function(x){ length(which( (abs(live_id[,1]-x[1])==0 & abs(live_id[,2]-x[2])==1) | (abs(live_id[,1]-x[1])==1 & abs(live_id[,2]-x[2])==0) | (abs(live_id[,1]-x[1])==1 & abs(live_id[,2]-x[2])==1) )) } ) part1 <- test_id[which(live_partner ==3),] part2 <- test_id[which(live_partner[1:nrow(live_id)] ==2),] live_id <- unique(rbind(part1, part2)) png(paste0('./CA/',k,'.png')) plot(live_id,pch=16,cex=0.5,xlim=c(1,slide),ylim=c(1,slide),main=k) dev.off() Sys.sleep(0.5) }
No Leanote account? Sign up now.