プログラムをチューニングする

  • こんなプログラムを作る
library(MCMCpack)
expectation<-(rdirichlet(1,c(1,1,1))) #出す手の割合を決める
guriko<-function(n){
p<-c()
for (i in 1:n){
if (runif(1)>expectation[1]+expectation[2])      {p<-c(p,2)} #gu
else if (runif(1)>expectation[1]) {p<-c(p,1)} #choki
else                             {p<-c(p,0)} #pa
}

q<-c()
for (i in 1:n){
if (runif(1)>2/3)      {q<-c(q,2)} #gu
else if (runif(1)>1/3) {q<-c(q,1)} #choki
else                   {q<-c(q,0)} #pa
}

step<- 0 #相手から見た自分の変位
step.vector<- c() #各試行での変位
for(k in 1:n){
if      ((p[k]==2)&&(q[k]==1)) {step<- step + 3}
else if ((p[k]==1)&&(q[k]==2)) {step<- step + (-3)}
else if ((p[k]==1)&&(q[k]==0)) {step<- step + 6}
else if ((p[k]==0)&&(q[k]==2)) {step<- step + 6}
else if ((p[k]==2)&&(q[k]==0)) {step<- step + (-6)}
else if ((p[k]==0)&&(q[k]==1)) {step<- step + (-6)}
else {step<- step + 0}
step.vector<- c(step.vector,step)
}
#plot(step.vector,type="b")
return(step) #正なら相手より前方、負なら後方
}

win<- function(n){ #勝率を返す関数
expectation<-(rdirichlet(1,c(1,1,1)))
win.count<- 0 #勝数
expectation.and.win.probability<- c()
for(i in 1:n){
if(guriko(100)>=0){ #グリコ100回の結果で決めることにする
win.count<- win.count + 1 #相手より前方なら勝数増やす
}
}
expectation.and.win.probability<- c(expectation,win.count/n) #手の割合と勝率をベクトル化
#print(expectation.and.win.probability) #出す手の割合と勝率を返す
#return(win.count/n) #勝率を返す
}


guriko.simulator<- function(n){ #シミュレーション関数
simulation.results<- matrix(win(100),nc=4) #手の割合と勝率を行列化するためのスタート
for(i in 1:(n-1)){ #シミュレーション関数をn回試行
#上記のwin関数100回試行
simulation.results<- rbind(simulation.results,win(100)) #ひたすら行に加算
} #the end of loop
return(simulation.results)
} #the end of guriko.simulator

res<- guriko.simulator(1000)
  • どんな点が「きれい」にできるだろう
    • ベクトルの長さをだんだんに長くするより、長さを確保してから、値を順番に座席に入れる方が速い
guriko<-function(n){
p<-c()
for (i in 1:n){
if (runif(1)>expectation[1]+expectation[2])      {p<-c(p,2)} #gu
else if (runif(1)>expectation[1]) {p<-c(p,1)} #choki
else                             {p<-c(p,0)} #pa
}
      • "p<-c(p,v)"では、pの中身を全部取り出して、その最後にvをつけて、長さが1増えたベクトルに格納しなおしている
      • "p<-rep(0,N) " (N は予め与える長さ)として"p[i]<-v"とすると、1,2,...,(i-1)"に格納し終えたpの値は参照せずに値をある位置に突っ込むだけ
      • これも同様
expectation.and.win.probability<- c(expectation,win.count/n) 
###
rbind(simulation.results,win(100))
    • Rは行列処理が得意
for(k in 1:n){
if      ((p[k]==2)&&(q[k]==1)) {step<- step + 3}
else if ((p[k]==1)&&(q[k]==2)) {step<- step + (-3)}
else if ((p[k]==1)&&(q[k]==0)) {step<- step + 6}
else if ((p[k]==0)&&(q[k]==2)) {step<- step + 6}
else if ((p[k]==2)&&(q[k]==0)) {step<- step + (-6)}
else if ((p[k]==0)&&(q[k]==1)) {step<- step + (-6)}
else {step<- step + 0}
step.vector<- c(step.vector,step)
}
    • ここでは、3x3行列を扱っている。3x3の組み合わせを『ベタ』に書いている。
      • 3x3行列を作り、(p[k],q[k])の番地の値を取り出すようにすると3x3行列の書き間違えだけを避ければよい
        • ゲインの行列を作ってもよいし、2者の差の行列を作ってもよい
    • プログラムの利点の大きな部分は、一般化すること(それはコーディングミスを少なくすること出もある)
      • ゲームを替えても行列勝負なら行列を取り替えるだけでよくなる
  • 乱数の発生
    • sample()を使うこともできる
library(MCMCpack)
#ゲイン行列
Mat<-matrix(c(0,3,0,0,0,6,6,0,0),ncol=3,byrow=TRUE)
njan<-100 #1勝負あたりのじゃんけんの回数
niter<-1000 # 勝負の回数

p<-rdirichlet(1,rep(1,3)) # 少しだけ1/3,1/3,1/3からずらすにはrep(10,3)とか

q<-rep(1/3,3)
#p<-q # p,q同じにする

# 100じゃんけん後の位置(ploc,qloc)と勝利数(winnum),勝率(winp)の推移
ploc<-qloc<-winnum<-winp<-rep(0,niter)

for(i in 1:niter){
#i-th 勝負のじゃんけんの手
 pj<-sample(1:3, size=njan, replace = TRUE,prob=p)
 qj<-sample(1:3, size=njan, replace = TRUE,prob=q)
 for(j in 1:njan){
  ploc[i]<-ploc[i]+Mat[pj[j],qj[j]]
  qloc[i]<-qloc[i]+Mat[qj[j],pj[j]]
 }
 #winpはpの勝ち数
 if(i>1){
  winnum[i]<-winnum[i-1]
 }
 if(ploc[i]>qloc[i]){
  winnum[i]<-winnum[i]+1
 }
}
winp<-winnum/(1:niter) # j勝負施行後の勝率に変換
# これの収束値が、pの手の出し方を与えたときの勝率の期待値
par(mfcol=c(2,2))
plot(ploc)

plot(qloc)

plot(winp)
print(p)
library(MCMCpack)
# 2人のじゃんけんの手の確率分布
p<-rdirichlet(1,rep(1,3)) 
q<-rdirichlet(1,rep(1,3)) 
# 相対的得点行列
Mat2<-matrix(c(0,3,-6,-3,0,6,6,-6,0),ncol=3,byrow=TRUE)
# 2人の手の組合せの確率分布
JanPattern<-t(p) %*% q
# その和は1
sum(JanPattern)
# njanは1グリコ勝負あたりのじゃんけんの回数
njan<-100
# 勝負の回数
niter<-1000
# 相対的位置
locs<-rep(0,niter)
for(i in 1:niter){
 locs[i]<-sum(sample(c(Mat2),size=njan,prob=c(JanPattern),replace=TRUE))
}
plot(sort(locs))
length(which(locs>0))/niter # 勝率
length(which(locs<0))/niter # 負け率
length(which(locs==0))/niter # 同点率