def _transformation_gates_from_z( pauli: Pauli ) -> typing.Tuple[typing.List[cirq.Gate], typing.List[cirq.Gate]]: if pauli == Pauli("Z"): return [], [] elif pauli == Pauli("X"): return [cirq.H], [cirq.H] elif pauli == Pauli("Y"): # vectors_y.inv.dagger @ z @ vectors_y.inv == y # vectors_y == i Rz(pi/2) Ry(pi/2) Rz(3pi/2) # vectors_y.inv == -i Rz(-3pi/2) Ry(-pi/2) Rz(-pi/2) # vectors_y.inv.dagger == i Rz(pi/2) Ry(pi/2) Rz(3pi/2) return ([ cirq.rz(np.pi / 2), cirq.ry(np.pi / 2), cirq.rz(3 * np.pi / 2) ], [ cirq.rz(-3 * np.pi / 2), cirq.ry(-np.pi / 2), cirq.rz(-np.pi / 2) ]) else: raise ValueError("invalid Pauli {}".format(pauli))
def test_commutator(self): word = Pauli("Y") word1, word2 = word.get_the_other_two_paulis() self.assertTupleEqual( (word1.string, word2.string), ("Z", "X") ) self.assertTrue(np.allclose( 2j * word.array, commutator(word1.array, word2.array) ))
def test_symbolic_gate(self): sym_circuit = Circuit() qubits = [GridQubit(i, j) for i in range(3) for j in range(3)] gate = TwoPauliExpGate(Pauli("X"), Pauli("Z"), sympy.Symbol("rad")) sym_circuit.append(gate.on(qubits[0], qubits[2])) self.assertEqual( str(sym_circuit), "(0, 0): ───^X────────\n" " │\n" "(0, 2): ───^Z{rad}───")
def test_pauli(self): for op in ["X", 0, np.array([[0, 1], [1, 0]])]: x = Pauli(op) self.assertEqual(x.string, "X") self.assertEqual(x.index, 0) self.assertTrue(np.allclose( x.array, np.array([[0, 1], [1, 0]]) )) for op in ["I", 3, np.array([[1, 0], [0, 1]])]: x = Pauli(op) self.assertEqual(x.string, "I") self.assertEqual(x.index, 3) self.assertTrue(np.allclose( x.array, np.array([[1, 0], [0, 1]]) ))
def __init__(self, pauli0: typing.Union[Pauli, str, numbers.Integral, np.ndarray], pauli1: typing.Union[Pauli, str, numbers.Integral, np.ndarray], rad: typing.Union[float, sympy.Basic]): """ Initialize the gate. :param pauli0: The `A0` in e^{-i A0 A1 rad}. :param pauli1: The `A1` in e^{-i A0 A1 rad}. :param rad: The `rad` in e^{-i A0 A1 rad}. """ self.pauli0 = pauli0 if isinstance(pauli0, Pauli) else Pauli(pauli0) self.pauli1 = pauli1 if isinstance(pauli1, Pauli) else Pauli(pauli1) self.rad = rad
def _decompose_(self, qubits: typing.Sequence[cirq.Qid]): factor = pauli_word_exp_factorization(self.coefficient, self.pauli_word) for coeff, word in reversed(factor): if word.effective_len == 1: # Note that `dict_form` is a property, therefore `word` won't be changed: qubit_index, rot_axis = word.dict_form.popitem() rotation_gate = getattr( cirq, "r{}".format(rot_axis.lower()) ) # type: typing.Union[cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate] # `* 2` comes from the 2 in the denominator in the exponential of R{x, y, z} yield rotation_gate(coeff * 2).on(qubits[qubit_index]) else: # word.effective_len == 2: (qubit_index0, rot_axis0), (qubit_index1, rot_axis1) = \ list(word.dict_form.items()) two_qubit_gate = TwoPauliExpGate(Pauli(rot_axis0), Pauli(rot_axis1), coeff) yield two_qubit_gate.on(qubits[qubit_index0], qubits[qubit_index1])
def setUp(self) -> None: self.circuit = Circuit() self.qubits = [GridQubit(i, j) for i in range(3) for j in range(3)] self.gate = TwoPauliExpGate(Pauli("X"), Pauli("Z"), 0.5) self.circuit.append(self.gate.on(self.qubits[0], self.qubits[2]))
def pauli_word_exp_factorization( coefficient: typing.Union[float, sympy.Basic], pauli_word: PauliWord ) -> typing.List[typing.Tuple[typing.Union[float, sympy.Basic], PauliWord]]: """ Factorize the exponentiation of Pauli word P $$ e^{−i t P} $$ (where t is the coefficient) with formula: $$ e^{−i t P} = e^{i (π/4) wk'' P2} e^{−i t P1 wk'} e^{−i (π/4) wk'' P2}, $$ where wk, P1 and P2 satisfy $P = P1 wk P2$. The subscript of $wk$ denotes that this elementary Pauli operator corresponds to the kth qubit. The word $P1 (P2)$ contains all qubit indices that are strictly greater (lower) than k. wk' and wk'' are the other two Pauli operators which satisfy $$ [ w', w'' ] = 2 i w. $$ :param coefficient: float coefficient t in the exponential. :param pauli_word: PauliWord the Pauli word P in the exponential. :return: the factorized form of $e^{−i t P}$. For example, if $$ e^{−i t P} = e^{−i tn Pn} ... e^{−i t1 P1} e^{−i t0 P0}, $$ then the returned will be like: [ (tn, Pn), ... (t0, P0), ]. Note that 0 <= Pi.effective_len <= 2. """ if pauli_word.effective_len == 0: return [] elif pauli_word.effective_len < 3: return [(coefficient, pauli_word)] # choose k pauli_dict_form = pauli_word.dict_form k = sorted(pauli_dict_form.keys())[len(pauli_dict_form) // 2] p1, wk, p2 = [pauli_word[:k], pauli_word[k], pauli_word[k + 1:]] i1, i2 = map(lambda word: PauliWord("I" * len(word)), [p1, p2]) wk1, wk2 = Pauli(wk.word).get_the_other_two_paulis() _factorized = pauli_word_exp_factorization(coefficient=sympy.Symbol("t"), pauli_word=PauliWord.join( i1, wk2, p2)) returned = [(float(c.subs({"t": -np.pi / 4})), w) if isinstance(c, sympy.Basic) else (c, w) for c, w in _factorized] returned.extend( pauli_word_exp_factorization(coefficient=coefficient, pauli_word=PauliWord.join(p1, wk1, i2))) returned.extend([(float(c.subs({"t": np.pi / 4})), w) if isinstance(c, sympy.Basic) else (c, w) for c, w in _factorized]) # returned = pauli_word_exp_factorization( # coefficient=-np.pi / 4, # pauli_word=PauliWord.join(i1, wk2, p2) # ) # # returned.extend(pauli_word_exp_factorization( # coefficient=coefficient, # pauli_word=PauliWord.join(p1, wk1, i2) # )) # # returned.extend(pauli_word_exp_factorization( # coefficient=np.pi / 4, # pauli_word=PauliWord.join(i1, wk2, p2) # )) return returned