library(ggplot2)
library(tidyverse)
library(cowplot)
library(animation)
ns <- seq(10, 1000, by = 10)
a <- 2; b <- 5
ap <- 2; bp <- 4
ratio <- function(x) dbeta(x, a, b) / dbeta(x, ap, bp)
c_opt <- max(
optimize(ratio, c(1e-9, 1-1e-9), maximum = TRUE)$objective,
ratio(1e-9), ratio(1-1e-9)
)
grid <- tibble(x = seq(0, 1, length.out = 1200)) |>
mutate(target = dbeta(x, a, b),
prop = dbeta(x, ap, bp),
scaled_prop = c_opt * prop,
ymin = pmin(target, scaled_prop),
ymax = pmax(target, scaled_prop))
curve_prop <- tibble(x = seq(0, 1, length.out = 400),
y = dbeta(x, ap, bp))
curve_target <- tibble(x = seq(0, 1, length.out = 400),
y = dbeta(x, a, b))
base_plot <- ggplot(grid, aes(x)) +
geom_area(aes(y = target), fill = "steelblue", alpha = 0.18) +
geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = "tomato", alpha = 0.22) +
geom_line(aes(y = target), linewidth = 1, color = "steelblue") +
geom_line(aes(y = scaled_prop), linewidth = 1, linetype = "dashed", color = "steelblue") +
labs(x = "x", y = "", title = "") +
theme_minimal(base_size = 13) +
coord_cartesian(xlim = c(0, 1))
invisible(saveGIF({
set.seed(123)
acc_store <- numeric(0)
x_store <- numeric(0)
for(n in ns){
xs <- rbeta(n, ap, bp)
us <- runif(n)
hg <- c_opt * dbeta(xs, ap, bp)
dots_y <- us * hg
fx <- dbeta(xs, a, b)
accept <- dots_y <= fx
x_store <- c(x_store, xs)
i <- sample.int(n, 1)
xi <- xs[i]
yi <- dots_y[i]
ai <- accept[i]
central1 <- base_plot +
labs(title = "(2a) Candidate from proposal") +
geom_segment(data = data.frame(x = xi, y0 = 0, y1 = c_opt * dbeta(xi, ap, bp)),
aes(x = x, xend = x, y = y0, yend = y1),
inherit.aes = FALSE,
linetype = "dashed",
linewidth = 1,
color = "grey")
central2 <- central1 +
labs(title = "(2b) Uniform draw on the line") +
geom_point(data = data.frame(x = xi, y = yi),
aes(x = x, y = y),
inherit.aes = FALSE,
size = 3,
color = "black")
central3 <- central1 +
labs(title = "(2c) Accept/Reject") +
geom_point(data = data.frame(x = xi, y = yi),
aes(x = x, y = y),
inherit.aes = FALSE,
size = 3,
color = if (ai) "steelblue" else "tomato")
right_hist <- ggplot(data.frame(x = x_store), aes(x = x)) +
geom_histogram(aes(y = after_stat(density)),
bins = 25,
fill = "tomato",
color = "black") +
geom_line(data = curve_prop, aes(x = x, y = y)) +
coord_flip(xlim = c(0, 1)) +
scale_y_continuous(limits = c(0, 6)) +
theme_minimal() +
labs(title = "(1) Proposal draws", x = "", y = "") +
theme(axis.text = element_blank(),
axis.ticks = element_blank(),
plot.margin = margin(r = 0, t = 0))
bottom_hist_prev <- ggplot(data.frame(x = acc_store), aes(x = x)) +
geom_histogram(aes(y = after_stat(density)),
bins = 25,
fill = "steelblue",
color = "black") +
geom_line(data = curve_target, aes(x = x, y = y), color = "steelblue") +
coord_cartesian(xlim = c(0, 1)) +
theme_minimal() +
labs(y = "(3) Accepted sample", x = "") +
theme(plot.margin = margin(t = 0, b = 0),
axis.title.y = element_text(size = 12))
acc_store_next <- c(acc_store, xs[accept])
bottom_hist_next <- ggplot(data.frame(x = acc_store_next), aes(x = x)) +
geom_histogram(aes(y = after_stat(density)),
bins = 25,
fill = "steelblue",
color = "black") +
geom_line(data = curve_target, aes(x = x, y = y), color = "steelblue") +
coord_cartesian(xlim = c(0, 1)) +
theme_minimal() +
labs(y = "(3) Accepted sample", x = "") +
theme(plot.margin = margin(t = 0, b = 0),
axis.title.y = element_text(size = 12))
title_plot <- ggplot() +
labs(title = paste0("Proposals = ", length(x_store),
" Accepts = ", length(acc_store_next))) +
theme_void() +
theme(plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
plot.margin = margin(r = 0, t = 0, b = 0, l = 0))
final1 <- ggdraw() +
draw_plot(title_plot, x = 0, y = 0.9, width = 1, height = 0.1) +
draw_plot(central1, x = 0.2, y = 0.2, width = 0.6, height = 0.6) +
draw_plot(right_hist, x = 0.8, y = 0.2, width = 0.2, height = 0.6) +
draw_plot(bottom_hist_prev, x = 0.2, y = 0, width = 0.6, height = 0.2)
final2 <- ggdraw() +
draw_plot(title_plot, x = 0, y = 0.9, width = 1, height = 0.1) +
draw_plot(central2, x = 0.2, y = 0.2, width = 0.6, height = 0.6) +
draw_plot(right_hist, x = 0.8, y = 0.2, width = 0.2, height = 0.6) +
draw_plot(bottom_hist_prev, x = 0.2, y = 0, width = 0.6, height = 0.2)
final3 <- ggdraw() +
draw_plot(title_plot, x = 0, y = 0.9, width = 1, height = 0.1) +
draw_plot(central3, x = 0.2, y = 0.2, width = 0.6, height = 0.6) +
draw_plot(right_hist, x = 0.8, y = 0.2, width = 0.2, height = 0.6) +
draw_plot(bottom_hist_next, x = 0.2, y = 0, width = 0.6, height = 0.2)
print(final1)
print(final2)
print(final3)
acc_store <- acc_store_next
}
}, movie.name = "accept_reject.gif", fps = 2, ani.width = 1000, ani.height = 1000))