Tukey-Lambda Distribution

The Tukey-Lambda distribution doesn’t have a closed form. Is there a way to implement this distribution in Stan?

Hi, we will need a bit more information. Do you have any references we can follow?

1 Like

The first search result:

The quantile function (inverse CDF) has closed form so in theory it’s possible to implement this with Stan’s algebraic equation solver.
Here’s what I came up with. (caveat: this emits a lot a of warnings so a different parameterization may be needed for reliable inference)

functions {
    real tukey_q(real logit_p, real lambda) {
        real log_p = log_inv_logit(logit_p);
        real log1m_p = log1m_inv_logit(logit_p);
        real s = lambda*log_p;
        real t = lambda*log1m_p;
        if (abs(s) > 1e-6 || abs(t) > 1e-6)
          return (exp(s) - exp(t))/lambda;
        else
          return (log_p - log1m_p) + (s*log_p - t*log1m_p);
    }
    real tukey_rng(real lambda) {
        real q = uniform_rng(0, 1);
        return tukey_q(logit(q), lambda);
    }
    vector tukey_system(vector logit_p, vector theta, real[] _y, int[] _z) {
        return [tukey_q(logit_p[1], theta[1])-theta[2]]';
    }
    real tukey_lcdf(real x, real lambda) {
        vector[1] logit_p = algebra_solver(tukey_system, [0.0]', [lambda, x]', {0.0},{0});
        return log_inv_logit(logit_p[1]);
    }
    real tukey_lpdf(real x, real lambda) {
        vector[1] logit_p = algebra_solver(tukey_system, [0.0]', [lambda, x]', {0.0},{0});
        real log_p = log_inv_logit(logit_p[1]);
        real log1m_p = log1m_inv_logit(logit_p[1]);
        return -log_sum_exp((lambda-1)*log_p, (lambda-1)*log1m_p);
    }
}
data {
    real lambda;
}
parameters {
    real x;
}
model {
    x ~ tukey(lambda);
}
generated quantities {
    real z = tukey_rng(lambda);
}
3 Likes