def _get_hamiltonian_variables( self) -> Tuple[q.qarray, q.qarray, q.qarray]: sx = q.pauli("X", sparse=True) sz = q.pauli("Z", sparse=True) qnum = (sz + q.identity(2, sparse=True)) / 2 dims = [2] * self.N # noinspection PyTypeChecker time_independent_terms: q.qarray = 0 # noinspection PyTypeChecker Omega_coeff_terms: q.qarray = 0 # noinspection PyTypeChecker Delta_coeff_terms: q.qarray = 0 for i in range(self.N): Omega_coeff_terms += q.ikron(sx, dims=dims, inds=i, sparse=True) / 2 n_i = q.ikron(qnum, dims=dims, inds=i, sparse=True) Delta_coeff_terms -= n_i for j in range(i): n_j = q.ikron(qnum, dims=dims, inds=j, sparse=True) time_independent_terms += self.V / self.geometry.get_distance( i, j)**6 * n_i * n_j return (time_independent_terms, Omega_coeff_terms, Delta_coeff_terms)
def get_hamiltonian_variables_with_edge_fields( e_qs: EvolvingQubitSystem) -> Tuple[q.qarray, q.qarray, q.qarray]: sx = q.pauli("X", sparse=True) sz = q.pauli("Z", sparse=True) qnum = (sz + q.identity(2, sparse=True)) / 2 dims = [2] * e_qs.N # noinspection PyTypeChecker time_independent_terms: q.qarray = 0 # noinspection PyTypeChecker Omega_coeff_terms: q.qarray = 0 # noinspection PyTypeChecker Delta_coeff_terms: q.qarray = 0 for i in range(e_qs.N): Omega_coeff_terms += q.ikron(sx, dims=dims, inds=i, sparse=True) / 2 n_i = q.ikron(qnum, dims=dims, inds=i, sparse=True) Delta_coeff_terms -= n_i if e_qs.N <= 8: if i == 0 or i == e_qs.N - 1: time_independent_terms += n_i * 4.5e6 * 2 * np.pi elif e_qs.N > 8: if i == 0 or i == e_qs.N - 1: time_independent_terms += n_i * 6e6 * 2 * np.pi elif i == 3 or i == e_qs.N - 4: time_independent_terms += n_i * 1.5e6 * 2 * np.pi for j in range(i): n_j = q.ikron(qnum, dims=dims, inds=j, sparse=True) time_independent_terms += e_qs.V / e_qs.geometry.get_distance( i, j)**6 * n_i * n_j return (time_independent_terms, Omega_coeff_terms, Delta_coeff_terms)
def test_graph_state_1d(self): n = 5 p = graph_state_1d(n, cyclic=True) for j in range(n): k = eyepad( [pauli('x'), pauli('z'), pauli('z')], [2] * n, (j, (j - 1) % n, (j + 1) % n)) o = p.H @ k @ p np.testing.assert_allclose(o, 1)
def test_entangled(self, s, ct, pre_c): p = qu.bell_state('psi-') c = qu.correlation(p, qu.pauli(s), qu.pauli(s), 0, 1, precomp_func=pre_c) c = c(p) if pre_c else c assert_allclose(c, ct)
def test_classically_no_correlated(self, s, qtype, pre_c): p = qu.up(qtype=qtype) & qu.up(qtype=qtype) c = qu.correlation(p, qu.pauli(s), qu.pauli(s), 0, 1, precomp_func=pre_c) c = c(p) if pre_c else c assert_allclose(c, 0.0)
def test_reuse_precomp(self): cfn = qu.correlation(None, qu.pauli('z'), qu.pauli('z'), 0, 1, dims=[2, 2], precomp_func=True) assert_allclose(cfn(qu.bell_state('psi-')), -1.0) assert_allclose(cfn(qu.bell_state('phi+')), 1.0)
def test_trans_invar(self): with pytest.raises(ValueError): psi = MPS_rand_state(10, 7, cyclic=False, trans_invar=True) psi = MPS_rand_state(10, 7, cyclic=True, trans_invar=True) z0 = expec_TN_1D(psi, gate_TN_1D(psi, qu.pauli('Z'), 0, contract=True)) z3 = expec_TN_1D(psi, gate_TN_1D(psi, qu.pauli('Z'), 0, contract=True)) z7 = expec_TN_1D(psi, gate_TN_1D(psi, qu.pauli('Z'), 0, contract=True)) assert_allclose(z0, z3) assert_allclose(z3, z7)
def test_correlation(self): ghz = (MPS_computational_state('0000') + MPS_computational_state('1111')) / 2**0.5 assert ghz.correlation(qu.pauli('Z'), 0, 1) == pytest.approx(1.0) assert ghz.correlation(qu.pauli('Z'), 1, 2) == pytest.approx(1.0) assert ghz.correlation(qu.pauli('Z'), 3, 1) == pytest.approx(1.0) assert ghz.correlation(qu.pauli('Z'), 3, 1, B=qu.pauli('Y')) == pytest.approx(0.0) assert ghz.H @ ghz == pytest.approx(1.0)
def test_classically_correlated(self, s, ct, pre_c): p = 0.5 * ((qu.up(qtype='dop') & qu.up(qtype='dop')) + (qu.down(qtype='dop') & qu.down(qtype='dop'))) c = qu.correlation(p, qu.pauli(s), qu.pauli(s), 0, 1, precomp_func=pre_c) c = c(p) if pre_c else c assert_allclose(c, ct)
def test_mixed(self): rho = qu.dop(qu.bell_state('psi-')) IZ = qu.pauli('I') & qu.pauli('Z') ZI = qu.pauli('Z') & qu.pauli('I') res, rho_after = qu.measure(rho, IZ) # normalized assert qu.tr(rho_after) == pytest.approx(1.0) # anticorrelated assert qu.expectation(rho_after, IZ) == pytest.approx(res) assert qu.expectation(rho_after, ZI) == pytest.approx(-res) assert isinstance(rho_after, qu.qarray)
def test_pure(self): psi = qu.bell_state('psi-') IZ = qu.pauli('I') & qu.pauli('Z') ZI = qu.pauli('Z') & qu.pauli('I') res, psi_after = qu.measure(psi, IZ) # normalized assert qu.expectation(psi_after, psi_after) == pytest.approx(1.0) # anticorrelated assert qu.expectation(psi_after, IZ) == pytest.approx(res) assert qu.expectation(psi_after, ZI) == pytest.approx(-res) assert isinstance(psi_after, qu.qarray)
def test_types(self, dims, op_sps, p_sps, pre_c): p = qu.rand_rho(4, sparse=p_sps) c = qu.correlation(p, qu.pauli('x', sparse=op_sps), qu.pauli('z', sparse=op_sps), 0, 1, dims=dims, precomp_func=pre_c) c = c(p) if pre_c else c assert c >= -1.0 assert c <= 1.0
def mpo_particle(L): We = np.zeros([1, 1, 2, 2]) Wo = np.zeros([1, 1, 2, 2]) Z = qu.pauli('Z') X = qu.pauli('X') Y = qu.pauli('Y') I = qu.pauli('I') S_up = (X + 1.0j * Y) * (0.5) S_down = (X - 1.0j * Y) * (0.5) # S_up=S_up.astype('float64') # S_down=S_down.astype('float64') # Z=Z.astype('float64') MPO_I = MPO_identity(2 * L, phys_dim=2) MPO_result = MPO_identity(2 * L, phys_dim=2) MPO_result = MPO_result * 0.0 max_bond_val = 200 cutoff_val = 1.0e-12 MPO_result = MPO_identity(2 * L, phys_dim=2) MPO_result = MPO_result * 0.0 for i in range(L): Wl = np.zeros([1, 2, 2], dtype='complex128') W = np.zeros([1, 1, 2, 2], dtype='complex128') Wr = np.zeros([1, 2, 2], dtype='complex128') Wl[0, :, :] = S_up @ S_down W[0, 0, :, :] = S_up @ S_down Wr[0, :, :] = S_up @ S_down W_list = [Wl] + [W] * (2 * L - 2) + [Wr] MPO_I = MPO_identity(2 * L, phys_dim=2) MPO_I[2 * i].modify(data=W_list[2 * i]) MPO_result = MPO_result + MPO_I MPO_result.compress(max_bond=max_bond_val, cutoff=cutoff_val) MPO_I = MPO_identity(2 * L, phys_dim=2) MPO_I[2 * i + 1].modify(data=W_list[2 * i + 1]) MPO_result = MPO_result + MPO_I MPO_result.compress(max_bond=max_bond_val, cutoff=cutoff_val) return MPO_result
def test_pauli_reconstruct(self): p1 = qu.rand_rho(4) names_cffs = qu.pauli_decomp(p1, mode='c') pr = sum( qu.kron(*(qu.pauli(s) for s in name)) * names_cffs["".join(name)] for name in itertools.product('IXYZ', repeat=2)) assert_allclose(pr, p1)
def H_hop(self, i, j, f, dir): ''' TODO: pkron vs ikron performance? i, j: (directed) edge qubits indices f: face qubit index dir: {'vertical', 'horizontal'} Returns hopping term acting on qbits ijf, (XiXjOf + YiYjOf)/2 where Of is Xf, Yf or Identity depending on ijf ''' X, Y = (qu.pauli(mu) for mu in ['x', 'y']) Of = {'vertical': X, 'horizontal': Y}[dir] #if no face qbit if f == None: # print('{}--{}-->{} (None)'.format(i,dir[0],j)) # XXO=qu.ikron(ops=[X,X], dims=self._sim_dims, inds=[i,j]) # YYO=qu.ikron(ops=[Y,Y], dims=self._sim_dims, inds=[i,j]) XXO = qu.pkron(op=X & X, dims=self._sim_dims, inds=[i, j]) YYO = qu.pkron(op=Y & Y, dims=self._sim_dims, inds=[i, j]) #if there's a face qubit: Of acts on index f else: # print('{}--{}-->{}, face {}'.format(i,dir[0],j,f)) # XXO=qu.ikron(ops=[X,X,Of], dims=self._sim_dims, inds=[i,j,f]) # YYO=qu.ikron(ops=[Y,Y,Of], dims=self._sim_dims, inds=[i,j,f]) XXO = qu.pkron(op=X & X & Of, dims=self._sim_dims, inds=(i, j, f)) YYO = qu.pkron(op=Y & Y & Of, dims=self._sim_dims, inds=(i, j, f)) return 0.5 * (XXO + YYO)
def stabilizer_at_face(self, fi, fj): stab_data = self.loop_stabilizer_data(fi, fj) oplist = [qu.pauli(Q) for Q in stab_data['opstring']] return qu.ikron(ops=oplist, dims=self._sim_dims, inds=stab_data['inds'])
def test_purify(self): for vec, op, val in zip(((.5, 0, 0), (0, .5, 0), (0, 0, .5), (-.5, 0, 0), (0, -.5, 0), (0, 0, -.5)), ("x", "y", "z", "x", "y", "z"), (1, 1, 1, -1, -1, -1)): x = tr(bloch_state(*vec, purified=True) @ pauli(op)) assert_allclose(x, val)
def test_mixed(self): for vec, op, val in zip(((.5, 0, 0), (0, .5, 0), (0, 0, .5), (-.5, 0, 0), (0, -.5, 0), (0, 0, -.5)), ("x", "y", "z", "x", "y", "z"), (.5, .5, .5, -.5, -.5, -.5)): x = tr(bloch_state(*vec) @ pauli(op)) assert_allclose(x, val)
def test_pure(self): for vec, op, val in zip(((1, 0, 0), (0, 1, 0), (0, 0, 1), (-1, 0, 0), (0, -1, 0), (0, 0, -1)), ("x", "y", "z", "x", "y", "z"), (1, 1, 1, -1, -1, -1)): x = tr(bloch_state(*vec) @ pauli(op)) assert_allclose(x, val)
def _three_site_hop_gate(self, edge_dir): '''Hop gate acting on two vertices and a face site. ''' X, Y = (qu.pauli(mu) for mu in ['x', 'y']) O_face = {'vertical': X, 'horizontal': Y}[edge_dir] return 0.5 * ((X & X & O_face) + (Y & Y & O_face))
def _three_site_hop_gate(self, spin, edge_dir): '''Hop gate acting on two vertices and a face site, in `spin` sector. Action on the face site depends on `edge_dir`: {'vertical', 'horizontal'} ''' spin = { 0: 'up', 1: 'down', 'up': 'up', 'down': 'down', 'u': 'up', 'd': 'down' }[spin] X, Y, I = (qu.pauli(mu) for mu in ['x', 'y', 'i']) #operators acting on the correct spin sector if spin == 'up': X_s = X & I Y_s = Y & I elif spin == 'down': X_s = I & X Y_s = I & Y #operator on face qubit (in `spin` sector) Of_s = {'vertical': X_s, 'horizontal': Y_s}[edge_dir] return 0.5 * ((X_s & X_s & Of_s) + (Y_s & Y_s & Of_s))
def main_test(): psi = beeky.QubitEncodeVector.rand(3, 3) X, Y, Z = (qu.pauli(i) for i in 'xyz') where = (3, 4, 9) #which qubits to act on numsites = len(where) dp = 2 #phys ind dimension gate = X & X & X ## take over from here ## g_xx = qtn.tensor_1d.maybe_factor_gate_into_tensor( gate, dp, numsites, where) #shape (2,2,2,2) or (2,2,2,2,2,2) site_inds = [psi.phys_ind_id.format(q) for q in where] bond_inds = [qtn.rand_uuid() for _ in range(numsites)] reindex_map = dict(zip(site_inds, bond_inds)) TG = qtn.Tensor(g_xx, inds=site_inds + bond_inds, left_inds=bond_inds, tags=['GATE']) original_ts = [psi[q] for q in where] bonds_along = [ next(iter(qtn.bonds(t1, t2))) for t1, t2 in qu.utils.pairwise(original_ts) ] triangle_gate_absorb(TG=TG, reindex_map=reindex_map, vertex_tensors=(psi[where[0]], psi[where[1]]), face_tensor=psi[where[2]], phys_inds=site_inds)
def test_pauli_dim3(self): for dir in (1, 'x', 'X', 2, 'y', 'Y', 3, 'z', 'Z'): x = qu.pauli(dir, dim=3) assert_allclose(qu.eigvalsh(x), [-1, 0, 1], atol=1e-15)
def two_qubit_eigsectors(strA='XY', strB='YX'): ''' Params: strA, strB [strings] Action of stabilizers on face-qubit subspace. Return: `eigsectors` [ndarray(shape=(2,2), dtype=object)] Each element of eigsector contains the unique vector in the face-qubit subspace that diagonalizes strA, strB with respective eigenvalues +/-1. eigsectors[0,0]: +1, +1 eigsectors[0,1]: +1, -1 eigsectors[1,0]: -1, +1 eigsectors[1,1]: -1, -1 ''' sign_dic = {0: 1.0, 1: -1.0} X, Y, Z, I = (qu.pauli(mu) for mu in ['x','y','z','i']) opmap = {'X': X, 'Y':Y, 'Z':Z, 'I':I} face_dims = [2]*2 #dimensions of face-qubit subspace # ### # strA = 'XY' # strB = 'YX' # ### SA = qu.kron(*[opmap[Q] for Q in strA]) SB = qu.kron(*[opmap[Q] for Q in strB]) # SA, SB = X&Y, Y&X eigsectors = np.ndarray(shape=face_dims, dtype=object) eva, Ua = qu.eigh(SA) for indA, signA in sign_dic.items(): #pick evectors in (signA) sector Ua_sgn = Ua[:, np.isclose(eva, signA)] #4x2 #Stabilizer B on (signA) eigspace of SA Qb = Ua_sgn.H @ SB @ Ua_sgn evb, Ub = qu.eigh(Qb) for indB, signB in sign_dic.items(): #pick evector in signB sector Ub_sgn = Ub[:,np.isclose(evb, signB)] #2x1 face_state = Ua_sgn @ Ub_sgn #4x1 assert np.allclose(SA@face_state, signA*face_state) assert np.allclose(SB@face_state, signB*face_state) eigsectors[indA,indB] = face_state return eigsectors
def test_simple(self): Z = qu.pauli('Z') P = qu.projector(Z & Z) uu = qu.dop(qu.up()) & qu.dop(qu.up()) dd = qu.dop(qu.down()) & qu.dop(qu.down()) assert_allclose(P, uu + dd) assert qu.expec(P, qu.bell_state('phi+')) == pytest.approx(1.0) assert qu.expec(P, qu.bell_state('psi+')) == pytest.approx(0.0)
def test_bigger(self): psi = qu.rand_ket(2**5) assert np.sum(abs(psi) < 1e-12) == 0 A = qu.kronpow(qu.pauli('Z'), 5) res, psi_after = qu.measure(psi, A, eigenvalue=-1.0) # should have projected to half subspace assert np.sum(abs(psi_after) < 1e-12) == 2**4 assert res == -1.0
def test_evo_at_times(self): ham = qu.ham_heis(2, cyclic=False) p0 = qu.up() & qu.down() sim = qu.Evolution(p0, ham, method='solve') ts = np.linspace(0, 10) for t, pt in zip(ts, sim.at_times(ts)): x = cos(t) y = qu.expec(pt, qu.ikron(qu.pauli('z'), [2, 2], 0)) assert_allclose(x, y, atol=1e-15)
def test_quevo_at_times(self): ham = ham_heis(2, cyclic=False) p0 = up() & down() sim = QuEvo(p0, ham, method='solve') ts = np.linspace(0, 10) for t, pt in zip(ts, sim.at_times(ts)): x = cos(t) y = expec(pt, eyepad(pauli('z'), [2, 2], 0)) assert_allclose(x, y, atol=1e-15)
def edge_simulate(args): circ, kwargs, edge = args ZZ = qu.pauli('Z') & qu.pauli('Z') opt_type = kwargs.get('ordering_algo', 'uniform') if opt_type == 'hyper': optimizer = ctg.HyperOptimizer(parallel=False, max_repeats=10000, max_time=kwargs.get( 'optimizer_time', 1)) elif opt_type == 'uniform': optimizer = ctg.UniformOptimizer(parallel=False, methods=['greedy'], max_repeats=1_000_000, max_time=kwargs.get( 'optimizer_time', 1)) else: raise ValueError('Ordering algorithm not supported') #return circ.local_expectation(ZZ, edge, optimize=optimizer) return circ.local_expectation(ZZ, edge, optimize=optimizer)
def test_simple(self): n = 10 d_psi = qu.computational_state('0' * n) t_psi = Dense1D(d_psi) assert set(t_psi.outer_inds()) == {'k{}'.format(i) for i in range(n)} assert set(t_psi.tags) == {'I{}'.format(i) for i in range(n)} for i in range(n): assert t_psi.H @ t_psi.gate(qu.pauli('Z'), i) == pytest.approx(1) for i in range(n): t_psi.gate_(qu.hadamard(), i) assert len(t_psi.tensors) == n + 1 # should have '++++++++++' assert t_psi.H @ t_psi == pytest.approx(1) for i in range(n): assert t_psi.H @ t_psi.gate(qu.pauli('X'), i) == pytest.approx(1)