I bet that this is easy but I’m having a bit of trouble. I have a function that is defined in a .stan file but it is not wrapped in functions { } because I may have a bunch of these I want to reference in my stan program like
functions {
#include my_fun.stan
}
data {
...
and in cmdstanr I run the program as
fp <- file.path("./full_program.stan")
mod <- cmdstan_model(fp, include_paths = "./function_file_path/")
Can I expose stan functions using rstan on the my_fun.stan function?
Hey there!
Are you looking for something like this?
Cheers,
Max
If the contents of my_fun.stan is not enclosed in functions {} it will not compile.
I think the easiest solutions here are:
- concat new Stan code by enclosing my_fun.stan in a
functions {} block
- auto-format the
full_program.stan to generate a model with #includes replaced with the code from the files and use the experimental rstan 2.26 (it will work with that).
Can you give some more detail on solution 2?
Sure.
Say we have my_fun.stan:
real foo(real a, real b) {
return a + b;
}
real goo(real a, real b) {
return a - b;
}
and full.stan:
functions {
#include "my_fun.stan"
}
parameters {
real y;
}
model {
y ~ std_normal();
}
library(cmdstanr)
library(rstan)
auto_format <- function(stan_file, include_paths = NULL) {
if(isTRUE(.Platform$OS.type == "windows")) {
stanc <- file.path(cmdstan_path(), "bin", "stanc.exe")
} else {
stanc <- file.path(cmdstan_path(), "bin", "stanc")
}
stancflags_val <- NULL
if (!is.null(include_paths)) {
include_paths <- paste0(include_paths, collapse = ",")
include_paths_flag <- " --include-paths="
include_paths_flag <- " --include_paths="
stancflags_val <- trimws(paste0(include_paths_flag, include_paths, " "))
}
args = c(
"--auto-format",
stan_file,
stancflags_val
)
processx::run(
stanc,
args = args,
echo_cmd = TRUE
)$stdout
}
setwd("~/Desktop/testing/standalone/")
fp <- file.path("full.stan")
p <- auto_format(fp, include_paths = ".")
full_temp_file <- write_stan_file(p)
expose_stan_functions(full_temp_file)
> foo(2,3)
[1] 5
> goo(2,3)
[1] -1
The auto-format parts could be done with rstan I think, but I had the auto format thing ready for cmdstanr for other purposes. Will update if I have time to explore rstan a bit.
The rstan I used is the development version from our repo:
install.packages("StanHeaders", repos = c("https://mc-stan.org/r-packages/", getOption("repos")))
install.packages("rstan", repos = c("https://mc-stan.org/r-packages/", getOption("repos")))
Actually, ignore the above. You can just do:
fp <- file.path("full.stan")
expose_stan_functions(fp, includes = ".")
and you get all the functions exposed.
install.packages("StanHeaders", repos = c("https://mc-stan.org/r-packages/", getOption("repos")))
install.packages("rstan", repos = c("https://mc-stan.org/r-packages/", getOption("repos")))
You might get a redefined something warning, but ignore it.