Exemple #1
0
def update_G_both(G_both, add_both, e_both, α, rng):
    df = df_0 + α * n
    rate = rate_0 + α * U
    K0 = np.empty((p, p))
    K1 = np.empty((p, p))

    try:
        accept_both = update_G_both_cpp(K0, K1, G_both[0].__graph_as_capsule(),
                                        G_both[1].__graph_as_capsule(),
                                        add_both[0], add_both[1], e_both[0],
                                        e_both[1], edge_prob, df, df_0, rate,
                                        cpmcmc.random_seed(rng))
    except:
        print("Error in `update_G_both_cpp`. Retrying...")
        return update_G_both(G_both, add_both, e_both, α, rng)

    K_both = (K0, K1)
    res = np.empty(2, dtype=object)

    for j in range(2):
        if accept_both[j]:
            G_tilde = G_both[j].copy()
            G_tilde[e_both[j]] = True if add_both[j] else False
            res[j] = [G_tilde, K_both[j]]
        else:
            res[j] = [G_both[j], K_both[j]]

    return res
Exemple #2
0
def update_G(G, add, e, α, rng):
    """
    MCMC step for the given graph `G`

    `G_tilde` is the proposed graph.

    This follows the exchange algorithm  from
    Lenkoski (2013, arXiv:1304.1350v1).
    The proposal distribution is assumed to be adding/removing an edge with
    equal probability, if `G` is not empty nor full.
    Then, the edge `e` is selected uniformly at random.
    """
    df = df_0 + α * n
    rate = rate_0 + α * U
    K = np.empty((p, p))

    try:
        accept = update_G_cpp(K, G.__graph_as_capsule(), add, e, edge_prob, df,
                              df_0, rate, cpmcmc.random_seed(rng))
    except:
        print("Error in `update_G_cpp`. Retrying...")
        return update_G(G, add, e, α, rng)

    if accept:
        G_tilde = G.copy()
        G_tilde[e] = True if add else False
        return [G_tilde, K]
    else:
        return [G, K]
Exemple #3
0
def sample_e_both(G_both, rng):
    """Coupled sampling of edges"""
    res = sample_e_both_cpp(G_both[0].__graph_as_capsule(),
                            G_both[1].__graph_as_capsule(),
                            cpmcmc.random_seed(rng))

    return [tuple(res[i]) for i in range(2)]
Exemple #4
0
def sample_from_prior(rng):
    """
    Draw z = (G, K) from its prior.
    
    This sets the random number generator from iGraph.
    """
    igraph.set_random_number_generator(random.Random(cpmcmc.random_seed(rng)))

    if edge_prob <= 0.0:
        m_max_p1 = p * (p - 1) // 2 + 1

        if edge_prob == 0.0:
            # Use the size-based prior.
            m = rng.integers(m_max_p1)
        else:
            # Use the size-based prior with a truncated geometric distribution
            # on the graph size.
            prob = -edge_prob

            m = int(
                np.floor(
                    np.log(1.0 - rng.random() * (1.0 -
                                                 (1.0 - prob)**m_max_p1)) /
                    np.log(1.0 - prob)))

        G = igraph.Graph.Erdos_Renyi(n=p, m=m)
    else:
        G = igraph.Graph.Erdos_Renyi(n=p, p=edge_prob)

    return [G, rgwish_identity(G, df_0, rng)]
Exemple #5
0
def coupled_sample_eta(eta_both, m_both, rng):
    """
    Coupled slice sampling for eta per Algorithm 4 of arXiv:2012.04798v1 with
    𝜈 = 1
    """

    coupled_sample_eta_cpp(eta_both[0], eta_both[1], m_both[0], m_both[1], p,
                           cpmcmc.random_seed(rng))

    #     # Step 1
    #     U_crn = rng.random(p)
    #     U_both = np.empty(2, dtype=object)

    #     for j in range(2):
    #         U_both[j] = U_crn / (1.0 + eta_both[j])

    #     # Step 2
    #     for j in range(p):
    #         eta_both[0][j], eta_both[1][j] = maximal_coupling(
    #             P=lambda rng: sample_P(m_both[0][j], U_both[0][j], rng),
    #             Q=lambda rng: sample_P(m_both[1][j], U_both[1][j], rng),
    #             log_p=lambda eta: log_dens_P(eta, m_both[0][j], U_both[0][j]),
    #             log_q=lambda eta: log_dens_P(eta, m_both[1][j], U_both[1][j]),
    #             rng=rng
    #         )

    return eta_both
Exemple #6
0
    def coupled_MCMC_update(z_i, rng, α=1.0):
        # Common seed MCMC update
        tmp_seed = cpmcmc.random_seed(rng)

        for j in range(2):
            z_i[:, j] = MCMC_update(x_i=z_i[:, j],
                                    rng=np.random.default_rng(tmp_seed),
                                    α=α)

        return z_i
Exemple #7
0
def rgwish_identity(G, df, rng):
    """Sample from the G-Wishart distribution with an identity scale matrix."""
    K = np.empty(2 * (G.vcount(), ))

    try:
        rgwish_L_identity_cpp(K, G.__graph_as_capsule(), df,
                              cpmcmc.random_seed(rng))
    except:
        print("Error in `rgwish_L_identity_cpp`. Retrying...")
        return rgwish_identity(G, df, rng)

    return K
Exemple #8
0
def rejection_sampling(N, α, rng):
    K_out = np.empty((N, p, p))
    adj_out = np.empty((N, p, p))

    try:
        rejection_sampling_cpp(K_out, adj_out, p, n, N, α, edge_prob, df_0, U,
                               cpmcmc.random_seed(rng))
    except:
        print("Error in `rejection_sampling`. Retrying...")
        return rejection_sampling(N, α, rng)

    res = np.empty(N, dtype=object)

    for i in range(N):
        res[i] = [
            igraph.Graph.Adjacency(adj_out[i, :, :].tolist(), mode=1),
            K_out[i, :, :]
        ]

    return res
Exemple #9
0
U = data.T @ data
# The code uses the size-based prior if edge_prob <= 0.0. Negative `edge_prob`
# specifies a truncated geometric prior with success probability `-edge_prob`
# on the number of edges. `edge_prob = 0` specifies a uniform prior on the
# number of edges. If `edge_prob > 0.0`, then the edges are a priori
# independent with prior edge inclusion probability `edge_prob`.
edge_prob = 0.5
df_0 = 3.0  # Degrees of freedom of the Wishart prior
rate_0 = np.eye(p)  # Rate matrix of the Wishart prior
rng = np.random.Generator(np.random.SFC64(seed=0))

N = 10**2  # Number of SMC particles
k = 7
min_iter = 40  # Denoted by l in the paper
max_iter = 10**4
tmp_seed = cpmcmc.random_seed(rng)
n_hours = 0.02  # Time budget post adaptation in hours


def trace_inner(A, B):
    """
    Trace inner product of the matrices `A` and `B`

    This function computes <A, B> = tr(A' B).
    Taken from https://stackoverflow.com/a/18855277/5216563.
    `A` can be a higher dimensional array. Then, this function is broadcast
    over the first dimensions of `A`.
    """
    return c_einsum('...ij,ji->...', A, B)