def from_single_map( pauli_map_to: Optional[Dict[Pauli, Tuple[Pauli, bool]]] = None, *, x_to: Optional[Tuple[Pauli, bool]] = None, y_to: Optional[Tuple[Pauli, bool]] = None, z_to: Optional[Tuple[Pauli, bool]] = None) -> 'SingleQubitCliffordGate': """Returns a SingleQubitCliffordGate for the specified transform with a 90 or 180 degree rotation. The arguments are exclusive, only one may be specified. Args: pauli_map_to: A dictionary with a single key value pair describing the transform. x_to: The transform from cirq.X y_to: The transform from cirq.Y z_to: The transform from cirq.Z """ rotation_map = SingleQubitCliffordGate._validate_map_input( 1, pauli_map_to, x_to=x_to, y_to=y_to, z_to=z_to) (trans_from, (trans_to, flip)), = tuple(rotation_map.items()) if trans_from == trans_to: trans_from2 = Pauli.by_relative_index(trans_to, 1) # 1 or 2 work trans_to2 = Pauli.by_relative_index(trans_from, 1) flip2 = False else: trans_from2 = trans_to trans_to2 = trans_from flip2 = not flip rotation_map[trans_from2] = PauliTransform(trans_to2, flip2) return SingleQubitCliffordGate.from_double_map( cast(Dict[Pauli, Tuple[Pauli, bool]], rotation_map))
def decompose_rotation(self) -> Sequence[Tuple[Pauli, int]]: """Decomposes this clifford into a series of pauli rotations. Each rotation is given as a tuple of (axis, quarter_turns), where axis is a Pauli giving the axis to rotate about. The result will be a sequence of zero, one, or two rotations. Note that the combined unitary effect of these rotations may differ from cirq.unitary(self) by a global phase. """ x_rot = self.pauli_tuple(pauli_gates.X) y_rot = self.pauli_tuple(pauli_gates.Y) z_rot = self.pauli_tuple(pauli_gates.Z) whole_arr = ( x_rot[0] == pauli_gates.X, y_rot[0] == pauli_gates.Y, z_rot[0] == pauli_gates.Z, ) num_whole = sum(whole_arr) flip_arr = (x_rot[1], y_rot[1], z_rot[1]) num_flip = sum(flip_arr) if num_whole == 3: if num_flip == 0: # Gate is identity return [] # 180 rotation about some axis pauli = Pauli.by_index(flip_arr.index(False)) return [(pauli, 2)] if num_whole == 1: index = whole_arr.index(True) pauli = Pauli.by_index(index) next_pauli = Pauli.by_index(index + 1) flip = flip_arr[index] output = [] if flip: # 180 degree rotation output.append((next_pauli, 2)) # 90 degree rotation about some axis if self.pauli_tuple(next_pauli)[1]: # Negative 90 degree rotation output.append((pauli, -1)) else: # Positive 90 degree rotation output.append((pauli, 1)) return output elif num_whole == 0: # Gate is a 120 degree rotation if x_rot[0] == pauli_gates.Y: return [ (pauli_gates.X, -1 if y_rot[1] else 1), (pauli_gates.Z, -1 if x_rot[1] else 1), ] return [(pauli_gates.Z, 1 if y_rot[1] else -1), (pauli_gates.X, 1 if z_rot[1] else -1)] # coverage: ignore assert ( False ), 'Impossible condition where this gate only rotates one Pauli to a different Pauli.'
def decompose_rotation(self) -> Sequence[Tuple[Pauli, int]]: """Returns ((first_rotation_axis, first_rotation_quarter_turns), ...) This is a sequence of zero, one, or two rotations.""" x_rot = self.transform(pauli_gates.X) y_rot = self.transform(pauli_gates.Y) z_rot = self.transform(pauli_gates.Z) whole_arr = ( x_rot.to == pauli_gates.X, y_rot.to == pauli_gates.Y, z_rot.to == pauli_gates.Z, ) num_whole = sum(whole_arr) flip_arr = (x_rot.flip, y_rot.flip, z_rot.flip) num_flip = sum(flip_arr) if num_whole == 3: if num_flip == 0: # Gate is identity return [] # 180 rotation about some axis pauli = Pauli.by_index(flip_arr.index(False)) return [(pauli, 2)] if num_whole == 1: index = whole_arr.index(True) pauli = Pauli.by_index(index) next_pauli = Pauli.by_index(index + 1) flip = flip_arr[index] output = [] if flip: # 180 degree rotation output.append((next_pauli, 2)) # 90 degree rotation about some axis if self.transform(next_pauli).flip: # Negative 90 degree rotation output.append((pauli, -1)) else: # Positive 90 degree rotation output.append((pauli, 1)) return output elif num_whole == 0: # Gate is a 120 degree rotation if x_rot.to == pauli_gates.Y: return [ (pauli_gates.X, -1 if y_rot.flip else 1), (pauli_gates.Z, -1 if x_rot.flip else 1), ] return [ (pauli_gates.Z, 1 if y_rot.flip else -1), (pauli_gates.X, 1 if z_rot.flip else -1), ] # coverage: ignore assert ( False ), 'Impossible condition where this gate only rotates one Pauli to a different Pauli.'
def from_pauli(pauli: Pauli, sqrt: bool = False) -> 'SingleQubitCliffordGate': prev_pauli = Pauli.by_relative_index(pauli, -1) next_pauli = Pauli.by_relative_index(pauli, 1) if sqrt: rotation_map = { prev_pauli: (next_pauli, True), pauli: (pauli, False), next_pauli: (prev_pauli, False), } else: rotation_map = { prev_pauli: (prev_pauli, True), pauli: (pauli, False), next_pauli: (next_pauli, True), } return SingleQubitCliffordGate.from_clifford_tableau(_to_clifford_tableau(rotation_map))
def from_pauli(pauli: Pauli, sqrt: bool = False) -> 'SingleQubitCliffordGate': prev_pauli = Pauli.by_relative_index(pauli, -1) next_pauli = Pauli.by_relative_index(pauli, 1) if sqrt: rotation_map = {prev_pauli: PauliTransform(next_pauli, True), pauli: PauliTransform(pauli, False), next_pauli: PauliTransform(prev_pauli, False)} else: rotation_map = {prev_pauli: PauliTransform(prev_pauli, True), pauli: PauliTransform(pauli, False), next_pauli: PauliTransform(next_pauli, True)} inverse_map = {to: PauliTransform(frm, flip) for frm, (to, flip) in rotation_map.items()} return SingleQubitCliffordGate(_rotation_map=rotation_map, _inverse_map=inverse_map)