コード例 #1
0
ファイル: test_oom.py プロジェクト: sklus/scikit-time
def oom_transformations(Ct, C2t, rank):
    # Number of states:
    N = Ct.shape[0]
    # Get the SVD of Ctau:
    U, s, V = scl.svd(Ct, full_matrices=False)
    # Reduce:
    s = s[:rank]
    U = U[:, :rank]
    V = V[:rank, :].transpose()
    # Define transformation matrices:
    F1 = np.dot(U, np.diag(s ** (-0.5)))
    F2 = np.dot(V, np.diag(s ** (-0.5)))
    # Compute observable operators:
    Xi = np.zeros((rank, N, rank))
    for n in range(N):
        Xi[:, n, :] = np.dot(F1.T, np.dot(C2t[:, :, n], F2))
    Xi_full = np.sum(Xi, axis=1)
    # Compute evaluator:
    c = np.sum(Ct, axis=1)
    sigma = np.dot(F1.T, c)
    # Compute information state:
    l, R = scl.eig(Xi_full.T)
    # Restrict eigenvalues to reasonable range:
    ind = np.where(np.logical_and(np.abs(l) <= (1 + 1e-2), np.real(l) >= 0.0))[0]
    l = l[ind]
    R = R[:, ind]
    l, R = sort_eigs(l, R)
    omega = np.real(R[:, 0])
    omega = omega / np.dot(omega, sigma)

    return Xi, omega, sigma, l
コード例 #2
0
def transform_C0(C, epsilon):
    d, V = scl.eigh(C)
    evmin = np.minimum(0, np.min(d))
    ep = np.maximum(-evmin, epsilon)
    d, V = sort_eigs(d, V)
    ind = np.where(np.abs(d) > ep)[0]
    d = d[ind]
    V = V[:, ind]
    V = scale_eigenvectors(V)
    R = np.dot(V, np.diag(d**(-0.5)))
    return R
コード例 #3
0
def oom_components(Ct, C2t, rank_ind=None, lcc=None, tol_one=1e-2):
    """
    Compute OOM components and eigenvalues from count matrices:

    Parameters
    ----------
    Ct : ndarray(N, N)
        count matrix from data
    C2t : sparse csc-matrix (N*N, N)
        two-step count matrix from data for all states, columns enumerate
        intermediate steps.
    rank_ind : ndarray(N, dtype=bool), optional, default=None
        indicates which singular values are accepted. By default, all non-
        zero singular values are accepted.
    lcc : ndarray(N,), optional, default=None
        largest connected set of the count-matrix. Two step count matrix
        will be reduced to this set.
    tol_one : float, optional, default=1e-2
        keep eigenvalues of absolute value less or equal 1+tol_one.

    Returns
    -------
    Xi : ndarray(M, N, M)
        matrix of set-observable operators
    oom_information_state_vector: ndarray(M,)
        information state vector of OOM
    oom_evaluator : ndarray(M,)
        evaluator of OOM
    l : ndarray(M,)
        eigenvalues from OOM
    """
    import deeptime.markov.tools.estimation as me
    # Decompose count matrix by SVD:
    if lcc is not None:
        Ct_svd = me.largest_connected_submatrix(Ct, lcc=lcc)
        N1 = Ct.shape[0]
    else:
        Ct_svd = Ct
    V, s, W = scl.svd(Ct_svd, full_matrices=False)
    # Make rank decision:
    if rank_ind is None:
        ind = (s >= np.finfo(float).eps)
    V = V[:, rank_ind]
    s = s[rank_ind]
    W = W[rank_ind, :].T

    # Compute transformations:
    F1 = np.dot(V, np.diag(s**-0.5))
    F2 = np.dot(W, np.diag(s**-0.5))

    # Apply the transformations to C2t:
    N = Ct_svd.shape[0]
    M = F1.shape[1]
    Xi = np.zeros((M, N, M))
    for n in range(N):
        if lcc is not None:
            C2t_n = C2t[:, lcc[n]]
            C2t_n = _reshape_sparse(C2t_n, (N1, N1))
            C2t_n = me.largest_connected_submatrix(C2t_n, lcc=lcc)
        else:
            C2t_n = C2t[:, n]
            C2t_n = _reshape_sparse(C2t_n, (N, N))
        Xi[:, n, :] = np.dot(F1.T, C2t_n.dot(F2))

    # Compute sigma:
    c = np.sum(Ct_svd, axis=1)
    sigma = np.dot(F1.T, c)
    # Compute eigenvalues:
    Xi_S = np.sum(Xi, axis=1)
    eigenvalues, right_eigenvectors = scl.eig(Xi_S.T)
    # Restrict eigenvalues to reasonable range:
    ind = np.where(
        np.logical_and(
            np.abs(eigenvalues) <= (1 + tol_one),
            np.real(eigenvalues) >= 0.0))[0]
    eigenvalues = eigenvalues[ind]
    right_eigenvectors = right_eigenvectors[:, ind]
    # Sort and extract omega
    eigenvalues, right_eigenvectors = sort_eigs(eigenvalues,
                                                right_eigenvectors)
    omega = np.real(right_eigenvectors[:, 0])
    omega = omega / np.dot(omega, sigma)

    return Xi, omega, sigma, eigenvalues
コード例 #4
0
    def setUpClass(cls):
        # Basis set definition:
        cls.nf = 10
        cls.chi = np.zeros((20, cls.nf), dtype=float)
        for n in range(cls.nf):
            cls.chi[2 * n:2 * (n + 1), n] = 1.0

        # Load simulations:
        f = np.load(
            pkg_resources.resource_filename(__name__,
                                            "data/test_data_koopman.npz"))
        trajs = [f[key] for key in f.keys()]
        cls.data = [cls.chi[traj, :] for traj in trajs]

        # Lag time:
        cls.tau = 10
        # Truncation for small eigenvalues:
        cls.epsilon = 1e-6

        # Compute the means:
        cls.mean_x = np.zeros(cls.nf)
        cls.mean_y = np.zeros(cls.nf)
        cls.frames = 0
        for traj in cls.data:
            cls.mean_x += np.sum(traj[:-cls.tau, :], axis=0)
            cls.mean_y += np.sum(traj[cls.tau:, :], axis=0)
            cls.frames += traj[:-cls.tau, :].shape[0]
        cls.mean_x *= (1.0 / cls.frames)
        cls.mean_y *= (1.0 / cls.frames)
        cls.mean_rev = 0.5 * (cls.mean_x + cls.mean_y)

        # Compute correlations:
        cls.C0 = np.zeros((cls.nf, cls.nf))
        cls.Ct = np.zeros((cls.nf, cls.nf))
        cls.C0_rev = np.zeros((cls.nf, cls.nf))
        cls.Ct_rev = np.zeros((cls.nf, cls.nf))
        for traj in cls.data:
            itraj = (traj - cls.mean_x[None, :]).copy()
            cls.C0 += np.dot(itraj[:-cls.tau, :].T, itraj[:-cls.tau, :])
            cls.Ct += np.dot(itraj[:-cls.tau, :].T, itraj[cls.tau:, :])
            itraj = (traj - cls.mean_rev[None, :]).copy()
            cls.C0_rev += np.dot(itraj[:-cls.tau, :].T, itraj[:-cls.tau, :]) \
                          + np.dot(itraj[cls.tau:, :].T, itraj[cls.tau:, :])
            cls.Ct_rev += np.dot(itraj[:-cls.tau, :].T, itraj[cls.tau:, :]) \
                          + np.dot(itraj[cls.tau:, :].T, itraj[:-cls.tau, :])
        cls.C0 *= (1.0 / cls.frames)
        cls.Ct *= (1.0 / cls.frames)
        cls.C0_rev *= (1.0 / (2 * cls.frames))
        cls.Ct_rev *= (1.0 / (2 * cls.frames))

        # Compute whitening transformation:
        cls.R = transform_C0(cls.C0, cls.epsilon)
        cls.Rrev = transform_C0(cls.C0_rev, cls.epsilon)

        # Perform non-reversible diagonalization
        cls.ln, cls.Rn = scl.eig(np.dot(cls.R.T, np.dot(cls.Ct, cls.R)))
        cls.ln, cls.Rn = sort_eigs(cls.ln, cls.Rn)
        cls.Rn = np.dot(cls.R, cls.Rn)
        cls.Rn = scale_eigenvectors(cls.Rn)
        cls.tsn = -cls.tau / np.log(np.abs(cls.ln))

        cls.ls, cls.Rs = scl.eig(
            np.dot(cls.Rrev.T, np.dot(cls.Ct_rev, cls.Rrev)))
        cls.ls, cls.Rs = sort_eigs(cls.ls, cls.Rs)
        cls.Rs = np.dot(cls.Rrev, cls.Rs)
        cls.Rs = scale_eigenvectors(cls.Rs)
        cls.tss = -cls.tau / np.log(np.abs(cls.ls))

        # Compute non-reversible Koopman matrix:
        cls.K = np.dot(cls.R.T, np.dot(cls.Ct, cls.R))
        cls.K = np.vstack((cls.K, np.dot((cls.mean_y - cls.mean_x), cls.R)))
        cls.K = np.hstack(
            (cls.K, np.eye(cls.K.shape[0], 1, k=-cls.K.shape[0] + 1)))
        cls.N1 = cls.K.shape[0]

        # Compute u-vector:
        ln, Un = scl.eig(cls.K.T)
        ln, Un = sort_eigs(ln, Un)
        cls.u = np.real(Un[:, 0])
        v = np.eye(cls.N1, 1, k=-cls.N1 + 1)[:, 0]
        cls.u *= (1.0 / np.dot(cls.u, v))

        # Prepare weight object:
        u_mod = cls.u.copy()
        N = cls.R.shape[0]
        u_input = np.zeros(N + 1)
        u_input[0:N] = cls.R.dot(u_mod[0:-1])  # in input basis
        u_input[N] = u_mod[-1] - cls.mean_x.dot(cls.R.dot(u_mod[0:-1]))
        cls.weight_obj = KoopmanWeightingModel(u=u_input[:-1],
                                               u_const=u_input[-1],
                                               koopman_operator=cls.K,
                                               whitening_transformation=cls.R,
                                               covariances=None)

        # Compute weights over all data points:
        cls.wtraj = []
        for traj in cls.data:
            traj = np.dot((traj - cls.mean_x[None, :]), cls.R).copy()
            traj = np.hstack((traj, np.ones((traj.shape[0], 1))))
            cls.wtraj.append(np.dot(traj, cls.u))

        # Compute equilibrium mean:
        cls.mean_eq = np.zeros(cls.nf)
        q = 0
        for traj in cls.data:
            qwtraj = cls.wtraj[q]
            cls.mean_eq += np.sum((qwtraj[:-cls.tau, None] * traj[:-cls.tau, :]), axis=0) \
                           + np.sum((qwtraj[:-cls.tau, None] * traj[cls.tau:, :]), axis=0)
            q += 1
        cls.mean_eq *= (1.0 / (2 * cls.frames))

        # Compute reversible C0, Ct:
        cls.C0_eq = np.zeros((cls.N1, cls.N1))
        cls.Ct_eq = np.zeros((cls.N1, cls.N1))
        q = 0
        for traj in cls.data:
            qwtraj = cls.wtraj[q]
            traj = (traj - cls.mean_eq[None, :]).copy()
            cls.C0_eq += np.dot((qwtraj[:-cls.tau, None] * traj[:-cls.tau, :]).T, traj[:-cls.tau, :]) \
                         + np.dot((qwtraj[:-cls.tau, None] * traj[cls.tau:, :]).T, traj[cls.tau:, :])
            cls.Ct_eq += np.dot((qwtraj[:-cls.tau, None] * traj[:-cls.tau, :]).T, traj[cls.tau:, :]) \
                         + np.dot((qwtraj[:-cls.tau, None] * traj[cls.tau:, :]).T, traj[:-cls.tau, :])
            q += 1
        cls.C0_eq *= (1.0 / (2 * cls.frames))
        cls.Ct_eq *= (1.0 / (2 * cls.frames))

        # Solve re-weighted eigenvalue problem:
        S = transform_C0(cls.C0_eq, cls.epsilon)
        Ct_S = np.dot(S.T, np.dot(cls.Ct_eq, S))

        # Compute its eigenvalues:
        cls.lr, cls.Rr = scl.eigh(Ct_S)
        cls.lr, cls.Rr = sort_eigs(cls.lr, cls.Rr)
        cls.Rr = np.dot(S, cls.Rr)
        cls.Rr = scale_eigenvectors(cls.Rr)
        cls.tsr = -cls.tau / np.log(np.abs(cls.lr))

        def tica(data, lag, weights=None, **params):
            from deeptime.decomposition import TICA
            return TICA(var_cutoff=0.95, lagtime=lag,
                        **params).fit_from_timeseries(
                            data, weights=weights).fetch_model()

        # Set up the model:
        cls.koop_rev = tica(cls.data, lag=cls.tau, scaling=None)
        cls.koop_eq = tica(cls.data,
                           lag=cls.tau,
                           weights=cls.weight_obj,
                           scaling=None)