text: # Copyright 2018 The Cirq Developers
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     https://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  """Quantum gates that are commonly used in the literature.
  
  This module creates Gate instances for the following gates:
      X,Y,Z: Pauli gates.
      H,S: Clifford gates.
      T: A non-Clifford gate.
      CZ: Controlled phase gate.
      CNOT: Controlled not gate.
  
  Each of these are implemented as EigenGates, which means that they can be
  raised to a power (i.e. cirq.H**0.5). See the definition in EigenGate.
  """
  from typing import Any, cast, Collection, Optional, Sequence, Tuple, Union
  
  import numpy as np
  import sympy
  
  import cirq
  from cirq import protocols, value
  from cirq._compat import deprecated, proper_repr
  from cirq._doc import document
  from cirq.ops import controlled_gate, gate_features, eigen_gate, raw_types
  
  from cirq.type_workarounds import NotImplementedType
  
  from cirq.ops.swap_gates import ISWAP, SWAP, ISwapPowGate, SwapPowGate
  from cirq.ops.measurement_gate import MeasurementGate
  
  assert all([ISWAP, SWAP, ISwapPowGate, SwapPowGate, MeasurementGate]), """
  Included for compatibility. Please continue to use top-level cirq.{thing}
  imports.
  """
  
  
  @value.value_equality
  class XPowGate(eigen_gate.EigenGate,
                 gate_features.SingleQubitGate):
      """A gate that rotates around the X axis of the Bloch sphere.
  
      The unitary matrix of ``XPowGate(exponent=t)`` is:
  
          [[g·c, -i·g·s],
           [-i·g·s, g·c]]
  
      where:
  
          c = cos(π·t/2)
          s = sin(π·t/2)
          g = exp(i·π·t/2).
  
      Note in particular that this gate has a global phase factor of
      e^{i·π·t/2} vs the traditionally defined rotation matrices
      about the Pauli X axis. See `cirq.rx` for rotations without the global
      phase. The global phase factor can be adjusted by using the `global_shift`
      parameter when initializing.
  
      `cirq.X`, the Pauli X gate, is an instance of this gate at exponent=1.
      """
  
      def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'
                         ) -> Optional[np.ndarray]:
          if self._exponent != 1:
              return NotImplemented
          zero = args.subspace_index(0)
          one = args.subspace_index(1)
          args.available_buffer[zero] = args.target_tensor[one]
          args.available_buffer[one] = args.target_tensor[zero]
          p = 1j**(2 * self._exponent * self._global_shift)
          if p != 1:
              args.available_buffer *= p
          return args.available_buffer
  
      def in_su2(self) -> 'XPowGate':
          """Returns an equal-up-global-phase gate from the group SU2."""
          return XPowGate(exponent=self._exponent, global_shift=-0.5)
  
      def with_canonical_global_phase(self) -> 'XPowGate':
          """Returns an equal-up-global-phase standardized form of the gate."""
          return XPowGate(exponent=self._exponent)
  
      def _eigen_components(self):
          return [
              (0, np.array([[0.5, 0.5], [0.5, 0.5]])),
              (1, np.array([[0.5, -0.5], [-0.5, 0.5]])),
          ]
  
      def _decompose_into_clifford_with_qubits_(self, qubits):
          from cirq.ops.clifford_gate import SingleQubitCliffordGate
          if self.exponent % 2 == 0:
              return []
          if self.exponent % 2 == 0.5:
              return SingleQubitCliffordGate.X_sqrt.on(*qubits)
          if self.exponent % 2 == 1:
              return SingleQubitCliffordGate.X.on(*qubits)
          if self.exponent % 2 == 1.5:
              return SingleQubitCliffordGate.X_nsqrt.on(*qubits)
          return NotImplemented
  
      def _trace_distance_bound_(self) -> Optional[float]:
          if self._is_parameterized_():
              return None
          return abs(np.sin(self._exponent * 0.5 * np.pi))
  
      def _pauli_expansion_(self) -> value.LinearDict[str]:
          if protocols.is_parameterized(self):
              return NotImplemented
          phase = 1j**(2 * self._exponent * (self._global_shift + 0.5))
          angle = np.pi * self._exponent / 2
          return value.LinearDict({
              'I': phase * np.cos(angle),
              'X': -1j * phase * np.sin(angle),
          })
  
      def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs'
                                ) -> Union[str, 'protocols.CircuitDiagramInfo']:
          if self._global_shift == -0.5:
              return _rads_func_symbol(
                  'Rx',
                  args,
                  self._diagram_exponent(args, ignore_global_phase=False))
  
          return protocols.CircuitDiagramInfo(
              wire_symbols=('X',),
              exponent=self._diagram_exponent(args))
  
      def _qasm_(self, args: 'cirq.QasmArgs',
                 qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
          args.validate_version('2.0')
          if self._exponent == 1:
              return args.format('x {0};\n', qubits[0])
  
          return args.format('rx({0:half_turns}) {1};\n', self._exponent,
                             qubits[0])
  
      @property
      def phase_exponent(self):
          return 0.0
  
      def _phase_by_(self, phase_turns, qubit_index):
          """See `cirq.SupportsPhase`."""
          return cirq.ops.phased_x_gate.PhasedXPowGate(
              exponent=self._exponent,
              phase_exponent=phase_turns * 2)
  
      def __str__(self) -> str:
          if self._global_shift == -0.5:
              if self._exponent == 1:
                  return 'Rx(π)'
              return 'Rx({}π)'.format(self._exponent)
          if self._global_shift == 0:
              if self._exponent == 1:
                  return 'X'
              return 'X**{}'.format(self._exponent)
          return ('XPowGate(exponent={}, '
                  'global_shift={!r})').format(self._exponent, self._global_shift)
  
      def __repr__(self) -> str:
          if self._global_shift == -0.5:
              if protocols.is_parameterized(self._exponent):
                  return 'cirq.rx({})'.format(
                      proper_repr(sympy.pi * self._exponent))
  
              return 'cirq.rx(np.pi*{})'.format(proper_repr(self._exponent))
          if self._global_shift == 0:
              if self._exponent == 1:
                  return 'cirq.X'
              return '(cirq.X**{})'.format(proper_repr(self._exponent))
          return (
              'cirq.XPowGate(exponent={}, '
              'global_shift={!r})'
          ).format(proper_repr(self._exponent), self._global_shift)
  
  
  @value.value_equality
  class YPowGate(eigen_gate.EigenGate,
                 gate_features.SingleQubitGate):
      """A gate that rotates around the Y axis of the Bloch sphere.
  
      The unitary matrix of ``YPowGate(exponent=t)`` is:
  
          [[g·c, -g·s],
           [g·s, g·c]]
  
      where:
  
          c = cos(π·t/2)
          s = sin(π·t/2)
          g = exp(i·π·t/2).
  
      Note in particular that this gate has a global phase factor of
      e^{i·π·t/2} vs the traditionally defined rotation matrices
      about the Pauli Y axis. See `cirq.ry` for rotations without the global
      phase. The global phase factor can be adjusted by using the `global_shift`
      parameter when initializing.
  
      `cirq.Y`, the Pauli Y gate, is an instance of this gate at exponent=1.
      """
  
      def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'
                         ) -> Optional[np.ndarray]:
          if self._exponent != 1:
              return NotImplemented
          zero = args.subspace_index(0)
          one = args.subspace_index(1)
          args.available_buffer[zero] = -1j * args.target_tensor[one]
          args.available_buffer[one] = 1j * args.target_tensor[zero]
          p = 1j**(2 * self._exponent * self._global_shift)
          if p != 1:
              args.available_buffer *= p
          return args.available_buffer
  
      def in_su2(self) -> 'YPowGate':
          """Returns an equal-up-global-phase gate from the group SU2."""
          return YPowGate(exponent=self._exponent, global_shift=-0.5)
  
      def with_canonical_global_phase(self) -> 'YPowGate':
          """Returns an equal-up-global-phase standardized form of the gate."""
          return YPowGate(exponent=self._exponent)
  
      def _decompose_into_clifford_with_qubits_(self, qubits):
          from cirq.ops.clifford_gate import SingleQubitCliffordGate
          if self.exponent % 2 == 0:
              return []
          if self.exponent % 2 == 0.5:
              return SingleQubitCliffordGate.Y_sqrt.on(*qubits)
          if self.exponent % 2 == 1:
              return SingleQubitCliffordGate.Y.on(*qubits)
          if self.exponent % 2 == 1.5:
              return SingleQubitCliffordGate.Y_nsqrt.on(*qubits)
          return NotImplemented
  
      def _eigen_components(self):
          return [
              (0, np.array([[0.5, -0.5j], [0.5j, 0.5]])),
              (1, np.array([[0.5, 0.5j], [-0.5j, 0.5]])),
          ]
  
      def _trace_distance_bound_(self) -> Optional[float]:
          if self._is_parameterized_():
              return None
          return abs(np.sin(self._exponent * 0.5 * np.pi))
  
      def _pauli_expansion_(self) -> value.LinearDict[str]:
          if protocols.is_parameterized(self):
              return NotImplemented
          phase = 1j**(2 * self._exponent * (self._global_shift + 0.5))
          angle = np.pi * self._exponent / 2
          return value.LinearDict({
              'I': phase * np.cos(angle),
              'Y': -1j * phase * np.sin(angle),
          })
  
      def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs'
                                ) -> Union[str, 'protocols.CircuitDiagramInfo']:
          if self._global_shift == -0.5:
              return _rads_func_symbol(
                  'Ry',
                  args,
                  self._diagram_exponent(args, ignore_global_phase=False))
  
          return protocols.CircuitDiagramInfo(
              wire_symbols=('Y',),
              exponent=self._diagram_exponent(args))
  
      def _qasm_(self, args: 'cirq.QasmArgs',
                 qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
          args.validate_version('2.0')
          if self._exponent == 1:
              return args.format('y {0};\n', qubits[0])
  
          return args.format('ry({0:half_turns}) {1};\n', self._exponent,
                             qubits[0])
  
      @property
      def phase_exponent(self):
          return 0.5
  
      def _phase_by_(self, phase_turns, qubit_index):
          """See `cirq.SupportsPhase`."""
          return cirq.ops.phased_x_gate.PhasedXPowGate(
              exponent=self._exponent,
              phase_exponent=0.5 + phase_turns * 2)
  
      def __str__(self) -> str:
          if self._global_shift == -0.5:
              if self._exponent == 1:
                  return 'Ry(π)'
              return 'Ry({}π)'.format(self._exponent)
          if self._global_shift == 0:
              if self._exponent == 1:
                  return 'Y'
              return 'Y**{}'.format(self._exponent)
          return ('YPowGate(exponent={}, '
                  'global_shift={!r})').format(self._exponent, self._global_shift)
  
      def __repr__(self) -> str:
          if self._global_shift == -0.5:
              if protocols.is_parameterized(self._exponent):
                  return 'cirq.ry({})'.format(
                      proper_repr(sympy.pi * self._exponent))
  
              return 'cirq.ry(np.pi*{})'.format(proper_repr(self._exponent))
          if self._global_shift == 0:
              if self._exponent == 1:
                  return 'cirq.Y'
              return '(cirq.Y**{})'.format(proper_repr(self._exponent))
          return (
              'cirq.YPowGate(exponent={}, '
              'global_shift={!r})'
          ).format(proper_repr(self._exponent), self._global_shift)
  
  
  @value.value_equality
  class ZPowGate(eigen_gate.EigenGate,
                 gate_features.SingleQubitGate):
      """A gate that rotates around the Z axis of the Bloch sphere.
  
      The unitary matrix of ``ZPowGate(exponent=t)`` is:
  
          [[1, 0],
           [0, g]]
  
      where:
  
          g = exp(i·π·t).
  
      Note in particular that this gate has a global phase factor of
      e^{i·π·t/2} vs the traditionally defined rotation matrices
      about the Pauli Z axis. See `cirq.rz` for rotations without the global
      phase. The global phase factor can be adjusted by using the `global_shift`
      parameter when initializing.
  
      `cirq.Z`, the Pauli Z gate, is an instance of this gate at exponent=1.
      """
  
      def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'
                         ) -> Optional[np.ndarray]:
          if protocols.is_parameterized(self):
              return None
  
          one = args.subspace_index(1)
          c = 1j**(self._exponent * 2)
          args.target_tensor[one] *= c
          p = 1j**(2 * self._exponent * self._global_shift)
          if p != 1:
              args.target_tensor *= p
          return args.target_tensor
  
      def _decompose_into_clifford_with_qubits_(self, qubits):
          from cirq.ops.clifford_gate import SingleQubitCliffordGate
          if self.exponent % 2 == 0:
              return []
          if self.exponent % 2 == 0.5:
              return SingleQubitCliffordGate.Z_sqrt.on(*qubits)
          if self.exponent % 2 == 1:
              return SingleQubitCliffordGate.Z.on(*qubits)
          if self.exponent % 2 == 1.5:
              return SingleQubitCliffordGate.Z_nsqrt.on(*qubits)
          return NotImplemented
  
      def in_su2(self) -> 'ZPowGate':
          """Returns an equal-up-global-phase gate from the group SU2."""
          return ZPowGate(exponent=self._exponent, global_shift=-0.5)
  
      def with_canonical_global_phase(self) -> 'ZPowGate':
          """Returns an equal-up-global-phase standardized form of the gate."""
          return ZPowGate(exponent=self._exponent)
  
      def controlled(self,
                     num_controls: int = None,
                     control_values: Optional[Sequence[
                         Union[int, Collection[int]]]] = None,
                     control_qid_shape: Optional[Tuple[int, ...]] = None
                    ) -> raw_types.Gate:
          """
          Specialize controlled for ZPow to return corresponding controlled CZPow
          when the last control (which acts first semantically) is a default-type
          control qubit.
          """
          result = super().controlled(num_controls, control_values,
                                      control_qid_shape)
          if (isinstance(result, controlled_gate.ControlledGate) and
                  result.control_values[-1] == (1,) and
                  result.control_qid_shape[-1] == 2):
              return cirq.CZPowGate(exponent=self._exponent,
                                    global_shift=self._global_shift).controlled(
                                        result.num_controls() - 1,
                                        result.control_values[:-1],
                                        result.control_qid_shape[:-1])
          return result
  
      def _eigen_components(self):
          return [
              (0, np.diag([1, 0])),
              (1, np.diag([0, 1])),
          ]
  
      def _trace_distance_bound_(self) -> Optional[float]:
          if self._is_parameterized_():
              return None
          return abs(np.sin(self._exponent * 0.5 * np.pi))
  
      def _pauli_expansion_(self) -> value.LinearDict[str]:
          if protocols.is_parameterized(self):
              return NotImplemented
          phase = 1j**(2 * self._exponent * (self._global_shift + 0.5))
          angle = np.pi * self._exponent / 2
          return value.LinearDict({
              'I': phase * np.cos(angle),
              'Z': -1j * phase * np.sin(angle),
          })
  
      def _phase_by_(self, phase_turns: float, qubit_index: int):
          return self
  
      def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs'
                                ) -> Union[str, 'protocols.CircuitDiagramInfo']:
          if self._global_shift == -0.5:
              return _rads_func_symbol(
                  'Rz',
                  args,
                  self._diagram_exponent(args, ignore_global_phase=False))
  
          e = self._diagram_exponent(args)
          if e in [-0.25, 0.25]:
              return protocols.CircuitDiagramInfo(
                  wire_symbols=('T',),
                  exponent=cast(float, e) * 4)
  
          if e in [-0.5, 0.5]:
              return protocols.CircuitDiagramInfo(
                  wire_symbols=('S',),
                  exponent=cast(float, e) * 2)
  
          return protocols.CircuitDiagramInfo(
              wire_symbols=('Z',),
              exponent=e)
  
      def _qasm_(self, args: 'cirq.QasmArgs',
                 qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
          args.validate_version('2.0')
          if self._exponent == 1:
              return args.format('z {0};\n', qubits[0])
  
          return args.format('rz({0:half_turns}) {1};\n', self._exponent,
                             qubits[0])
  
      def __str__(self) -> str:
          if self._global_shift == -0.5:
              if self._exponent == 1:
                  return 'Rz(π)'
              return 'Rz({}π)'.format(self._exponent)
          if self._global_shift == 0:
              if self._exponent == 0.25:
                  return 'T'
              if self._exponent == -0.25:
                  return 'T**-1'
              if self._exponent == 0.5:
                  return 'S'
              if self._exponent == -0.5:
                  return 'S**-1'
              if self._exponent == 1:
                  return 'Z'
              return 'Z**{}'.format(self._exponent)
          return ('ZPowGate(exponent={}, '
                  'global_shift={!r})').format(self._exponent, self._global_shift)
  
      def __repr__(self) -> str:
          if self._global_shift == -0.5:
              if protocols.is_parameterized(self._exponent):
                  return 'cirq.rz({})'.format(
                      proper_repr(sympy.pi * self._exponent))
  
              return 'cirq.rz(np.pi*{!r})'.format(self._exponent)
          if self._global_shift == 0:
              if self._exponent == 0.25:
                  return 'cirq.T'
              if self._exponent == -0.25:
                  return '(cirq.T**-1)'
              if self._exponent == 0.5:
                  return 'cirq.S'
              if self._exponent == -0.5:
                  return '(cirq.S**-1)'
              if self._exponent == 1:
                  return 'cirq.Z'
              return '(cirq.Z**{})'.format(proper_repr(self._exponent))
          return (
              'cirq.ZPowGate(exponent={}, '
              'global_shift={!r})'
          ).format(proper_repr(self._exponent), self._global_shift)
  
  
  class HPowGate(eigen_gate.EigenGate, gate_features.SingleQubitGate):
      """A Gate that performs a rotation around the X+Z axis of the Bloch sphere.
  
      The unitary matrix of ``HPowGate(exponent=t)`` is:
  
          [[g·(c-i·s/sqrt(2)), -i·g·s/sqrt(2)],
          [-i·g·s/sqrt(2)], g·(c+i·s/sqrt(2))]]
  
      where
  
          c = cos(π·t/2)
          s = sin(π·t/2)
          g = exp(i·π·t/2).
  
      Note in particular that for `t=1`, this gives the Hadamard matrix.
  
      `cirq.H`, the Hadamard gate, is an instance of this gate at `exponent=1`.
      """
  
      def _eigen_components(self):
          s = np.sqrt(2)
  
          component0 = np.array([
              [3 + 2 * s, 1 + s],
              [1 + s, 1]
          ]) / (4 + 2 * s)
  
          component1 = np.array([
              [3 - 2 * s, 1 - s],
              [1 - s, 1]
          ]) / (4 - 2 * s)
  
          return [(0, component0), (1, component1)]
  
      def _trace_distance_bound_(self) -> Optional[float]:
          if self._is_parameterized_():
              return None
          return abs(np.sin(self._exponent * 0.5 * np.pi))
  
      def _pauli_expansion_(self) -> value.LinearDict[str]:
          if protocols.is_parameterized(self):
              return NotImplemented
          phase = 1j**(2 * self._exponent * (self._global_shift + 0.5))
          angle = np.pi * self._exponent / 2
          return value.LinearDict({
              'I': phase * np.cos(angle),
              'X': -1j * phase * np.sin(angle) / np.sqrt(2),
              'Z': -1j * phase * np.sin(angle) / np.sqrt(2),
          })
  
      def _decompose_into_clifford_with_qubits_(self, qubits):
          from cirq.ops.clifford_gate import SingleQubitCliffordGate
          if self.exponent % 2 == 1:
              return SingleQubitCliffordGate.H.on(*qubits)
          if self.exponent % 2 == 0:
              return []
          return NotImplemented
  
      def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'
                         ) -> Optional[np.ndarray]:
          if self._exponent != 1:
              return NotImplemented
  
          zero = args.subspace_index(0)
          one = args.subspace_index(1)
          args.target_tensor[one] -= args.target_tensor[zero]
          args.target_tensor[one] *= -0.5
          args.target_tensor[zero] -= args.target_tensor[one]
          p = 1j**(2 * self._exponent * self._global_shift)
          args.target_tensor *= np.sqrt(2) * p
          return args.target_tensor
  
      def _decompose_(self, qubits):
          q = qubits[0]
  
          if self._exponent == 1:
              yield cirq.Y(q)**0.5
              yield cirq.XPowGate(global_shift=-0.25).on(q)
              return
  
          yield YPowGate(exponent=0.25).on(q)
          yield XPowGate(exponent=self._exponent).on(q)
          yield YPowGate(exponent=-0.25).on(q)
  
      def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs'
                                ) -> 'cirq.CircuitDiagramInfo':
          return protocols.CircuitDiagramInfo(
              wire_symbols=('H',),
              exponent=self._diagram_exponent(args))
  
      def _qasm_(self, args: 'cirq.QasmArgs',
                 qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
          args.validate_version('2.0')
          if self._exponent == 1:
              return args.format('h {0};\n', qubits[0])
  
          return args.format(
              'ry({0:half_turns}) {3};\n'
              'rx({1:half_turns}) {3};\n'
              'ry({2:half_turns}) {3};\n', 0.25, self._exponent, -0.25, qubits[0])
  
      def __str__(self):
          if self._exponent == 1:
              return 'H'
          return 'H^{}'.format(self._exponent)
  
      def __repr__(self):
          if self._global_shift == 0:
              if self._exponent == 1:
                  return 'cirq.H'
              return '(cirq.H**{})'.format(proper_repr(self._exponent))
          return (
              'cirq.HPowGate(exponent={}, '
              'global_shift={!r})'
          ).format(proper_repr(self._exponent), self._global_shift)
  
  
  class CZPowGate(eigen_gate.EigenGate,
                  gate_features.TwoQubitGate,
                  gate_features.InterchangeableQubitsGate):
      """A gate that applies a phase to the |11⟩ state of two qubits.
  
      The unitary matrix of `CZPowGate(exponent=t)` is:
  
          [[1, 0, 0, 0],
           [0, 1, 0, 0],
           [0, 0, 1, 0],
           [0, 0, 0, g]]
  
      where:
  
          g = exp(i·π·t).
  
      `cirq.CZ`, the controlled Z gate, is an instance of this gate at
      `exponent=1`.
      """
  
      def _decompose_into_clifford_with_qubits_(self, qubits):
          from cirq.ops.pauli_interaction_gate import PauliInteractionGate
          if self.exponent % 2 == 1:
              return PauliInteractionGate.CZ.on(*qubits)
          if self.exponent % 2 == 0:
              return []
          return NotImplemented
  
      def _eigen_components(self):
          return [
              (0, np.diag([1, 1, 1, 0])),
              (1, np.diag([0, 0, 0, 1])),
          ]
  
      def _trace_distance_bound_(self) -> Optional[float]:
          if self._is_parameterized_():
              return None
          return abs(np.sin(self._exponent * 0.5 * np.pi))
  
      def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'
                         ) -> Union[np.ndarray, NotImplementedType]:
          if protocols.is_parameterized(self):
              return NotImplemented
  
          c = 1j**(2 * self._exponent)
          one_one = args.subspace_index(0b11)
          args.target_tensor[one_one] *= c
          p = 1j**(2 * self._exponent * self._global_shift)
          if p != 1:
              args.target_tensor *= p
          return args.target_tensor
  
      def _pauli_expansion_(self) -> value.LinearDict[str]:
          if protocols.is_parameterized(self):
              return NotImplemented
          global_phase = 1j**(2 * self._exponent * self._global_shift)
          z_phase = 1j**self._exponent
          c = -1j * z_phase * np.sin(np.pi * self._exponent / 2) / 2
          return value.LinearDict({
              'II': global_phase * (1 - c),
              'IZ': global_phase * c,
              'ZI': global_phase * c,
              'ZZ': global_phase * -c,
          })
  
      def _phase_by_(self, phase_turns, qubit_index):
          return self
  
      def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs'
                                ) -> 'cirq.CircuitDiagramInfo':
          return protocols.CircuitDiagramInfo(
                  wire_symbols=('@', '@'),
                  exponent=self._diagram_exponent(args))
  
      def _qasm_(self, args: 'cirq.QasmArgs',
                 qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
          if self._exponent != 1:
              return None  # Don't have an equivalent gate in QASM
          args.validate_version('2.0')
          return args.format('cz {0},{1};\n', qubits[0], qubits[1])
  
      def __str__(self) -> str:
          if self._exponent == 1:
              return 'CZ'
          return 'CZ**{!r}'.format(self._exponent)
  
      def __repr__(self) -> str:
          if self._global_shift == 0:
              if self._exponent == 1:
                  return 'cirq.CZ'
              return '(cirq.CZ**{})'.format(proper_repr(self._exponent))
          return (
              'cirq.CZPowGate(exponent={}, '
              'global_shift={!r})'
          ).format(proper_repr(self._exponent), self._global_shift)
  
  
  def _rads_func_symbol(func_name: str, args: 'protocols.CircuitDiagramInfoArgs',
                        half_turns: Any) -> str:
      if protocols.is_parameterized(half_turns):
          return '{}({})'.format(func_name, sympy.pi * half_turns)
      unit = 'π' if args.use_unicode_characters else 'pi'
      if half_turns == 1:
          return '{}({})'.format(func_name, unit)
      if half_turns == -1:
          return '{}(-{})'.format(func_name, unit)
      return '{}({}{})'.format(func_name, half_turns, unit)
  
  
  class CNotPowGate(eigen_gate.EigenGate, gate_features.TwoQubitGate):
      """A gate that applies a controlled power of an X gate.
  
      When applying CNOT (controlled-not) to qubits, you can either use
      positional arguments CNOT(q1, q2), where q2 is toggled when q1 is on,
      or named arguments CNOT(control=q1, target=q2).
      (Mixing the two is not permitted.)
  
      The unitary matrix of `CNotPowGate(exponent=t)` is:
  
          [[1, 0, 0, 0],
           [0, 1, 0, 0],
           [0, 0, g·c, -i·g·s],
           [0, 0, -i·g·s, g·c]]
  
      where:
  
          c = cos(π·t/2)
          s = sin(π·t/2)
          g = exp(i·π·t/2).
  
      `cirq.CNOT`, the controlled NOT gate, is an instance of this gate at
      `exponent=1`.
      """
  
      def _decompose_into_clifford_with_qubits_(self, qubits):
          from cirq.ops.pauli_interaction_gate import PauliInteractionGate
          if self.exponent % 2 == 1:
              return PauliInteractionGate.CNOT.on(*qubits)
          if self.exponent % 2 == 0:
              return []
          return NotImplemented
  
      def _decompose_(self, qubits):
          c, t = qubits
          yield YPowGate(exponent=-0.5).on(t)
          yield CZ(c, t)**self._exponent
          yield YPowGate(exponent=0.5).on(t)
  
      def _eigen_components(self):
          return [
              (0, np.array([[1, 0, 0, 0],
                            [0, 1, 0, 0],
                            [0, 0, 0.5, 0.5],
                            [0, 0, 0.5, 0.5]])),
              (1, np.array([[0, 0, 0, 0],
                            [0, 0, 0, 0],
                            [0, 0, 0.5, -0.5],
                            [0, 0, -0.5, 0.5]])),
          ]
  
      def _trace_distance_bound_(self) -> Optional[float]:
          if self._is_parameterized_():
              return None
          return abs(np.sin(self._exponent * 0.5 * np.pi))
  
      def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs'
                                ) -> 'cirq.CircuitDiagramInfo':
          return protocols.CircuitDiagramInfo(
              wire_symbols=('@', 'X'),
              exponent=self._diagram_exponent(args))
  
      def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'
                         ) -> Optional[np.ndarray]:
          if self._exponent != 1:
              return NotImplemented
  
          oo = args.subspace_index(0b11)
          zo = args.subspace_index(0b01)
          args.available_buffer[oo] = args.target_tensor[oo]
          args.target_tensor[oo] = args.target_tensor[zo]
          args.target_tensor[zo] = args.available_buffer[oo]
          p = 1j**(2 * self._exponent * self._global_shift)
          if p != 1:
              args.target_tensor *= p
          return args.target_tensor
  
      def _pauli_expansion_(self) -> value.LinearDict[str]:
          if protocols.is_parameterized(self):
              return NotImplemented
          global_phase = 1j**(2 * self._exponent * self._global_shift)
          cnot_phase = 1j**self._exponent
          c = -1j * cnot_phase * np.sin(np.pi * self._exponent / 2) / 2
          return value.LinearDict({
              'II': global_phase * (1 - c),
              'IX': global_phase * c,
              'ZI': global_phase * c,
              'ZX': global_phase * -c,
          })
  
      def _qasm_(self, args: 'cirq.QasmArgs',
                 qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
          if self._exponent != 1:
              return None  # Don't have an equivalent gate in QASM
          args.validate_version('2.0')
          return args.format('cx {0},{1};\n', qubits[0], qubits[1])
  
      def __str__(self) -> str:
          if self._exponent == 1:
              return 'CNOT'
          return 'CNOT**{!r}'.format(self._exponent)
  
      def __repr__(self):
          if self._global_shift == 0:
              if self._exponent == 1:
                  return 'cirq.CNOT'
              return '(cirq.CNOT**{})'.format(proper_repr(self._exponent))
          return (
              'cirq.CNotPowGate(exponent={}, '
              'global_shift={!r})'
          ).format(proper_repr(self._exponent), self._global_shift)
  
      def on(self, *args: 'cirq.Qid',
             **kwargs: 'cirq.Qid') -> raw_types.Operation:
          if not kwargs:
              return super().on(*args)
          if not args and set(kwargs.keys()) == {'control', 'target'}:
              return super().on(kwargs['control'], kwargs['target'])
          raise ValueError(
              "Expected two positional argument or else 'target' AND 'control' "
              "keyword arguments. But got args={!r}, kwargs={!r}.".format(
                  args, kwargs))
  
  
  def rx(rads: value.TParamVal) -> XPowGate:
      """Returns a gate with the matrix e^{-i X rads / 2}."""
      pi = sympy.pi if protocols.is_parameterized(rads) else np.pi
      return XPowGate(exponent=rads / pi, global_shift=-0.5)
  
  
  @deprecated(deadline='v0.8.0', fix='Use cirq.rx, instead.')
  def Rx(rads: value.TParamVal) -> XPowGate:
      """Returns a gate with the matrix e^{-i X rads / 2}."""
      return rx(rads)
  
  
  def ry(rads: value.TParamVal) -> YPowGate:
      """Returns a gate with the matrix e^{-i Y rads / 2}."""
      pi = sympy.pi if protocols.is_parameterized(rads) else np.pi
      return YPowGate(exponent=rads / pi, global_shift=-0.5)
  
  
  @deprecated(deadline='v0.8.0', fix='Use cirq.ry, instead.')
  def Ry(rads: value.TParamVal) -> YPowGate:
      """Returns a gate with the matrix e^{-i Y rads / 2}."""
      return ry(rads)
  
  
  def rz(rads: value.TParamVal) -> ZPowGate:
      """Returns a gate with the matrix e^{-i Z rads / 2}."""
      pi = sympy.pi if protocols.is_parameterized(rads) else np.pi
      return ZPowGate(exponent=rads / pi, global_shift=-0.5)
  
  
  @deprecated(deadline='v0.8.0', fix='Use cirq.rz, instead.')
  def Rz(rads: value.TParamVal) -> ZPowGate:
      """Returns a gate with the matrix e^{-i Z rads / 2}."""
      return rz(rads)
  
  
  H = HPowGate()
  document(
      H, """The Hadamard gate.
  
      The `exponent=1` instance of `cirq.HPowGate`.
  
      Matrix:
          [[s, s],
           [s, -s]]
          where s = sqrt(0.5).
      """)
  
  S = ZPowGate(exponent=0.5)
  document(
      S, """The Clifford S gate.
  
      The `exponent=0.5` instance of `cirq.ZPowGate`.
  
      Matrix:
          [[1, 0],
           [0, i]]
      """)
  
  T = ZPowGate(exponent=0.25)
  document(
      T, """The non-Clifford T gate.
  
      The `exponent=0.25` instance of `cirq.ZPowGate`.
  
      Matrix:
          [[1, 0]
           [0, exp(i pi / 4)]]
      """)
  
  CZ = CZPowGate()
  document(
      CZ, """The controlled Z gate.
  
      The `exponent=1` instance of `cirq.CZPowGate`.
  
      Matrix:
  
          [[1 . . .],
           [. 1 . .],
           [. . 1 .],
           [. . . -1]]
      """)
  
  CNOT = CX = CNotPowGate()
  document(
      CNOT, """The controlled NOT gate.
  
      The `exponent=1` instance of `cirq.CNotPowGate`.
  
      Matrix:
  
          [[1 . . .],
           [. 1 . .],
           [. . . 1],
           [. . 1 .]]
      """)
  