9.1節 放射性崩壊
著者:梅谷 武
放射性崩壊シミュレーションの基本アルゴリズムを示す。
作成:2012-03-17
更新:2012-03-17
 指数分布乱数により、与えられた母数λの待ち時間を生成し、それらにより放射性崩壊を計数検出器で検出したときの計測パルス列を作成する。
 計測パルス列から指定した時間間隔毎の計数表を作成する。
 計数表から度数分布表を作成し、χ2適合度検定を行なう。
 1000回繰り返したときの、標本平均、標準偏差、有意水準5%χ2検定棄却数を記す。

λ=0.5 (30cpm相当)

[1] " 30.0 ±   3.0 [cpm], err = 52"

λ=1.0 (60cpm相当)

[1] " 59.3 ±   6.2 [cpm], err = 36"

λ=2.0 (120cpm相当)

[1] "117.6 ±   8.6 [cpm], err = 71"

λ=2.5 (150cpm相当)

[1] "147.4 ±   9.6 [cpm], err = 50"
# 関数:乱数による計数列生成
# 戻値:時間間隔毎計数列
# sampling(
#   num,	総数
#   rat,	平均到着率[1/s]
#   dt		計測時間間隔[s]
# )
# 1. 指数分布乱数により待ち時間生成
# 2. パルス時刻列作成
# 3. 時間間隔内の計数列作成
sampling <- function( num, rat, dt ) {
waitings <- rexp( num, rate=rat )
times <- numeric( num )
i <- 1
for ( t in waitings ) {
if ( i == 1 ) times[i] <- t
else times[i] <- times[i-1] + t
i <- i + 1
}
n <- ceiling( max( times ) / dt )
freq <- numeric( n )
for ( t in times ) {
i <- ceiling( t / dt )
freq[i] <- freq[i] + 1
}
return( freq )
}
 
# 関数:乱数による計数列生成し、測定結果を戻す
# 戻値:測定結果表
# measure(
#   num,	総数
#   rat,	平均到着率[1/s]
#   dt		計測時間間隔[s]
# )
# 1. 乱数による計数列生成
# 2. χ^2適合度検定
# 3. (λ,自由度,χ^2,右側確率,cpm)を戻す
measure <- function( num, rat, dt ) {
r <- sampling( num, rat, dt )
n <- length( r )
k <- max( r ) + 1
o <- numeric( k )
for ( i in r ) {
o[i+1] <- o[i+1] + 1
}
x <- 0:(k-1)
l <- sum( o * x ) / n
p <- exp(-l) * l^x / factorial(x)
p[k] <- 1 - sum( p[-k] )
e <- n * p
#plot( x, o, type="h", xlab="", ylab="" )
#points( x, e, type="l", col="red" )
while ( e[1] < 5 ) {
o[2] <- o[2] + o[1]
e[2] <- e[2] + e[1]
o <- o[-1]
e <- e[-1]
k <- k - 1
}
while ( e[k] < 5 ) {
o[k-1] <- o[k-1] + o[k]
e[k-1] <- e[k-1] + e[k]
o <- o[-k]
e <- e[-k]
k <- k - 1
}
z <- sum( (o - e)^2 / e )
q <- pchisq( z, (k-2), lower.tail=FALSE )
if ( is.nan(q) ) q = -1
cpm <- num * 60 / (n*dt)
return( c( l, (k-2), z, q, cpm ) )
}
 
# メインルーチン
# 指定パラメータで測定シミュレーションを繰り返し、
# 平均値、分散、χ^2検定棄却数を表示する。
rat <- 2.5
if ( rat <= 1.0 ) {
num <- 100
} else {
num <- 100 * rat
}
dt  <- 5
len <- 1000
cpm <- numeric( len )
err <- 0
for ( i in 1:len ) {
dat <- measure( num, rat, dt )
sprintf("m = %4.2f, n = %d, chi = %5.3f, p = %5.4f, cpm = %5.1f",
dat[1], dat[2], dat[3], dat[4], dat[5] )
cpm[i] <- dat[5]
if ( dat[4] < 0.05 ) err <- err + 1
}
sprintf( "%5.1f ± %5.1f [cpm], err = %d",
mean( cpm ), sd( cpm ), err )