cirq-core 1.6.0.dev20250520054601__py3-none-any.whl → 1.6.0.dev20250520183459__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cirq-core might be problematic. Click here for more details.

Files changed (290) hide show
  1. cirq/_compat.py +15 -17
  2. cirq/_compat_test.py +6 -9
  3. cirq/_doc.py +2 -2
  4. cirq/_import.py +6 -6
  5. cirq/_version.py +1 -1
  6. cirq/_version_test.py +1 -1
  7. cirq/circuits/_block_diagram_drawer.py +9 -10
  8. cirq/circuits/_box_drawing_character_data.py +6 -8
  9. cirq/circuits/_bucket_priority_queue.py +7 -7
  10. cirq/circuits/circuit.py +118 -125
  11. cirq/circuits/circuit_operation.py +38 -52
  12. cirq/circuits/circuit_test.py +4 -4
  13. cirq/circuits/frozen_circuit.py +13 -23
  14. cirq/circuits/moment.py +23 -29
  15. cirq/circuits/optimization_pass.py +4 -4
  16. cirq/circuits/optimization_pass_test.py +4 -6
  17. cirq/circuits/qasm_output.py +11 -11
  18. cirq/circuits/text_diagram_drawer.py +21 -36
  19. cirq/contrib/acquaintance/bipartite.py +5 -8
  20. cirq/contrib/acquaintance/executor.py +5 -5
  21. cirq/contrib/acquaintance/executor_test.py +3 -3
  22. cirq/contrib/acquaintance/gates.py +16 -26
  23. cirq/contrib/acquaintance/gates_test.py +3 -3
  24. cirq/contrib/acquaintance/mutation_utils.py +4 -4
  25. cirq/contrib/acquaintance/optimizers.py +4 -4
  26. cirq/contrib/acquaintance/permutation.py +15 -27
  27. cirq/contrib/acquaintance/shift.py +3 -3
  28. cirq/contrib/acquaintance/shift_swap_network.py +4 -4
  29. cirq/contrib/acquaintance/strategies/cubic.py +2 -2
  30. cirq/contrib/acquaintance/strategies/quartic_paired.py +6 -6
  31. cirq/contrib/bayesian_network/bayesian_network_gate.py +9 -10
  32. cirq/contrib/circuitdag/circuit_dag.py +2 -2
  33. cirq/contrib/custom_simulators/custom_state_simulator.py +3 -3
  34. cirq/contrib/custom_simulators/custom_state_simulator_test.py +4 -4
  35. cirq/contrib/graph_device/graph_device.py +5 -5
  36. cirq/contrib/graph_device/hypergraph.py +12 -12
  37. cirq/contrib/graph_device/uniform_graph_device.py +4 -4
  38. cirq/contrib/paulistring/clifford_optimize.py +2 -2
  39. cirq/contrib/paulistring/clifford_target_gateset.py +7 -7
  40. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +31 -31
  41. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +23 -23
  42. cirq/contrib/paulistring/recombine.py +3 -3
  43. cirq/contrib/paulistring/separate.py +2 -2
  44. cirq/contrib/qasm_import/_parser.py +20 -32
  45. cirq/contrib/qcircuit/qcircuit_diagram_info.py +3 -5
  46. cirq/contrib/quantum_volume/quantum_volume.py +24 -24
  47. cirq/contrib/quimb/density_matrix.py +12 -14
  48. cirq/contrib/quimb/mps_simulator.py +20 -20
  49. cirq/contrib/quimb/state_vector.py +6 -10
  50. cirq/contrib/quirk/export_to_quirk.py +3 -3
  51. cirq/contrib/quirk/quirk_gate.py +15 -15
  52. cirq/contrib/routing/device.py +3 -3
  53. cirq/contrib/routing/greedy.py +10 -21
  54. cirq/contrib/routing/initialization.py +2 -2
  55. cirq/contrib/routing/swap_network.py +3 -3
  56. cirq/contrib/routing/utils.py +2 -2
  57. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +8 -8
  58. cirq/contrib/svg/svg.py +3 -3
  59. cirq/devices/grid_device_metadata.py +10 -10
  60. cirq/devices/grid_qubit.py +20 -20
  61. cirq/devices/insertion_noise_model.py +5 -5
  62. cirq/devices/line_qubit.py +13 -13
  63. cirq/devices/named_topologies.py +18 -29
  64. cirq/devices/noise_model.py +3 -3
  65. cirq/devices/noise_properties.py +2 -2
  66. cirq/devices/noise_properties_test.py +1 -3
  67. cirq/devices/noise_utils.py +7 -7
  68. cirq/devices/superconducting_qubits_noise_properties.py +21 -21
  69. cirq/devices/superconducting_qubits_noise_properties_test.py +5 -7
  70. cirq/devices/thermal_noise_model.py +14 -14
  71. cirq/devices/unconstrained_device.py +2 -2
  72. cirq/experiments/benchmarking/parallel_xeb.py +29 -31
  73. cirq/experiments/n_qubit_tomography.py +5 -7
  74. cirq/experiments/qubit_characterizations.py +29 -40
  75. cirq/experiments/qubit_characterizations_test.py +1 -1
  76. cirq/experiments/random_quantum_circuit_generation.py +19 -33
  77. cirq/experiments/random_quantum_circuit_generation_test.py +6 -6
  78. cirq/experiments/readout_confusion_matrix.py +14 -14
  79. cirq/experiments/single_qubit_readout_calibration.py +12 -12
  80. cirq/experiments/t2_decay_experiment.py +7 -7
  81. cirq/experiments/two_qubit_xeb.py +32 -32
  82. cirq/experiments/two_qubit_xeb_test.py +5 -5
  83. cirq/experiments/xeb_fitting.py +25 -25
  84. cirq/experiments/xeb_sampling.py +22 -33
  85. cirq/experiments/xeb_simulation.py +5 -5
  86. cirq/experiments/xeb_simulation_test.py +3 -3
  87. cirq/experiments/z_phase_calibration.py +19 -19
  88. cirq/interop/quirk/cells/arithmetic_cells.py +23 -36
  89. cirq/interop/quirk/cells/cell.py +9 -21
  90. cirq/interop/quirk/cells/composite_cell.py +7 -22
  91. cirq/interop/quirk/cells/control_cells.py +8 -8
  92. cirq/interop/quirk/cells/input_cells.py +4 -4
  93. cirq/interop/quirk/cells/input_rotation_cells.py +5 -5
  94. cirq/interop/quirk/cells/parse.py +20 -23
  95. cirq/interop/quirk/cells/qubit_permutation_cells.py +3 -3
  96. cirq/interop/quirk/cells/swap_cell.py +3 -3
  97. cirq/interop/quirk/cells/testing.py +5 -7
  98. cirq/interop/quirk/url_to_circuit.py +17 -33
  99. cirq/json_resolver_cache.py +6 -6
  100. cirq/linalg/decompositions.py +20 -31
  101. cirq/linalg/diagonalize.py +4 -4
  102. cirq/linalg/diagonalize_test.py +3 -4
  103. cirq/linalg/operator_spaces.py +5 -5
  104. cirq/linalg/predicates.py +7 -7
  105. cirq/linalg/transformations.py +20 -20
  106. cirq/ops/arithmetic_operation.py +13 -15
  107. cirq/ops/boolean_hamiltonian.py +17 -17
  108. cirq/ops/classically_controlled_operation.py +13 -25
  109. cirq/ops/clifford_gate.py +31 -35
  110. cirq/ops/clifford_gate_test.py +2 -3
  111. cirq/ops/common_channels.py +30 -32
  112. cirq/ops/common_gates.py +64 -74
  113. cirq/ops/control_values.py +12 -12
  114. cirq/ops/controlled_gate.py +15 -30
  115. cirq/ops/controlled_gate_test.py +5 -5
  116. cirq/ops/controlled_operation.py +12 -25
  117. cirq/ops/controlled_operation_test.py +5 -5
  118. cirq/ops/dense_pauli_string.py +23 -34
  119. cirq/ops/dense_pauli_string_test.py +1 -2
  120. cirq/ops/diagonal_gate.py +9 -20
  121. cirq/ops/diagonal_gate_test.py +1 -3
  122. cirq/ops/eigen_gate.py +11 -23
  123. cirq/ops/eigen_gate_test.py +6 -8
  124. cirq/ops/fourier_transform.py +5 -5
  125. cirq/ops/fsim_gate.py +14 -14
  126. cirq/ops/gate_operation.py +23 -44
  127. cirq/ops/gateset.py +23 -37
  128. cirq/ops/gateset_test.py +2 -2
  129. cirq/ops/global_phase_op.py +8 -10
  130. cirq/ops/greedy_qubit_manager.py +6 -6
  131. cirq/ops/identity.py +9 -9
  132. cirq/ops/kraus_channel.py +7 -7
  133. cirq/ops/linear_combinations.py +29 -48
  134. cirq/ops/matrix_gates.py +8 -8
  135. cirq/ops/measure_util.py +13 -14
  136. cirq/ops/measurement_gate.py +18 -29
  137. cirq/ops/mixed_unitary_channel.py +8 -8
  138. cirq/ops/named_qubit.py +10 -10
  139. cirq/ops/op_tree.py +7 -7
  140. cirq/ops/parallel_gate.py +5 -5
  141. cirq/ops/parity_gates.py +14 -14
  142. cirq/ops/pauli_gates.py +8 -10
  143. cirq/ops/pauli_interaction_gate.py +6 -6
  144. cirq/ops/pauli_measurement_gate.py +11 -23
  145. cirq/ops/pauli_string.py +35 -52
  146. cirq/ops/pauli_string_phasor.py +4 -14
  147. cirq/ops/pauli_string_raw_types.py +3 -3
  148. cirq/ops/pauli_sum_exponential.py +2 -2
  149. cirq/ops/permutation_gate.py +4 -4
  150. cirq/ops/phased_iswap_gate.py +9 -9
  151. cirq/ops/phased_x_gate.py +10 -10
  152. cirq/ops/phased_x_z_gate.py +11 -11
  153. cirq/ops/projector.py +6 -6
  154. cirq/ops/qubit_manager.py +6 -6
  155. cirq/ops/qubit_order.py +3 -3
  156. cirq/ops/random_gate_channel.py +4 -4
  157. cirq/ops/raw_types.py +48 -70
  158. cirq/ops/state_preparation_channel.py +3 -3
  159. cirq/ops/swap_gates.py +9 -9
  160. cirq/ops/tags.py +2 -4
  161. cirq/ops/three_qubit_gates.py +20 -38
  162. cirq/ops/two_qubit_diagonal_gate.py +5 -5
  163. cirq/ops/uniform_superposition_gate.py +2 -2
  164. cirq/ops/wait_gate.py +5 -5
  165. cirq/protocols/act_on_protocol_test.py +3 -3
  166. cirq/protocols/apply_channel_protocol.py +8 -14
  167. cirq/protocols/apply_mixture_protocol.py +14 -16
  168. cirq/protocols/apply_mixture_protocol_test.py +5 -6
  169. cirq/protocols/apply_unitary_protocol.py +17 -19
  170. cirq/protocols/circuit_diagram_info_protocol.py +19 -30
  171. cirq/protocols/decompose_protocol.py +30 -34
  172. cirq/protocols/inverse_protocol.py +7 -7
  173. cirq/protocols/json_serialization.py +32 -51
  174. cirq/protocols/json_serialization_test.py +9 -10
  175. cirq/protocols/kraus_protocol.py +4 -4
  176. cirq/protocols/kraus_protocol_test.py +3 -3
  177. cirq/protocols/measurement_key_protocol.py +11 -13
  178. cirq/protocols/mixture_protocol.py +4 -4
  179. cirq/protocols/qasm.py +11 -13
  180. cirq/protocols/qid_shape_protocol.py +6 -8
  181. cirq/qis/clifford_tableau.py +12 -12
  182. cirq/qis/measures.py +7 -7
  183. cirq/qis/quantum_state_representation.py +3 -3
  184. cirq/qis/states.py +51 -51
  185. cirq/sim/classical_simulator.py +10 -10
  186. cirq/sim/clifford/clifford_simulator.py +6 -6
  187. cirq/sim/clifford/clifford_tableau_simulation_state_test.py +1 -3
  188. cirq/sim/clifford/stabilizer_sampler.py +4 -4
  189. cirq/sim/clifford/stabilizer_state_ch_form.py +3 -3
  190. cirq/sim/density_matrix_simulation_state.py +15 -15
  191. cirq/sim/density_matrix_simulator.py +11 -11
  192. cirq/sim/density_matrix_utils.py +9 -9
  193. cirq/sim/mux.py +9 -9
  194. cirq/sim/simulation_product_state.py +9 -9
  195. cirq/sim/simulation_product_state_test.py +2 -2
  196. cirq/sim/simulation_state.py +14 -27
  197. cirq/sim/simulation_state_base.py +8 -24
  198. cirq/sim/simulation_utils.py +3 -4
  199. cirq/sim/simulator.py +28 -43
  200. cirq/sim/simulator_base.py +12 -25
  201. cirq/sim/simulator_base_test.py +6 -6
  202. cirq/sim/simulator_test.py +7 -7
  203. cirq/sim/sparse_simulator.py +8 -8
  204. cirq/sim/state_vector.py +8 -8
  205. cirq/sim/state_vector_simulation_state.py +17 -17
  206. cirq/sim/state_vector_simulator.py +4 -4
  207. cirq/study/flatten_expressions.py +12 -14
  208. cirq/study/resolver.py +9 -11
  209. cirq/study/result.py +11 -24
  210. cirq/study/sweepable.py +5 -5
  211. cirq/study/sweeps.py +27 -40
  212. cirq/testing/circuit_compare.py +5 -5
  213. cirq/testing/consistent_controlled_gate_op_test.py +7 -11
  214. cirq/testing/consistent_protocols.py +10 -10
  215. cirq/testing/consistent_protocols_test.py +7 -7
  216. cirq/testing/consistent_qasm.py +4 -4
  217. cirq/testing/consistent_qasm_test.py +2 -3
  218. cirq/testing/devices.py +4 -5
  219. cirq/testing/equals_tester.py +2 -2
  220. cirq/testing/equivalent_basis_map.py +4 -4
  221. cirq/testing/equivalent_repr_eval.py +3 -3
  222. cirq/testing/json.py +14 -14
  223. cirq/testing/logs.py +3 -3
  224. cirq/testing/no_identifier_qubit.py +2 -3
  225. cirq/testing/random_circuit.py +7 -7
  226. cirq/testing/random_circuit_test.py +3 -3
  227. cirq/transformers/analytical_decompositions/clifford_decomposition.py +16 -16
  228. cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +13 -13
  229. cirq/transformers/analytical_decompositions/cphase_to_fsim.py +5 -5
  230. cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +3 -3
  231. cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +3 -3
  232. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +4 -4
  233. cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +6 -7
  234. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +2 -2
  235. cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +7 -7
  236. cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +4 -4
  237. cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +7 -7
  238. cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +11 -11
  239. cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +5 -5
  240. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +14 -14
  241. cirq/transformers/dynamical_decoupling.py +13 -13
  242. cirq/transformers/dynamical_decoupling_test.py +4 -4
  243. cirq/transformers/eject_phased_paulis.py +16 -16
  244. cirq/transformers/eject_z.py +5 -7
  245. cirq/transformers/gauge_compiling/gauge_compiling.py +38 -38
  246. cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +2 -2
  247. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +8 -8
  248. cirq/transformers/insertion_sort.py +5 -5
  249. cirq/transformers/measurement_transformers.py +14 -14
  250. cirq/transformers/merge_k_qubit_gates_test.py +1 -3
  251. cirq/transformers/merge_single_qubit_gates_test.py +1 -3
  252. cirq/transformers/qubit_management_transformers.py +5 -5
  253. cirq/transformers/routing/initial_mapper.py +4 -4
  254. cirq/transformers/routing/line_initial_mapper.py +9 -9
  255. cirq/transformers/routing/mapping_manager.py +7 -7
  256. cirq/transformers/routing/route_circuit_cqc.py +27 -27
  257. cirq/transformers/routing/visualize_routed_circuit.py +4 -4
  258. cirq/transformers/stratify.py +8 -8
  259. cirq/transformers/synchronize_terminal_measurements.py +6 -6
  260. cirq/transformers/target_gatesets/compilation_target_gateset.py +8 -8
  261. cirq/transformers/target_gatesets/compilation_target_gateset_test.py +2 -2
  262. cirq/transformers/target_gatesets/cz_gateset.py +4 -4
  263. cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +5 -5
  264. cirq/transformers/transformer_api.py +11 -26
  265. cirq/transformers/transformer_primitives.py +24 -36
  266. cirq/transformers/transformer_primitives_test.py +3 -3
  267. cirq/value/classical_data.py +18 -18
  268. cirq/value/condition.py +8 -8
  269. cirq/value/digits.py +7 -7
  270. cirq/value/duration.py +12 -12
  271. cirq/value/linear_dict.py +8 -12
  272. cirq/value/linear_dict_test.py +2 -2
  273. cirq/value/measurement_key.py +8 -8
  274. cirq/value/product_state.py +9 -9
  275. cirq/value/value_equality_attr.py +4 -4
  276. cirq/vis/heatmap.py +23 -35
  277. cirq/work/collector.py +9 -17
  278. cirq/work/observable_grouping.py +4 -7
  279. cirq/work/observable_measurement.py +29 -41
  280. cirq/work/observable_measurement_data.py +14 -14
  281. cirq/work/observable_measurement_test.py +2 -2
  282. cirq/work/observable_settings.py +9 -10
  283. cirq/work/pauli_sum_collector.py +5 -5
  284. cirq/work/sampler.py +17 -17
  285. cirq/work/zeros_sampler.py +3 -3
  286. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/METADATA +1 -1
  287. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/RECORD +290 -290
  288. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/WHEEL +1 -1
  289. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/licenses/LICENSE +0 -0
  290. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/top_level.txt +0 -0
cirq/ops/common_gates.py CHANGED
@@ -28,7 +28,7 @@ raised to a power (i.e. cirq.H**0.5). See the definition in EigenGate.
28
28
  from __future__ import annotations
29
29
 
30
30
  from types import NotImplementedType
31
- from typing import Any, cast, Collection, Dict, List, Optional, Sequence, Tuple, Union
31
+ from typing import Any, cast, Collection, Sequence
32
32
 
33
33
  import numpy as np
34
34
  import sympy
@@ -75,7 +75,7 @@ class XPowGate(eigen_gate.EigenGate):
75
75
  `cirq.X`, the Pauli X gate, is an instance of this gate at `exponent=1`.
76
76
  """
77
77
 
78
- _eigencomponents: Dict[int, List[Tuple[float, np.ndarray]]] = {}
78
+ _eigencomponents: dict[int, list[tuple[float, np.ndarray]]] = {}
79
79
 
80
80
  def __init__(
81
81
  self, *, exponent: value.TParamVal = 1.0, global_shift: float = 0.0, dimension: int = 2
@@ -114,7 +114,7 @@ class XPowGate(eigen_gate.EigenGate):
114
114
  def _num_qubits_(self) -> int:
115
115
  return 1
116
116
 
117
- def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> Optional[np.ndarray]:
117
+ def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray | None:
118
118
  if self._exponent != 1 or self._dimension != 2:
119
119
  return NotImplemented
120
120
  zero = args.subspace_index(0)
@@ -134,10 +134,10 @@ class XPowGate(eigen_gate.EigenGate):
134
134
  """Returns an equal-up-global-phase standardized form of the gate."""
135
135
  return XPowGate(exponent=self._exponent, dimension=self._dimension)
136
136
 
137
- def _qid_shape_(self) -> Tuple[int, ...]:
137
+ def _qid_shape_(self) -> tuple[int, ...]:
138
138
  return (self._dimension,)
139
139
 
140
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
140
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
141
141
  if self._dimension not in XPowGate._eigencomponents:
142
142
  components = []
143
143
  root = 1j ** (4 / self._dimension)
@@ -167,18 +167,16 @@ class XPowGate(eigen_gate.EigenGate):
167
167
  return SingleQubitCliffordGate.X_nsqrt.on(*qubits)
168
168
  return NotImplemented # pragma: no cover
169
169
 
170
- def _trace_distance_bound_(self) -> Optional[float]:
170
+ def _trace_distance_bound_(self) -> float | None:
171
171
  if self._is_parameterized_() or self._dimension != 2:
172
172
  return None
173
173
  return abs(np.sin(self._exponent * 0.5 * np.pi))
174
174
 
175
175
  def controlled(
176
176
  self,
177
- num_controls: Optional[int] = None,
178
- control_values: Optional[
179
- Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
180
- ] = None,
181
- control_qid_shape: Optional[Tuple[int, ...]] = None,
177
+ num_controls: int | None = None,
178
+ control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
179
+ control_qid_shape: tuple[int, ...] | None = None,
182
180
  ) -> raw_types.Gate:
183
181
  """Returns a controlled `XPowGate`, using a `CXPowGate` where possible.
184
182
 
@@ -255,12 +253,12 @@ class XPowGate(eigen_gate.EigenGate):
255
253
 
256
254
  def _circuit_diagram_info_(
257
255
  self, args: cirq.CircuitDiagramInfoArgs
258
- ) -> Union[str, protocols.CircuitDiagramInfo]:
256
+ ) -> str | protocols.CircuitDiagramInfo:
259
257
  return protocols.CircuitDiagramInfo(
260
258
  wire_symbols=('X',), exponent=self._diagram_exponent(args)
261
259
  )
262
260
 
263
- def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
261
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
264
262
  args.validate_version('2.0', '3.0')
265
263
  if self._global_shift == 0:
266
264
  if self._exponent == 1:
@@ -279,7 +277,7 @@ class XPowGate(eigen_gate.EigenGate):
279
277
  """See `cirq.SupportsPhase`."""
280
278
  return _phased_x_or_pauli_gate(exponent=self._exponent, phase_exponent=phase_turns * 2)
281
279
 
282
- def _has_stabilizer_effect_(self) -> Optional[bool]:
280
+ def _has_stabilizer_effect_(self) -> bool | None:
283
281
  if self._is_parameterized_() or self._dimension != 2:
284
282
  return None
285
283
  return self.exponent % 0.5 == 0
@@ -306,7 +304,7 @@ class XPowGate(eigen_gate.EigenGate):
306
304
  all_args = ', '.join(args)
307
305
  return f'cirq.XPowGate({all_args})'
308
306
 
309
- def _json_dict_(self) -> Dict[str, Any]:
307
+ def _json_dict_(self) -> dict[str, Any]:
310
308
  d = protocols.obj_to_dict_helper(self, ['exponent', 'global_shift'])
311
309
  if self.dimension != 2:
312
310
  d['dimension'] = self.dimension
@@ -342,7 +340,7 @@ class Rx(XPowGate):
342
340
 
343
341
  def _circuit_diagram_info_(
344
342
  self, args: cirq.CircuitDiagramInfoArgs
345
- ) -> Union[str, protocols.CircuitDiagramInfo]:
343
+ ) -> str | protocols.CircuitDiagramInfo:
346
344
  angle_str = self._format_exponent_as_angle(args)
347
345
  return f'Rx({angle_str})'
348
346
 
@@ -354,11 +352,11 @@ class Rx(XPowGate):
354
352
  def __repr__(self) -> str:
355
353
  return f'cirq.Rx(rads={proper_repr(self._rads)})'
356
354
 
357
- def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
355
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
358
356
  args.validate_version('2.0', '3.0')
359
357
  return args.format('rx({0:half_turns}) {1};\n', self._exponent, qubits[0])
360
358
 
361
- def _json_dict_(self) -> Dict[str, Any]:
359
+ def _json_dict_(self) -> dict[str, Any]:
362
360
  return {'rads': self._rads}
363
361
 
364
362
  @classmethod
@@ -400,7 +398,7 @@ class YPowGate(eigen_gate.EigenGate):
400
398
  def _num_qubits_(self) -> int:
401
399
  return 1
402
400
 
403
- def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> Optional[np.ndarray]:
401
+ def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray | None:
404
402
  if self._exponent != 1:
405
403
  return NotImplemented
406
404
  zero = args.subspace_index(0)
@@ -433,13 +431,13 @@ class YPowGate(eigen_gate.EigenGate):
433
431
  return SingleQubitCliffordGate.Y_nsqrt.on(*qubits)
434
432
  return NotImplemented # pragma: no cover
435
433
 
436
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
434
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
437
435
  return [
438
436
  (0, np.array([[0.5, -0.5j], [0.5j, 0.5]])),
439
437
  (1, np.array([[0.5, 0.5j], [-0.5j, 0.5]])),
440
438
  ]
441
439
 
442
- def _trace_distance_bound_(self) -> Optional[float]:
440
+ def _trace_distance_bound_(self) -> float | None:
443
441
  if self._is_parameterized_():
444
442
  return None
445
443
  return abs(np.sin(self._exponent * 0.5 * np.pi))
@@ -452,12 +450,12 @@ class YPowGate(eigen_gate.EigenGate):
452
450
 
453
451
  def _circuit_diagram_info_(
454
452
  self, args: cirq.CircuitDiagramInfoArgs
455
- ) -> Union[str, protocols.CircuitDiagramInfo]:
453
+ ) -> str | protocols.CircuitDiagramInfo:
456
454
  return protocols.CircuitDiagramInfo(
457
455
  wire_symbols=('Y',), exponent=self._diagram_exponent(args)
458
456
  )
459
457
 
460
- def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
458
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
461
459
  args.validate_version('2.0', '3.0')
462
460
  if self._exponent == 1 and self.global_shift != -0.5:
463
461
  return args.format('y {0};\n', qubits[0])
@@ -474,7 +472,7 @@ class YPowGate(eigen_gate.EigenGate):
474
472
  exponent=self._exponent, phase_exponent=0.5 + phase_turns * 2
475
473
  )
476
474
 
477
- def _has_stabilizer_effect_(self) -> Optional[bool]:
475
+ def _has_stabilizer_effect_(self) -> bool | None:
478
476
  if self._is_parameterized_():
479
477
  return None
480
478
  return self.exponent % 0.5 == 0
@@ -527,7 +525,7 @@ class Ry(YPowGate):
527
525
 
528
526
  def _circuit_diagram_info_(
529
527
  self, args: cirq.CircuitDiagramInfoArgs
530
- ) -> Union[str, protocols.CircuitDiagramInfo]:
528
+ ) -> str | protocols.CircuitDiagramInfo:
531
529
  angle_str = self._format_exponent_as_angle(args)
532
530
  return f'Ry({angle_str})'
533
531
 
@@ -539,11 +537,11 @@ class Ry(YPowGate):
539
537
  def __repr__(self) -> str:
540
538
  return f'cirq.Ry(rads={proper_repr(self._rads)})'
541
539
 
542
- def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
540
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
543
541
  args.validate_version('2.0', '3.0')
544
542
  return args.format('ry({0:half_turns}) {1};\n', self._exponent, qubits[0])
545
543
 
546
- def _json_dict_(self) -> Dict[str, Any]:
544
+ def _json_dict_(self) -> dict[str, Any]:
547
545
  return {'rads': self._rads}
548
546
 
549
547
  @classmethod
@@ -573,7 +571,7 @@ class ZPowGate(eigen_gate.EigenGate):
573
571
  `cirq.Z`, the Pauli Z gate, is an instance of this gate at `exponent=1`.
574
572
  """
575
573
 
576
- _eigencomponents: Dict[int, List[Tuple[float, np.ndarray]]] = {}
574
+ _eigencomponents: dict[int, list[tuple[float, np.ndarray]]] = {}
577
575
 
578
576
  def __init__(
579
577
  self, *, exponent: value.TParamVal = 1.0, global_shift: float = 0.0, dimension: int = 2
@@ -612,7 +610,7 @@ class ZPowGate(eigen_gate.EigenGate):
612
610
  def _num_qubits_(self) -> int:
613
611
  return 1
614
612
 
615
- def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> Optional[np.ndarray]:
613
+ def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray | None:
616
614
  if protocols.is_parameterized(self):
617
615
  return None
618
616
 
@@ -648,11 +646,9 @@ class ZPowGate(eigen_gate.EigenGate):
648
646
 
649
647
  def controlled(
650
648
  self,
651
- num_controls: Optional[int] = None,
652
- control_values: Optional[
653
- Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
654
- ] = None,
655
- control_qid_shape: Optional[Tuple[int, ...]] = None,
649
+ num_controls: int | None = None,
650
+ control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
651
+ control_qid_shape: tuple[int, ...] | None = None,
656
652
  ) -> raw_types.Gate:
657
653
  """Returns a controlled `ZPowGate`, using a `CZPowGate` where possible.
658
654
 
@@ -719,10 +715,10 @@ class ZPowGate(eigen_gate.EigenGate):
719
715
  )
720
716
  return result
721
717
 
722
- def _qid_shape_(self) -> Tuple[int, ...]:
718
+ def _qid_shape_(self) -> tuple[int, ...]:
723
719
  return (self._dimension,)
724
720
 
725
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
721
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
726
722
  if self._dimension not in ZPowGate._eigencomponents:
727
723
  components = []
728
724
  for i in range(self._dimension):
@@ -738,7 +734,7 @@ class ZPowGate(eigen_gate.EigenGate):
738
734
  exponent=exponent, global_shift=self._global_shift, dimension=self._dimension
739
735
  )
740
736
 
741
- def _trace_distance_bound_(self) -> Optional[float]:
737
+ def _trace_distance_bound_(self) -> float | None:
742
738
  if self._is_parameterized_() or self._dimension != 2:
743
739
  return None
744
740
  return abs(np.sin(self._exponent * 0.5 * np.pi))
@@ -754,14 +750,14 @@ class ZPowGate(eigen_gate.EigenGate):
754
750
  def _phase_by_(self, phase_turns: float, qubit_index: int):
755
751
  return self
756
752
 
757
- def _has_stabilizer_effect_(self) -> Optional[bool]:
753
+ def _has_stabilizer_effect_(self) -> bool | None:
758
754
  if self._is_parameterized_() or self._dimension != 2:
759
755
  return None
760
756
  return self.exponent % 0.5 == 0
761
757
 
762
758
  def _circuit_diagram_info_(
763
759
  self, args: cirq.CircuitDiagramInfoArgs
764
- ) -> Union[str, protocols.CircuitDiagramInfo]:
760
+ ) -> str | protocols.CircuitDiagramInfo:
765
761
  e = self._diagram_exponent(args)
766
762
  if e in [-0.25, 0.25]:
767
763
  return protocols.CircuitDiagramInfo(wire_symbols=('T',), exponent=cast(float, e) * 4)
@@ -771,7 +767,7 @@ class ZPowGate(eigen_gate.EigenGate):
771
767
 
772
768
  return protocols.CircuitDiagramInfo(wire_symbols=('Z',), exponent=e)
773
769
 
774
- def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
770
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
775
771
  args.validate_version('2.0', '3.0')
776
772
 
777
773
  if self.global_shift == 0:
@@ -827,7 +823,7 @@ class ZPowGate(eigen_gate.EigenGate):
827
823
 
828
824
  def _commutes_on_qids_(
829
825
  self, qids: Sequence[cirq.Qid], other: Any, *, atol: float = 1e-8
830
- ) -> Union[bool, NotImplementedType, None]:
826
+ ) -> bool | NotImplementedType | None:
831
827
  from cirq.ops.parity_gates import ZZPowGate
832
828
 
833
829
  if not isinstance(other, raw_types.Operation):
@@ -836,7 +832,7 @@ class ZPowGate(eigen_gate.EigenGate):
836
832
  return NotImplemented
837
833
  return True
838
834
 
839
- def _json_dict_(self) -> Dict[str, Any]:
835
+ def _json_dict_(self) -> dict[str, Any]:
840
836
  d = protocols.obj_to_dict_helper(self, ['exponent', 'global_shift'])
841
837
  if self.dimension != 2:
842
838
  d['dimension'] = self.dimension
@@ -872,7 +868,7 @@ class Rz(ZPowGate):
872
868
 
873
869
  def _circuit_diagram_info_(
874
870
  self, args: cirq.CircuitDiagramInfoArgs
875
- ) -> Union[str, protocols.CircuitDiagramInfo]:
871
+ ) -> str | protocols.CircuitDiagramInfo:
876
872
  angle_str = self._format_exponent_as_angle(args)
877
873
  return f'Rz({angle_str})'
878
874
 
@@ -884,11 +880,11 @@ class Rz(ZPowGate):
884
880
  def __repr__(self) -> str:
885
881
  return f'cirq.Rz(rads={proper_repr(self._rads)})'
886
882
 
887
- def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
883
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
888
884
  args.validate_version('2.0', '3.0')
889
885
  return args.format('rz({0:half_turns}) {1};\n', self._exponent, qubits[0])
890
886
 
891
- def _json_dict_(self) -> Dict[str, Any]:
887
+ def _json_dict_(self) -> dict[str, Any]:
892
888
  return {'rads': self._rads}
893
889
 
894
890
  @classmethod
@@ -919,7 +915,7 @@ class HPowGate(eigen_gate.EigenGate):
919
915
  `cirq.H`, the Hadamard gate, is an instance of this gate at `exponent=1`.
920
916
  """
921
917
 
922
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
918
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
923
919
  s = np.sqrt(2)
924
920
 
925
921
  component0 = np.array([[3 + 2 * s, 1 + s], [1 + s, 1]]) / (4 + 2 * s)
@@ -931,7 +927,7 @@ class HPowGate(eigen_gate.EigenGate):
931
927
  def _num_qubits_(self) -> int:
932
928
  return 1
933
929
 
934
- def _trace_distance_bound_(self) -> Optional[float]:
930
+ def _trace_distance_bound_(self) -> float | None:
935
931
  if self._is_parameterized_():
936
932
  return None
937
933
  return abs(np.sin(self._exponent * 0.5 * np.pi))
@@ -958,7 +954,7 @@ class HPowGate(eigen_gate.EigenGate):
958
954
  return []
959
955
  return NotImplemented # pragma: no cover
960
956
 
961
- def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> Optional[np.ndarray]:
957
+ def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray | None:
962
958
  if self._exponent != 1:
963
959
  return NotImplemented
964
960
 
@@ -988,7 +984,7 @@ class HPowGate(eigen_gate.EigenGate):
988
984
  wire_symbols=('H',), exponent=self._diagram_exponent(args)
989
985
  )
990
986
 
991
- def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
987
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
992
988
  args.validate_version('2.0', '3.0')
993
989
  if self._exponent == 0:
994
990
  return args.format('id {0};\n', qubits[0])
@@ -1003,7 +999,7 @@ class HPowGate(eigen_gate.EigenGate):
1003
999
  qubits[0],
1004
1000
  )
1005
1001
 
1006
- def _has_stabilizer_effect_(self) -> Optional[bool]:
1002
+ def _has_stabilizer_effect_(self) -> bool | None:
1007
1003
  if self._is_parameterized_():
1008
1004
  return None
1009
1005
  return self.exponent % 1 == 0
@@ -1054,17 +1050,15 @@ class CZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
1054
1050
  return []
1055
1051
  return NotImplemented # pragma: no cover
1056
1052
 
1057
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
1053
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
1058
1054
  return [(0, np.diag([1, 1, 1, 0])), (1, np.diag([0, 0, 0, 1]))]
1059
1055
 
1060
- def _trace_distance_bound_(self) -> Optional[float]:
1056
+ def _trace_distance_bound_(self) -> float | None:
1061
1057
  if self._is_parameterized_():
1062
1058
  return None
1063
1059
  return abs(np.sin(self._exponent * 0.5 * np.pi))
1064
1060
 
1065
- def _apply_unitary_(
1066
- self, args: protocols.ApplyUnitaryArgs
1067
- ) -> Union[np.ndarray, NotImplementedType]:
1061
+ def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray | NotImplementedType:
1068
1062
  if protocols.is_parameterized(self):
1069
1063
  return NotImplemented
1070
1064
 
@@ -1096,11 +1090,9 @@ class CZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
1096
1090
 
1097
1091
  def controlled(
1098
1092
  self,
1099
- num_controls: Optional[int] = None,
1100
- control_values: Optional[
1101
- Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
1102
- ] = None,
1103
- control_qid_shape: Optional[Tuple[int, ...]] = None,
1093
+ num_controls: int | None = None,
1094
+ control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
1095
+ control_qid_shape: tuple[int, ...] | None = None,
1104
1096
  ) -> raw_types.Gate:
1105
1097
  """Returns a controlled `CZPowGate`, using a `CCZPowGate` where possible.
1106
1098
 
@@ -1172,13 +1164,13 @@ class CZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
1172
1164
  wire_symbols=('@', '@'), exponent=self._diagram_exponent(args)
1173
1165
  )
1174
1166
 
1175
- def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
1167
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
1176
1168
  if self._exponent != 1:
1177
1169
  return None # Don't have an equivalent gate in QASM
1178
1170
  args.validate_version('2.0', '3.0')
1179
1171
  return args.format('cz {0},{1};\n', qubits[0], qubits[1])
1180
1172
 
1181
- def _has_stabilizer_effect_(self) -> Optional[bool]:
1173
+ def _has_stabilizer_effect_(self) -> bool | None:
1182
1174
  if self._is_parameterized_():
1183
1175
  return None
1184
1176
  return self.exponent % 1 == 0
@@ -1253,13 +1245,13 @@ class CXPowGate(eigen_gate.EigenGate):
1253
1245
  yield cirq.CZPowGate(exponent=self._exponent, global_shift=self.global_shift).on(c, t)
1254
1246
  yield YPowGate(exponent=0.5).on(t)
1255
1247
 
1256
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
1248
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
1257
1249
  return [
1258
1250
  (0, np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0.5, 0.5], [0, 0, 0.5, 0.5]])),
1259
1251
  (1, np.array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0.5, -0.5], [0, 0, -0.5, 0.5]])),
1260
1252
  ]
1261
1253
 
1262
- def _trace_distance_bound_(self) -> Optional[float]:
1254
+ def _trace_distance_bound_(self) -> float | None:
1263
1255
  if self._is_parameterized_():
1264
1256
  return None
1265
1257
  return abs(np.sin(self._exponent * 0.5 * np.pi))
@@ -1269,7 +1261,7 @@ class CXPowGate(eigen_gate.EigenGate):
1269
1261
  wire_symbols=('@', 'X'), exponent=self._diagram_exponent(args), exponent_qubit_index=1
1270
1262
  )
1271
1263
 
1272
- def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> Optional[np.ndarray]:
1264
+ def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray | None:
1273
1265
  if self._exponent != 1:
1274
1266
  return NotImplemented
1275
1267
 
@@ -1300,11 +1292,9 @@ class CXPowGate(eigen_gate.EigenGate):
1300
1292
 
1301
1293
  def controlled(
1302
1294
  self,
1303
- num_controls: Optional[int] = None,
1304
- control_values: Optional[
1305
- Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
1306
- ] = None,
1307
- control_qid_shape: Optional[Tuple[int, ...]] = None,
1295
+ num_controls: int | None = None,
1296
+ control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
1297
+ control_qid_shape: tuple[int, ...] | None = None,
1308
1298
  ) -> raw_types.Gate:
1309
1299
  """Returns a controlled `CXPowGate`, using a `CCXPowGate` where possible.
1310
1300
 
@@ -1371,13 +1361,13 @@ class CXPowGate(eigen_gate.EigenGate):
1371
1361
  )
1372
1362
  return result
1373
1363
 
1374
- def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
1364
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
1375
1365
  if self._exponent != 1:
1376
1366
  return None # Don't have an equivalent gate in QASM
1377
1367
  args.validate_version('2.0', '3.0')
1378
1368
  return args.format('cx {0},{1};\n', qubits[0], qubits[1])
1379
1369
 
1380
- def _has_stabilizer_effect_(self) -> Optional[bool]:
1370
+ def _has_stabilizer_effect_(self) -> bool | None:
1381
1371
  if self._is_parameterized_():
1382
1372
  return None
1383
1373
  return self.exponent % 1 == 0
@@ -1525,8 +1515,8 @@ document(
1525
1515
 
1526
1516
 
1527
1517
  def _phased_x_or_pauli_gate(
1528
- exponent: Union[float, sympy.Expr], phase_exponent: Union[float, sympy.Expr]
1529
- ) -> Union[cirq.PhasedXPowGate, cirq.XPowGate, cirq.YPowGate]:
1518
+ exponent: float | sympy.Expr, phase_exponent: float | sympy.Expr
1519
+ ) -> cirq.PhasedXPowGate | cirq.XPowGate | cirq.YPowGate:
1530
1520
  """Return PhasedXPowGate or X or Y gate if equivalent at the given phase_exponent."""
1531
1521
  if not isinstance(phase_exponent, sympy.Expr) or phase_exponent.is_constant():
1532
1522
  half_turns = value.canonicalize_half_turns(float(phase_exponent))
@@ -17,7 +17,7 @@ from __future__ import annotations
17
17
  import abc
18
18
  import itertools
19
19
  from functools import cached_property
20
- from typing import Any, Collection, Dict, Iterator, Optional, Sequence, Tuple, TYPE_CHECKING, Union
20
+ from typing import Any, Collection, Iterator, Sequence, TYPE_CHECKING
21
21
 
22
22
  from cirq import protocols, value
23
23
 
@@ -67,7 +67,7 @@ class AbstractControlValues(abc.ABC):
67
67
  """Returns the number of qubits for which control values are stored by this object."""
68
68
 
69
69
  @abc.abstractmethod
70
- def _json_dict_(self) -> Dict[str, Any]:
70
+ def _json_dict_(self) -> dict[str, Any]:
71
71
  """Returns a dictionary used for serializing this object."""
72
72
 
73
73
  @abc.abstractmethod
@@ -75,7 +75,7 @@ class AbstractControlValues(abc.ABC):
75
75
  """Returns information used to draw this object in circuit diagrams."""
76
76
 
77
77
  @abc.abstractmethod
78
- def __iter__(self) -> Iterator[Tuple[int, ...]]:
78
+ def __iter__(self) -> Iterator[tuple[int, ...]]:
79
79
  """Iterator on internal representation of control values used by the derived classes.
80
80
 
81
81
  Note: Be careful that the terms iterated upon by this iterator will have different
@@ -141,8 +141,8 @@ class AbstractControlValues(abc.ABC):
141
141
  class ProductOfSums(AbstractControlValues):
142
142
  """Represents control values as N OR (sum) clauses, each of which applies to one qubit."""
143
143
 
144
- def __init__(self, data: Sequence[Union[int, Collection[int]]]):
145
- self._qubit_sums: Tuple[Tuple[int, ...], ...] = tuple(
144
+ def __init__(self, data: Sequence[int | Collection[int]]):
145
+ self._qubit_sums: tuple[tuple[int, ...], ...] = tuple(
146
146
  (cv,) if isinstance(cv, int) else tuple(sorted(set(cv))) for cv in data
147
147
  )
148
148
 
@@ -150,7 +150,7 @@ class ProductOfSums(AbstractControlValues):
150
150
  def is_trivial(self) -> bool:
151
151
  return self._qubit_sums == ((1,),) * self._num_qubits_()
152
152
 
153
- def __iter__(self) -> Iterator[Tuple[int, ...]]:
153
+ def __iter__(self) -> Iterator[tuple[int, ...]]:
154
154
  return iter(self._qubit_sums)
155
155
 
156
156
  def expand(self) -> SumOfProducts:
@@ -162,7 +162,7 @@ class ProductOfSums(AbstractControlValues):
162
162
  def _num_qubits_(self) -> int:
163
163
  return len(self._qubit_sums)
164
164
 
165
- def __getitem__(self, key: Union[int, slice]) -> Union[ProductOfSums, Tuple[int, ...]]:
165
+ def __getitem__(self, key: int | slice) -> ProductOfSums | tuple[int, ...]:
166
166
  if isinstance(key, slice):
167
167
  return ProductOfSums(self._qubit_sums[key])
168
168
  return self._qubit_sums[key]
@@ -194,7 +194,7 @@ class ProductOfSums(AbstractControlValues):
194
194
 
195
195
  return ''.join(get_prefix(t) for t in self._qubit_sums)
196
196
 
197
- def _json_dict_(self) -> Dict[str, Any]:
197
+ def _json_dict_(self) -> dict[str, Any]:
198
198
  return {"data": self._qubit_sums}
199
199
 
200
200
  def __and__(self, other: AbstractControlValues) -> AbstractControlValues:
@@ -241,8 +241,8 @@ class SumOfProducts(AbstractControlValues):
241
241
  >>> nand_cop = cirq.X(q2).controlled_by(q0, q1, control_values=nand_control_values)
242
242
  """
243
243
 
244
- def __init__(self, data: Collection[Sequence[int]], *, name: Optional[str] = None):
245
- self._conjunctions: Tuple[Tuple[int, ...], ...] = tuple(
244
+ def __init__(self, data: Collection[Sequence[int]], *, name: str | None = None):
245
+ self._conjunctions: tuple[tuple[int, ...], ...] = tuple(
246
246
  sorted(set(tuple(cv) for cv in data))
247
247
  )
248
248
  self._name = name
@@ -259,7 +259,7 @@ class SumOfProducts(AbstractControlValues):
259
259
  def expand(self) -> SumOfProducts:
260
260
  return self
261
261
 
262
- def __iter__(self) -> Iterator[Tuple[int, ...]]:
262
+ def __iter__(self) -> Iterator[tuple[int, ...]]:
263
263
  """Returns the combinations tracked by the object."""
264
264
  return iter(self._conjunctions)
265
265
 
@@ -313,5 +313,5 @@ class SumOfProducts(AbstractControlValues):
313
313
  f' of range [0, {qid_shapes[q_i]}) for control qubit number <{q_i}>.'
314
314
  )
315
315
 
316
- def _json_dict_(self) -> Dict[str, Any]:
316
+ def _json_dict_(self) -> dict[str, Any]:
317
317
  return {'data': self._conjunctions, 'name': self._name}
@@ -15,18 +15,7 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  from types import NotImplementedType
18
- from typing import (
19
- AbstractSet,
20
- Any,
21
- Collection,
22
- Dict,
23
- List,
24
- Optional,
25
- Sequence,
26
- Tuple,
27
- TYPE_CHECKING,
28
- Union,
29
- )
18
+ from typing import AbstractSet, Any, Collection, Sequence, TYPE_CHECKING
30
19
 
31
20
  import numpy as np
32
21
 
@@ -60,11 +49,9 @@ class ControlledGate(raw_types.Gate):
60
49
  def __init__(
61
50
  self,
62
51
  sub_gate: cirq.Gate,
63
- num_controls: Optional[int] = None,
64
- control_values: Optional[
65
- Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
66
- ] = None,
67
- control_qid_shape: Optional[Sequence[int]] = None,
52
+ num_controls: int | None = None,
53
+ control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
54
+ control_qid_shape: Sequence[int] | None = None,
68
55
  ) -> None:
69
56
  """Initializes the controlled gate. If no arguments are specified for
70
57
  the controls, defaults to a single qubit control.
@@ -135,7 +122,7 @@ class ControlledGate(raw_types.Gate):
135
122
  self._sub_gate = sub_gate
136
123
 
137
124
  @property
138
- def control_qid_shape(self) -> Tuple[int, ...]:
125
+ def control_qid_shape(self) -> tuple[int, ...]:
139
126
  return self._control_qid_shape
140
127
 
141
128
  @property
@@ -149,17 +136,15 @@ class ControlledGate(raw_types.Gate):
149
136
  def num_controls(self) -> int:
150
137
  return len(self.control_qid_shape)
151
138
 
152
- def _qid_shape_(self) -> Tuple[int, ...]:
139
+ def _qid_shape_(self) -> tuple[int, ...]:
153
140
  return self.control_qid_shape + protocols.qid_shape(self.sub_gate)
154
141
 
155
- def _decompose_(
156
- self, qubits: Tuple[cirq.Qid, ...]
157
- ) -> Union[None, NotImplementedType, cirq.OP_TREE]:
142
+ def _decompose_(self, qubits: tuple[cirq.Qid, ...]) -> None | NotImplementedType | cirq.OP_TREE:
158
143
  return self._decompose_with_context_(qubits)
159
144
 
160
145
  def _decompose_with_context_(
161
- self, qubits: Tuple[cirq.Qid, ...], context: Optional[cirq.DecompositionContext] = None
162
- ) -> Union[None, NotImplementedType, cirq.OP_TREE]:
146
+ self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext | None = None
147
+ ) -> None | NotImplementedType | cirq.OP_TREE:
163
148
  control_qubits = list(qubits[: self.num_controls()])
164
149
  if (
165
150
  protocols.has_unitary(self.sub_gate)
@@ -167,7 +152,7 @@ class ControlledGate(raw_types.Gate):
167
152
  and self._qid_shape_() == (2,) * len(self._qid_shape_())
168
153
  and isinstance(self.control_values, cv.ProductOfSums)
169
154
  ):
170
- invert_ops: List[cirq.Operation] = []
155
+ invert_ops: list[cirq.Operation] = []
171
156
  for cvals, cqbit in zip(self.control_values, qubits[: self.num_controls()]):
172
157
  if set(cvals) == {0}:
173
158
  invert_ops.append(common_gates.X(cqbit))
@@ -260,7 +245,7 @@ class ControlledGate(raw_types.Gate):
260
245
  def _has_unitary_(self) -> bool:
261
246
  return protocols.has_unitary(self.sub_gate)
262
247
 
263
- def _unitary_(self) -> Union[np.ndarray, NotImplementedType]:
248
+ def _unitary_(self) -> np.ndarray | NotImplementedType:
264
249
  qubits = line_qubit.LineQid.for_gate(self)
265
250
  op = self.sub_gate.on(*qubits[self.num_controls() :])
266
251
  c_op = cop.ControlledOperation(qubits[: self.num_controls()], op, self.control_values)
@@ -270,7 +255,7 @@ class ControlledGate(raw_types.Gate):
270
255
  def _has_mixture_(self) -> bool:
271
256
  return protocols.has_mixture(self.sub_gate)
272
257
 
273
- def _mixture_(self) -> Union[Sequence[tuple[float, np.ndarray]], NotImplementedType]:
258
+ def _mixture_(self) -> Sequence[tuple[float, np.ndarray]] | NotImplementedType:
274
259
  qubits = line_qubit.LineQid.for_gate(self)
275
260
  op = self.sub_gate.on(*qubits[self.num_controls() :])
276
261
  c_op = cop.ControlledOperation(qubits[: self.num_controls()], op, self.control_values)
@@ -302,7 +287,7 @@ class ControlledGate(raw_types.Gate):
302
287
  control_qid_shape=self.control_qid_shape,
303
288
  )
304
289
 
305
- def _trace_distance_bound_(self) -> Optional[float]:
290
+ def _trace_distance_bound_(self) -> float | None:
306
291
  if self._is_parameterized_():
307
292
  return None
308
293
  u = protocols.unitary(self.sub_gate, default=None)
@@ -353,7 +338,7 @@ class ControlledGate(raw_types.Gate):
353
338
  f'control_qid_shape={self.control_qid_shape!r})'
354
339
  )
355
340
 
356
- def _json_dict_(self) -> Dict[str, Any]:
341
+ def _json_dict_(self) -> dict[str, Any]:
357
342
  return {
358
343
  'control_values': self.control_values,
359
344
  'control_qid_shape': self.control_qid_shape,
@@ -361,7 +346,7 @@ class ControlledGate(raw_types.Gate):
361
346
  }
362
347
 
363
348
 
364
- def _validate_sub_object(sub_object: Union[cirq.Gate, cirq.Operation]):
349
+ def _validate_sub_object(sub_object: cirq.Gate | cirq.Operation):
365
350
  if protocols.is_measurement(sub_object):
366
351
  raise ValueError(f'Cannot control measurement {sub_object}')
367
352
  if not protocols.has_mixture(sub_object) and not protocols.is_parameterized(sub_object):