Using `nimbleFunction`s as first-class objects?

52 views
Skip to first unread message

Scott Brown

unread,
Jan 11, 2024, 11:15:25 AM1/11/24
to nimble-users
Can I pass a `nimbleFunction` to another `nimbleFunction`?

My specific use case is that I would like to define my model to accept arbitrary kernel functions.  Viz. I define many kernel `nimbleFunction`s, such as a Gaussian kernel, or a Matern kernel that conform to a particular interfaace, and then define additional `nimbleFunction`s that use those functions in the same way.  

Here is my naive approach that doesn't work as hoped:

```
gpCov <- function(kernelFunc) {
  nimbleFunction(
    run = function(
      dists = double(2),
      rho = double(0),
      sigma = double(0),
      nugget = double(0)
    ) {
      returnType(double(2))
      ret <- sigma*sigma*kernelFunc(dists/(2*sqrt(rho)))
      diag(ret) <- diag(ret) + nugget
      return(ret)
    })
}
```


Daniel Turek

unread,
Jan 11, 2024, 1:14:51 PM1/11/24
to Scott Brown, nimble-users
Scott, great question.  I sketched out below the "nimble" way to do this.

Hopefully this should get you going, but let me know if you have any questions.

Daniel




kernel_base <- nimbleFunctionVirtual(
    name = 'kernel_base',
    run = function(x = double(2)) { returnType(double(2)) }
)

kernel1 <- nimbleFunction(
    contains = kernel_base,
    setup = TRUE,
    run = function(x = double(2)) {
        returnType(double(2))
        ## some code here
        return(something)
    }
)

kernel2 <- nimbleFunction(
    contains = kernel_base,
    setup = TRUE,
    run = function(x = double(2)) {
        returnType(double(2))
        ## some other code here
        return(something)
    }
)

gpCov_general <- nimbleFunction(
    setup = function(kernelFunc) {
        kernelList <- nimbleFunctionList(kernel_base)
        kernelList[[1]] <- kernelFunc()
    },

    run = function(
                   dists = double(2),
                   rho = double(0),
                   sigma = double(0),
                   nugget = double(0)
                   ) {
        returnType(double(2))
        ret <- sigma * sigma * kernelList[[1]]$run(dists/(2*sqrt(rho)))

        diag(ret) <- diag(ret) + nugget
        return(ret)
    }
)

gpCov_kernel1 <- gpCov_general(kernel1)
gpCov_kernel1$run(...)

gpCov_kernel2 <- gpCov_general(kernel2)
gpCov_kernel2$run(...)




--
You received this message because you are subscribed to the Google Groups "nimble-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nimble-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/nimble-users/625553ca-4d92-47cb-a7b1-76602250dbb0n%40googlegroups.com.

Perry de Valpine

unread,
Jan 11, 2024, 1:19:02 PM1/11/24
to Daniel Turek, Scott Brown, nimble-users
However, at the moment, unfortunately, it is not supported to use the setup in model code. That is, you could not use gpCov_kernel1 in model code.

Reply all
Reply to author
Forward
0 new messages