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

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

Potentially problematic release.


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

Files changed (290) hide show
  1. cirq/_compat.py +15 -17
  2. cirq/_compat_test.py +6 -9
  3. cirq/_doc.py +2 -2
  4. cirq/_import.py +6 -6
  5. cirq/_version.py +1 -1
  6. cirq/_version_test.py +1 -1
  7. cirq/circuits/_block_diagram_drawer.py +9 -10
  8. cirq/circuits/_box_drawing_character_data.py +6 -8
  9. cirq/circuits/_bucket_priority_queue.py +7 -7
  10. cirq/circuits/circuit.py +118 -125
  11. cirq/circuits/circuit_operation.py +38 -52
  12. cirq/circuits/circuit_test.py +4 -4
  13. cirq/circuits/frozen_circuit.py +13 -23
  14. cirq/circuits/moment.py +23 -29
  15. cirq/circuits/optimization_pass.py +4 -4
  16. cirq/circuits/optimization_pass_test.py +4 -6
  17. cirq/circuits/qasm_output.py +11 -11
  18. cirq/circuits/text_diagram_drawer.py +21 -36
  19. cirq/contrib/acquaintance/bipartite.py +5 -8
  20. cirq/contrib/acquaintance/executor.py +5 -5
  21. cirq/contrib/acquaintance/executor_test.py +3 -3
  22. cirq/contrib/acquaintance/gates.py +16 -26
  23. cirq/contrib/acquaintance/gates_test.py +3 -3
  24. cirq/contrib/acquaintance/mutation_utils.py +4 -4
  25. cirq/contrib/acquaintance/optimizers.py +4 -4
  26. cirq/contrib/acquaintance/permutation.py +15 -27
  27. cirq/contrib/acquaintance/shift.py +3 -3
  28. cirq/contrib/acquaintance/shift_swap_network.py +4 -4
  29. cirq/contrib/acquaintance/strategies/cubic.py +2 -2
  30. cirq/contrib/acquaintance/strategies/quartic_paired.py +6 -6
  31. cirq/contrib/bayesian_network/bayesian_network_gate.py +9 -10
  32. cirq/contrib/circuitdag/circuit_dag.py +2 -2
  33. cirq/contrib/custom_simulators/custom_state_simulator.py +3 -3
  34. cirq/contrib/custom_simulators/custom_state_simulator_test.py +4 -4
  35. cirq/contrib/graph_device/graph_device.py +5 -5
  36. cirq/contrib/graph_device/hypergraph.py +12 -12
  37. cirq/contrib/graph_device/uniform_graph_device.py +4 -4
  38. cirq/contrib/paulistring/clifford_optimize.py +2 -2
  39. cirq/contrib/paulistring/clifford_target_gateset.py +7 -7
  40. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +31 -31
  41. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +23 -23
  42. cirq/contrib/paulistring/recombine.py +3 -3
  43. cirq/contrib/paulistring/separate.py +2 -2
  44. cirq/contrib/qasm_import/_parser.py +20 -32
  45. cirq/contrib/qcircuit/qcircuit_diagram_info.py +3 -5
  46. cirq/contrib/quantum_volume/quantum_volume.py +24 -24
  47. cirq/contrib/quimb/density_matrix.py +12 -14
  48. cirq/contrib/quimb/mps_simulator.py +20 -20
  49. cirq/contrib/quimb/state_vector.py +6 -10
  50. cirq/contrib/quirk/export_to_quirk.py +3 -3
  51. cirq/contrib/quirk/quirk_gate.py +15 -15
  52. cirq/contrib/routing/device.py +3 -3
  53. cirq/contrib/routing/greedy.py +10 -21
  54. cirq/contrib/routing/initialization.py +2 -2
  55. cirq/contrib/routing/swap_network.py +3 -3
  56. cirq/contrib/routing/utils.py +2 -2
  57. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +8 -8
  58. cirq/contrib/svg/svg.py +3 -3
  59. cirq/devices/grid_device_metadata.py +10 -10
  60. cirq/devices/grid_qubit.py +20 -20
  61. cirq/devices/insertion_noise_model.py +5 -5
  62. cirq/devices/line_qubit.py +13 -13
  63. cirq/devices/named_topologies.py +18 -29
  64. cirq/devices/noise_model.py +3 -3
  65. cirq/devices/noise_properties.py +2 -2
  66. cirq/devices/noise_properties_test.py +1 -3
  67. cirq/devices/noise_utils.py +7 -7
  68. cirq/devices/superconducting_qubits_noise_properties.py +21 -21
  69. cirq/devices/superconducting_qubits_noise_properties_test.py +5 -7
  70. cirq/devices/thermal_noise_model.py +14 -14
  71. cirq/devices/unconstrained_device.py +2 -2
  72. cirq/experiments/benchmarking/parallel_xeb.py +29 -31
  73. cirq/experiments/n_qubit_tomography.py +5 -7
  74. cirq/experiments/qubit_characterizations.py +29 -40
  75. cirq/experiments/qubit_characterizations_test.py +1 -1
  76. cirq/experiments/random_quantum_circuit_generation.py +19 -33
  77. cirq/experiments/random_quantum_circuit_generation_test.py +6 -6
  78. cirq/experiments/readout_confusion_matrix.py +14 -14
  79. cirq/experiments/single_qubit_readout_calibration.py +12 -12
  80. cirq/experiments/t2_decay_experiment.py +7 -7
  81. cirq/experiments/two_qubit_xeb.py +32 -32
  82. cirq/experiments/two_qubit_xeb_test.py +5 -5
  83. cirq/experiments/xeb_fitting.py +25 -25
  84. cirq/experiments/xeb_sampling.py +22 -33
  85. cirq/experiments/xeb_simulation.py +5 -5
  86. cirq/experiments/xeb_simulation_test.py +3 -3
  87. cirq/experiments/z_phase_calibration.py +19 -19
  88. cirq/interop/quirk/cells/arithmetic_cells.py +23 -36
  89. cirq/interop/quirk/cells/cell.py +9 -21
  90. cirq/interop/quirk/cells/composite_cell.py +7 -22
  91. cirq/interop/quirk/cells/control_cells.py +8 -8
  92. cirq/interop/quirk/cells/input_cells.py +4 -4
  93. cirq/interop/quirk/cells/input_rotation_cells.py +5 -5
  94. cirq/interop/quirk/cells/parse.py +20 -23
  95. cirq/interop/quirk/cells/qubit_permutation_cells.py +3 -3
  96. cirq/interop/quirk/cells/swap_cell.py +3 -3
  97. cirq/interop/quirk/cells/testing.py +5 -7
  98. cirq/interop/quirk/url_to_circuit.py +17 -33
  99. cirq/json_resolver_cache.py +6 -6
  100. cirq/linalg/decompositions.py +20 -31
  101. cirq/linalg/diagonalize.py +4 -4
  102. cirq/linalg/diagonalize_test.py +3 -4
  103. cirq/linalg/operator_spaces.py +5 -5
  104. cirq/linalg/predicates.py +7 -7
  105. cirq/linalg/transformations.py +20 -20
  106. cirq/ops/arithmetic_operation.py +13 -15
  107. cirq/ops/boolean_hamiltonian.py +17 -17
  108. cirq/ops/classically_controlled_operation.py +13 -25
  109. cirq/ops/clifford_gate.py +31 -35
  110. cirq/ops/clifford_gate_test.py +2 -3
  111. cirq/ops/common_channels.py +30 -32
  112. cirq/ops/common_gates.py +64 -74
  113. cirq/ops/control_values.py +12 -12
  114. cirq/ops/controlled_gate.py +15 -30
  115. cirq/ops/controlled_gate_test.py +5 -5
  116. cirq/ops/controlled_operation.py +12 -25
  117. cirq/ops/controlled_operation_test.py +5 -5
  118. cirq/ops/dense_pauli_string.py +23 -34
  119. cirq/ops/dense_pauli_string_test.py +1 -2
  120. cirq/ops/diagonal_gate.py +9 -20
  121. cirq/ops/diagonal_gate_test.py +1 -3
  122. cirq/ops/eigen_gate.py +11 -23
  123. cirq/ops/eigen_gate_test.py +6 -8
  124. cirq/ops/fourier_transform.py +5 -5
  125. cirq/ops/fsim_gate.py +14 -14
  126. cirq/ops/gate_operation.py +23 -44
  127. cirq/ops/gateset.py +23 -37
  128. cirq/ops/gateset_test.py +2 -2
  129. cirq/ops/global_phase_op.py +8 -10
  130. cirq/ops/greedy_qubit_manager.py +6 -6
  131. cirq/ops/identity.py +9 -9
  132. cirq/ops/kraus_channel.py +7 -7
  133. cirq/ops/linear_combinations.py +29 -48
  134. cirq/ops/matrix_gates.py +8 -8
  135. cirq/ops/measure_util.py +13 -14
  136. cirq/ops/measurement_gate.py +18 -29
  137. cirq/ops/mixed_unitary_channel.py +8 -8
  138. cirq/ops/named_qubit.py +10 -10
  139. cirq/ops/op_tree.py +7 -7
  140. cirq/ops/parallel_gate.py +5 -5
  141. cirq/ops/parity_gates.py +14 -14
  142. cirq/ops/pauli_gates.py +8 -10
  143. cirq/ops/pauli_interaction_gate.py +6 -6
  144. cirq/ops/pauli_measurement_gate.py +11 -23
  145. cirq/ops/pauli_string.py +35 -52
  146. cirq/ops/pauli_string_phasor.py +4 -14
  147. cirq/ops/pauli_string_raw_types.py +3 -3
  148. cirq/ops/pauli_sum_exponential.py +2 -2
  149. cirq/ops/permutation_gate.py +4 -4
  150. cirq/ops/phased_iswap_gate.py +9 -9
  151. cirq/ops/phased_x_gate.py +10 -10
  152. cirq/ops/phased_x_z_gate.py +11 -11
  153. cirq/ops/projector.py +6 -6
  154. cirq/ops/qubit_manager.py +6 -6
  155. cirq/ops/qubit_order.py +3 -3
  156. cirq/ops/random_gate_channel.py +4 -4
  157. cirq/ops/raw_types.py +48 -70
  158. cirq/ops/state_preparation_channel.py +3 -3
  159. cirq/ops/swap_gates.py +9 -9
  160. cirq/ops/tags.py +2 -4
  161. cirq/ops/three_qubit_gates.py +20 -38
  162. cirq/ops/two_qubit_diagonal_gate.py +5 -5
  163. cirq/ops/uniform_superposition_gate.py +2 -2
  164. cirq/ops/wait_gate.py +5 -5
  165. cirq/protocols/act_on_protocol_test.py +3 -3
  166. cirq/protocols/apply_channel_protocol.py +8 -14
  167. cirq/protocols/apply_mixture_protocol.py +14 -16
  168. cirq/protocols/apply_mixture_protocol_test.py +5 -6
  169. cirq/protocols/apply_unitary_protocol.py +17 -19
  170. cirq/protocols/circuit_diagram_info_protocol.py +19 -30
  171. cirq/protocols/decompose_protocol.py +30 -34
  172. cirq/protocols/inverse_protocol.py +7 -7
  173. cirq/protocols/json_serialization.py +32 -51
  174. cirq/protocols/json_serialization_test.py +9 -10
  175. cirq/protocols/kraus_protocol.py +4 -4
  176. cirq/protocols/kraus_protocol_test.py +3 -3
  177. cirq/protocols/measurement_key_protocol.py +11 -13
  178. cirq/protocols/mixture_protocol.py +4 -4
  179. cirq/protocols/qasm.py +11 -13
  180. cirq/protocols/qid_shape_protocol.py +6 -8
  181. cirq/qis/clifford_tableau.py +12 -12
  182. cirq/qis/measures.py +7 -7
  183. cirq/qis/quantum_state_representation.py +3 -3
  184. cirq/qis/states.py +51 -51
  185. cirq/sim/classical_simulator.py +10 -10
  186. cirq/sim/clifford/clifford_simulator.py +6 -6
  187. cirq/sim/clifford/clifford_tableau_simulation_state_test.py +1 -3
  188. cirq/sim/clifford/stabilizer_sampler.py +4 -4
  189. cirq/sim/clifford/stabilizer_state_ch_form.py +3 -3
  190. cirq/sim/density_matrix_simulation_state.py +15 -15
  191. cirq/sim/density_matrix_simulator.py +11 -11
  192. cirq/sim/density_matrix_utils.py +9 -9
  193. cirq/sim/mux.py +9 -9
  194. cirq/sim/simulation_product_state.py +9 -9
  195. cirq/sim/simulation_product_state_test.py +2 -2
  196. cirq/sim/simulation_state.py +14 -27
  197. cirq/sim/simulation_state_base.py +8 -24
  198. cirq/sim/simulation_utils.py +3 -4
  199. cirq/sim/simulator.py +28 -43
  200. cirq/sim/simulator_base.py +12 -25
  201. cirq/sim/simulator_base_test.py +6 -6
  202. cirq/sim/simulator_test.py +7 -7
  203. cirq/sim/sparse_simulator.py +8 -8
  204. cirq/sim/state_vector.py +8 -8
  205. cirq/sim/state_vector_simulation_state.py +17 -17
  206. cirq/sim/state_vector_simulator.py +4 -4
  207. cirq/study/flatten_expressions.py +12 -14
  208. cirq/study/resolver.py +9 -11
  209. cirq/study/result.py +11 -24
  210. cirq/study/sweepable.py +5 -5
  211. cirq/study/sweeps.py +27 -40
  212. cirq/testing/circuit_compare.py +5 -5
  213. cirq/testing/consistent_controlled_gate_op_test.py +7 -11
  214. cirq/testing/consistent_protocols.py +10 -10
  215. cirq/testing/consistent_protocols_test.py +7 -7
  216. cirq/testing/consistent_qasm.py +4 -4
  217. cirq/testing/consistent_qasm_test.py +2 -3
  218. cirq/testing/devices.py +4 -5
  219. cirq/testing/equals_tester.py +2 -2
  220. cirq/testing/equivalent_basis_map.py +4 -4
  221. cirq/testing/equivalent_repr_eval.py +3 -3
  222. cirq/testing/json.py +14 -14
  223. cirq/testing/logs.py +3 -3
  224. cirq/testing/no_identifier_qubit.py +2 -3
  225. cirq/testing/random_circuit.py +7 -7
  226. cirq/testing/random_circuit_test.py +3 -3
  227. cirq/transformers/analytical_decompositions/clifford_decomposition.py +16 -16
  228. cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +13 -13
  229. cirq/transformers/analytical_decompositions/cphase_to_fsim.py +5 -5
  230. cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +3 -3
  231. cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +3 -3
  232. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +4 -4
  233. cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +6 -7
  234. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +2 -2
  235. cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +7 -7
  236. cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +4 -4
  237. cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +7 -7
  238. cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +11 -11
  239. cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +5 -5
  240. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +14 -14
  241. cirq/transformers/dynamical_decoupling.py +13 -13
  242. cirq/transformers/dynamical_decoupling_test.py +4 -4
  243. cirq/transformers/eject_phased_paulis.py +16 -16
  244. cirq/transformers/eject_z.py +5 -7
  245. cirq/transformers/gauge_compiling/gauge_compiling.py +38 -38
  246. cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +2 -2
  247. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +8 -8
  248. cirq/transformers/insertion_sort.py +5 -5
  249. cirq/transformers/measurement_transformers.py +14 -14
  250. cirq/transformers/merge_k_qubit_gates_test.py +1 -3
  251. cirq/transformers/merge_single_qubit_gates_test.py +1 -3
  252. cirq/transformers/qubit_management_transformers.py +5 -5
  253. cirq/transformers/routing/initial_mapper.py +4 -4
  254. cirq/transformers/routing/line_initial_mapper.py +9 -9
  255. cirq/transformers/routing/mapping_manager.py +7 -7
  256. cirq/transformers/routing/route_circuit_cqc.py +27 -27
  257. cirq/transformers/routing/visualize_routed_circuit.py +4 -4
  258. cirq/transformers/stratify.py +8 -8
  259. cirq/transformers/synchronize_terminal_measurements.py +6 -6
  260. cirq/transformers/target_gatesets/compilation_target_gateset.py +8 -8
  261. cirq/transformers/target_gatesets/compilation_target_gateset_test.py +2 -2
  262. cirq/transformers/target_gatesets/cz_gateset.py +4 -4
  263. cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +5 -5
  264. cirq/transformers/transformer_api.py +11 -26
  265. cirq/transformers/transformer_primitives.py +24 -36
  266. cirq/transformers/transformer_primitives_test.py +3 -3
  267. cirq/value/classical_data.py +18 -18
  268. cirq/value/condition.py +8 -8
  269. cirq/value/digits.py +7 -7
  270. cirq/value/duration.py +12 -12
  271. cirq/value/linear_dict.py +8 -12
  272. cirq/value/linear_dict_test.py +2 -2
  273. cirq/value/measurement_key.py +8 -8
  274. cirq/value/product_state.py +9 -9
  275. cirq/value/value_equality_attr.py +4 -4
  276. cirq/vis/heatmap.py +23 -35
  277. cirq/work/collector.py +9 -17
  278. cirq/work/observable_grouping.py +4 -7
  279. cirq/work/observable_measurement.py +29 -41
  280. cirq/work/observable_measurement_data.py +14 -14
  281. cirq/work/observable_measurement_test.py +2 -2
  282. cirq/work/observable_settings.py +9 -10
  283. cirq/work/pauli_sum_collector.py +5 -5
  284. cirq/work/sampler.py +17 -17
  285. cirq/work/zeros_sampler.py +3 -3
  286. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/METADATA +1 -1
  287. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/RECORD +290 -290
  288. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/WHEEL +1 -1
  289. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/licenses/LICENSE +0 -0
  290. {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/top_level.txt +0 -0
cirq/circuits/circuit.py CHANGED
@@ -33,19 +33,12 @@ from typing import (
33
33
  Any,
34
34
  Callable,
35
35
  cast,
36
- Dict,
37
- FrozenSet,
38
36
  Iterable,
39
37
  Iterator,
40
- List,
41
38
  Mapping,
42
39
  MutableSequence,
43
- Optional,
44
40
  overload,
45
41
  Sequence,
46
- Set,
47
- Tuple,
48
- Type,
49
42
  TYPE_CHECKING,
50
43
  TypeVar,
51
44
  Union,
@@ -93,7 +86,7 @@ document(
93
86
  """,
94
87
  )
95
88
 
96
- _INT_TYPE = Union[int, np.integer]
89
+ _INT_TYPE = int | np.integer
97
90
 
98
91
 
99
92
  class Alignment(enum.Enum):
@@ -148,7 +141,7 @@ class AbstractCircuit(abc.ABC):
148
141
  """
149
142
 
150
143
  @classmethod
151
- def from_moments(cls: Type[CIRCUIT_TYPE], *moments: Optional[cirq.OP_TREE]) -> CIRCUIT_TYPE:
144
+ def from_moments(cls: type[CIRCUIT_TYPE], *moments: cirq.OP_TREE | None) -> CIRCUIT_TYPE:
152
145
  """Create a circuit from moment op trees.
153
146
 
154
147
  Args:
@@ -166,7 +159,7 @@ class AbstractCircuit(abc.ABC):
166
159
  return cls._from_moments(cls._make_moments(moments))
167
160
 
168
161
  @staticmethod
169
- def _make_moments(moments: Iterable[Optional[cirq.OP_TREE]]) -> Iterator[cirq.Moment]:
162
+ def _make_moments(moments: Iterable[cirq.OP_TREE | None]) -> Iterator[cirq.Moment]:
170
163
  for m in moments:
171
164
  if isinstance(m, Moment):
172
165
  yield m
@@ -177,7 +170,7 @@ class AbstractCircuit(abc.ABC):
177
170
 
178
171
  @classmethod
179
172
  @abc.abstractmethod
180
- def _from_moments(cls: Type[CIRCUIT_TYPE], moments: Iterable[cirq.Moment]) -> CIRCUIT_TYPE:
173
+ def _from_moments(cls: type[CIRCUIT_TYPE], moments: Iterable[cirq.Moment]) -> CIRCUIT_TYPE:
181
174
  """Create a circuit from moments.
182
175
 
183
176
  This must be implemented by subclasses. It provides a more efficient way
@@ -246,11 +239,11 @@ class AbstractCircuit(abc.ABC):
246
239
  pass
247
240
 
248
241
  @overload
249
- def __getitem__(self, key: Tuple[int, cirq.Qid]) -> cirq.Operation:
242
+ def __getitem__(self, key: tuple[int, cirq.Qid]) -> cirq.Operation:
250
243
  pass
251
244
 
252
245
  @overload
253
- def __getitem__(self, key: Tuple[int, Iterable[cirq.Qid]]) -> cirq.Moment:
246
+ def __getitem__(self, key: tuple[int, Iterable[cirq.Qid]]) -> cirq.Moment:
254
247
  pass
255
248
 
256
249
  @overload
@@ -258,11 +251,11 @@ class AbstractCircuit(abc.ABC):
258
251
  pass
259
252
 
260
253
  @overload
261
- def __getitem__(self, key: Tuple[slice, cirq.Qid]) -> Self:
254
+ def __getitem__(self, key: tuple[slice, cirq.Qid]) -> Self:
262
255
  pass
263
256
 
264
257
  @overload
265
- def __getitem__(self, key: Tuple[slice, Iterable[cirq.Qid]]) -> Self:
258
+ def __getitem__(self, key: tuple[slice, Iterable[cirq.Qid]]) -> Self:
266
259
  pass
267
260
 
268
261
  def __getitem__(self, key):
@@ -318,7 +311,7 @@ class AbstractCircuit(abc.ABC):
318
311
 
319
312
  def _first_moment_operating_on(
320
313
  self, qubits: Iterable[cirq.Qid], indices: Iterable[int]
321
- ) -> Optional[int]:
314
+ ) -> int | None:
322
315
  qubits = frozenset(qubits)
323
316
  for m in indices:
324
317
  if self._has_op_at(m, qubits):
@@ -329,8 +322,8 @@ class AbstractCircuit(abc.ABC):
329
322
  self,
330
323
  qubits: Iterable[cirq.Qid],
331
324
  start_moment_index: int = 0,
332
- max_distance: Optional[int] = None,
333
- ) -> Optional[int]:
325
+ max_distance: int | None = None,
326
+ ) -> int | None:
334
327
  """Finds the index of the next moment that touches the given qubits.
335
328
 
336
329
  Args:
@@ -360,7 +353,7 @@ class AbstractCircuit(abc.ABC):
360
353
 
361
354
  def next_moments_operating_on(
362
355
  self, qubits: Iterable[cirq.Qid], start_moment_index: int = 0
363
- ) -> Dict[cirq.Qid, int]:
356
+ ) -> dict[cirq.Qid, int]:
364
357
  """Finds the index of the next moment that touches each qubit.
365
358
 
366
359
  Args:
@@ -383,9 +376,9 @@ class AbstractCircuit(abc.ABC):
383
376
  def prev_moment_operating_on(
384
377
  self,
385
378
  qubits: Sequence[cirq.Qid],
386
- end_moment_index: Optional[int] = None,
387
- max_distance: Optional[int] = None,
388
- ) -> Optional[int]:
379
+ end_moment_index: int | None = None,
380
+ max_distance: int | None = None,
381
+ ) -> int | None:
389
382
  """Finds the index of the previous moment that touches the given qubits.
390
383
 
391
384
  Args:
@@ -427,10 +420,10 @@ class AbstractCircuit(abc.ABC):
427
420
 
428
421
  def reachable_frontier_from(
429
422
  self,
430
- start_frontier: Dict[cirq.Qid, int],
423
+ start_frontier: dict[cirq.Qid, int],
431
424
  *,
432
425
  is_blocker: Callable[[cirq.Operation], bool] = lambda op: False,
433
- ) -> Dict[cirq.Qid, int]:
426
+ ) -> dict[cirq.Qid, int]:
434
427
  """Determines how far can be reached into a circuit under certain rules.
435
428
 
436
429
  The location L = (qubit, moment_index) is *reachable* if and only if the
@@ -566,7 +559,7 @@ class AbstractCircuit(abc.ABC):
566
559
  where i is the moment index, q is the qubit, and end_frontier is the
567
560
  result of this method.
568
561
  """
569
- active: Set[cirq.Qid] = set()
562
+ active: set[cirq.Qid] = set()
570
563
  end_frontier = {}
571
564
  queue = BucketPriorityQueue[ops.Operation](drop_duplicate_entries=True)
572
565
 
@@ -610,10 +603,10 @@ class AbstractCircuit(abc.ABC):
610
603
 
611
604
  def findall_operations_between(
612
605
  self,
613
- start_frontier: Dict[cirq.Qid, int],
614
- end_frontier: Dict[cirq.Qid, int],
606
+ start_frontier: dict[cirq.Qid, int],
607
+ end_frontier: dict[cirq.Qid, int],
615
608
  omit_crossing_operations: bool = False,
616
- ) -> List[Tuple[int, cirq.Operation]]:
609
+ ) -> list[tuple[int, cirq.Operation]]:
617
610
  """Finds operations between the two given frontiers.
618
611
 
619
612
  If a qubit is in `start_frontier` but not `end_frontier`, its end index
@@ -658,9 +651,9 @@ class AbstractCircuit(abc.ABC):
658
651
 
659
652
  def findall_operations_until_blocked(
660
653
  self,
661
- start_frontier: Dict[cirq.Qid, int],
654
+ start_frontier: dict[cirq.Qid, int],
662
655
  is_blocker: Callable[[cirq.Operation], bool] = lambda op: False,
663
- ) -> List[Tuple[int, cirq.Operation]]:
656
+ ) -> list[tuple[int, cirq.Operation]]:
664
657
  """Finds all operations until a blocking operation is hit.
665
658
 
666
659
  An operation is considered blocking if both of the following hold:
@@ -746,11 +739,11 @@ class AbstractCircuit(abc.ABC):
746
739
  and the second item is the operation itself.
747
740
 
748
741
  """
749
- op_list: List[Tuple[int, ops.Operation]] = []
742
+ op_list: list[tuple[int, ops.Operation]] = []
750
743
  if not start_frontier:
751
744
  return op_list
752
745
  start_index = min(start_frontier.values())
753
- blocked_qubits: Set[cirq.Qid] = set()
746
+ blocked_qubits: set[cirq.Qid] = set()
754
747
  for index, moment in enumerate(self[start_index:], start_index):
755
748
  active_qubits = set(q for q, s in start_frontier.items() if s <= index)
756
749
  for op in moment.operations:
@@ -762,7 +755,7 @@ class AbstractCircuit(abc.ABC):
762
755
  break
763
756
  return op_list
764
757
 
765
- def operation_at(self, qubit: cirq.Qid, moment_index: int) -> Optional[cirq.Operation]:
758
+ def operation_at(self, qubit: cirq.Qid, moment_index: int) -> cirq.Operation | None:
766
759
  """Finds the operation on a qubit within a moment, if any.
767
760
 
768
761
  Args:
@@ -780,7 +773,7 @@ class AbstractCircuit(abc.ABC):
780
773
 
781
774
  def findall_operations(
782
775
  self, predicate: Callable[[cirq.Operation], bool]
783
- ) -> Iterable[Tuple[int, cirq.Operation]]:
776
+ ) -> Iterable[tuple[int, cirq.Operation]]:
784
777
  """Find the locations of all operations that satisfy a given condition.
785
778
 
786
779
  This returns an iterator of (index, operation) tuples where each
@@ -800,8 +793,8 @@ class AbstractCircuit(abc.ABC):
800
793
  yield index, op
801
794
 
802
795
  def findall_operations_with_gate_type(
803
- self, gate_type: Type[_TGate]
804
- ) -> Iterable[Tuple[int, cirq.GateOperation, _TGate]]:
796
+ self, gate_type: type[_TGate]
797
+ ) -> Iterable[tuple[int, cirq.GateOperation, _TGate]]:
805
798
  """Find the locations of all gate operations of a given type.
806
799
 
807
800
  Args:
@@ -922,7 +915,7 @@ class AbstractCircuit(abc.ABC):
922
915
  qubits
923
916
  )
924
917
 
925
- def all_qubits(self) -> FrozenSet[cirq.Qid]:
918
+ def all_qubits(self) -> frozenset[cirq.Qid]:
926
919
  """Returns the qubits acted upon by Operations in this circuit.
927
920
 
928
921
  Returns: FrozenSet of `cirq.Qid` objects acted on by all operations
@@ -956,7 +949,7 @@ class AbstractCircuit(abc.ABC):
956
949
 
957
950
  def qid_shape(
958
951
  self, qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT
959
- ) -> Tuple[int, ...]:
952
+ ) -> tuple[int, ...]:
960
953
  """Get the qubit shapes of all qubits in this circuit.
961
954
 
962
955
  Returns: A tuple containing the dimensions (shape) of all qudits
@@ -965,12 +958,12 @@ class AbstractCircuit(abc.ABC):
965
958
  qids = ops.QubitOrder.as_qubit_order(qubit_order).order_for(self.all_qubits())
966
959
  return protocols.qid_shape(qids)
967
960
 
968
- def all_measurement_key_objs(self) -> FrozenSet[cirq.MeasurementKey]:
961
+ def all_measurement_key_objs(self) -> frozenset[cirq.MeasurementKey]:
969
962
  return frozenset(
970
963
  key for op in self.all_operations() for key in protocols.measurement_key_objs(op)
971
964
  )
972
965
 
973
- def _measurement_key_objs_(self) -> FrozenSet[cirq.MeasurementKey]:
966
+ def _measurement_key_objs_(self) -> frozenset[cirq.MeasurementKey]:
974
967
  """Returns the set of all measurement keys in this circuit.
975
968
 
976
969
  Returns: FrozenSet of `cirq.MeasurementKey` objects that are
@@ -978,7 +971,7 @@ class AbstractCircuit(abc.ABC):
978
971
  """
979
972
  return self.all_measurement_key_objs()
980
973
 
981
- def all_measurement_key_names(self) -> FrozenSet[str]:
974
+ def all_measurement_key_names(self) -> frozenset[str]:
982
975
  """Returns the set of all measurement key names in this circuit.
983
976
 
984
977
  Returns: FrozenSet of strings that are the measurement key
@@ -988,7 +981,7 @@ class AbstractCircuit(abc.ABC):
988
981
  key for op in self.all_operations() for key in protocols.measurement_key_names(op)
989
982
  )
990
983
 
991
- def _measurement_key_names_(self) -> FrozenSet[str]:
984
+ def _measurement_key_names_(self) -> frozenset[str]:
992
985
  return self.all_measurement_key_names()
993
986
 
994
987
  def _with_measurement_key_mapping_(self, key_map: Mapping[str, str]):
@@ -996,16 +989,16 @@ class AbstractCircuit(abc.ABC):
996
989
  protocols.with_measurement_key_mapping(moment, key_map) for moment in self.moments
997
990
  )
998
991
 
999
- def _with_key_path_(self, path: Tuple[str, ...]):
992
+ def _with_key_path_(self, path: tuple[str, ...]):
1000
993
  return self._from_moments(protocols.with_key_path(moment, path) for moment in self.moments)
1001
994
 
1002
- def _with_key_path_prefix_(self, prefix: Tuple[str, ...]):
995
+ def _with_key_path_prefix_(self, prefix: tuple[str, ...]):
1003
996
  return self._from_moments(
1004
997
  protocols.with_key_path_prefix(moment, prefix) for moment in self.moments
1005
998
  )
1006
999
 
1007
1000
  def _with_rescoped_keys_(
1008
- self, path: Tuple[str, ...], bindable_keys: FrozenSet[cirq.MeasurementKey]
1001
+ self, path: tuple[str, ...], bindable_keys: frozenset[cirq.MeasurementKey]
1009
1002
  ):
1010
1003
  moments = []
1011
1004
  for moment in self.moments:
@@ -1014,7 +1007,7 @@ class AbstractCircuit(abc.ABC):
1014
1007
  bindable_keys |= protocols.measurement_key_objs(new_moment)
1015
1008
  return self._from_moments(moments)
1016
1009
 
1017
- def _qid_shape_(self) -> Tuple[int, ...]:
1010
+ def _qid_shape_(self) -> tuple[int, ...]:
1018
1011
  return self.qid_shape()
1019
1012
 
1020
1013
  def _has_unitary_(self) -> bool:
@@ -1029,7 +1022,7 @@ class AbstractCircuit(abc.ABC):
1029
1022
  )
1030
1023
  return all(protocols.has_unitary(e) for e in unitary_ops)
1031
1024
 
1032
- def _unitary_(self) -> Union[np.ndarray, NotImplementedType]:
1025
+ def _unitary_(self) -> np.ndarray | NotImplementedType:
1033
1026
  """Converts the circuit into a unitary matrix, if possible.
1034
1027
 
1035
1028
  If the circuit contains any non-terminal measurements, the conversion
@@ -1047,7 +1040,7 @@ class AbstractCircuit(abc.ABC):
1047
1040
  qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
1048
1041
  qubits_that_should_be_present: Iterable[cirq.Qid] = (),
1049
1042
  ignore_terminal_measurements: bool = True,
1050
- dtype: Type[np.complexfloating] = np.complex128,
1043
+ dtype: type[np.complexfloating] = np.complex128,
1051
1044
  ) -> np.ndarray:
1052
1045
  """Converts the circuit into a unitary matrix, if possible.
1053
1046
 
@@ -1124,7 +1117,7 @@ class AbstractCircuit(abc.ABC):
1124
1117
  initial_state: cirq.STATE_VECTOR_LIKE = 0,
1125
1118
  qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
1126
1119
  ignore_terminal_measurements: bool = False,
1127
- dtype: Type[np.complexfloating] = np.complex128,
1120
+ dtype: type[np.complexfloating] = np.complex128,
1128
1121
  param_resolver: cirq.ParamResolverOrSimilarType = None,
1129
1122
  seed: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
1130
1123
  ) -> np.ndarray:
@@ -1183,7 +1176,7 @@ class AbstractCircuit(abc.ABC):
1183
1176
  use_unicode_characters: bool = True,
1184
1177
  transpose: bool = False,
1185
1178
  include_tags: bool = True,
1186
- precision: Optional[int] = 3,
1179
+ precision: int | None = 3,
1187
1180
  qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
1188
1181
  ) -> str:
1189
1182
  """Returns text containing a diagram describing the circuit.
@@ -1217,15 +1210,15 @@ class AbstractCircuit(abc.ABC):
1217
1210
  self,
1218
1211
  *,
1219
1212
  use_unicode_characters: bool = True,
1220
- qubit_namer: Optional[Callable[[cirq.Qid], str]] = None,
1213
+ qubit_namer: Callable[[cirq.Qid], str] | None = None,
1221
1214
  transpose: bool = False,
1222
1215
  include_tags: bool = True,
1223
1216
  draw_moment_groups: bool = True,
1224
- precision: Optional[int] = 3,
1217
+ precision: int | None = 3,
1225
1218
  qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
1226
- get_circuit_diagram_info: Optional[
1227
- Callable[[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo]
1228
- ] = None,
1219
+ get_circuit_diagram_info: (
1220
+ Callable[[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo] | None
1221
+ ) = None,
1229
1222
  ) -> cirq.TextDiagramDrawer:
1230
1223
  """Returns a TextDiagramDrawer with the circuit drawn into it.
1231
1224
 
@@ -1276,7 +1269,7 @@ class AbstractCircuit(abc.ABC):
1276
1269
  diagram.write(0, max(label_map.values(), default=0) + 1, 'global phase:')
1277
1270
  first_annotation_row += 1
1278
1271
 
1279
- moment_groups: List[Tuple[int, int]] = []
1272
+ moment_groups: list[tuple[int, int]] = []
1280
1273
  for moment in self.moments:
1281
1274
  _draw_moment_in_diagram(
1282
1275
  moment=moment,
@@ -1311,7 +1304,7 @@ class AbstractCircuit(abc.ABC):
1311
1304
 
1312
1305
  def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> Self:
1313
1306
  changed = False
1314
- resolved_moments: List[cirq.Moment] = []
1307
+ resolved_moments: list[cirq.Moment] = []
1315
1308
  for moment in self:
1316
1309
  resolved_moment = protocols.resolve_parameters(moment, resolver, recursive)
1317
1310
  if resolved_moment is not moment:
@@ -1321,7 +1314,7 @@ class AbstractCircuit(abc.ABC):
1321
1314
  return self # pragma: no cover
1322
1315
  return self._from_moments(resolved_moments)
1323
1316
 
1324
- def _qasm_(self, args: Optional[cirq.QasmArgs] = None) -> str:
1317
+ def _qasm_(self, args: cirq.QasmArgs | None = None) -> str:
1325
1318
  if args is None:
1326
1319
  output = self._to_qasm_output()
1327
1320
  else:
@@ -1330,7 +1323,7 @@ class AbstractCircuit(abc.ABC):
1330
1323
 
1331
1324
  def _to_qasm_output(
1332
1325
  self,
1333
- header: Optional[str] = None,
1326
+ header: str | None = None,
1334
1327
  precision: int = 10,
1335
1328
  qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
1336
1329
  version: str = '2.0',
@@ -1359,7 +1352,7 @@ class AbstractCircuit(abc.ABC):
1359
1352
 
1360
1353
  def to_qasm(
1361
1354
  self,
1362
- header: Optional[str] = None,
1355
+ header: str | None = None,
1363
1356
  precision: int = 10,
1364
1357
  qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
1365
1358
  version: str = '2.0',
@@ -1380,8 +1373,8 @@ class AbstractCircuit(abc.ABC):
1380
1373
 
1381
1374
  def save_qasm(
1382
1375
  self,
1383
- file_path: Union[str, bytes, int],
1384
- header: Optional[str] = None,
1376
+ file_path: str | bytes | int,
1377
+ header: str | None = None,
1385
1378
  precision: int = 10,
1386
1379
  qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
1387
1380
  ) -> None:
@@ -1405,7 +1398,7 @@ class AbstractCircuit(abc.ABC):
1405
1398
  return cls(moments, strategy=InsertStrategy.EARLIEST)
1406
1399
 
1407
1400
  def zip(
1408
- *circuits: cirq.AbstractCircuit, align: Union[cirq.Alignment, str] = Alignment.LEFT
1401
+ *circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
1409
1402
  ) -> cirq.AbstractCircuit:
1410
1403
  """Combines operations from circuits in a moment-by-moment fashion.
1411
1404
 
@@ -1481,7 +1474,7 @@ class AbstractCircuit(abc.ABC):
1481
1474
  return result
1482
1475
 
1483
1476
  def concat_ragged(
1484
- *circuits: cirq.AbstractCircuit, align: Union[cirq.Alignment, str] = Alignment.LEFT
1477
+ *circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
1485
1478
  ) -> cirq.AbstractCircuit:
1486
1479
  """Concatenates circuits, overlapping them if possible due to ragged edges.
1487
1480
 
@@ -1537,7 +1530,7 @@ class AbstractCircuit(abc.ABC):
1537
1530
 
1538
1531
  return cirq.Circuit(buffer[offset : offset + n_acc])
1539
1532
 
1540
- def get_independent_qubit_sets(self) -> List[Set[cirq.Qid]]:
1533
+ def get_independent_qubit_sets(self) -> list[set[cirq.Qid]]:
1541
1534
  """Divide circuit's qubits into independent qubit sets.
1542
1535
 
1543
1536
  Independent qubit sets are the qubit sets such that there are
@@ -1616,7 +1609,7 @@ class AbstractCircuit(abc.ABC):
1616
1609
  # moments.
1617
1610
  return (self._from_moments(m[qubits] for m in self.moments) for qubits in qubit_factors)
1618
1611
 
1619
- def _control_keys_(self) -> FrozenSet[cirq.MeasurementKey]:
1612
+ def _control_keys_(self) -> frozenset[cirq.MeasurementKey]:
1620
1613
  controls = frozenset(k for op in self.all_operations() for k in protocols.control_keys(op))
1621
1614
  return controls - protocols.measurement_key_objs(self)
1622
1615
 
@@ -1626,7 +1619,7 @@ def _overlap_collision_time(
1626
1619
  ) -> int:
1627
1620
  # Tracks the first used moment index for each qubit in c2.
1628
1621
  # Tracks the complementary last used moment index for each qubit in c1.
1629
- seen_times: Dict[cirq.Qid, int] = {}
1622
+ seen_times: dict[cirq.Qid, int] = {}
1630
1623
 
1631
1624
  # Start scanning from end of first and start of second.
1632
1625
  if align == Alignment.LEFT:
@@ -1667,7 +1660,7 @@ def _concat_ragged_helper(
1667
1660
  buf: MutableSequence[cirq.Moment],
1668
1661
  c2: Sequence[cirq.Moment],
1669
1662
  align: cirq.Alignment,
1670
- ) -> Tuple[int, int]:
1663
+ ) -> tuple[int, int]:
1671
1664
  n2 = len(c2)
1672
1665
  shift = _overlap_collision_time(buf[c1_offset : c1_offset + n1], c2, align)
1673
1666
  c2_offset = c1_offset + n1 - shift
@@ -1772,17 +1765,17 @@ class Circuit(AbstractCircuit):
1772
1765
  together. This option does not affect later insertions into the
1773
1766
  circuit.
1774
1767
  """
1775
- self._placement_cache: Optional[_PlacementCache] = _PlacementCache()
1776
- self._moments: List[cirq.Moment] = []
1768
+ self._placement_cache: _PlacementCache | None = _PlacementCache()
1769
+ self._moments: list[cirq.Moment] = []
1777
1770
 
1778
1771
  # Implementation note: the following cached properties are set lazily and then
1779
1772
  # invalidated and reset to None in `self._mutated()`, which is called any time
1780
1773
  # `self._moments` is changed.
1781
- self._all_qubits: Optional[FrozenSet[cirq.Qid]] = None
1782
- self._frozen: Optional[cirq.FrozenCircuit] = None
1783
- self._is_measurement: Optional[bool] = None
1784
- self._is_parameterized: Optional[bool] = None
1785
- self._parameter_names: Optional[AbstractSet[str]] = None
1774
+ self._all_qubits: frozenset[cirq.Qid] | None = None
1775
+ self._frozen: cirq.FrozenCircuit | None = None
1776
+ self._is_measurement: bool | None = None
1777
+ self._is_parameterized: bool | None = None
1778
+ self._parameter_names: AbstractSet[str] | None = None
1786
1779
  if not contents:
1787
1780
  return
1788
1781
  flattened_contents = tuple(ops.flatten_to_ops_or_moments(contents))
@@ -1837,8 +1830,8 @@ class Circuit(AbstractCircuit):
1837
1830
 
1838
1831
  # We also maintain the dict from moment index to moments/ops that go into it, for use when
1839
1832
  # building the actual moments at the end.
1840
- op_lists_by_index: Dict[int, List[cirq.Operation]] = defaultdict(list)
1841
- moments_by_index: Dict[int, cirq.Moment] = {}
1833
+ op_lists_by_index: dict[int, list[cirq.Operation]] = defaultdict(list)
1834
+ moments_by_index: dict[int, cirq.Moment] = {}
1842
1835
 
1843
1836
  # "mop" means current moment-or-operation
1844
1837
  for mop in ops.flatten_to_ops_or_moments(contents):
@@ -1875,7 +1868,7 @@ class Circuit(AbstractCircuit):
1875
1868
  def unfreeze(self, copy: bool = True) -> cirq.Circuit:
1876
1869
  return self.copy() if copy else self
1877
1870
 
1878
- def all_qubits(self) -> FrozenSet[cirq.Qid]:
1871
+ def all_qubits(self) -> frozenset[cirq.Qid]:
1879
1872
  if self._all_qubits is None:
1880
1873
  self._all_qubits = super().all_qubits()
1881
1874
  return self._all_qubits
@@ -1925,7 +1918,7 @@ class Circuit(AbstractCircuit):
1925
1918
 
1926
1919
  # pylint: enable=function-redefined
1927
1920
 
1928
- def __delitem__(self, key: Union[int, slice]):
1921
+ def __delitem__(self, key: int | slice):
1929
1922
  del self._moments[key]
1930
1923
  self._mutated()
1931
1924
 
@@ -1993,21 +1986,21 @@ class Circuit(AbstractCircuit):
1993
1986
  __hash__ = None # type: ignore
1994
1987
 
1995
1988
  def concat_ragged(
1996
- *circuits: cirq.AbstractCircuit, align: Union[cirq.Alignment, str] = Alignment.LEFT
1989
+ *circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
1997
1990
  ) -> cirq.Circuit:
1998
1991
  return AbstractCircuit.concat_ragged(*circuits, align=align).unfreeze(copy=False)
1999
1992
 
2000
1993
  concat_ragged.__doc__ = AbstractCircuit.concat_ragged.__doc__
2001
1994
 
2002
1995
  def zip(
2003
- *circuits: cirq.AbstractCircuit, align: Union[cirq.Alignment, str] = Alignment.LEFT
1996
+ *circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
2004
1997
  ) -> cirq.Circuit:
2005
1998
  return AbstractCircuit.zip(*circuits, align=align).unfreeze(copy=False)
2006
1999
 
2007
2000
  zip.__doc__ = AbstractCircuit.zip.__doc__
2008
2001
 
2009
2002
  def transform_qubits(
2010
- self, qubit_map: Union[Dict[cirq.Qid, cirq.Qid], Callable[[cirq.Qid], cirq.Qid]]
2003
+ self, qubit_map: dict[cirq.Qid, cirq.Qid] | Callable[[cirq.Qid], cirq.Qid]
2011
2004
  ) -> cirq.Circuit:
2012
2005
  """Returns the same circuit, but with different qubits.
2013
2006
 
@@ -2055,7 +2048,7 @@ class Circuit(AbstractCircuit):
2055
2048
  return Circuit(op_list)
2056
2049
 
2057
2050
  def earliest_available_moment(
2058
- self, op: cirq.Operation, *, end_moment_index: Optional[int] = None
2051
+ self, op: cirq.Operation, *, end_moment_index: int | None = None
2059
2052
  ) -> int:
2060
2053
  """Finds the index of the earliest (i.e. left most) moment which can accommodate `op`.
2061
2054
 
@@ -2148,7 +2141,7 @@ class Circuit(AbstractCircuit):
2148
2141
  and not all(
2149
2142
  (strategy is InsertStrategy.EARLIEST and self._can_add_op_at(k, op))
2150
2143
  or (k > 0 and self._can_add_op_at(k - 1, op))
2151
- for op in cast(List[cirq.Operation], batch)
2144
+ for op in cast(list[cirq.Operation], batch)
2152
2145
  )
2153
2146
  ):
2154
2147
  self._moments.insert(k, Moment())
@@ -2227,10 +2220,10 @@ class Circuit(AbstractCircuit):
2227
2220
 
2228
2221
  def _push_frontier(
2229
2222
  self,
2230
- early_frontier: Dict[cirq.Qid, int],
2231
- late_frontier: Dict[cirq.Qid, int],
2232
- update_qubits: Optional[Iterable[cirq.Qid]] = None,
2233
- ) -> Tuple[int, int]:
2223
+ early_frontier: dict[cirq.Qid, int],
2224
+ late_frontier: dict[cirq.Qid, int],
2225
+ update_qubits: Iterable[cirq.Qid] | None = None,
2226
+ ) -> tuple[int, int]:
2234
2227
  """Inserts moments to separate two frontiers.
2235
2228
 
2236
2229
  After insertion n_new moments, the following holds:
@@ -2292,15 +2285,15 @@ class Circuit(AbstractCircuit):
2292
2285
  raise ValueError('operations and insertion_indices must have the same length.')
2293
2286
  self._moments += [Moment() for _ in range(1 + max(insertion_indices) - len(self))]
2294
2287
  self._mutated()
2295
- moment_to_ops: Dict[int, List[cirq.Operation]] = defaultdict(list)
2288
+ moment_to_ops: dict[int, list[cirq.Operation]] = defaultdict(list)
2296
2289
  for op_index, moment_index in enumerate(insertion_indices):
2297
2290
  moment_to_ops[moment_index].append(operations[op_index])
2298
2291
  for moment_index, new_ops in moment_to_ops.items():
2299
2292
  self._moments[moment_index] = self._moments[moment_index].with_operations(*new_ops)
2300
2293
 
2301
2294
  def insert_at_frontier(
2302
- self, operations: cirq.OP_TREE, start: int, frontier: Optional[Dict[cirq.Qid, int]] = None
2303
- ) -> Dict[cirq.Qid, int]:
2295
+ self, operations: cirq.OP_TREE, start: int, frontier: dict[cirq.Qid, int] | None = None
2296
+ ) -> dict[cirq.Qid, int]:
2304
2297
  """Inserts operations inline at frontier.
2305
2298
 
2306
2299
  Args:
@@ -2334,7 +2327,7 @@ class Circuit(AbstractCircuit):
2334
2327
 
2335
2328
  return frontier
2336
2329
 
2337
- def batch_remove(self, removals: Iterable[Tuple[int, cirq.Operation]]) -> None:
2330
+ def batch_remove(self, removals: Iterable[tuple[int, cirq.Operation]]) -> None:
2338
2331
  """Removes several operations from a circuit.
2339
2332
 
2340
2333
  Args:
@@ -2358,7 +2351,7 @@ class Circuit(AbstractCircuit):
2358
2351
  self._mutated()
2359
2352
 
2360
2353
  def batch_replace(
2361
- self, replacements: Iterable[Tuple[int, cirq.Operation, cirq.Operation]]
2354
+ self, replacements: Iterable[tuple[int, cirq.Operation, cirq.Operation]]
2362
2355
  ) -> None:
2363
2356
  """Replaces several operations in a circuit with new operations.
2364
2357
 
@@ -2382,7 +2375,7 @@ class Circuit(AbstractCircuit):
2382
2375
  self._moments = copy._moments
2383
2376
  self._mutated()
2384
2377
 
2385
- def batch_insert_into(self, insert_intos: Iterable[Tuple[int, cirq.OP_TREE]]) -> None:
2378
+ def batch_insert_into(self, insert_intos: Iterable[tuple[int, cirq.OP_TREE]]) -> None:
2386
2379
  """Inserts operations into empty spaces in existing moments.
2387
2380
 
2388
2381
  If any of the insertions fails (due to colliding with an existing
@@ -2403,7 +2396,7 @@ class Circuit(AbstractCircuit):
2403
2396
  self._moments = copy._moments
2404
2397
  self._mutated()
2405
2398
 
2406
- def batch_insert(self, insertions: Iterable[Tuple[int, cirq.OP_TREE]]) -> None:
2399
+ def batch_insert(self, insertions: Iterable[tuple[int, cirq.OP_TREE]]) -> None:
2407
2400
  """Applies a batched insert operation to the circuit.
2408
2401
 
2409
2402
  Transparently handles the fact that earlier insertions may shift
@@ -2495,8 +2488,8 @@ class Circuit(AbstractCircuit):
2495
2488
  def _pick_inserted_ops_moment_indices(
2496
2489
  operations: Sequence[cirq.Operation],
2497
2490
  start: int = 0,
2498
- frontier: Optional[Dict[cirq.Qid, int]] = None,
2499
- ) -> Tuple[Sequence[int], Dict[cirq.Qid, int]]:
2491
+ frontier: dict[cirq.Qid, int] | None = None,
2492
+ ) -> tuple[Sequence[int], dict[cirq.Qid, int]]:
2500
2493
  """Greedily assigns operations to moments.
2501
2494
 
2502
2495
  Args:
@@ -2541,9 +2534,9 @@ def _draw_moment_annotations(
2541
2534
  moment: cirq.Moment,
2542
2535
  col: int,
2543
2536
  use_unicode_characters: bool,
2544
- label_map: Dict[cirq.LabelEntity, int],
2537
+ label_map: dict[cirq.LabelEntity, int],
2545
2538
  out_diagram: cirq.TextDiagramDrawer,
2546
- precision: Optional[int],
2539
+ precision: int | None,
2547
2540
  get_circuit_diagram_info: Callable[
2548
2541
  [cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo
2549
2542
  ],
@@ -2572,13 +2565,13 @@ def _draw_moment_in_diagram(
2572
2565
  *,
2573
2566
  moment: cirq.Moment,
2574
2567
  use_unicode_characters: bool,
2575
- label_map: Dict[cirq.LabelEntity, int],
2568
+ label_map: dict[cirq.LabelEntity, int],
2576
2569
  out_diagram: cirq.TextDiagramDrawer,
2577
- precision: Optional[int],
2578
- moment_groups: List[Tuple[int, int]],
2579
- get_circuit_diagram_info: Optional[
2580
- Callable[[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo]
2581
- ],
2570
+ precision: int | None,
2571
+ moment_groups: list[tuple[int, int]],
2572
+ get_circuit_diagram_info: (
2573
+ Callable[[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo] | None
2574
+ ),
2582
2575
  include_tags: bool,
2583
2576
  first_annotation_row: int,
2584
2577
  transpose: bool,
@@ -2662,7 +2655,7 @@ def _draw_moment_in_diagram(
2662
2655
  moment_groups.append((x0, max_x))
2663
2656
 
2664
2657
 
2665
- def _get_global_phase_and_tags_for_op(op: cirq.Operation) -> Tuple[Optional[complex], List[Any]]:
2658
+ def _get_global_phase_and_tags_for_op(op: cirq.Operation) -> tuple[complex | None, list[Any]]:
2666
2659
  if isinstance(op.gate, ops.GlobalPhaseGate):
2667
2660
  return complex(op.gate.coefficient), list(op.tags)
2668
2661
  elif isinstance(op.untagged, CircuitOperation):
@@ -2671,9 +2664,9 @@ def _get_global_phase_and_tags_for_op(op: cirq.Operation) -> Tuple[Optional[comp
2671
2664
  return None, []
2672
2665
 
2673
2666
 
2674
- def _get_global_phase_and_tags_for_ops(op_list: Any) -> Tuple[Optional[complex], List[Any]]:
2675
- global_phase: Optional[complex] = None
2676
- tags: List[Any] = []
2667
+ def _get_global_phase_and_tags_for_ops(op_list: Any) -> tuple[complex | None, list[Any]]:
2668
+ global_phase: complex | None = None
2669
+ tags: list[Any] = []
2677
2670
  for op in op_list:
2678
2671
  op_phase, op_tags = _get_global_phase_and_tags_for_op(op)
2679
2672
  if op_phase:
@@ -2685,7 +2678,7 @@ def _get_global_phase_and_tags_for_ops(op_list: Any) -> Tuple[Optional[complex],
2685
2678
  return global_phase, tags
2686
2679
 
2687
2680
 
2688
- def _formatted_phase(coefficient: complex, unicode: bool, precision: Optional[int]) -> str:
2681
+ def _formatted_phase(coefficient: complex, unicode: bool, precision: int | None) -> str:
2689
2682
  h = math.atan2(coefficient.imag, coefficient.real) / math.pi
2690
2683
  unit = 'π' if unicode else 'pi'
2691
2684
  if h == 1:
@@ -2694,7 +2687,7 @@ def _formatted_phase(coefficient: complex, unicode: bool, precision: Optional[in
2694
2687
 
2695
2688
 
2696
2689
  def _draw_moment_groups_in_diagram(
2697
- moment_groups: List[Tuple[int, int]],
2690
+ moment_groups: list[tuple[int, int]],
2698
2691
  use_unicode_characters: bool,
2699
2692
  out_diagram: cirq.TextDiagramDrawer,
2700
2693
  ):
@@ -2728,8 +2721,8 @@ def _draw_moment_groups_in_diagram(
2728
2721
  def _apply_unitary_circuit(
2729
2722
  circuit: cirq.AbstractCircuit,
2730
2723
  state: np.ndarray,
2731
- qubits: Tuple[cirq.Qid, ...],
2732
- dtype: Type[np.complexfloating],
2724
+ qubits: tuple[cirq.Qid, ...],
2725
+ dtype: type[np.complexfloating],
2733
2726
  ) -> np.ndarray:
2734
2727
  """Applies a circuit's unitary effect to the given vector or matrix.
2735
2728
 
@@ -2792,14 +2785,14 @@ _TKey = TypeVar('_TKey')
2792
2785
  @overload
2793
2786
  def _group_until_different(
2794
2787
  items: Iterable[_TIn], key: Callable[[_TIn], _TKey]
2795
- ) -> Iterable[Tuple[_TKey, List[_TIn]]]:
2788
+ ) -> Iterable[tuple[_TKey, list[_TIn]]]:
2796
2789
  pass
2797
2790
 
2798
2791
 
2799
2792
  @overload
2800
2793
  def _group_until_different(
2801
2794
  items: Iterable[_TIn], key: Callable[[_TIn], _TKey], val: Callable[[_TIn], _TOut]
2802
- ) -> Iterable[Tuple[_TKey, List[_TOut]]]:
2795
+ ) -> Iterable[tuple[_TKey, list[_TOut]]]:
2803
2796
  pass
2804
2797
 
2805
2798
 
@@ -2829,7 +2822,7 @@ def _group_until_different(items: Iterable[_TIn], key: Callable[[_TIn], _TKey],
2829
2822
  return ((k, [val(i) for i in v]) for (k, v) in itertools.groupby(items, key))
2830
2823
 
2831
2824
 
2832
- def _group_into_moment_compatible(inputs: Sequence[_MOMENT_OR_OP]) -> Iterator[List[_MOMENT_OR_OP]]:
2825
+ def _group_into_moment_compatible(inputs: Sequence[_MOMENT_OR_OP]) -> Iterator[list[_MOMENT_OR_OP]]:
2833
2826
  """Groups sequential ops into those that can coexist in a single moment.
2834
2827
 
2835
2828
  This function will go through the input sequence in order, emitting lists of sequential
@@ -2844,8 +2837,8 @@ def _group_into_moment_compatible(inputs: Sequence[_MOMENT_OR_OP]) -> Iterator[L
2844
2837
  [X(a), X(a), X(b)] -> [[X(a)], [X(a), X(b)]]
2845
2838
  [X(a), Moment(X(b)), X(c)] -> [[X(a)], [Moment(X(b))], [X(c)]]
2846
2839
  """
2847
- batch: List[_MOMENT_OR_OP] = []
2848
- batch_qubits: Set[cirq.Qid] = set()
2840
+ batch: list[_MOMENT_OR_OP] = []
2841
+ batch_qubits: set[cirq.Qid] = set()
2849
2842
  for mop in inputs:
2850
2843
  is_moment = isinstance(mop, cirq.Moment)
2851
2844
  if (is_moment and batch) or not batch_qubits.isdisjoint(mop.qubits):
@@ -2863,10 +2856,10 @@ def _group_into_moment_compatible(inputs: Sequence[_MOMENT_OR_OP]) -> Iterator[L
2863
2856
 
2864
2857
  def get_earliest_accommodating_moment_index(
2865
2858
  moment_or_operation: _MOMENT_OR_OP,
2866
- qubit_indices: Dict[cirq.Qid, int],
2867
- mkey_indices: Dict[cirq.MeasurementKey, int],
2868
- ckey_indices: Dict[cirq.MeasurementKey, int],
2869
- length: Optional[int] = None,
2859
+ qubit_indices: dict[cirq.Qid, int],
2860
+ mkey_indices: dict[cirq.MeasurementKey, int],
2861
+ ckey_indices: dict[cirq.MeasurementKey, int],
2862
+ length: int | None = None,
2870
2863
  ) -> int:
2871
2864
  """Get the index of the earliest moment that can accommodate the given moment or operation.
2872
2865
 
@@ -2951,9 +2944,9 @@ class _PlacementCache:
2951
2944
 
2952
2945
  def __init__(self) -> None:
2953
2946
  # These are dicts from the qubit/key to the greatest moment index that has it.
2954
- self._qubit_indices: Dict[cirq.Qid, int] = {}
2955
- self._mkey_indices: Dict[cirq.MeasurementKey, int] = {}
2956
- self._ckey_indices: Dict[cirq.MeasurementKey, int] = {}
2947
+ self._qubit_indices: dict[cirq.Qid, int] = {}
2948
+ self._mkey_indices: dict[cirq.MeasurementKey, int] = {}
2949
+ self._ckey_indices: dict[cirq.MeasurementKey, int] = {}
2957
2950
 
2958
2951
  # For keeping track of length of the circuit thus far.
2959
2952
  self._length = 0