cirq-core 1.6.0.dev20250520054601__py3-none-any.whl → 1.6.0.dev20250520181654__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 (289) 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/measurement_key.py +8 -8
  273. cirq/value/product_state.py +9 -9
  274. cirq/value/value_equality_attr.py +4 -4
  275. cirq/vis/heatmap.py +23 -35
  276. cirq/work/collector.py +9 -17
  277. cirq/work/observable_grouping.py +4 -7
  278. cirq/work/observable_measurement.py +29 -41
  279. cirq/work/observable_measurement_data.py +14 -14
  280. cirq/work/observable_measurement_test.py +2 -2
  281. cirq/work/observable_settings.py +9 -10
  282. cirq/work/pauli_sum_collector.py +5 -5
  283. cirq/work/sampler.py +17 -17
  284. cirq/work/zeros_sampler.py +3 -3
  285. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/METADATA +1 -1
  286. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/RECORD +289 -289
  287. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/WHEEL +1 -1
  288. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/licenses/LICENSE +0 -0
  289. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/top_level.txt +0 -0
@@ -15,7 +15,7 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import itertools
18
- from typing import List, Sequence, Tuple
18
+ from typing import Sequence
19
19
 
20
20
  import numpy as np
21
21
  import pytest
@@ -113,9 +113,9 @@ def test_valid_cphase_exponents(theta, phi):
113
113
  assert_decomposition_valid(cphase_gate, fsim_gate=fsim_gate)
114
114
 
115
115
 
116
- def complement_intervals(intervals: Sequence[Tuple[float, float]]) -> Sequence[Tuple[float, float]]:
116
+ def complement_intervals(intervals: Sequence[tuple[float, float]]) -> Sequence[tuple[float, float]]:
117
117
  """Computes complement of union of intervals in [0, 2]."""
118
- complements: List[Tuple[float, float]] = []
118
+ complements: list[tuple[float, float]] = []
119
119
  a = 0.0
120
120
  for b, c in intervals:
121
121
  complements.append((a, b))
@@ -14,7 +14,7 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import cast, Optional, Tuple
17
+ from typing import cast
18
18
 
19
19
  import numpy as np
20
20
  import numpy.typing as npt
@@ -23,7 +23,7 @@ from cirq import protocols
23
23
  from cirq.ops import DensePauliString
24
24
 
25
25
 
26
- def _argmax(V: npt.NDArray) -> Tuple[int, float]:
26
+ def _argmax(V: npt.NDArray) -> tuple[int, float]:
27
27
  """Returns a tuple (index of max number, max number)."""
28
28
  V = (V * V.conj()).real
29
29
  idx_max = np.argmax(V)
@@ -62,7 +62,7 @@ def _conjugate_with_hadamard(U: npt.NDArray) -> npt.NDArray:
62
62
  return U
63
63
 
64
64
 
65
- def unitary_to_pauli_string(U: npt.NDArray, eps: float = 1e-15) -> Optional[DensePauliString]:
65
+ def unitary_to_pauli_string(U: npt.NDArray, eps: float = 1e-15) -> DensePauliString | None:
66
66
  """Attempts to find a pauli string (with possible phase) equivalent to U up to eps.
67
67
 
68
68
  Based on this answer https://shorturl.at/aA079.
@@ -21,7 +21,7 @@ https://arxiv.org/abs/quant-ph/0406176
21
21
 
22
22
  from __future__ import annotations
23
23
 
24
- from typing import Callable, Iterable, List, TYPE_CHECKING
24
+ from typing import Callable, Iterable, TYPE_CHECKING
25
25
 
26
26
  import numpy as np
27
27
  from scipy.linalg import cossin
@@ -42,7 +42,7 @@ if TYPE_CHECKING:
42
42
 
43
43
 
44
44
  def quantum_shannon_decomposition(
45
- qubits: List[cirq.Qid], u: np.ndarray, atol: float = 1e-8
45
+ qubits: list[cirq.Qid], u: np.ndarray, atol: float = 1e-8
46
46
  ) -> Iterable[cirq.Operation]:
47
47
  """Decomposes n-qubit unitary 1-q, 2-q and GlobalPhase gates, preserving global phase.
48
48
 
@@ -185,7 +185,7 @@ def _single_qubit_decomposition(qubit: cirq.Qid, u: np.ndarray) -> Iterable[cirq
185
185
 
186
186
 
187
187
  def _msb_demuxer(
188
- demux_qubits: List[cirq.Qid], u1: np.ndarray, u2: np.ndarray
188
+ demux_qubits: list[cirq.Qid], u1: np.ndarray, u2: np.ndarray
189
189
  ) -> Iterable[cirq.Operation]:
190
190
  """Demultiplexes a unitary matrix that is multiplexed in its most-significant-qubit.
191
191
 
@@ -248,7 +248,7 @@ def _nth_gray(n: int) -> int:
248
248
 
249
249
 
250
250
  def _multiplexed_cossin(
251
- cossin_qubits: List[cirq.Qid], angles: List[float], rot_func: Callable = ops.ry
251
+ cossin_qubits: list[cirq.Qid], angles: list[float], rot_func: Callable = ops.ry
252
252
  ) -> Iterable[cirq.Operation]:
253
253
  """Performs a multiplexed rotation over all qubits in this unitary matrix,
254
254
 
@@ -17,7 +17,6 @@
17
17
  from __future__ import annotations
18
18
 
19
19
  import math
20
- from typing import List, Optional, Tuple
21
20
 
22
21
  import numpy as np
23
22
  import sympy
@@ -41,7 +40,7 @@ def _signed_mod_1(x: float) -> float:
41
40
 
42
41
  def single_qubit_matrix_to_pauli_rotations(
43
42
  mat: np.ndarray, atol: float = 0
44
- ) -> List[Tuple[ops.Pauli, float]]:
43
+ ) -> list[tuple[ops.Pauli, float]]:
45
44
  """Implements a single-qubit operation with few rotations.
46
45
 
47
46
  Args:
@@ -100,7 +99,7 @@ def single_qubit_matrix_to_pauli_rotations(
100
99
  return [(pauli, ht) for pauli, ht in rotation_list if not is_no_turn(ht)]
101
100
 
102
101
 
103
- def single_qubit_matrix_to_gates(mat: np.ndarray, tolerance: float = 0) -> List[ops.Gate]:
102
+ def single_qubit_matrix_to_gates(mat: np.ndarray, tolerance: float = 0) -> list[ops.Gate]:
104
103
  """Implements a single-qubit operation with few gates.
105
104
 
106
105
  Args:
@@ -116,7 +115,7 @@ def single_qubit_matrix_to_gates(mat: np.ndarray, tolerance: float = 0) -> List[
116
115
  return [pauli**ht for pauli, ht in rotations]
117
116
 
118
117
 
119
- def single_qubit_op_to_framed_phase_form(mat: np.ndarray) -> Tuple[np.ndarray, complex, complex]:
118
+ def single_qubit_op_to_framed_phase_form(mat: np.ndarray) -> tuple[np.ndarray, complex, complex]:
120
119
  """Decomposes a 2x2 unitary M into U^-1 * diag(1, r) * U * diag(g, g).
121
120
 
122
121
  U translates the rotation axis of M to the Z axis.
@@ -143,7 +142,7 @@ def single_qubit_op_to_framed_phase_form(mat: np.ndarray) -> Tuple[np.ndarray, c
143
142
  return u, r, g
144
143
 
145
144
 
146
- def _deconstruct_single_qubit_matrix_into_gate_turns(mat: np.ndarray) -> Tuple[float, float, float]:
145
+ def _deconstruct_single_qubit_matrix_into_gate_turns(mat: np.ndarray) -> tuple[float, float, float]:
147
146
  """Breaks down a 2x2 unitary into gate parameters.
148
147
 
149
148
  Args:
@@ -167,7 +166,7 @@ def _deconstruct_single_qubit_matrix_into_gate_turns(mat: np.ndarray) -> Tuple[f
167
166
  return (_signed_mod_1(xy_turn), _signed_mod_1(xy_phase_turn), _signed_mod_1(total_z_turn))
168
167
 
169
168
 
170
- def single_qubit_matrix_to_phased_x_z(mat: np.ndarray, atol: float = 0) -> List[ops.Gate]:
169
+ def single_qubit_matrix_to_phased_x_z(mat: np.ndarray, atol: float = 0) -> list[ops.Gate]:
171
170
  """Implements a single-qubit operation with a PhasedX and Z gate.
172
171
 
173
172
  If one of the gates isn't needed, it will be omitted.
@@ -198,7 +197,7 @@ def single_qubit_matrix_to_phased_x_z(mat: np.ndarray, atol: float = 0) -> List[
198
197
  return result
199
198
 
200
199
 
201
- def single_qubit_matrix_to_phxz(mat: np.ndarray, atol: float = 0) -> Optional[ops.PhasedXZGate]:
200
+ def single_qubit_matrix_to_phxz(mat: np.ndarray, atol: float = 0) -> ops.PhasedXZGate | None:
202
201
  """Implements a single-qubit operation with a PhasedXZ gate.
203
202
 
204
203
  Under the hood, this uses deconstruct_single_qubit_matrix_into_angles which
@@ -16,7 +16,7 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- from typing import List, TYPE_CHECKING
19
+ from typing import TYPE_CHECKING
20
20
 
21
21
  import numpy as np
22
22
 
@@ -34,7 +34,7 @@ def two_qubit_matrix_to_cz_isometry(
34
34
  allow_partial_czs: bool = False,
35
35
  atol: float = 1e-8,
36
36
  clean_operations: bool = True,
37
- ) -> List[cirq.Operation]:
37
+ ) -> list[cirq.Operation]:
38
38
  """Decomposes a 2q operation into at-most 2 CZs + 1q rotations; assuming `q0` is initially |0>.
39
39
 
40
40
  The method implements isometry from one to two qubits; assuming qubit `q0` is always in the |0>
@@ -16,7 +16,7 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- from typing import List, Optional, Sequence, Tuple, Union
19
+ from typing import Sequence
20
20
 
21
21
  import numpy as np
22
22
 
@@ -26,7 +26,7 @@ from cirq import ops, transformers as opt
26
26
 
27
27
  def three_qubit_matrix_to_operations(
28
28
  q0: ops.Qid, q1: ops.Qid, q2: ops.Qid, u: np.ndarray, atol: float = 1e-8
29
- ) -> List[ops.Operation]:
29
+ ) -> list[ops.Operation]:
30
30
  """Returns operations for a 3 qubit unitary.
31
31
 
32
32
  The algorithm is described in Shende et al.:
@@ -87,7 +87,7 @@ def three_qubit_matrix_to_operations(
87
87
  return list(cirq.Circuit(vdh_ops + cs_ops + ud_ops).all_operations())
88
88
 
89
89
 
90
- def _cs_to_ops(q0: ops.Qid, q1: ops.Qid, q2: ops.Qid, theta: np.ndarray) -> List[ops.Operation]:
90
+ def _cs_to_ops(q0: ops.Qid, q1: ops.Qid, q2: ops.Qid, theta: np.ndarray) -> list[ops.Operation]:
91
91
  """Converts theta angles based Cosine Sine matrix to operations.
92
92
 
93
93
  Using the optimization as per Appendix A.1, it uses CZ gates instead of
@@ -126,9 +126,9 @@ def _two_qubit_multiplexor_to_ops(
126
126
  u1: np.ndarray,
127
127
  u2: np.ndarray,
128
128
  shift_left: bool = True,
129
- diagonal: Optional[np.ndarray] = None,
129
+ diagonal: np.ndarray | None = None,
130
130
  atol: float = 1e-8,
131
- ) -> Tuple[Optional[np.ndarray], List[ops.Operation]]:
131
+ ) -> tuple[np.ndarray | None, list[ops.Operation]]:
132
132
  r"""Converts a two qubit double multiplexor to circuit.
133
133
  Input: U_1 ⊕ U_2, with select qubit a (i.e. a = |0> => U_1(b,c),
134
134
  a = |1> => U_2(b,c).
@@ -187,7 +187,7 @@ def _two_qubit_multiplexor_to_ops(
187
187
 
188
188
  w = d_v @ w
189
189
 
190
- d_w: Optional[np.ndarray]
190
+ d_w: np.ndarray | None
191
191
 
192
192
  # if it's interesting to extract the diagonal then let's do it
193
193
  if shift_left:
@@ -260,7 +260,7 @@ def _middle_multiplexor_to_ops(q0: ops.Qid, q1: ops.Qid, q2: ops.Qid, eigvals: n
260
260
  return _optimize_multiplexed_angles_circuit(ops)
261
261
 
262
262
 
263
- def _multiplexed_angles(theta: Union[Sequence[float], np.ndarray]) -> np.ndarray:
263
+ def _multiplexed_angles(theta: Sequence[float] | np.ndarray) -> np.ndarray:
264
264
  """Calculates the angles for a 4-way multiplexed rotation.
265
265
 
266
266
  For example, if we want rz(theta[i]) if the select qubits are in state
@@ -16,7 +16,7 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- from typing import List, TYPE_CHECKING
19
+ from typing import TYPE_CHECKING
20
20
 
21
21
  import numpy as np
22
22
 
@@ -41,7 +41,7 @@ def _1q_matrices_to_ops(g0, g1, q0, q1, include_identity=False):
41
41
 
42
42
  def prepare_two_qubit_state_using_sqrt_iswap(
43
43
  q0: cirq.Qid, q1: cirq.Qid, state: cirq.STATE_VECTOR_LIKE, *, use_sqrt_iswap_inv: bool = True
44
- ) -> List[cirq.Operation]:
44
+ ) -> list[cirq.Operation]:
45
45
  """Prepares the given 2q state from |00> using at-most 1 √iSWAP gate + single qubit rotations.
46
46
 
47
47
  Entangled states are prepared using exactly 1 √iSWAP gate while product states are prepared
@@ -76,7 +76,7 @@ def prepare_two_qubit_state_using_sqrt_iswap(
76
76
 
77
77
  def prepare_two_qubit_state_using_cz(
78
78
  q0: cirq.Qid, q1: cirq.Qid, state: cirq.STATE_VECTOR_LIKE
79
- ) -> List[cirq.Operation]:
79
+ ) -> list[cirq.Operation]:
80
80
  """Prepares the given 2q state from |00> using at-most 1 CZ gate + single qubit rotations.
81
81
 
82
82
  Entangled states are prepared using exactly 1 CZ gate while product states are prepared
@@ -109,7 +109,7 @@ def prepare_two_qubit_state_using_cz(
109
109
 
110
110
  def prepare_two_qubit_state_using_iswap(
111
111
  q0: cirq.Qid, q1: cirq.Qid, state: cirq.STATE_VECTOR_LIKE, use_iswap_inv: bool = False
112
- ) -> List[cirq.Operation]:
112
+ ) -> list[cirq.Operation]:
113
113
  """Prepares the given 2q state from |00> using at-most 1 ISWAP gate + single qubit rotations.
114
114
 
115
115
  Entangled states are prepared using exactly 1 ISWAP gate while product states are prepared
@@ -16,7 +16,7 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- from typing import cast, Iterable, List, Optional, Sequence, Tuple, TYPE_CHECKING
19
+ from typing import cast, Iterable, Sequence, TYPE_CHECKING
20
20
 
21
21
  import numpy as np
22
22
 
@@ -34,7 +34,7 @@ if TYPE_CHECKING:
34
34
 
35
35
  def _remove_partial_czs_or_fail(
36
36
  operations: Iterable[cirq.Operation], atol: float
37
- ) -> List[cirq.Operation]:
37
+ ) -> list[cirq.Operation]:
38
38
  result = []
39
39
  for op in operations:
40
40
  if isinstance(op.gate, ops.CZPowGate):
@@ -57,7 +57,7 @@ def two_qubit_matrix_to_cz_operations(
57
57
  allow_partial_czs: bool,
58
58
  atol: float = 1e-8,
59
59
  clean_operations: bool = True,
60
- ) -> List[ops.Operation]:
60
+ ) -> list[ops.Operation]:
61
61
  """Decomposes a two-qubit operation into Z/XY/CZ gates.
62
62
 
63
63
  Args:
@@ -93,7 +93,7 @@ def two_qubit_matrix_to_diagonal_and_cz_operations(
93
93
  allow_partial_czs: bool = False,
94
94
  atol: float = 1e-8,
95
95
  clean_operations: bool = True,
96
- ) -> Tuple[np.ndarray, List[cirq.Operation]]:
96
+ ) -> tuple[np.ndarray, list[cirq.Operation]]:
97
97
  """Decomposes a 2-qubit unitary to a diagonal and the remaining operations.
98
98
 
99
99
  For a 2-qubit unitary V, return ops, a list of operations and
@@ -197,7 +197,7 @@ def _kak_decomposition_to_operations(
197
197
  kak: linalg.KakDecomposition,
198
198
  allow_partial_czs: bool,
199
199
  atol: float = 1e-8,
200
- ) -> List[ops.Operation]:
200
+ ) -> list[ops.Operation]:
201
201
  """Assumes that the decomposition is canonical."""
202
202
  b0, b1 = kak.single_qubit_operations_before
203
203
  pre = [_do_single_on(b0, q0, atol=atol), _do_single_on(b1, q1, atol=atol)]
@@ -232,7 +232,7 @@ def _is_trivial_angle(rad: float, atol: float) -> bool:
232
232
 
233
233
 
234
234
  def _parity_interaction(
235
- q0: cirq.Qid, q1: cirq.Qid, rads: float, atol: float, gate: Optional[ops.Gate] = None
235
+ q0: cirq.Qid, q1: cirq.Qid, rads: float, atol: float, gate: ops.Gate | None = None
236
236
  ):
237
237
  """Yields a ZZ interaction framed by the given operation."""
238
238
  if abs(rads) < atol:
@@ -263,7 +263,7 @@ def _do_single_on(u: np.ndarray, q: cirq.Qid, atol: float = 1e-8):
263
263
  def _non_local_part(
264
264
  q0: cirq.Qid,
265
265
  q1: cirq.Qid,
266
- interaction_coefficients: Tuple[float, float, float],
266
+ interaction_coefficients: tuple[float, float, float],
267
267
  allow_partial_czs: bool,
268
268
  atol: float = 1e-8,
269
269
  ):
@@ -16,7 +16,7 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- from typing import Iterable, Iterator, List, Optional, Sequence, TYPE_CHECKING, Union
19
+ from typing import Iterable, Iterator, Sequence, TYPE_CHECKING
20
20
 
21
21
  import numpy as np
22
22
 
@@ -27,10 +27,10 @@ if TYPE_CHECKING:
27
27
 
28
28
 
29
29
  def decompose_two_qubit_interaction_into_four_fsim_gates(
30
- interaction: Union[cirq.SupportsUnitary, np.ndarray],
30
+ interaction: cirq.SupportsUnitary | np.ndarray,
31
31
  *,
32
- fsim_gate: Union[cirq.FSimGate, cirq.ISwapPowGate],
33
- qubits: Optional[Sequence[cirq.Qid]] = None,
32
+ fsim_gate: cirq.FSimGate | cirq.ISwapPowGate,
33
+ qubits: Sequence[cirq.Qid] | None = None,
34
34
  ) -> cirq.Circuit:
35
35
  """Decomposes operations into an FSimGate near theta=pi/2, phi=0.
36
36
 
@@ -100,7 +100,7 @@ def decompose_two_qubit_interaction_into_four_fsim_gates(
100
100
  return result
101
101
 
102
102
 
103
- def _sticky_0_to_1(v: float, *, atol: float) -> Optional[float]:
103
+ def _sticky_0_to_1(v: float, *, atol: float) -> float | None:
104
104
  if 0 <= v <= 1:
105
105
  return v
106
106
  if 1 < v <= 1 + atol:
@@ -117,7 +117,7 @@ def _decompose_xx_yy_into_two_fsims_ignoring_single_qubit_ops(
117
117
  canonical_x_kak_coefficient: float,
118
118
  canonical_y_kak_coefficient: float,
119
119
  atol: float = 1e-8,
120
- ) -> List[cirq.Operation]:
120
+ ) -> list[cirq.Operation]:
121
121
  x = canonical_x_kak_coefficient
122
122
  y = canonical_y_kak_coefficient
123
123
  assert 0 <= y <= x <= np.pi / 4
@@ -176,10 +176,10 @@ _B = _BGate()
176
176
 
177
177
 
178
178
  def _decompose_two_qubit_interaction_into_two_b_gates(
179
- interaction: Union[cirq.SupportsUnitary, np.ndarray, cirq.KakDecomposition],
179
+ interaction: cirq.SupportsUnitary | np.ndarray | cirq.KakDecomposition,
180
180
  *,
181
181
  qubits: Sequence[cirq.Qid],
182
- ) -> List[cirq.Operation]:
182
+ ) -> list[cirq.Operation]:
183
183
  kak = linalg.kak_decomposition(interaction)
184
184
 
185
185
  result = _decompose_interaction_into_two_b_gates_ignoring_single_qubit_ops(
@@ -195,7 +195,7 @@ def _decompose_two_qubit_interaction_into_two_b_gates(
195
195
 
196
196
  def _decompose_b_gate_into_two_fsims(
197
197
  *, fsim_gate: cirq.FSimGate, qubits: Sequence[cirq.Qid]
198
- ) -> List[cirq.Operation]:
198
+ ) -> list[cirq.Operation]:
199
199
  kak = linalg.kak_decomposition(_B)
200
200
 
201
201
  result = _decompose_xx_yy_into_two_fsims_ignoring_single_qubit_ops(
@@ -214,7 +214,7 @@ def _decompose_b_gate_into_two_fsims(
214
214
 
215
215
  def _decompose_interaction_into_two_b_gates_ignoring_single_qubit_ops(
216
216
  qubits: Sequence[cirq.Qid], kak_interaction_coefficients: Iterable[float]
217
- ) -> List[cirq.Operation]:
217
+ ) -> list[cirq.Operation]:
218
218
  """Decompose using a minimal construction of two-qubit operations.
219
219
 
220
220
  References:
@@ -238,7 +238,7 @@ def _decompose_interaction_into_two_b_gates_ignoring_single_qubit_ops(
238
238
 
239
239
 
240
240
  def _fix_single_qubit_gates_around_kak_interaction(
241
- *, desired: cirq.KakDecomposition, operations: List[cirq.Operation], qubits: Sequence[cirq.Qid]
241
+ *, desired: cirq.KakDecomposition, operations: list[cirq.Operation], qubits: Sequence[cirq.Qid]
242
242
  ) -> Iterator[cirq.Operation]:
243
243
  """Adds single qubit operations to complete a desired interaction.
244
244
 
@@ -21,7 +21,7 @@ Gate compilation methods implemented here are following the paper below:
21
21
 
22
22
  from __future__ import annotations
23
23
 
24
- from typing import cast, Iterable, List, Optional, Tuple, TYPE_CHECKING
24
+ from typing import cast, Iterable, TYPE_CHECKING
25
25
 
26
26
  from cirq import linalg, ops, protocols
27
27
  from cirq.transformers.analytical_decompositions import single_qubit_decompositions, two_qubit_to_cz
@@ -34,7 +34,7 @@ if TYPE_CHECKING:
34
34
 
35
35
  def two_qubit_matrix_to_ion_operations(
36
36
  q0: cirq.Qid, q1: cirq.Qid, mat: np.ndarray, atol: float = 1e-8, clean_operations: bool = True
37
- ) -> List[ops.Operation]:
37
+ ) -> list[ops.Operation]:
38
38
  """Decomposes a two-qubit operation into MS/single-qubit rotation gates.
39
39
 
40
40
  Args:
@@ -55,7 +55,7 @@ def two_qubit_matrix_to_ion_operations(
55
55
 
56
56
  def _kak_decomposition_to_operations(
57
57
  q0: cirq.Qid, q1: cirq.Qid, kak: linalg.KakDecomposition, atol: float = 1e-8
58
- ) -> List[ops.Operation]:
58
+ ) -> list[ops.Operation]:
59
59
  """Assumes that the decomposition is canonical."""
60
60
  b0, b1 = kak.single_qubit_operations_before
61
61
  pre = [_do_single_on(b0, q0, atol), _do_single_on(b1, q1, atol)]
@@ -78,7 +78,7 @@ def _do_single_on(u: np.ndarray, q: cirq.Qid, atol: float = 1e-8):
78
78
 
79
79
 
80
80
  def _parity_interaction(
81
- q0: cirq.Qid, q1: cirq.Qid, rads: float, atol: float, gate: Optional[ops.Gate] = None
81
+ q0: cirq.Qid, q1: cirq.Qid, rads: float, atol: float, gate: ops.Gate | None = None
82
82
  ):
83
83
  """Yields an XX interaction framed by the given operation."""
84
84
 
@@ -98,7 +98,7 @@ def _parity_interaction(
98
98
  def _non_local_part(
99
99
  q0: cirq.Qid,
100
100
  q1: cirq.Qid,
101
- interaction_coefficients: Tuple[float, float, float],
101
+ interaction_coefficients: tuple[float, float, float],
102
102
  atol: float = 1e-8,
103
103
  ):
104
104
  """Yields non-local operation of KAK decomposition."""
@@ -22,7 +22,7 @@ References:
22
22
 
23
23
  from __future__ import annotations
24
24
 
25
- from typing import Optional, Sequence, Tuple, TYPE_CHECKING
25
+ from typing import Sequence, TYPE_CHECKING
26
26
 
27
27
  import numpy as np
28
28
  import sympy
@@ -233,7 +233,7 @@ def two_qubit_matrix_to_sqrt_iswap_operations(
233
233
  q1: cirq.Qid,
234
234
  mat: np.ndarray,
235
235
  *,
236
- required_sqrt_iswap_count: Optional[int] = None,
236
+ required_sqrt_iswap_count: int | None = None,
237
237
  use_sqrt_iswap_inv: bool = False,
238
238
  atol: float = 1e-8,
239
239
  check_preconditions: bool = True,
@@ -303,7 +303,7 @@ def _kak_decomposition_to_sqrt_iswap_operations(
303
303
  q0: cirq.Qid,
304
304
  q1: cirq.Qid,
305
305
  kak: linalg.KakDecomposition,
306
- required_sqrt_iswap_count: Optional[int] = None,
306
+ required_sqrt_iswap_count: int | None = None,
307
307
  use_sqrt_iswap_inv: bool = False,
308
308
  atol: float = 1e-8,
309
309
  ) -> Sequence[cirq.Operation]:
@@ -328,7 +328,7 @@ def _decomp_to_operations(
328
328
  q0: cirq.Qid,
329
329
  q1: cirq.Qid,
330
330
  two_qubit_gate: cirq.Gate,
331
- single_qubit_operations: Sequence[Tuple[np.ndarray, np.ndarray]],
331
+ single_qubit_operations: Sequence[tuple[np.ndarray, np.ndarray]],
332
332
  u0_before: np.ndarray = np.eye(2),
333
333
  u0_after: np.ndarray = np.eye(2),
334
334
  atol: float = 1e-8,
@@ -401,8 +401,8 @@ def _decomp_to_operations(
401
401
 
402
402
 
403
403
  def _single_qubit_matrices_with_sqrt_iswap(
404
- kak: cirq.KakDecomposition, required_sqrt_iswap_count: Optional[int] = None, atol: float = 1e-8
405
- ) -> Tuple[Sequence[Tuple[np.ndarray, np.ndarray]], complex]:
404
+ kak: cirq.KakDecomposition, required_sqrt_iswap_count: int | None = None, atol: float = 1e-8
405
+ ) -> tuple[Sequence[tuple[np.ndarray, np.ndarray]], complex]:
406
406
  """Computes the sequence of interleaved single-qubit unitary matrices in the
407
407
  sqrt-iSWAP decomposition."""
408
408
  decomposers = [
@@ -428,7 +428,7 @@ def _single_qubit_matrices_with_sqrt_iswap(
428
428
 
429
429
 
430
430
  def _in_0_region(
431
- interaction_coefficients: Tuple[float, float, float], weyl_tol: float = 1e-8
431
+ interaction_coefficients: tuple[float, float, float], weyl_tol: float = 1e-8
432
432
  ) -> bool:
433
433
  """Tests if (x, y, z) ~= (0, 0, 0) assuming x, y, z are canonical."""
434
434
  x, y, z = interaction_coefficients
@@ -436,7 +436,7 @@ def _in_0_region(
436
436
 
437
437
 
438
438
  def _in_1sqrt_iswap_region(
439
- interaction_coefficients: Tuple[float, float, float], weyl_tol: float = 1e-8
439
+ interaction_coefficients: tuple[float, float, float], weyl_tol: float = 1e-8
440
440
  ) -> bool:
441
441
  """Tests if (x, y, z) ~= (π/8, π/8, 0), assuming x, y, z are canonical."""
442
442
  x, y, z = interaction_coefficients
@@ -444,7 +444,7 @@ def _in_1sqrt_iswap_region(
444
444
 
445
445
 
446
446
  def _in_2sqrt_iswap_region(
447
- interaction_coefficients: Tuple[float, float, float], weyl_tol: float = 1e-8
447
+ interaction_coefficients: tuple[float, float, float], weyl_tol: float = 1e-8
448
448
  ) -> bool:
449
449
  """Tests if (x, y, z) is inside or within weyl_tol of the volume
450
450
  x >= y + |z| assuming x, y, z are canonical.
@@ -461,7 +461,7 @@ def _in_2sqrt_iswap_region(
461
461
 
462
462
 
463
463
  def _in_3sqrt_iswap_region(
464
- interaction_coefficients: Tuple[float, float, float], weyl_tol: float = 1e-8
464
+ interaction_coefficients: tuple[float, float, float], weyl_tol: float = 1e-8
465
465
  ) -> bool:
466
466
  """Any two-qubit operation is decomposable into three SQRT_ISWAP gates.
467
467
 
@@ -475,7 +475,7 @@ def _in_3sqrt_iswap_region(
475
475
 
476
476
  def _decomp_0_matrices(
477
477
  kak: cirq.KakDecomposition, atol: float = 1e-8
478
- ) -> Tuple[Sequence[Tuple[np.ndarray, np.ndarray]], complex]:
478
+ ) -> tuple[Sequence[tuple[np.ndarray, np.ndarray]], complex]:
479
479
  """Returns the single-qubit matrices for the 0-SQRT_ISWAP decomposition.
480
480
 
481
481
  Assumes canonical x, y, z and (x, y, z) = (0, 0, 0) within tolerance.
@@ -493,7 +493,7 @@ def _decomp_0_matrices(
493
493
 
494
494
  def _decomp_1sqrt_iswap_matrices(
495
495
  kak: cirq.KakDecomposition, atol: float = 1e-8
496
- ) -> Tuple[Sequence[Tuple[np.ndarray, np.ndarray]], complex]:
496
+ ) -> tuple[Sequence[tuple[np.ndarray, np.ndarray]], complex]:
497
497
  """Returns the single-qubit matrices for the 1-SQRT_ISWAP decomposition.
498
498
 
499
499
  Assumes canonical x, y, z and (x, y, z) = (π/8, π/8, 0) within tolerance.
@@ -506,7 +506,7 @@ def _decomp_1sqrt_iswap_matrices(
506
506
 
507
507
  def _decomp_2sqrt_iswap_matrices(
508
508
  kak: cirq.KakDecomposition, atol: float = 1e-8
509
- ) -> Tuple[Sequence[Tuple[np.ndarray, np.ndarray]], complex]:
509
+ ) -> tuple[Sequence[tuple[np.ndarray, np.ndarray]], complex]:
510
510
  """Returns the single-qubit matrices for the 2-SQRT_ISWAP decomposition.
511
511
 
512
512
  Assumes canonical x, y, z and x >= y + |z| within tolerance. For x, y, z
@@ -569,7 +569,7 @@ def _decomp_2sqrt_iswap_matrices(
569
569
 
570
570
  def _decomp_3sqrt_iswap_matrices(
571
571
  kak: cirq.KakDecomposition, atol: float = 1e-8
572
- ) -> Tuple[Sequence[Tuple[np.ndarray, np.ndarray]], complex]:
572
+ ) -> tuple[Sequence[tuple[np.ndarray, np.ndarray]], complex]:
573
573
  """Returns the single-qubit matrices for the 3-SQRT_ISWAP decomposition.
574
574
 
575
575
  Assumes any canonical x, y, z. Three sqrt-iSWAP gates are only needed if
@@ -18,7 +18,7 @@ from __future__ import annotations
18
18
 
19
19
  from functools import reduce
20
20
  from itertools import cycle
21
- from typing import Dict, Optional, Tuple, TYPE_CHECKING, Union
21
+ from typing import TYPE_CHECKING
22
22
 
23
23
  import numpy as np
24
24
 
@@ -33,7 +33,7 @@ if TYPE_CHECKING:
33
33
  import cirq
34
34
 
35
35
 
36
- def _get_dd_sequence_from_schema_name(schema: str) -> Tuple[ops.Gate, ...]:
36
+ def _get_dd_sequence_from_schema_name(schema: str) -> tuple[ops.Gate, ...]:
37
37
  """Gets dynamical decoupling sequence from a schema name."""
38
38
  match schema:
39
39
  case 'DEFAULT':
@@ -50,14 +50,14 @@ def _get_dd_sequence_from_schema_name(schema: str) -> Tuple[ops.Gate, ...]:
50
50
  raise ValueError('Invalid schema name.')
51
51
 
52
52
 
53
- def _pauli_up_to_global_phase(gate: ops.Gate) -> Union[ops.Pauli, None]:
53
+ def _pauli_up_to_global_phase(gate: ops.Gate) -> ops.Pauli | None:
54
54
  for pauli_gate in [ops.X, ops.Y, ops.Z]:
55
55
  if protocols.equal_up_to_global_phase(gate, pauli_gate):
56
56
  return pauli_gate
57
57
  return None
58
58
 
59
59
 
60
- def _validate_dd_sequence(dd_sequence: Tuple[ops.Gate, ...]) -> None:
60
+ def _validate_dd_sequence(dd_sequence: tuple[ops.Gate, ...]) -> None:
61
61
  """Validates a given dynamical decoupling sequence.
62
62
 
63
63
  The sequence should only consists of Pauli gates and is essentially an identity gate.
@@ -87,8 +87,8 @@ def _validate_dd_sequence(dd_sequence: Tuple[ops.Gate, ...]) -> None:
87
87
 
88
88
 
89
89
  def _parse_dd_sequence(
90
- schema: Union[str, Tuple[ops.Gate, ...]],
91
- ) -> Tuple[Tuple[ops.Gate, ...], Dict[ops.Gate, ops.Pauli]]:
90
+ schema: str | tuple[ops.Gate, ...],
91
+ ) -> tuple[tuple[ops.Gate, ...], dict[ops.Gate, ops.Pauli]]:
92
92
  """Parses and returns dynamical decoupling sequence and its associated pauli map from schema."""
93
93
  dd_sequence = None
94
94
  if isinstance(schema, str):
@@ -98,7 +98,7 @@ def _parse_dd_sequence(
98
98
  dd_sequence = schema
99
99
 
100
100
  # Map gate to Pauli gate. This is necessary as dd sequence might contain gates like X^-1.
101
- pauli_map: Dict[ops.Gate, ops.Pauli] = {}
101
+ pauli_map: dict[ops.Gate, ops.Pauli] = {}
102
102
  for gate in dd_sequence:
103
103
  pauli_gate = _pauli_up_to_global_phase(gate)
104
104
  if pauli_gate is not None:
@@ -123,8 +123,8 @@ def _is_clifford_op(op: ops.Operation) -> bool:
123
123
 
124
124
  def _calc_busy_moment_range_of_each_qubit(
125
125
  circuit: circuits.FrozenCircuit,
126
- ) -> Dict[ops.Qid, list[int]]:
127
- busy_moment_range_by_qubit: Dict[ops.Qid, list[int]] = {
126
+ ) -> dict[ops.Qid, list[int]]:
127
+ busy_moment_range_by_qubit: dict[ops.Qid, list[int]] = {
128
128
  q: [len(circuit), -1] for q in circuit.all_qubits()
129
129
  }
130
130
  for moment_id, moment in enumerate(circuit):
@@ -139,7 +139,7 @@ def _is_insertable_moment(moment: circuits.Moment, single_qubit_gate_moments_onl
139
139
 
140
140
 
141
141
  def _merge_single_qubit_ops_to_phxz(
142
- q: ops.Qid, operations: Tuple[ops.Operation, ...]
142
+ q: ops.Qid, operations: tuple[ops.Operation, ...]
143
143
  ) -> ops.Operation:
144
144
  """Merges [op1, op2, ...] and returns an equivalent op"""
145
145
  if len(operations) == 1:
@@ -152,7 +152,7 @@ def _merge_single_qubit_ops_to_phxz(
152
152
 
153
153
  def _try_merge_single_qubit_ops_of_two_moments(
154
154
  m1: circuits.Moment, m2: circuits.Moment
155
- ) -> Tuple[circuits.Moment, ...]:
155
+ ) -> tuple[circuits.Moment, ...]:
156
156
  """Merge single qubit ops of 2 moments if possible, returns 2 moments otherwise."""
157
157
  for q in m1.qubits & m2.qubits:
158
158
  op1 = m1.operation_at(q)
@@ -208,8 +208,8 @@ def _need_merge_pulled_through(op_at_q: ops.Operation, is_at_last_busy_moment: b
208
208
  def add_dynamical_decoupling(
209
209
  circuit: cirq.AbstractCircuit,
210
210
  *,
211
- context: Optional[cirq.TransformerContext] = None,
212
- schema: Union[str, Tuple[ops.Gate, ...]] = 'DEFAULT',
211
+ context: cirq.TransformerContext | None = None,
212
+ schema: str | tuple[ops.Gate, ...] = 'DEFAULT',
213
213
  single_qubit_gate_moments_only: bool = True,
214
214
  ) -> cirq.Circuit:
215
215
  """Adds dynamical decoupling gate operations to a given circuit.