cirq-core 1.5.0.dev20250409222543__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.dev20250409222543.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.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/WHEEL +1 -1
  730. cirq_core-1.5.0.dev20250409222543.dist-info/RECORD +0 -1216
  731. {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/licenses/LICENSE +0 -0
  732. {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/top_level.txt +0 -0
cirq/ops/common_gates.py CHANGED
@@ -25,19 +25,10 @@ Each of these are implemented as EigenGates, which means that they can be
25
25
  raised to a power (i.e. cirq.H**0.5). See the definition in EigenGate.
26
26
  """
27
27
 
28
+ from __future__ import annotations
29
+
28
30
  from types import NotImplementedType
29
- from typing import (
30
- Any,
31
- cast,
32
- Collection,
33
- Dict,
34
- List,
35
- Optional,
36
- Sequence,
37
- Tuple,
38
- TYPE_CHECKING,
39
- Union,
40
- )
31
+ from typing import Any, cast, Collection, Sequence
41
32
 
42
33
  import numpy as np
43
34
  import sympy
@@ -46,13 +37,17 @@ import cirq
46
37
  from cirq import protocols, value
47
38
  from cirq._compat import proper_repr
48
39
  from cirq._doc import document
49
- from cirq.ops import control_values as cv, controlled_gate, eigen_gate, gate_features, raw_types
40
+ from cirq.ops import (
41
+ control_values as cv,
42
+ controlled_gate,
43
+ eigen_gate,
44
+ gate_features,
45
+ global_phase_op,
46
+ raw_types,
47
+ )
50
48
  from cirq.ops.measurement_gate import MeasurementGate
51
49
  from cirq.ops.swap_gates import ISWAP, ISwapPowGate, SWAP, SwapPowGate
52
50
 
53
- if TYPE_CHECKING:
54
- import cirq
55
-
56
51
  assert all(
57
52
  [ISWAP, SWAP, ISwapPowGate, SwapPowGate, MeasurementGate]
58
53
  ), """
@@ -87,7 +82,7 @@ class XPowGate(eigen_gate.EigenGate):
87
82
  `cirq.X`, the Pauli X gate, is an instance of this gate at `exponent=1`.
88
83
  """
89
84
 
90
- _eigencomponents: Dict[int, List[Tuple[float, np.ndarray]]] = {}
85
+ _eigencomponents: dict[int, list[tuple[float, np.ndarray]]] = {}
91
86
 
92
87
  def __init__(
93
88
  self, *, exponent: value.TParamVal = 1.0, global_shift: float = 0.0, dimension: int = 2
@@ -126,7 +121,7 @@ class XPowGate(eigen_gate.EigenGate):
126
121
  def _num_qubits_(self) -> int:
127
122
  return 1
128
123
 
129
- def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs') -> Optional[np.ndarray]:
124
+ def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray | None:
130
125
  if self._exponent != 1 or self._dimension != 2:
131
126
  return NotImplemented
132
127
  zero = args.subspace_index(0)
@@ -138,18 +133,18 @@ class XPowGate(eigen_gate.EigenGate):
138
133
  args.available_buffer *= p
139
134
  return args.available_buffer
140
135
 
141
- def in_su2(self) -> 'Rx':
136
+ def in_su2(self) -> Rx:
142
137
  """Returns an equal-up-global-phase gate from the group SU2."""
143
138
  return Rx(rads=self._exponent * _pi(self._exponent))
144
139
 
145
- def with_canonical_global_phase(self) -> 'XPowGate':
140
+ def with_canonical_global_phase(self) -> XPowGate:
146
141
  """Returns an equal-up-global-phase standardized form of the gate."""
147
142
  return XPowGate(exponent=self._exponent, dimension=self._dimension)
148
143
 
149
- def _qid_shape_(self) -> Tuple[int, ...]:
144
+ def _qid_shape_(self) -> tuple[int, ...]:
150
145
  return (self._dimension,)
151
146
 
152
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
147
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
153
148
  if self._dimension not in XPowGate._eigencomponents:
154
149
  components = []
155
150
  root = 1j ** (4 / self._dimension)
@@ -161,7 +156,7 @@ class XPowGate(eigen_gate.EigenGate):
161
156
  XPowGate._eigencomponents[self._dimension] = components
162
157
  return XPowGate._eigencomponents[self._dimension]
163
158
 
164
- def _with_exponent(self, exponent: 'cirq.TParamVal') -> 'cirq.XPowGate':
159
+ def _with_exponent(self, exponent: cirq.TParamVal) -> cirq.XPowGate:
165
160
  return XPowGate(
166
161
  exponent=exponent, global_shift=self._global_shift, dimension=self._dimension
167
162
  )
@@ -179,18 +174,16 @@ class XPowGate(eigen_gate.EigenGate):
179
174
  return SingleQubitCliffordGate.X_nsqrt.on(*qubits)
180
175
  return NotImplemented # pragma: no cover
181
176
 
182
- def _trace_distance_bound_(self) -> Optional[float]:
177
+ def _trace_distance_bound_(self) -> float | None:
183
178
  if self._is_parameterized_() or self._dimension != 2:
184
179
  return None
185
180
  return abs(np.sin(self._exponent * 0.5 * np.pi))
186
181
 
187
182
  def controlled(
188
183
  self,
189
- num_controls: Optional[int] = None,
190
- control_values: Optional[
191
- Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
192
- ] = None,
193
- control_qid_shape: Optional[Tuple[int, ...]] = None,
184
+ num_controls: int | None = None,
185
+ control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
186
+ control_qid_shape: tuple[int, ...] | None = None,
194
187
  ) -> raw_types.Gate:
195
188
  """Returns a controlled `XPowGate`, using a `CXPowGate` where possible.
196
189
 
@@ -236,27 +229,24 @@ class XPowGate(eigen_gate.EigenGate):
236
229
  A `cirq.ControlledGate` (or `cirq.CXPowGate` if possible) representing
237
230
  `self` controlled by the given control values and qubits.
238
231
  """
239
- if control_values and not isinstance(control_values, cv.AbstractControlValues):
240
- control_values = cv.ProductOfSums(
241
- tuple(
242
- (val,) if isinstance(val, int) else tuple(sorted(val)) for val in control_values
243
- )
244
- )
245
232
  result = super().controlled(num_controls, control_values, control_qid_shape)
246
233
  if (
247
234
  self._global_shift == 0
248
235
  and isinstance(result, controlled_gate.ControlledGate)
249
236
  and isinstance(result.control_values, cv.ProductOfSums)
250
- and result.control_values[-1] == (1,)
251
- and result.control_qid_shape[-1] == 2
237
+ and result.control_values.is_trivial
252
238
  ):
253
- return cirq.CXPowGate(
254
- exponent=self._exponent, global_shift=self._global_shift
255
- ).controlled(
256
- result.num_controls() - 1, result.control_values[:-1], result.control_qid_shape[:-1]
257
- )
239
+ if result.control_qid_shape == (2,):
240
+ return cirq.CXPowGate(exponent=self._exponent)
241
+ if result.control_qid_shape == (2, 2):
242
+ return cirq.CCXPowGate(exponent=self._exponent)
258
243
  return result
259
244
 
245
+ def _decompose_with_context_(
246
+ self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext
247
+ ) -> list[cirq.Operation] | NotImplementedType:
248
+ return _extract_phase(self, XPowGate, qubits, context)
249
+
260
250
  def _pauli_expansion_(self) -> value.LinearDict[str]:
261
251
  if self._dimension != 2:
262
252
  return NotImplemented # pragma: no cover
@@ -266,13 +256,13 @@ class XPowGate(eigen_gate.EigenGate):
266
256
  return value.LinearDict({'I': phase * lib.cos(angle), 'X': -1j * phase * lib.sin(angle)})
267
257
 
268
258
  def _circuit_diagram_info_(
269
- self, args: 'cirq.CircuitDiagramInfoArgs'
270
- ) -> Union[str, 'protocols.CircuitDiagramInfo']:
259
+ self, args: cirq.CircuitDiagramInfoArgs
260
+ ) -> str | protocols.CircuitDiagramInfo:
271
261
  return protocols.CircuitDiagramInfo(
272
262
  wire_symbols=('X',), exponent=self._diagram_exponent(args)
273
263
  )
274
264
 
275
- def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
265
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
276
266
  args.validate_version('2.0', '3.0')
277
267
  if self._global_shift == 0:
278
268
  if self._exponent == 1:
@@ -291,7 +281,7 @@ class XPowGate(eigen_gate.EigenGate):
291
281
  """See `cirq.SupportsPhase`."""
292
282
  return _phased_x_or_pauli_gate(exponent=self._exponent, phase_exponent=phase_turns * 2)
293
283
 
294
- def _has_stabilizer_effect_(self) -> Optional[bool]:
284
+ def _has_stabilizer_effect_(self) -> bool | None:
295
285
  if self._is_parameterized_() or self._dimension != 2:
296
286
  return None
297
287
  return self.exponent % 0.5 == 0
@@ -318,7 +308,7 @@ class XPowGate(eigen_gate.EigenGate):
318
308
  all_args = ', '.join(args)
319
309
  return f'cirq.XPowGate({all_args})'
320
310
 
321
- def _json_dict_(self) -> Dict[str, Any]:
311
+ def _json_dict_(self) -> dict[str, Any]:
322
312
  d = protocols.obj_to_dict_helper(self, ['exponent', 'global_shift'])
323
313
  if self.dimension != 2:
324
314
  d['dimension'] = self.dimension
@@ -349,12 +339,12 @@ class Rx(XPowGate):
349
339
  self._rads = rads
350
340
  super().__init__(exponent=rads / _pi(rads), global_shift=-0.5)
351
341
 
352
- def _with_exponent(self, exponent: value.TParamVal) -> 'Rx':
342
+ def _with_exponent(self, exponent: value.TParamVal) -> Rx:
353
343
  return Rx(rads=exponent * _pi(exponent))
354
344
 
355
345
  def _circuit_diagram_info_(
356
- self, args: 'cirq.CircuitDiagramInfoArgs'
357
- ) -> Union[str, 'protocols.CircuitDiagramInfo']:
346
+ self, args: cirq.CircuitDiagramInfoArgs
347
+ ) -> str | protocols.CircuitDiagramInfo:
358
348
  angle_str = self._format_exponent_as_angle(args)
359
349
  return f'Rx({angle_str})'
360
350
 
@@ -366,15 +356,15 @@ class Rx(XPowGate):
366
356
  def __repr__(self) -> str:
367
357
  return f'cirq.Rx(rads={proper_repr(self._rads)})'
368
358
 
369
- def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
359
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
370
360
  args.validate_version('2.0', '3.0')
371
361
  return args.format('rx({0:half_turns}) {1};\n', self._exponent, qubits[0])
372
362
 
373
- def _json_dict_(self) -> Dict[str, Any]:
363
+ def _json_dict_(self) -> dict[str, Any]:
374
364
  return {'rads': self._rads}
375
365
 
376
366
  @classmethod
377
- def _from_json_dict_(cls, rads, **kwargs) -> 'Rx':
367
+ def _from_json_dict_(cls, rads, **kwargs) -> Rx:
378
368
  return cls(rads=rads)
379
369
 
380
370
 
@@ -412,7 +402,7 @@ class YPowGate(eigen_gate.EigenGate):
412
402
  def _num_qubits_(self) -> int:
413
403
  return 1
414
404
 
415
- def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs') -> Optional[np.ndarray]:
405
+ def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray | None:
416
406
  if self._exponent != 1:
417
407
  return NotImplemented
418
408
  zero = args.subspace_index(0)
@@ -424,11 +414,11 @@ class YPowGate(eigen_gate.EigenGate):
424
414
  args.available_buffer *= p
425
415
  return args.available_buffer
426
416
 
427
- def in_su2(self) -> 'Ry':
417
+ def in_su2(self) -> Ry:
428
418
  """Returns an equal-up-global-phase gate from the group SU2."""
429
419
  return Ry(rads=self._exponent * _pi(self._exponent))
430
420
 
431
- def with_canonical_global_phase(self) -> 'YPowGate':
421
+ def with_canonical_global_phase(self) -> YPowGate:
432
422
  """Returns an equal-up-global-phase standardized form of the gate."""
433
423
  return YPowGate(exponent=self._exponent)
434
424
 
@@ -445,13 +435,13 @@ class YPowGate(eigen_gate.EigenGate):
445
435
  return SingleQubitCliffordGate.Y_nsqrt.on(*qubits)
446
436
  return NotImplemented # pragma: no cover
447
437
 
448
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
438
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
449
439
  return [
450
440
  (0, np.array([[0.5, -0.5j], [0.5j, 0.5]])),
451
441
  (1, np.array([[0.5, 0.5j], [-0.5j, 0.5]])),
452
442
  ]
453
443
 
454
- def _trace_distance_bound_(self) -> Optional[float]:
444
+ def _trace_distance_bound_(self) -> float | None:
455
445
  if self._is_parameterized_():
456
446
  return None
457
447
  return abs(np.sin(self._exponent * 0.5 * np.pi))
@@ -463,13 +453,13 @@ class YPowGate(eigen_gate.EigenGate):
463
453
  return value.LinearDict({'I': phase * lib.cos(angle), 'Y': -1j * phase * lib.sin(angle)})
464
454
 
465
455
  def _circuit_diagram_info_(
466
- self, args: 'cirq.CircuitDiagramInfoArgs'
467
- ) -> Union[str, 'protocols.CircuitDiagramInfo']:
456
+ self, args: cirq.CircuitDiagramInfoArgs
457
+ ) -> str | protocols.CircuitDiagramInfo:
468
458
  return protocols.CircuitDiagramInfo(
469
459
  wire_symbols=('Y',), exponent=self._diagram_exponent(args)
470
460
  )
471
461
 
472
- def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
462
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
473
463
  args.validate_version('2.0', '3.0')
474
464
  if self._exponent == 1 and self.global_shift != -0.5:
475
465
  return args.format('y {0};\n', qubits[0])
@@ -486,7 +476,7 @@ class YPowGate(eigen_gate.EigenGate):
486
476
  exponent=self._exponent, phase_exponent=0.5 + phase_turns * 2
487
477
  )
488
478
 
489
- def _has_stabilizer_effect_(self) -> Optional[bool]:
479
+ def _has_stabilizer_effect_(self) -> bool | None:
490
480
  if self._is_parameterized_():
491
481
  return None
492
482
  return self.exponent % 0.5 == 0
@@ -509,6 +499,11 @@ class YPowGate(eigen_gate.EigenGate):
509
499
  f'global_shift={self._global_shift!r})'
510
500
  )
511
501
 
502
+ def _decompose_with_context_(
503
+ self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext
504
+ ) -> list[cirq.Operation] | NotImplementedType:
505
+ return _extract_phase(self, YPowGate, qubits, context)
506
+
512
507
 
513
508
  class Ry(YPowGate):
514
509
  r"""A gate with matrix $e^{-i Y t/2}$ that rotates around the Y axis of the Bloch sphere by $t$.
@@ -534,12 +529,12 @@ class Ry(YPowGate):
534
529
  self._rads = rads
535
530
  super().__init__(exponent=rads / _pi(rads), global_shift=-0.5)
536
531
 
537
- def _with_exponent(self, exponent: value.TParamVal) -> 'Ry':
532
+ def _with_exponent(self, exponent: value.TParamVal) -> Ry:
538
533
  return Ry(rads=exponent * _pi(exponent))
539
534
 
540
535
  def _circuit_diagram_info_(
541
- self, args: 'cirq.CircuitDiagramInfoArgs'
542
- ) -> Union[str, 'protocols.CircuitDiagramInfo']:
536
+ self, args: cirq.CircuitDiagramInfoArgs
537
+ ) -> str | protocols.CircuitDiagramInfo:
543
538
  angle_str = self._format_exponent_as_angle(args)
544
539
  return f'Ry({angle_str})'
545
540
 
@@ -551,15 +546,15 @@ class Ry(YPowGate):
551
546
  def __repr__(self) -> str:
552
547
  return f'cirq.Ry(rads={proper_repr(self._rads)})'
553
548
 
554
- def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
549
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
555
550
  args.validate_version('2.0', '3.0')
556
551
  return args.format('ry({0:half_turns}) {1};\n', self._exponent, qubits[0])
557
552
 
558
- def _json_dict_(self) -> Dict[str, Any]:
553
+ def _json_dict_(self) -> dict[str, Any]:
559
554
  return {'rads': self._rads}
560
555
 
561
556
  @classmethod
562
- def _from_json_dict_(cls, rads, **kwargs) -> 'Ry':
557
+ def _from_json_dict_(cls, rads, **kwargs) -> Ry:
563
558
  return cls(rads=rads)
564
559
 
565
560
 
@@ -585,7 +580,7 @@ class ZPowGate(eigen_gate.EigenGate):
585
580
  `cirq.Z`, the Pauli Z gate, is an instance of this gate at `exponent=1`.
586
581
  """
587
582
 
588
- _eigencomponents: Dict[int, List[Tuple[float, np.ndarray]]] = {}
583
+ _eigencomponents: dict[int, list[tuple[float, np.ndarray]]] = {}
589
584
 
590
585
  def __init__(
591
586
  self, *, exponent: value.TParamVal = 1.0, global_shift: float = 0.0, dimension: int = 2
@@ -624,7 +619,7 @@ class ZPowGate(eigen_gate.EigenGate):
624
619
  def _num_qubits_(self) -> int:
625
620
  return 1
626
621
 
627
- def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs') -> Optional[np.ndarray]:
622
+ def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray | None:
628
623
  if protocols.is_parameterized(self):
629
624
  return None
630
625
 
@@ -650,21 +645,19 @@ class ZPowGate(eigen_gate.EigenGate):
650
645
  return SingleQubitCliffordGate.Z_nsqrt.on(*qubits)
651
646
  return NotImplemented # pragma: no cover
652
647
 
653
- def in_su2(self) -> 'Rz':
648
+ def in_su2(self) -> Rz:
654
649
  """Returns an equal-up-global-phase gate from the group SU2."""
655
650
  return Rz(rads=self._exponent * _pi(self._exponent))
656
651
 
657
- def with_canonical_global_phase(self) -> 'ZPowGate':
652
+ def with_canonical_global_phase(self) -> ZPowGate:
658
653
  """Returns an equal-up-global-phase standardized form of the gate."""
659
654
  return ZPowGate(exponent=self._exponent, dimension=self._dimension)
660
655
 
661
656
  def controlled(
662
657
  self,
663
- num_controls: Optional[int] = None,
664
- control_values: Optional[
665
- Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
666
- ] = None,
667
- control_qid_shape: Optional[Tuple[int, ...]] = None,
658
+ num_controls: int | None = None,
659
+ control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
660
+ control_qid_shape: tuple[int, ...] | None = None,
668
661
  ) -> raw_types.Gate:
669
662
  """Returns a controlled `ZPowGate`, using a `CZPowGate` where possible.
670
663
 
@@ -710,31 +703,28 @@ class ZPowGate(eigen_gate.EigenGate):
710
703
  A `cirq.ControlledGate` (or `cirq.CZPowGate` if possible) representing
711
704
  `self` controlled by the given control values and qubits.
712
705
  """
713
- if control_values and not isinstance(control_values, cv.AbstractControlValues):
714
- control_values = cv.ProductOfSums(
715
- tuple(
716
- (val,) if isinstance(val, int) else tuple(sorted(val)) for val in control_values
717
- )
718
- )
719
706
  result = super().controlled(num_controls, control_values, control_qid_shape)
720
707
  if (
721
708
  self._global_shift == 0
722
709
  and isinstance(result, controlled_gate.ControlledGate)
723
710
  and isinstance(result.control_values, cv.ProductOfSums)
724
- and result.control_values[-1] == (1,)
725
- and result.control_qid_shape[-1] == 2
711
+ and result.control_values.is_trivial
726
712
  ):
727
- return cirq.CZPowGate(
728
- exponent=self._exponent, global_shift=self._global_shift
729
- ).controlled(
730
- result.num_controls() - 1, result.control_values[:-1], result.control_qid_shape[:-1]
731
- )
713
+ if result.control_qid_shape == (2,):
714
+ return cirq.CZPowGate(exponent=self._exponent)
715
+ if result.control_qid_shape == (2, 2):
716
+ return cirq.CCZPowGate(exponent=self._exponent)
732
717
  return result
733
718
 
734
- def _qid_shape_(self) -> Tuple[int, ...]:
719
+ def _decompose_with_context_(
720
+ self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext
721
+ ) -> list[cirq.Operation] | NotImplementedType:
722
+ return _extract_phase(self, ZPowGate, qubits, context)
723
+
724
+ def _qid_shape_(self) -> tuple[int, ...]:
735
725
  return (self._dimension,)
736
726
 
737
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
727
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
738
728
  if self._dimension not in ZPowGate._eigencomponents:
739
729
  components = []
740
730
  for i in range(self._dimension):
@@ -745,12 +735,12 @@ class ZPowGate(eigen_gate.EigenGate):
745
735
  ZPowGate._eigencomponents[self._dimension] = components
746
736
  return ZPowGate._eigencomponents[self._dimension]
747
737
 
748
- def _with_exponent(self, exponent: 'cirq.TParamVal') -> 'cirq.ZPowGate':
738
+ def _with_exponent(self, exponent: cirq.TParamVal) -> cirq.ZPowGate:
749
739
  return ZPowGate(
750
740
  exponent=exponent, global_shift=self._global_shift, dimension=self._dimension
751
741
  )
752
742
 
753
- def _trace_distance_bound_(self) -> Optional[float]:
743
+ def _trace_distance_bound_(self) -> float | None:
754
744
  if self._is_parameterized_() or self._dimension != 2:
755
745
  return None
756
746
  return abs(np.sin(self._exponent * 0.5 * np.pi))
@@ -766,14 +756,14 @@ class ZPowGate(eigen_gate.EigenGate):
766
756
  def _phase_by_(self, phase_turns: float, qubit_index: int):
767
757
  return self
768
758
 
769
- def _has_stabilizer_effect_(self) -> Optional[bool]:
759
+ def _has_stabilizer_effect_(self) -> bool | None:
770
760
  if self._is_parameterized_() or self._dimension != 2:
771
761
  return None
772
762
  return self.exponent % 0.5 == 0
773
763
 
774
764
  def _circuit_diagram_info_(
775
- self, args: 'cirq.CircuitDiagramInfoArgs'
776
- ) -> Union[str, 'protocols.CircuitDiagramInfo']:
765
+ self, args: cirq.CircuitDiagramInfoArgs
766
+ ) -> str | protocols.CircuitDiagramInfo:
777
767
  e = self._diagram_exponent(args)
778
768
  if e in [-0.25, 0.25]:
779
769
  return protocols.CircuitDiagramInfo(wire_symbols=('T',), exponent=cast(float, e) * 4)
@@ -783,7 +773,7 @@ class ZPowGate(eigen_gate.EigenGate):
783
773
 
784
774
  return protocols.CircuitDiagramInfo(wire_symbols=('Z',), exponent=e)
785
775
 
786
- def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
776
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
787
777
  args.validate_version('2.0', '3.0')
788
778
 
789
779
  if self.global_shift == 0:
@@ -838,8 +828,8 @@ class ZPowGate(eigen_gate.EigenGate):
838
828
  return f'cirq.ZPowGate({all_args})'
839
829
 
840
830
  def _commutes_on_qids_(
841
- self, qids: 'Sequence[cirq.Qid]', other: Any, *, atol: float = 1e-8
842
- ) -> Union[bool, NotImplementedType, None]:
831
+ self, qids: Sequence[cirq.Qid], other: Any, *, atol: float = 1e-8
832
+ ) -> bool | NotImplementedType | None:
843
833
  from cirq.ops.parity_gates import ZZPowGate
844
834
 
845
835
  if not isinstance(other, raw_types.Operation):
@@ -848,7 +838,7 @@ class ZPowGate(eigen_gate.EigenGate):
848
838
  return NotImplemented
849
839
  return True
850
840
 
851
- def _json_dict_(self) -> Dict[str, Any]:
841
+ def _json_dict_(self) -> dict[str, Any]:
852
842
  d = protocols.obj_to_dict_helper(self, ['exponent', 'global_shift'])
853
843
  if self.dimension != 2:
854
844
  d['dimension'] = self.dimension
@@ -879,12 +869,12 @@ class Rz(ZPowGate):
879
869
  self._rads = rads
880
870
  super().__init__(exponent=rads / _pi(rads), global_shift=-0.5)
881
871
 
882
- def _with_exponent(self, exponent: value.TParamVal) -> 'Rz':
872
+ def _with_exponent(self, exponent: value.TParamVal) -> Rz:
883
873
  return Rz(rads=exponent * _pi(exponent))
884
874
 
885
875
  def _circuit_diagram_info_(
886
- self, args: 'cirq.CircuitDiagramInfoArgs'
887
- ) -> Union[str, 'protocols.CircuitDiagramInfo']:
876
+ self, args: cirq.CircuitDiagramInfoArgs
877
+ ) -> str | protocols.CircuitDiagramInfo:
888
878
  angle_str = self._format_exponent_as_angle(args)
889
879
  return f'Rz({angle_str})'
890
880
 
@@ -896,15 +886,15 @@ class Rz(ZPowGate):
896
886
  def __repr__(self) -> str:
897
887
  return f'cirq.Rz(rads={proper_repr(self._rads)})'
898
888
 
899
- def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
889
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
900
890
  args.validate_version('2.0', '3.0')
901
891
  return args.format('rz({0:half_turns}) {1};\n', self._exponent, qubits[0])
902
892
 
903
- def _json_dict_(self) -> Dict[str, Any]:
893
+ def _json_dict_(self) -> dict[str, Any]:
904
894
  return {'rads': self._rads}
905
895
 
906
896
  @classmethod
907
- def _from_json_dict_(cls, rads, **kwargs) -> 'Rz':
897
+ def _from_json_dict_(cls, rads, **kwargs) -> Rz:
908
898
  return cls(rads=rads)
909
899
 
910
900
 
@@ -931,7 +921,7 @@ class HPowGate(eigen_gate.EigenGate):
931
921
  `cirq.H`, the Hadamard gate, is an instance of this gate at `exponent=1`.
932
922
  """
933
923
 
934
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
924
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
935
925
  s = np.sqrt(2)
936
926
 
937
927
  component0 = np.array([[3 + 2 * s, 1 + s], [1 + s, 1]]) / (4 + 2 * s)
@@ -943,7 +933,7 @@ class HPowGate(eigen_gate.EigenGate):
943
933
  def _num_qubits_(self) -> int:
944
934
  return 1
945
935
 
946
- def _trace_distance_bound_(self) -> Optional[float]:
936
+ def _trace_distance_bound_(self) -> float | None:
947
937
  if self._is_parameterized_():
948
938
  return None
949
939
  return abs(np.sin(self._exponent * 0.5 * np.pi))
@@ -970,7 +960,7 @@ class HPowGate(eigen_gate.EigenGate):
970
960
  return []
971
961
  return NotImplemented # pragma: no cover
972
962
 
973
- def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs') -> Optional[np.ndarray]:
963
+ def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray | None:
974
964
  if self._exponent != 1:
975
965
  return NotImplemented
976
966
 
@@ -995,14 +985,12 @@ class HPowGate(eigen_gate.EigenGate):
995
985
  yield XPowGate(exponent=self._exponent, global_shift=self.global_shift).on(q)
996
986
  yield YPowGate(exponent=-0.25).on(q)
997
987
 
998
- def _circuit_diagram_info_(
999
- self, args: 'cirq.CircuitDiagramInfoArgs'
1000
- ) -> 'cirq.CircuitDiagramInfo':
988
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
1001
989
  return protocols.CircuitDiagramInfo(
1002
990
  wire_symbols=('H',), exponent=self._diagram_exponent(args)
1003
991
  )
1004
992
 
1005
- def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
993
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
1006
994
  args.validate_version('2.0', '3.0')
1007
995
  if self._exponent == 0:
1008
996
  return args.format('id {0};\n', qubits[0])
@@ -1017,7 +1005,7 @@ class HPowGate(eigen_gate.EigenGate):
1017
1005
  qubits[0],
1018
1006
  )
1019
1007
 
1020
- def _has_stabilizer_effect_(self) -> Optional[bool]:
1008
+ def _has_stabilizer_effect_(self) -> bool | None:
1021
1009
  if self._is_parameterized_():
1022
1010
  return None
1023
1011
  return self.exponent % 1 == 0
@@ -1068,17 +1056,15 @@ class CZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
1068
1056
  return []
1069
1057
  return NotImplemented # pragma: no cover
1070
1058
 
1071
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
1059
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
1072
1060
  return [(0, np.diag([1, 1, 1, 0])), (1, np.diag([0, 0, 0, 1]))]
1073
1061
 
1074
- def _trace_distance_bound_(self) -> Optional[float]:
1062
+ def _trace_distance_bound_(self) -> float | None:
1075
1063
  if self._is_parameterized_():
1076
1064
  return None
1077
1065
  return abs(np.sin(self._exponent * 0.5 * np.pi))
1078
1066
 
1079
- def _apply_unitary_(
1080
- self, args: 'protocols.ApplyUnitaryArgs'
1081
- ) -> Union[np.ndarray, NotImplementedType]:
1067
+ def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray | NotImplementedType:
1082
1068
  if protocols.is_parameterized(self):
1083
1069
  return NotImplemented
1084
1070
 
@@ -1110,11 +1096,9 @@ class CZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
1110
1096
 
1111
1097
  def controlled(
1112
1098
  self,
1113
- num_controls: Optional[int] = None,
1114
- control_values: Optional[
1115
- Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
1116
- ] = None,
1117
- control_qid_shape: Optional[Tuple[int, ...]] = None,
1099
+ num_controls: int | None = None,
1100
+ control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
1101
+ control_qid_shape: tuple[int, ...] | None = None,
1118
1102
  ) -> raw_types.Gate:
1119
1103
  """Returns a controlled `CZPowGate`, using a `CCZPowGate` where possible.
1120
1104
 
@@ -1160,41 +1144,32 @@ class CZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
1160
1144
  A `cirq.ControlledGate` (or `cirq.CCZPowGate` if possible) representing
1161
1145
  `self` controlled by the given control values and qubits.
1162
1146
  """
1163
- if control_values and not isinstance(control_values, cv.AbstractControlValues):
1164
- control_values = cv.ProductOfSums(
1165
- tuple(
1166
- (val,) if isinstance(val, int) else tuple(sorted(val)) for val in control_values
1167
- )
1168
- )
1169
1147
  result = super().controlled(num_controls, control_values, control_qid_shape)
1170
- if (
1171
- self._global_shift == 0
1172
- and isinstance(result, controlled_gate.ControlledGate)
1173
- and isinstance(result.control_values, cv.ProductOfSums)
1174
- and result.control_values[-1] == (1,)
1175
- and result.control_qid_shape[-1] == 2
1176
- ):
1177
- return cirq.CCZPowGate(
1178
- exponent=self._exponent, global_shift=self._global_shift
1179
- ).controlled(
1180
- result.num_controls() - 1, result.control_values[:-1], result.control_qid_shape[:-1]
1181
- )
1182
- return result
1148
+ if self._global_shift != 0 or not isinstance(result, controlled_gate.ControlledGate):
1149
+ return result
1150
+ return ZPowGate(exponent=self.exponent).controlled(
1151
+ num_controls=result.num_controls() + 1,
1152
+ control_values=result.control_values & cv.ProductOfSums([1]),
1153
+ control_qid_shape=result.control_qid_shape + (2,),
1154
+ )
1183
1155
 
1184
- def _circuit_diagram_info_(
1185
- self, args: 'cirq.CircuitDiagramInfoArgs'
1186
- ) -> 'cirq.CircuitDiagramInfo':
1156
+ def _decompose_with_context_(
1157
+ self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext
1158
+ ) -> list[cirq.Operation] | NotImplementedType:
1159
+ return _extract_phase(self, CZPowGate, qubits, context)
1160
+
1161
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
1187
1162
  return protocols.CircuitDiagramInfo(
1188
1163
  wire_symbols=('@', '@'), exponent=self._diagram_exponent(args)
1189
1164
  )
1190
1165
 
1191
- def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
1166
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
1192
1167
  if self._exponent != 1:
1193
1168
  return None # Don't have an equivalent gate in QASM
1194
1169
  args.validate_version('2.0', '3.0')
1195
1170
  return args.format('cz {0},{1};\n', qubits[0], qubits[1])
1196
1171
 
1197
- def _has_stabilizer_effect_(self) -> Optional[bool]:
1172
+ def _has_stabilizer_effect_(self) -> bool | None:
1198
1173
  if self._is_parameterized_():
1199
1174
  return None
1200
1175
  return self.exponent % 1 == 0
@@ -1269,25 +1244,23 @@ class CXPowGate(eigen_gate.EigenGate):
1269
1244
  yield cirq.CZPowGate(exponent=self._exponent, global_shift=self.global_shift).on(c, t)
1270
1245
  yield YPowGate(exponent=0.5).on(t)
1271
1246
 
1272
- def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
1247
+ def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
1273
1248
  return [
1274
1249
  (0, np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0.5, 0.5], [0, 0, 0.5, 0.5]])),
1275
1250
  (1, np.array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0.5, -0.5], [0, 0, -0.5, 0.5]])),
1276
1251
  ]
1277
1252
 
1278
- def _trace_distance_bound_(self) -> Optional[float]:
1253
+ def _trace_distance_bound_(self) -> float | None:
1279
1254
  if self._is_parameterized_():
1280
1255
  return None
1281
1256
  return abs(np.sin(self._exponent * 0.5 * np.pi))
1282
1257
 
1283
- def _circuit_diagram_info_(
1284
- self, args: 'cirq.CircuitDiagramInfoArgs'
1285
- ) -> 'cirq.CircuitDiagramInfo':
1258
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
1286
1259
  return protocols.CircuitDiagramInfo(
1287
1260
  wire_symbols=('@', 'X'), exponent=self._diagram_exponent(args), exponent_qubit_index=1
1288
1261
  )
1289
1262
 
1290
- def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs') -> Optional[np.ndarray]:
1263
+ def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray | None:
1291
1264
  if self._exponent != 1:
1292
1265
  return NotImplemented
1293
1266
 
@@ -1318,11 +1291,9 @@ class CXPowGate(eigen_gate.EigenGate):
1318
1291
 
1319
1292
  def controlled(
1320
1293
  self,
1321
- num_controls: Optional[int] = None,
1322
- control_values: Optional[
1323
- Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
1324
- ] = None,
1325
- control_qid_shape: Optional[Tuple[int, ...]] = None,
1294
+ num_controls: int | None = None,
1295
+ control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
1296
+ control_qid_shape: tuple[int, ...] | None = None,
1326
1297
  ) -> raw_types.Gate:
1327
1298
  """Returns a controlled `CXPowGate`, using a `CCXPowGate` where possible.
1328
1299
 
@@ -1368,34 +1339,22 @@ class CXPowGate(eigen_gate.EigenGate):
1368
1339
  A `cirq.ControlledGate` (or `cirq.CCXPowGate` if possible) representing
1369
1340
  `self` controlled by the given control values and qubits.
1370
1341
  """
1371
- if control_values and not isinstance(control_values, cv.AbstractControlValues):
1372
- control_values = cv.ProductOfSums(
1373
- tuple(
1374
- (val,) if isinstance(val, int) else tuple(sorted(val)) for val in control_values
1375
- )
1376
- )
1377
1342
  result = super().controlled(num_controls, control_values, control_qid_shape)
1378
- if (
1379
- self._global_shift == 0
1380
- and isinstance(result, controlled_gate.ControlledGate)
1381
- and isinstance(result.control_values, cv.ProductOfSums)
1382
- and result.control_values[-1] == (1,)
1383
- and result.control_qid_shape[-1] == 2
1384
- ):
1385
- return cirq.CCXPowGate(
1386
- exponent=self._exponent, global_shift=self._global_shift
1387
- ).controlled(
1388
- result.num_controls() - 1, result.control_values[:-1], result.control_qid_shape[:-1]
1389
- )
1390
- return result
1343
+ if self._global_shift != 0 or not isinstance(result, controlled_gate.ControlledGate):
1344
+ return result
1345
+ return XPowGate(exponent=self.exponent).controlled(
1346
+ num_controls=result.num_controls() + 1,
1347
+ control_values=result.control_values & cv.ProductOfSums([1]),
1348
+ control_qid_shape=result.control_qid_shape + (2,),
1349
+ )
1391
1350
 
1392
- def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
1351
+ def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
1393
1352
  if self._exponent != 1:
1394
1353
  return None # Don't have an equivalent gate in QASM
1395
1354
  args.validate_version('2.0', '3.0')
1396
1355
  return args.format('cx {0},{1};\n', qubits[0], qubits[1])
1397
1356
 
1398
- def _has_stabilizer_effect_(self) -> Optional[bool]:
1357
+ def _has_stabilizer_effect_(self) -> bool | None:
1399
1358
  if self._is_parameterized_():
1400
1359
  return None
1401
1360
  return self.exponent % 1 == 0
@@ -1543,8 +1502,8 @@ document(
1543
1502
 
1544
1503
 
1545
1504
  def _phased_x_or_pauli_gate(
1546
- exponent: Union[float, sympy.Expr], phase_exponent: Union[float, sympy.Expr]
1547
- ) -> Union['cirq.PhasedXPowGate', 'cirq.XPowGate', 'cirq.YPowGate']:
1505
+ exponent: float | sympy.Expr, phase_exponent: float | sympy.Expr
1506
+ ) -> cirq.PhasedXPowGate | cirq.XPowGate | cirq.YPowGate:
1548
1507
  """Return PhasedXPowGate or X or Y gate if equivalent at the given phase_exponent."""
1549
1508
  if not isinstance(phase_exponent, sympy.Expr) or phase_exponent.is_constant():
1550
1509
  half_turns = value.canonicalize_half_turns(float(phase_exponent))
@@ -1554,3 +1513,25 @@ def _phased_x_or_pauli_gate(
1554
1513
  case 0.5:
1555
1514
  return YPowGate(exponent=exponent)
1556
1515
  return cirq.ops.PhasedXPowGate(exponent=exponent, phase_exponent=phase_exponent)
1516
+
1517
+
1518
+ def _extract_phase(
1519
+ gate: cirq.EigenGate,
1520
+ gate_class: type,
1521
+ qubits: tuple[cirq.Qid, ...],
1522
+ context: cirq.DecompositionContext,
1523
+ ) -> list[cirq.Operation] | NotImplementedType:
1524
+ """Extracts the global phase field to its own gate, or absorbs it if it has no effect.
1525
+
1526
+ This is for use within the decompose handlers, and will return `NotImplemented` if there is no
1527
+ global phase, implying it is already in its simplest form. It will return a list, with the
1528
+ original op minus any global phase first, and the global phase op second. If the resulting
1529
+ global phase is empty (can happen for example in `XPowGate(global_phase=2/3)**3`), then it is
1530
+ excluded from the return value."""
1531
+ if not context.extract_global_phases or gate.global_shift == 0:
1532
+ return NotImplemented
1533
+ result = [gate_class(exponent=gate.exponent).on(*qubits)]
1534
+ phase_gate = global_phase_op.from_phase_and_exponent(gate.global_shift, gate.exponent)
1535
+ if not phase_gate.is_identity():
1536
+ result.append(phase_gate())
1537
+ return result