# Buggy code
def random(self, point=None, size=None):
    """
    Draw random values from ZeroInflatedNegativeBinomial distribution.

    Parameters
    ----------
    point : dict, optional
        Dict of variable values on which random values are to be
        conditioned (uses default point if not specified).
    size : int, optional
        Desired size of random sample (returns one sample if not
        specified).

    Returns
    -------
    array
    """
    mu, alpha, psi = draw_values(
        [self.mu, self.alpha, self.psi], point=point, size=size
    )
    g = generate_samples(
        stats.gamma.rvs, alpha, scale=mu / alpha, dist_shape=self.shape, size=size
    )
    g[g == 0] = np.finfo(float).eps  # Just in case
    g, psi = broadcast_distribution_samples([g, psi], size=size)
    return stats.poisson.rvs(g) * (np.random.random(g.shape) < psi)


# Traceback (ValueError)
ValueError                                Traceback (most recent call last)
~/projects/xplan/xplan-experiment-analysis/sample_prior_predictive_error.py in <module>
8
9 with model:
---> 10     pre_trace = pm.sample_prior_predictive()

/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pymc3/sampling.py in sample_prior_predictive(samples, model, vars, var_names, random_seed)
1320     names = get_default_varnames(model.named_vars, include_transformed=False)
1321     # draw_values fails with auto-transformed variables. transform them later!
-> 1322     values = draw_values([model[name] for name in names], size=samples)
1323
1324     data = {k: v for k, v in zip(names, values)}

/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pymc3/distributions/distribution.py in draw_values(params, point, size)
393                                         point=point,
394                                         givens=temp_givens,
--> 395                                         size=size)
396                     givens[next_.name] = (next_, value)
397                     drawn[(next_, size)] = value

/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pymc3/distributions/distribution.py in _draw_value(param, point, givens, size)
579                         else:
580                             dist_tmp.shape = val.shape
--> 581                 return dist_tmp.random(point=point, size=size)
582             else:
583                 return param.distribution.random(point=point, size=size)

/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pymc3/distributions/continuous.py in random(self, point, size)
668             [self.mu, self.sigma, self.lower, self.upper], point=point, size=size)
669         return generate_samples(stats.truncnorm.rvs,
--> 670                                 a=(a_v - mu_v)/std_v,
671                                 b=(b_v - mu_v) / std_v,
672                                 loc=mu_v,

ValueError: operands could not be broadcast together with shapes (500,1031) (500,)

# Fixed code
def random(self, point=None, size=None):
    """
    Draw random values from ZeroInflatedNegativeBinomial distribution.

    Parameters
    ----------
    point : dict, optional
        Dict of variable values on which random values are to be
        conditioned (uses default point if not specified).
    size : int, optional
        Desired size of random sample (returns one sample if not
        specified).

    Returns
    -------
    array
    """
    mu, alpha, psi = draw_values(
        [self.mu, self.alpha, self.psi], point=point, size=size
    )
    g = generate_samples(
        self._random, mu=mu, alpha=alpha, dist_shape=self.shape, size=size
    )
    g[g == 0] = np.finfo(float).eps  # Just in case
    g, psi = broadcast_distribution_samples([g, psi], size=size)
    return stats.poisson.rvs(g) * (np.random.random(g.shape) < psi)