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
@@ -17,7 +17,7 @@
17
17
  from __future__ import annotations
18
18
 
19
19
  import re
20
- from typing import Callable, Dict, Iterator, Optional, Sequence, Tuple, TYPE_CHECKING, Union
20
+ from typing import Callable, Iterator, Sequence, TYPE_CHECKING
21
21
 
22
22
  import numpy as np
23
23
 
@@ -55,7 +55,7 @@ class QasmUGate(ops.Gate):
55
55
  def _has_unitary_(self):
56
56
  return True
57
57
 
58
- def _qasm_(self, qubits: Tuple[cirq.Qid, ...], args: cirq.QasmArgs) -> str:
58
+ def _qasm_(self, qubits: tuple[cirq.Qid, ...], args: cirq.QasmArgs) -> str:
59
59
  args.validate_version('2.0', '3.0')
60
60
  return args.format(
61
61
  'u3({0:half_turns},{1:half_turns},{2:half_turns}) {3};\n',
@@ -84,7 +84,7 @@ class QasmUGate(ops.Gate):
84
84
  def _value_equality_values_(self):
85
85
  return self.lmda, self.theta, self.phi
86
86
 
87
- def _json_dict_(self) -> Dict[str, float]:
87
+ def _json_dict_(self) -> dict[str, float]:
88
88
  return {'theta': self.theta, 'phi': self.phi, 'lmda': self.lmda}
89
89
 
90
90
  @classmethod
@@ -173,7 +173,7 @@ class QasmOutput:
173
173
  def __init__(
174
174
  self,
175
175
  operations: cirq.OP_TREE,
176
- qubits: Tuple[cirq.Qid, ...],
176
+ qubits: tuple[cirq.Qid, ...],
177
177
  header: str = '',
178
178
  precision: int = 10,
179
179
  version: str = '2.0',
@@ -208,10 +208,10 @@ class QasmOutput:
208
208
  meas_key_bitcount={k: v[0] for k, v in self.cregs.items()},
209
209
  )
210
210
 
211
- def _generate_measurement_ids(self) -> Tuple[Dict[str, str], Dict[str, Optional[str]]]:
211
+ def _generate_measurement_ids(self) -> tuple[dict[str, str], dict[str, str | None]]:
212
212
  # Pick an id for the creg that will store each measurement
213
- meas_key_id_map: Dict[str, str] = {}
214
- meas_comments: Dict[str, Optional[str]] = {}
213
+ meas_key_id_map: dict[str, str] = {}
214
+ meas_comments: dict[str, str | None] = {}
215
215
  meas_i = 0
216
216
  for meas in self.measurements:
217
217
  key = protocols.measurement_key_name(meas)
@@ -227,10 +227,10 @@ class QasmOutput:
227
227
  meas_key_id_map[key] = meas_id
228
228
  return meas_key_id_map, meas_comments
229
229
 
230
- def _generate_qubit_ids(self) -> Dict[cirq.Qid, str]:
230
+ def _generate_qubit_ids(self) -> dict[cirq.Qid, str]:
231
231
  return {qubit: f'q[{i}]' for i, qubit in enumerate(self.qubits)}
232
232
 
233
- def _generate_cregs(self, meas_key_id_map: Dict[str, str]) -> Dict[str, tuple[int, str]]:
233
+ def _generate_cregs(self, meas_key_id_map: dict[str, str]) -> dict[str, tuple[int, str]]:
234
234
  """Pick an id for the creg that will store each measurement
235
235
 
236
236
  This function finds the largest measurement using each key.
@@ -239,7 +239,7 @@ class QasmOutput:
239
239
 
240
240
  Returns: dictionary with key of measurement id and value of (#qubits, comment).
241
241
  """
242
- cregs: Dict[str, tuple[int, str]] = {}
242
+ cregs: dict[str, tuple[int, str]] = {}
243
243
  for meas in self.measurements:
244
244
  key = protocols.measurement_key_name(meas)
245
245
  meas_id = meas_key_id_map[key]
@@ -258,7 +258,7 @@ class QasmOutput:
258
258
  """Test if id_str is a valid id in QASM grammar."""
259
259
  return self.valid_id_re.match(id_str) is not None
260
260
 
261
- def save(self, path: Union[str, bytes, int]) -> None:
261
+ def save(self, path: str | bytes | int) -> None:
262
262
  """Write QASM output to a file specified by path."""
263
263
  with open(path, 'w') as f:
264
264
 
@@ -14,20 +14,7 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import (
18
- Any,
19
- Callable,
20
- cast,
21
- Dict,
22
- Iterable,
23
- List,
24
- Mapping,
25
- NamedTuple,
26
- Optional,
27
- Sequence,
28
- Tuple,
29
- TYPE_CHECKING,
30
- )
17
+ from typing import Any, Callable, cast, Iterable, Mapping, NamedTuple, Sequence, TYPE_CHECKING
31
18
 
32
19
  import numpy as np
33
20
 
@@ -73,25 +60,25 @@ class TextDiagramDrawer:
73
60
 
74
61
  def __init__(
75
62
  self,
76
- entries: Optional[Mapping[Tuple[int, int], _DiagramText]] = None,
77
- horizontal_lines: Optional[Iterable[_HorizontalLine]] = None,
78
- vertical_lines: Optional[Iterable[_VerticalLine]] = None,
79
- horizontal_padding: Optional[Mapping[int, int]] = None,
80
- vertical_padding: Optional[Mapping[int, int]] = None,
63
+ entries: Mapping[tuple[int, int], _DiagramText] | None = None,
64
+ horizontal_lines: Iterable[_HorizontalLine] | None = None,
65
+ vertical_lines: Iterable[_VerticalLine] | None = None,
66
+ horizontal_padding: Mapping[int, int] | None = None,
67
+ vertical_padding: Mapping[int, int] | None = None,
81
68
  ) -> None:
82
- self.entries: Dict[Tuple[int, int], _DiagramText] = (
69
+ self.entries: dict[tuple[int, int], _DiagramText] = (
83
70
  dict() if entries is None else dict(entries)
84
71
  )
85
- self.horizontal_lines: List[_HorizontalLine] = (
72
+ self.horizontal_lines: list[_HorizontalLine] = (
86
73
  [] if horizontal_lines is None else list(horizontal_lines)
87
74
  )
88
- self.vertical_lines: List[_VerticalLine] = (
75
+ self.vertical_lines: list[_VerticalLine] = (
89
76
  [] if vertical_lines is None else list(vertical_lines)
90
77
  )
91
- self.horizontal_padding: Dict[int, float] = (
78
+ self.horizontal_padding: dict[int, float] = (
92
79
  dict() if horizontal_padding is None else dict(horizontal_padding)
93
80
  )
94
- self.vertical_padding: Dict[int, float] = (
81
+ self.vertical_padding: dict[int, float] = (
95
82
  dict() if vertical_padding is None else dict(vertical_padding)
96
83
  )
97
84
 
@@ -108,7 +95,7 @@ class TextDiagramDrawer:
108
95
  def __bool__(self):
109
96
  return any(self._value_equality_values_())
110
97
 
111
- def write(self, x: int, y: int, text: str, transposed_text: Optional[str] = None):
98
+ def write(self, x: int, y: int, text: str, transposed_text: str | None = None):
112
99
  """Adds text to the given location.
113
100
 
114
101
  Args:
@@ -215,7 +202,7 @@ class TextDiagramDrawer:
215
202
  """Change the padding after the given row."""
216
203
  self.vertical_padding[index] = padding
217
204
 
218
- def _transform_coordinates(self, func: Callable[[float, float], Tuple[float, float]]) -> None:
205
+ def _transform_coordinates(self, func: Callable[[float, float], tuple[float, float]]) -> None:
219
206
  """Helper method to transformer either row or column coordinates."""
220
207
 
221
208
  def func_x(x: float) -> float:
@@ -225,7 +212,7 @@ class TextDiagramDrawer:
225
212
  return func(0, y)[1]
226
213
 
227
214
  self.entries = {
228
- cast(Tuple[int, int], func(int(x), int(y))): v for (x, y), v in self.entries.items()
215
+ cast(tuple[int, int], func(int(x), int(y))): v for (x, y), v in self.entries.items()
229
216
  }
230
217
  self.vertical_lines = [
231
218
  _VerticalLine(func_x(x), func_y(y1), func_y(y2), emph, doubled)
@@ -245,7 +232,7 @@ class TextDiagramDrawer:
245
232
  def insert_empty_columns(self, x: int, amount: int = 1) -> None:
246
233
  """Insert a number of columns after the given column."""
247
234
 
248
- def transform_columns(column: float, row: float) -> Tuple[float, float]:
235
+ def transform_columns(column: float, row: float) -> tuple[float, float]:
249
236
  return column + (amount if column >= x else 0), row
250
237
 
251
238
  self._transform_coordinates(transform_columns)
@@ -253,7 +240,7 @@ class TextDiagramDrawer:
253
240
  def insert_empty_rows(self, y: int, amount: int = 1) -> None:
254
241
  """Insert a number of rows after the given row."""
255
242
 
256
- def transform_rows(column: float, row: float) -> Tuple[float, float]:
243
+ def transform_rows(column: float, row: float) -> tuple[float, float]:
257
244
  return column, row + (amount if row >= y else 0)
258
245
 
259
246
  self._transform_coordinates(transform_rows)
@@ -262,7 +249,7 @@ class TextDiagramDrawer:
262
249
  self,
263
250
  horizontal_spacing: int = 1,
264
251
  vertical_spacing: int = 1,
265
- crossing_char: Optional[str] = None,
252
+ crossing_char: str | None = None,
266
253
  use_unicode_characters: bool = True,
267
254
  ) -> str:
268
255
  """Outputs text containing the diagram."""
@@ -357,7 +344,7 @@ class TextDiagramDrawer:
357
344
  def vstack(
358
345
  cls,
359
346
  diagrams: Sequence[cirq.TextDiagramDrawer],
360
- padding_resolver: Optional[Callable[[Sequence[Optional[int]]], int]] = None,
347
+ padding_resolver: Callable[[Sequence[int | None]], int] | None = None,
361
348
  ):
362
349
  """Vertically stack text diagrams.
363
350
 
@@ -386,9 +373,7 @@ class TextDiagramDrawer:
386
373
  dy += diagram.height()
387
374
  for x in stacked.horizontal_padding:
388
375
  resolved_padding = padding_resolver(
389
- tuple(
390
- cast(Optional[int], diagram.horizontal_padding.get(x)) for diagram in diagrams
391
- )
376
+ tuple(cast(int | None, diagram.horizontal_padding.get(x)) for diagram in diagrams)
392
377
  )
393
378
  if resolved_padding is not None:
394
379
  stacked.horizontal_padding[x] = resolved_padding
@@ -398,7 +383,7 @@ class TextDiagramDrawer:
398
383
  def hstack(
399
384
  cls,
400
385
  diagrams: Sequence[cirq.TextDiagramDrawer],
401
- padding_resolver: Optional[Callable[[Sequence[Optional[int]]], int]] = None,
386
+ padding_resolver: Callable[[Sequence[int | None]], int] | None = None,
402
387
  ):
403
388
  """Horizontally stack text diagrams.
404
389
 
@@ -427,7 +412,7 @@ class TextDiagramDrawer:
427
412
  dx += diagram.width()
428
413
  for y in stacked.vertical_padding:
429
414
  resolved_padding = padding_resolver(
430
- tuple(cast(Optional[int], diagram.vertical_padding.get(y)) for diagram in diagrams)
415
+ tuple(cast(int | None, diagram.vertical_padding.get(y)) for diagram in diagrams)
431
416
  )
432
417
  if resolved_padding is not None:
433
418
  stacked.vertical_padding[y] = resolved_padding
@@ -16,7 +16,7 @@ from __future__ import annotations
16
16
 
17
17
  import enum
18
18
  import itertools
19
- from typing import Dict, Iterator, Sequence, Tuple, TYPE_CHECKING, Union
19
+ from typing import Iterator, Sequence, TYPE_CHECKING
20
20
 
21
21
  from cirq import ops
22
22
  from cirq.contrib.acquaintance.gates import acquaint
@@ -61,10 +61,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
61
61
  """
62
62
 
63
63
  def __init__(
64
- self,
65
- subgraph: Union[str, BipartiteGraphType],
66
- part_size: int,
67
- swap_gate: cirq.Gate = ops.SWAP,
64
+ self, subgraph: str | BipartiteGraphType, part_size: int, swap_gate: cirq.Gate = ops.SWAP
68
65
  ) -> None:
69
66
  super().__init__(2 * part_size, swap_gate)
70
67
  self.part_size = part_size
@@ -106,7 +103,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
106
103
  return self.decompose_matching(qubits)
107
104
  raise NotImplementedError('No decomposition implemented for ' + str(self.subgraph))
108
105
 
109
- def permutation(self) -> Dict[int, int]:
106
+ def permutation(self) -> dict[int, int]:
110
107
  if self.num_qubits() != 2 * self.part_size:
111
108
  raise ValueError('qubit_count != 2 * self.part_size')
112
109
  if self.subgraph == BipartiteGraphType.MATCHING:
@@ -124,7 +121,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
124
121
  return dict(enumerate(range(2 * self.part_size)))
125
122
  raise NotImplementedError(str(self.subgraph) + 'not implemented')
126
123
 
127
- def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> Tuple[str, ...]:
124
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> tuple[str, ...]:
128
125
  qubit_count = 2 * self.part_size
129
126
  if args.known_qubit_count not in (None, qubit_count):
130
127
  raise ValueError('args.known_qubit_count not in (None, 2 * self.part_size)')
@@ -149,7 +146,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
149
146
  return wire_symbols
150
147
 
151
148
  def __repr__(self) -> str:
152
- args: Tuple[str, ...] = (repr(self.subgraph), repr(self.part_size))
149
+ args: tuple[str, ...] = (repr(self.subgraph), repr(self.part_size))
153
150
  if self.swap_gate != ops.SWAP:
154
151
  args += (repr(self.swap_gate),)
155
152
  args_str = ', '.join(args)
@@ -16,7 +16,7 @@ from __future__ import annotations
16
16
 
17
17
  import abc
18
18
  from collections import defaultdict
19
- from typing import DefaultDict, Dict, Iterator, Optional, Sequence, TYPE_CHECKING
19
+ from typing import Iterator, Sequence, TYPE_CHECKING
20
20
 
21
21
  from cirq import circuits, devices, ops, protocols, transformers
22
22
  from cirq.contrib.acquaintance.gates import AcquaintanceOpportunityGate
@@ -99,7 +99,7 @@ class StrategyExecutorTransformer:
99
99
  self._mapping = execution_strategy.initial_mapping.copy()
100
100
 
101
101
  def __call__(
102
- self, circuit: circuits.AbstractCircuit, context: Optional[cirq.TransformerContext] = None
102
+ self, circuit: circuits.AbstractCircuit, context: cirq.TransformerContext | None = None
103
103
  ) -> circuits.Circuit:
104
104
  """Executes an acquaintance strategy using cirq.map_operations_and_unroll and
105
105
  mutates initial mapping.
@@ -174,7 +174,7 @@ class GreedyExecutionStrategy(ExecutionStrategy):
174
174
  self,
175
175
  gates: LogicalGates,
176
176
  initial_mapping: LogicalMapping,
177
- device: Optional[cirq.Device] = None,
177
+ device: cirq.Device | None = None,
178
178
  ) -> None:
179
179
  """Inits GreedyExecutionStrategy.
180
180
 
@@ -214,13 +214,13 @@ class GreedyExecutionStrategy(ExecutionStrategy):
214
214
  yield gate(*[index_to_qubit[i] for i in gate_indices])
215
215
 
216
216
  @staticmethod
217
- def canonicalize_gates(gates: LogicalGates) -> Dict[frozenset, LogicalGates]:
217
+ def canonicalize_gates(gates: LogicalGates) -> dict[frozenset, LogicalGates]:
218
218
  """Canonicalizes a set of gates by the qubits they act on.
219
219
 
220
220
  Takes a set of gates specified by ordered sequences of logical
221
221
  indices, and groups those that act on the same qubits regardless of
222
222
  order."""
223
- canonicalized_gates: DefaultDict[frozenset, LogicalGates] = defaultdict(dict)
223
+ canonicalized_gates: defaultdict[frozenset, LogicalGates] = defaultdict(dict)
224
224
  for indices, gate in gates.items():
225
225
  indices = tuple(indices)
226
226
  canonicalized_gates[frozenset(indices)][indices] = gate
@@ -16,7 +16,7 @@ from __future__ import annotations
16
16
 
17
17
  from itertools import combinations
18
18
  from string import ascii_lowercase
19
- from typing import Dict, Sequence, Tuple
19
+ from typing import Sequence
20
20
 
21
21
  import numpy as np
22
22
  import pytest
@@ -87,7 +87,7 @@ def test_executor_explicit():
87
87
 
88
88
  def random_diagonal_gates(
89
89
  num_qubits: int, acquaintance_size: int
90
- ) -> Dict[Tuple[cirq.Qid, ...], cirq.Gate]:
90
+ ) -> dict[tuple[cirq.Qid, ...], cirq.Gate]:
91
91
 
92
92
  return {
93
93
  Q: cirq.DiagonalGate(np.random.random(2**acquaintance_size))
@@ -106,7 +106,7 @@ def random_diagonal_gates(
106
106
  ],
107
107
  )
108
108
  def test_executor_random(
109
- num_qubits: int, acquaintance_size: int, gates: Dict[Tuple[cirq.Qid, ...], cirq.Gate]
109
+ num_qubits: int, acquaintance_size: int, gates: dict[tuple[cirq.Qid, ...], cirq.Gate]
110
110
  ):
111
111
  qubits = cirq.LineQubit.range(num_qubits)
112
112
  circuit = cca.complete_acquaintance_strategy(qubits, acquaintance_size)
@@ -18,17 +18,7 @@ import functools
18
18
  import itertools
19
19
  import math
20
20
  import operator
21
- from typing import (
22
- Dict,
23
- Iterable,
24
- Iterator,
25
- List,
26
- NamedTuple,
27
- Optional,
28
- Sequence,
29
- Tuple,
30
- TYPE_CHECKING,
31
- )
21
+ from typing import Iterable, Iterator, NamedTuple, Sequence, TYPE_CHECKING
32
22
 
33
23
  from cirq import ops, protocols, value
34
24
  from cirq.contrib.acquaintance.permutation import (
@@ -44,10 +34,10 @@ if TYPE_CHECKING:
44
34
 
45
35
  def operations_to_part_lens(
46
36
  qubit_order: Sequence[cirq.Qid], op_tree: cirq.OP_TREE
47
- ) -> Tuple[int, ...]:
37
+ ) -> tuple[int, ...]:
48
38
  qubit_sort_key = functools.partial(operator.indexOf, qubit_order)
49
39
  op_parts = [tuple(sorted(op.qubits, key=qubit_sort_key)) for op in ops.flatten_op_tree(op_tree)]
50
- singletons: List[Tuple[cirq.Qid, ...]] = [(q,) for q in set(qubit_order).difference(*op_parts)]
40
+ singletons: list[tuple[cirq.Qid, ...]] = [(q,) for q in set(qubit_order).difference(*op_parts)]
51
41
  part_sort_key = lambda p: min(qubit_sort_key(q) for q in p)
52
42
  parts = tuple(tuple(part) for part in sorted(singletons + op_parts, key=part_sort_key))
53
43
 
@@ -87,16 +77,16 @@ def acquaint(*qubits) -> cirq.Operation:
87
77
  Layers = NamedTuple(
88
78
  'Layers',
89
79
  [
90
- ('prior_interstitial', List['cirq.Operation']),
91
- ('pre', List['cirq.Operation']),
92
- ('intra', List['cirq.Operation']),
93
- ('post', List['cirq.Operation']),
94
- ('posterior_interstitial', List['cirq.Operation']),
80
+ ('prior_interstitial', list['cirq.Operation']),
81
+ ('pre', list['cirq.Operation']),
82
+ ('intra', list['cirq.Operation']),
83
+ ('post', list['cirq.Operation']),
84
+ ('posterior_interstitial', list['cirq.Operation']),
95
85
  ],
96
86
  )
97
87
 
98
88
 
99
- def new_layers(**kwargs: List[cirq.Operation]) -> Layers:
89
+ def new_layers(**kwargs: list[cirq.Operation]) -> Layers:
100
90
  return Layers._make(kwargs.get(field, []) for field in Layers._fields)
101
91
 
102
92
 
@@ -106,7 +96,7 @@ def acquaint_insides(
106
96
  qubits: Sequence[cirq.Qid],
107
97
  before: bool,
108
98
  layers: Layers,
109
- mapping: Dict[ops.Qid, int],
99
+ mapping: dict[ops.Qid, int],
110
100
  ) -> None:
111
101
  """Acquaints each of the qubits with another set specified by an
112
102
  acquaintance gate.
@@ -153,11 +143,11 @@ def _get_max_reach(size: int, round_up: bool = True) -> int:
153
143
 
154
144
 
155
145
  def acquaint_and_shift(
156
- parts: Tuple[List[cirq.Qid], List[cirq.Qid]],
146
+ parts: tuple[list[cirq.Qid], list[cirq.Qid]],
157
147
  layers: Layers,
158
- acquaintance_size: Optional[int],
148
+ acquaintance_size: int | None,
159
149
  swap_gate: cirq.Gate,
160
- mapping: Dict[ops.Qid, int],
150
+ mapping: dict[ops.Qid, int],
161
151
  ):
162
152
  """Acquaints and shifts a pair of lists of qubits. The first part is
163
153
  acquainted with every qubit individually in the second part, and vice
@@ -276,7 +266,7 @@ class SwapNetworkGate(PermutationGate):
276
266
  def __init__(
277
267
  self,
278
268
  part_lens: Sequence[int],
279
- acquaintance_size: Optional[int] = 0,
269
+ acquaintance_size: int | None = 0,
280
270
  swap_gate: cirq.Gate = ops.SWAP,
281
271
  ) -> None:
282
272
  super().__init__(sum(part_lens), swap_gate)
@@ -346,13 +336,13 @@ class SwapNetworkGate(PermutationGate):
346
336
  def from_operations(
347
337
  qubit_order: Sequence[cirq.Qid],
348
338
  operations: Sequence[cirq.Operation],
349
- acquaintance_size: Optional[int] = 0,
339
+ acquaintance_size: int | None = 0,
350
340
  swap_gate: cirq.Gate = ops.SWAP,
351
341
  ) -> SwapNetworkGate:
352
342
  part_sizes = operations_to_part_lens(qubit_order, operations)
353
343
  return SwapNetworkGate(part_sizes, acquaintance_size, swap_gate)
354
344
 
355
- def permutation(self) -> Dict[int, int]:
345
+ def permutation(self) -> dict[int, int]:
356
346
  return {i: j for i, j in enumerate(reversed(range(sum(self.part_lens))))}
357
347
 
358
348
  def __repr__(self) -> str:
@@ -17,7 +17,7 @@ from __future__ import annotations
17
17
  from itertools import combinations, product
18
18
  from random import randint
19
19
  from string import ascii_lowercase as alphabet
20
- from typing import Optional, Sequence, Tuple
20
+ from typing import Sequence
21
21
 
22
22
  import numpy
23
23
  import pytest
@@ -141,7 +141,7 @@ def test_acquaint_part_pairs(part_lens):
141
141
  assert expected_opps == actual_opps
142
142
 
143
143
 
144
- acquaintance_sizes: Tuple[Optional[int], ...] = (None,)
144
+ acquaintance_sizes: tuple[int | None, ...] = (None,)
145
145
  acquaintance_sizes += tuple(range(5))
146
146
 
147
147
 
@@ -256,7 +256,7 @@ class OtherOperation(cirq.Operation):
256
256
  self._qubits = tuple(qubits)
257
257
 
258
258
  @property
259
- def qubits(self) -> Tuple[cirq.Qid, ...]:
259
+ def qubits(self) -> tuple[cirq.Qid, ...]:
260
260
  return self._qubits
261
261
 
262
262
  def with_qubits(self, *new_qubits: cirq.Qid) -> OtherOperation:
@@ -15,7 +15,7 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import collections
18
- from typing import cast, Dict, List, Optional, Sequence, TYPE_CHECKING, Union
18
+ from typing import cast, Sequence, TYPE_CHECKING
19
19
 
20
20
  from cirq import circuits, ops, transformers
21
21
  from cirq.contrib.acquaintance.devices import get_acquaintance_size
@@ -25,7 +25,7 @@ from cirq.contrib.acquaintance.permutation import PermutationGate
25
25
  if TYPE_CHECKING:
26
26
  import cirq
27
27
 
28
- STRATEGY_GATE = Union[AcquaintanceOpportunityGate, PermutationGate]
28
+ STRATEGY_GATE = AcquaintanceOpportunityGate | PermutationGate
29
29
 
30
30
 
31
31
  def rectify_acquaintance_strategy(circuit: cirq.Circuit, acquaint_first: bool = True) -> None:
@@ -43,7 +43,7 @@ def rectify_acquaintance_strategy(circuit: cirq.Circuit, acquaint_first: bool =
43
43
  """
44
44
  rectified_moments = []
45
45
  for moment in circuit:
46
- gate_type_to_ops: Dict[bool, List[ops.GateOperation]] = collections.defaultdict(list)
46
+ gate_type_to_ops: dict[bool, list[ops.GateOperation]] = collections.defaultdict(list)
47
47
  for op in moment.operations:
48
48
  gate_op = cast(ops.GateOperation, op)
49
49
  is_acquaintance = isinstance(gate_op.gate, AcquaintanceOpportunityGate)
@@ -59,7 +59,7 @@ def rectify_acquaintance_strategy(circuit: cirq.Circuit, acquaint_first: bool =
59
59
  def replace_acquaintance_with_swap_network(
60
60
  circuit: cirq.Circuit,
61
61
  qubit_order: Sequence[cirq.Qid],
62
- acquaintance_size: Optional[int] = 0,
62
+ acquaintance_size: int | None = 0,
63
63
  swap_gate: cirq.Gate = ops.SWAP,
64
64
  ) -> bool:
65
65
  """Replace every rectified moment with acquaintance gates with a generalized swap network.
@@ -14,7 +14,7 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import cast, FrozenSet, List, Sequence, Set, TYPE_CHECKING
17
+ from typing import cast, Sequence, TYPE_CHECKING
18
18
 
19
19
  from cirq import circuits
20
20
  from cirq.contrib.acquaintance.executor import AcquaintanceOperation
@@ -36,11 +36,11 @@ def remove_redundant_acquaintance_opportunities(strategy: cirq.Circuit) -> int:
36
36
  annotated_strategy = strategy.copy()
37
37
  LogicalAnnotator(mapping)(annotated_strategy)
38
38
 
39
- new_moments: List[cirq.Moment] = []
40
- acquaintance_opps: Set[FrozenSet[int]] = set()
39
+ new_moments: list[cirq.Moment] = []
40
+ acquaintance_opps: set[frozenset[int]] = set()
41
41
  n_removed = 0
42
42
  for moment in annotated_strategy:
43
- new_moment: List[cirq.Operation] = []
43
+ new_moment: list[cirq.Operation] = []
44
44
  for op in moment:
45
45
  if isinstance(op, AcquaintanceOperation):
46
46
  opp = frozenset(cast(Sequence[int], op.logical_indices))
@@ -16,19 +16,7 @@ from __future__ import annotations
16
16
 
17
17
  import abc
18
18
  from types import NotImplementedType
19
- from typing import (
20
- Any,
21
- cast,
22
- Dict,
23
- Iterable,
24
- Iterator,
25
- Optional,
26
- Sequence,
27
- Tuple,
28
- TYPE_CHECKING,
29
- TypeVar,
30
- Union,
31
- )
19
+ from typing import Any, cast, Iterable, Iterator, Sequence, TYPE_CHECKING, TypeVar
32
20
 
33
21
  from cirq import circuits, ops, protocols, transformers, value
34
22
 
@@ -37,10 +25,10 @@ if TYPE_CHECKING:
37
25
 
38
26
 
39
27
  LogicalIndex = TypeVar('LogicalIndex', int, ops.Qid)
40
- LogicalIndexSequence = Union[Sequence[int], Sequence['cirq.Qid']]
41
- LogicalGates = Dict[Tuple[LogicalIndex, ...], ops.Gate]
28
+ LogicalIndexSequence = Sequence[int] | Sequence['cirq.Qid']
29
+ LogicalGates = dict[tuple[LogicalIndex, ...], ops.Gate]
42
30
  LogicalMappingKey = TypeVar('LogicalMappingKey', bound=ops.Qid)
43
- LogicalMapping = Dict[LogicalMappingKey, LogicalIndex]
31
+ LogicalMapping = dict[LogicalMappingKey, LogicalIndex]
44
32
 
45
33
 
46
34
  class PermutationGate(ops.Gate, metaclass=abc.ABCMeta):
@@ -61,12 +49,12 @@ class PermutationGate(ops.Gate, metaclass=abc.ABCMeta):
61
49
  return self._num_qubits
62
50
 
63
51
  @abc.abstractmethod
64
- def permutation(self) -> Dict[int, int]:
52
+ def permutation(self) -> dict[int, int]:
65
53
  """permutation = {i: s[i]} indicates that the i-th element is mapped to
66
54
  the s[i]-th element."""
67
55
 
68
56
  def update_mapping(
69
- self, mapping: Dict[ops.Qid, LogicalIndex], keys: Sequence[cirq.Qid]
57
+ self, mapping: dict[ops.Qid, LogicalIndex], keys: Sequence[cirq.Qid]
70
58
  ) -> None:
71
59
  """Updates a mapping (in place) from qubits to logical indices.
72
60
 
@@ -86,7 +74,7 @@ class PermutationGate(ops.Gate, metaclass=abc.ABCMeta):
86
74
  mapping[new_key] = old_element
87
75
 
88
76
  @staticmethod
89
- def validate_permutation(permutation: Dict[int, int], n_elements: Optional[int] = None) -> None:
77
+ def validate_permutation(permutation: dict[int, int], n_elements: int | None = None) -> None:
90
78
  if not permutation:
91
79
  return
92
80
  if set(permutation.values()) != set(permutation):
@@ -99,7 +87,7 @@ class PermutationGate(ops.Gate, metaclass=abc.ABCMeta):
99
87
 
100
88
  def _circuit_diagram_info_(
101
89
  self, args: cirq.CircuitDiagramInfoArgs
102
- ) -> Union[str, Iterable[str], cirq.CircuitDiagramInfo]:
90
+ ) -> str | Iterable[str] | cirq.CircuitDiagramInfo:
103
91
  if args.known_qubit_count is None:
104
92
  return NotImplemented
105
93
  permutation = self.permutation()
@@ -150,7 +138,7 @@ class SwapPermutationGate(PermutationGate):
150
138
  def __init__(self, swap_gate: cirq.Gate = ops.SWAP):
151
139
  super().__init__(2, swap_gate)
152
140
 
153
- def permutation(self) -> Dict[int, int]:
141
+ def permutation(self) -> dict[int, int]:
154
142
  return {0: 1, 1: 0}
155
143
 
156
144
  def _decompose_(self, qubits: Sequence[cirq.Qid]) -> Iterator[cirq.OP_TREE]:
@@ -166,7 +154,7 @@ class SwapPermutationGate(PermutationGate):
166
154
  def _value_equality_values_(self) -> Any:
167
155
  return (self.swap_gate,)
168
156
 
169
- def _commutes_(self, other: Any, *, atol: float = 1e-8) -> Union[bool, NotImplementedType]:
157
+ def _commutes_(self, other: Any, *, atol: float = 1e-8) -> bool | NotImplementedType:
170
158
  if (
171
159
  isinstance(other, ops.Gate)
172
160
  and isinstance(other, ops.InterchangeableQubitsGate)
@@ -176,7 +164,7 @@ class SwapPermutationGate(PermutationGate):
176
164
  return NotImplemented
177
165
 
178
166
 
179
- def _canonicalize_permutation(permutation: Dict[int, int]) -> Dict[int, int]:
167
+ def _canonicalize_permutation(permutation: dict[int, int]) -> dict[int, int]:
180
168
  return {i: j for i, j in permutation.items() if i != j}
181
169
 
182
170
 
@@ -186,7 +174,7 @@ class LinearPermutationGate(PermutationGate):
186
174
  sorting network."""
187
175
 
188
176
  def __init__(
189
- self, num_qubits: int, permutation: Dict[int, int], swap_gate: cirq.Gate = ops.SWAP
177
+ self, num_qubits: int, permutation: dict[int, int], swap_gate: cirq.Gate = ops.SWAP
190
178
  ) -> None:
191
179
  """Initializes a linear permutation gate.
192
180
 
@@ -199,7 +187,7 @@ class LinearPermutationGate(PermutationGate):
199
187
  PermutationGate.validate_permutation(permutation, num_qubits)
200
188
  self._permutation = permutation
201
189
 
202
- def permutation(self) -> Dict[int, int]:
190
+ def permutation(self) -> dict[int, int]:
203
191
  return self._permutation
204
192
 
205
193
  def _decompose_(self, qubits: Sequence[cirq.Qid]) -> Iterator[cirq.OP_TREE]:
@@ -238,7 +226,7 @@ class LinearPermutationGate(PermutationGate):
238
226
  return NotImplemented
239
227
 
240
228
 
241
- def update_mapping(mapping: Dict[ops.Qid, LogicalIndex], operations: cirq.OP_TREE) -> None:
229
+ def update_mapping(mapping: dict[ops.Qid, LogicalIndex], operations: cirq.OP_TREE) -> None:
242
230
  """Updates a mapping (in place) from qubits to logical indices according to
243
231
  a set of permutation gates. Any gates other than permutation gates are
244
232
  ignored.
@@ -253,7 +241,7 @@ def update_mapping(mapping: Dict[ops.Qid, LogicalIndex], operations: cirq.OP_TRE
253
241
 
254
242
 
255
243
  def get_logical_operations(
256
- operations: cirq.OP_TREE, initial_mapping: Dict[ops.Qid, ops.Qid]
244
+ operations: cirq.OP_TREE, initial_mapping: dict[ops.Qid, ops.Qid]
257
245
  ) -> Iterable[cirq.Operation]:
258
246
  """Gets the logical operations specified by the physical operations and
259
247
  initial mapping.