Ejemplo n.º 1
0
def test_cond_mvn_exception_given():
    """Test cond_mvn raises exceptions when invalid `given_ind` or `given_value` is passed."""
    mean, cov, dependent_ind, given_ind, given_value = get_strategies(
        "cond_mvn_exception_given",
    )

    n = cov.shape[0]
    if n % 3 != 0:
        # Valid case: only `given_ind` is empty or both `given_ind` and `given_value` are empty
        cond_mvn(mean, cov, dependent_ind, given_ind, given_value)
    else:
        # `given_value` is empty or does not align with `given_ind`
        with pytest.raises(ValueError) as e:
            cond_mvn(mean, cov, dependent_ind, given_ind, given_value)
        assert "lengths of given_value and given_ind must be the same" in str(e.value)
Ejemplo n.º 2
0
def test_cond_mvn():
    """Test cond_mvn against the original from R package cond_mvnorm."""
    request = get_strategies("cond_mvn")

    r_cond_mean, r_cond_cov = r_cond_mvn(*request)
    cond_mean, cond_cov = cond_mvn(*request)

    np.testing.assert_allclose(cond_mean, r_cond_mean)
    np.testing.assert_allclose(cond_cov, r_cond_cov)
Ejemplo n.º 3
0
def test_gaussian_copula_mvn():
    """
    The results from a Gaussian copula with normal marginal distributions
    should be identical to the direct use of a multivariate normal
    distribution.
    """

    dim = rng.integers(2, 10)
    means = rng.uniform(-100, 100, dim)

    sigma = rng.normal(size=(dim, dim))
    cov = sigma @ sigma.T

    marginals = list()
    for i in range(dim):
        mean, sigma = means[i], np.sqrt(cov[i, i])
        marginals.append(cp.Normal(mu=mean, sigma=sigma))
    distribution = cp.J(*marginals)

    sample = distribution.sample(1).T[0]

    full = list(range(0, dim))
    dependent_ind = [rng.choice(full)]

    given_ind = full[:]

    # TODO: This test always treats the first element as given.
    # We need it to be more flexible and select random subsets.
    given_ind.remove(dependent_ind[0])

    given_value = sample[given_ind]

    np.testing.assert_almost_equal(np.linalg.inv(np.linalg.inv(cov)), cov)

    np.random.seed(seed)
    given_value_u = [
        distribution[ind].cdf(given_value[i])
        for i, ind in enumerate(given_ind)
    ]
    condi_value_u = cond_gaussian_copula(cov, dependent_ind, given_ind,
                                         given_value_u)
    gc_value = distribution[int(dependent_ind[0])].inv(condi_value_u)

    np.random.seed(seed)
    cond_mean, cond_cov = cond_mvn(means, cov, dependent_ind, given_ind,
                                   given_value)
    cond_dist = multivariate_norm(cond_mean, cond_cov)
    cn_value = np.atleast_1d(cond_dist.rvs())

    np.testing.assert_almost_equal(cn_value, gc_value)
Ejemplo n.º 4
0
def cond_gaussian_copula(cov, dependent_ind, given_ind, given_value_u):

    given_value_u = np.atleast_1d(given_value_u)

    assert np.all((given_value_u >= 0)
                  & (given_value_u <= 1)), "sanitize your inputs!"

    given_value_y = norm().ppf(given_value_u)

    means = np.zeros(cov.shape[0])
    cond_mean, cond_cov = cond_mvn(means, _cov2corr(cov), dependent_ind,
                                   given_ind, given_value_y)

    cond_dist = multivariate_norm(cond_mean, cond_cov)
    cond_draw = np.atleast_1d(cond_dist.rvs())
    cond_quan = norm.cdf(cond_draw)

    return np.atleast_1d(cond_quan)
Ejemplo n.º 5
0
def test_cond_gaussian_copula():
    """
    The results from a Gaussian copula with normal marginal distributions
    should be identical to the direct use of a multivariate normal
    distribution.
    """
    args_gc, args_cn = get_strategies("test_cond_gaussian_copula")
    cov, dependent_ind, given_ind, given_value_u, distribution = args_gc

    np.random.seed(123)
    condi_value_u = cond_gaussian_copula(cov, dependent_ind, given_ind, given_value_u)
    dist_subset = list()
    for ind in dependent_ind:
        dist_subset.append(distribution[int(ind)])
    dist_subset = cp.J(*dist_subset)
    gc_value = dist_subset.inv(condi_value_u)

    np.random.seed(123)
    cond_mean, cond_cov = cond_mvn(*args_cn)
    cond_dist = multivariate_norm(cond_mean, cond_cov)
    cn_value = np.atleast_1d(cond_dist.rvs())

    np.testing.assert_almost_equal(cn_value, gc_value)
Ejemplo n.º 6
0
def _r_condmvn(
    n,
    mean,
    cov,
    dependent_ind,
    given_ind,
    x_given,
):
    """Function to generate conditional law.

    Function to simulate conditional gaussian distribution of x[dependent.ind]
    | x[given.ind] = x.given where x is multivariateNormal(mean = mean, covariance = cov)

    """
    cond_mean, cond_var = cond_mvn(
        mean,
        cov,
        dependent_ind=dependent_ind,
        given_ind=given_ind,
        given_value=x_given,
    )
    distribution = cp.MvNormal(cond_mean, cond_var)

    return distribution.sample(n)
Ejemplo n.º 7
0
def test_cond_mvn_exception_cov():
    """Test cond_mvn raises exceptions when invalid `cov` is passed."""
    mean, cov, dependent_ind, given_ind, given_value = get_strategies(
        "test_cond_mvn_exception_cov",
    )

    n = cov.shape[0]

    if n % 3 != 0 and n % 2 != 0:
        # `cov` is negative definite matrix
        with pytest.raises(ValueError) as e:
            cond_mvn(mean, cov, dependent_ind, given_ind, given_value)
        assert "cov is not positive-definite" in str(e.value)
    elif n % 2 != 0:
        # `cov` is not symmetric
        with pytest.raises(ValueError) as e:
            cond_mvn(mean, cov, dependent_ind, given_ind, given_value)
        assert "cov is not a symmetric matrix" in str(e.value)
    else:
        cond_mvn(mean, cov, dependent_ind, given_ind, given_value)
Ejemplo n.º 8
0
    sample = distribution.sample(1).T[0]

    full = list(range(0, dim))
    dependent_ind = [np.random.choice(full)]

    given_ind = full[:]

    # TODO: This test always treats the first element as given. We need it to be more
    #  flexible and select random subets.
    given_ind.remove(dependent_ind[0])

    given_value = sample[given_ind]

    np.random.seed(123)
    given_value_u = [
        distribution[ind].cdf(given_value[i])
        for i, ind in enumerate(given_ind)
    ]
    condi_value_u = cond_gaussian_copula(cov, dependent_ind, given_ind,
                                         given_value_u)
    gc_value = distribution[int(dependent_ind[0])].inv(condi_value_u)

    np.random.seed(123)
    cond_mean, cond_cov = cond_mvn(means, cov, dependent_ind, given_ind,
                                   given_value)
    cond_dist = multivariate_norm(cond_mean, cond_cov)
    cn_value = np.atleast_1d(cond_dist.rvs())

    print(dim)
    np.testing.assert_allclose(cn_value, gc_value, rtol=1e-4)
Ejemplo n.º 9
0
def cond_gaussian_copula(cov, dependent_ind, given_ind, given_value_u, size=1):
    r"""Conditional sampling from Gaussian copula.

    This function provides the probability distribution of conditional sample
    drawn from a Gaussian copula, given covariance matrix and a uniform random vector.

    Parameters
    ----------
    cov : array_like
        Covariance matrix of the desired sample.

    dependent_ind : int or array_like
        The indices of dependent variables.

    given_ind : array_like
        The indices of independent variables.

    given_value_u : array_like
        The given random vector (:math:`u`) that is uniformly distributed between 0 and 1.

    size : int
        Number of draws from the conditional distribution. (default value is `1`)

    Returns
    -------
    cond_quan : numpy.ndarray
        The conditional sample (:math:`G(u)`) that is between 0 and 1,
        and has the same length as ``dependent_ind``.

    Examples
    --------
    >>> np.random.seed(123)
    >>> cov = np.array([[ 3.290887,  0.465004, -3.411841],
    ...                 [ 0.465004,  3.962172, -0.574745],
    ...                 [-3.411841, -0.574745,  4.063252]])
    >>> dependent_ind = 2
    >>> given_ind = [0, 1]
    >>> given_value_u = [0.0596779, 0.39804426]
    >>> condi_value_u = cond_gaussian_copula(cov, dependent_ind, given_ind, given_value_u)
    >>> np.testing.assert_almost_equal(condi_value_u[0], 0.856504, decimal=6)
    """
    given_value_u = np.atleast_1d(given_value_u)

    # Check `given_value_u` are between 0 and 1
    if not np.all((given_value_u >= 0) & (given_value_u <= 1)):
        raise ValueError("given_value_u must be between 0 and 1")

    # F^{−1}(u)
    given_value_y = norm().ppf(given_value_u)

    mean = np.zeros(cov.shape[0])
    cond_mean, cond_cov = cond_mvn(
        mean,
        _cov2corr(cov),
        dependent_ind,
        given_ind,
        given_value_y,
    )

    # C(u, Sigma)
    cond_dist = multivariate_norm(cond_mean, cond_cov)
    cond_draw = np.atleast_1d(cond_dist.rvs(size=size))
    cond_quan = np.atleast_1d(norm.cdf(cond_draw))

    return cond_quan