示例#1
0
    def eig(self,
            state: State,
            k=6,
            which='SM',
            use_initial_guess=False,
            plot=False):
        """Returns a list of the eigenvalues and the corresponding valid density matrix.
        Functionality only for if input is a density matrix."""
        assert not state.is_ket
        is_ket = state.is_ket
        code = state.code
        IS_subspace = state.IS_subspace
        graph = state.graph
        state_shape = state.shape

        def f(flattened):
            s = State(flattened.reshape(state_shape))
            res = self.evolution_generator(s)
            return res.reshape(flattened.shape)

        state_flattened = state.flatten()

        lindbladian = LinearOperator(shape=(len(state_flattened),
                                            len(state_flattened)),
                                     dtype=np.complex128,
                                     matvec=f)

        if not use_initial_guess:
            v0 = None
        else:
            v0 = state_flattened
        try:
            eigvals, eigvecs = eigs(lindbladian, k=k, which=which, v0=v0)
        except ArpackNoConvergence as exception_info:
            eigvals = exception_info.eigenvalues
            eigvecs = exception_info.eigenvectors
        if eigvals.size != 0:
            # Do some basic reshaping to post process the results and select for only the steady states
            eigvecs = np.reshape(
                eigvecs, [state.shape[0], state.shape[1], eigvecs.shape[-1]])
            eigvecs = np.moveaxis(eigvecs, -1, 0)
            # If there is one steady s, then normalize it because it is a valid density matrix

            if plot:
                eigvals_cc = eigvals.conj()
                eigvals_real = np.concatenate((eigvals.real, eigvals.real))
                eigvals_complex = np.concatenate(
                    (eigvals_cc.imag, eigvals_cc.imag))
                plt.hlines(0, xmin=-1, xmax=.1)
                plt.vlines(0, ymin=-100, ymax=100)
                plt.scatter(eigvals_real, eigvals_complex, c='m', s=4)
                plt.show()
            return eigvals, eigvecs
        else:
            return None, None
示例#2
0
    def edg(self,
            state: State,
            k=6,
            which='LR',
            use_initial_guess=False,
            tol=1e-8):
        dim = state.dimension
        eigval, eigvec = self.steady_state(state,
                                           k=k,
                                           which=which,
                                           use_initial_guess=use_initial_guess,
                                           plot=False)
        steady_state = eigvec[np.argwhere(eigval[np.abs(eigval) <= tol])[
            0, 0], :, :]
        steady_state = steady_state / np.trace(steady_state)
        # Diagonalize the steady state
        ss_eigvals, ss_eigvecs = np.linalg.eigh(steady_state)
        where_nonzero = np.abs(ss_eigvals) > tol
        if np.sum(where_nonzero) < dim:
            print('Steady state is not full rank.')
        projected_ss_eigvals = where_nonzero * ss_eigvecs
        P = projected_ss_eigvals @ projected_ss_eigvals.conj().T
        Q = np.identity(dim) - P

        state_shape = state.shape

        def f(flattened):
            s = State(flattened.reshape(state_shape))
            res = P @ self.evolution_generator(P @ s @ P) @ P + Q @ self.evolution_generator(Q @ s @ P) @ P + \
                  P @ self.evolution_generator(P @ s @ Q) @ Q
            return res.reshape(flattened.shape)

        state_flattened = state.flatten()

        lindbladian = LinearOperator(shape=(len(state_flattened),
                                            len(state_flattened)),
                                     dtype=np.complex128,
                                     matvec=f)

        if not use_initial_guess:
            v0 = None
        else:
            v0 = state_flattened
        try:
            eigvals, eigvecs = eigs(lindbladian, k=k, which=which, v0=v0)
        except ArpackNoConvergence as exception_info:
            eigvals = exception_info.eigenvalues
        if eigvals.size == 0:
            return None

        nonzero = np.abs(eigvals[np.abs(eigvals) > tol])
        where_max = np.argmin(nonzero)
        min_eigval = np.abs(nonzero[where_max])
        return min_eigval
示例#3
0
    def steady_state(self,
                     state: State,
                     k=6,
                     which='LR',
                     use_initial_guess=False,
                     plot=False,
                     tol=1e-8,
                     verbose=False):
        """Returns a list of the eigenvalues and the corresponding valid density matrix."""
        assert not state.is_ket
        state_shape = state.shape

        def f(flattened):
            s = State(flattened.reshape(state_shape))
            res = self.evolution_generator(s)
            return res.reshape(flattened.shape)

        state_flattened = state.flatten()
        lindbladian = LinearOperator(shape=(len(state_flattened),
                                            len(state_flattened)),
                                     dtype=np.complex128,
                                     matvec=f)
        if not use_initial_guess:
            v0 = None
        else:
            v0 = state_flattened
        try:
            eigvals, eigvecs = eigs(lindbladian, k=k, which=which, v0=v0)
        except ArpackNoConvergence as exception_info:
            eigvals = exception_info.eigenvalues
            eigvecs = exception_info.eigenvectors
        if eigvals.size != 0:
            # Do some basic reshaping to post process the results and select for only the steady states
            eigvecs = np.moveaxis(eigvecs, -1, 0)
            eigvecs = np.reshape(
                eigvecs, [eigvecs.shape[0], state_shape[0], state_shape[1]])
            steady_state_indices = np.argwhere(eigvals.real > -1 * tol).T[0]
            steady_state_eigvecs = eigvecs[steady_state_indices, :, :]
            if verbose:
                print('Number of steady states is ',
                      str(steady_state_eigvecs.shape[0]))
            # If there is one steady s, then normalize it because it is a valid density matrix
            if steady_state_eigvecs.shape[0] == 1:
                steady_state_eigvecs[0, :, :] = steady_state_eigvecs[
                    0, :, :] / np.trace(steady_state_eigvecs[0, :, :])
                if verbose:
                    print(
                        'Steady state is a valid density matrix:',
                        tools.is_valid_state(steady_state_eigvecs[0, :, :],
                                             verbose=False))
            steady_state_eigvals = eigvals[steady_state_indices]
            if plot:
                steady_state_eigvals_cc = steady_state_eigvals.conj()
                steady_state_eigvals_real = np.concatenate(
                    (steady_state_eigvals.real, steady_state_eigvals.real))
                steady_state_eigvals_complex = np.concatenate(
                    (steady_state_eigvals_cc.imag,
                     steady_state_eigvals_cc.imag))
                plt.hlines(0, xmin=-1, xmax=.1)
                plt.vlines(0, ymin=-100, ymax=100)
                plt.scatter(steady_state_eigvals_real,
                            steady_state_eigvals_complex,
                            c='m',
                            s=4)
                plt.show()
            return steady_state_eigvals, steady_state_eigvecs
        else:
            return None, None