#' Univariate discrete point mass priors
#'
#' \code{PointMassPrior} is a sub-class of \code{\link[=Prior-class]{Prior}}
#' representing a univariate prior over a discrete set of points with positive
#' probability mass.
#'
#' @slot theta cf. parameter 'theta'
#' @slot mass cf. parameter 'mass'
#'
#' @seealso To represent continuous prior distributions use \code{\link{ContinuousPrior}}.
#'
#' @aliases PointMassPrior
#' @exportClass PointMassPrior
setClass("PointMassPrior", representation(
theta = "numeric",
mass = "numeric"
),
contains = "Prior")
#' @param theta numeric vector of pivot points with positive prior mass
#' @param mass numeric vector of probability masses at the pivot points
#' (must sum to 1)
#' @template label
#'
#' @return an object of class \code{PointMassPrior}, \code{theta} is
#' automatically sorted in ascending order
#'
#' @examples
#' PointMassPrior(c(0, .5), c(.3, .7))
#'
#' @rdname PointMassPrior-class
#' @export
PointMassPrior <- function(theta, mass, label = NA_character_) {
if (round(sum(mass), 10) != 1)
stop("mass must sum to one")
new("PointMassPrior", theta = theta[order(theta)], mass = mass[order(theta)],
label = label)
}
setMethod("print", signature('PointMassPrior'), function(x, ...) {
name <- if (!is.na(x@label)) x@label else 'PointMass'
if (length(x@theta) == 1)
glue::glue("{name}<{sprintf('%.2f',x@theta)}>")
else
paste0(
glue::glue("{name}<"),
paste0(glue::glue("Pr[{sprintf('%.2f',x@theta)}]={sprintf('%3.2f',x@mass)}"), collapse = ";"),
">",
collapse = ""
)
})
#' @examples
#' bounds(PointMassPrior(c(0, .5), c(.3, .7)))
#' # > 0.3 0.7
#'
#' @rdname bounds
#' @export
setMethod("bounds", signature("PointMassPrior"),
function(dist, ...) range(dist@theta))
#' @examples
#' expectation(PointMassPrior(c(0, .5), c(.3, .7)), identity)
#' # > .35
#'
#' @rdname expectation
#' @export
setMethod("expectation", signature("PointMassPrior", "function"),
function(dist, f, ...) sum(dist@mass * sapply(dist@theta, f, ...)) )
#' @examples
#' tmp <- condition(PointMassPrior(c(0, .5), c(.3, .7)), c(-1, .25))
#' expectation(tmp, identity) # 0
#'
#' @rdname condition
#' @export
setMethod("condition", signature("PointMassPrior", "numeric"),
function(dist, interval, ...) {
if (length(interval) != 2)
stop("interval must be of length 2")
if (any(!is.finite(interval)))
stop("interval must be finite")
if (diff(interval) < 0)
stop("interval[2] must be larger or equal to interval[1]")
epsilon <- sqrt(.Machine$double.eps)
# find indices of pivots wihtin interval (up to machine precision!)
idx <- (interval[1] - dist@theta <= epsilon) & (dist@theta - interval[2] <= epsilon)
# re-normalize and return
return(PointMassPrior(
dist@theta[idx], dist@mass[idx] / sum(dist@mass[idx])
))
})
#' @examples
#' predictive_pdf(Normal(), PointMassPrior(.3, 1), 1.5, 20) # ~.343
#'
#' @rdname predictive_pdf
#' @export
setMethod("predictive_pdf", signature("DataDistribution", "PointMassPrior", "numeric"),
function(dist, prior, x1, n1, ...) {
grid <- expand.grid(x1 = x1, piv = prior@theta)
(matrix(probability_density_function(dist, grid$x1, n1, grid$piv), nrow = length(x1)) %*% prior@mass)[, 1]
})
#' @examples
#' predictive_cdf(Normal(), PointMassPrior(.0, 1), 0, 20) # .5
#'
#' @rdname predictive_cdf
#' @export
setMethod("predictive_cdf", signature("DataDistribution", "PointMassPrior", "numeric"),
function(dist, prior, x1, n1, ...) {
grid <- expand.grid(x1 = x1, piv = prior@theta)
(matrix(cumulative_distribution_function(dist, grid$x1, n1, grid$piv), nrow = length(x1)) %*% prior@mass)[, 1]
})
#' @examples
#' posterior(Normal(), PointMassPrior(0, 1), 2, 20)
#'
#' @rdname posterior
#' @export
setMethod("posterior", signature("DataDistribution", "PointMassPrior", "numeric"),
function(dist, prior, x1, n1, ...) {
if (length(prior@theta) == 1) return(prior) # shortcut
mass <- prior@mass * probability_density_function(dist, x1, n1, prior@theta)
mass <- mass / sum(mass) # normalize
PointMassPrior(prior@theta, mass)
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.