Specifying a base probability density function

Motivation

Providing a more suitable probability density function can further reduce computational cost and increase the acceptance probability. Therefore, inspecting an alternative for the base probability density function is a good practice.

The accept_reject() function supports, for the continuous case, specifying a base probability density function if you don’t want to use the continuous uniform distribution as the default base.

When choosing to specify another probability density function different from the uniform one, it’s necessary to specify the following arguments:

  • f_base: base probability density function;
  • random_base: sampling from the base probability density function;
  • args_f_base: list with the parameters of the base density.

By default, all of them are NULL, and the continuous uniform distribution in xlim is used as the base. If at least one of these arguments is not specified, no error will occur, and the continuous uniform distribution in xlim will still be used as the base.

For the discrete case, if the user mistakenly specifies any of these arguments, i.e., when continuous = FALSE, the accept_reject() function will ignore these arguments and use the discrete uniform distribution as the base.

If you choose to specify a base density, it’s convenient to inspect it by comparing the base density function with the theoretical probability density function. The inspect() function facilitates this task. The inspect() function will plot the base probability density function and the theoretical probability density function, find the intersection between the densities, and display the value of the intersection area on the plot. These are important pieces of information to decide if the base probability density function specified in the args_f_base argument and the value of c (default is 1) are appropriate.

Example of inspection

library(AcceptReject)
library(cowplot) # install.packages("cowplot")

# Ensuring reproducibility
set.seed(0)

# Inspecting
# Case a
a <- inspect(
  f = dweibull,
  args_f = list(shape = 2.1, scale = 2.2),
  f_base = dgamma,
  args_f_base = list(shape = 2.8, rate = 1.2),
  xlim = c(0, 10),
  c = 1.2
)

# Inspecting
# Case b
b <- inspect(
  f = dweibull,
  args_f = list(shape = 2.1, scale = 2.2),
  f_base = dgamma,
  args_f_base = list(shape = 2.9, rate = 2.5),
  xlim = c(0, 10),
  c = 1.4
)

plot_grid(a, b, nrow = 2L, labels = c("a", "b"))

Notice that considering the distribution in scenario “a” in the code above is more convenient. Note that the area is approximately 1, the base probability density function with parameters shape = 2.8 and rate = 1.2 provides a shape close to the theoretical distribution, and c = 1.2 ensures that the base density function upper bounds the theoretical probability density function. Therefore, considering f_base with Γ(α = 2.8, β = 1.2) and c = 1.2 is a reasonable choice for a base distribution.

Therefore, passing arguments to f_base = dgamma, args_f_base = list(shape = 2.8, rate = 1.2), and c = 1.2 to the accept_reject() function will lead us to an even more efficient code.

library(AcceptReject)
library(tictoc) # install.packages("tictoc")

# Ensuring reproducibility
set.seed(0)

# Não especificando a função densidade de probabilidade base

tic()
case_1 <- accept_reject(
  n = 200e3L,
  continuous = TRUE,
  f = dweibull,
  args_f = list(shape = 2.1, scale = 2.2),
  xlim = c(0, 10)
)
toc()
#> 0.072 sec elapsed

# Specifying the base probability density function
tic()
case_2 <- accept_reject(
  n = 200e3L,
  continuous = TRUE,
  f = dweibull,
  args_f = list(shape = 2.1, scale = 2.2),
  f_base = dgamma,
  random_base = rgamma,
  args_f_base = list(shape = 2.8, rate = 1.2),
  xlim = c(0, 10),
  c = 1.2
)
toc()
#> 0.116 sec elapsed

# Visualizing the results
p1 <- plot(case_1)
p2 <- plot(case_2)

plot_grid(p1, p2, nrow = 2L)

Notice that the results were very close in a graphical analysis. However, the execution time specifying a convenient base density was lower for a very large sample.

Important:

You can investigate and try inspecting a base probability density function to find a specification of the base density and a value of c that you can pass as an argument to accept_reject(). The idea is to find a small value of c to maximize the acceptance probability and pass this value to stat_c so that the accept_reject() function can improve this value.