行列処理化して扱いやすくする

  • ライフゲームによる、パターンの推移を見守っている
  • こちらで書いたように、推移が「行列」の積のようにできて、その行列の作用の特長抽出ができたり、推移の様子から、規則がスカラー量で取り出せたりすると、ライフゲームが視覚化しにくくても、取り扱えるようになると思われるので、ライフゲーム「グライダー」を例にとって、それをやってみる
  • 2次元近傍を行列計算で取り扱うために、以下を定める
n<-4
m<-matrix(1:n^2,n,n)
# t1,t2行列を作成
t1<-diag(rep(1,(n-1)))
t1<-cbind(rep(0,n-1),t1)
t1<-rbind(t1,rep(0,n))
t2<-t(t1)
# 近傍の値を取り出すためには、t1,t2を組み合わせるとよい
# m[i,j]->m[i,j]
m
# m[i+1,j]->m[i,j]
t1%*%m
# m[i,j-1]->m[i,j]
m%*%t1
# m[i-1,j]->m[i,j]
t2%*%m
# m[i,j+1]->m[i,j]
m%*%t2
# m[i+1,j+1]->m[i,j]
(t1%*%m)%*%t2
# m[i-1,j-1]->m[i,j]
(t2%*%m)%*%t1
# m[i+1,j-1]->m[i,j]
(t1%*%m)%*%t1
# m[i-1,j+1]
(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か所に発生させる(これは、きちんとした生命体にはならない)
# nxnの平面に
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)