# Path: bmlingam/prob.py
# def sample_gg(scov, beta, n_samples, rng, dim, normalize):
#     """Draw samples from GG distribution. 
# 
#     See: Gómez, E., Gomez-Viilegas, M. A., & Marin, J. M. (1998). 
#     A multivariate generalization of the power exponential family of distributions. 
#     Communications in Statistics-Theory and Methods, 27(3), 589-600.
# 
#     Parameters
#     ----------
#     scov: numpy.ndarray, shape=(dim, dim)
#         A scaled covariance matrix. For beta=1, it becomes the covariance matrix. 
# 
#     beta: float
#         Shape parameter, a positive value. 
# 
#     n_samples: int
#         Number of samples. 
# 
#     rng: numpy.random.RandomState
#         Random number generator. 
# 
#     dim: int 
#         The dimension of the distribution. 
# 
#     normalize: bool
#         If true, each dimension is normalized such that its variance is 1. 
#     """
#     # Draw samples from unit sphere
#     gs = rng.normal(0, 1, size=(n_samples, dim))
#     ss = gs + sign(sign(gs) + 1e-10) * 1e-10
#     ns = np.linalg.norm(ss, ord=2, axis=1)[:, np.newaxis]
#     us = ss / ns
# 
#     # Draw samples from GG
#     S = np.linalg.cholesky(scov).T
#     ts = rng.gamma(shape=dim / (2.0 * beta), scale=2.0, 
#                    size=n_samples)[:, np.newaxis]
#     xs = (ts**(1.0 / (2.0 * beta))) * us.dot(S)
# 
#     if normalize:
#         v = (2**(1.0 / beta) * gamma((dim + 2.0) / (2.0 * beta))) / \
#             (dim * gamma(dim / (2.0 * beta)))
#         xs = xs / np.sqrt(v * np.diag(scov))
# 
#     return xs
# 
# def multivariatet(mu, Sigma, N, M, rng):
#     """Return a sample (or samples) from the multivariate t distribution.
# 
#     This function is adopted from 
#     http://kennychowdhary.me/2013/03/python-code-to-generate-samples-from-multivariate-t/.
# 
#     :param mu: Mean.
#     :type mu: ndarray, shape=(n_dim,), dtype=float
#     :param Sigma: Scaling matrix.
#     :type Sigma: ndarray, shape=(n_dim, n_dim), dtype=float
#     :param float N: Degrees of freedom.
#     :param int M: Number of samples to produce. 
#     :param np.random.RandomState rng: Random number generator. 
#     :return: M samples of (n_dim)-dimensional multivariate t distribution.
#     :rtype: ndarray, shape=(n_samples, n_dim), dtype=float
# 
#     """
#     d = len(Sigma)
#     g = np.tile(rng.gamma(N/2., 2./N, M), (d, 1)).T
#     Z = rng.multivariate_normal(np.zeros(d), Sigma, M)
#     return mu + Z / np.sqrt(g)


from itertools import chain
from parse import parse
from bmlingam.prob import sample_gg, multivariatet
import numpy as np

        L_cov_21 = rng.uniform(r[0], r[1])
        return np.array([[1.0, L_cov_21], 
                         [L_cov_21, 1.0]])

def _cache_mu_indvdl(
    prior_indvdls, L_covs, df_indvdls, beta_coeffs, n_mc_samples, n_samples, 
    rng):
    # Define conditional parameter sets
    df_indvdls_ = lambda p: df_indvdls if p == 't' else [None]
    beta_coeffs_ = lambda p: beta_coeffs if p == 'gg' else [None]

    # Make list of parameter sets
    paramss = flt([
        [
            (prior_indvdl, L_cov, df_indvdl, beta)
            for df_indvdl in df_indvdls_(prior_indvdl)
            for beta in beta_coeffs_(prior_indvdl)
        ]
        for prior_indvdl in prior_indvdls
        for L_cov in L_covs
    ])

    # Define function to draw random samples
    def f(params):
        prior_indvdl = params[0]
        L_covs = [_get_L_cov(params[1], rng) for _ in range(n_mc_samples)]
        df_L = params[2]
        beta = params[3]

        if prior_indvdl == 't':

# Path: bmlingam/prob.py
# def sample_gg(scov, beta, n_samples, rng, dim, normalize):
#     """Draw samples from GG distribution. 
# 
#     See: Gómez, E., Gomez-Viilegas, M. A., & Marin, J. M. (1998). 
#     A multivariate generalization of the power exponential family of distributions. 
#     Communications in Statistics-Theory and Methods, 27(3), 589-600.
# 
#     Parameters
#     ----------
#     scov: numpy.ndarray, shape=(dim, dim)
#         A scaled covariance matrix. For beta=1, it becomes the covariance matrix. 
# 
#     beta: float
#         Shape parameter, a positive value. 
# 
#     n_samples: int
#         Number of samples. 
# 
#     rng: numpy.random.RandomState
#         Random number generator. 
# 
#     dim: int 
#         The dimension of the distribution. 
# 
#     normalize: bool
#         If true, each dimension is normalized such that its variance is 1. 
#     """
#     # Draw samples from unit sphere
#     gs = rng.normal(0, 1, size=(n_samples, dim))
#     ss = gs + sign(sign(gs) + 1e-10) * 1e-10
#     ns = np.linalg.norm(ss, ord=2, axis=1)[:, np.newaxis]
#     us = ss / ns
# 
#     # Draw samples from GG
#     S = np.linalg.cholesky(scov).T
#     ts = rng.gamma(shape=dim / (2.0 * beta), scale=2.0, 
#                    size=n_samples)[:, np.newaxis]
#     xs = (ts**(1.0 / (2.0 * beta))) * us.dot(S)
# 
#     if normalize:
#         v = (2**(1.0 / beta) * gamma((dim + 2.0) / (2.0 * beta))) / \
#             (dim * gamma(dim / (2.0 * beta)))
#         xs = xs / np.sqrt(v * np.diag(scov))
# 
#     return xs
# 
# def multivariatet(mu, Sigma, N, M, rng):
#     """Return a sample (or samples) from the multivariate t distribution.
# 
#     This function is adopted from 
#     http://kennychowdhary.me/2013/03/python-code-to-generate-samples-from-multivariate-t/.
# 
#     :param mu: Mean.
#     :type mu: ndarray, shape=(n_dim,), dtype=float
#     :param Sigma: Scaling matrix.
#     :type Sigma: ndarray, shape=(n_dim, n_dim), dtype=float
#     :param float N: Degrees of freedom.
#     :param int M: Number of samples to produce. 
#     :param np.random.RandomState rng: Random number generator. 
#     :return: M samples of (n_dim)-dimensional multivariate t distribution.
#     :rtype: ndarray, shape=(n_samples, n_dim), dtype=float
# 
#     """
#     d = len(Sigma)
#     g = np.tile(rng.gamma(N/2., 2./N, M), (d, 1)).T
#     Z = rng.multivariate_normal(np.zeros(d), Sigma, M)
#     return mu + Z / np.sqrt(g)


# Path: bmlingam/cache_mc.py
from itertools import chain
from parse import parse
from bmlingam.prob import sample_gg, multivariatet
import numpy as np

        L_cov_21 = rng.uniform(r[0], r[1])
        return np.array([[1.0, L_cov_21], 
                         [L_cov_21, 1.0]])

def _cache_mu_indvdl(
    prior_indvdls, L_covs, df_indvdls, beta_coeffs, n_mc_samples, n_samples, 
    rng):
    # Define conditional parameter sets
    df_indvdls_ = lambda p: df_indvdls if p == 't' else [None]
    beta_coeffs_ = lambda p: beta_coeffs if p == 'gg' else [None]

    # Make list of parameter sets
    paramss = flt([
        [
            (prior_indvdl, L_cov, df_indvdl, beta)
            for df_indvdl in df_indvdls_(prior_indvdl)
            for beta in beta_coeffs_(prior_indvdl)
        ]
        for prior_indvdl in prior_indvdls
        for L_cov in L_covs
    ])

    # Define function to draw random samples
    def f(params):
        prior_indvdl = params[0]
        L_covs = [_get_L_cov(params[1], rng) for _ in range(n_mc_samples)]
        df_L = params[2]
        beta = params[3]

        if prior_indvdl == 't':

            sample_func = lambda L_cov_: multivariatet(
