- ライフゲームによる、パターンの推移を見守っている
- こちらで書いたように、推移が「行列」の積のようにできて、その行列の作用の特長抽出ができたり、推移の様子から、規則がスカラー量で取り出せたりすると、ライフゲームが視覚化しにくくても、取り扱えるようになると思われるので、ライフゲーム「グライダー」を例にとって、それをやってみる
- 2次元近傍を行列計算で取り扱うために、以下を定める
n<-4
m<-matrix(1:n^2,n,n)
t1<-diag(rep(1,(n-1)))
t1<-cbind(rep(0,n-1),t1)
t1<-rbind(t1,rep(0,n))
t2<-t(t1)
m
t1%*%m
m%*%t1
t2%*%m
m%*%t2
(t1%*%m)%*%t2
(t2%*%m)%*%t1
(t1%*%m)%*%t1
(t2%*%m)%*%t2
moore<-t1%*%m+m%*%t1+t2%*%m+m%*%t2+(t1%*%m)%*%t2+(t2%*%m)%*%t1+(t1%*%m)%*%t1+(t2%*%m)%*%t2
neuman<-t1%*%m+m%*%t1+t2%*%m+m%*%t2
> t1
[,1] [,2] [,3] [,4]
[1,] 0 1 0 0
[2,] 0 0 1 0
[3,] 0 0 0 1
[4,] 0 0 0 0
> t2
[,1] [,2] [,3] [,4]
[1,] 0 0 0 0
[2,] 1 0 0 0
[3,] 0 1 0 0
[4,] 0 0 1 0
MooreSum<-function(m){
nr<-nrow(m)
nc<-ncol(m)
t1r<-diag(rep(1,(nr-1)))
t1r<-cbind(rep(0,nr-1),t1r)
t1r<-rbind(t1r,rep(0,nr))
t2r<-t(t1r)
t1c<-diag(rep(1,(nc-1)))
t1c<-cbind(rep(0,nc-1),t1c)
t1c<-rbind(t1c,rep(0,nc))
t2c<-t(t1c)
t1r%*%m+m%*%t1c+t2r%*%m+m%*%t2c+(t1r%*%m)%*%t2c+(t2r%*%m)%*%t1c+(t1r%*%m)%*%t1c+(t2r%*%m)%*%t2c
}
- グライダーの条件から条件分岐を取り除く
- 自身が1のときにその場所が次の時点に生きる条件はムーア近傍の和が2か3
- 自身が0のときにその場所が次の時点に生きる条件はムーア近傍の和が3
- 自身の生の重みを近傍の生の重みの半分とすると、この2条件は、「ムーア近傍の和と自身の重みづけ(半分)の和が2.5以上、3.5以下」となって、統一できる
- グライダーパターンからちょっとずらして、2か所に発生させる(これは、きちんとした生命体にはならない)
n<-100
m<-matrix(0,n,n)
c<-n/2
m[c,c]<-1
m[(c+1),(c+1)]<-1
m[(c+2),(c-1):(c+1)]<-1
m[(c+3),c]<-1
c<-3*n/5
m[c+10,c]<-1
m[(c-1)+10,(c-1)]<-1
m[(c-2)+10,(c+1):(c-1)]<-1
m[(c-3)+10,c]<-1
Niter<-100
selfWeight<-0.5
minval<-2.5
maxval<-3.5
NumLives<-rep(0,Niter)
for(i in 1:Niter){
NumLives[i]<-sum(m)
tmpm<-MooreSum(m)+selfWeight*m
m<-(tmpm>=minval) * (tmpm<=maxval)
image(m)
}
plot(NumLives)