## Gráfico da fdp da v.a. X, f(x).
curve(1.5 * (x ^ 2), -1, 1)
O Método da Aceitação-Rejeição
ESTAT0090 – Estatística Computacional
Prof. Dr. Sadraque E. F. Lucena
sadraquelucena@academico.ufs.br
Imagine que você está trabalhando com uma nova distribuição de probabilidade contínua. Como ela é muito recente, ainda não existem funções de simulação disponíveis em bibliotecas ou pacotes de programação. Para conseguir validar seus modelos, você precisa desenvolver do zero o código para gerar dados aleatórios e realizar suas simulações.
Nesta aula, aprenderemos a gerar ocorrências de variáveis aleatórias contínuas usando o método da aceitação-rejeição.
O método da aceitação-rejeição consiste em gerar ocorrências de uma distribuição \(f\) usando a distribuição auxiliar \(g\).
Algoritmo
Passo 1: Gere um valor \(x\) a partir da distribuição \(g(x)\);
Passo 2: Gere \(u \sim\) Uniforme(\(0,1\));
Passo 3: O valor \(x\) gerado é aceito se o número uniforme \(u\) satisfizer: \[u\leq \frac{f(x)}{M g(x)}.\] Caso contrário, o valor \(x\) é rejeitado e o processo é repetido a partir do Passo 1.
Passo 4: Se o valor \(x\) for aceito, ele é considerado um número aleatório da distribuição \(f(x)\). Se for rejeitado, um novo valor é gerado até que seja aceito.
Gere valores de uma variável aleatória \(X\) com \(f(x) = 1.5x^2\), \(-1 < x < 1\).
Vamos considerar como \(g\) (distribuição auxiliar) a densidade da \(U[−1, 1]\). Ou seja, \[ g(x) = \frac{1}{1-(-1)} = \frac{1}{2} = 0.5, \quad -1<x<1. \] Agora vamos definir \(M\): \[ M \geq \max_x \frac{f(x)}{g(x)} = \frac{1.5}{0.5}=3. \] Portanto, vamos usar \(M=3\).
Então o algoritmo para gerar ocorrências da v.a. com densidade \(f\) a partir de \(g\) é
Código R:
geraf <- function(n=1) {
f <- function(x) 1.5 * x^2
g <- function(x) 0.5 + 0 * x
M <- 3
x <- numeric(0)
while (length(x) < n) {
x_candidato <- runif(n = 1, min = -1, max = 1)
u <- runif(1)
r <- f(x_candidato)/(M * g(x_candidato))
if(u < r) {
x <- c(x, x_candidato)
}
}
return(x)
}
geraf(1)
[1] -0.6771899
Gerando 1.000 ocorrências:
Gere valores de uma distribuição Beta(\(\alpha = 2.7, \beta = 6.3\)) usando o método da aceitação-rejeição.
Se preferirmos obter \(M\) por otimização numérica, usamos a função optimize()
. No caso da beta, usaremos a função dbeta()
, que já implementa a função da densidade beta, mas poderíamos escrevê-la manualmente.
Assim, o algoritmo para gerar ocorrências da beta(\(2.7, 6.3\)) a partir da \(U(0, 1)\) é:
Código R:
beta2.7_6.3 <- function(n = 1) {
## Define funções
f <- function(x) dbeta(x, alfa, beta)
g <- function(x) 1 + 0 * x
M <- 2.669744
x <- numeric(0)
while (length(x) < n) {
x_candidato <- runif(n = 1, min = 0, max = 1)
u <- runif(1)
r <- f(x_candidato)/(M * g(x_candidato))
if(u < r) {
x <- c(x, x_candidato)
}
}
return(x)
}
Gere ocorrências da \(N(0, 1)\) a partir da Cauchy(\(0, 1\)).
Vamos obter \(M\) por otimização.
## Obtém valor de M por otimização
(M <- optimize(f = function(x) {dnorm(x)/dcauchy(x)},
interval = c(-6, 6), maximum = TRUE)$objective)
[1] 1.520347
Algoritmo:
Código R:
norm01 <- function(n = 1) {
## Define funções
f <- function(x) dnorm(x, 0, 1)
g <- function(x) dcauchy(x, 0, 1)
M <- optimize(f = function(x) {dnorm(x)/dcauchy(x)},
interval = c(-6, 6), maximum = TRUE)$objective
x <- numeric(0)
while (length(x) < n) {
x_candidato <- rcauchy(n = 1, location = 0, scale = 1)
u <- runif(1)
r <- f(x_candidato)/(M * g(x_candidato))
if(u < r) {
x <- c(x, x_candidato)
}
}
return(x)
}
Código R:
Gere ocorrências da densidade \[ f(x) = \frac{2}{\sqrt{2\pi}}e^{-\frac{x^2}{2}}, x\geq 0, \] a partir da Exponencial(1).
Vamos obter \(M\) por otimização.
# Obtém valor de M por otimização
(M <- optimize(function(x) {((2/sqrt(2*pi)*exp(-(x^2)/2)))/dexp(x)},
interval = c(0, 20), maximum = TRUE)$objective)
[1] 1.315489
Algoritmo: 1. Gere \(x \sim\) Exponencial(1); 2. Gere \(u \sim U(0, 1)\); 3. O valor \(x\) é aceito se \[ u\leq \frac{f(x)}{M g(x)} = \frac{f(x)}{1.315489 g(x)}.\] Caso contrário, o valor \(x\) é rejeitado e todo o processo é repetido.
Código R:
geraEx4 <- function(n = 1) {
## Define funções
f <- function(x) (2/sqrt(2*pi) * exp(-(x^2)/2))
g <- function(x) dexp(x, 1)
M <- optimize(f = function(x) {f(x)/g(x)},
interval = c(0, 10), maximum = TRUE)$objective
x <- numeric(0)
while (length(x) < n) {
x_candidato <- rexp(n = 1, rate = 1)
u <- runif(1)
r <- f(x_candidato)/(M * g(x_candidato))
if(u < r) {
x <- c(x, x_candidato)
}
}
return(x)
}
Gere ocorrências da \(N(0, 1)\) a partir da \(U(-10, 10)\) pelo método da aceitação-rejeição.
Aula baseada no material de Walmes M. Zeviani e Fernando P. Mayer.