def test_sample_nonrev_1(self):
        P = sample_tmatrix(self.C, reversible=False)
        assert np.all(P.shape == self.C.shape)
        assert is_transition_matrix(P)

        # same with boject
        sampler = tmatrix_sampler(self.C, reversible=False)
        P = sampler.sample()
        assert np.all(P.shape == self.C.shape)
        assert is_transition_matrix(P)
Exemple #2
0
    def _update_transition_matrix(model: _SampleStorage,
                                  transition_matrix_prior,
                                  initial_distribution_prior,
                                  reversible: bool = True,
                                  stationary: bool = False,
                                  n_sampling_steps: int = 1000):
        """ Updates the hidden-state transition matrix and the initial distribution """
        C = _bd_util.count_matrix(model.hidden_trajs, 1,
                                  model.transition_matrix.shape[0])
        model.counts[...] = C
        C = C + transition_matrix_prior

        # check if we work with these options
        if reversible and not is_connected(C, directed=True):
            raise NotImplementedError(
                'Encountered disconnected count matrix with sampling option reversible:\n '
                f'{C}\nUse prior to ensure connectivity or use reversible=False.'
            )
        # ensure consistent sparsity pattern (P0 might have additional zeros because of underflows)
        # TODO: these steps work around a bug in msmtools. Should be fixed there
        P0 = transition_matrix(C,
                               reversible=reversible,
                               maxiter=10000,
                               warn_not_converged=False)
        zeros = np.where(P0 + P0.T == 0)
        C[zeros] = 0
        # run sampler
        Tij = sample_tmatrix(C,
                             nsample=1,
                             nsteps=n_sampling_steps,
                             reversible=reversible)

        # INITIAL DISTRIBUTION
        if stationary:  # p0 is consistent with P
            p0 = stationary_distribution(Tij, C=C)
        else:
            n0 = BayesianHMM._count_init(model.hidden_trajs,
                                         model.transition_matrix.shape[0])
            first_timestep_counts_with_prior = n0 + initial_distribution_prior
            positive = first_timestep_counts_with_prior > 0
            p0 = np.zeros(n0.shape, dtype=model.transition_matrix.dtype)
            p0[positive] = np.random.dirichlet(
                first_timestep_counts_with_prior[positive]
            )  # sample p0 from posterior

        # update HMM with new sample
        model.transition_matrix[...] = Tij
        model.stationary_distribution[...] = p0