model {
# This is the lower box (indexed by s) in Figure 1 from the paper:
for (s in 1:Subjects) {
# The per-subject ability is called \alpha_s in the paper:
ability[s] ~ dnorm(0, 1);
}
# The precision parameter is called \tau in the paper:
tau.article ~ dgamma(0.001, 0.001);
sd.article <- pow(tau.article, -2);
# This is the upper, outer box (indexed by a) in Figure 1 from the paper:
for (a in 1:Articles) {
# The difficulty of complex articles is called \eta_a in the paper:
diff.article[a] ~ dnorm(0, 1.0e-6);
# The difficulty delta is called \delta_a in the paper:
delta.article[a] ~ dnorm(0, 1.0e-6);
# This is the inner box (indexed by q) in Figure 1 from the paper:
for (q in 1:Questions) {
# This is called \theta^{\mathrm{com}}_{a,q} in the paper:
diff.question[q, a] ~ dnorm(diff.article[a], tau.article);
# This box unifies the treatment of complex and simplified articles.
# diff.item[2, q, a] is called \theta^{\mathrm{com}}_{a,q} and
# diff.item[1, q, a] is called \theta^{\mathrm{sim}}_{a,q} in the paper:
for (c in 1:2) {
# For questions about simplified articles (c = 1), subtract \delta_a
# from \theta^{\mathrm{com}}_{a,q}. For complex articles (c = 2),
# leave the question difficulty unchanged.
diff.item[c, q, a] <- diff.question[q, a] - (2 - c) * delta.article[a];
}
}
}
# By design, not all combinations of subjects, questions, articles,
# and article versions have been observed. We therefore use a
# sparse representation in terms of observations. The subject,
# question, etc. corresponding to each observation are defined in
# reading_data.R. The only wrinkle here is that the version of each
# article (complex or simple) is offset by 1, since array indices
# are 1-based. So 2 means complex, 1 means simple.
for (i in 1:Observations) {
logit(p[i]) <-
ability[subject[i]] - diff.item[1 + complex[i], question[i], article[i]];
# This is called y^v_{s,a,q} in the paper:
correct.response[i] ~ dbern(p[i]);
}
}