class TestStationaryVector(unittest.TestCase): def setUp(self): self.dim = 100 self.k = 10 """Set up meta-stable birth-death chain""" p = np.zeros(self.dim) p[0:-1] = 0.5 q = np.zeros(self.dim) q[1:] = 0.5 p[self.dim // 2 - 1] = 0.001 q[self.dim // 2 + 1] = 0.001 self.bdc = BirthDeathChain(q, p) def test_statdist_decomposition(self): P = self.bdc.transition_matrix() mu = self.bdc.stationary_distribution() mun = stationary_distribution_from_eigenvector(P) assert_allclose(mu, mun) def test_statdist_iteration(self): P = self.bdc.transition_matrix() mu = self.bdc.stationary_distribution() mun = stationary_distribution_from_backward_iteration(P) assert_allclose(mu, mun)
class TestCommittorDense(unittest.TestCase): def setUp(self): p = np.zeros(10) q = np.zeros(10) p[0:-1] = 0.5 q[1:] = 0.5 p[4] = 0.01 q[6] = 0.1 self.bdc = BirthDeathChain(q, p) def tearDown(self): pass def test_forward_comittor(self): P = self.bdc.transition_matrix() un = committor(P, [0, 1], [8, 9], forward=True) u = self.bdc.committor_forward(1, 8) assert_allclose(un, u) def test_backward_comittor(self): P = self.bdc.transition_matrix() un = committor(P, [0, 1], [8, 9], forward=False) u = self.bdc.committor_backward(1, 8) assert_allclose(un, u)
def setUpClass(cls) -> None: """Store state of the rng""" cls.state = np.random.mtrand.get_state() """Reseed the rng to enforce 'deterministic' behavior""" np.random.mtrand.seed(42) """Meta-stable birth-death chain""" b = 2 q = np.zeros(7) p = np.zeros(7) q[1:] = 0.5 p[0:-1] = 0.5 q[2] = 1.0 - 10 ** (-b) q[4] = 10 ** (-b) p[2] = 10 ** (-b) p[4] = 1.0 - 10 ** (-b) bdc = BirthDeathChain(q, p) P = bdc.transition_matrix() cls.dtraj = generate_traj(P, 10000, start=0) cls.tau = 1 """Estimate MSM""" import inspect argspec = inspect.getfullargspec(MaximumLikelihoodMSM) default_maxerr = argspec.defaults[argspec.args.index('maxerr') - 1] cls.C_MSM = msmest.count_matrix(cls.dtraj, cls.tau, sliding=True) cls.lcc_MSM = msmest.largest_connected_set(cls.C_MSM) cls.Ccc_MSM = msmest.largest_connected_submatrix(cls.C_MSM, lcc=cls.lcc_MSM) cls.P_MSM = msmest.transition_matrix(cls.Ccc_MSM, reversible=True, maxerr=default_maxerr) cls.mu_MSM = msmana.stationary_distribution(cls.P_MSM) cls.k = 3 cls.ts = msmana.timescales(cls.P_MSM, k=cls.k, tau=cls.tau)
class TestTptFunctionsSparse(unittest.TestCase): def setUp(self): p = np.zeros(10) q = np.zeros(10) p[0:-1] = 0.5 q[1:] = 0.5 p[4] = 0.01 q[6] = 0.1 self.A = [0, 1] self.B = [8, 9] self.a = 1 self.b = 8 self.bdc = BirthDeathChain(q, p) T_dense = self.bdc.transition_matrix() T_sparse = csr_matrix(T_dense) self.T = T_sparse self.mu = self.bdc.stationary_distribution() self.qminus = self.bdc.committor_backward(self.a, self.b) self.qplus = self.bdc.committor_forward(self.a, self.b) # present results self.fluxn = flux.flux_matrix(self.T, self.mu, self.qminus, self.qplus, netflux=False) self.netfluxn = flux.flux_matrix(self.T, self.mu, self.qminus, self.qplus, netflux=True) self.totalfluxn = flux.total_flux(self.netfluxn, self.A) self.raten = flux.rate(self.totalfluxn, self.mu, self.qminus) def test_tpt_flux(self): flux = self.bdc.flux(self.a, self.b) assert_allclose(self.fluxn.toarray(), flux) def test_tpt_netflux(self): netflux = self.bdc.netflux(self.a, self.b) assert_allclose(self.netfluxn.toarray(), netflux) def test_tpt_totalflux(self): totalflux = self.bdc.totalflux(self.a, self.b) assert_allclose(self.totalfluxn, totalflux) def test_tpt_rate(self): rate = self.bdc.rate(self.a, self.b) assert_allclose(self.raten, rate)
class TestRelaxationDense(unittest.TestCase): def setUp(self): p = np.zeros(10) q = np.zeros(10) p[0:-1] = 0.5 q[1:] = 0.5 p[4] = 0.01 q[6] = 0.1 self.bdc = BirthDeathChain(q, p) self.mu = self.bdc.stationary_distribution() self.T = self.bdc.transition_matrix() """Test matrix-vector product against spectral decomposition""" R, D, L = rdl_decomposition(self.T) self.L = L self.R = R self.ts = timescales(self.T) self.times = np.array([1, 5, 10, 20, 100]) ev = np.diagonal(D) self.ev_t = ev[np.newaxis, :]**self.times[:, np.newaxis] self.k = 4 """Observable""" obs1 = np.zeros(10) obs1[0] = 1 obs1[1] = 1 self.obs = obs1 """Initial distribution""" w0 = np.zeros(10) w0[0:4] = 0.25 self.p0 = w0 def test_relaxation(self): """k=None""" relax_amp = np.dot(self.p0, self.R) * np.dot(self.L, self.obs) relax = np.dot(self.ev_t, relax_amp) relaxn = relaxation(self.T, self.p0, self.obs, times=self.times) assert_allclose(relaxn, relax) """k=4""" k = self.k relax_amp = np.dot(self.p0, self.R[:, 0:k]) * np.dot( self.L[0:k, :], self.obs) relax = np.dot(self.ev_t[:, 0:k], relax_amp) relaxn = relaxation(self.T, self.p0, self.obs, k=k, times=self.times) assert_allclose(relaxn, relax)
class ReversibleTest(unittest.TestCase): def setUp(self): p = np.zeros(10) q = np.zeros(10) p[0:-1] = 0.5 q[1:] = 0.5 p[4] = 0.01 q[6] = 0.1 self.bdc = BirthDeathChain(q, p) self.T = self.bdc.transition_matrix() self.mu = self.bdc.stationary_distribution() def testIsReversible(self): # create a reversible matrix self.assertTrue(assessment.is_reversible(self.T, self.mu), "T should be reversible")
class TestTPT(unittest.TestCase): def setUp(self): p = np.zeros(10) q = np.zeros(10) p[0:-1] = 0.5 q[1:] = 0.5 p[4] = 0.01 q[6] = 0.1 self.A = [0, 1] self.B = [8, 9] self.a = 1 self.b = 8 self.bdc = BirthDeathChain(q, p) self.T = self.bdc.transition_matrix() """Use precomputed mu, qminus, qplus""" self.mu = self.bdc.stationary_distribution() self.qplus = self.bdc.committor_forward(self.a, self.b) self.qminus = self.bdc.committor_backward(self.a, self.b) # self.qminus = committor.backward_committor(self.T, self.A, self.B, mu=self.mu) # self.qplus = committor.forward_committor(self.T, self.A, self.B) self.fluxn = tpt.flux_matrix(self.T, self.mu, self.qminus, self.qplus, netflux=False) self.netfluxn = tpt.to_netflux(self.fluxn) self.Fn = tpt.total_flux(self.fluxn, self.A) self.kn = tpt.rate(self.Fn, self.mu, self.qminus) def test_flux(self): flux = self.bdc.flux(self.a, self.b) assert_allclose(self.fluxn, flux) def test_netflux(self): netflux = self.bdc.netflux(self.a, self.b) assert_allclose(self.netfluxn, netflux) def test_totalflux(self): F = self.bdc.totalflux(self.a, self.b) assert_allclose(self.Fn, F) def test_rate(self): k = self.bdc.rate(self.a, self.b) assert_allclose(self.kn, k)
class TestAssessmentDense(unittest.TestCase): def setUp(self): p = np.zeros(10) q = np.zeros(10) p[0:-1] = 0.5 q[1:] = 0.5 p[4] = 0.01 q[6] = 0.1 self.bdc = BirthDeathChain(q, p) self.T = self.bdc.transition_matrix() self.mu = self.bdc.stationary_distribution() self.A = create_rate_matrix() def test_IsRateMatrix(self): self.assertTrue(is_rate_matrix(self.A), 'A should be a rate matrix') # manipulate matrix so it isn't a rate matrix any more self.A[0][0] = 3 self.assertFalse(is_rate_matrix(self.A), 'matrix is not a rate matrix') def test_IsReversible(self): # create a reversible matrix self.assertTrue(is_reversible(self.T, self.mu), "T should be reversible") def test_is_transition_matrix(self): self.assertTrue(is_transition_matrix(self.T)) """Larger test-case to prevent too restrictive tolerance settings""" X = np.random.random((2000, 2000)) Tlarge = X / X.sum(axis=1)[:, np.newaxis] self.assertTrue(is_transition_matrix(Tlarge)) def test_is_connected(self): self.assertTrue(is_connected(self.T)) self.assertTrue(is_connected(self.T, directed=False))
class TestExpectation(unittest.TestCase): def setUp(self): p = np.zeros(10) q = np.zeros(10) p[0:-1] = 0.5 q[1:] = 0.5 p[4] = 0.01 q[6] = 0.1 self.bdc = BirthDeathChain(q, p) self.mu = self.bdc.stationary_distribution() self.T = self.bdc.transition_matrix() obs1 = np.zeros(10) obs1[0] = 1 obs1[1] = 1 self.obs1 = obs1 def test_expectation(self): exp = np.dot(self.mu, self.obs1) expn = expectation(self.T, self.obs1) assert_allclose(exp, expn)
class TestFingerprintDense(unittest.TestCase): def setUp(self): p = np.zeros(10) q = np.zeros(10) p[0:-1] = 0.5 q[1:] = 0.5 p[4] = 0.01 q[6] = 0.1 self.bdc = BirthDeathChain(q, p) self.mu = self.bdc.stationary_distribution() self.T = self.bdc.transition_matrix() R, D, L = rdl_decomposition(self.T) self.L = L self.R = R self.ts = timescales(self.T) self.times = np.array([1, 5, 10, 20]) ev = np.diagonal(D) self.ev_t = ev[np.newaxis, :]**self.times[:, np.newaxis] self.k = 4 self.tau = 7.5 """Observables""" obs1 = np.zeros(10) obs1[0] = 1 obs1[1] = 1 obs2 = np.zeros(10) obs2[8] = 1 obs2[9] = 1 self.obs1 = obs1 self.obs2 = obs2 """Initial vector for relaxation""" w0 = np.zeros(10) w0[0:4] = 0.25 self.p0 = w0 def test_fingerprint_correlation(self): """Autocorrelation""" """k=None, tau=1""" acorr_amp = np.dot(self.mu * self.obs1, self.R) * np.dot( self.L, self.obs1) tsn, acorr_ampn = fingerprint_correlation(self.T, self.obs1) assert_allclose(tsn, self.ts) assert_allclose(acorr_ampn, acorr_amp) """k=None, tau=7.5""" tau = self.tau tsn, acorr_ampn = fingerprint_correlation(self.T, self.obs1, tau=tau) assert_allclose(tsn, tau * self.ts) assert_allclose(acorr_ampn, acorr_amp) """k=4, tau=1""" k = self.k acorr_amp = np.dot(self.mu * self.obs1, self.R[:, 0:k]) * np.dot( self.L[0:k, :], self.obs1) tsn, acorr_ampn = fingerprint_correlation(self.T, self.obs1, k=k) assert_allclose(tsn, self.ts[0:k]) assert_allclose(acorr_ampn, acorr_amp) """k=4, tau=7.5""" tau = self.tau tsn, acorr_ampn = fingerprint_correlation(self.T, self.obs1, k=k, tau=tau) assert_allclose(tsn, tau * self.ts[0:k]) assert_allclose(acorr_ampn, acorr_amp) """Cross-correlation""" """k=None, tau=1""" corr_amp = np.dot(self.mu * self.obs1, self.R) * np.dot( self.L, self.obs2) tsn, corr_ampn = fingerprint_correlation(self.T, self.obs1, obs2=self.obs2) assert_allclose(tsn, self.ts) assert_allclose(corr_ampn, corr_amp) """k=None, tau=7.5""" tau = self.tau tsn, corr_ampn = fingerprint_correlation(self.T, self.obs1, obs2=self.obs2, tau=tau) assert_allclose(tsn, tau * self.ts) assert_allclose(corr_ampn, corr_amp) """k=4, tau=1""" k = self.k corr_amp = np.dot(self.mu * self.obs1, self.R[:, 0:k]) * np.dot( self.L[0:k, :], self.obs2) tsn, corr_ampn = fingerprint_correlation(self.T, self.obs1, obs2=self.obs2, k=k) assert_allclose(tsn, self.ts[0:k]) assert_allclose(corr_ampn, corr_amp) """k=4, tau=7.5""" tau = self.tau tsn, corr_ampn = fingerprint_correlation(self.T, self.obs1, obs2=self.obs2, k=k, tau=tau) assert_allclose(tsn, tau * self.ts[0:k]) assert_allclose(corr_ampn, corr_amp) def test_fingerprint_relaxation(self): one_vec = np.ones(self.T.shape[0]) """k=None""" relax_amp = np.dot(self.p0, self.R) * np.dot(self.L, self.obs1) tsn, relax_ampn = fingerprint_relaxation(self.T, self.p0, self.obs1) assert_allclose(tsn, self.ts) assert_allclose(relax_ampn, relax_amp) """k=4""" k = self.k relax_amp = np.dot(self.p0, self.R[:, 0:k]) * np.dot( self.L[0:k, :], self.obs1) tsn, relax_ampn = fingerprint_relaxation(self.T, self.p0, self.obs1, k=k) assert_allclose(tsn, self.ts[0:k]) assert_allclose(relax_ampn, relax_amp)
class TestCorrelationDense(unittest.TestCase): def setUp(self): p = np.zeros(10) q = np.zeros(10) p[0:-1] = 0.5 q[1:] = 0.5 p[4] = 0.01 q[6] = 0.1 self.bdc = BirthDeathChain(q, p) self.mu = self.bdc.stationary_distribution() self.T = self.bdc.transition_matrix() R, D, L = rdl_decomposition(self.T, norm='reversible') self.L = L self.R = R self.ts = timescales(self.T) self.times = np.array([1, 5, 10, 20, 100]) ev = np.diagonal(D) self.ev_t = ev[np.newaxis, :]**self.times[:, np.newaxis] self.k = 4 obs1 = np.zeros(10) obs1[0] = 1 obs1[1] = 1 obs2 = np.zeros(10) obs2[8] = 1 obs2[9] = 1 self.obs1 = obs1 self.obs2 = obs2 self.one_vec = np.ones(10) def test_correlation(self): """Auto-correlation""" """k=None""" acorr_amp = np.dot(self.mu * self.obs1, self.R) * np.dot( self.L, self.obs1) acorr = np.dot(self.ev_t, acorr_amp) acorrn = correlation(self.T, self.obs1, times=self.times) assert_allclose(acorrn, acorr) """k=4""" k = self.k acorr_amp = np.dot(self.mu * self.obs1, self.R[:, 0:k]) * np.dot( self.L[0:k, :], self.obs1) acorr = np.dot(self.ev_t[:, 0:k], acorr_amp) acorrn = correlation(self.T, self.obs1, times=self.times, k=k) assert_allclose(acorrn, acorr) """Cross-correlation""" """k=None""" corr_amp = np.dot(self.mu * self.obs1, self.R) * np.dot( self.L, self.obs2) corr = np.dot(self.ev_t, corr_amp) corrn = correlation(self.T, self.obs1, obs2=self.obs2, times=self.times) assert_allclose(corrn, corr) """k=4""" k = self.k corr_amp = np.dot(self.mu * self.obs1, self.R[:, 0:k]) * np.dot( self.L[0:k, :], self.obs2) corr = np.dot(self.ev_t[:, 0:k], corr_amp) corrn = correlation(self.T, self.obs1, obs2=self.obs2, times=self.times, k=k) assert_allclose(corrn, corr)
class TestDecompositionDense(unittest.TestCase): def setUp(self): self.dim = 100 self.k = 10 """Set up meta-stable birth-death chain""" p = np.zeros(self.dim) p[0:-1] = 0.5 q = np.zeros(self.dim) q[1:] = 0.5 p[self.dim // 2 - 1] = 0.001 q[self.dim // 2 + 1] = 0.001 self.bdc = BirthDeathChain(q, p) def test_statdist(self): P = self.bdc.transition_matrix() mu = self.bdc.stationary_distribution() mun = stationary_distribution(P) assert_allclose(mu, mun) def test_eigenvalues(self): P = self.bdc.transition_matrix() ev = eigvals(P) """Sort with decreasing magnitude""" ev = ev[np.argsort(np.abs(ev))[::-1]] """k=None""" evn = eigenvalues(P) assert_allclose(ev, evn) """k is not None""" evn = eigenvalues(P, k=self.k) assert_allclose(ev[0:self.k], evn) def test_eigenvectors(self): P = self.bdc.transition_matrix() # k==None ev = eigvals(P) ev = ev[np.argsort(np.abs(ev))[::-1]] Dn = np.diag(ev) # right eigenvectors Rn = eigenvectors(P) assert_allclose(np.dot(P, Rn), np.dot(Rn, Dn)) # left eigenvectors Ln = eigenvectors(P, right=False).T assert_allclose(np.dot(Ln.T, P), np.dot(Dn, Ln.T)) # orthogonality Xn = np.dot(Ln.T, Rn) di = np.diag_indices(Xn.shape[0]) Xn[di] = 0.0 assert_allclose(Xn, 0) # k!=None Dnk = Dn[:, 0:self.k][0:self.k, :] # right eigenvectors Rn = eigenvectors(P, k=self.k) assert_allclose(np.dot(P, Rn), np.dot(Rn, Dnk)) # left eigenvectors Ln = eigenvectors(P, right=False, k=self.k).T assert_allclose(np.dot(Ln.T, P), np.dot(Dnk, Ln.T)) # orthogonality Xn = np.dot(Ln.T, Rn) di = np.diag_indices(self.k) Xn[di] = 0.0 assert_allclose(Xn, 0) def test_eigenvalues_reversible(self): P = self.bdc.transition_matrix() ev = eigvals(P) """Sort with decreasing magnitude""" ev = ev[np.argsort(np.abs(ev))[::-1]] """reversible without given mu""" evn = eigenvalues(P, reversible=True) assert_allclose(ev, evn) """reversible with given mu""" evn = eigenvalues(P, reversible=True, mu=self.bdc.stationary_distribution()) assert_allclose(ev, evn) def test_eigenvectors_reversible(self): P = self.bdc.transition_matrix() # k==None ev = eigvals(P) ev = ev[np.argsort(np.abs(ev))[::-1]] Dn = np.diag(ev) # right eigenvectors Rn = eigenvectors(P, reversible=True) assert_allclose(np.dot(P, Rn), np.dot(Rn, Dn)) # left eigenvectors Ln = eigenvectors(P, right=False, reversible=True).T assert_allclose(np.dot(Ln.T, P), np.dot(Dn, Ln.T)) # orthogonality Xn = np.dot(Ln.T, Rn) di = np.diag_indices(Xn.shape[0]) Xn[di] = 0.0 assert_allclose(Xn, 0) # k!=None Dnk = Dn[:, 0:self.k][0:self.k, :] # right eigenvectors Rn = eigenvectors(P, k=self.k, reversible=True) assert_allclose(np.dot(P, Rn), np.dot(Rn, Dnk)) # left eigenvectors Ln = eigenvectors(P, right=False, k=self.k, reversible=True).T assert_allclose(np.dot(Ln.T, P), np.dot(Dnk, Ln.T)) # orthogonality Xn = np.dot(Ln.T, Rn) di = np.diag_indices(self.k) Xn[di] = 0.0 assert_allclose(Xn, 0) def test_rdl_decomposition(self): P = self.bdc.transition_matrix() assert is_reversible(P) mu = self.bdc.stationary_distribution() """Non-reversible""" """k=None""" Rn, Dn, Ln = rdl_decomposition(P) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(np.dot(P, Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(np.dot(Ln, P), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.dim)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """k is not None""" Rn, Dn, Ln = rdl_decomposition(P, k=self.k) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(np.dot(P, Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(np.dot(Ln, P), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Reversible""" """k=None""" Rn, Dn, Ln = rdl_decomposition(P, norm='reversible') assert Dn.dtype in (np.float32, np.float64) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(np.dot(P, Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(np.dot(Ln, P), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.dim)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Reversibility""" assert_allclose(Ln.transpose(), mu[:, np.newaxis] * Rn) """k is not None""" Rn, Dn, Ln = rdl_decomposition(P, norm='reversible', k=self.k) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(np.dot(P, Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(np.dot(Ln, P), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Reversibility""" assert_allclose(Ln.transpose(), mu[:, np.newaxis] * Rn) def test_rdl_decomposition_rev(self): P = self.bdc.transition_matrix() mu = self.bdc.stationary_distribution() """norm='standard'""" """k=None""" Rn, Dn, Ln = rdl_decomposition(P, reversible=True, norm='standard') Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(np.dot(P, Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(np.dot(Ln, P), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.dim)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Standard l2-normalization of right eigenvectors except dominant one""" Yn = np.dot(Rn.T, Rn) assert_allclose(np.diag(Yn)[1:], 1.0) """k is not None""" Rn, Dn, Ln = rdl_decomposition(P, k=self.k, reversible=True, norm='standard') Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(np.dot(P, Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(np.dot(Ln, P), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Standard l2-normalization of right eigenvectors except dominant one""" Yn = np.dot(Rn.T, Rn) assert_allclose(np.diag(Yn)[1:], 1.0) """norm='reversible'""" """k=None""" Rn, Dn, Ln = rdl_decomposition(P, reversible=True, norm='reversible') Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(np.dot(P, Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(np.dot(Ln, P), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.dim)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Reversibility""" assert_allclose(Ln.transpose(), mu[:, np.newaxis] * Rn) """k is not None""" Rn, Dn, Ln = rdl_decomposition(P, reversible=True, norm='reversible', k=self.k) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(np.dot(P, Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(np.dot(Ln, P), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Reversibility""" assert_allclose(Ln.transpose(), mu[:, np.newaxis] * Rn) def test_timescales(self): P = self.bdc.transition_matrix() ev = eigvals(P) """Sort with decreasing magnitude""" ev = ev[np.argsort(np.abs(ev))[::-1]] ts = -1.0 / np.log(np.abs(ev)) """k=None""" tsn = timescales(P) assert_allclose(ts[1:], tsn[1:]) """k is not None""" tsn = timescales(P, k=self.k) assert_allclose(ts[1:self.k], tsn[1:]) """tau=7""" """k=None""" tsn = timescales(P, tau=7) assert_allclose(7 * ts[1:], tsn[1:]) """k is not None""" tsn = timescales(P, k=self.k, tau=7) assert_allclose(7 * ts[1:self.k], tsn[1:]) def test_timescales_rev(self): P_dense = self.bdc.transition_matrix() P = self.bdc.transition_matrix() mu = self.bdc.stationary_distribution() ev = eigvals(P_dense) """Sort with decreasing magnitude""" ev = ev[np.argsort(np.abs(ev))[::-1]] ts = -1.0 / np.log(np.abs(ev)) tsn = timescales(P, reversible=True) assert_allclose(ts[1:], tsn[1:]) """k is not None""" tsn = timescales(P, k=self.k, reversible=True) assert_allclose(ts[1:self.k], tsn[1:]) """k is not None, mu is not None""" tsn = timescales(P, k=self.k, reversible=True, mu=mu) assert_allclose(ts[1:self.k], tsn[1:]) """tau=7""" """k is not None""" tsn = timescales(P, k=self.k, tau=7, reversible=True) assert_allclose(7 * ts[1:self.k], tsn[1:])
class TestDecompositionSparse(unittest.TestCase): def setUp(self): self.dim = 100 self.k = 10 self.ncv = 40 """Set up meta-stable birth-death chain""" p = np.zeros(self.dim) p[0:-1] = 0.5 q = np.zeros(self.dim) q[1:] = 0.5 p[int(self.dim / 2 - 1)] = 0.001 q[int(self.dim / 2 + 1)] = 0.001 self.bdc = BirthDeathChain(q, p) def test_statdist(self): P = self.bdc.transition_matrix_sparse() mu = self.bdc.stationary_distribution() mun = stationary_distribution(P) assert_allclose(mu, mun) def test_eigenvalues(self): P = self.bdc.transition_matrix_sparse() P_dense = self.bdc.transition_matrix() ev = eigvals(P_dense) """Sort with decreasing magnitude""" ev = ev[np.argsort(np.abs(ev))[::-1]] """k=None""" with self.assertRaises(ValueError): evn = eigenvalues(P) """k is not None""" evn = eigenvalues(P, k=self.k) assert_allclose(ev[0:self.k], evn) """k is not None and ncv is not None""" evn = eigenvalues(P, k=self.k, ncv=self.ncv) assert_allclose(ev[0:self.k], evn) def test_eigenvalues_rev(self): P = self.bdc.transition_matrix_sparse() P_dense = self.bdc.transition_matrix() ev = eigvals(P_dense) """Sort with decreasing magnitude""" ev = ev[np.argsort(np.abs(ev))[::-1]] """k=None""" with self.assertRaises(ValueError): evn = eigenvalues(P, reversible=True) """k is not None""" evn = eigenvalues(P, k=self.k, reversible=True) assert_allclose(ev[0:self.k], evn) """k is not None and ncv is not None""" evn = eigenvalues(P, k=self.k, ncv=self.ncv, reversible=True) assert_allclose(ev[0:self.k], evn) """mu is not None""" mu = self.bdc.stationary_distribution() """k=None""" with self.assertRaises(ValueError): evn = eigenvalues(P, reversible=True, mu=mu) """k is not None""" evn = eigenvalues(P, k=self.k, reversible=True, mu=mu) assert_allclose(ev[0:self.k], evn) """k is not None and ncv is not None""" evn = eigenvalues(P, k=self.k, ncv=self.ncv, reversible=True, mu=mu) assert_allclose(ev[0:self.k], evn) def test_eigenvectors(self): P_dense = self.bdc.transition_matrix() P = self.bdc.transition_matrix_sparse() ev, L, R = eig(P_dense, left=True, right=True) ind = np.argsort(np.abs(ev))[::-1] ev = ev[ind] R = R[:, ind] L = L[:, ind] vals = ev[0:self.k] """k=None""" with self.assertRaises(ValueError): Rn = eigenvectors(P) with self.assertRaises(ValueError): Ln = eigenvectors(P, right=False) """k is not None""" Rn = eigenvectors(P, k=self.k) assert_allclose(vals[np.newaxis, :] * Rn, P.dot(Rn)) Ln = eigenvectors(P, right=False, k=self.k).T assert_allclose(P.transpose().dot(Ln), vals[np.newaxis, :] * Ln) """k is not None and ncv is not None""" Rn = eigenvectors(P, k=self.k, ncv=self.ncv) assert_allclose(vals[np.newaxis, :] * Rn, P.dot(Rn)) Ln = eigenvectors(P, right=False, k=self.k, ncv=self.ncv).T assert_allclose(P.transpose().dot(Ln), vals[np.newaxis, :] * Ln) def test_eigenvectors_rev(self): P_dense = self.bdc.transition_matrix() P = self.bdc.transition_matrix_sparse() ev, L, R = eig(P_dense, left=True, right=True) ind = np.argsort(np.abs(ev))[::-1] ev = ev[ind] R = R[:, ind] L = L[:, ind] vals = ev[0:self.k] """k=None""" with self.assertRaises(ValueError): Rn = eigenvectors(P, reversible=True) with self.assertRaises(ValueError): Ln = eigenvectors(P, right=False, reversible=True).T """k is not None""" Rn = eigenvectors(P, k=self.k, reversible=True) assert_allclose(vals[np.newaxis, :] * Rn, P.dot(Rn)) Ln = eigenvectors(P, right=False, k=self.k, reversible=True).T assert_allclose(P.transpose().dot(Ln), vals[np.newaxis, :] * Ln) """k is not None and ncv is not None""" Rn = eigenvectors(P, k=self.k, ncv=self.ncv, reversible=True) assert_allclose(vals[np.newaxis, :] * Rn, P.dot(Rn)) Ln = eigenvectors(P, right=False, k=self.k, ncv=self.ncv, reversible=True).T assert_allclose(P.transpose().dot(Ln), vals[np.newaxis, :] * Ln) """mu is not None""" mu = self.bdc.stationary_distribution() """k=None""" with self.assertRaises(ValueError): Rn = eigenvectors(P, reversible=True, mu=mu) with self.assertRaises(ValueError): Ln = eigenvectors(P, right=False, reversible=True, mu=mu).T """k is not None""" Rn = eigenvectors(P, k=self.k, reversible=True, mu=mu) assert_allclose(vals[np.newaxis, :] * Rn, P.dot(Rn)) Ln = eigenvectors(P, right=False, k=self.k, reversible=True, mu=mu).T assert_allclose(P.transpose().dot(Ln), vals[np.newaxis, :] * Ln) """k is not None and ncv is not None""" Rn = eigenvectors(P, k=self.k, ncv=self.ncv, reversible=True, mu=mu) assert_allclose(vals[np.newaxis, :] * Rn, P.dot(Rn)) Ln = eigenvectors(P, right=False, k=self.k, ncv=self.ncv, reversible=True, mu=mu).T assert_allclose(P.transpose().dot(Ln), vals[np.newaxis, :] * Ln) def test_rdl_decomposition(self): P = self.bdc.transition_matrix_sparse() mu = self.bdc.stationary_distribution() """Non-reversible""" """k=None""" with self.assertRaises(ValueError): Rn, Dn, Ln = rdl_decomposition(P) """k is not None""" Rn, Dn, Ln = rdl_decomposition(P, k=self.k) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(P.dot(Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(P.transpose().dot(Ln.transpose()).transpose(), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """k is not None, ncv is not None""" Rn, Dn, Ln = rdl_decomposition(P, k=self.k, ncv=self.ncv) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(P.dot(Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(P.transpose().dot(Ln.transpose()).transpose(), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Reversible""" """k=None""" with self.assertRaises(ValueError): Rn, Dn, Ln = rdl_decomposition(P, norm='reversible') """k is not None""" Rn, Dn, Ln = rdl_decomposition(P, k=self.k, norm='reversible') Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(P.dot(Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(P.transpose().dot(Ln.transpose()).transpose(), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Reversibility""" assert_allclose(Ln.transpose(), mu[:, np.newaxis] * Rn) """k is not None ncv is not None""" Rn, Dn, Ln = rdl_decomposition(P, k=self.k, norm='reversible', ncv=self.ncv) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(P.dot(Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(P.transpose().dot(Ln.transpose()).transpose(), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Reversibility""" assert_allclose(Ln.transpose(), mu[:, np.newaxis] * Rn) def test_rdl_decomposition_rev(self): P = self.bdc.transition_matrix_sparse() mu = self.bdc.stationary_distribution() """Non-reversible""" """k=None""" with self.assertRaises(ValueError): Rn, Dn, Ln = rdl_decomposition(P, reversible=True) """norm='standard'""" Rn, Dn, Ln = rdl_decomposition(P, k=self.k, reversible=True, norm='standard') Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(P.dot(Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(P.transpose().dot(Ln.transpose()).transpose(), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Standard l2-normalization of right eigenvectors except dominant one""" Yn = np.dot(Rn.T, Rn) assert_allclose(np.diag(Yn)[1:], 1.0) """ncv is not None""" Rn, Dn, Ln = rdl_decomposition(P, k=self.k, reversible=True, norm='standard', ncv=self.ncv) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(P.dot(Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(P.transpose().dot(Ln.transpose()).transpose(), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Standard l2-normalization of right eigenvectors except dominant one""" Yn = np.dot(Rn.T, Rn) assert_allclose(np.diag(Yn)[1:], 1.0) """norm='reversible'""" Rn, Dn, Ln = rdl_decomposition(P, reversible=True, norm='reversible', k=self.k) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(P.dot(Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(P.transpose().dot(Ln.transpose()).transpose(), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Reversibility""" assert_allclose(Ln.transpose(), mu[:, np.newaxis] * Rn) Rn, Dn, Ln = rdl_decomposition(P, reversible=True, norm='reversible', k=self.k, ncv=self.ncv) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(P.dot(Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(P.transpose().dot(Ln.transpose()).transpose(), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Reversibility""" assert_allclose(Ln.transpose(), mu[:, np.newaxis] * Rn) """mu is not None""" """norm='standard'""" Rn, Dn, Ln = rdl_decomposition(P, k=self.k, reversible=True, norm='standard', mu=mu) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(P.dot(Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(P.transpose().dot(Ln.transpose()).transpose(), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Standard l2-normalization of right eigenvectors except dominant one""" Yn = np.dot(Rn.T, Rn) assert_allclose(np.diag(Yn)[1:], 1.0) """ncv is not None""" Rn, Dn, Ln = rdl_decomposition(P, k=self.k, reversible=True, norm='standard', ncv=self.ncv, mu=mu) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(P.dot(Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(P.transpose().dot(Ln.transpose()).transpose(), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Standard l2-normalization of right eigenvectors except dominant one""" Yn = np.dot(Rn.T, Rn) assert_allclose(np.diag(Yn)[1:], 1.0) """norm='reversible'""" Rn, Dn, Ln = rdl_decomposition(P, reversible=True, norm='reversible', k=self.k, mu=mu) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(P.dot(Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(P.transpose().dot(Ln.transpose()).transpose(), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Reversibility""" assert_allclose(Ln.transpose(), mu[:, np.newaxis] * Rn) Rn, Dn, Ln = rdl_decomposition(P, reversible=True, norm='reversible', k=self.k, ncv=self.ncv, mu=mu) Xn = np.dot(Ln, Rn) """Right-eigenvectors""" assert_allclose(P.dot(Rn), np.dot(Rn, Dn)) """Left-eigenvectors""" assert_allclose(P.transpose().dot(Ln.transpose()).transpose(), np.dot(Dn, Ln)) """Orthonormality""" assert_allclose(Xn, np.eye(self.k)) """Probability vector""" assert_allclose(np.sum(Ln[0, :]), 1.0) """Reversibility""" assert_allclose(Ln.transpose(), mu[:, np.newaxis] * Rn) def test_timescales(self): P_dense = self.bdc.transition_matrix() P = self.bdc.transition_matrix_sparse() ev = eigvals(P_dense) """Sort with decreasing magnitude""" ev = ev[np.argsort(np.abs(ev))[::-1]] ts = -1.0 / np.log(np.abs(ev)) """k=None""" with self.assertRaises(ValueError): tsn = timescales(P) """k is not None""" tsn = timescales(P, k=self.k) assert_allclose(ts[1:self.k], tsn[1:]) """k is not None, ncv is not None""" tsn = timescales(P, k=self.k, ncv=self.ncv) assert_allclose(ts[1:self.k], tsn[1:]) """tau=7""" """k is not None""" tsn = timescales(P, k=self.k, tau=7) assert_allclose(7 * ts[1:self.k], tsn[1:]) def test_timescales_rev(self): P_dense = self.bdc.transition_matrix() P = self.bdc.transition_matrix_sparse() mu = self.bdc.stationary_distribution() ev = eigvals(P_dense) """Sort with decreasing magnitude""" ev = ev[np.argsort(np.abs(ev))[::-1]] ts = -1.0 / np.log(np.abs(ev)) """k=None""" with self.assertRaises(ValueError): tsn = timescales(P, reversible=True) """k is not None""" tsn = timescales(P, k=self.k, reversible=True) assert_allclose(ts[1:self.k], tsn[1:]) """k is not None, ncv is not None""" tsn = timescales(P, k=self.k, ncv=self.ncv, reversible=True) assert_allclose(ts[1:self.k], tsn[1:]) """k is not None, mu is not None""" tsn = timescales(P, k=self.k, reversible=True, mu=mu) assert_allclose(ts[1:self.k], tsn[1:]) """k is not None, mu is not None, ncv is not None""" tsn = timescales(P, k=self.k, ncv=self.ncv, reversible=True, mu=mu) assert_allclose(ts[1:self.k], tsn[1:]) """tau=7""" """k is not None""" tsn = timescales(P, k=self.k, tau=7, reversible=True) assert_allclose(7 * ts[1:self.k], tsn[1:])
class TestTPTDense(unittest.TestCase): def setUp(self): p = np.zeros(10) q = np.zeros(10) p[0:-1] = 0.5 q[1:] = 0.5 p[4] = 0.01 q[6] = 0.1 self.A = [0, 1] self.B = [8, 9] self.a = 1 self.b = 8 self.bdc = BirthDeathChain(q, p) self.T = self.bdc.transition_matrix() """Compute mu, qminus, qplus in constructor""" self.tpt = flux.tpt(self.T, self.A, self.B) """Use precomputed mu, qminus, qplus""" self.mu = self.bdc.stationary_distribution() self.qminus = self.bdc.committor_backward(self.a, self.b) self.qplus = self.bdc.committor_forward(self.a, self.b) self.tpt_fast = flux.tpt(self.T, self.A, self.B, mu=self.mu, qminus=self.qminus, qplus=self.qplus) def test_grossflux(self): flux = self.bdc.flux(self.a, self.b) fluxn = self.tpt.gross_flux assert_allclose(fluxn, flux) fluxn = self.tpt_fast.gross_flux assert_allclose(fluxn, flux) def test_netflux(self): netflux = self.bdc.netflux(self.a, self.b) netfluxn = self.tpt.net_flux assert_allclose(netfluxn, netflux) netfluxn = self.tpt_fast.net_flux assert_allclose(netfluxn, netflux) def test_totalflux(self): F = self.bdc.totalflux(self.a, self.b) Fn = self.tpt.total_flux assert_allclose(Fn, F) Fn = self.tpt_fast.total_flux assert_allclose(Fn, F) def test_rate(self): k = self.bdc.rate(self.a, self.b) kn = self.tpt.rate assert_allclose(kn, k) kn = self.tpt_fast.rate assert_allclose(kn, k) def test_backward_committor(self): qminus = self.qminus qminusn = self.tpt.backward_committor assert_allclose(qminusn, qminus) qminusn = self.tpt_fast.backward_committor assert_allclose(qminusn, qminus) def test_forward_committor(self): qplus = self.qplus qplusn = self.tpt.forward_committor assert_allclose(qplusn, qplus) qplusn = self.tpt_fast.forward_committor assert_allclose(qplusn, qplus) def test_stationary_distribution(self): mu = self.mu mun = self.tpt.stationary_distribution assert_allclose(mun, mu) mun = self.tpt_fast.stationary_distribution assert_allclose(mun, mu)
class TestCorrelations(unittest.TestCase): def setUp(self): p = np.zeros(10) q = np.zeros(10) p[0:-1] = 0.5 q[1:] = 0.5 p[4] = 0.01 q[6] = 0.1 self.bdc = BirthDeathChain(q, p) self.mu = self.bdc.stationary_distribution() self.T = self.bdc.transition_matrix() def test_time_correlation(self): """ since we have no overlap between observations and do not propagate the operator, the correlation is zero. P^0 = diag(1) """ obs1 = np.zeros(10) obs1[0] = 1 obs1[1] = 1 obs2 = np.zeros(10) obs2[8] = 1 obs2[9] = 1 time = 0 corr = correlations.time_correlation_direct_by_mtx_vec_prod( self.T, self.mu, obs1, obs2, time) self.assertEqual(corr, 0) time = 100 corr = correlations.time_correlation_direct_by_mtx_vec_prod( self.T, self.mu, obs1, obs2, time) self.assertGreater(corr, 0.0, "correlation should be > 0.") @unittest.SkipTest def test_time_auto_correlation(self): """test with obs2 = obs1, to test autocorrelation""" obs1 = np.zeros(10) obs1[0] = 1 time = 100 print( correlations.time_correlation_direct_by_mtx_vec_prod(self.T, self.mu, obs1, time=time)) @unittest.SkipTest def test_time_corr2(self): obs1 = np.zeros(10) obs1[5:] = 1 obs2 = np.zeros(10) obs2[8] = 1 time = 2 print( correlations.time_correlation_direct_by_mtx_vec_prod(self.T, self.mu, obs1, obs2, time=time)) def test_time_correlations(self): """ tests whether the outcome of the wrapper time_correlations_direct is equivalent to calls to time_correlation_direct_by_mtx_vec_prod with same time set. """ obs1 = np.zeros(10) obs1[3:5] = 1 obs2 = np.zeros(10) obs2[4:8] = 1 times = [1, 2, 20, 40, 100, 200, 1000] # calculate without wrapper corr_expected = np.empty(len(times)) i = 0 for t in times: corr_expected[ i] = correlations.time_correlation_direct_by_mtx_vec_prod( self.T, self.mu, obs1, obs2, t) i += 1 # calculate with wrapper corr_actual = correlations.time_correlations_direct( self.T, self.mu, obs1, obs2, times) self.assertTrue( np.allclose(corr_expected, corr_actual), "correlations differ:\n%s\n%s" % (corr_expected, corr_actual)) def test_time_relaxation_stat(self): """ start with stationary distribution, so increasing time should not change relaxation any more. """ obs = np.zeros(10) obs[9] = 1 p0 = self.mu c1 = correlations.time_relaxation_direct_by_mtx_vec_prod(self.T, p0, obs, time=1) c1000 = correlations.time_relaxation_direct_by_mtx_vec_prod(self.T, p0, obs, time=1000) self.assertAlmostEqual( c1, c1000, msg="relaxation should be same, since we start in equilibrium.") def test_time_relaxation(self): obs = np.zeros(10) obs[9] = 1 p0 = np.zeros(10) * 1. / 10 # compute by hand # p0 P^k obs P1000 = np.linalg.matrix_power(self.T, 1000) expected = np.dot(np.dot(p0, P1000), obs) result = correlations.time_relaxation_direct_by_mtx_vec_prod(self.T, p0, obs, time=1000) self.assertAlmostEqual(expected, result) def test_time_relaxations(self): obs = np.zeros(10) obs[9] = 1 p0 = np.zeros(10) * 1. / 10 times = [1, 100, 1000] expected = [] for t in times: expected.append( correlations.time_relaxation_direct_by_mtx_vec_prod( self.T, p0, obs, t)) result = correlations.time_relaxations_direct(self.T, p0, obs, times) assert_allclose(expected, result)