--- title: "Introduction to LangevinFlow" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Introduction to LangevinFlow} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 6, fig.height = 4 ) ``` # Overview `LangevinFlow` implements two Markov chain Monte Carlo (MCMC) samplers based on overdamped Langevin diffusion: - `ula()` — the **Unadjusted Langevin Algorithm**, an Euler-Maruyama discretization of the SDE. Cheap per step, but introduces a discretization bias that vanishes only as the step size goes to zero. - `mala()` — the **Metropolis-Adjusted Langevin Algorithm**, which corrects that bias with an accept/reject step. Asymptotically exact. Both target $\pi(x) \propto \exp(-\beta U(x))$ for a user-supplied potential $U$. The user passes the gradient $\nabla U$ (and, for MALA, $U$ itself). ## Sign convention The Langevin SDE is $$ dX_t = -\nabla U(X_t)\,dt + \sqrt{2/\beta}\,dW_t, $$ so the user supplies $U = -\log \pi$ (the *potential* / negative log density). Get this wrong and the chain runs away from the mode rather than toward it — so it's worth a sanity check on a simple target before trusting any real run. # Example 1: standard Gaussian ```{r} library(LangevinFlow) # Target: N(0, I_2). U(x) = 0.5 * ||x||^2. U <- function(x) 0.5 * sum(x^2) grad_u <- function(x) x set.seed(1) fit_ula <- ula(init_x = c(3, -3), grad_u = grad_u, step_size = 0.05, n_iter = 5000, burn_in = 1000) summary(fit_ula) ``` ```{r, fig.alt="ULA trace plots"} plot(fit_ula) ``` The same target with MALA: ```{r} set.seed(1) fit_mala <- mala(init_x = c(3, -3), U = U, grad_u = grad_u, step_size = 0.4, n_iter = 5000, burn_in = 1000) fit_mala$acceptance_rate summary(fit_mala) ``` # Example 2: a correlated Gaussian ```{r} Sigma <- matrix(c(1, 0.8, 0.8, 1), 2, 2) Sigma_inv <- solve(Sigma) mu_true <- c(2, -1) U <- function(x) 0.5 * as.numeric(t(x - mu_true) %*% Sigma_inv %*% (x - mu_true)) grad_u <- function(x) as.numeric(Sigma_inv %*% (x - mu_true)) set.seed(2) fit <- mala(c(0, 0), U, grad_u, step_size = 0.4, n_iter = 8000, burn_in = 2000) colMeans(fit$samples) cov(fit$samples) ``` # Choosing the step size For MALA in $d$ dimensions, the optimal acceptance rate is known to be roughly **0.574** as $d \to \infty$ (Roberts & Rosenthal, 1998). A practical recipe: 1. Run a short pilot chain. 2. If the acceptance rate is too high (>0.7), the steps are too small — **increase** `step_size`. 3. If it is too low (<0.4), the steps are too large — **decrease** `step_size`. 4. Iterate until it lands in the 0.5–0.6 range. For ULA there is no accept/reject feedback, so step-size choice depends on the curvature of $U$: too large and the chain diverges (the package raises an error); too small and mixing is slow. # References - Roberts, G. O., & Tweedie, R. L. (1996). Exponential convergence of Langevin distributions and their discrete approximations. *Bernoulli*, 2(4), 341-363. - Roberts, G. O., & Rosenthal, J. S. (1998). Optimal scaling of discrete approximations to Langevin diffusions. *JRSS-B*, 60(1), 255-268.