def _sample_cond_single(rng, marginal_pmf, n_group, out, eps):
"""Single sample from conditional probab. (call :func:`self.sample`)"""
n_sites = len(marginal_pmf[-1])
# Probability of the incomplete output. Empty output has unit probab.
out_p = 1.0
# `n_out` sites of the output have been sampled. We will add
# at most `n_group` sites to the output at a time.
for n_out in range(0, n_sites, n_group):
# Select marginal probability distribution on (at most)
# `n_out + n_group` sites.
p = marginal_pmf[min(n_sites, n_out + n_group)]
# Obtain conditional probab. from joint `p` and marginal `out_p`
p = p.get(tuple(out[:n_out]) + (slice(None),) * (len(p) - n_out))
p = project_pmf(mp.prune(p).to_array() / out_p, eps, eps)
# Sample from conditional probab. for next `n_group` sites
choice = rng.choice(p.size, p=p.flat)
out[n_out:n_out + n_group] = np.unravel_index(choice, p.shape)
# Update probability of the partial output
out_p *= np.prod(p.flat[choice])
# Verify we have the correct partial output probability
p = marginal_pmf[-1].get(tuple(out)).to_array()
assert abs(p - out_p) <= eps
评论列表
文章目录