def default_decompose(self, qubits): """An adjacency-respecting decomposition. 0: ───T───@──────────────@───────@──────────@────────── │ │ │ │ 1: ───T───X───@───T^-1───X───@───X──────@───X──────@─── │ │ │ │ 2: ───T───────X───T──────────X───T^-1───X───T^-1───X─── """ a, b, c = qubits # Hacky magic: avoid the non-adjacent edge. if hasattr(b, 'is_adjacent'): if not b.is_adjacent(a): b, c = c, b elif not b.is_adjacent(c): a, b = b, a t = common_gates.T sweep_abc = [common_gates.CNOT(a, b), common_gates.CNOT(b, c)] yield t(a), t(b), t(c) yield sweep_abc yield t(b)**-1, t(c) yield sweep_abc yield t(c)**-1 yield sweep_abc yield t(c)**-1 yield sweep_abc
def _decompose_(self, qubits): """See base class.""" a, b = qubits yield common_gates.CNOT(a, b) yield common_gates.CNotPowGate(exponent=self._exponent, global_shift=self.global_shift).on(b, a) yield common_gates.CNOT(a, b)
def default_decompose(self, qubits): a, b, c = qubits # Hacky magic: avoid the non-adjacent edge. if hasattr(b, 'is_adjacent'): if not b.is_adjacent(a): b, c = c, b elif not b.is_adjacent(c): a, b = b, a yield common_gates.T.on_each([a, b, c]) # Phase a, b, and c. yield common_gates.CNOT(c, b) yield common_gates.T(b)**-1 # Counter-phase b ⊕ c. yield common_gates.CNOT(a, b) yield common_gates.T(b) # Phase a ⊕ b ⊕ c. yield common_gates.CNOT(c, b) yield common_gates.T(b)**-1 # Counter-phase a ⊕ b. yield common_gates.CNOT(a, b) # If a then toggle b and c. yield common_gates.CNOT(b, c) yield common_gates.CNOT(a, b) yield common_gates.CNOT(b, c) yield common_gates.T(c)**-1 # Counter-phase a ⊕ c. # If a then un-toggle b and c. yield common_gates.CNOT(b, c) yield common_gates.CNOT(a, b) yield common_gates.CNOT(b, c)
def _decompose_outside_control( self, control: 'cirq.Qid', near_target: 'cirq.Qid', far_target: 'cirq.Qid' ) -> 'cirq.OP_TREE': """A decomposition assuming one of the targets is in the middle. control: ───T──────@────────@───@────────────@──────────────── │ │ │ │ near: ─X─T──────X─@─T^-1─X─@─X────@─X^0.5─X─@─X^0.5──────── │ │ │ │ │ far: ─@─Y^-0.5─T─X─T──────X─T^-1─X─T^-1────X─S─────X^-0.5─ """ a, b, c = control, near_target, far_target t = common_gates.T sweep_abc = [common_gates.CNOT(a, b), common_gates.CNOT(b, c)] yield common_gates.CNOT(c, b) yield pauli_gates.Y(c) ** -0.5 yield t(a), t(b), t(c) yield sweep_abc yield t(b) ** -1, t(c) yield sweep_abc yield t(c) ** -1 yield sweep_abc yield t(c) ** -1 yield pauli_gates.X(b) ** 0.5 yield sweep_abc yield common_gates.S(c) yield pauli_gates.X(b) ** 0.5 yield pauli_gates.X(c) ** -0.5
def default_decompose(self, qubits): """An adjacency-respecting decomposition. 0: ───p───@──────────────@───────@──────────@────────── │ │ │ │ 1: ───p───X───@───p^-1───X───@───X──────@───X──────@─── │ │ │ │ 2: ───p───────X───p──────────X───p^-1───X───p^-1───X─── where p = T**self._exponent """ a, b, c = qubits # Hacky magic: avoid the non-adjacent edge. if hasattr(b, 'is_adjacent'): if not b.is_adjacent(a): b, c = c, b elif not b.is_adjacent(c): a, b = b, a p = common_gates.T**self._exponent sweep_abc = [common_gates.CNOT(a, b), common_gates.CNOT(b, c)] yield p(a), p(b), p(c) yield sweep_abc yield p(b)**-1, p(c) yield sweep_abc yield p(c)**-1 yield sweep_abc yield p(c)**-1 yield sweep_abc
def _decompose_(self, qubits): """An adjacency-respecting decomposition. 0: ───p_0───@──────────────@───────@──────────@────────── │ │ │ │ 1: ───p_1───X───@───p_3────X───@───X──────@───X──────@─── │ │ │ │ 2: ───p_2───────X───p_4────────X───p_5────X───p_6────X─── where p_i = T**(4*x_i) and x_i solve the system of equations [0, 0, 1, 0, 1, 1, 1][x_0] [r_1] [0, 1, 0, 1, 1, 0, 1][x_1] [r_2] [0, 1, 1, 1, 0, 1, 0][x_2] [r_3] [1, 0, 0, 1, 1, 1, 0][x_3] = [r_4] [1, 0, 1, 1, 0, 0, 1][x_4] [r_5] [1, 1, 0, 0, 0, 1, 1][x_5] [r_6] [1, 1, 1, 0, 1, 0, 0][x_6] [r_7] where r_i is self._diag_angles_radians[i]. The above system was created by equating the composition of the gates in the circuit diagram to np.diag(self._diag_angles) (shifted by a global phase of np.exp(-1j * self._diag_angles[0])). """ a, b, c = qubits if hasattr(b, 'is_adjacent'): if not b.is_adjacent(a): b, c = c, b elif not b.is_adjacent(c): a, b = b, a sweep_abc = [common_gates.CNOT(a, b), common_gates.CNOT(b, c)] phase_matrix_inverse = .25 * np.array( [[-1, -1, -1, 1, 1, 1, 1], [-1, 1, 1, -1, -1, 1, 1], [1, -1, 1, -1, 1, -1, 1], [-1, 1, 1, 1, 1, -1, -1], [1, 1, -1, 1, -1, -1, 1], [1, -1, 1, 1, -1, 1, -1], [1, 1, -1, -1, 1, 1, -1]]) shifted_angles_tail = [ angle - self._diag_angles_radians[0] for angle in self._diag_angles_radians[1:] ] phase_solutions = phase_matrix_inverse.dot(shifted_angles_tail) p_gates = [ pauli_gates.Z**(solution / np.pi) for solution in phase_solutions ] return [ p_gates[0](a), p_gates[1](b), p_gates[2](c), sweep_abc, p_gates[3](b), p_gates[4](c), sweep_abc, p_gates[5](c), sweep_abc, p_gates[6](c), sweep_abc, ]
def _decompose_(self, qubits): a, b = qubits yield common_gates.CNOT(a, b) yield common_gates.H(a) yield common_gates.CNOT(b, a) yield common_gates.S(a)**self._exponent yield common_gates.CNOT(b, a) yield common_gates.S(a)**-self._exponent yield common_gates.H(a) yield common_gates.CNOT(a, b)
def _decompose_for_basis( self, index: int, bit_flip: int, theta: float, qubits: Sequence['cirq.Qid'] ) -> Iterator[Union['cirq.ZPowGate', 'cirq.CXPowGate']]: if index == 0: return [] largest_digit = self._num_qubits_() - (len(bin(index)) - 2) yield common_gates.rz(2 * theta)(qubits[largest_digit]) _flip_bit = self._num_qubits_() - bit_flip - 1 if _flip_bit < largest_digit: yield common_gates.CNOT(qubits[largest_digit], qubits[_flip_bit]) elif _flip_bit > largest_digit: yield common_gates.CNOT(qubits[_flip_bit], qubits[largest_digit])
def _decompose_(self, qubits): a, b = qubits yield common_gates.CNOT(a, b) yield common_gates.H(a) yield common_gates.CNOT(b, a) yield common_gates.ZPowGate(exponent=self._exponent / 2, global_shift=self.global_shift).on(a) yield common_gates.CNOT(b, a) yield common_gates.ZPowGate(exponent=-self._exponent / 2, global_shift=-self.global_shift).on(a) yield common_gates.H(a) yield common_gates.CNOT(a, b)
def default_decompose(self, qubits): c, t1, t2 = qubits # Hacky magic: cross the non-adjacent edge. need_hop = hasattr(t1, 'is_adjacent') and not t1.is_adjacent(t2) cnot = common_gates.CNOT(t2, t1) if not need_hop else [ common_gates.CNOT(t2, c), common_gates.CNOT(c, t1), common_gates.CNOT(t2, c), common_gates.CNOT(c, t1), ] yield cnot yield TOFFOLI(c, t1, t2) yield cnot
def xor_nonlocal_decompose( qubits: Iterable[raw_types.Qid], onto_qubit: 'cirq.Qid') -> Iterable[raw_types.Operation]: """Decomposition ignores connectivity.""" for qubit in qubits: if qubit != onto_qubit: yield common_gates.CNOT(qubit, onto_qubit)
def _decompose_(self, qubits): """An adjacency-respecting decomposition. 0: ───p───@──────────────@───────@──────────@────────── │ │ │ │ 1: ───p───X───@───p^-1───X───@───X──────@───X──────@─── │ │ │ │ 2: ───p───────X───p──────────X───p^-1───X───p^-1───X─── where p = T**self._exponent """ a, b, c = qubits # Hacky magic: avoid the non-adjacent edge. if hasattr(b, 'is_adjacent'): if not b.is_adjacent(a): b, c = c, b elif not b.is_adjacent(c): a, b = b, a p = common_gates.T**self._exponent sweep_abc = [common_gates.CNOT(a, b), common_gates.CNOT(b, c)] global_phase = 1j ** (2 * self.global_shift * self._exponent) global_phase = ( complex(global_phase) if protocols.is_parameterized(global_phase) and global_phase.is_complex else global_phase ) global_phase_operation = ( [global_phase_op.global_phase_operation(global_phase)] if protocols.is_parameterized(global_phase) or abs(global_phase - 1.0) > 0 else [] ) return global_phase_operation + [ p(a), p(b), p(c), sweep_abc, p(b) ** -1, p(c), sweep_abc, p(c) ** -1, sweep_abc, p(c) ** -1, sweep_abc, ]
def _decompose_(self, qubits): """An adjacency-respecting decomposition. 0: ───p───@──────────────@───────@──────────@────────── │ │ │ │ 1: ───p───X───@───p^-1───X───@───X──────@───X──────@─── │ │ │ │ 2: ───p───────X───p──────────X───p^-1───X───p^-1───X─── where p = T**self._exponent """ if protocols.is_parameterized(self): return NotImplemented a, b, c = qubits # Hacky magic: avoid the non-adjacent edge. if hasattr(b, 'is_adjacent'): if not b.is_adjacent(a): b, c = c, b elif not b.is_adjacent(c): a, b = b, a p = common_gates.T**self._exponent sweep_abc = [common_gates.CNOT(a, b), common_gates.CNOT(b, c)] return [ p(a), p(b), p(c), sweep_abc, p(b)**-1, p(c), sweep_abc, p(c)**-1, sweep_abc, p(c)**-1, sweep_abc, ]
def assert_act_on_clifford_tableau_effect_matches_unitary(val: Any) -> None: """Checks that act_on with CliffordTableau generates stabilizers that stabilize the final state vector. Does not work with Operations or Gates expecting non-qubit Qids.""" # pylint: disable=unused-variable __tracebackhide__ = True # pylint: enable=unused-variable num_qubits_val = protocols.num_qubits(val) if not protocols.has_unitary(val) or \ protocols.qid_shape(val) != (2,) * num_qubits_val: return None qubits = LineQubit.range(protocols.num_qubits(val) * 2) qubit_map = {qubit: i for i, qubit in enumerate(qubits)} circuit = Circuit() for i in range(num_qubits_val): circuit.append([ common_gates.H(qubits[i]), common_gates.CNOT(qubits[i], qubits[-i - 1]) ]) if hasattr(val, "on"): circuit.append(val.on(*qubits[:num_qubits_val])) else: circuit.append(val.with_qubits(*qubits[:num_qubits_val])) tableau = _final_clifford_tableau(circuit, qubit_map) if tableau is None: return None state_vector = np.reshape(final_state_vector(circuit, qubit_order=qubits), protocols.qid_shape(qubits)) assert all( state_vector_has_stabilizer(state_vector, stab) for stab in tableau.stabilizers()), ( "act_on clifford tableau is not consistent with " "final_state_vector simulation.\n\nval: {!r}".format(val))
def _decompose_inside_control(self, target1: raw_types.QubitId, control: raw_types.QubitId, target2: raw_types.QubitId ) -> op_tree.OP_TREE: """A decomposition assuming the control separates the targets. target1: ─@─X───────T──────@────────@─────────X───@─────X^-0.5─ │ │ │ │ │ │ control: ─X─@─X─────@─T^-1─X─@─T────X─@─X^0.5─@─@─X─@────────── │ │ │ │ │ │ target2: ─────@─H─T─X─T──────X─T^-1───X─T^-1────X───X─H─S^-1─── """ a, b, c = target1, control, target2 yield common_gates.CNOT(a, b) yield common_gates.CNOT(b, a) yield common_gates.CNOT(c, b) yield common_gates.H(c) yield common_gates.T(c) yield common_gates.CNOT(b, c) yield common_gates.T(a) yield common_gates.T(b)**-1 yield common_gates.T(c) yield common_gates.CNOT(a, b) yield common_gates.CNOT(b, c) yield common_gates.T(b) yield common_gates.T(c)**-1 yield common_gates.CNOT(a, b) yield common_gates.CNOT(b, c) yield common_gates.X(b)**0.5 yield common_gates.T(c)**-1 yield common_gates.CNOT(b, a) yield common_gates.CNOT(b, c) yield common_gates.CNOT(a, b) yield common_gates.CNOT(b, c) yield common_gates.H(c) yield common_gates.S(c)**-1 yield common_gates.X(a)**-0.5
def _decompose_(self, qubits): """See base class.""" a, b = qubits yield common_gates.CNOT(a, b) yield common_gates.CNOT(b, a)**self._exponent yield common_gates.CNOT(a, b)
def _decompose_inside_control( self, target1: 'cirq.Qid', control: 'cirq.Qid', target2: 'cirq.Qid' ) -> 'cirq.OP_TREE': """A decomposition assuming the control separates the targets. target1: ─@─X───────T──────@────────@─────────X───@─────X^-0.5─ │ │ │ │ │ │ control: ─X─@─X─────@─T^-1─X─@─T────X─@─X^0.5─@─@─X─@────────── │ │ │ │ │ │ target2: ─────@─H─T─X─T──────X─T^-1───X─T^-1────X───X─H─S^-1─── """ a, b, c = target1, control, target2 yield common_gates.CNOT(a, b) yield common_gates.CNOT(b, a) yield common_gates.CNOT(c, b) yield common_gates.H(c) yield common_gates.T(c) yield common_gates.CNOT(b, c) yield common_gates.T(a) yield common_gates.T(b) ** -1 yield common_gates.T(c) yield common_gates.CNOT(a, b) yield common_gates.CNOT(b, c) yield common_gates.T(b) yield common_gates.T(c) ** -1 yield common_gates.CNOT(a, b) yield common_gates.CNOT(b, c) yield pauli_gates.X(b) ** 0.5 yield common_gates.T(c) ** -1 yield common_gates.CNOT(b, a) yield common_gates.CNOT(b, c) yield common_gates.CNOT(a, b) yield common_gates.CNOT(b, c) yield common_gates.H(c) yield common_gates.S(c) ** -1 yield pauli_gates.X(a) ** -0.5
def assert_all_implemented_act_on_effects_match_unitary( val: Any, assert_tableau_implemented: bool = False, assert_ch_form_implemented: bool = False) -> None: """Uses val's effect on final_state_vector to check act_on(val)'s behavior. Checks that act_on with CliffordTableau or StabilizerStateCHForm behaves consistently with act_on through final state vector. Does not work with Operations or Gates expecting non-qubit Qids. If either of the assert_*_implmented args is true, fails if the corresponding method is not implemented for the test circuit. Args: val: A gate or operation that may be an input to protocols.act_on. assert_tableau_implemented: asserts that protocols.act_on() works with val and ActOnCliffordTableauArgs inputs. assert_ch_form_implemented: asserts that protocols.act_on() works with val and ActOnStabilizerStateChFormArgs inputs. """ # pylint: disable=unused-variable __tracebackhide__ = True # pylint: enable=unused-variable num_qubits_val = protocols.num_qubits(val) if (protocols.is_parameterized(val) or not protocols.has_unitary(val) or protocols.qid_shape(val) != (2, ) * num_qubits_val): if assert_tableau_implemented or assert_ch_form_implemented: assert False, ("Could not assert if any act_on methods were " "implemented. Operating on qudits or with a " "non-unitary or parameterized operation is " "unsupported.\n\nval: {!r}".format(val)) return None qubits = LineQubit.range(protocols.num_qubits(val) * 2) qubit_map = {qubit: i for i, qubit in enumerate(qubits)} circuit = Circuit() for i in range(num_qubits_val): circuit.append([ common_gates.H(qubits[i]), common_gates.CNOT(qubits[i], qubits[-i - 1]) ]) if hasattr(val, "on"): circuit.append(val.on(*qubits[:num_qubits_val])) else: circuit.append(val.with_qubits(*qubits[:num_qubits_val])) state_vector = np.reshape(final_state_vector(circuit, qubit_order=qubits), protocols.qid_shape(qubits)) tableau = _final_clifford_tableau(circuit, qubit_map) if tableau is None: assert ( not assert_tableau_implemented ), "Failed to generate final tableau for the test circuit.\n\nval: {!r}".format( val) else: assert all( state_vector_has_stabilizer(state_vector, stab) for stab in tableau.stabilizers()), ( "act_on clifford tableau is not consistent with " "final_state_vector simulation.\n\nval: {!r}".format(val)) stabilizer_ch_form = _final_stabilizer_state_ch_form(circuit, qubit_map) if stabilizer_ch_form is None: assert not assert_ch_form_implemented, ("Failed to generate final " "stabilizer state CH form " "for the test circuit." "\n\nval: {!r}".format(val)) else: np.testing.assert_allclose( np.reshape(stabilizer_ch_form.state_vector(), protocols.qid_shape(qubits)), state_vector, atol=1e-07, err_msg= f"stabilizer_ch_form.state_vector disagrees with state_vector for {val!r}", verbose=True, )