Learn R Programming

scorematchingad (version 0.1.1)

tape_uld: Generate a tape of a custom unnormalised log-density

Description

Generate tapes of unnormalised log-densities. Use tape_ult() to specify a custom unnormalised log-density using C++ code much like TMB::compile(). Use tape_uld_inbuilt() for tapes of inbuilt unnormalised log-densities implemented in this package.

Usage

tape_uld_inbuilt(name, x, theta)

tape_uld(fileORcode = "", x, theta, Cppopt = NULL)

Value

A list of three objects

  • fun a function that evaluates the function directly

  • tape a tape of the function

  • file the temporary file storing the final source code passed to Rcpp::sourceCpp()

Arguments

name

Name of an inbuilt function. See details.

x

Value of independent variables for taping.

theta

Value of the dynamic parameter vector for taping.

fileORcode

A character string giving the path name of a file containing the unnormalised log-density definition OR code. fileORcode will be treated as a file name if fileORcode contains no new line characters ('\n' or '\r\n') and has a file extension detected by tools::file_ext().

Cppopt

List of named options passed to Rcpp::sourceCpp()

Writing the <code>fileORcode</code> Argument

The code (possibly in the file pointed to by fileORcode) must be C++ that uses only CppAD and Eigen, which makes it very similar to the requirements of the input to TMB::compile() (which also uses CppAD and Eigen).

The start of code should always be "a1type fname(const veca1 &x, const veca1 &theta){" where fname is your chosen name of the log-density function, x represents a point in the data space and theta is a vector of parameters for the log-density. This specifies that the function will have two vector arguments (of type veca1) and will return a single numeric value (a1type).

The type a1type is a double with special ability for being taped by CppAD. The veca1 type is a vector of a1type elements, with the vector wrapping supplied by the Eigen C++ package (that is an Eigen matrix with 1 column and dynamic number of rows).

The body of the function must use operations from Eigen and/or CppAD, prefixed by Eigen:: and CppAD:: respectively. There are no easy instructions for writing these as it is genuine C++ code, which can be very opaque to those unfamiliar with C++. However, recently ChatGPT and claude.ai have been able to very quickly translating R functions to C++ functions (KLH has been telling these A.I. to use Eigen and CppAD, and giving the definitions of a1type and veca1). I've found the quick reference pages for for Eigen useful. Limited unary and binary operations are available directly from CppAD without Eigen. For the purposes of score matching the operations should all be smooth to create a smooth log-density and the normalising constant may be omitted.

Details

For tape_uld_inbuilt(), currently available unnormalised log-density functions are:

  • dirichlet

  • ppi

  • vMF

  • Bingham

  • FB

The function tape_uld() uses Rcpp::sourceCpp() to generate a tape of a function defined in C++. (An alternative design, where the function is compiled interactively and then taped using a function internal to scorematchingad, was not compatible with Windows OS).

The result result is NOT safe to save or pass to other CPUs in a parallel operation.

See Also

Other tape builders: tape_Hessian(), tape_Jacobian(), tape_gradoffset(), tape_logJacdet(), tape_smd(), tape_swap()

Examples

Run this code
if (FALSE) {
out <- tape_uld(system.file("demo_custom_uld.cpp", package = "scorematchingad"), 
                rep(0.2, 5), rep(-0.1, 5))
out$fun(c(0.1, 0.2, 0.2, 0.2, 0.2), c(-0.5, -0.5, -0.1, -0.1, 0))
out$tape$eval(c(0.1, 0.2, 0.2, 0.2, 0.2), c(-0.5, -0.5, -0.1, -0.1, 0))
out$tape$Jac(c(0.1, 0.2, 0.2, 0.2, 0.2), c(-0.5, -0.5, -0.1, -0.1, 0))
out$tape$name
}

Run the code above in your browser using DataLab