Beispiel #1
0
def expected_counts_stationary(T, n, mu=None):
    r"""Expected transition counts for Markov chain in equilibrium. 
    
    Since mu is stationary for T we have 
    
    .. math::
    
        E(C^{(n)})=n diag(mu)*T.
    
    Parameters
    ----------
    T : (M, M) sparse matrix
        Transition matrix.
    n : int
        Number of steps for chain.
    mu : (M,) ndarray (optional)
        Stationary distribution for T. If mu is not specified it will be
        computed via diagonalization of T.
    
    Returns
    -------
    EC : (M, M) sparse matrix
        Expected value for transition counts after N steps.         
    
    """
    if(n<=0):
        EC=coo_matrix(T.shape, dtype=float)
        return EC
    else:
        if mu is None:
            mu=decomposition.stationary_distribution_from_eigenvector(T)
        D_mu=diags(mu, 0)
        EC=n*D_mu.dot(T)
        return EC
Beispiel #2
0
def is_reversible(T, mu=None, tol=1e-15):
    r"""
    checks whether T is reversible in terms of given stationary distribution.
    If no distribution is given, it will be calculated out of T.
    
    performs follwing check:
    :math:`\pi_i P_{ij} = \pi_j P_{ji}
    Parameters
    ----------
    T : scipy.sparse matrix
        Transition matrix
    mu : numpy.ndarray vector
        stationary distribution
    tol : float
        tolerance to check with
        
    Returns
    -------
    Truth value : bool
        True, if T is a stochastic matrix
        False, otherwise
    """
    if not is_transition_matrix(T, tol):
        raise ValueError("given matrix is not a valid transition matrix.")

    T = T.tocsr()

    if mu is None:
        from decomposition import stationary_distribution_from_backward_iteration as statdist
        mu = statdist(T)

    Mu = diags(mu, 0)
    prod = Mu * T

    return allclose_sparse(prod, prod.transpose(), rtol=tol)
Beispiel #3
0
def is_reversible(T, mu=None, tol=1e-15):
    r"""
    checks whether T is reversible in terms of given stationary distribution.
    If no distribution is given, it will be calculated out of T.
    
    performs follwing check:
    :math:`\pi_i P_{ij} = \pi_j P_{ji}
    Parameters
    ----------
    T : scipy.sparse matrix
        Transition matrix
    mu : numpy.ndarray vector
        stationary distribution
    tol : float
        tolerance to check with
        
    Returns
    -------
    Truth value : bool
        True, if T is a stochastic matrix
        False, otherwise
    """
    if not is_transition_matrix(T, tol):
        raise ValueError("given matrix is not a valid transition matrix.")
    
    T = T.tocsr()
    
    if mu is None:
        from decomposition import stationary_distribution_from_backward_iteration as statdist
        mu = statdist(T)
    
    Mu = diags(mu, 0)
    prod = Mu * T
    
    return allclose_sparse(prod, prod.transpose(), rtol=tol)        
Beispiel #4
0
    def test_expected_counts(self):
        N = 50
        T = self.T_sparse
        p0 = self.mu_sparse

        EC_n = expected_counts(T, p0, N)

        D_mu = diags(self.mu_sparse, 0)
        EC_true = N * D_mu.dot(T)

        self.assertTrue(sparse_allclose(EC_true, EC_n))
Beispiel #5
0
    def test_expected_counts(self):
        N = 50
        T = self.T_sparse
        p0 = self.mu_sparse

        EC_n = expected_counts(T, p0, N)

        D_mu = diags(self.mu_sparse, 0)
        EC_true = N * D_mu.dot(T)

        self.assertTrue(sparse_allclose(EC_true, EC_n))
Beispiel #6
0
def is_rate_matrix(K, tol):
    """
    True if K is a rate matrix
    Parameters
    ----------
    K : scipy.sparse matrix
        Matrix to check
    tol : float
        tolerance to check with
        
    Returns
    -------
    Truth value : bool
        True, if K negated diagonal is positive and row sums up to zero.
        False, otherwise
    """
    K = K.tocsr()
    
    # check rows sum up to zero.
    row_sum = K.sum(axis = 1)
    sum_eq_zero = np.allclose(row_sum, np.zeros(shape=row_sum.shape), atol=tol)


    # store copy of original diagonal
    org_diag = K.diagonal()
    
    # substract diagonal
    K=K-diags(org_diag, 0)

    # check off diagonals are > 0
    values=K.data
    values_gt_zero = np.allclose(values, np.abs(values), atol = tol)

    # add diagonal
    K=K+diags(org_diag, 0)

    return values_gt_zero and sum_eq_zero
Beispiel #7
0
def is_rate_matrix(K, tol):
    """
    True if K is a rate matrix
    Parameters
    ----------
    K : scipy.sparse matrix
        Matrix to check
    tol : float
        tolerance to check with
        
    Returns
    -------
    Truth value : bool
        True, if K negated diagonal is positive and row sums up to zero.
        False, otherwise
    """
    K = K.tocsr()

    # check rows sum up to zero.
    row_sum = K.sum(axis=1)
    sum_eq_zero = np.allclose(row_sum, np.zeros(shape=row_sum.shape), atol=tol)

    # store copy of original diagonal
    org_diag = K.diagonal()

    # substract diagonal
    K = K - diags(org_diag, 0)

    # check off diagonals are > 0
    values = K.data
    values_gt_zero = np.allclose(values, np.abs(values), atol=tol)

    # add diagonal
    K = K + diags(org_diag, 0)

    return values_gt_zero and sum_eq_zero
Beispiel #8
0
    def test_expected_counts_stationary(self):
        n = 50
        T = self.T_sparse
        mu = self.mu_sparse

        D_mu = diags(self.mu_sparse, 0)
        EC_true = n * D_mu.dot(T)
        """Compute mu on the fly"""
        EC_n = expected_counts_stationary(T, n)
        self.assertTrue(sparse_allclose(EC_true, EC_n))
        """With precomputed mu"""
        EC_n = expected_counts_stationary(T, n, mu=mu)
        self.assertTrue(sparse_allclose(EC_true, EC_n))

        n = 0
        EC_true = scipy.sparse.coo_matrix(T.shape)
        EC_n = expected_counts_stationary(T, n)
        self.assertTrue(sparse_allclose(EC_true, EC_n))
Beispiel #9
0
    def test_expected_counts_stationary(self):
        n = 50
        T = self.T_sparse
        mu = self.mu_sparse

        D_mu = diags(self.mu_sparse, 0)
        EC_true = n * D_mu.dot(T)

        """Compute mu on the fly"""
        EC_n = expected_counts_stationary(T, n)
        self.assertTrue(sparse_allclose(EC_true, EC_n))

        """With precomputed mu"""
        EC_n = expected_counts_stationary(T, n, mu=mu)
        self.assertTrue(sparse_allclose(EC_true, EC_n))

        n = 0
        EC_true = scipy.sparse.coo_matrix(T.shape)
        EC_n = expected_counts_stationary(T, n)
        self.assertTrue(sparse_allclose(EC_true, EC_n))
Beispiel #10
0
def expected_counts(p0, T, N):
    r"""Compute expected transition counts for Markov chain after N steps. 
    
    Expected counts are computed according to ..math::
    
    E[C_{ij}^{(n)}]=\sum_{k=0}^{N-1} (p_0^T T^{k})_{i} p_{ij}   
    
    Parameters
    ----------
    p0 : (M,) ndarray
        Starting (probability) vector of the chain.
    T : (M, M) sparse matrix
        Transition matrix of the chain.
    N : int
        Number of steps to take from initial state.
        
    Returns
    --------
    EC : (M, M) sparse matrix
        Expected value for transition counts after N steps. 
    
    """
    if(N<=0):
        EC=coo_matrix(T.shape, dtype=float)
        return EC
    else:        
        """Probability vector after (k=0) propagations"""                     
        p_k=1.0*p0
        """Sum of vectors after (k=0) propagations"""
        p_sum=1.0*p_k           
        """Transpose T to use sparse dot product"""
        Tt=T.transpose()
        for k in np.arange(N-1):
            """Propagate one step p_{k} -> p_{k+1}"""
            p_k=Tt.dot(p_k)
            """Update sum"""
            p_sum+=p_k
        D_psum=diags(p_sum, 0)
        EC=D_psum.dot(T)
        return EC