Exemple #1
0
def anal_Am(np_pmf, pmf_index, sys_index, m):
    """ Analytic A_m """
    m_ind = len(pmf_index[0]) - 2 - m
    if m_ind < 0:
        print("require seq_len > 1+m")
        return None

    s_ind = pmf_index[sys_index][:, [-2, -1]].flatten()
    e_ind = np.delete(pmf_index, sys_index, axis=0)[:, m_ind:-1].flatten()
    se_ind = np.concatenate((s_ind, e_ind))

    margin_index = np.delete(pmf_index.flatten(), se_ind)
    margin_pmf = prob.numpy_margin(np_pmf, margin_index)

    x_ind = [list(se_ind).index(x) for x in s_ind][0:len(sys_index)]
    y_ind = [list(se_ind).index(x)
             for x in s_ind][len(sys_index):2 * len(sys_index)]

    # print("indices")
    # print(pmf_index)
    # print(se_ind)
    # print(total_ind)

    # inf.numpy_conditional_mutual_information()

    return inf.numpy_conditional_mutual_information(margin_pmf, x_ind, y_ind)
Exemple #2
0
def anal_step_MI(np_pmf, pmf_index, xind, yind):
    """ I(X;Y) """

    xy_index = list(itt.chain(*xind, *yind))

    margin_index = np.delete(pmf_index.flatten(), xy_index)
    margin_pmf = prob.numpy_margin(np_pmf, margin_index)

    XIND = [list(xy_index).index(x) for x in list(itt.chain(*xind))]
    YIND = [list(xy_index).index(x) for x in list(itt.chain(*yind))]

    return inf.numpy_mutual_information(margin_pmf, XIND, YIND)
Exemple #3
0
def anal_Astar(np_pmf, pmf_index, sys_index):
    """ Analytic A* """

    s_ind = pmf_index[sys_index][:, [-2, -1]].flatten()

    margin_index = np.delete(pmf_index.flatten(), s_ind)
    margin_pmf = prob.numpy_margin(np_pmf, margin_index)

    x_ind = [list(s_ind).index(x) for x in s_ind][0:len(sys_index)]
    y_ind = [list(s_ind).index(x)
             for x in s_ind][len(sys_index):2 * len(sys_index)]

    return inf.numpy_mutual_information(margin_pmf, x_ind, y_ind)
Exemple #4
0
def anal_step_cond_MI(np_pmf, pmf_index, xind, yind, zind=()):
    """ I(X;Y|Z), z optional """

    xy_index = list(itt.chain(*xind, *yind, *zind))

    margin_index = np.delete(pmf_index.flatten(), xy_index)
    margin_pmf = prob.numpy_margin(np_pmf, margin_index)

    XIND = [list(xy_index).index(x) for x in list(itt.chain(*xind))]
    YIND = [list(xy_index).index(x) for x in list(itt.chain(*yind))]

    if zind == ():
        return inf.numpy_mutual_information(margin_pmf, XIND, YIND)

    return inf.numpy_conditional_mutual_information(margin_pmf, XIND, YIND)
Exemple #5
0
def numpy_conditional_mutual_information(np_pmf, x_index, y_index):
    """ Conditional Mutual Information I(X;Y|Z)
    
    Parameters
    ----------
    np_pmf : array_like
        A numpy array of the form [x1, ... , xn, p(x1, ... , xn)] with length n+1
    x_index : list
        index for X in p(X,Y,Z) for I(X;Y|Z)
    y_index : list
        index for Y in p(X,Y,Z) for I(X;Y|Z)
    """

    var_index = [x_index, y_index]
    for i, var in enumerate(var_index):
        var_index[i] = [var] if isinstance(var, int) else var

    # marginalizing
    pmf_z, inverse_index_z = prob.numpy_margin(np_pmf,
                                               [*var_index[0], *var_index[1]],
                                               return_inverse=True)
    pmf_xz, inverse_index_xz = prob.numpy_margin(np_pmf,
                                                 var_index[1],
                                                 return_inverse=True)
    pmf_yz, inverse_index_yz = prob.numpy_margin(np_pmf,
                                                 var_index[0],
                                                 return_inverse=True)

    CMI = 0
    for i, p_xyz in enumerate(np_pmf[-1]):
        p_z = pmf_z[-1][inverse_index_z[i]]
        p_xz = pmf_xz[-1][inverse_index_xz[i]]
        p_yz = pmf_yz[-1][inverse_index_yz[i]]
        CMI += p_xyz * np.log2((p_z * p_xyz) / (p_xz * p_yz))

    return CMI
Exemple #6
0
def numpy_mutual_information(np_pmf, x_index, y_index):
    """ Mutual information I(X;Y)

    Parameters
    ----------
    np_pmf : array_like
        A numpy array of the form [x1, ... , xn, p(x1, ... , xn)] with length n+1
    x_index : list
        index for X in p(X,Y,Z) for I(X;Y|Z)
    y_index : list
        index for Y in p(X,Y,Z) for I(X;Y|Z)
    
    Note
    ----
    .. math:: I(X;Y) = \sum_{x,y} p_{X,Y}(x,y) \log \frac{p_{X,Y}(x,y)}{p_X(x) p_Y(y)} = H(X) - H(X \mid Y)

    """

    # y_index = np.delete(np.arange(len(np_pmf)-1), x_index)
    var_index = [x_index, y_index]

    # marginalizing
    pmf_x, inverse_index_x = prob.numpy_margin(np_pmf,
                                               var_index[1],
                                               return_inverse=True)
    pmf_y, inverse_index_y = prob.numpy_margin(np_pmf,
                                               var_index[0],
                                               return_inverse=True)

    MI = 0
    for i, p_xy in enumerate(np_pmf[-1]):
        p_x = pmf_x[-1][inverse_index_x[i]]
        p_y = pmf_y[-1][inverse_index_y[i]]
        MI += p_xy * np.log2(p_xy / (p_x * p_y))

    return MI
Exemple #7
0
def anal_non_heteronomy(np_pmf, pmf_index, sys_index, m):
    """ Analytic H(S_n+1 | E_n,... E_n-m) """
    m_ind = len(pmf_index[0]) - 2 - m
    if m_ind < 0:
        print("require seq_len > 1+m")
        return None

    s_ind = pmf_index[sys_index][:, -1].flatten()
    e_ind = np.delete(pmf_index, sys_index, axis=0)[:, m_ind:-1].flatten()
    se_ind = np.concatenate((s_ind, e_ind))

    margin_index = np.delete(pmf_index.flatten(), se_ind)
    margin_pmf = prob.numpy_margin(np_pmf, margin_index)

    env_cond_index = [list(se_ind).index(x) for x in e_ind]
    return inf.numpy_conditional_entropy(margin_pmf, env_cond_index)
Exemple #8
0
def anal_IF(np_pmf, pmf_index, x_index):
    """ Analytic IF(X->Y) = I(Y_{n+1}:X_{n}|Y_{n}) """

    pmf_index = np.array(pmf_index)
    X_n = pmf_index[x_index][:, -2].flatten()
    Y_n = np.delete(pmf_index, x_index, axis=0)[:, -2].flatten()
    Y_n1 = np.delete(pmf_index, x_index, axis=0)[:, -1].flatten()
    flat_ind = np.sort(np.concatenate((X_n, Y_n, Y_n1)))

    margin_index = np.delete(pmf_index.flatten(), flat_ind)
    margin_pmf = prob.numpy_margin(np_pmf, margin_index)

    x_ind = [list(flat_ind).index(x) for x in X_n]
    y_ind = [list(flat_ind).index(y) for y in Y_n1]

    return inf.numpy_conditional_mutual_information(margin_pmf, x_ind, y_ind)