stan-dev / stanc3

The Stan transpiler (from Stan to C++ and beyond).
BSD 3-Clause "New" or "Revised" License
142 stars 46 forks source link

[BUG] missing signature for normal_id_glm #1143

Closed avehtari closed 2 years ago

avehtari commented 2 years ago

Current Behavior:

Using CmdStan 2.29.1 (via CmdStanR), getting stanc error

Ill-typed arguments supplied to function 'normal_id_glm':
(vector, matrix, real, vector, vector)

This signature makes sense and is listed in the documentation as available since 2.25 https://mc-stan.org/docs/2_29/functions-reference/normal-id-glm.html

Expected Behavior:

Expected to work with this signature

Model Code

functions {
#include gpbasisfun_functions.stan
}
data {
  int<lower=1> N;      // number of observations
  vector[N] x;         // univariate covariate
  vector[N] y;         // target variable

  real<lower=0> c_f;   // factor c to determine the boundary value L
  int<lower=1> M_f;    // number of basis functions
  real<lower=0> c_g;   // factor c to determine the boundary value L
  int<lower=1> M_g;    // number of basis functions
}
transformed data {
  // Normalize data
  real xmean = mean(x);
  real ymean = mean(y);
  real xsd = sd(x);
  real ysd = sd(y);
  vector[N] xn = (x - xmean)/xsd;
  vector[N] yn = (y - ymean)/ysd;
  // Basis functions for f
  real L_f = c_f*max(xn);
  matrix[N,M_f] PHI_f = PHI(N, M_f, L_f, xn);
  // Basis functions for g
  real L_g= c_g*max(xn);
  matrix[N,M_g] PHI_g = PHI(N, M_g, L_g, xn);
}
parameters {
  real intercept_f;
  real intercept_g;
  vector[M_f] beta_f;          // the basis functions coefficients
  vector[M_g] beta_g;          // the basis functions coefficients
  real<lower=0> lengthscale_f; // lengthscale of f
  real<lower=0> sigma_f;       // scale of f
  real<lower=0> lengthscale_g; // lengthscale of g
  real<lower=0> sigma_g;       // scale of g
}
model {
  // spectral densities for f and g
  vector[M_f] diagSPD_f = diagSPD_EQ(sigma_f, lengthscale_f, L_f, M_f);
  vector[M_g] diagSPD_g = diagSPD_EQ(sigma_g, lengthscale_g, L_g, M_g);
  // priors
  intercept_f ~ normal(0, 1);
  intercept_g ~ normal(0, 1);
  beta_f ~ normal(0, 1);
  beta_g ~ normal(0, 1);
  lengthscale_f ~ normal(0, 1);
  lengthscale_g ~ normal(0, 1);
  sigma_f ~ normal(0, .5);
  sigma_g ~ normal(0, .5);
  // model
  yn ~ normal_id_glm(PHI_f, intercept_f, (diagSPD_f .* beta_f),
          exp(intercept_g + PHI_g * (diagSPD_g .* beta_g))) ;
}
generated quantities {
  vector[N] f;
  vector[N] sigma;
  {
    // spectral densities
    vector[M_f] diagSPD_f = diagSPD_EQ(sigma_f, lengthscale_f, L_f, M_f);
    vector[M_g] diagSPD_g = diagSPD_EQ(sigma_g, lengthscale_g, L_g, M_g);
    // function scaled back to the original scale
    f = (intercept_f + PHI_f * (diagSPD_f .* beta_f))*ysd + ymean;
    sigma = exp(intercept_g + PHI_g * (diagSPD_g .* beta_g))*ysd;
  }
}

Anything else:

Notebook with data https://avehtari.github.io/casestudies/Motorcycle/motorcycle_gpcourse.html

@SteveBronder has played with this model

rok-cesnovar commented 2 years ago

Ah, that, unfortunately, is a docs "bug".

Prior to the last release, we found that there is a huge mess around normal_id_glm_lpdf. There were signatures that were listed in these docs, but were not actually supported and there were supported signatures that were not listed in the docs. See https://github.com/stan-dev/stanc3/issues/1080#issuecomment-1003730528

It seems that the mess was not cleaned up as we hoped. That should be a row_vector x listed instead of matrix x I believe.

We can definitely add that signature though if it makes sense.

rok-cesnovar commented 2 years ago

The actual supported signatures in stanc3 are:

normal_id_glm_lpdf(real, matrix, real, vector, real) => real
normal_id_glm_lpdf(real, matrix, real, vector, vector) => real
normal_id_glm_lpdf(real, matrix, vector, vector, real) => real
normal_id_glm_lpdf(real, matrix, vector, vector, vector) => real
normal_id_glm_lpdf(vector, row_vector, real, vector, real) => real
normal_id_glm_lpdf(vector, row_vector, real, vector, vector) => real
normal_id_glm_lpdf(vector, row_vector, vector, vector, real) => real
normal_id_glm_lpdf(vector, row_vector, vector, vector, vector) => real
normal_id_glm_lpdf(vector, matrix, real, vector, real) => real
normal_id_glm_lpdf(vector, matrix, vector, vector, real) => real

opened a docs issue https://github.com/stan-dev/docs/issues/503

avehtari commented 2 years ago

Looking at the supported signatures, the signature I need makes completely sense. Just looking at the combinatorics in the list, it is missing logical combinations

normal_id_glm_lpdf(vector, matrix, real, vector, vector) => real
normal_id_glm_lpdf(vector, matrix, vector, vector, vector) => real
WardBrian commented 2 years ago

Is this simply a matter of adding them to stanc, or does additional C++ support need to be added first?

rok-cesnovar commented 2 years ago

Only stanc, Math supports all combinations.