Exemplo n.º 1
0
    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))
Exemplo n.º 2
0
    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.'
Exemplo n.º 3
0
    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.'
Exemplo n.º 4
0
 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))
Exemplo n.º 5
0
 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)