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
@@ -16,19 +16,7 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- from typing import (
20
- AbstractSet,
21
- Any,
22
- Collection,
23
- Dict,
24
- Iterator,
25
- List,
26
- Optional,
27
- Sequence,
28
- Tuple,
29
- TYPE_CHECKING,
30
- Union,
31
- )
19
+ from typing import AbstractSet, Any, Collection, Iterator, Sequence, TYPE_CHECKING
32
20
 
33
21
  import numpy as np
34
22
  import sympy
@@ -72,10 +60,10 @@ class CCZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
72
60
  $$
73
61
  """
74
62
 
75
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
63
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
76
64
  return [(0, np.diag([1, 1, 1, 1, 1, 1, 1, 0])), (1, np.diag([0, 0, 0, 0, 0, 0, 0, 1]))]
77
65
 
78
- def _trace_distance_bound_(self) -> Optional[float]:
66
+ def _trace_distance_bound_(self) -> float | None:
79
67
  if self._is_parameterized_():
80
68
  return None
81
69
  return abs(np.sin(self._exponent * 0.5 * np.pi))
@@ -159,7 +147,7 @@ class CCZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
159
147
  def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
160
148
  return protocols.CircuitDiagramInfo(('@', '@', '@'), exponent=self._diagram_exponent(args))
161
149
 
162
- def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
150
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
163
151
  if self._exponent != 1:
164
152
  return None
165
153
 
@@ -191,11 +179,9 @@ class CCZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
191
179
 
192
180
  def controlled(
193
181
  self,
194
- num_controls: Optional[int] = None,
195
- control_values: Optional[
196
- Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
197
- ] = None,
198
- control_qid_shape: Optional[Tuple[int, ...]] = None,
182
+ num_controls: int | None = None,
183
+ control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
184
+ control_qid_shape: tuple[int, ...] | None = None,
199
185
  ) -> raw_types.Gate:
200
186
  """Returns a controlled `ZPowGate` with two additional controls.
201
187
 
@@ -238,10 +224,10 @@ class ThreeQubitDiagonalGate(raw_types.Gate):
238
224
  If these values are $(x_0, x_1, \ldots , x_7)$ then the unitary
239
225
  has diagonal values $(e^{i x_0}, e^{i x_1}, \ldots, e^{i x_7})$.
240
226
  """
241
- self._diag_angles_radians: Tuple[value.TParamVal, ...] = tuple(diag_angles_radians)
227
+ self._diag_angles_radians: tuple[value.TParamVal, ...] = tuple(diag_angles_radians)
242
228
 
243
229
  @property
244
- def diag_angles_radians(self) -> Tuple[value.TParamVal, ...]:
230
+ def diag_angles_radians(self) -> tuple[value.TParamVal, ...]:
245
231
  return self._diag_angles_radians
246
232
 
247
233
  def _is_parameterized_(self) -> bool:
@@ -380,7 +366,7 @@ class ThreeQubitDiagonalGate(raw_types.Gate):
380
366
  }
381
367
  )
382
368
 
383
- def _json_dict_(self) -> Dict[str, Any]:
369
+ def _json_dict_(self) -> dict[str, Any]:
384
370
  return protocols.obj_to_dict_helper(self, attribute_names=["diag_angles_radians"])
385
371
 
386
372
  def __repr__(self) -> str:
@@ -411,7 +397,7 @@ class CCXPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
411
397
  $$
412
398
  """
413
399
 
414
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
400
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
415
401
  return [
416
402
  (0, linalg.block_diag(np.diag([1, 1, 1, 1, 1, 1]), np.array([[0.5, 0.5], [0.5, 0.5]]))),
417
403
  (
@@ -422,7 +408,7 @@ class CCXPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
422
408
  ),
423
409
  ]
424
410
 
425
- def _trace_distance_bound_(self) -> Optional[float]:
411
+ def _trace_distance_bound_(self) -> float | None:
426
412
  if self._is_parameterized_():
427
413
  return None
428
414
  return abs(np.sin(self._exponent * 0.5 * np.pi))
@@ -474,7 +460,7 @@ class CCXPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
474
460
  ('@', '@', 'X'), exponent=self._diagram_exponent(args), exponent_qubit_index=2
475
461
  )
476
462
 
477
- def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
463
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
478
464
  if self._exponent != 1:
479
465
  return None
480
466
 
@@ -501,11 +487,9 @@ class CCXPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
501
487
 
502
488
  def controlled(
503
489
  self,
504
- num_controls: Optional[int] = None,
505
- control_values: Optional[
506
- Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
507
- ] = None,
508
- control_qid_shape: Optional[Tuple[int, ...]] = None,
490
+ num_controls: int | None = None,
491
+ control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
492
+ control_qid_shape: tuple[int, ...] | None = None,
509
493
  ) -> raw_types.Gate:
510
494
  """Returns a controlled `XPowGate` with two additional controls.
511
495
 
@@ -653,7 +637,7 @@ class CSwapGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
653
637
  return protocols.CircuitDiagramInfo(('@', 'swap', 'swap'))
654
638
  return protocols.CircuitDiagramInfo(('@', '×', '×'))
655
639
 
656
- def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
640
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
657
641
  args.validate_version('2.0', '3.0')
658
642
  return args.format('cswap {0},{1},{2};\n', qubits[0], qubits[1], qubits[2])
659
643
 
@@ -676,11 +660,9 @@ class CSwapGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
676
660
 
677
661
  def controlled(
678
662
  self,
679
- num_controls: Optional[int] = None,
680
- control_values: Optional[
681
- Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
682
- ] = None,
683
- control_qid_shape: Optional[Tuple[int, ...]] = None,
663
+ num_controls: int | None = None,
664
+ control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
665
+ control_qid_shape: tuple[int, ...] | None = None,
684
666
  ) -> raw_types.Gate:
685
667
  """Returns a controlled `SWAP` with one additional control.
686
668
 
@@ -20,7 +20,7 @@ passed as a list.
20
20
 
21
21
  from __future__ import annotations
22
22
 
23
- from typing import AbstractSet, Any, Dict, Iterator, Optional, Sequence, Tuple, TYPE_CHECKING
23
+ from typing import AbstractSet, Any, Iterator, Sequence, TYPE_CHECKING
24
24
 
25
25
  import numpy as np
26
26
  import sympy
@@ -64,10 +64,10 @@ class TwoQubitDiagonalGate(raw_types.Gate):
64
64
  If these values are $(x_0, x_1, \ldots , x_3)$ then the unitary
65
65
  has diagonal values $(e^{i x_0}, e^{i x_1}, \ldots, e^{i x_3})$.
66
66
  """
67
- self._diag_angles_radians: Tuple[value.TParamVal, ...] = tuple(diag_angles_radians)
67
+ self._diag_angles_radians: tuple[value.TParamVal, ...] = tuple(diag_angles_radians)
68
68
 
69
69
  @property
70
- def diag_angles_radians(self) -> Tuple[value.TParamVal, ...]:
70
+ def diag_angles_radians(self) -> tuple[value.TParamVal, ...]:
71
71
  return self._diag_angles_radians
72
72
 
73
73
  def _num_qubits_(self) -> int:
@@ -91,7 +91,7 @@ class TwoQubitDiagonalGate(raw_types.Gate):
91
91
  def _has_unitary_(self) -> bool:
92
92
  return not self._is_parameterized_()
93
93
 
94
- def _unitary_(self) -> Optional[np.ndarray]:
94
+ def _unitary_(self) -> np.ndarray | None:
95
95
  if self._is_parameterized_():
96
96
  return None
97
97
  return np.diag([np.exp(1j * angle) for angle in self._diag_angles_radians])
@@ -139,5 +139,5 @@ class TwoQubitDiagonalGate(raw_types.Gate):
139
139
  angles = ','.join(proper_repr(angle) for angle in self._diag_angles_radians)
140
140
  return f'cirq.TwoQubitDiagonalGate([{angles}])'
141
141
 
142
- def _json_dict_(self) -> Dict[str, Any]:
142
+ def _json_dict_(self) -> dict[str, Any]:
143
143
  return protocols.obj_to_dict_helper(self, attribute_names=["diag_angles_radians"])
@@ -14,7 +14,7 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import Any, Dict, Iterator, Sequence, TYPE_CHECKING
17
+ from typing import Any, Iterator, Sequence, TYPE_CHECKING
18
18
 
19
19
  import numpy as np
20
20
 
@@ -115,7 +115,7 @@ class UniformSuperpositionGate(raw_types.Gate):
115
115
  def __repr__(self) -> str:
116
116
  return f'UniformSuperpositionGate(m_value={self._m_value}, num_qubits={self._num_qubits})'
117
117
 
118
- def _json_dict_(self) -> Dict[str, Any]:
118
+ def _json_dict_(self) -> dict[str, Any]:
119
119
  d = {}
120
120
  d['m_value'] = self._m_value
121
121
  d['num_qubits'] = self._num_qubits
cirq/ops/wait_gate.py CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import AbstractSet, Any, Dict, Optional, Tuple, TYPE_CHECKING
17
+ from typing import AbstractSet, Any, TYPE_CHECKING
18
18
 
19
19
  from cirq import protocols, value
20
20
  from cirq.ops import raw_types
@@ -34,8 +34,8 @@ class WaitGate(raw_types.Gate):
34
34
  def __init__(
35
35
  self,
36
36
  duration: cirq.DURATION_LIKE,
37
- num_qubits: Optional[int] = None,
38
- qid_shape: Optional[Tuple[int, ...]] = None,
37
+ num_qubits: int | None = None,
38
+ qid_shape: tuple[int, ...] | None = None,
39
39
  ) -> None:
40
40
  """Initialize a wait gate with the given duration.
41
41
 
@@ -84,7 +84,7 @@ class WaitGate(raw_types.Gate):
84
84
  qid_shape=self._qid_shape,
85
85
  )
86
86
 
87
- def _qid_shape_(self) -> Tuple[int, ...]:
87
+ def _qid_shape_(self) -> tuple[int, ...]:
88
88
  return self._qid_shape
89
89
 
90
90
  def _has_unitary_(self) -> bool:
@@ -114,7 +114,7 @@ class WaitGate(raw_types.Gate):
114
114
  def __repr__(self) -> str:
115
115
  return f'cirq.WaitGate({repr(self.duration)})'
116
116
 
117
- def _json_dict_(self) -> Dict[str, Any]:
117
+ def _json_dict_(self) -> dict[str, Any]:
118
118
  d = protocols.obj_to_dict_helper(self, ['duration'])
119
119
  if len(self._qid_shape) != 1:
120
120
  d['num_qubits'] = len(self._qid_shape)
@@ -14,7 +14,7 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import Any, Sequence, Tuple
17
+ from typing import Any, Sequence
18
18
 
19
19
  import numpy as np
20
20
  import pytest
@@ -65,7 +65,7 @@ def test_act_on_fallback_errors() -> None:
65
65
  def test_act_on_errors() -> None:
66
66
  class Op(cirq.Operation):
67
67
  @property
68
- def qubits(self) -> Tuple[cirq.Qid, ...]: # type: ignore[empty-body]
68
+ def qubits(self) -> tuple[cirq.Qid, ...]: # type: ignore[empty-body]
69
69
  pass
70
70
 
71
71
  def with_qubits(self, *new_qubits: cirq.Qid) -> Self: # type: ignore[empty-body]
@@ -82,7 +82,7 @@ def test_act_on_errors() -> None:
82
82
  def test_qubits_not_allowed_for_operations() -> None:
83
83
  class Op(cirq.Operation):
84
84
  @property
85
- def qubits(self) -> Tuple[cirq.Qid, ...]: # type: ignore[empty-body]
85
+ def qubits(self) -> tuple[cirq.Qid, ...]: # type: ignore[empty-body]
86
86
  pass
87
87
 
88
88
  def with_qubits(self, *new_qubits: cirq.Qid) -> Self: # type: ignore[empty-body]
@@ -17,7 +17,7 @@
17
17
  from __future__ import annotations
18
18
 
19
19
  from types import NotImplementedType
20
- from typing import Any, Iterable, Optional, Sequence, Tuple, TypeVar, Union
20
+ from typing import Any, Iterable, Sequence, TypeVar
21
21
 
22
22
  import numpy as np
23
23
  from typing_extensions import Protocol
@@ -126,9 +126,7 @@ class SupportsApplyChannel(Protocol):
126
126
  """An object that can efficiently implement a channel."""
127
127
 
128
128
  @doc_private
129
- def _apply_channel_(
130
- self, args: ApplyChannelArgs
131
- ) -> Union[np.ndarray, None, NotImplementedType]:
129
+ def _apply_channel_(self, args: ApplyChannelArgs) -> np.ndarray | None | NotImplementedType:
132
130
  """Efficiently applies a channel.
133
131
 
134
132
  This method is given both the target tensor and workspace of the same
@@ -168,10 +166,8 @@ class SupportsApplyChannel(Protocol):
168
166
 
169
167
 
170
168
  def apply_channel(
171
- val: Any,
172
- args: ApplyChannelArgs,
173
- default: Union[np.ndarray, TDefault] = RaiseTypeErrorIfNotProvided,
174
- ) -> Union[np.ndarray, TDefault]:
169
+ val: Any, args: ApplyChannelArgs, default: np.ndarray | TDefault = RaiseTypeErrorIfNotProvided
170
+ ) -> np.ndarray | TDefault:
175
171
  """High performance evolution under a channel evolution.
176
172
 
177
173
  If `val` defines an `_apply_channel_` method, that method will be
@@ -275,7 +271,7 @@ def apply_channel(
275
271
  )
276
272
 
277
273
 
278
- def _apply_unitary(val: Any, args: ApplyChannelArgs) -> Optional[np.ndarray]:
274
+ def _apply_unitary(val: Any, args: 'ApplyChannelArgs') -> np.ndarray | None:
279
275
  """Attempt to use `apply_unitary` and return the result.
280
276
 
281
277
  If `val` does not support `apply_unitary` returns None.
@@ -298,9 +294,7 @@ def _apply_unitary(val: Any, args: ApplyChannelArgs) -> Optional[np.ndarray]:
298
294
  return right_result
299
295
 
300
296
 
301
- def _apply_kraus(
302
- kraus: Union[Tuple[np.ndarray], Sequence[Any]], args: ApplyChannelArgs
303
- ) -> np.ndarray:
297
+ def _apply_kraus(kraus: tuple[np.ndarray] | Sequence[Any], args: 'ApplyChannelArgs') -> np.ndarray:
304
298
  """Directly apply the kraus operators to the target tensor."""
305
299
  # Initialize output.
306
300
  args.out_buffer[:] = 0
@@ -315,7 +309,7 @@ def _apply_kraus(
315
309
 
316
310
 
317
311
  def _apply_kraus_single_qubit(
318
- kraus: Union[Tuple[Any], Sequence[Any]], args: ApplyChannelArgs
312
+ kraus: tuple[Any] | Sequence[Any], args: 'ApplyChannelArgs'
319
313
  ) -> np.ndarray:
320
314
  """Use slicing to apply single qubit channel. Only for two-level qubits."""
321
315
  zero_left = linalg.slice_for_qubits_equal_to(args.left_axes, 0)
@@ -340,7 +334,7 @@ def _apply_kraus_single_qubit(
340
334
 
341
335
 
342
336
  def _apply_kraus_multi_qubit(
343
- kraus: Union[Tuple[Any], Sequence[Any]], args: ApplyChannelArgs
337
+ kraus: tuple[Any] | Sequence[Any], args: 'ApplyChannelArgs'
344
338
  ) -> np.ndarray:
345
339
  """Use numpy's einsum to apply a multi-qubit channel."""
346
340
  qid_shape = tuple(args.target_tensor.shape[i] for i in args.left_axes)
@@ -17,7 +17,7 @@
17
17
  from __future__ import annotations
18
18
 
19
19
  from types import NotImplementedType
20
- from typing import Any, cast, Iterable, Optional, Tuple, TypeVar, Union
20
+ from typing import Any, cast, Iterable, TypeVar
21
21
 
22
22
  import numpy as np
23
23
  from typing_extensions import Protocol
@@ -75,7 +75,7 @@ class ApplyMixtureArgs:
75
75
  auxiliary_buffer0: np.ndarray,
76
76
  auxiliary_buffer1: np.ndarray,
77
77
  left_axes: Iterable[int],
78
- right_axes: Optional[Iterable[int]] = None,
78
+ right_axes: Iterable[int] | None = None,
79
79
  ):
80
80
  """Args for apply mixture.
81
81
 
@@ -114,9 +114,7 @@ class SupportsApplyMixture(Protocol):
114
114
  """An object that can efficiently implement a mixture."""
115
115
 
116
116
  @doc_private
117
- def _apply_mixture_(
118
- self, args: ApplyMixtureArgs
119
- ) -> Union[np.ndarray, None, NotImplementedType]:
117
+ def _apply_mixture_(self, args: ApplyMixtureArgs) -> np.ndarray | None | NotImplementedType:
120
118
  """Efficiently applies a mixture.
121
119
 
122
120
  This method is given both the target tensor and workspace of the same
@@ -159,8 +157,8 @@ def apply_mixture(
159
157
  val: Any,
160
158
  args: ApplyMixtureArgs,
161
159
  *,
162
- default: Union[np.ndarray, TDefault] = RaiseTypeErrorIfNotProvided,
163
- ) -> Union[np.ndarray, TDefault]:
160
+ default: np.ndarray | TDefault = RaiseTypeErrorIfNotProvided,
161
+ ) -> np.ndarray | TDefault:
164
162
  """High performance evolution under a mixture of unitaries evolution.
165
163
 
166
164
  Follows the steps below to attempt to apply a mixture:
@@ -275,7 +273,7 @@ def apply_mixture(
275
273
  )
276
274
 
277
275
 
278
- def _validate_input(val: Any, args: ApplyMixtureArgs) -> Tuple[Any, ApplyMixtureArgs, bool]:
276
+ def _validate_input(val: Any, args: 'ApplyMixtureArgs') -> tuple[Any, 'ApplyMixtureArgs', bool]:
279
277
  """Validate args input and determine if we are operating on a
280
278
  density matrix or a state vector.
281
279
  """
@@ -305,8 +303,8 @@ def _validate_input(val: Any, args: ApplyMixtureArgs) -> Tuple[Any, ApplyMixture
305
303
 
306
304
 
307
305
  def _apply_unitary_strat(
308
- val: Any, args: ApplyMixtureArgs, is_density_matrix: bool
309
- ) -> Optional[np.ndarray]:
306
+ val: Any, args: 'ApplyMixtureArgs', is_density_matrix: bool
307
+ ) -> np.ndarray | None:
310
308
  """Attempt to use `apply_unitary` and return the result.
311
309
 
312
310
  If `val` does not support `apply_unitary` returns None.
@@ -327,7 +325,7 @@ def _apply_unitary_strat(
327
325
  right_args = ApplyUnitaryArgs(
328
326
  target_tensor=np.conjugate(left_result),
329
327
  available_buffer=args.auxiliary_buffer0,
330
- axes=cast(Tuple[int], args.right_axes),
328
+ axes=cast(tuple[int], args.right_axes),
331
329
  )
332
330
  right_result = apply_unitary(val, right_args)
333
331
  np.conjugate(right_result, out=right_result)
@@ -335,8 +333,8 @@ def _apply_unitary_strat(
335
333
 
336
334
 
337
335
  def _apply_unitary_from_matrix_strat(
338
- val: np.ndarray, args: ApplyMixtureArgs, is_density_matrix: bool
339
- ) -> Optional[np.ndarray]:
336
+ val: np.ndarray, args: 'ApplyMixtureArgs', is_density_matrix: bool
337
+ ) -> np.ndarray | None:
340
338
  """Used to enact mixture tuples that are given as (probability, np.ndarray)
341
339
 
342
340
  If `val` does not support `apply_unitary` returns None.
@@ -354,15 +352,15 @@ def _apply_unitary_from_matrix_strat(
354
352
  linalg.targeted_left_multiply(
355
353
  np.conjugate(matrix_tensor),
356
354
  args.auxiliary_buffer0,
357
- cast(Tuple[int], args.right_axes),
355
+ cast(tuple[int], args.right_axes),
358
356
  out=args.target_tensor,
359
357
  )
360
358
  return args.target_tensor
361
359
 
362
360
 
363
361
  def _apply_mixture_from_mixture_strat(
364
- val: Any, args: ApplyMixtureArgs, is_density_matrix: bool
365
- ) -> Optional[np.ndarray]:
362
+ val: Any, args: 'ApplyMixtureArgs', is_density_matrix: bool
363
+ ) -> np.ndarray | None:
366
364
  """Attempt to use unitary matrices in _mixture_ and return the result."""
367
365
  method = getattr(val, '_mixture_', None)
368
366
  if method is None:
@@ -11,10 +11,9 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
-
15
14
  from __future__ import annotations
16
15
 
17
- from typing import Any, cast, Iterable, Optional, Tuple
16
+ from typing import Any, cast, Iterable
18
17
 
19
18
  import numpy as np
20
19
  import pytest
@@ -34,9 +33,9 @@ def assert_apply_mixture_returns(
34
33
  val: Any,
35
34
  rho: np.ndarray,
36
35
  left_axes: Iterable[int],
37
- right_axes: Optional[Iterable[int]],
36
+ right_axes: Iterable[int] | None,
38
37
  assert_result_is_out_buf: bool = False,
39
- expected_result: Optional[np.ndarray] = None,
38
+ expected_result: np.ndarray | None = None,
40
39
  ):
41
40
  out_buf, buf0, buf1 = make_buffers(rho.shape, rho.dtype)
42
41
  result = cirq.apply_mixture(
@@ -97,8 +96,8 @@ def test_apply_mixture_simple():
97
96
  def _apply_mixture_(self, args: cirq.ApplyMixtureArgs):
98
97
  zero_left = cirq.slice_for_qubits_equal_to(args.left_axes, 0)
99
98
  one_left = cirq.slice_for_qubits_equal_to(args.left_axes, 1)
100
- zero_right = cirq.slice_for_qubits_equal_to(cast(Tuple[int], args.right_axes), 0)
101
- one_right = cirq.slice_for_qubits_equal_to(cast(Tuple[int], args.right_axes), 1)
99
+ zero_right = cirq.slice_for_qubits_equal_to(cast(tuple[int], args.right_axes), 0)
100
+ one_right = cirq.slice_for_qubits_equal_to(cast(tuple[int], args.right_axes), 1)
102
101
  args.out_buffer[:] = 0
103
102
  np.copyto(dst=args.auxiliary_buffer0, src=args.target_tensor)
104
103
  for kraus_op in [np.sqrt(0.5) * np.eye(2, dtype=np.complex128), np.sqrt(0.5) * x]:
@@ -18,7 +18,7 @@ from __future__ import annotations
18
18
 
19
19
  import warnings
20
20
  from types import EllipsisType, NotImplementedType
21
- from typing import Any, cast, Iterable, Optional, Sequence, Tuple, TYPE_CHECKING, TypeVar, Union
21
+ from typing import Any, cast, Iterable, Sequence, TYPE_CHECKING, TypeVar
22
22
 
23
23
  import numpy as np
24
24
  from typing_extensions import Protocol
@@ -75,7 +75,7 @@ class ApplyUnitaryArgs:
75
75
  target_tensor: np.ndarray,
76
76
  available_buffer: np.ndarray,
77
77
  axes: Iterable[int],
78
- subspaces: Optional[Sequence[Tuple[int, ...]]] = None,
78
+ subspaces: Sequence[tuple[int, ...]] | None = None,
79
79
  ):
80
80
  """Inits ApplyUnitaryArgs.
81
81
 
@@ -113,7 +113,7 @@ class ApplyUnitaryArgs:
113
113
 
114
114
  @staticmethod
115
115
  def default(
116
- num_qubits: Optional[int] = None, *, qid_shape: Optional[Tuple[int, ...]] = None
116
+ num_qubits: int | None = None, *, qid_shape: tuple[int, ...] | None = None
117
117
  ) -> ApplyUnitaryArgs:
118
118
  """A default instance starting in state |0⟩.
119
119
 
@@ -132,14 +132,14 @@ class ApplyUnitaryArgs:
132
132
  raise TypeError('Specify exactly one of num_qubits or qid_shape.')
133
133
  if num_qubits is not None:
134
134
  qid_shape = (2,) * num_qubits
135
- qid_shape = cast(Tuple[int, ...], qid_shape) # Satisfy mypy
135
+ qid_shape = cast(tuple[int, ...], qid_shape) # Satisfy mypy
136
136
  num_qubits = len(qid_shape)
137
137
  state = qis.one_hot(index=(0,) * num_qubits, shape=qid_shape, dtype=np.complex128)
138
138
  return ApplyUnitaryArgs(state, np.empty_like(state), range(num_qubits))
139
139
 
140
140
  @classmethod
141
141
  def for_unitary(
142
- cls, num_qubits: Optional[int] = None, *, qid_shape: Optional[Tuple[int, ...]] = None
142
+ cls, num_qubits: int | None = None, *, qid_shape: tuple[int, ...] | None = None
143
143
  ) -> ApplyUnitaryArgs:
144
144
  """A default instance corresponding to an identity matrix.
145
145
 
@@ -159,7 +159,7 @@ class ApplyUnitaryArgs:
159
159
  raise TypeError('Specify exactly one of num_qubits or qid_shape.')
160
160
  if num_qubits is not None:
161
161
  qid_shape = (2,) * num_qubits
162
- qid_shape = cast(Tuple[int, ...], qid_shape) # Satisfy mypy
162
+ qid_shape = cast(tuple[int, ...], qid_shape) # Satisfy mypy
163
163
  num_qubits = len(qid_shape)
164
164
  state = qis.eye_tensor(qid_shape, dtype=np.complex128)
165
165
  return ApplyUnitaryArgs(state, np.empty_like(state), range(num_qubits))
@@ -182,7 +182,7 @@ class ApplyUnitaryArgs:
182
182
  return ApplyUnitaryArgs(target_tensor, available_buffer, range(len(self.axes)))
183
183
 
184
184
  def _for_operation_with_qid_shape(
185
- self, indices: Iterable[int], slices: Tuple[Union[int, slice], ...]
185
+ self, indices: Iterable[int], slices: tuple[int | slice, ...]
186
186
  ) -> ApplyUnitaryArgs:
187
187
  """Creates a sliced and transposed view of `self` appropriate for an
188
188
  operation with shape `qid_shape` on qubits with the given indices.
@@ -215,7 +215,7 @@ class ApplyUnitaryArgs:
215
215
 
216
216
  def subspace_index(
217
217
  self, little_endian_bits_int: int = 0, *, big_endian_bits_int: int = 0
218
- ) -> Tuple[Union[slice, int, EllipsisType], ...]:
218
+ ) -> tuple[slice | int | EllipsisType, ...]:
219
219
  """An index for the subspace where the target axes equal a value.
220
220
 
221
221
  Args:
@@ -260,9 +260,7 @@ class SupportsConsistentApplyUnitary(Protocol):
260
260
  """An object that can be efficiently left-multiplied into tensors."""
261
261
 
262
262
  @doc_private
263
- def _apply_unitary_(
264
- self, args: ApplyUnitaryArgs
265
- ) -> Union[np.ndarray, None, NotImplementedType]:
263
+ def _apply_unitary_(self, args: ApplyUnitaryArgs) -> np.ndarray | None | NotImplementedType:
266
264
  """Left-multiplies a unitary effect onto a tensor with good performance.
267
265
 
268
266
  This method is given both the target tensor and workspace of the same
@@ -308,10 +306,10 @@ class SupportsConsistentApplyUnitary(Protocol):
308
306
  def apply_unitary(
309
307
  unitary_value: Any,
310
308
  args: ApplyUnitaryArgs,
311
- default: Union[np.ndarray, TDefault] = RaiseTypeErrorIfNotProvided,
309
+ default: np.ndarray | TDefault = RaiseTypeErrorIfNotProvided,
312
310
  *,
313
311
  allow_decompose: bool = True,
314
- ) -> Union[np.ndarray, TDefault]:
312
+ ) -> np.ndarray | TDefault:
315
313
  """High performance left-multiplication of a unitary effect onto a tensor.
316
314
 
317
315
  Applies the unitary effect of `unitary_value` to the tensor specified in
@@ -422,7 +420,7 @@ def apply_unitary(
422
420
 
423
421
  def _strat_apply_unitary_from_apply_unitary(
424
422
  unitary_value: Any, args: ApplyUnitaryArgs
425
- ) -> Optional[np.ndarray]:
423
+ ) -> np.ndarray | None:
426
424
  # Check for magic method.
427
425
  func = getattr(unitary_value, '_apply_unitary_', None)
428
426
  if func is None:
@@ -470,7 +468,7 @@ def _apply_unitary_from_matrix(matrix: np.ndarray, unitary_value: Any, args: App
470
468
 
471
469
  def _strat_apply_unitary_from_unitary(
472
470
  unitary_value: Any, args: ApplyUnitaryArgs
473
- ) -> Optional[np.ndarray]:
471
+ ) -> np.ndarray | None:
474
472
  # Check for magic method.
475
473
  method = getattr(unitary_value, '_unitary_', None)
476
474
  if method is None:
@@ -484,7 +482,7 @@ def _strat_apply_unitary_from_unitary(
484
482
  return _apply_unitary_from_matrix(matrix, unitary_value, args)
485
483
 
486
484
 
487
- def _strat_apply_unitary_from_decompose(val: Any, args: ApplyUnitaryArgs) -> Optional[np.ndarray]:
485
+ def _strat_apply_unitary_from_decompose(val: Any, args: ApplyUnitaryArgs) -> np.ndarray | None:
488
486
  operations, qubits, _ = _try_decompose_into_operations_and_qubits(val)
489
487
  if operations is None:
490
488
  return NotImplemented
@@ -509,9 +507,9 @@ def _strat_apply_unitary_from_decompose(val: Any, args: ApplyUnitaryArgs) -> Opt
509
507
  def apply_unitaries(
510
508
  unitary_values: Iterable[Any],
511
509
  qubits: Sequence[cirq.Qid],
512
- args: Optional[ApplyUnitaryArgs] = None,
510
+ args: ApplyUnitaryArgs | None = None,
513
511
  default: Any = RaiseTypeErrorIfNotProvided,
514
- ) -> Optional[np.ndarray]:
512
+ ) -> np.ndarray | None:
515
513
  """Apply a series of unitaries onto a state tensor.
516
514
 
517
515
  Uses `cirq.apply_unitary` on each of the unitary values, to apply them to
@@ -647,7 +645,7 @@ def _incorporate_result_into_target(
647
645
  return args.target_tensor
648
646
 
649
647
 
650
- def _to_slice(subspace_def: Tuple[int, ...]):
648
+ def _to_slice(subspace_def: tuple[int, ...]):
651
649
  if len(subspace_def) < 1:
652
650
  raise ValueError(f'Subspace {subspace_def} has zero dimensions.')
653
651