Handling deprecated Stan features with the canonicalizer in CmdStanR • cmdstanr
Description: cmdstanr

## 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);
    }