Ejemplo n.º 1
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)
Ejemplo n.º 2
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) ndarray
        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 : numpy array, shape=(n,n)
        Expected value for transition counts after a propagation of n steps. 
    
    """
    if n <= 0:
        EC = np.zeros(T.shape)
        return EC
    else:
        if mu is None:
            mu = statdist(T)
        EC = n * mu[:, np.newaxis] * T
        return EC
Ejemplo n.º 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)        
Ejemplo n.º 4
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) ndarray
        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 : numpy array, shape=(n,n)
        Expected value for transition counts after a propagation of n steps. 
    
    """
    if n<=0:
        EC=np.zeros(T.shape)
        return EC
    else:
        if mu is None:
            mu=statdist(T)
        EC=n*mu[:, np.newaxis]*T
        return EC
Ejemplo n.º 5
0
def correlation_matvec(P, obs1, obs2=None, times=[1]):
    r"""Time-correlation for equilibrium experiment - via matrix vector products.

    Parameters
    ----------
    P : (M, M) ndarray
        Transition matrix
    obs1 : (M,) ndarray
        Observable, represented as vector on state space
    obs2 : (M,) ndarray (optional)
        Second observable, for cross-correlations
    times : list of int (optional)
        List of times (in tau) at which to compute correlation

    Returns
    -------
    correlations : ndarray
        Correlation values at given times
        
    """
    if obs2 is None: 
        obs2=obs1

    """Compute stationary vector"""
    mu=statdist(P)
    obs1mu=mu*obs1

    times=np.asarray(times)
    """Sort in increasing order"""
    ind=np.argsort(times)
    times=times[ind]

    if times[0]<0:
        raise ValueError("Times can not be negative")    
    dt=times[1:]-times[0:-1] 

    nt=len(times)

    correlations=np.zeros(nt)

    """Propagate obs2 to initial time"""
    obs2_t=1.0*obs2
    obs2_t=propagate(P, obs2_t, times[0])
    correlations[0]=np.dot(obs1mu, obs2_t)
    for i in range(nt-1):
        obs2_t=propagate(P, obs2_t, dt[i])
        correlations[i+1]=np.dot(obs1mu, obs2_t)

    """Cast back to original order of time points"""
    correlations=correlations[ind]

    return correlations        
Ejemplo n.º 6
0
def expectation(P, obs):
    r"""Equilibrium expectation of given observable.
    
    Parameters
    ----------
    P : (M, M) ndarray
        Transition matrix
    obs : (M,) ndarray
        Observable, represented as vector on state space

    Returns
    -------
    x : float
        Expectation value    

    """
    pi = statdist(P)
    return np.dot(pi, obs)
Ejemplo n.º 7
0
def expectation(P, obs):
    r"""Equilibrium expectation of given observable.
    
    Parameters
    ----------
    P : (M, M) ndarray
        Transition matrix
    obs : (M,) ndarray
        Observable, represented as vector on state space

    Returns
    -------
    x : float
        Expectation value    

    """
    pi = statdist(P)
    return np.dot(pi, obs)
Ejemplo n.º 8
0
def backward_committor(T, A, B):
    r"""Backward committor between given sets.

    The backward committor u(x) between sets A and B is the
    probability for the chain starting in x to have come from A last
    rather than from B.

    Parameters
    ----------
    T : (M, M) ndarray
        Transition matrix
    A : array_like
        List of integer state labels for set A
    B : array_like
        List of integer state labels for set B

    Returns
    -------
    u : (M, ) ndarray
        Vector of forward committor probabilities    

    Notes
    -----
    The forward committor is a solution to the following
    boundary-value problem

    .. math::

        \sum_j K_{ij} \pi_{j} u_{j}=0    for i in X\(A u B) (I)
                                  u_{i}=1    for i \in A        (II)
                                  u_{i}=0    for i \in B        (III)

    with adjoint of the generator matrix K=(D_pi(P-I))'.

    """
    X = set(range(T.shape[0]))
    A = set(A)
    B = set(B)
    AB = A.intersection(B)
    notAB = X.difference(A).difference(B)
    if len(AB) > 0:
        raise ValueError("Sets A and B have to be disjoint")
    pi = statdist(T)
    L = T - eye(T.shape[0], T.shape[0])
    D = diags([
        pi,
    ], [
        0,
    ])
    K = (D.dot(L)).T
    """Assemble left-hand side W for linear system"""
    """Equation (I)"""
    W = 1.0 * K
    """Equation (II)"""
    W = W.todok()
    W[list(A), :] = 0.0
    W.tocsr()
    W = W + coo_matrix(
        (np.ones(len(A)), (list(A), list(A))), shape=W.shape).tocsr()
    """Equation (III)"""
    W = W.todok()
    W[list(B), :] = 0.0
    W.tocsr()
    W = W + coo_matrix(
        (np.ones(len(B)), (list(B), list(B))), shape=W.shape).tocsr()
    """Assemble right-hand side r for linear system"""
    """Equation (I)+(III)"""
    r = np.zeros(T.shape[0])
    """Equation (II)"""
    r[list(A)] = 1.0

    u = spsolve(W, r)

    return u
Ejemplo n.º 9
0
def backward_committor(T, A, B, mu=None):
    r"""Backward committor between given sets.

    The backward committor u(x) between sets A and B is the
    probability for the chain starting in x to have come from A last
    rather than from B.

    Parameters
    ----------
    T : (M, M) ndarray
        Transition matrix
    A : array_like
        List of integer state labels for set A
    B : array_like
        List of integer state labels for set B
    mu : (M, ) ndarray (optional)
        Stationary vector        

    Returns
    -------
    u : (M, ) ndarray
        Vector of forward committor probabilities    

    Notes
    -----
    The forward committor is a solution to the following
    boundary-value problem

    .. math::

        \sum_j K_{ij} \pi_{j} u_{j}=0    for i in X\(A u B) (I)
                                  u_{i}=1    for i \in A        (II)
                                  u_{i}=0    for i \in B        (III)

    with adjoint of the generator matrix K=(D_pi(P-I))'.
                          
    """
    X = set(range(T.shape[0]))
    A = set(A)
    B = set(B)
    AB = A.intersection(B)
    notAB = X.difference(A).difference(B)
    if len(AB) > 0:
        raise ValueError("Sets A and B have to be disjoint")
    if mu is None:
        mu = statdist(T)
    K = np.transpose(mu[:, np.newaxis] * (T - np.eye(T.shape[0])))
    """Assemble left-hand side W for linear system"""
    """Equation (I)"""
    W = 1.0 * K
    """Equation (II)"""
    W[list(A), :] = 0.0
    W[list(A), list(A)] = 1.0
    """Equation (III)"""
    W[list(B), :] = 0.0
    W[list(B), list(B)] = 1.0
    """Assemble right-hand side r for linear system"""
    """Equation (I)+(III)"""
    r = np.zeros(T.shape[0])
    """Equation (II)"""
    r[list(A)] = 1.0

    u = solve(W, r)

    return u
Ejemplo n.º 10
0
def backward_committor(T, A, B):
    r"""Backward committor between given sets.

    The backward committor u(x) between sets A and B is the
    probability for the chain starting in x to have come from A last
    rather than from B.

    Parameters
    ----------
    T : (M, M) ndarray
        Transition matrix
    A : array_like
        List of integer state labels for set A
    B : array_like
        List of integer state labels for set B

    Returns
    -------
    u : (M, ) ndarray
        Vector of forward committor probabilities    

    Notes
    -----
    The forward committor is a solution to the following
    boundary-value problem

    .. math::

        \sum_j K_{ij} \pi_{j} u_{j}=0    for i in X\(A u B) (I)
                                  u_{i}=1    for i \in A        (II)
                                  u_{i}=0    for i \in B        (III)

    with adjoint of the generator matrix K=(D_pi(P-I))'.

    """
    X = set(range(T.shape[0]))
    A = set(A)
    B = set(B)
    AB = A.intersection(B)
    notAB = X.difference(A).difference(B)
    if len(AB) > 0:
        raise ValueError("Sets A and B have to be disjoint")
    pi = statdist(T)
    L = T - eye(T.shape[0], T.shape[0])
    D = diags([pi, ], [0, ])
    K = (D.dot(L)).T

    """Assemble left-hand side W for linear system"""
    """Equation (I)"""
    W = 1.0 * K

    """Equation (II)"""
    W = W.todok()
    W[list(A), :] = 0.0
    W.tocsr()
    W = W + coo_matrix((np.ones(len(A)), (list(A), list(A))), shape=W.shape).tocsr()

    """Equation (III)"""
    W = W.todok()
    W[list(B), :] = 0.0
    W.tocsr()
    W = W + coo_matrix((np.ones(len(B)), (list(B), list(B))), shape=W.shape).tocsr()

    """Assemble right-hand side r for linear system"""
    """Equation (I)+(III)"""
    r = np.zeros(T.shape[0])
    """Equation (II)"""
    r[list(A)] = 1.0

    u = spsolve(W, r)

    return u
Ejemplo n.º 11
0
def backward_committor(T, A, B, mu=None):
    r"""Backward committor between given sets.

    The backward committor u(x) between sets A and B is the
    probability for the chain starting in x to have come from A last
    rather than from B.

    Parameters
    ----------
    T : (M, M) ndarray
        Transition matrix
    A : array_like
        List of integer state labels for set A
    B : array_like
        List of integer state labels for set B
    mu : (M, ) ndarray (optional)
        Stationary vector        

    Returns
    -------
    u : (M, ) ndarray
        Vector of forward committor probabilities    

    Notes
    -----
    The forward committor is a solution to the following
    boundary-value problem

    .. math::

        \sum_j K_{ij} \pi_{j} u_{j}=0    for i in X\(A u B) (I)
                                  u_{i}=1    for i \in A        (II)
                                  u_{i}=0    for i \in B        (III)

    with adjoint of the generator matrix K=(D_pi(P-I))'.
                          
    """
    X=set(range(T.shape[0]))
    A=set(A)
    B=set(B)
    AB=A.intersection(B)
    notAB=X.difference(A).difference(B)
    if len(AB)>0:
        raise ValueError("Sets A and B have to be disjoint")
    if mu is None:
        mu=statdist(T)
    K=np.transpose(mu[:,np.newaxis]*(T-np.eye(T.shape[0])))

    """Assemble left-hand side W for linear system"""
    """Equation (I)"""
    W=1.0*K
    """Equation (II)"""
    W[list(A), :]=0.0
    W[list(A), list(A)]=1.0
    """Equation (III)"""
    W[list(B), :]=0.0
    W[list(B), list(B)]=1.0

    """Assemble right-hand side r for linear system"""
    """Equation (I)+(III)"""
    r=np.zeros(T.shape[0])
    """Equation (II)"""
    r[list(A)]=1.0

    u=solve(W, r)

    return u