Introduction

This vignette demonstrates how to handle cases where your Stan program contains deprecated features resulting in deprecation warnings. In most cases, the Stan-to-C++ compiler can be used to automatically update your code to a non-deprecated feature that replaces the deprecated one. This vignette showcases how that automatic conversion can be done using CmdStanR.

The automatic conversion of deprecated features to non-deprecated features is done using the so-called “canonicalizer”, which is part of the Stan-to-C++ compiler. We recommend using CmdStan 2.29.2 or later when using the canonicalizer and this vignette. The minimum CmdStanR version to run the code in the vignette is 0.5.0.

library(cmdstanr)
check_cmdstan_toolchain(fix = TRUE, quiet = TRUE)

Deprecation warnings

The following logistic regression model uses several deprecated language features, resulting in several warnings during compilation.

stan_file <- write_stan_file("
data {
  int<lower=1> k;
  int<lower=0> n;
  matrix[n, k] X;
  int y[n];
}
parameters {
  vector[k] beta;
  real alpha;
}
model {
  # priors
  target += std_normal_log(beta);
  alpha ~ std_normal();

  y ~ bernoulli_logit(X * beta + alpha);
}
")
mod <- cmdstan_model(stan_file)
Warning in '/var/folders/s0/zfzm55px2nd2v__zlw5xfj2h0000gn/T/RtmpMBUSHs/model-17e6a34f96f68.stan', line 6, column 2: Declaration
    of arrays by placing brackets after a variable name is deprecated and
    will be removed in Stan 2.33.0. Instead use the array keyword before the
    type. This can be changed automatically using the auto-format flag to
    stanc
Warning in '/var/folders/s0/zfzm55px2nd2v__zlw5xfj2h0000gn/T/RtmpMBUSHs/model-17e6a34f96f68.stan', line 13, column 2: Comments
    beginning with # are deprecated and this syntax will be removed in Stan
    2.33.0. Use // to begin line comments; this can be done automatically
    using the auto-format flag to stanc
Warning in '/var/folders/s0/zfzm55px2nd2v__zlw5xfj2h0000gn/T/RtmpMBUSHs/model-17e6a34f96f68.stan', line 14, column 12: std_normal_log
    is deprecated and will be removed in Stan 2.33.0. Use std_normal_lpdf
    instead. This can be automatically changed using the canonicalize flag
    for stanc

The first warning is about using the deprecated array syntax

int y[n];

which should be replaced with the new syntax using the array keyword:

array[n] int y;

The second warning is about using the deprecated commenting symbol #, which should be replaced by //.

The last warning is about the use of the deprecated _log suffix for probability density and mass functions. In this case the _log suffix should be replaced with _lpdf. For probability mass functions the suffix _lpmf is used.

We can go and fix these issues manually or use the canonicalizer as outlined in the next section.

Using the canonicalizer

The canonicalizer is available through the canonicalize argument of the $format() method of the CmdStanModel class. The arguments accepts TRUE and FALSE values, in which case all or none of the features of the canonicalizer are used. It can also accept a list of character vectors that determine which features of the canonicalizer to use.

The canonincalizer in CmdStan 2.29.2 supports four features: parentheses, braces, includes and deprecations. The parentheses and braces features clean up the use of parentheses and braces, while includes will replace #include statements with the code from the included files. See the canonicalizer section of the Stan User’s Guide for more details.

In this vignette we will be using the deprecations feature that replaces deprecated Stan model features with non-deprecated ones if possible.

mod$format(canonicalize = list("deprecations"))
data {
  int<lower=1> k;
  int<lower=0> n;
  matrix[n, k] X;
  array[n] int y;
}
parameters {
  vector[k] beta;
  real alpha;
}
model {
  // priors
  target += std_normal_lpdf(beta);
  alpha ~ std_normal();
  
  y ~ bernoulli_logit(X * beta + alpha);
}

By default, the format function will print the resulting model code. We can see that all three issues were resolved. y is now defined using the new array keyword, the comment uses // and the std_normal_log() is replaced with std_normal_lpdf().

You can also use the $format() method to write the updated version of the model directly to the Stan model file. That can be enabled by setting overwrite_file = TRUE. The previous version of the file will automatically be backed up to a file with the .stan.bak suffix. If that is not desired or you are using a version system and making a backup is redundant, you can disable it by setting backup = FALSE.

mod$format(
    canonicalize = list("deprecations"),
    overwrite_file = TRUE,
    backup = FALSE
)
mod$print()
data {
  int<lower=1> k;
  int<lower=0> n;
  matrix[n, k] X;
  array[n] int y;
}
parameters {
  vector[k] beta;
  real alpha;
}
model {
  // priors
  target += std_normal_lpdf(beta);
  alpha ~ std_normal();
  
  y ~ bernoulli_logit(X * beta + alpha);
}