def test_both_mixed(self, p1, p2): f = qu.fidelity(qu.eye(3) / 3, qu.eye(3) / 3) assert_allclose(f, 1.0) f = qu.fidelity(p1, p1) assert_allclose(f, 1.0) f = qu.fidelity(p1, p2) assert f > 0 and f < 1
def get_fidelity_with(self, target_state: Union[str, q.qarray] = "ghz") -> float: """ :param target_state: One of "ghz", "ghz_antisymmetric", "ground", and "excited" :return: """ assert ( self.evo is not None), "evo attribute cannot be None (call solve method)" final_state = self.solved_states[-1] if target_state == "ghz": return q.fidelity(final_state, self.ghz_state.get_state_tensor(symmetric=True)) elif target_state == "ghz_antisymmetric": return q.fidelity(final_state, self.ghz_state.get_state_tensor(symmetric=False)) elif target_state == "ground": return q.fidelity(final_state, q.kron(*states_quimb.get_ground_states(self.N))) elif target_state == "excited": return q.fidelity(final_state, q.kron(*states_quimb.get_excited_states(self.N))) elif isinstance(target_state, q.qarray): return q.fidelity(final_state, target_state) else: raise ValueError( f"target_state has to be one of 'ghz', 'ground', or 'excited', not {target_state}." )
def plot_ghz_states_overlaps(self, ax, with_antisymmetric_ghz: bool, plot_title: bool = True): labelled_states = [(self.ghz_state.get_state_tensor(), r"$\psi_{\mathrm{GHZ}}^{\mathrm{s}}$")] if with_antisymmetric_ghz: labelled_states.append( (self.ghz_state.get_state_tensor(symmetric=False), r"$\psi_{\mathrm{GHZ}}^{\mathrm{a}}$")) for _state, _label in labelled_states: ax.plot(self.solved_t_list, [ q.fidelity(_state, _instantaneous_state) for _instantaneous_state in self.solved_states ], label=_label, lw=1, alpha=0.8) ax.set_ylabel("Fidelity") if plot_title: ax.set_title("Fidelity with GHZ states") ax.set_ylim((-0.1, 1.1)) ax.yaxis.set_ticks([0, 0.5, 1]) ax.legend()
def test_w_state(self, dtype): mps = qtn.MPS_w_state(5, dtype=dtype) assert mps.dtype == dtype psi = qu.w_state(5, dtype=dtype) assert mps.H @ mps == pytest.approx(1.0) assert mps.bond_sizes() == [2, 2, 2, 2] assert qu.fidelity(psi, mps.to_dense()) == pytest.approx(1.0)
def test_orthog_pure(self, orthog_ks): k1, k2, k3 = orthog_ks for s1, s2, in ([k1, k2], [k2, k3], [k3, k1], [k1 @ k1.H, k2], [k1, k2 @ k2.H], [k3 @ k3.H, k2], [k3, k2 @ k2.H], [k1 @ k1.H, k3], [k1, k3 @ k3.H], [k1 @ k1.H, k2 @ k2.H], [k2 @ k2.H, k3 @ k3.H], [k1 @ k1.H, k3 @ k3.H]): f = qu.fidelity(s1, s2) assert_allclose(f, 0.0, atol=1e-6)
if dis_flag == 1: H_1 = qu.ham_mbl(N, W, J_tab, cyclic=False, dh_dist='qp', beta=0.721, seed=seed, sparse=True).real else: H_1 = qu.ham_mbl(N, W, J_tab, cyclic=False, seed=seed, sparse=True).real H_post = P.T @ H_1 @ P compute = {'time': lambda t, p: t, 'losch': lambda t, p: qu.fidelity(psi_0, p)} evo = qu.Evolution(psi_0, H_post, compute=compute, method='expm') for t in evo.at_times(t_tab): continue TS = evo.results['time'] LOSCH = np.array(-np.log(evo.results['losch'])) / N if dis_flag == 1: directory = '../DATA/GSQPWi' + str(W_i) + '/L' + str(N) + '/D' + str( W) + '/' PATH_now = LOCAL + os.sep + directory + os.sep if not os.path.exists(PATH_now): os.makedirs(PATH_now) else:
subsys = range(N//2) # define subsystem base=hf.Base_states(N,N//2) ind_n=np.zeros((len(base), 2)) for i in range(len(base)): somma=0 for j in range(N//2): somma+=int(base[i][j]) ind_n[i]=[somma,i] StateList=[] for i in range(N//2+1): StateList.append(np.where(ind_n[:,0]==i)[0]) compute = { 'time': lambda t, p: t, 'losch': lambda t, p: np.square(np.absolute(qu.fidelity(psi_0, p))), 'imb': lambda t,p: np.real(I.expt_value(p)), 'entropy': lambda t, p: ent_entropy(p, basis, chain_subsys=subsys)['Sent_A'], 'num_ent': lambda t, p: hf.Num_ent(N, p, StateList) } evo = qu.Evolution(psi_0, H, compute=compute, method='solve') for pt in evo.at_times(t_tab): ts=evo.results['time'] Sent=N//2*(np.array(evo.results['entropy'])/np.log2(math.e)) P_N=np.array(evo.results['num_ent'])/np.log2(math.e) Losch=np.array(-np.log(evo.results['losch']))/N Imb=2*np.array(evo.results['imb'])
def test_both_pure(self, k1, k2): f = qu.fidelity(k1, k1) assert_allclose(f, 1.0) f = qu.fidelity(k1, k2) assert f > 0 and f < 1
calculate_subsystem_entropy(state_) for state_ in e_qs.solved_states ] print(f"calculated entropies in {time.time() - start_time:.3f}s") print("plotting.") fig, axs = plt.subplots(3, 1, sharex='all', figsize=(10, 8)) ax0, ax1, ax2 = axs ax0.xaxis.set_major_formatter(ticker.EngFormatter('s')) plt.xlabel('Time') e_qs.plot_Omega_and_Delta(ax0) ghz_state_tensor = ghz_state.get_state_tensor(True) ax1.plot(e_qs.t_list, [q.fidelity(ghz_state_tensor, _state) for _state in solved_states], label=r"$\psi_{\mathrm{GHZ}}^{\mathrm{s}}$", lw=1, alpha=0.8) ax1.set_ylabel("Fidelity") ax1.set_title("Fidelity with GHZ states") ax1.set_ylim((-0.1, 1.1)) ax1.yaxis.set_ticks([0, 0.5, 1]) ax1.legend() ax2.plot( e_qs.t_list, subsystem_entropy, ) ax2.set_title("Entanglement Entropy") ax2.set_ylabel(r"$e^{ \mathcal{S} ( \rho_A ) } \, / \, \frac{N}{2}$")
def test_evo_timedep_adiabatic_with_callbacks(self, dop, linop, num_callbacks): # tests time dependent Evolution via an adiabatic sweep with: # a) no callbacks # b) 1 callback that accesses the time-dependent Hamiltonian # c) 2 callbacks where one access the Hamiltonian and one doesn't if num_callbacks > 0 and (dop or linop): # should implement this at some point return L = 6 T = 20 H1 = qu.ham_mbl(L, dh=1.0, seed=4, sparse=True) gs1 = qu.groundstate(H1) H2 = qu.ham_mbl(L, dh=1.0, seed=5, sparse=True) gs2 = qu.groundstate(H2) if linop: import scipy.sparse.linalg as spla H1 = spla.aslinearoperator(H1) H2 = spla.aslinearoperator(H2) # make sure two ground states are different assert qu.fidelity(gs1, gs2) < 0.5 # linearly interpolate from one ham to the other def ham(t): return (1 - t / T) * H1 + (t / T) * H2 if linop: assert isinstance(ham(0.3), spla.LinearOperator) if dop: p0 = qu.dop(gs1) else: p0 = gs1 if num_callbacks == 0: evo = qu.Evolution(p0, ham, progbar=True) else: def gs_overlap(t, pt, H): evals, evecs = eigs_scipy(H(t), k=1, which='SA') return np.abs(qu.dot(pt.T, qu.qu(evecs[:, 0])))**2 if num_callbacks == 1: compute = gs_overlap if num_callbacks == 2: def norm(t, pt): return qu.dot(pt.T, pt) compute = {'norm': norm, 'gs_overlap': gs_overlap} evo = qu.Evolution(p0, ham, compute=compute, progbar=True) evo.update_to(T) # final state should now overlap much more with second hamiltonian GS assert qu.fidelity(evo.pt, gs1) < 0.5 assert qu.fidelity(evo.pt, gs2) > 0.99 if num_callbacks == 1: gs_overlap_results = evo.results # check that we stayed in the ground state the whole time assert ((np.array(gs_overlap_results) - 1.0) < 1e-3).all() if num_callbacks == 2: norm_results = evo.results['norm'] gs_overlap_results = evo.results['gs_overlap'] # check that we stayed normalized the whole time assert ((np.array(norm_results) - 1.0) < 1e-3).all() # check that we stayed in the ground state the whole time assert ((np.array(gs_overlap_results) - 1.0) < 1e-3).all()
H_ETH = P.T @ qu.ham_heis(N, J_ETH, sparse=True, cyclic=False) @ P Psi_ETH = qu.eigvecsh(H_ETH, k=1, which='SA') J_evo1 = (0.0, 0.0, 0.0) H_evo1 = P.T @ qu.ham_mbl(N, W, J_evo1, cyclic=False, dh_dist='qp', beta=0.721, seed=seed, sparse=True).real @ P compute = { 'time': lambda t, p: t, 'losch': lambda t, p: qu.fidelity(Psi_ETH, p) } evo_ETH = qu.Evolution(Psi_ETH, H_evo1, compute=compute, method='expm') for t in evo_ETH.at_times(t_tab): continue TS = evo_ETH.results['time'] LOSCH_ETH = np.array(-np.log(evo_ETH.results['losch'])) / N ### MBL --> ETH ### W_i = params.W_i J_MBL = (0.0, 0.0, 0.0) H_MBL = P.T @ qu.ham_mbl(N,