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
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
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