SuperGauss: Superfast Likelihood Inference for Stationary Gaussian Time Series

Yun Ling, Martin Lysy


Description

Likelihood evaluations for stationary Gaussian time series are typically obtained via the Durbin-Levinson algorithm, which scales as O(N^2) in the number of time series observations. This package provides a "superfast" O(N log^2 N) algorithm written in C++, crossing over with Durbin-Levinson around N = 300. Efficient implementations of the score and Hessian functions are also provided, leading to superfast versions of inference algorithms such as Newton-Raphson and Hamiltonian Monte Carlo. The C++ code provides a Toeplitz matrix class and a NormalToeplitz distribution class packaged as a header-only library, to simplify low-level usage in other packages and outside of R. A complete description of the algorithms is available in this preprint.

Installation

Version 1.0.2 is available on CRAN, but in order to install this much-updated development version from GitHub, it is necessary to first install the FFTW library:

Once you have successfully installed FFTW, SuperGauss can be installed from GitHub via the command:

# devtools::install_github("mlysy/SuperGauss")
install.packages("SuperGauss", repos = c('https://mlysy.r-universe.dev', 'https://cloud.r-project.org'))

R API

Please see the package vignette.

C++ API

The NormalToeplitz class corresponds to the distribution

z ~ N( 0, Tz = Toeplitz(acf) ),

where z is an N-dimensional vector and Tz is a symmetric positive-definite Toeplitz variance matrix with "autocorrelation" (i.e., first row/column) acf. Extensive member documentation is provided by Doxygen code comments, but very briefly we have the following:

NormalToeplitz NTz(N); // constructor

// log-density.  both z and acf are `double*`
ld = NTz.logdens(z, acf); 

// log-density gradient wrt z and/or acf
// dldz, dlda: `double*` outputs
// z, acf: `double*` inputs
// calc_dldz, calc_dlda: `bool` to calculate one or both gradients.
// when e.g., `calc_dldz = false`, `dldz` is not modified.
NTz.grad_full(dldz, dlda, z, acf, calc_dldz, calc_dlda)