回答:
この演習には簡単な(そして私が追加できる場合はエレガントな)ソリューションがあります:は2つの生存分布の積のように見えるため、:(
分布は分布です
この場合、は指数分布であり、は -thです指数分布のべき乗。
関連するRコードは、取得するのと同じくらい簡単です
x=pmin(rexp(n,a),rexp(n,b/(p+1))^(1/(p+1))) #simulating an n-sample
そして、それは逆pdfとaccept-rejectの解像度よりも間違いなくはるかに高速です:
> n=1e6
> system.time(results <- Vectorize(simulate,"prob")(runif(n)))
utilisateur système écoulé
89.060 0.072 89.124
> system.time(x <- simuF(n,1,2,3))
utilisateur système écoulé
1.080 0.020 1.103
> system.time(x <- pmin(rexp(n,a),rexp(n,b/(p+1))^(1/(p+1))))
utilisateur système écoulé
0.160 0.000 0.163
驚くほど完璧なフィット感:
逆変換はいつでも数値的に解くことができます。
以下では、非常に簡単な二分法検索を行います。与えられた入力確率(式に既にがあるのでを使用します)について、とからます。次に、までを2倍にします。最後に、その長さがより短く、その中点が満たすまで、間隔を繰り返し二等分します。
ECDF はと選択するのに十分に適合し、かなり高速です。単純な二分探索の代わりに、ニュートン型の最適化を使用することで、おそらくこれを高速化できます。
aa <- 2
bb <- 1
pp <- 0.1
cdf <- function(x) 1-exp(-aa*x-bb*x^(pp+1)/(pp+1))
simulate <- function(prob,epsilon=1e-5) {
left <- 0
right <- 1
while ( cdf(right) < prob ) right <- 2*right
while ( right-left>epsilon ) {
middle <- mean(c(left,right))
value_middle <- cdf(middle)
if ( value_middle < prob ) left <- middle else right <- middle
}
mean(c(left,right))
}
set.seed(1)
results <- Vectorize(simulate,"prob")(runif(10000))
hist(results)
xx <- seq(0,max(results),by=.01)
plot(ecdf(results))
lines(xx,cdf(xx),col="red")
accept-rejectによる直接解決の場合、多少複雑な問題があります。まず、単純な微分は、分布のpdfが
次に、
上限
3番目に、の2番目の項を考慮して、変数、つまり。その後、
は変数の変化のヤコビアンです。場合
したがって、受け入れ-拒否アルゴリズムのRレンダリングは
simuF <- function(a,b,p){
reepeat=TRUE
while (reepeat){
if (runif(1)<.5) x=rexp(1,a) else
x=rexp(1,b/(p+1))^(1/(p+1))
reepeat=(runif(1)>(a+b*x^p)*exp(-a*x-b*x^(p+1)/(p+1))/
(a*exp(-a*x)+b*x^p*exp(-b*x^(p+1)/(p+1))))}
return(x)}
n-サンプルの場合:
simuF <- function(n,a,b,p){
sampl=NULL
while (length(sampl)<n){
x=u=sample(0:1,n,rep=TRUE)
x[u==0]=rexp(sum(u==0),b/(p+1))^(1/(p+1))
x[u==1]=rexp(sum(u==1),a)
sampl=c(sampl,x[runif(n)<(a+b*x^p)*exp(-a*x-b*x^(p+1)/(p+1))/
(a*exp(-a*x)+b*x^p*exp(-b*x^(p+1)/(p+1)))])
}
return(sampl[1:n])}
これは、a = 1、b = 2、p = 3の図です。