StanBlocks.jl
  • Overview
  • Implementations
  • @slic
  • Golf
  • ISBA-2024
  • Crowdsourcing

On this page

  • StanBlocks.jl implementation
    • Post-hoc model adjustment via model component replacement and splicing
  • Full Julia + StanBlocks.jl code to define the models
  • Generated Stan code

Reimplementing the Stan models from https://github.com/seongwoohan/crowdsource-computo-bayes

Author

Nikolas Siccha

The full Julia code for this notebook can be accessed via the top right corner (</> Code).

The Julia packages needed to reproduce this document are StanBlocks.jl (for the model generation) and QuartoComponents.jl (for the “pretty” printing). Both packages have to be installed from the latest main branch (as of Oct 14th 2025).

StanBlocks.jl implementation

The function and model definitions below make use of

  • higher-order user defined functions,
  • variadic functions,
  • “Post-hoc model adjustment via model component replacement and splicing”.

For an explanation of the first two, see the ISBA 2024 example.

Post-hoc model adjustment via model component replacement and splicing

TO DO: elaborate

Full Julia + StanBlocks.jl code to define the models

The following generates all models:

using StanBlocks

@deffun begin 
    increment_at(rv0, idxs::int[n], arg1) = begin 
        rv = rv0
        for i in 1:n
            idx = idxs[i]
            rv[idx] += arg1[idx]
        end
        rv
    end
    increment_at(f, rv0, idxs::int[n], arg1, arg2) = begin 
        rv = rv0
        for i in 1:n
            idx = idxs[i]
            rv[idx] += f(arg1[idx], arg2[idx])
        end
        rv
    end
    vote_count(rating, item, rater, I, J) = increment_at(
        rep_array(0, J + 1), increment_at(rep_array(1, I), item, rating), rep_array(1, I)
    )
    rater_count(rating, rater, J) = increment_at(rep_array(0, J), rater, rating) 
    lte_sim_rng(x, y) = if x == y
        bernoulli_rng(.5)
    else
        x < y
    end
    lte_sim_rng(x::anything[_], y) = jbroadcasted(lte_sim_rng, x, y)
    pos_probs(lambda, delta, alpha_sens, beta_, item, rater) = (
        lambda[item] + (1 - lambda[item]) * inv_logit(delta[item] * (alpha_sens[rater] - beta_[item]))
    )
    neg_probs(lambda, delta, alpha_spec, beta_, item, rater) = (
        (1 - lambda[item]) * inv_logit(-delta[item] * (alpha_spec[rater] - beta_[item]))
    )
    no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda) = jbroadcasted(
        log_sum_exp, 
        increment_at(bernoulli_lpmf, rep_vector(log(pi_), I), item, rating, pos_probs(lambda, delta, alpha_sens, beta_, item, rater)),
        increment_at(bernoulli_lpmf, rep_vector(log1m(pi_), I), item, rating, neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
    ) 
    no_good_name_lpmf(args...) = sum(no_good_name_lpmfs(args...))
    no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda) = begin 
        z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)))
        bernoulli_rng(
            z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
            + (1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    end
    StanBlocks.stan.log_sum_exp(::real, ::real)::real
end

mock_data = (;I=1,J=1,item=[1],rater=[1],rating=[1])

full = @slic mock_data begin 
    votes_data = vote_count(rating, item, rater, I, J)
    rater_data = rater_count(rating, rater, J)
    pi_ ~ beta(2, 2)
    alpha_spec ~ normal(2, 2; n=J)
    alpha_sens ~ normal(1, 2; n=J, lower=-alpha_spec)
    beta_ ~ normal(0, 1; n=I)
    delta ~ lognormal(0, 0.25; n=I)
    lambda ~ beta(2, 2; n=I)
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda)

    rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda)
    votes_sim = vote_count(rating_sim, item, rater, I, J)
    votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data)
    rater_sim = rater_count(rating_sim, rater, J)
    rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data)
end

a_transform = quote 
    lambda = rep_vector(0, I)
end
b_transform = quote 
    delta = rep_vector(1, I)
end
c_transform = quote 
    beta_ = rep_vector(0, I)
end
d_transform = quote 
    alpha_acc ~ normal(1, 2; n=J, lower=0)
    alpha_sens = alpha_acc
    alpha_spec = alpha_acc
end
de_transform = quote 
    alpha_acc_scalar ~ normal(1, 2; lower=0)
    alpha_sens = rep_vector(alpha_acc_scalar, J)
    alpha_spec = rep_vector(alpha_acc_scalar, J)
end
e_transform = quote 
    alpha_spec_scalar ~ normal(2, 2)
    alpha_sens_scalar ~ normal(1, 2; lower=-alpha_spec_scalar)
    alpha_spec = rep_vector(alpha_spec_scalar, J)
    alpha_sens = rep_vector(alpha_sens_scalar, J)
end

a = full(a_transform)
ab = a(b_transform)
abc = ab(c_transform)
abcd = abc(d_transform)
abcde = abc(de_transform)
abce = abc(e_transform)
abd = ab(d_transform)
abde = ab(de_transform)
ac = a(c_transform)
acd = ac(d_transform)
ad = a(d_transform)
b = full(b_transform)
bc = b(c_transform)
bcd = bc(d_transform)
bd = b(d_transform)
c = full(c_transform)
cd_ = c(d_transform)
d = full(d_transform)

posteriors = (;
    full,
    a, ab, abc, abcd, abcde, abce, abd, abde, ac, acd, ad,
    b, bc, bcd, bd,
    c, cd=cd_,
    d,
)

Generated Stan code

  • full
  • a
  • ab
  • abc
  • abcd
  • abcde
  • abce
  • abd
  • abde
  • ac
  • acd
  • ad
  • b
  • bc
  • bcd
  • bd
  • c
  • cd
  • d
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector[J] alpha_spec;
    vector<lower=(-alpha_spec)>[J] alpha_sens;
    vector[I] beta_;
    vector<lower=0.0>[I] delta;
    vector<lower=0, upper=1>[I] lambda;
}
transformed parameters {
}
model {
    pi_ ~ beta(2, 2);
    alpha_spec ~ normal(2, 2);
    alpha_sens ~ normal(1, 2);
    beta_ ~ normal(0, 1);
    delta ~ lognormal(0, 0.25);
    lambda ~ beta(2, 2);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] lambda = rep_vector(0, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector[J] alpha_spec;
    vector<lower=(-alpha_spec)>[J] alpha_sens;
    vector[I] beta_;
    vector<lower=0.0>[I] delta;
}
transformed parameters {
}
model {
    pi_ ~ beta(2, 2);
    alpha_spec ~ normal(2, 2);
    alpha_sens ~ normal(1, 2);
    beta_ ~ normal(0, 1);
    delta ~ lognormal(0, 0.25);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] delta = rep_vector(1, I);
    vector[I] lambda = rep_vector(0, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector[J] alpha_spec;
    vector<lower=(-alpha_spec)>[J] alpha_sens;
    vector[I] beta_;
}
transformed parameters {
}
model {
    pi_ ~ beta(2, 2);
    alpha_spec ~ normal(2, 2);
    alpha_sens ~ normal(1, 2);
    beta_ ~ normal(0, 1);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] beta_ = rep_vector(0, I);
    vector[I] delta = rep_vector(1, I);
    vector[I] lambda = rep_vector(0, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector[J] alpha_spec;
    vector<lower=(-alpha_spec)>[J] alpha_sens;
}
transformed parameters {
}
model {
    pi_ ~ beta(2, 2);
    alpha_spec ~ normal(2, 2);
    alpha_sens ~ normal(1, 2);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] beta_ = rep_vector(0, I);
    vector[I] delta = rep_vector(1, I);
    vector[I] lambda = rep_vector(0, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector<lower=0>[J] alpha_acc;
}
transformed parameters {
    vector<lower=0>[J] alpha_spec = alpha_acc;
    vector<lower=0>[J] alpha_sens = alpha_acc;
}
model {
    pi_ ~ beta(2, 2);
    alpha_acc ~ normal(1, 2);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] beta_ = rep_vector(0, I);
    vector[I] delta = rep_vector(1, I);
    vector[I] lambda = rep_vector(0, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    real<lower=0> alpha_acc_scalar;
}
transformed parameters {
    vector[J] alpha_spec = rep_vector(alpha_acc_scalar, J);
    vector[J] alpha_sens = rep_vector(alpha_acc_scalar, J);
}
model {
    pi_ ~ beta(2, 2);
    alpha_acc_scalar ~ normal(1, 2);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] beta_ = rep_vector(0, I);
    vector[I] delta = rep_vector(1, I);
    vector[I] lambda = rep_vector(0, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    real alpha_spec_scalar;
    real<lower=(-alpha_spec_scalar)> alpha_sens_scalar;
}
transformed parameters {
    vector[J] alpha_spec = rep_vector(alpha_spec_scalar, J);
    vector[J] alpha_sens = rep_vector(alpha_sens_scalar, J);
}
model {
    pi_ ~ beta(2, 2);
    alpha_spec_scalar ~ normal(2, 2);
    alpha_sens_scalar ~ normal(1, 2);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] delta = rep_vector(1, I);
    vector[I] lambda = rep_vector(0, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector<lower=0>[J] alpha_acc;
    vector[I] beta_;
}
transformed parameters {
    vector<lower=0>[J] alpha_spec = alpha_acc;
    vector<lower=0>[J] alpha_sens = alpha_acc;
}
model {
    pi_ ~ beta(2, 2);
    alpha_acc ~ normal(1, 2);
    beta_ ~ normal(0, 1);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] delta = rep_vector(1, I);
    vector[I] lambda = rep_vector(0, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    real<lower=0> alpha_acc_scalar;
    vector[I] beta_;
}
transformed parameters {
    vector[J] alpha_spec = rep_vector(alpha_acc_scalar, J);
    vector[J] alpha_sens = rep_vector(alpha_acc_scalar, J);
}
model {
    pi_ ~ beta(2, 2);
    alpha_acc_scalar ~ normal(1, 2);
    beta_ ~ normal(0, 1);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] beta_ = rep_vector(0, I);
    vector[I] lambda = rep_vector(0, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector[J] alpha_spec;
    vector<lower=(-alpha_spec)>[J] alpha_sens;
    vector<lower=0.0>[I] delta;
}
transformed parameters {
}
model {
    pi_ ~ beta(2, 2);
    alpha_spec ~ normal(2, 2);
    alpha_sens ~ normal(1, 2);
    delta ~ lognormal(0, 0.25);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] beta_ = rep_vector(0, I);
    vector[I] lambda = rep_vector(0, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector<lower=0>[J] alpha_acc;
    vector<lower=0.0>[I] delta;
}
transformed parameters {
    vector<lower=0>[J] alpha_spec = alpha_acc;
    vector<lower=0>[J] alpha_sens = alpha_acc;
}
model {
    pi_ ~ beta(2, 2);
    alpha_acc ~ normal(1, 2);
    delta ~ lognormal(0, 0.25);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] lambda = rep_vector(0, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector<lower=0>[J] alpha_acc;
    vector[I] beta_;
    vector<lower=0.0>[I] delta;
}
transformed parameters {
    vector<lower=0>[J] alpha_spec = alpha_acc;
    vector<lower=0>[J] alpha_sens = alpha_acc;
}
model {
    pi_ ~ beta(2, 2);
    alpha_acc ~ normal(1, 2);
    beta_ ~ normal(0, 1);
    delta ~ lognormal(0, 0.25);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] delta = rep_vector(1, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector[J] alpha_spec;
    vector<lower=(-alpha_spec)>[J] alpha_sens;
    vector[I] beta_;
    vector<lower=0, upper=1>[I] lambda;
}
transformed parameters {
}
model {
    pi_ ~ beta(2, 2);
    alpha_spec ~ normal(2, 2);
    alpha_sens ~ normal(1, 2);
    beta_ ~ normal(0, 1);
    lambda ~ beta(2, 2);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] beta_ = rep_vector(0, I);
    vector[I] delta = rep_vector(1, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector[J] alpha_spec;
    vector<lower=(-alpha_spec)>[J] alpha_sens;
    vector<lower=0, upper=1>[I] lambda;
}
transformed parameters {
}
model {
    pi_ ~ beta(2, 2);
    alpha_spec ~ normal(2, 2);
    alpha_sens ~ normal(1, 2);
    lambda ~ beta(2, 2);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] beta_ = rep_vector(0, I);
    vector[I] delta = rep_vector(1, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector<lower=0>[J] alpha_acc;
    vector<lower=0, upper=1>[I] lambda;
}
transformed parameters {
    vector<lower=0>[J] alpha_spec = alpha_acc;
    vector<lower=0>[J] alpha_sens = alpha_acc;
}
model {
    pi_ ~ beta(2, 2);
    alpha_acc ~ normal(1, 2);
    lambda ~ beta(2, 2);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] delta = rep_vector(1, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector<lower=0>[J] alpha_acc;
    vector[I] beta_;
    vector<lower=0, upper=1>[I] lambda;
}
transformed parameters {
    vector<lower=0>[J] alpha_spec = alpha_acc;
    vector<lower=0>[J] alpha_sens = alpha_acc;
}
model {
    pi_ ~ beta(2, 2);
    alpha_acc ~ normal(1, 2);
    beta_ ~ normal(0, 1);
    lambda ~ beta(2, 2);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] beta_ = rep_vector(0, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector[J] alpha_spec;
    vector<lower=(-alpha_spec)>[J] alpha_sens;
    vector<lower=0.0>[I] delta;
    vector<lower=0, upper=1>[I] lambda;
}
transformed parameters {
}
model {
    pi_ ~ beta(2, 2);
    alpha_spec ~ normal(2, 2);
    alpha_sens ~ normal(1, 2);
    delta ~ lognormal(0, 0.25);
    lambda ~ beta(2, 2);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
    vector[I] beta_ = rep_vector(0, I);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector<lower=0>[J] alpha_acc;
    vector<lower=0.0>[I] delta;
    vector<lower=0, upper=1>[I] lambda;
}
transformed parameters {
    vector<lower=0>[J] alpha_spec = alpha_acc;
    vector<lower=0>[J] alpha_sens = alpha_acc;
}
model {
    pi_ ~ beta(2, 2);
    alpha_acc ~ normal(1, 2);
    delta ~ lognormal(0, 0.25);
    lambda ~ beta(2, 2);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
functions {
array[] int vote_count(
    array[] int rating,
    array[] int item,
    array[] int rater,
    int I,
    int J
) {
    return increment_at(rep_array(0, (J + 1)), increment_at(rep_array(1, I), item, rating), rep_array(1, I));
}
array[] int increment_at(
    array[] int rv0,
    array[] int idxs,
    array[] int arg1
) {
    int n = dims(idxs)[1];
    array[dims(rv0)[1]] int rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += arg1[idx];
    }
    return rv;
}
array[] int rater_count(
    array[] int rating,
    array[] int rater,
    int J
) {
    return increment_at(rep_array(0, J), rater, rating);
}
real no_good_name_lpmf(
    array[] int args1,
    int args2,
    array[] int args3,
    array[] int args4,
    real args5,
    vector args6,
    vector args7,
    vector args8,
    vector args9,
    vector args10
) {
    return sum(no_good_name_lpmfs(args1, args2, args3, args4, args5, args6, args7, args8, args9, args10));
}
vector no_good_name_lpmfs(
    array[] int rating,
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    return jbroadcasted_log_sum_exp(
        increment_at_bernoulli_lpmf(rep_vector(log(pi_), I) | 
            item,
            rating,
            pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
        ),
        increment_at_bernoulli_lpmf(rep_vector(log1m(pi_), I) | 
            item,
            rating,
            neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    );
}
vector jbroadcasted_log_sum_exp(
    vector x1,
    vector x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = log_sum_exp(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
real broadcasted_getindex(vector x, int i) {
    int m = dims(x)[1];
    return x[i];
}
vector increment_at_bernoulli_lpmf(
    vector rv0,
    array[] int idxs,
    array[] int arg1,
    vector arg2
) {
    int n = dims(idxs)[1];
    vector[dims(rv0)[1]] rv = rv0;
    for(i in 1:n) {
        int idx = idxs[i];
        rv[idx] += bernoulli_lpmf(arg1[idx] | arg2[idx]);
    }
    return rv;
}
vector pos_probs(
    vector lambda,
    vector delta,
    vector alpha_sens,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return (lambda[item] + ((1 - lambda[item]) * inv_logit((delta[item] * (alpha_sens[rater] - beta_[item])))));
}
vector neg_probs(
    vector lambda,
    vector delta,
    vector alpha_spec,
    vector beta_,
    array[] int item,
    array[] int rater
) {
    return ((1 - lambda[item]) * inv_logit(((-delta[item]) * (alpha_spec[rater] - beta_[item]))));
}
array[] int no_good_name_rng(
    int I,
    array[] int item,
    array[] int rater,
    real pi_,
    vector alpha_spec,
    vector alpha_sens,
    vector beta_,
    vector delta,
    vector lambda
) {
    vector[I] z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)));
    return bernoulli_rng(
        (
            (z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)) +
            ((1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
        )
    );
}
vector lte_sim_rng(array[] int x, array[] int y) {
    return jbroadcasted_lte_sim_rng(x, y);
}
vector jbroadcasted_lte_sim_rng(
    array[] int x1,
    array[] int x2
) {
    int n = dims(x1)[1];
    vector[n] rv;
    for(i in 1:n) {
        rv[i] = lte_sim_rng(broadcasted_getindex(x1, i), broadcasted_getindex(x2, i));
    }
    return rv;
}
int lte_sim_rng(
    int x,
    int y
) {
    if((x == y)) {
        return bernoulli_rng(0.5);
    } else {
        return (x < y);
    }
}
int broadcasted_getindex(array[] int x, int i) {
    int m = dims(x)[1];
    return x[i];
}
}
data {
    int J;
    int rating_n;
    array[rating_n] int rating;
    int item_n;
    array[item_n] int item;
    int rater_n;
    array[rater_n] int rater;
    int I;
}
transformed data {
    array[(J + 1)] int votes_data = vote_count(rating, item, rater, I, J);
    array[J] int rater_data = rater_count(rating, rater, J);
}
parameters {
    real<lower=0, upper=1> pi_;
    vector<lower=0>[J] alpha_acc;
    vector[I] beta_;
    vector<lower=0.0>[I] delta;
    vector<lower=0, upper=1>[I] lambda;
}
transformed parameters {
    vector<lower=0>[J] alpha_spec = alpha_acc;
    vector<lower=0>[J] alpha_sens = alpha_acc;
}
model {
    pi_ ~ beta(2, 2);
    alpha_acc ~ normal(1, 2);
    beta_ ~ normal(0, 1);
    delta ~ lognormal(0, 0.25);
    lambda ~ beta(2, 2);
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
}
generated quantities {
    vector[I] rating_likelihood = no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_gen = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[item_n] int rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda);
    array[(J + 1)] int votes_sim = vote_count(rating_sim, item, rater, I, J);
    vector[(J + 1)] votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data);
    array[J] int rater_sim = rater_count(rating_sim, rater, J);
    vector[J] rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data);
}
Source Code
---
title: "Reimplementing the Stan models from https://github.com/seongwoohan/crowdsource-computo-bayes"
---

The full Julia code for this notebook can be accessed via the top right corner (`</> Code`).

The Julia packages needed to reproduce this document are [`StanBlocks.jl`](https://github.com/nsiccha/StanBlocks.jl) (for the model generation) and [`QuartoComponents.jl`](https://github.com/nsiccha/QuartoComponents.jl) (for the "pretty" printing). 
Both packages have to be installed from the latest `main` branch (as of Oct 14th 2025).

## StanBlocks.jl implementation

The function and model definitions below make use of 

* higher-order user defined functions, 
* variadic functions,
* "Post-hoc model adjustment via model component replacement and splicing".

For an explanation of the first two, see [the ISBA 2024 example](isba-2024.qmd).

### Post-hoc model adjustment via model component replacement and splicing

TO DO: elaborate


## Full Julia + StanBlocks.jl code to define the models

The following generates all models:

```julia
using StanBlocks

@deffun begin 
    increment_at(rv0, idxs::int[n], arg1) = begin 
        rv = rv0
        for i in 1:n
            idx = idxs[i]
            rv[idx] += arg1[idx]
        end
        rv
    end
    increment_at(f, rv0, idxs::int[n], arg1, arg2) = begin 
        rv = rv0
        for i in 1:n
            idx = idxs[i]
            rv[idx] += f(arg1[idx], arg2[idx])
        end
        rv
    end
    vote_count(rating, item, rater, I, J) = increment_at(
        rep_array(0, J + 1), increment_at(rep_array(1, I), item, rating), rep_array(1, I)
    )
    rater_count(rating, rater, J) = increment_at(rep_array(0, J), rater, rating) 
    lte_sim_rng(x, y) = if x == y
        bernoulli_rng(.5)
    else
        x < y
    end
    lte_sim_rng(x::anything[_], y) = jbroadcasted(lte_sim_rng, x, y)
    pos_probs(lambda, delta, alpha_sens, beta_, item, rater) = (
        lambda[item] + (1 - lambda[item]) * inv_logit(delta[item] * (alpha_sens[rater] - beta_[item]))
    )
    neg_probs(lambda, delta, alpha_spec, beta_, item, rater) = (
        (1 - lambda[item]) * inv_logit(-delta[item] * (alpha_spec[rater] - beta_[item]))
    )
    no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda) = jbroadcasted(
        log_sum_exp, 
        increment_at(bernoulli_lpmf, rep_vector(log(pi_), I), item, rating, pos_probs(lambda, delta, alpha_sens, beta_, item, rater)),
        increment_at(bernoulli_lpmf, rep_vector(log1m(pi_), I), item, rating, neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
    ) 
    no_good_name_lpmf(args...) = sum(no_good_name_lpmfs(args...))
    no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda) = begin 
        z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)))
        bernoulli_rng(
            z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
            + (1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    end
    StanBlocks.stan.log_sum_exp(::real, ::real)::real
end

mock_data = (;I=1,J=1,item=[1],rater=[1],rating=[1])

full = @slic mock_data begin 
    votes_data = vote_count(rating, item, rater, I, J)
    rater_data = rater_count(rating, rater, J)
    pi_ ~ beta(2, 2)
    alpha_spec ~ normal(2, 2; n=J)
    alpha_sens ~ normal(1, 2; n=J, lower=-alpha_spec)
    beta_ ~ normal(0, 1; n=I)
    delta ~ lognormal(0, 0.25; n=I)
    lambda ~ beta(2, 2; n=I)
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda)

    rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda)
    votes_sim = vote_count(rating_sim, item, rater, I, J)
    votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data)
    rater_sim = rater_count(rating_sim, rater, J)
    rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data)
end

a_transform = quote 
    lambda = rep_vector(0, I)
end
b_transform = quote 
    delta = rep_vector(1, I)
end
c_transform = quote 
    beta_ = rep_vector(0, I)
end
d_transform = quote 
    alpha_acc ~ normal(1, 2; n=J, lower=0)
    alpha_sens = alpha_acc
    alpha_spec = alpha_acc
end
de_transform = quote 
    alpha_acc_scalar ~ normal(1, 2; lower=0)
    alpha_sens = rep_vector(alpha_acc_scalar, J)
    alpha_spec = rep_vector(alpha_acc_scalar, J)
end
e_transform = quote 
    alpha_spec_scalar ~ normal(2, 2)
    alpha_sens_scalar ~ normal(1, 2; lower=-alpha_spec_scalar)
    alpha_spec = rep_vector(alpha_spec_scalar, J)
    alpha_sens = rep_vector(alpha_sens_scalar, J)
end

a = full(a_transform)
ab = a(b_transform)
abc = ab(c_transform)
abcd = abc(d_transform)
abcde = abc(de_transform)
abce = abc(e_transform)
abd = ab(d_transform)
abde = ab(de_transform)
ac = a(c_transform)
acd = ac(d_transform)
ad = a(d_transform)
b = full(b_transform)
bc = b(c_transform)
bcd = bc(d_transform)
bd = b(d_transform)
c = full(c_transform)
cd_ = c(d_transform)
d = full(d_transform)

posteriors = (;
    full,
    a, ab, abc, abcd, abcde, abce, abd, abde, ac, acd, ad,
    b, bc, bcd, bd,
    c, cd=cd_,
    d,
)
```

## Generated Stan code


```{julia}
using StanBlocks, QuartoComponents

@deffun begin 
    increment_at(rv0, idxs::int[n], arg1) = begin 
        rv = rv0
        for i in 1:n
            idx = idxs[i]
            rv[idx] += arg1[idx]
        end
        rv
    end
    increment_at(f, rv0, idxs::int[n], arg1, arg2) = begin 
        rv = rv0
        for i in 1:n
            idx = idxs[i]
            rv[idx] += f(arg1[idx], arg2[idx])
        end
        rv
    end
    vote_count(rating, item, rater, I, J) = increment_at(
        rep_array(0, J + 1), increment_at(rep_array(1, I), item, rating), rep_array(1, I)
    )
    rater_count(rating, rater, J) = increment_at(rep_array(0, J), rater, rating) 
    lte_sim_rng(x, y) = if x == y
        bernoulli_rng(.5)
    else
        x < y
    end
    lte_sim_rng(x::anything[_], y) = jbroadcasted(lte_sim_rng, x, y)
    pos_probs(lambda, delta, alpha_sens, beta_, item, rater) = (
        lambda[item] + (1 - lambda[item]) * inv_logit(delta[item] * (alpha_sens[rater] - beta_[item]))
    )
    neg_probs(lambda, delta, alpha_spec, beta_, item, rater) = (
        (1 - lambda[item]) * inv_logit(-delta[item] * (alpha_spec[rater] - beta_[item]))
    )
    no_good_name_lpmfs(rating, I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda) = jbroadcasted(
        log_sum_exp, 
        increment_at(bernoulli_lpmf, rep_vector(log(pi_), I), item, rating, pos_probs(lambda, delta, alpha_sens, beta_, item, rater)),
        increment_at(bernoulli_lpmf, rep_vector(log1m(pi_), I), item, rating, neg_probs(lambda, delta, alpha_spec, beta_, item, rater))
    ) 
    no_good_name_lpmf(args...) = sum(no_good_name_lpmfs(args...))
    no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda) = begin 
        z_sim = to_vector(bernoulli_rng(rep_vector(pi_, I)))
        bernoulli_rng(
            z_sim[item] .* pos_probs(lambda, delta, alpha_sens, beta_, item, rater)
            + (1 - z_sim[item]) .* neg_probs(lambda, delta, alpha_spec, beta_, item, rater)
        )
    end
    StanBlocks.stan.log_sum_exp(::real, ::real)::real
end

mock_data = (;I=1,J=1,item=[1],rater=[1],rating=[1])

full = @slic mock_data begin 
    votes_data = vote_count(rating, item, rater, I, J)
    rater_data = rater_count(rating, rater, J)
    pi_ ~ beta(2, 2)
    alpha_spec ~ normal(2, 2; n=J)
    alpha_sens ~ normal(1, 2; n=J, lower=-alpha_spec)
    beta_ ~ normal(0, 1; n=I)
    delta ~ lognormal(0, 0.25; n=I)
    lambda ~ beta(2, 2; n=I)
    rating ~ no_good_name(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda)

    rating_sim = no_good_name_rng(I, item, rater, pi_, alpha_spec, alpha_sens, beta_, delta, lambda)
    votes_sim = vote_count(rating_sim, item, rater, I, J)
    votes_sim_lt_data = lte_sim_rng(votes_sim, votes_data)
    rater_sim = rater_count(rating_sim, rater, J)
    rater_sim_lt_data = lte_sim_rng(rater_sim, rater_data)
end

a_transform = quote 
    lambda = rep_vector(0, I)
end
b_transform = quote 
    delta = rep_vector(1, I)
end
c_transform = quote 
    beta_ = rep_vector(0, I)
end
d_transform = quote 
    alpha_acc ~ normal(1, 2; n=J, lower=0)
    alpha_sens = alpha_acc
    alpha_spec = alpha_acc
end
de_transform = quote 
    alpha_acc_scalar ~ normal(1, 2; lower=0)
    alpha_sens = rep_vector(alpha_acc_scalar, J)
    alpha_spec = rep_vector(alpha_acc_scalar, J)
end
e_transform = quote 
    alpha_spec_scalar ~ normal(2, 2)
    alpha_sens_scalar ~ normal(1, 2; lower=-alpha_spec_scalar)
    alpha_spec = rep_vector(alpha_spec_scalar, J)
    alpha_sens = rep_vector(alpha_sens_scalar, J)
end

a = full(a_transform)
ab = a(b_transform)
abc = ab(c_transform)
abcd = abc(d_transform)
abcde = abc(de_transform)
abce = abc(e_transform)
abd = ab(d_transform)
abde = ab(de_transform)
ac = a(c_transform)
acd = ac(d_transform)
ad = a(d_transform)
b = full(b_transform)
bc = b(c_transform)
bcd = bc(d_transform)
bd = b(d_transform)
c = full(c_transform)
cd_ = c(d_transform)
d = full(d_transform)

posteriors = (;
    full,
    a, ab, abc, abcd, abcde, abce, abd, abde, ac, acd, ad,
    b, bc, bcd, bd,
    c, cd=cd_,
    d,
)

 map(posteriors) do posterior 
    QuartoComponents.Code("stan", stan_code(posterior))
end |> QuartoComponents.Tabset
```