cirq-core 1.5.0.dev20250409225226__py3-none-any.whl → 1.6.0__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 (732) hide show
  1. cirq/__init__.py +16 -17
  2. cirq/_compat.py +21 -20
  3. cirq/_compat_test.py +14 -34
  4. cirq/_doc.py +4 -2
  5. cirq/_import.py +8 -6
  6. cirq/_import_test.py +4 -2
  7. cirq/_version.py +6 -6
  8. cirq/_version_test.py +2 -2
  9. cirq/circuits/_block_diagram_drawer.py +11 -10
  10. cirq/circuits/_block_diagram_drawer_test.py +8 -6
  11. cirq/circuits/_box_drawing_character_data.py +8 -8
  12. cirq/circuits/_box_drawing_character_data_test.py +3 -1
  13. cirq/circuits/_bucket_priority_queue.py +9 -7
  14. cirq/circuits/_bucket_priority_queue_test.py +22 -20
  15. cirq/circuits/circuit.py +248 -172
  16. cirq/circuits/circuit_operation.py +73 -83
  17. cirq/circuits/circuit_operation_test.py +128 -90
  18. cirq/circuits/circuit_test.py +211 -151
  19. cirq/circuits/frozen_circuit.py +23 -60
  20. cirq/circuits/frozen_circuit_test.py +31 -8
  21. cirq/circuits/insert_strategy.py +7 -5
  22. cirq/circuits/insert_strategy_test.py +4 -2
  23. cirq/circuits/moment.py +88 -40
  24. cirq/circuits/moment_test.py +128 -51
  25. cirq/circuits/optimization_pass.py +5 -5
  26. cirq/circuits/optimization_pass_test.py +10 -10
  27. cirq/circuits/qasm_output.py +11 -11
  28. cirq/circuits/qasm_output_test.py +25 -22
  29. cirq/circuits/text_diagram_drawer.py +23 -38
  30. cirq/circuits/text_diagram_drawer_test.py +19 -17
  31. cirq/conftest.py +4 -3
  32. cirq/contrib/__init__.py +4 -4
  33. cirq/contrib/acquaintance/__init__.py +1 -1
  34. cirq/contrib/acquaintance/bipartite.py +5 -8
  35. cirq/contrib/acquaintance/bipartite_test.py +18 -13
  36. cirq/contrib/acquaintance/devices.py +2 -2
  37. cirq/contrib/acquaintance/devices_test.py +5 -3
  38. cirq/contrib/acquaintance/executor.py +5 -5
  39. cirq/contrib/acquaintance/executor_test.py +13 -9
  40. cirq/contrib/acquaintance/gates.py +18 -28
  41. cirq/contrib/acquaintance/gates_test.py +24 -20
  42. cirq/contrib/acquaintance/inspection_utils.py +8 -4
  43. cirq/contrib/acquaintance/inspection_utils_test.py +4 -2
  44. cirq/contrib/acquaintance/mutation_utils.py +4 -4
  45. cirq/contrib/acquaintance/mutation_utils_test.py +4 -2
  46. cirq/contrib/acquaintance/optimizers.py +4 -4
  47. cirq/contrib/acquaintance/optimizers_test.py +4 -1
  48. cirq/contrib/acquaintance/permutation.py +15 -27
  49. cirq/contrib/acquaintance/permutation_test.py +26 -17
  50. cirq/contrib/acquaintance/shift.py +4 -4
  51. cirq/contrib/acquaintance/shift_swap_network.py +4 -4
  52. cirq/contrib/acquaintance/shift_swap_network_test.py +9 -6
  53. cirq/contrib/acquaintance/shift_test.py +8 -6
  54. cirq/contrib/acquaintance/strategies/cubic.py +2 -2
  55. cirq/contrib/acquaintance/strategies/cubic_test.py +4 -2
  56. cirq/contrib/acquaintance/strategies/quartic_paired.py +6 -6
  57. cirq/contrib/acquaintance/strategies/quartic_paired_test.py +10 -6
  58. cirq/contrib/acquaintance/testing.py +2 -0
  59. cirq/contrib/acquaintance/topological_sort.py +2 -2
  60. cirq/contrib/acquaintance/topological_sort_test.py +3 -1
  61. cirq/contrib/bayesian_network/bayesian_network_gate.py +9 -10
  62. cirq/contrib/bayesian_network/bayesian_network_gate_test.py +14 -9
  63. cirq/contrib/circuitdag/circuit_dag.py +4 -4
  64. cirq/contrib/circuitdag/circuit_dag_test.py +17 -15
  65. cirq/contrib/custom_simulators/custom_state_simulator.py +5 -5
  66. cirq/contrib/custom_simulators/custom_state_simulator_test.py +22 -17
  67. cirq/contrib/graph_device/graph_device.py +12 -11
  68. cirq/contrib/graph_device/graph_device_test.py +18 -14
  69. cirq/contrib/graph_device/hypergraph.py +16 -14
  70. cirq/contrib/graph_device/hypergraph_test.py +13 -11
  71. cirq/contrib/graph_device/uniform_graph_device.py +6 -4
  72. cirq/contrib/graph_device/uniform_graph_device_test.py +11 -3
  73. cirq/contrib/hacks/disable_validation.py +6 -1
  74. cirq/contrib/hacks/disable_validation_test.py +3 -1
  75. cirq/contrib/json.py +31 -5
  76. cirq/contrib/json_test.py +6 -3
  77. cirq/contrib/json_test_data/DampedReadoutNoiseModel.json +12 -0
  78. cirq/contrib/json_test_data/DampedReadoutNoiseModel.repr +4 -0
  79. cirq/contrib/json_test_data/DepolarizingNoiseModel.json +12 -0
  80. cirq/contrib/json_test_data/DepolarizingNoiseModel.repr +4 -0
  81. cirq/contrib/json_test_data/DepolarizingWithDampedReadoutNoiseModel.json +6 -0
  82. cirq/contrib/json_test_data/DepolarizingWithDampedReadoutNoiseModel.repr +1 -0
  83. cirq/contrib/json_test_data/DepolarizingWithReadoutNoiseModel.json +5 -0
  84. cirq/contrib/json_test_data/DepolarizingWithReadoutNoiseModel.repr +1 -0
  85. cirq/contrib/json_test_data/ReadoutNoiseModel.json +12 -0
  86. cirq/contrib/json_test_data/ReadoutNoiseModel.repr +4 -0
  87. cirq/contrib/json_test_data/__init__.py +17 -0
  88. cirq/contrib/json_test_data/spec.py +32 -0
  89. cirq/contrib/noise_models/noise_models.py +119 -5
  90. cirq/contrib/noise_models/noise_models_test.py +37 -9
  91. cirq/contrib/paulistring/clifford_optimize.py +6 -4
  92. cirq/contrib/paulistring/clifford_optimize_test.py +6 -5
  93. cirq/contrib/paulistring/clifford_target_gateset.py +10 -10
  94. cirq/contrib/paulistring/clifford_target_gateset_test.py +13 -11
  95. cirq/contrib/paulistring/optimize.py +2 -0
  96. cirq/contrib/paulistring/optimize_test.py +4 -3
  97. cirq/contrib/paulistring/pauli_string_dag.py +2 -0
  98. cirq/contrib/paulistring/pauli_string_dag_test.py +3 -1
  99. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +255 -120
  100. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +398 -19
  101. cirq/contrib/paulistring/pauli_string_optimize.py +7 -1
  102. cirq/contrib/paulistring/pauli_string_optimize_test.py +5 -3
  103. cirq/contrib/paulistring/recombine.py +6 -4
  104. cirq/contrib/paulistring/recombine_test.py +3 -1
  105. cirq/contrib/paulistring/separate.py +9 -6
  106. cirq/contrib/paulistring/separate_test.py +3 -1
  107. cirq/contrib/qasm_import/_lexer.py +3 -2
  108. cirq/contrib/qasm_import/_lexer_test.py +49 -13
  109. cirq/contrib/qasm_import/_parser.py +547 -83
  110. cirq/contrib/qasm_import/_parser_test.py +988 -97
  111. cirq/contrib/qasm_import/exception.py +2 -0
  112. cirq/contrib/qasm_import/qasm.py +8 -2
  113. cirq/contrib/qasm_import/qasm_test.py +7 -4
  114. cirq/contrib/qcircuit/qcircuit_diagram_info.py +5 -5
  115. cirq/contrib/qcircuit/qcircuit_diagram_info_test.py +4 -1
  116. cirq/contrib/qcircuit/qcircuit_pdf.py +7 -3
  117. cirq/contrib/qcircuit/qcircuit_pdf_test.py +3 -1
  118. cirq/contrib/qcircuit/qcircuit_test.py +10 -8
  119. cirq/contrib/quantum_volume/quantum_volume.py +31 -27
  120. cirq/contrib/quantum_volume/quantum_volume_test.py +19 -16
  121. cirq/contrib/quimb/density_matrix.py +15 -14
  122. cirq/contrib/quimb/density_matrix_test.py +10 -7
  123. cirq/contrib/quimb/grid_circuits.py +5 -2
  124. cirq/contrib/quimb/grid_circuits_test.py +3 -0
  125. cirq/contrib/quimb/mps_simulator.py +20 -20
  126. cirq/contrib/quimb/mps_simulator_test.py +3 -0
  127. cirq/contrib/quimb/state_vector.py +12 -11
  128. cirq/contrib/quimb/state_vector_test.py +3 -0
  129. cirq/contrib/quirk/export_to_quirk.py +5 -3
  130. cirq/contrib/quirk/export_to_quirk_test.py +18 -16
  131. cirq/contrib/quirk/linearize_circuit.py +2 -0
  132. cirq/contrib/quirk/quirk_gate.py +18 -17
  133. cirq/contrib/routing/device.py +5 -3
  134. cirq/contrib/routing/device_test.py +2 -0
  135. cirq/contrib/routing/greedy.py +10 -21
  136. cirq/contrib/routing/greedy_test.py +4 -2
  137. cirq/contrib/routing/initialization.py +2 -2
  138. cirq/contrib/routing/initialization_test.py +5 -3
  139. cirq/contrib/routing/router.py +9 -5
  140. cirq/contrib/routing/router_test.py +2 -0
  141. cirq/contrib/routing/swap_network.py +3 -3
  142. cirq/contrib/routing/swap_network_test.py +3 -1
  143. cirq/contrib/routing/utils.py +2 -2
  144. cirq/contrib/routing/utils_test.py +3 -0
  145. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +15 -9
  146. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking_test.py +3 -0
  147. cirq/contrib/svg/svg.py +3 -3
  148. cirq/contrib/svg/svg_test.py +8 -5
  149. cirq/devices/device.py +4 -4
  150. cirq/devices/device_test.py +7 -4
  151. cirq/devices/grid_device_metadata.py +10 -10
  152. cirq/devices/grid_device_metadata_test.py +3 -0
  153. cirq/devices/grid_qubit.py +29 -21
  154. cirq/devices/grid_qubit_test.py +3 -0
  155. cirq/devices/insertion_noise_model.py +7 -7
  156. cirq/devices/insertion_noise_model_test.py +7 -5
  157. cirq/devices/line_qubit.py +13 -13
  158. cirq/devices/line_qubit_test.py +2 -0
  159. cirq/devices/named_topologies.py +18 -29
  160. cirq/devices/named_topologies_test.py +13 -10
  161. cirq/devices/noise_model.py +3 -3
  162. cirq/devices/noise_model_test.py +19 -15
  163. cirq/devices/noise_properties.py +15 -6
  164. cirq/devices/noise_properties_test.py +34 -3
  165. cirq/devices/noise_utils.py +11 -9
  166. cirq/devices/noise_utils_test.py +2 -0
  167. cirq/devices/superconducting_qubits_noise_properties.py +23 -22
  168. cirq/devices/superconducting_qubits_noise_properties_test.py +6 -6
  169. cirq/devices/thermal_noise_model.py +107 -37
  170. cirq/devices/thermal_noise_model_test.py +21 -0
  171. cirq/devices/unconstrained_device.py +5 -3
  172. cirq/devices/unconstrained_device_test.py +2 -0
  173. cirq/experiments/__init__.py +4 -2
  174. cirq/experiments/benchmarking/__init__.py +17 -0
  175. cirq/experiments/benchmarking/parallel_xeb.py +677 -0
  176. cirq/experiments/benchmarking/parallel_xeb_test.py +447 -0
  177. cirq/experiments/fidelity_estimation.py +14 -8
  178. cirq/experiments/fidelity_estimation_test.py +3 -0
  179. cirq/experiments/n_qubit_tomography.py +17 -16
  180. cirq/experiments/n_qubit_tomography_test.py +8 -5
  181. cirq/experiments/purity_estimation.py +2 -0
  182. cirq/experiments/purity_estimation_test.py +2 -0
  183. cirq/experiments/qubit_characterizations.py +207 -103
  184. cirq/experiments/qubit_characterizations_test.py +40 -12
  185. cirq/experiments/random_quantum_circuit_generation.py +56 -70
  186. cirq/experiments/random_quantum_circuit_generation_test.py +11 -8
  187. cirq/experiments/readout_confusion_matrix.py +24 -22
  188. cirq/experiments/readout_confusion_matrix_test.py +2 -0
  189. cirq/experiments/single_qubit_readout_calibration.py +30 -15
  190. cirq/experiments/single_qubit_readout_calibration_test.py +5 -2
  191. cirq/experiments/t1_decay_experiment.py +9 -7
  192. cirq/experiments/t1_decay_experiment_test.py +13 -11
  193. cirq/experiments/t2_decay_experiment.py +16 -13
  194. cirq/experiments/t2_decay_experiment_test.py +2 -0
  195. cirq/experiments/two_qubit_xeb.py +64 -57
  196. cirq/experiments/two_qubit_xeb_test.py +10 -6
  197. cirq/experiments/xeb_fitting.py +39 -35
  198. cirq/experiments/xeb_sampling.py +37 -44
  199. cirq/experiments/xeb_sampling_test.py +3 -0
  200. cirq/experiments/xeb_simulation.py +14 -10
  201. cirq/experiments/xeb_simulation_test.py +5 -5
  202. cirq/experiments/z_phase_calibration.py +32 -29
  203. cirq/experiments/z_phase_calibration_test.py +3 -4
  204. cirq/interop/quirk/cells/__init__.py +1 -1
  205. cirq/interop/quirk/cells/all_cells.py +7 -2
  206. cirq/interop/quirk/cells/arithmetic_cells.py +29 -41
  207. cirq/interop/quirk/cells/arithmetic_cells_test.py +17 -14
  208. cirq/interop/quirk/cells/cell.py +19 -28
  209. cirq/interop/quirk/cells/cell_test.py +3 -0
  210. cirq/interop/quirk/cells/composite_cell.py +13 -28
  211. cirq/interop/quirk/cells/composite_cell_test.py +2 -0
  212. cirq/interop/quirk/cells/control_cells.py +15 -15
  213. cirq/interop/quirk/cells/control_cells_test.py +7 -5
  214. cirq/interop/quirk/cells/frequency_space_cells.py +4 -3
  215. cirq/interop/quirk/cells/frequency_space_cells_test.py +3 -1
  216. cirq/interop/quirk/cells/ignored_cells.py +3 -0
  217. cirq/interop/quirk/cells/ignored_cells_test.py +3 -1
  218. cirq/interop/quirk/cells/input_cells.py +7 -5
  219. cirq/interop/quirk/cells/input_cells_test.py +7 -5
  220. cirq/interop/quirk/cells/input_rotation_cells.py +15 -13
  221. cirq/interop/quirk/cells/input_rotation_cells_test.py +9 -7
  222. cirq/interop/quirk/cells/measurement_cells.py +5 -2
  223. cirq/interop/quirk/cells/measurement_cells_test.py +3 -1
  224. cirq/interop/quirk/cells/parse.py +22 -23
  225. cirq/interop/quirk/cells/parse_test.py +12 -10
  226. cirq/interop/quirk/cells/qubit_permutation_cells.py +5 -3
  227. cirq/interop/quirk/cells/qubit_permutation_cells_test.py +9 -7
  228. cirq/interop/quirk/cells/scalar_cells.py +4 -1
  229. cirq/interop/quirk/cells/scalar_cells_test.py +3 -1
  230. cirq/interop/quirk/cells/single_qubit_rotation_cells.py +5 -2
  231. cirq/interop/quirk/cells/single_qubit_rotation_cells_test.py +5 -3
  232. cirq/interop/quirk/cells/swap_cell.py +8 -6
  233. cirq/interop/quirk/cells/swap_cell_test.py +6 -4
  234. cirq/interop/quirk/cells/testing.py +6 -6
  235. cirq/interop/quirk/cells/testing_test.py +8 -6
  236. cirq/interop/quirk/cells/unsupported_cells.py +3 -0
  237. cirq/interop/quirk/cells/unsupported_cells_test.py +4 -2
  238. cirq/interop/quirk/url_to_circuit.py +23 -36
  239. cirq/interop/quirk/url_to_circuit_test.py +4 -1
  240. cirq/json_resolver_cache.py +14 -12
  241. cirq/linalg/__init__.py +4 -6
  242. cirq/linalg/combinators.py +7 -5
  243. cirq/linalg/combinators_test.py +10 -7
  244. cirq/linalg/decompositions.py +24 -35
  245. cirq/linalg/decompositions_test.py +3 -1
  246. cirq/linalg/diagonalize.py +6 -4
  247. cirq/linalg/diagonalize_test.py +15 -14
  248. cirq/linalg/operator_spaces.py +14 -14
  249. cirq/linalg/operator_spaces_test.py +13 -11
  250. cirq/linalg/predicates.py +18 -9
  251. cirq/linalg/predicates_test.py +5 -0
  252. cirq/linalg/tolerance.py +6 -3
  253. cirq/linalg/tolerance_test.py +6 -4
  254. cirq/linalg/transformations.py +23 -20
  255. cirq/linalg/transformations_test.py +73 -43
  256. cirq/neutral_atoms/convert_to_neutral_atom_gates.py +9 -3
  257. cirq/neutral_atoms/convert_to_neutral_atom_gates_test.py +3 -1
  258. cirq/neutral_atoms/neutral_atom_devices.py +2 -0
  259. cirq/ops/__init__.py +2 -0
  260. cirq/ops/arithmetic_operation.py +21 -21
  261. cirq/ops/arithmetic_operation_test.py +7 -8
  262. cirq/ops/boolean_hamiltonian.py +23 -22
  263. cirq/ops/boolean_hamiltonian_test.py +12 -9
  264. cirq/ops/classically_controlled_operation.py +31 -36
  265. cirq/ops/classically_controlled_operation_test.py +121 -117
  266. cirq/ops/clifford_gate.py +98 -81
  267. cirq/ops/clifford_gate_test.py +72 -57
  268. cirq/ops/common_channels.py +44 -44
  269. cirq/ops/common_channels_test.py +83 -81
  270. cirq/ops/common_gate_families.py +9 -7
  271. cirq/ops/common_gate_families_test.py +11 -7
  272. cirq/ops/common_gates.py +164 -183
  273. cirq/ops/common_gates_test.py +135 -95
  274. cirq/ops/control_values.py +23 -26
  275. cirq/ops/control_values_test.py +22 -20
  276. cirq/ops/controlled_gate.py +64 -112
  277. cirq/ops/controlled_gate_test.py +130 -35
  278. cirq/ops/controlled_operation.py +24 -35
  279. cirq/ops/controlled_operation_test.py +8 -6
  280. cirq/ops/dense_pauli_string.py +38 -49
  281. cirq/ops/dense_pauli_string_test.py +4 -2
  282. cirq/ops/diagonal_gate.py +18 -31
  283. cirq/ops/diagonal_gate_test.py +13 -13
  284. cirq/ops/eigen_gate.py +29 -29
  285. cirq/ops/eigen_gate_test.py +45 -28
  286. cirq/ops/fourier_transform.py +14 -20
  287. cirq/ops/fourier_transform_test.py +15 -12
  288. cirq/ops/fsim_gate.py +43 -42
  289. cirq/ops/fsim_gate_test.py +29 -29
  290. cirq/ops/gate_features.py +2 -0
  291. cirq/ops/gate_features_test.py +5 -3
  292. cirq/ops/gate_operation.py +43 -65
  293. cirq/ops/gate_operation_test.py +46 -42
  294. cirq/ops/gateset.py +28 -40
  295. cirq/ops/gateset_test.py +4 -2
  296. cirq/ops/global_phase_op.py +45 -20
  297. cirq/ops/global_phase_op_test.py +44 -20
  298. cirq/ops/greedy_qubit_manager.py +10 -8
  299. cirq/ops/greedy_qubit_manager_test.py +5 -3
  300. cirq/ops/identity.py +14 -12
  301. cirq/ops/identity_test.py +24 -20
  302. cirq/ops/kraus_channel.py +11 -8
  303. cirq/ops/kraus_channel_test.py +14 -11
  304. cirq/ops/linear_combinations.py +65 -77
  305. cirq/ops/linear_combinations_test.py +14 -9
  306. cirq/ops/matrix_gates.py +21 -18
  307. cirq/ops/matrix_gates_test.py +16 -0
  308. cirq/ops/measure_util.py +15 -20
  309. cirq/ops/measure_util_test.py +2 -0
  310. cirq/ops/measurement_gate.py +26 -37
  311. cirq/ops/measurement_gate_test.py +2 -0
  312. cirq/ops/mixed_unitary_channel.py +12 -9
  313. cirq/ops/mixed_unitary_channel_test.py +14 -11
  314. cirq/ops/named_qubit.py +16 -13
  315. cirq/ops/named_qubit_test.py +15 -13
  316. cirq/ops/op_tree.py +9 -7
  317. cirq/ops/op_tree_test.py +22 -19
  318. cirq/ops/parallel_gate.py +15 -17
  319. cirq/ops/parallel_gate_test.py +18 -16
  320. cirq/ops/parity_gates.py +23 -25
  321. cirq/ops/parity_gates_test.py +36 -32
  322. cirq/ops/pauli_gates.py +22 -21
  323. cirq/ops/pauli_gates_test.py +29 -20
  324. cirq/ops/pauli_interaction_gate.py +15 -19
  325. cirq/ops/pauli_interaction_gate_test.py +10 -8
  326. cirq/ops/pauli_measurement_gate.py +23 -35
  327. cirq/ops/pauli_measurement_gate_test.py +2 -0
  328. cirq/ops/pauli_string.py +92 -120
  329. cirq/ops/pauli_string_phasor.py +52 -45
  330. cirq/ops/pauli_string_phasor_test.py +4 -5
  331. cirq/ops/pauli_string_raw_types.py +9 -7
  332. cirq/ops/pauli_string_raw_types_test.py +2 -0
  333. cirq/ops/pauli_string_test.py +31 -154
  334. cirq/ops/pauli_sum_exponential.py +12 -12
  335. cirq/ops/pauli_sum_exponential_test.py +12 -10
  336. cirq/ops/permutation_gate.py +8 -6
  337. cirq/ops/permutation_gate_test.py +10 -8
  338. cirq/ops/phased_iswap_gate.py +16 -16
  339. cirq/ops/phased_iswap_gate_test.py +17 -15
  340. cirq/ops/phased_x_gate.py +16 -17
  341. cirq/ops/phased_x_gate_test.py +18 -16
  342. cirq/ops/phased_x_z_gate.py +24 -22
  343. cirq/ops/phased_x_z_gate_test.py +17 -11
  344. cirq/ops/projector.py +16 -11
  345. cirq/ops/projector_test.py +19 -16
  346. cirq/ops/qid_util.py +7 -5
  347. cirq/ops/qid_util_test.py +2 -0
  348. cirq/ops/qubit_manager.py +11 -9
  349. cirq/ops/qubit_manager_test.py +6 -4
  350. cirq/ops/qubit_order.py +11 -14
  351. cirq/ops/qubit_order_or_list.py +4 -2
  352. cirq/ops/qubit_order_test.py +12 -10
  353. cirq/ops/random_gate_channel.py +12 -10
  354. cirq/ops/random_gate_channel_test.py +14 -11
  355. cirq/ops/raw_types.py +109 -129
  356. cirq/ops/raw_types_test.py +63 -57
  357. cirq/ops/state_preparation_channel.py +7 -7
  358. cirq/ops/state_preparation_channel_test.py +11 -9
  359. cirq/ops/swap_gates.py +13 -15
  360. cirq/ops/swap_gates_test.py +19 -17
  361. cirq/ops/tags.py +5 -3
  362. cirq/ops/tags_test.py +4 -2
  363. cirq/ops/three_qubit_gates.py +43 -76
  364. cirq/ops/three_qubit_gates_test.py +19 -17
  365. cirq/ops/two_qubit_diagonal_gate.py +13 -13
  366. cirq/ops/two_qubit_diagonal_gate_test.py +10 -8
  367. cirq/ops/uniform_superposition_gate.py +5 -3
  368. cirq/ops/uniform_superposition_gate_test.py +5 -3
  369. cirq/ops/wait_gate.py +17 -14
  370. cirq/ops/wait_gate_test.py +9 -6
  371. cirq/protocols/__init__.py +0 -3
  372. cirq/protocols/act_on_protocol.py +8 -6
  373. cirq/protocols/act_on_protocol_test.py +15 -12
  374. cirq/protocols/apply_channel_protocol.py +10 -14
  375. cirq/protocols/apply_channel_protocol_test.py +2 -0
  376. cirq/protocols/apply_mixture_protocol.py +13 -42
  377. cirq/protocols/apply_mixture_protocol_test.py +7 -5
  378. cirq/protocols/apply_unitary_protocol.py +39 -34
  379. cirq/protocols/apply_unitary_protocol_test.py +4 -1
  380. cirq/protocols/approximate_equality_protocol.py +2 -0
  381. cirq/protocols/approximate_equality_protocol_test.py +2 -0
  382. cirq/protocols/circuit_diagram_info_protocol.py +58 -42
  383. cirq/protocols/circuit_diagram_info_protocol_test.py +70 -12
  384. cirq/protocols/commutes_protocol.py +8 -7
  385. cirq/protocols/commutes_protocol_test.py +2 -0
  386. cirq/protocols/control_key_protocol.py +6 -4
  387. cirq/protocols/control_key_protocol_test.py +3 -1
  388. cirq/protocols/decompose_protocol.py +49 -48
  389. cirq/protocols/decompose_protocol_test.py +27 -16
  390. cirq/protocols/equal_up_to_global_phase_protocol.py +2 -0
  391. cirq/protocols/equal_up_to_global_phase_protocol_test.py +9 -6
  392. cirq/protocols/has_stabilizer_effect_protocol.py +7 -5
  393. cirq/protocols/has_stabilizer_effect_protocol_test.py +7 -5
  394. cirq/protocols/has_unitary_protocol.py +10 -6
  395. cirq/protocols/has_unitary_protocol_test.py +13 -8
  396. cirq/protocols/hash_from_pickle_test.py +2 -11
  397. cirq/protocols/inverse_protocol.py +13 -16
  398. cirq/protocols/inverse_protocol_test.py +5 -3
  399. cirq/protocols/json_serialization.py +35 -54
  400. cirq/protocols/json_serialization_test.py +14 -21
  401. cirq/protocols/json_test_data/CXSWAP.json +46 -0
  402. cirq/protocols/json_test_data/CXSWAP.repr +13 -0
  403. cirq/protocols/json_test_data/CZSWAP.json +46 -0
  404. cirq/protocols/json_test_data/CZSWAP.repr +13 -0
  405. cirq/protocols/json_test_data/CircuitOperation.json +6 -3
  406. cirq/protocols/json_test_data/CircuitOperation.repr_inward +4 -2
  407. cirq/protocols/json_test_data/Moment.json +24 -1
  408. cirq/protocols/json_test_data/Moment.repr +6 -1
  409. cirq/protocols/json_test_data/ThermalNoiseModel.json +32 -0
  410. cirq/protocols/json_test_data/ThermalNoiseModel.repr +1 -0
  411. cirq/protocols/json_test_data/spec.py +6 -2
  412. cirq/protocols/kraus_protocol.py +47 -7
  413. cirq/protocols/kraus_protocol_test.py +86 -12
  414. cirq/protocols/measurement_key_protocol.py +15 -16
  415. cirq/protocols/measurement_key_protocol_test.py +13 -11
  416. cirq/protocols/mixture_protocol.py +7 -5
  417. cirq/protocols/mixture_protocol_test.py +4 -2
  418. cirq/protocols/mul_protocol.py +2 -3
  419. cirq/protocols/mul_protocol_test.py +2 -0
  420. cirq/protocols/pauli_expansion_protocol.py +6 -3
  421. cirq/protocols/pauli_expansion_protocol_test.py +5 -3
  422. cirq/protocols/phase_protocol.py +2 -0
  423. cirq/protocols/phase_protocol_test.py +3 -1
  424. cirq/protocols/pow_protocol.py +11 -16
  425. cirq/protocols/pow_protocol_test.py +2 -0
  426. cirq/protocols/qasm.py +14 -20
  427. cirq/protocols/qasm_test.py +6 -3
  428. cirq/protocols/qid_shape_protocol.py +8 -8
  429. cirq/protocols/qid_shape_protocol_test.py +3 -1
  430. cirq/protocols/resolve_parameters.py +5 -3
  431. cirq/protocols/resolve_parameters_test.py +8 -7
  432. cirq/protocols/trace_distance_bound.py +6 -4
  433. cirq/protocols/trace_distance_bound_test.py +3 -1
  434. cirq/protocols/unitary_protocol.py +17 -7
  435. cirq/protocols/unitary_protocol_test.py +12 -2
  436. cirq/qis/channels.py +6 -2
  437. cirq/qis/channels_test.py +20 -16
  438. cirq/qis/clifford_tableau.py +21 -19
  439. cirq/qis/clifford_tableau_test.py +2 -2
  440. cirq/qis/entropy.py +14 -3
  441. cirq/qis/entropy_test.py +3 -1
  442. cirq/qis/measures.py +13 -13
  443. cirq/qis/measures_test.py +20 -14
  444. cirq/qis/noise_utils.py +2 -0
  445. cirq/qis/noise_utils_test.py +9 -7
  446. cirq/qis/quantum_state_representation.py +7 -8
  447. cirq/qis/states.py +58 -56
  448. cirq/qis/states_test.py +2 -0
  449. cirq/sim/classical_simulator.py +23 -22
  450. cirq/sim/classical_simulator_test.py +2 -0
  451. cirq/sim/clifford/clifford_simulator.py +23 -21
  452. cirq/sim/clifford/clifford_simulator_test.py +7 -4
  453. cirq/sim/clifford/clifford_tableau_simulation_state.py +10 -7
  454. cirq/sim/clifford/clifford_tableau_simulation_state_test.py +5 -5
  455. cirq/sim/clifford/stabilizer_ch_form_simulation_state.py +8 -6
  456. cirq/sim/clifford/stabilizer_ch_form_simulation_state_test.py +8 -6
  457. cirq/sim/clifford/stabilizer_sampler.py +9 -7
  458. cirq/sim/clifford/stabilizer_sampler_test.py +4 -2
  459. cirq/sim/clifford/stabilizer_simulation_state.py +14 -13
  460. cirq/sim/clifford/stabilizer_simulation_state_test.py +6 -4
  461. cirq/sim/clifford/stabilizer_state_ch_form.py +13 -11
  462. cirq/sim/clifford/stabilizer_state_ch_form_test.py +4 -2
  463. cirq/sim/density_matrix_simulation_state.py +26 -27
  464. cirq/sim/density_matrix_simulation_state_test.py +10 -8
  465. cirq/sim/density_matrix_simulator.py +30 -28
  466. cirq/sim/density_matrix_simulator_test.py +48 -48
  467. cirq/sim/density_matrix_utils.py +13 -11
  468. cirq/sim/density_matrix_utils_test.py +38 -36
  469. cirq/sim/mux.py +33 -31
  470. cirq/sim/mux_test.py +3 -0
  471. cirq/sim/simulation_product_state.py +15 -15
  472. cirq/sim/simulation_product_state_test.py +29 -26
  473. cirq/sim/simulation_state.py +29 -38
  474. cirq/sim/simulation_state_base.py +21 -32
  475. cirq/sim/simulation_state_test.py +15 -13
  476. cirq/sim/simulation_utils.py +5 -2
  477. cirq/sim/simulation_utils_test.py +5 -2
  478. cirq/sim/simulator.py +90 -106
  479. cirq/sim/simulator_base.py +33 -45
  480. cirq/sim/simulator_base_test.py +20 -15
  481. cirq/sim/simulator_test.py +23 -14
  482. cirq/sim/sparse_simulator.py +19 -17
  483. cirq/sim/sparse_simulator_test.py +41 -40
  484. cirq/sim/state_vector.py +15 -12
  485. cirq/sim/state_vector_simulation_state.py +31 -31
  486. cirq/sim/state_vector_simulation_state_test.py +16 -14
  487. cirq/sim/state_vector_simulator.py +17 -14
  488. cirq/sim/state_vector_simulator_test.py +2 -0
  489. cirq/sim/state_vector_test.py +6 -3
  490. cirq/study/flatten_expressions.py +16 -15
  491. cirq/study/flatten_expressions_test.py +13 -11
  492. cirq/study/resolver.py +18 -17
  493. cirq/study/resolver_test.py +22 -20
  494. cirq/study/result.py +17 -27
  495. cirq/study/result_test.py +2 -0
  496. cirq/study/sweepable.py +12 -10
  497. cirq/study/sweepable_test.py +3 -0
  498. cirq/study/sweeps.py +42 -61
  499. cirq/study/sweeps_test.py +33 -0
  500. cirq/testing/__init__.py +7 -11
  501. cirq/testing/_compat_test_data/module_a/__init__.py +1 -0
  502. cirq/testing/_compat_test_data/module_a/module_b/__init__.py +1 -0
  503. cirq/testing/_compat_test_data/module_a/sub/__init__.py +1 -0
  504. cirq/testing/circuit_compare.py +8 -17
  505. cirq/testing/circuit_compare_test.py +2 -0
  506. cirq/testing/consistent_act_on.py +13 -11
  507. cirq/testing/consistent_act_on_test.py +5 -3
  508. cirq/testing/consistent_channels.py +2 -0
  509. cirq/testing/consistent_channels_test.py +10 -8
  510. cirq/testing/consistent_controlled_gate_op.py +5 -5
  511. cirq/testing/consistent_controlled_gate_op_test.py +18 -18
  512. cirq/testing/consistent_decomposition.py +2 -2
  513. cirq/testing/consistent_decomposition_test.py +4 -2
  514. cirq/testing/consistent_pauli_expansion.py +2 -0
  515. cirq/testing/consistent_pauli_expansion_test.py +3 -1
  516. cirq/testing/consistent_phase_by.py +2 -0
  517. cirq/testing/consistent_phase_by_test.py +3 -1
  518. cirq/testing/consistent_protocols.py +14 -20
  519. cirq/testing/consistent_protocols_test.py +13 -11
  520. cirq/testing/consistent_qasm.py +6 -4
  521. cirq/testing/consistent_qasm_test.py +7 -7
  522. cirq/testing/consistent_resolve_parameters.py +2 -0
  523. cirq/testing/consistent_specified_has_unitary.py +2 -2
  524. cirq/testing/consistent_specified_has_unitary_test.py +6 -4
  525. cirq/testing/consistent_unitary.py +1 -0
  526. cirq/testing/consistent_unitary_test.py +4 -2
  527. cirq/testing/deprecation.py +5 -2
  528. cirq/testing/deprecation_test.py +5 -2
  529. cirq/testing/devices.py +7 -4
  530. cirq/testing/devices_test.py +7 -4
  531. cirq/testing/equals_tester.py +4 -2
  532. cirq/testing/equals_tester_test.py +21 -17
  533. cirq/testing/equivalent_basis_map.py +6 -4
  534. cirq/testing/equivalent_basis_map_test.py +6 -4
  535. cirq/testing/equivalent_repr_eval.py +6 -4
  536. cirq/testing/equivalent_repr_eval_test.py +5 -3
  537. cirq/testing/gate_features.py +2 -0
  538. cirq/testing/gate_features_test.py +7 -5
  539. cirq/testing/json.py +19 -15
  540. cirq/testing/json_test.py +5 -3
  541. cirq/testing/lin_alg_utils.py +10 -11
  542. cirq/testing/lin_alg_utils_test.py +14 -12
  543. cirq/testing/logs.py +7 -6
  544. cirq/testing/logs_test.py +9 -7
  545. cirq/testing/no_identifier_qubit.py +4 -2
  546. cirq/testing/no_identifier_qubit_test.py +5 -3
  547. cirq/testing/op_tree.py +2 -0
  548. cirq/testing/op_tree_test.py +4 -1
  549. cirq/testing/order_tester.py +2 -0
  550. cirq/testing/order_tester_test.py +8 -6
  551. cirq/testing/pytest_utils.py +2 -0
  552. cirq/testing/pytest_utils_test.py +4 -2
  553. cirq/testing/random_circuit.py +21 -20
  554. cirq/testing/random_circuit_test.py +12 -9
  555. cirq/testing/repr_pretty_tester.py +1 -0
  556. cirq/testing/repr_pretty_tester_test.py +5 -3
  557. cirq/testing/routing_devices.py +4 -1
  558. cirq/testing/routing_devices_test.py +9 -6
  559. cirq/testing/sample_circuits.py +4 -1
  560. cirq/testing/sample_circuits_test.py +3 -1
  561. cirq/testing/sample_gates.py +3 -0
  562. cirq/testing/sample_gates_test.py +5 -2
  563. cirq/transformers/__init__.py +11 -4
  564. cirq/transformers/align.py +9 -7
  565. cirq/transformers/align_test.py +2 -0
  566. cirq/transformers/analytical_decompositions/__init__.py +3 -6
  567. cirq/transformers/analytical_decompositions/clifford_decomposition.py +18 -16
  568. cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +2 -0
  569. cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +19 -16
  570. cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +2 -0
  571. cirq/transformers/analytical_decompositions/cphase_to_fsim.py +11 -9
  572. cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +5 -3
  573. cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +5 -3
  574. cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +5 -3
  575. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +141 -44
  576. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +35 -1
  577. cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +8 -7
  578. cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py +2 -0
  579. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +7 -4
  580. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +3 -0
  581. cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +11 -19
  582. cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +8 -33
  583. cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +9 -11
  584. cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +2 -0
  585. cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +91 -27
  586. cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +36 -7
  587. cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +20 -21
  588. cirq/transformers/analytical_decompositions/two_qubit_to_fsim_test.py +8 -6
  589. cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +13 -15
  590. cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py +3 -1
  591. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +39 -41
  592. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +2 -0
  593. cirq/transformers/drop_empty_moments.py +5 -3
  594. cirq/transformers/drop_empty_moments_test.py +4 -2
  595. cirq/transformers/drop_negligible_operations.py +7 -5
  596. cirq/transformers/drop_negligible_operations_test.py +2 -0
  597. cirq/transformers/dynamical_decoupling.py +49 -42
  598. cirq/transformers/dynamical_decoupling_test.py +223 -205
  599. cirq/transformers/eject_phased_paulis.py +28 -26
  600. cirq/transformers/eject_phased_paulis_test.py +12 -9
  601. cirq/transformers/eject_z.py +12 -12
  602. cirq/transformers/eject_z_test.py +2 -2
  603. cirq/transformers/expand_composite.py +6 -4
  604. cirq/transformers/expand_composite_test.py +3 -1
  605. cirq/transformers/gauge_compiling/__init__.py +3 -1
  606. cirq/transformers/gauge_compiling/cphase_gauge.py +2 -0
  607. cirq/transformers/gauge_compiling/cphase_gauge_test.py +2 -0
  608. cirq/transformers/gauge_compiling/cz_gauge.py +2 -0
  609. cirq/transformers/gauge_compiling/cz_gauge_test.py +1 -0
  610. cirq/transformers/gauge_compiling/gauge_compiling.py +45 -41
  611. cirq/transformers/gauge_compiling/gauge_compiling_test.py +2 -0
  612. cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +1 -0
  613. cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +5 -1
  614. cirq/transformers/gauge_compiling/iswap_gauge.py +2 -0
  615. cirq/transformers/gauge_compiling/iswap_gauge_test.py +1 -0
  616. cirq/transformers/gauge_compiling/spin_inversion_gauge.py +2 -0
  617. cirq/transformers/gauge_compiling/spin_inversion_gauge_test.py +2 -0
  618. cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +7 -6
  619. cirq/transformers/gauge_compiling/sqrt_cz_gauge_test.py +2 -0
  620. cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +2 -0
  621. cirq/transformers/gauge_compiling/sqrt_iswap_gauge_test.py +2 -0
  622. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +6 -3
  623. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +3 -0
  624. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +12 -9
  625. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation_test.py +9 -7
  626. cirq/transformers/insertion_sort.py +8 -6
  627. cirq/transformers/insertion_sort_test.py +3 -1
  628. cirq/transformers/measurement_transformers.py +29 -29
  629. cirq/transformers/measurement_transformers_test.py +2 -0
  630. cirq/transformers/merge_k_qubit_gates.py +12 -10
  631. cirq/transformers/merge_k_qubit_gates_test.py +18 -18
  632. cirq/transformers/merge_single_qubit_gates.py +197 -20
  633. cirq/transformers/merge_single_qubit_gates_test.py +177 -5
  634. cirq/transformers/noise_adding.py +5 -3
  635. cirq/transformers/noise_adding_test.py +2 -0
  636. cirq/transformers/optimize_for_target_gateset.py +19 -17
  637. cirq/transformers/optimize_for_target_gateset_test.py +11 -8
  638. cirq/transformers/qubit_management_transformers.py +13 -11
  639. cirq/transformers/qubit_management_transformers_test.py +5 -3
  640. cirq/transformers/randomized_measurements.py +16 -14
  641. cirq/transformers/randomized_measurements_test.py +10 -4
  642. cirq/transformers/routing/initial_mapper.py +6 -4
  643. cirq/transformers/routing/initial_mapper_test.py +2 -0
  644. cirq/transformers/routing/line_initial_mapper.py +16 -14
  645. cirq/transformers/routing/line_initial_mapper_test.py +9 -7
  646. cirq/transformers/routing/mapping_manager.py +10 -10
  647. cirq/transformers/routing/mapping_manager_test.py +2 -0
  648. cirq/transformers/routing/route_circuit_cqc.py +33 -31
  649. cirq/transformers/routing/route_circuit_cqc_test.py +15 -13
  650. cirq/transformers/routing/visualize_routed_circuit.py +8 -7
  651. cirq/transformers/routing/visualize_routed_circuit_test.py +4 -2
  652. cirq/transformers/stratify.py +17 -15
  653. cirq/transformers/stratify_test.py +3 -0
  654. cirq/transformers/symbolize.py +103 -0
  655. cirq/transformers/symbolize_test.py +62 -0
  656. cirq/transformers/synchronize_terminal_measurements.py +10 -10
  657. cirq/transformers/synchronize_terminal_measurements_test.py +12 -10
  658. cirq/transformers/tag_transformers.py +97 -0
  659. cirq/transformers/tag_transformers_test.py +103 -0
  660. cirq/transformers/target_gatesets/compilation_target_gateset.py +21 -19
  661. cirq/transformers/target_gatesets/compilation_target_gateset_test.py +20 -16
  662. cirq/transformers/target_gatesets/cz_gateset.py +7 -5
  663. cirq/transformers/target_gatesets/cz_gateset_test.py +21 -19
  664. cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +9 -7
  665. cirq/transformers/target_gatesets/sqrt_iswap_gateset_test.py +25 -25
  666. cirq/transformers/transformer_api.py +34 -47
  667. cirq/transformers/transformer_api_test.py +9 -8
  668. cirq/transformers/transformer_primitives.py +39 -49
  669. cirq/transformers/transformer_primitives_test.py +10 -17
  670. cirq/value/abc_alt.py +6 -4
  671. cirq/value/abc_alt_test.py +5 -3
  672. cirq/value/angle.py +11 -12
  673. cirq/value/angle_test.py +5 -3
  674. cirq/value/classical_data.py +27 -27
  675. cirq/value/classical_data_test.py +11 -8
  676. cirq/value/condition.py +26 -24
  677. cirq/value/condition_test.py +2 -0
  678. cirq/value/digits.py +14 -11
  679. cirq/value/digits_test.py +2 -0
  680. cirq/value/duration.py +23 -20
  681. cirq/value/duration_test.py +2 -0
  682. cirq/value/linear_dict.py +25 -30
  683. cirq/value/linear_dict_test.py +10 -8
  684. cirq/value/measurement_key.py +12 -12
  685. cirq/value/measurement_key_test.py +2 -0
  686. cirq/value/periodic_value.py +4 -4
  687. cirq/value/periodic_value_test.py +11 -7
  688. cirq/value/probability.py +3 -1
  689. cirq/value/probability_test.py +4 -2
  690. cirq/value/product_state.py +15 -13
  691. cirq/value/product_state_test.py +4 -1
  692. cirq/value/random_state.py +2 -0
  693. cirq/value/random_state_test.py +5 -3
  694. cirq/value/timestamp.py +11 -7
  695. cirq/value/timestamp_test.py +14 -12
  696. cirq/value/type_alias.py +4 -4
  697. cirq/value/value_equality_attr.py +8 -9
  698. cirq/value/value_equality_attr_test.py +14 -11
  699. cirq/vis/density_matrix.py +3 -3
  700. cirq/vis/density_matrix_test.py +20 -17
  701. cirq/vis/heatmap.py +24 -37
  702. cirq/vis/heatmap_test.py +3 -0
  703. cirq/vis/histogram.py +9 -6
  704. cirq/vis/histogram_test.py +5 -2
  705. cirq/vis/state_histogram.py +10 -8
  706. cirq/vis/state_histogram_test.py +7 -5
  707. cirq/vis/vis_utils.py +4 -1
  708. cirq/vis/vis_utils_test.py +4 -1
  709. cirq/work/collector.py +12 -18
  710. cirq/work/collector_test.py +15 -10
  711. cirq/work/observable_grouping.py +6 -7
  712. cirq/work/observable_grouping_test.py +10 -9
  713. cirq/work/observable_measurement.py +47 -45
  714. cirq/work/observable_measurement_data.py +22 -17
  715. cirq/work/observable_measurement_data_test.py +4 -1
  716. cirq/work/observable_measurement_test.py +48 -29
  717. cirq/work/observable_readout_calibration.py +5 -2
  718. cirq/work/observable_readout_calibration_test.py +5 -2
  719. cirq/work/observable_settings.py +13 -22
  720. cirq/work/observable_settings_test.py +9 -7
  721. cirq/work/pauli_sum_collector.py +12 -10
  722. cirq/work/pauli_sum_collector_test.py +9 -9
  723. cirq/work/sampler.py +42 -43
  724. cirq/work/sampler_test.py +31 -24
  725. cirq/work/zeros_sampler.py +6 -4
  726. cirq/work/zeros_sampler_test.py +7 -5
  727. {cirq_core-1.5.0.dev20250409225226.dist-info → cirq_core-1.6.0.dist-info}/METADATA +7 -8
  728. cirq_core-1.6.0.dist-info/RECORD +1241 -0
  729. {cirq_core-1.5.0.dev20250409225226.dist-info → cirq_core-1.6.0.dist-info}/WHEEL +1 -1
  730. cirq_core-1.5.0.dev20250409225226.dist-info/RECORD +0 -1216
  731. {cirq_core-1.5.0.dev20250409225226.dist-info → cirq_core-1.6.0.dist-info}/licenses/LICENSE +0 -0
  732. {cirq_core-1.5.0.dev20250409225226.dist-info → cirq_core-1.6.0.dist-info}/top_level.txt +0 -0
@@ -18,25 +18,15 @@ from __future__ import annotations
18
18
 
19
19
  from functools import cached_property
20
20
  from types import NotImplementedType
21
- from typing import (
22
- AbstractSet,
23
- FrozenSet,
24
- Hashable,
25
- Iterable,
26
- Iterator,
27
- Sequence,
28
- Tuple,
29
- TYPE_CHECKING,
30
- Union,
31
- )
32
-
33
- import numpy as np
21
+ from typing import AbstractSet, Hashable, Iterable, Iterator, Sequence, TYPE_CHECKING
34
22
 
35
23
  from cirq import _compat, protocols
36
24
  from cirq.circuits import AbstractCircuit, Alignment, Circuit
37
25
  from cirq.circuits.insert_strategy import InsertStrategy
38
26
 
39
27
  if TYPE_CHECKING:
28
+ import numpy as np
29
+
40
30
  import cirq
41
31
 
42
32
 
@@ -75,9 +65,12 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
75
65
  self._tags = tuple(tags)
76
66
 
77
67
  @classmethod
78
- def _from_moments(cls, moments: Iterable[cirq.Moment]) -> FrozenCircuit:
68
+ def _from_moments(
69
+ cls, moments: Iterable[cirq.Moment], tags: Sequence[Hashable]
70
+ ) -> FrozenCircuit:
79
71
  new_circuit = FrozenCircuit()
80
72
  new_circuit._moments = tuple(moments)
73
+ new_circuit._tags = tuple(tags)
81
74
  return new_circuit
82
75
 
83
76
  @property
@@ -88,17 +81,16 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
88
81
  return self
89
82
 
90
83
  def unfreeze(self, copy: bool = True) -> cirq.Circuit:
91
- return Circuit._from_moments(self._moments)
84
+ return Circuit._from_moments(self._moments, tags=self.tags)
92
85
 
93
86
  @property
94
- def tags(self) -> Tuple[Hashable, ...]:
87
+ def tags(self) -> tuple[Hashable, ...]:
95
88
  """Returns a tuple of the Circuit's tags."""
96
89
  return self._tags
97
90
 
98
91
  @cached_property
99
92
  def untagged(self) -> cirq.FrozenCircuit:
100
- """Returns the underlying FrozenCircuit without any tags."""
101
- return self._from_moments(self._moments) if self.tags else self
93
+ return super().untagged
102
94
 
103
95
  def with_tags(self, *new_tags: Hashable) -> cirq.FrozenCircuit:
104
96
  """Creates a new tagged `FrozenCircuit` with `self.tags` and `new_tags` combined."""
@@ -113,13 +105,6 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
113
105
  # Explicitly cached for performance
114
106
  return hash((self.moments, self.tags))
115
107
 
116
- def __eq__(self, other):
117
- super_eq = super().__eq__(other)
118
- if super_eq is not True:
119
- return super_eq
120
- other_tags = other.tags if isinstance(other, FrozenCircuit) else ()
121
- return self.tags == other_tags
122
-
123
108
  def __getstate__(self):
124
109
  # Don't save hash when pickling; see #3777.
125
110
  state = self.__dict__
@@ -134,7 +119,7 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
134
119
  return len(self.all_qubits())
135
120
 
136
121
  @_compat.cached_method
137
- def _qid_shape_(self) -> Tuple[int, ...]:
122
+ def _qid_shape_(self) -> tuple[int, ...]:
138
123
  return super()._qid_shape_()
139
124
 
140
125
  @_compat.cached_method
@@ -142,7 +127,7 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
142
127
  return super()._has_unitary_()
143
128
 
144
129
  @_compat.cached_method
145
- def _unitary_(self) -> Union[np.ndarray, NotImplementedType]:
130
+ def _unitary_(self) -> np.ndarray | NotImplementedType:
146
131
  return super()._unitary_()
147
132
 
148
133
  @_compat.cached_method
@@ -150,11 +135,11 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
150
135
  return protocols.is_measurement(self.unfreeze())
151
136
 
152
137
  @_compat.cached_method
153
- def all_qubits(self) -> FrozenSet[cirq.Qid]:
138
+ def all_qubits(self) -> frozenset[cirq.Qid]:
154
139
  return super().all_qubits()
155
140
 
156
141
  @cached_property
157
- def _all_operations(self) -> Tuple[cirq.Operation, ...]:
142
+ def _all_operations(self) -> tuple[cirq.Operation, ...]:
158
143
  return tuple(super().all_operations())
159
144
 
160
145
  def all_operations(self) -> Iterator[cirq.Operation]:
@@ -164,14 +149,14 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
164
149
  return self._is_measurement_()
165
150
 
166
151
  @_compat.cached_method
167
- def all_measurement_key_objs(self) -> FrozenSet[cirq.MeasurementKey]:
152
+ def all_measurement_key_objs(self) -> frozenset[cirq.MeasurementKey]:
168
153
  return super().all_measurement_key_objs()
169
154
 
170
- def _measurement_key_objs_(self) -> FrozenSet[cirq.MeasurementKey]:
155
+ def _measurement_key_objs_(self) -> frozenset[cirq.MeasurementKey]:
171
156
  return self.all_measurement_key_objs()
172
157
 
173
158
  @_compat.cached_method
174
- def _control_keys_(self) -> FrozenSet[cirq.MeasurementKey]:
159
+ def _control_keys_(self) -> frozenset[cirq.MeasurementKey]:
175
160
  return super()._control_keys_()
176
161
 
177
162
  @_compat.cached_method
@@ -179,30 +164,18 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
179
164
  return super().are_all_measurements_terminal()
180
165
 
181
166
  @_compat.cached_method
182
- def all_measurement_key_names(self) -> FrozenSet[str]:
167
+ def all_measurement_key_names(self) -> frozenset[str]:
183
168
  return frozenset(str(key) for key in self.all_measurement_key_objs())
184
169
 
185
170
  @_compat.cached_method
186
171
  def _is_parameterized_(self) -> bool:
187
- return super()._is_parameterized_() or any(
188
- protocols.is_parameterized(tag) for tag in self.tags
189
- )
172
+ return super()._is_parameterized_()
190
173
 
191
174
  @_compat.cached_method
192
175
  def _parameter_names_(self) -> AbstractSet[str]:
193
- tag_params = {name for tag in self.tags for name in protocols.parameter_names(tag)}
194
- return super()._parameter_names_() | tag_params
195
-
196
- def _resolve_parameters_(
197
- self, resolver: cirq.ParamResolver, recursive: bool
198
- ) -> cirq.FrozenCircuit:
199
- resolved_circuit = super()._resolve_parameters_(resolver, recursive)
200
- resolved_tags = [
201
- protocols.resolve_parameters(tag, resolver, recursive) for tag in self.tags
202
- ]
203
- return resolved_circuit.with_tags(*resolved_tags)
176
+ return super()._parameter_names_()
204
177
 
205
- def _measurement_key_names_(self) -> FrozenSet[str]:
178
+ def _measurement_key_names_(self) -> frozenset[str]:
206
179
  return self.all_measurement_key_names()
207
180
 
208
181
  def __add__(self, other) -> cirq.FrozenCircuit:
@@ -227,29 +200,19 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
227
200
  except:
228
201
  return NotImplemented
229
202
 
230
- def _repr_args(self) -> str:
231
- moments_repr = super()._repr_args()
232
- tag_repr = ','.join(_compat.proper_repr(t) for t in self._tags)
233
- return f'{moments_repr}, tags=[{tag_repr}]' if self.tags else moments_repr
234
-
235
- def _json_dict_(self):
236
- attribute_names = ['moments', 'tags'] if self.tags else ['moments']
237
- ret = protocols.obj_to_dict_helper(self, attribute_names)
238
- return ret
239
-
240
203
  @classmethod
241
204
  def _from_json_dict_(cls, moments, *, tags=(), **kwargs):
242
205
  return cls(moments, strategy=InsertStrategy.EARLIEST, tags=tags)
243
206
 
244
207
  def concat_ragged(
245
- *circuits: cirq.AbstractCircuit, align: Union[cirq.Alignment, str] = Alignment.LEFT
208
+ *circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
246
209
  ) -> cirq.FrozenCircuit:
247
210
  return AbstractCircuit.concat_ragged(*circuits, align=align).freeze()
248
211
 
249
212
  concat_ragged.__doc__ = AbstractCircuit.concat_ragged.__doc__
250
213
 
251
214
  def zip(
252
- *circuits: cirq.AbstractCircuit, align: Union[cirq.Alignment, str] = Alignment.LEFT
215
+ *circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
253
216
  ) -> cirq.FrozenCircuit:
254
217
  return AbstractCircuit.zip(*circuits, align=align).freeze()
255
218
 
@@ -16,13 +16,15 @@
16
16
  Behavior shared with Circuit is tested with parameters in circuit_test.py.
17
17
  """
18
18
 
19
+ from __future__ import annotations
20
+
19
21
  import pytest
20
22
  import sympy
21
23
 
22
24
  import cirq
23
25
 
24
26
 
25
- def test_from_moments():
27
+ def test_from_moments() -> None:
26
28
  a, b, c, d = cirq.LineQubit.range(4)
27
29
  moment = cirq.Moment(cirq.Z(a), cirq.Z(b))
28
30
  subcircuit = cirq.FrozenCircuit.from_moments(cirq.X(c), cirq.Y(d))
@@ -49,10 +51,11 @@ def test_from_moments():
49
51
  cirq.Moment(cirq.measure(a, b, key='ab'), cirq.measure(c, d, key='cd')),
50
52
  )
51
53
  assert circuit[0] is moment
54
+ assert isinstance(circuit[1].operations[0], cirq.CircuitOperation)
52
55
  assert circuit[1].operations[0].circuit is subcircuit
53
56
 
54
57
 
55
- def test_freeze_and_unfreeze():
58
+ def test_freeze_and_unfreeze() -> None:
56
59
  a, b = cirq.LineQubit.range(2)
57
60
  c = cirq.Circuit(cirq.X(a), cirq.H(b))
58
61
 
@@ -78,7 +81,7 @@ def test_freeze_and_unfreeze():
78
81
  assert fcc is not f
79
82
 
80
83
 
81
- def test_immutable():
84
+ def test_immutable() -> None:
82
85
  q = cirq.LineQubit(0)
83
86
  c = cirq.FrozenCircuit(cirq.X(q), cirq.H(q))
84
87
 
@@ -87,21 +90,21 @@ def test_immutable():
87
90
  AttributeError,
88
91
  match="(can't set attribute)|(property 'moments' of 'FrozenCircuit' object has no setter)",
89
92
  ):
90
- c.moments = (cirq.Moment(cirq.H(q)), cirq.Moment(cirq.X(q)))
93
+ c.moments = (cirq.Moment(cirq.H(q)), cirq.Moment(cirq.X(q))) # type: ignore[misc]
91
94
 
92
95
 
93
- def test_tagged_circuits():
96
+ def test_tagged_circuits() -> None:
94
97
  q = cirq.LineQubit(0)
95
98
  ops = [cirq.X(q), cirq.H(q)]
96
- tags = [sympy.Symbol("a"), "b"]
99
+ tags = (sympy.Symbol("a"), "b")
97
100
  circuit = cirq.Circuit(ops)
98
101
  frozen_circuit = cirq.FrozenCircuit(ops)
99
102
  tagged_circuit = cirq.FrozenCircuit(ops, tags=tags)
100
103
  # Test equality
101
- assert tagged_circuit.tags == tuple(tags)
104
+ assert tagged_circuit.tags == tags
102
105
  assert circuit == frozen_circuit != tagged_circuit
106
+ assert not cirq.approx_eq(frozen_circuit, tagged_circuit)
103
107
  assert cirq.approx_eq(circuit, frozen_circuit)
104
- assert cirq.approx_eq(frozen_circuit, tagged_circuit)
105
108
  # Test hash
106
109
  assert hash(frozen_circuit) != hash(tagged_circuit)
107
110
  # Test _repr_ and _json_ round trips.
@@ -113,9 +116,29 @@ def test_tagged_circuits():
113
116
  assert tagged_circuit.with_tags("c") == cirq.FrozenCircuit(ops, tags=[*tags, "c"])
114
117
  assert tagged_circuit.untagged == frozen_circuit
115
118
  assert frozen_circuit.untagged is frozen_circuit
119
+ assert tagged_circuit.unfreeze(copy=True).tags == tags
120
+ assert tagged_circuit.unfreeze(copy=False).tags == tags
116
121
  # Test parameterized protocols
117
122
  assert cirq.is_parameterized(frozen_circuit) is False
118
123
  assert cirq.is_parameterized(tagged_circuit) is True
119
124
  assert cirq.parameter_names(tagged_circuit) == {"a"}
125
+ assert cirq.resolve_parameters(tagged_circuit, {"a": 1}).tags == (1, "b")
120
126
  # Tags are not propagated to diagrams yet.
121
127
  assert str(frozen_circuit) == str(tagged_circuit)
128
+ # Test tags are preserved through operations
129
+ assert (tagged_circuit + circuit).tags == tags
130
+ assert (circuit + tagged_circuit).tags == () # We only preserve the tags for the first one
131
+ assert (2 * tagged_circuit).tags == tags
132
+ assert (tagged_circuit * 2).tags == tags
133
+ assert (tagged_circuit**-1).tags == tags
134
+ for c in tagged_circuit.factorize():
135
+ assert tagged_circuit.tags == tags
136
+
137
+ q2 = cirq.LineQubit(1)
138
+ circuit2 = cirq.Circuit(cirq.X(q2), cirq.H(q2))
139
+ assert tagged_circuit.zip(circuit2).tags == tags
140
+ assert circuit2.zip(tagged_circuit).tags == () # We only preserve the tags for the first one
141
+ assert tagged_circuit.concat_ragged(circuit2).tags == tags
142
+ assert (
143
+ circuit2.concat_ragged(tagged_circuit).tags == ()
144
+ ) # We only preserve the tags for the first one
@@ -14,16 +14,18 @@
14
14
 
15
15
  """Hard-coded options for adding multiple operations to a circuit."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
 
18
20
  class InsertStrategy:
19
21
  """Indicates preferences on how to add multiple operations to a circuit."""
20
22
 
21
- NEW: 'InsertStrategy'
22
- NEW_THEN_INLINE: 'InsertStrategy'
23
- INLINE: 'InsertStrategy'
24
- EARLIEST: 'InsertStrategy'
23
+ NEW: InsertStrategy
24
+ NEW_THEN_INLINE: InsertStrategy
25
+ INLINE: InsertStrategy
26
+ EARLIEST: InsertStrategy
25
27
 
26
- def __new__(cls, name: str, doc: str) -> 'InsertStrategy':
28
+ def __new__(cls, name: str, doc: str) -> InsertStrategy:
27
29
  inst = getattr(cls, name, None)
28
30
  if not inst or not isinstance(inst, cls):
29
31
  inst = super().__new__(cls)
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import pickle
16
18
 
17
19
  import pytest
@@ -19,7 +21,7 @@ import pytest
19
21
  import cirq
20
22
 
21
23
 
22
- def test_repr():
24
+ def test_repr() -> None:
23
25
  assert repr(cirq.InsertStrategy.NEW) == 'cirq.InsertStrategy.NEW'
24
26
  assert str(cirq.InsertStrategy.NEW) == 'NEW'
25
27
 
@@ -34,6 +36,6 @@ def test_repr():
34
36
  ],
35
37
  ids=lambda strategy: strategy.name,
36
38
  )
37
- def test_identity_after_pickling(strategy: cirq.InsertStrategy):
39
+ def test_identity_after_pickling(strategy: cirq.InsertStrategy) -> None:
38
40
  unpickled_strategy = pickle.loads(pickle.dumps(strategy))
39
41
  assert unpickled_strategy is strategy
cirq/circuits/moment.py CHANGED
@@ -24,18 +24,13 @@ from typing import (
24
24
  Any,
25
25
  Callable,
26
26
  cast,
27
- Dict,
28
- FrozenSet,
27
+ Hashable,
29
28
  Iterable,
30
29
  Iterator,
31
- List,
32
30
  Mapping,
33
- Optional,
34
31
  overload,
35
32
  Sequence,
36
- Tuple,
37
33
  TYPE_CHECKING,
38
- Union,
39
34
  )
40
35
 
41
36
  import numpy as np
@@ -51,13 +46,12 @@ if TYPE_CHECKING:
51
46
 
52
47
  # Lazy imports to break circular dependencies.
53
48
  circuit = LazyLoader("circuit", globals(), "cirq.circuits.circuit")
54
- op_tree = LazyLoader("op_tree", globals(), "cirq.ops.op_tree")
55
49
  text_diagram_drawer = LazyLoader(
56
50
  "text_diagram_drawer", globals(), "cirq.circuits.text_diagram_drawer"
57
51
  )
58
52
 
59
53
 
60
- def _default_breakdown(qid: cirq.Qid) -> Tuple[Any, Any]:
54
+ def _default_breakdown(qid: cirq.Qid) -> tuple[Any, Any]:
61
55
  # Attempt to convert into a position on the complex plane.
62
56
  try:
63
57
  plane_pos = complex(qid) # type: ignore
@@ -84,7 +78,12 @@ class Moment:
84
78
  are no such operations, returns an empty Moment.
85
79
  """
86
80
 
87
- def __init__(self, *contents: cirq.OP_TREE, _flatten_contents: bool = True) -> None:
81
+ def __init__(
82
+ self,
83
+ *contents: cirq.OP_TREE,
84
+ _flatten_contents: bool = True,
85
+ tags: tuple[Hashable, ...] = (),
86
+ ) -> None:
88
87
  """Constructs a moment with the given operations.
89
88
 
90
89
  Args:
@@ -95,6 +94,12 @@ class Moment:
95
94
  we skip flattening and assume that contents already consists
96
95
  of individual operations. This is used internally by helper
97
96
  methods to avoid unnecessary validation.
97
+ tags: Optional tags to denote specific Moment objects with meta-data.
98
+ These are a tuple of any Hashable object. Typically, a class
99
+ will be passed. Tags apply only to this specific set of operations
100
+ and will be lost on any transformation of the
101
+ Moment. For instance, if operations are added to the Moment, tags
102
+ will be dropped unless explicitly added back in by the user.
98
103
 
99
104
  Raises:
100
105
  ValueError: A qubit appears more than once.
@@ -102,12 +107,12 @@ class Moment:
102
107
  self._operations = (
103
108
  tuple(op_tree.flatten_to_ops(contents))
104
109
  if _flatten_contents
105
- else cast(Tuple['cirq.Operation'], contents)
110
+ else cast(tuple['cirq.Operation'], contents)
106
111
  )
107
- self._sorted_operations: Optional[Tuple[cirq.Operation, ...]] = None
112
+ self._sorted_operations: tuple[cirq.Operation, ...] | None = None
108
113
 
109
114
  # An internal dictionary to support efficient operation access by qubit.
110
- self._qubit_to_op: Dict[cirq.Qid, cirq.Operation] = {}
115
+ self._qubit_to_op: dict[cirq.Qid, cirq.Operation] = {}
111
116
  for op in self.operations:
112
117
  for q in op.qubits:
113
118
  # Check that operations don't overlap.
@@ -115,11 +120,12 @@ class Moment:
115
120
  raise ValueError(f'Overlapping operations: {self.operations}')
116
121
  self._qubit_to_op[q] = op
117
122
 
118
- self._measurement_key_objs: Optional[FrozenSet[cirq.MeasurementKey]] = None
119
- self._control_keys: Optional[FrozenSet[cirq.MeasurementKey]] = None
123
+ self._measurement_key_objs: frozenset[cirq.MeasurementKey] | None = None
124
+ self._control_keys: frozenset[cirq.MeasurementKey] | None = None
125
+ self._tags = tags
120
126
 
121
127
  @classmethod
122
- def from_ops(cls, *ops: cirq.Operation) -> cirq.Moment:
128
+ def from_ops(cls, *ops: cirq.Operation, tags: tuple[Hashable, ...] = ()) -> cirq.Moment:
123
129
  """Construct a Moment from the given operations.
124
130
 
125
131
  This avoids calling `flatten_to_ops` in the moment constructor, which
@@ -129,17 +135,48 @@ class Moment:
129
135
 
130
136
  Args:
131
137
  *ops: Operations to include in the Moment.
138
+ tags: Optional tags to denote specific Moment objects with meta-data.
139
+ These are a tuple of any Hashable object. Tags will be dropped if
140
+ the operations in the Moment are modified or transformed.
132
141
  """
133
- return cls(*ops, _flatten_contents=False)
142
+ return cls(*ops, _flatten_contents=False, tags=tags)
134
143
 
135
144
  @property
136
- def operations(self) -> Tuple[cirq.Operation, ...]:
145
+ def operations(self) -> tuple[cirq.Operation, ...]:
137
146
  return self._operations
138
147
 
139
148
  @cached_property
140
- def qubits(self) -> FrozenSet[cirq.Qid]:
149
+ def qubits(self) -> frozenset[cirq.Qid]:
141
150
  return frozenset(self._qubit_to_op)
142
151
 
152
+ @property
153
+ def tags(self) -> tuple[Hashable, ...]:
154
+ """Returns a tuple of the operation's tags."""
155
+ return self._tags
156
+
157
+ def with_tags(self, *new_tags: Hashable) -> cirq.Moment:
158
+ """Creates a new Moment with the current ops and the specified tags.
159
+
160
+ If the moment already has tags, this will add the new_tags to the
161
+ preexisting tags.
162
+
163
+ This method can be used to attach meta-data to moments
164
+ without affecting their functionality. The intended usage is to
165
+ attach classes intended for this purpose or strings to mark operations
166
+ for specific usage that will be recognized by consumers.
167
+
168
+ Tags can be a list of any type of object that is useful to identify
169
+ this operation as long as the type is hashable. If you wish the
170
+ resulting operation to be eventually serialized into JSON, you should
171
+ also restrict the operation to be JSON serializable.
172
+
173
+ Please note that tags should be instantiated if classes are
174
+ used. Raw types are not allowed.
175
+ """
176
+ if not new_tags:
177
+ return self
178
+ return Moment(*self._operations, _flatten_contents=False, tags=(*self._tags, *new_tags))
179
+
143
180
  def operates_on_single_qubit(self, qubit: cirq.Qid) -> bool:
144
181
  """Determines if the moment has operations touching the given qubit.
145
182
  Args:
@@ -160,7 +197,7 @@ class Moment:
160
197
  """
161
198
  return not self._qubit_to_op.keys().isdisjoint(qubits)
162
199
 
163
- def operation_at(self, qubit: raw_types.Qid) -> Optional[cirq.Operation]:
200
+ def operation_at(self, qubit: raw_types.Qid) -> cirq.Operation | None:
164
201
  """Returns the operation on a certain qubit for the moment.
165
202
 
166
203
  Args:
@@ -177,6 +214,8 @@ class Moment:
177
214
  def with_operation(self, operation: cirq.Operation) -> cirq.Moment:
178
215
  """Returns an equal moment, but with the given op added.
179
216
 
217
+ Any tags on the Moment will be dropped.
218
+
180
219
  Args:
181
220
  operation: The operation to append.
182
221
 
@@ -205,6 +244,9 @@ class Moment:
205
244
  def with_operations(self, *contents: cirq.OP_TREE) -> cirq.Moment:
206
245
  """Returns a new moment with the given contents added.
207
246
 
247
+ Any tags on the original Moment object are dropped if the Moment
248
+ is changed.
249
+
208
250
  Args:
209
251
  *contents: New operations to add to this moment.
210
252
 
@@ -242,6 +284,9 @@ class Moment:
242
284
  def without_operations_touching(self, qubits: Iterable[cirq.Qid]) -> cirq.Moment:
243
285
  """Returns an equal moment, but without ops on the given qubits.
244
286
 
287
+ Any tags on the original Moment object are dropped if the Moment
288
+ is changed.
289
+
245
290
  Args:
246
291
  qubits: Operations that touch these will be removed.
247
292
 
@@ -267,7 +312,7 @@ class Moment:
267
312
 
268
313
  def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> cirq.Moment:
269
314
  changed = False
270
- resolved_ops: List[cirq.Operation] = []
315
+ resolved_ops: list[cirq.Operation] = []
271
316
  for op in self:
272
317
  resolved_op = protocols.resolve_parameters(op, resolver, recursive)
273
318
  changed = (
@@ -291,35 +336,35 @@ class Moment:
291
336
  )
292
337
 
293
338
  @_compat.cached_method()
294
- def _measurement_key_names_(self) -> FrozenSet[str]:
339
+ def _measurement_key_names_(self) -> frozenset[str]:
295
340
  return frozenset(str(key) for key in self._measurement_key_objs_())
296
341
 
297
- def _measurement_key_objs_(self) -> FrozenSet[cirq.MeasurementKey]:
342
+ def _measurement_key_objs_(self) -> frozenset[cirq.MeasurementKey]:
298
343
  if self._measurement_key_objs is None:
299
344
  self._measurement_key_objs = frozenset(
300
345
  key for op in self.operations for key in protocols.measurement_key_objs(op)
301
346
  )
302
347
  return self._measurement_key_objs
303
348
 
304
- def _control_keys_(self) -> FrozenSet[cirq.MeasurementKey]:
349
+ def _control_keys_(self) -> frozenset[cirq.MeasurementKey]:
305
350
  if self._control_keys is None:
306
351
  self._control_keys = frozenset(
307
352
  k for op in self.operations for k in protocols.control_keys(op)
308
353
  )
309
354
  return self._control_keys
310
355
 
311
- def _sorted_operations_(self) -> Tuple[cirq.Operation, ...]:
356
+ def _sorted_operations_(self) -> tuple[cirq.Operation, ...]:
312
357
  if self._sorted_operations is None:
313
358
  self._sorted_operations = tuple(sorted(self._operations, key=lambda op: op.qubits))
314
359
  return self._sorted_operations
315
360
 
316
- def _with_key_path_(self, path: Tuple[str, ...]):
361
+ def _with_key_path_(self, path: tuple[str, ...]):
317
362
  return Moment(
318
363
  protocols.with_key_path(op, path) if protocols.is_measurement(op) else op
319
364
  for op in self.operations
320
365
  )
321
366
 
322
- def _with_key_path_prefix_(self, prefix: Tuple[str, ...]):
367
+ def _with_key_path_prefix_(self, prefix: tuple[str, ...]):
323
368
  return Moment(
324
369
  (
325
370
  protocols.with_key_path_prefix(op, prefix)
@@ -330,7 +375,7 @@ class Moment:
330
375
  )
331
376
 
332
377
  def _with_rescoped_keys_(
333
- self, path: Tuple[str, ...], bindable_keys: FrozenSet[cirq.MeasurementKey]
378
+ self, path: tuple[str, ...], bindable_keys: frozenset[cirq.MeasurementKey]
334
379
  ):
335
380
  return Moment(
336
381
  protocols.with_rescoped_keys(op, path, bindable_keys) for op in self.operations
@@ -364,7 +409,7 @@ class Moment:
364
409
  def __hash__(self):
365
410
  return hash((Moment, self._sorted_operations_()))
366
411
 
367
- def __getstate__(self) -> Dict[str, Any]:
412
+ def __getstate__(self) -> dict[str, Any]:
368
413
  # clear cached hash value when pickling, see #6674
369
414
  state = self.__dict__
370
415
  hash_attr = _compat._method_cache_name(self.__hash__)
@@ -407,7 +452,7 @@ class Moment:
407
452
  return self._operations
408
453
 
409
454
  def transform_qubits(
410
- self, qubit_map: Union[Dict[cirq.Qid, cirq.Qid], Callable[[cirq.Qid], cirq.Qid]]
455
+ self, qubit_map: dict[cirq.Qid, cirq.Qid] | Callable[[cirq.Qid], cirq.Qid]
411
456
  ) -> Self:
412
457
  """Returns the same moment, but with different qubits.
413
458
 
@@ -516,12 +561,14 @@ class Moment:
516
561
  return NotImplemented
517
562
  return qis.kraus_to_superoperator(self._kraus_())
518
563
 
519
- def _json_dict_(self) -> Dict[str, Any]:
520
- return protocols.obj_to_dict_helper(self, ['operations'])
564
+ def _json_dict_(self) -> dict[str, Any]:
565
+ # For backwards compatibility, only output tags if they exist.
566
+ args = ['operations', 'tags'] if self._tags else ['operations']
567
+ return protocols.obj_to_dict_helper(self, args)
521
568
 
522
569
  @classmethod
523
- def _from_json_dict_(cls, operations, **kwargs):
524
- return cls.from_ops(*operations)
570
+ def _from_json_dict_(cls, operations, tags=(), **kwargs):
571
+ return cls(*operations, tags=tags)
525
572
 
526
573
  def __add__(self, other: cirq.OP_TREE) -> cirq.Moment:
527
574
  if isinstance(other, circuit.AbstractCircuit):
@@ -544,7 +591,6 @@ class Moment:
544
591
  )
545
592
  return Moment(new_ops)
546
593
 
547
- # pylint: disable=function-redefined
548
594
  @overload
549
595
  def __getitem__(self, key: raw_types.Qid) -> cirq.Operation:
550
596
  pass
@@ -569,11 +615,11 @@ class Moment:
569
615
  def to_text_diagram(
570
616
  self: cirq.Moment,
571
617
  *,
572
- xy_breakdown_func: Callable[[cirq.Qid], Tuple[Any, Any]] = _default_breakdown,
618
+ xy_breakdown_func: Callable[[cirq.Qid], tuple[Any, Any]] = _default_breakdown,
573
619
  extra_qubits: Iterable[cirq.Qid] = (),
574
620
  use_unicode_characters: bool = True,
575
- precision: Optional[int] = None,
576
- include_tags: bool = True,
621
+ precision: int | None = None,
622
+ include_tags: bool | Iterable[type] = True,
577
623
  ) -> str:
578
624
  """Create a text diagram for the moment.
579
625
 
@@ -591,8 +637,10 @@ class Moment:
591
637
  precision: How precise numbers, such as angles, should be. Use None
592
638
  for infinite precision, or an integer for a certain number of
593
639
  digits of precision.
594
- include_tags: Whether or not to include operation tags in the
595
- diagram.
640
+ include_tags: Controls which tags attached to operations are
641
+ included. ``True`` includes all tags, ``False`` includes none,
642
+ or a collection of tag classes may be specified to include only
643
+ those tags.
596
644
 
597
645
  Returns:
598
646
  The text diagram rendered into text.
@@ -657,7 +705,7 @@ class Moment:
657
705
 
658
706
  return diagram.render()
659
707
 
660
- def _commutes_(self, other: Any, *, atol: float = 1e-8) -> Union[bool, NotImplementedType]:
708
+ def _commutes_(self, other: Any, *, atol: float = 1e-8) -> bool | NotImplementedType:
661
709
  """Determines whether Moment commutes with the other Moment or Operation.
662
710
 
663
711
  Args: