···11Package: R.NURS
22-Title: What the Package Does (One Line, Title Case)
22+Title: R Implementation of No-Underrun Sampler
33Version: 0.0.0.9000
44Authors@R:
55- person("First", "Last", , "first.last@example.com", role = c("aut", "cre"))
66-Description: What the package does (one paragraph).
55+ person("Visruth", "Srimath Kandali", , "public@visruth.com", role = c("aut", "cre"))
66+Description: A bare-bones R implementation of the No-Underrun Sampler
77+ (Nawaf Bou-Rabee, Bob Carpenter, Sifan Liu, Stefan Oberdörster. 2025.)
88+ written in base R. This implementation attempts to stick very closely
99+ to the algorithm described in Appendix A of the paper.
710License: MIT + file LICENSE
1111+Suggests:
1212+ matrixStats
813Encoding: UTF-8
914Roxygen: list(markdown = TRUE)
1015RoxygenNote: 7.3.2
+1
NAMESPACE
···11# Generated by roxygen2: do not edit by hand
2233+export(NURS)
+30-3
R/NURS.R
···11log_sum_exp <- function(log_vals) {
22+ # if matrixStats is available, rely on C version of logSumExp
23 if (requireNamespace("matrixStats", quietly = TRUE)) {
34 matrixStats::logSumExp(log_vals)
45 } else {
···78 }
89}
9101010-# No underrun condition
1111+#' Check no underrun stopping condition
1212+#'
1313+#' @param log_vals orbit
1414+#' @param log_eps_h log(epsilon) + log(h)
1515+#' @returns True if Orbit satisfies stopping criterion.
1116NURS_stop <- function(log_vals, log_eps_h) {
1217 max(log_vals[1], log_vals[length(log_vals)]) <=
1318 log_eps_h + log_sum_exp(log_vals)
1419}
15201616-# Recursive sub stopping
2121+#' Recursively check sub stopping
2222+#'
2323+#' @param log_vals sub orbit
2424+#' @param log_eps_h log(epsilon) + log(h)
2525+#' @returns True if sub orbit satisfies stopping criterion.
1726NURS_sub_stop <- function(log_vals, log_eps_h) {
1827 n <- length(log_vals)
1928 if (n < 2) return(FALSE)
···2332 NURS_sub_stop(log_vals[-left_indices], log_eps_h)
2433}
25343535+#' Single NURS step
3636+#'
3737+#' @param logpdf log (non-normalized) target density
3838+#' @param theta current state
3939+#' @param epsilon density threshold
4040+#' @param h lattice size
4141+#' @param M maximum number of doublings
4242+#' @returns One NURS step from theta.
2643NURS_step <- function(logpdf, theta, epsilon, h, M) {
2744 d <- length(theta)
2845 # hit
···8198 )]]
8299}
83100101101+#' NURS draws
102102+#'
103103+#' @param logpdf log (non-normalized) target density
104104+#' @param theta_init initial state
105105+#' @param n number of draws
106106+#' @param epsilon density threshold
107107+#' @param h lattice size
108108+#' @param M maximum number of doublings
109109+#' @export
110110+#' @source <https://arxiv.org/abs/2501.18548v2>
84111NURS <- function(logpdf, theta_init, n, epsilon, h, M) {
85112 d <- length(theta_init)
8686- draws <- matrix(NA_real_, n, d)
113113+ draws <- matrix(NA, n, d)
87114 draws[1, ] <- theta_init
88115 for (i in 2:n) {
89116 draws[i, ] <- NURS_step(logpdf, draws[i - 1, ], epsilon, h, M)
+56
README.Rmd
···11+---
22+output: github_document
33+---
44+55+<!-- README.md is generated from README.Rmd. Please edit that file -->
66+77+```{r, include = FALSE}
88+knitr::opts_chunk$set(
99+ collapse = TRUE,
1010+ comment = "#>",
1111+ fig.path = "man/figures/README-",
1212+ out.width = "100%"
1313+)
1414+```
1515+1616+# R.NURS
1717+1818+<!-- badges: start -->
1919+<!-- badges: end -->
2020+2121+Base R implementation of the No-Underrun Sampler.
2222+2323+## Installation
2424+2525+You can install the development version of R.NURS from [GitHub](https://github.com/) with:
2626+2727+``` r
2828+# install.packages("pak")
2929+pak::pak("VisruthSK/R.NURS")
3030+```
3131+3232+## Example: Neal's Funnel
3333+3434+```{r funnel}
3535+library(R.NURS)
3636+library(ggplot2)
3737+3838+set.seed(0)
3939+logpdf_funnel <- function(theta) {
4040+ y <- theta[1]
4141+ dnorm(y, 0, 3, log = TRUE) + sum(dnorm(theta[-1], 0, exp(y / 2), log = TRUE))
4242+}
4343+samples <- NURS(
4444+ logpdf_funnel,
4545+ theta_init = rep(0, 15),
4646+ n = 5000,
4747+ epsilon = 0.1,
4848+ h = 0.5,
4949+ M = 5
5050+)
5151+5252+data.frame(y = samples[, 1], x1 = samples[, 2]) |>
5353+ ggplot(aes(x = y, y = x1)) +
5454+ geom_point(alpha = 0.3) +
5555+ theme_minimal()
5656+```
+48-42
README.md
···11-22-# R.NURS
33-44-Base R implementation of the No-Underrun Sampler.
55-66-## Installation
77-88-You can install the development version of R.NURS like so:
99-1010-``` r
1111-# install.packages("pak")
1212-pak::pak("VisruthSK/R.NURS")
1313-```
1414-1515-## Example
1616-1717-This is a basic example which shows you how to solve a common problem:
1818-1919-``` r
2020-library(R.NURS)
2121-library(ggplot2)
2222-2323-set.seed(0)
2424-logpdf_funnel <- function(theta) {
2525- y <- theta[1]
2626- dnorm(y, 0, 3, log = TRUE) + sum(dnorm(theta[-1], 0, exp(y / 2), log = TRUE))
2727-}
2828-samples <- NURS(
2929- logpdf_funnel,
3030- theta_init = rep(0, 15),
3131- n = 5000,
3232- epsilon = 0.1,
3333- h = 0.5,
3434- M = 5
3535-)
3636-3737-data.frame(y = samples[, 1], x1 = samples[, 2]) |>
3838- ggplot(aes(x = y, y = x1)) +
3939- geom_point(alpha = 0.3) +
4040- theme_minimal()
4141-```
4242-11+22+<!-- README.md is generated from README.Rmd. Please edit that file -->
33+44+# R.NURS
55+66+<!-- badges: start -->
77+88+<!-- badges: end -->
99+1010+Base R implementation of the No-Underrun Sampler.
1111+1212+## Installation
1313+1414+You can install the development version of R.NURS from
1515+[GitHub](https://github.com/) with:
1616+1717+``` r
1818+# install.packages("pak")
1919+pak::pak("VisruthSK/R.NURS")
2020+```
2121+2222+## Example: Neal’s Funnel
2323+2424+``` r
2525+library(R.NURS)
2626+library(ggplot2)
2727+2828+set.seed(0)
2929+logpdf_funnel <- function(theta) {
3030+ y <- theta[1]
3131+ dnorm(y, 0, 3, log = TRUE) + sum(dnorm(theta[-1], 0, exp(y / 2), log = TRUE))
3232+}
3333+samples <- NURS(
3434+ logpdf_funnel,
3535+ theta_init = rep(0, 15),
3636+ n = 5000,
3737+ epsilon = 0.1,
3838+ h = 0.5,
3939+ M = 5
4040+)
4141+4242+data.frame(y = samples[, 1], x1 = samples[, 2]) |>
4343+ ggplot(aes(x = y, y = x1)) +
4444+ geom_point(alpha = 0.3) +
4545+ theme_minimal()
4646+```
4747+4848+<img src="man/figures/README-funnel-1.png" width="100%" />
+27
man/NURS.Rd
···11+% Generated by roxygen2: do not edit by hand
22+% Please edit documentation in R/NURS.R
33+\name{NURS}
44+\alias{NURS}
55+\title{NURS draws}
66+\source{
77+\url{https://arxiv.org/abs/2501.18548v2}
88+}
99+\usage{
1010+NURS(logpdf, theta_init, n, epsilon, h, M)
1111+}
1212+\arguments{
1313+\item{logpdf}{log (non-normalized) target density}
1414+1515+\item{theta_init}{initial state}
1616+1717+\item{n}{number of draws}
1818+1919+\item{epsilon}{density threshold}
2020+2121+\item{h}{lattice size}
2222+2323+\item{M}{maximum number of doublings}
2424+}
2525+\description{
2626+NURS draws
2727+}
+25
man/NURS_step.Rd
···11+% Generated by roxygen2: do not edit by hand
22+% Please edit documentation in R/NURS.R
33+\name{NURS_step}
44+\alias{NURS_step}
55+\title{Single NURS step}
66+\usage{
77+NURS_step(logpdf, theta, epsilon, h, M)
88+}
99+\arguments{
1010+\item{logpdf}{log (non-normalized) target density}
1111+1212+\item{theta}{current state}
1313+1414+\item{epsilon}{density threshold}
1515+1616+\item{h}{lattice size}
1717+1818+\item{M}{maximum number of doublings}
1919+}
2020+\value{
2121+One NURS step from theta.
2222+}
2323+\description{
2424+Single NURS step
2525+}
+19
man/NURS_stop.Rd
···11+% Generated by roxygen2: do not edit by hand
22+% Please edit documentation in R/NURS.R
33+\name{NURS_stop}
44+\alias{NURS_stop}
55+\title{Check no underrun stopping condition}
66+\usage{
77+NURS_stop(log_vals, log_eps_h)
88+}
99+\arguments{
1010+\item{log_vals}{orbit}
1111+1212+\item{log_eps_h}{log(epsilon) + log(h)}
1313+}
1414+\value{
1515+True if Orbit satisfies stopping criterion.
1616+}
1717+\description{
1818+Check no underrun stopping condition
1919+}
+19
man/NURS_sub_stop.Rd
···11+% Generated by roxygen2: do not edit by hand
22+% Please edit documentation in R/NURS.R
33+\name{NURS_sub_stop}
44+\alias{NURS_sub_stop}
55+\title{Recursively check sub stopping}
66+\usage{
77+NURS_sub_stop(log_vals, log_eps_h)
88+}
99+\arguments{
1010+\item{log_vals}{sub orbit}
1111+1212+\item{log_eps_h}{log(epsilon) + log(h)}
1313+}
1414+\value{
1515+True if sub orbit satisfies stopping criterion.
1616+}
1717+\description{
1818+Recursively check sub stopping
1919+}