Posterior inference for the shape parameter alpha and mean matrix mu in the model X_i ~ Wishart_p(2*alpha, Sigma), under both an improper prior and a proper Gamma/inverse-Wishart prior. The posterior mode is found via a Newton-within-EM algorithm and joint samples are drawn via rejection sampling.
Bayesian inference for the shape parameter of the Wishart distribution — and its p = 1 reduction, the Gamma distribution.
Given data $X_1, \dots, X_n \overset{iid}{\sim} \text{Wishart}_p(2\alpha, \Sigma)$, this package provides posterior inference for the shape parameter $\alpha$ and the mean matrix $\mu = \alpha\Sigma$. The posterior mode is found via a Newton-within-EM algorithm, and joint samples of $(\alpha, \mu)$ are drawn via rejection sampling with a Gamma covering density. The core computation is implemented in C++ (RcppArmadillo + Boost) for speed.
The package has two independent backends, covered in their own sections below — there is no unifying dispatcher, so use whichever matches your data:
wishart_inference() — matrix data, p >= 2gamma_inference() — scalar data, p = 1 (the exact p = 1 reduction
of the same model, so scalar observations never need to be wrapped in
trivial 1 x 1 matrices)A full walkthrough of both backends — improper and proper priors, the
manual step-by-step workflow, and the package's error-handling
conventions — is in demo/wishart_demo.R.
install.packages(
"wishartinference",
repos = c("https://sunnyhq-shi.r-universe.dev", "https://cloud.r-project.org")
)
This installs a precompiled binary where available — no local C++ compiler or Rtools setup required.
Improper prior: $$p(\alpha, \mu) \propto (\alpha - (p-1)/2)^{-1} \cdot |\mu|^{-(p+1)/2}$$
Proper prior: $$(\alpha - (p-1)/2) \sim \text{Gamma}(\beta, \text{rate} = \beta\eta), \qquad \mu \mid \alpha \sim \text{inv-Wishart}(2\kappa\alpha, 2\kappa\alpha\mu_0)$$
library(wishartinference)
# Simulate data from a known truth
set.seed(6)
p <- 3; nu <- 10; Sigma <- diag(p); n <- 10
X <- rwishart(n, p, nu, Sigma)
# Full pipeline: sufficient stats, EM mode, rejection sampling
res <- wishart_inference(X, nsamp = 5000)
res$results$ahat # posterior mode
quantile(res$results$alpha_samples, c(0.025, 0.975)) # 95% interval
The prior type is auto-detected from the arguments you supply. beta = 0, eta = 1, kappa = 0 (the function defaults) is not merely a placeholder
flag — it is mathematically identical to the improper prior above.
| Improper | Proper | |
|---|---|---|
mu0 |
omit | supply (p x p, positive definite) |
beta |
omit (0) | >= 0 |
eta |
omit (1) | >= 0 |
kappa |
omit (0) | >= 1 |
beta <- 50
eta <- (beta - 1) / (beta * (3 - (p - 1) / 2)) # places the prior mode at alpha = 3
kappa <- 1
mu0 <- diag(10, p)
res_pro <- wishart_inference(X, mu0 = mu0, beta = beta, eta = eta,
kappa = kappa, nsamp = 5000)
For full control over each stage, or to reuse the mode/sampler independently:
stat <- wishart_stats(X) # sufficient statistics
ahat <- mode_alphaEM(n, p, stat$xbar, stat$ldetxbarg) # posterior mode
lambda <- max(n * (ldet(stat$xbar) - stat$ldetxbarg), 1e-10)
nu_star <- ahat[1] * lambda + 1
samp <- rejection_sampler(ahat[1], ahat[2], lambda, nu_star,
p, n, stat$xbar, stat$ldetxbarg)
| Function | Purpose |
|---|---|
wishart_inference() |
Full pipeline: sufficient statistics, EM mode finding, rejection sampling |
mode_alphaEM() |
Find the posterior mode of alpha via Newton-within-EM |
rejection_sampler() |
Draw joint posterior samples of (alpha, mu) given a mode |
wishart_stats() |
Compute sufficient statistics (xbar, ldetxbarg) from data |
rwishart() |
Generate draws from a Wishart distribution |
lfafun_improper() / lfafun_proper() |
Evaluate the log unnormalized posterior of alpha |
lgammap_export() |
Log of the multivariate Gamma function |
ldet() |
Log determinant of a positive definite matrix |
p >= 2 and n >= 2 are required.n * (log|xbar| - mean(log|X_i|)) must be
strictly positive; fails only when all n observations are numerically
identical.The exact p = 1 case of the model above: $X_i \sim \text{Gamma}(\alpha,
\alpha/\mu)$. Same priors, same EM-then-rejection-sampling approach, just
scalar inputs/outputs instead of matrices.
set.seed(11)
n <- 20; a <- 3
x <- rgamma(n, a, a) # mean 1
res <- gamma_inference(x, nsamp = 5000)
res$results$ahat # posterior mode
quantile(res$results$alpha_samples, c(0.025, 0.975)) # 95% interval
# Proper prior
res_pro <- gamma_inference(x, mu0 = 1, beta = 5, eta = 0.5, kappa = 2, nsamp = 5000)
| Function | Purpose |
|---|---|
gamma_inference() |
Full pipeline for scalar data |
mode_alphaEM_gamma() |
Posterior mode via EM |
rejection_sampler_gamma() |
Joint posterior samples of (alpha, mu) given a mode |
lfafun_gamma() |
Log unnormalized posterior of alpha |
kappa = 0 is allowed even with beta > 0 here (proper prior on
alpha, flat prior on mu) — the matrix backend requires kappa >= 1
whenever the prior isn't fully improper.n = 2 with a fully improper prior
(beta = 0, kappa = 0), the posterior has no interior mode for any
dataset — its supremum sits exactly at the boundary alpha = 0.
gamma_inference() raises an informative error here rather than
returning a degenerate result. Any beta > 0, any kappa > 0, or
n > 2 resolves it. (The matrix model has no analogous failure — an
interior mode is always guaranteed there at n >= 2.)Bad inputs (invalid nsamp, malformed priors, non-positive-definite
matrices, degenerate data, etc.) raise an informative R-level error
immediately, for both backends. Genuine numerical non-convergence is
instead caught internally by wishart_inference() / gamma_inference(),
which return list(error = "...") rather than stopping — useful when
iterating over many datasets in a batch job. The manual-workflow functions
(mode_alphaEM(), rejection_sampler(), and their _gamma counterparts)
always raise directly.
r <- wishart_inference(X, nsamp = 100, max_em_iter = 1)
if (!is.null(r$error)) {
message("Inference failed: ", r$error)
}
[email protected][email protected]Developed at Swarthmore College.
MIT — see LICENSE.