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
@@ -14,8 +14,10 @@
14
14
 
15
15
  """Transformer pass to repack circuits avoiding simultaneous operations with different classes."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import itertools
18
- from typing import Callable, Dict, Iterable, List, Optional, Sequence, Type, TYPE_CHECKING, Union
20
+ from typing import Callable, Iterable, Sequence, TYPE_CHECKING, Union
19
21
 
20
22
  from cirq import _import, circuits, ops, protocols
21
23
  from cirq.transformers import transformer_api
@@ -31,17 +33,17 @@ Classifier = Callable[['cirq.Operation'], bool]
31
33
 
32
34
  # Any of the possible operation categories that we can stratify on.
33
35
  Category = Union[
34
- 'cirq.Gate', 'cirq.Operation', Type['cirq.Gate'], Type['cirq.Operation'], Classifier
36
+ 'cirq.Gate', 'cirq.Operation', type['cirq.Gate'], type['cirq.Operation'], Classifier
35
37
  ]
36
38
 
37
39
 
38
40
  @transformer_api.transformer(add_deep_support=True)
39
41
  def stratified_circuit(
40
- circuit: 'cirq.AbstractCircuit',
42
+ circuit: cirq.AbstractCircuit,
41
43
  *,
42
- context: Optional['cirq.TransformerContext'] = None,
44
+ context: cirq.TransformerContext | None = None,
43
45
  categories: Iterable[Category] = (),
44
- ) -> 'cirq.Circuit':
46
+ ) -> cirq.Circuit:
45
47
  """Repacks avoiding simultaneous operations with different classes.
46
48
 
47
49
  This transforms the given circuit to ensure that no operations of different categories are
@@ -96,9 +98,9 @@ def stratified_circuit(
96
98
  def _stratify_circuit(
97
99
  circuit: circuits.AbstractCircuit,
98
100
  *,
99
- context: 'cirq.TransformerContext',
101
+ context: cirq.TransformerContext,
100
102
  classifiers: Sequence[Classifier],
101
- ) -> 'cirq.Circuit':
103
+ ) -> cirq.Circuit:
102
104
  """Performs the stratification by iterating through the operations in the
103
105
  circuit and using the given classifiers to align them.
104
106
 
@@ -115,12 +117,12 @@ def _stratify_circuit(
115
117
  The stratified circuit.
116
118
  """
117
119
  num_classes = len(classifiers) + 1 # include one "extra" category for ignored operations
118
- new_moments: List[List['cirq.Operation']] = []
120
+ new_moments: list[list[cirq.Operation]] = []
119
121
 
120
122
  # Keep track of the latest time index for each qubit, measurement key, and control key.
121
- qubit_time_index: Dict['cirq.Qid', int] = {}
122
- measurement_time_index: Dict['cirq.MeasurementKey', int] = {}
123
- control_time_index: Dict['cirq.MeasurementKey', int] = {}
123
+ qubit_time_index: dict[cirq.Qid, int] = {}
124
+ measurement_time_index: dict[cirq.MeasurementKey, int] = {}
125
+ control_time_index: dict[cirq.MeasurementKey, int] = {}
124
126
 
125
127
  # The minimum time index for operations with a tag in context.tags_to_ignore.
126
128
  last_ignored_ops_time_index = 0
@@ -162,7 +164,7 @@ def _stratify_circuit(
162
164
  new_moments += [[] for _ in range(num_classes)]
163
165
  new_moments[time_index].append(op)
164
166
 
165
- # Update qubit, measurment key, and control key moments.
167
+ # Update qubit, measurement key, and control key moments.
166
168
  for qubit in op.qubits:
167
169
  qubit_time_index[qubit] = time_index
168
170
  for key in protocols.measurement_key_objs(op):
@@ -175,7 +177,7 @@ def _stratify_circuit(
175
177
 
176
178
  def _get_classifiers(
177
179
  circuit: circuits.AbstractCircuit, categories: Iterable[Category]
178
- ) -> List[Classifier]:
180
+ ) -> list[Classifier]:
179
181
  """Convert a collection of categories into a list of classifiers.
180
182
 
181
183
  The returned list of classifiers is:
@@ -221,12 +223,12 @@ def _category_to_classifier(category) -> Classifier:
221
223
  )
222
224
 
223
225
 
224
- def _mock_classifier(op: 'cirq.Operation') -> bool:
226
+ def _mock_classifier(op: cirq.Operation) -> bool:
225
227
  """Mock classifier, used to "complete" a collection of classifiers and make it exhaustive."""
226
228
  return False # pragma: no cover
227
229
 
228
230
 
229
- def _get_op_class(op: 'cirq.Operation', classifiers: Sequence[Classifier]) -> int:
231
+ def _get_op_class(op: cirq.Operation, classifiers: Sequence[Classifier]) -> int:
230
232
  """Get the "class" of an operator, by index."""
231
233
  for class_index, classifier in enumerate(classifiers):
232
234
  if classifier is _mock_classifier:
@@ -11,6 +11,9 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
14
17
  import pytest
15
18
 
16
19
  import cirq
@@ -0,0 +1,103 @@
1
+ # Copyright 2025 The Cirq Developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Transformers that symbolize operations."""
16
+
17
+ from __future__ import annotations
18
+
19
+ import re
20
+ from typing import Hashable, TYPE_CHECKING
21
+
22
+ import attrs
23
+ import sympy
24
+ from attrs import validators
25
+
26
+ from cirq import ops
27
+ from cirq.transformers import transformer_api, transformer_primitives
28
+
29
+ if TYPE_CHECKING:
30
+ import cirq
31
+
32
+
33
+ @attrs.frozen
34
+ class SymbolizeTag:
35
+ prefix: str = attrs.field(
36
+ validator=validators.and_(validators.instance_of(str), validators.min_len(1))
37
+ )
38
+
39
+
40
+ @transformer_api.transformer
41
+ def symbolize_single_qubit_gates_by_indexed_tags(
42
+ circuit: cirq.AbstractCircuit,
43
+ *,
44
+ context: cirq.TransformerContext | None = None,
45
+ symbolize_tag: SymbolizeTag = SymbolizeTag(prefix="TO-PHXZ"),
46
+ ) -> cirq.Circuit:
47
+ """Symbolizes single qubit operations by indexed tags prefixed by symbolize_tag.prefix.
48
+
49
+ Example:
50
+ >>> from cirq import transformers
51
+ >>> q0, q1 = cirq.LineQubit.range(2)
52
+ >>> c = cirq.Circuit(
53
+ ... cirq.X(q0).with_tags("phxz_0"),
54
+ ... cirq.CZ(q0,q1),
55
+ ... cirq.Y(q0).with_tags("phxz_1"),
56
+ ... cirq.X(q0))
57
+ >>> print(c)
58
+ 0: ───X[phxz_0]───@───Y[phxz_1]───X───
59
+
60
+ 1: ───────────────@───────────────────
61
+ >>> new_circuit = cirq.symbolize_single_qubit_gates_by_indexed_tags(
62
+ ... c, symbolize_tag=transformers.SymbolizeTag(prefix="phxz"))
63
+ >>> print(new_circuit)
64
+ 0: ───PhXZ(a=a0,x=x0,z=z0)───@───PhXZ(a=a1,x=x1,z=z1)───X───
65
+
66
+ 1: ──────────────────────────@──────────────────────────────
67
+
68
+ Args:
69
+ circuit: Input circuit to apply the transformations on. The input circuit is not mutated.
70
+ context: `cirq.TransformerContext` storing common configurable options for transformers.
71
+ symbolize_tag: The tag info used to symbolize the phxz gate. Prefix is required.
72
+
73
+ Returns:
74
+ Copy of the transformed input circuit.
75
+ """
76
+
77
+ def _map_func(op: cirq.Operation, _):
78
+ """Maps an op with tag `{tag_prefix}_i` to a symbolized `PhasedXZGate(xi,zi,ai)`."""
79
+ tags: set[Hashable] = set(op.tags)
80
+ tag_id: None | int = None
81
+ for tag in tags:
82
+ if re.fullmatch(f"{symbolize_tag.prefix}_\\d+", str(tag)):
83
+ if tag_id is None:
84
+ tag_id = int(str(tag).rsplit("_", maxsplit=-1)[-1])
85
+ else:
86
+ raise ValueError(f"Multiple tags are prefixed with {symbolize_tag.prefix}.")
87
+ if tag_id is None:
88
+ return op
89
+ tags.remove(f"{symbolize_tag.prefix}_{tag_id}")
90
+ phxz_params = {
91
+ "x_exponent": sympy.Symbol(f"x{tag_id}"),
92
+ "z_exponent": sympy.Symbol(f"z{tag_id}"),
93
+ "axis_phase_exponent": sympy.Symbol(f"a{tag_id}"),
94
+ }
95
+
96
+ return ops.PhasedXZGate(**phxz_params).on(*op.qubits).with_tags(*tags)
97
+
98
+ return transformer_primitives.map_operations(
99
+ circuit.freeze(),
100
+ _map_func,
101
+ deep=context.deep if context else False,
102
+ tags_to_ignore=context.tags_to_ignore if context else [],
103
+ ).unfreeze(copy=False)
@@ -0,0 +1,62 @@
1
+ # Copyright 2025 The Cirq Developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ import pytest
18
+ import sympy
19
+
20
+ import cirq
21
+ from cirq.transformers.symbolize import SymbolizeTag
22
+
23
+
24
+ def test_symbolize_single_qubit_gates_by_indexed_tags_success():
25
+ q = cirq.NamedQubit("a")
26
+ input_circuit = cirq.Circuit(
27
+ cirq.X(q).with_tags("phxz_1"), cirq.Y(q).with_tags("tag1"), cirq.Z(q).with_tags("phxz_0")
28
+ )
29
+ output_circuit = cirq.symbolize_single_qubit_gates_by_indexed_tags(
30
+ input_circuit, symbolize_tag=SymbolizeTag(prefix="phxz")
31
+ )
32
+ cirq.testing.assert_same_circuits(
33
+ output_circuit,
34
+ cirq.Circuit(
35
+ cirq.PhasedXZGate(
36
+ x_exponent=sympy.Symbol("x1"),
37
+ z_exponent=sympy.Symbol("z1"),
38
+ axis_phase_exponent=sympy.Symbol("a1"),
39
+ ).on(q),
40
+ cirq.Y(q).with_tags("tag1"),
41
+ cirq.PhasedXZGate(
42
+ x_exponent=sympy.Symbol("x0"),
43
+ z_exponent=sympy.Symbol("z0"),
44
+ axis_phase_exponent=sympy.Symbol("a0"),
45
+ ).on(q),
46
+ ),
47
+ )
48
+
49
+
50
+ def test_symbolize_single_qubit_gates_by_indexed_tags_multiple_tags():
51
+ q = cirq.NamedQubit("a")
52
+ input_circuit = cirq.Circuit(cirq.X(q).with_tags("TO-PHXZ_0", "TO-PHXZ_2"))
53
+
54
+ with pytest.raises(ValueError, match="Multiple tags are prefixed with TO-PHXZ."):
55
+ cirq.symbolize_single_qubit_gates_by_indexed_tags(input_circuit)
56
+
57
+
58
+ def test_symbolize_tag_invalid_prefix():
59
+ with pytest.raises(ValueError, match="Length of 'prefix' must be >= 1: 0"):
60
+ SymbolizeTag(prefix="")
61
+ with pytest.raises(TypeError, match="'prefix' must be <class 'str'>"):
62
+ SymbolizeTag(prefix=[1])
@@ -14,7 +14,9 @@
14
14
 
15
15
  """Transformer pass to move terminal measurements to the end of circuit."""
16
16
 
17
- from typing import List, Optional, Set, Tuple, TYPE_CHECKING
17
+ from __future__ import annotations
18
+
19
+ from typing import TYPE_CHECKING
18
20
 
19
21
  from cirq import circuits, protocols
20
22
  from cirq.transformers import transformer_api
@@ -23,9 +25,7 @@ if TYPE_CHECKING:
23
25
  import cirq
24
26
 
25
27
 
26
- def find_terminal_measurements(
27
- circuit: 'cirq.AbstractCircuit',
28
- ) -> List[Tuple[int, 'cirq.Operation']]:
28
+ def find_terminal_measurements(circuit: cirq.AbstractCircuit) -> list[tuple[int, cirq.Operation]]:
29
29
  """Finds all terminal measurements in the given circuit.
30
30
 
31
31
  A measurement is terminal if there are no other operations acting on the measured qubits
@@ -39,9 +39,9 @@ def find_terminal_measurements(
39
39
  (moment_index, measurement_operation).
40
40
  """
41
41
 
42
- open_qubits: Set['cirq.Qid'] = set(circuit.all_qubits())
43
- seen_control_keys: Set['cirq.MeasurementKey'] = set()
44
- terminal_measurements: Set[Tuple[int, 'cirq.Operation']] = set()
42
+ open_qubits: set[cirq.Qid] = set(circuit.all_qubits())
43
+ seen_control_keys: set[cirq.MeasurementKey] = set()
44
+ terminal_measurements: set[tuple[int, cirq.Operation]] = set()
45
45
  for i in range(len(circuit) - 1, -1, -1):
46
46
  moment = circuit[i]
47
47
  for q in open_qubits:
@@ -62,11 +62,11 @@ def find_terminal_measurements(
62
62
 
63
63
  @transformer_api.transformer(add_deep_support=True)
64
64
  def synchronize_terminal_measurements(
65
- circuit: 'cirq.AbstractCircuit',
65
+ circuit: cirq.AbstractCircuit,
66
66
  *,
67
- context: Optional['cirq.TransformerContext'] = None,
67
+ context: cirq.TransformerContext | None = None,
68
68
  after_other_operations: bool = True,
69
- ) -> 'cirq.Circuit':
69
+ ) -> cirq.Circuit:
70
70
  """Move measurements to the end of the circuit.
71
71
 
72
72
  Move all measurements in a circuit to the final moment, if it can accommodate them (without
@@ -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 cirq
16
18
 
17
19
  NO_COMPILE_TAG = "no_compile_tag"
@@ -48,14 +50,14 @@ def assert_optimizes(before, after, measure_only_moment=True, with_context=False
48
50
  cirq.testing.assert_same_circuits(transformed_circuit, c_expected)
49
51
 
50
52
 
51
- def test_no_move():
53
+ def test_no_move() -> None:
52
54
  q1 = cirq.NamedQubit('q1')
53
55
  before = cirq.Circuit([cirq.Moment([cirq.H(q1)])])
54
56
  after = before
55
57
  assert_optimizes(before=before, after=after)
56
58
 
57
59
 
58
- def test_simple_align():
60
+ def test_simple_align() -> None:
59
61
  q1 = cirq.NamedQubit('q1')
60
62
  q2 = cirq.NamedQubit('q2')
61
63
  before = cirq.Circuit(
@@ -76,7 +78,7 @@ def test_simple_align():
76
78
  assert_optimizes(before=before, after=before, with_context=True)
77
79
 
78
80
 
79
- def test_simple_partial_align():
81
+ def test_simple_partial_align() -> None:
80
82
  q1 = cirq.NamedQubit('q1')
81
83
  q2 = cirq.NamedQubit('q2')
82
84
  before = cirq.Circuit(
@@ -96,7 +98,7 @@ def test_simple_partial_align():
96
98
  assert_optimizes(before=before, after=before, with_context=True)
97
99
 
98
100
 
99
- def test_slide_forward_one():
101
+ def test_slide_forward_one() -> None:
100
102
  q1 = cirq.NamedQubit('q1')
101
103
  q2 = cirq.NamedQubit('q2')
102
104
  q3 = cirq.NamedQubit('q3')
@@ -119,7 +121,7 @@ def test_slide_forward_one():
119
121
  assert_optimizes(before=before, after=after_no_compile, with_context=True)
120
122
 
121
123
 
122
- def test_no_slide_forward_one():
124
+ def test_no_slide_forward_one() -> None:
123
125
  q1 = cirq.NamedQubit('q1')
124
126
  q2 = cirq.NamedQubit('q2')
125
127
  q3 = cirq.NamedQubit('q3')
@@ -128,7 +130,7 @@ def test_no_slide_forward_one():
128
130
  assert_optimizes(before=before, after=after, measure_only_moment=False)
129
131
 
130
132
 
131
- def test_blocked_shift_one():
133
+ def test_blocked_shift_one() -> None:
132
134
  q1 = cirq.NamedQubit('q1')
133
135
  q2 = cirq.NamedQubit('q2')
134
136
  before = cirq.Circuit(
@@ -150,7 +152,7 @@ def test_blocked_shift_one():
150
152
  assert_optimizes(before=before, after=before, with_context=True)
151
153
 
152
154
 
153
- def test_complex_move():
155
+ def test_complex_move() -> None:
154
156
  q1 = cirq.NamedQubit('q1')
155
157
  q2 = cirq.NamedQubit('q2')
156
158
  q3 = cirq.NamedQubit('q3')
@@ -182,7 +184,7 @@ def test_complex_move():
182
184
  assert_optimizes(before=before, after=before, with_context=True)
183
185
 
184
186
 
185
- def test_complex_move_no_slide():
187
+ def test_complex_move_no_slide() -> None:
186
188
  q1 = cirq.NamedQubit('q1')
187
189
  q2 = cirq.NamedQubit('q2')
188
190
  q3 = cirq.NamedQubit('q3')
@@ -208,13 +210,13 @@ def test_complex_move_no_slide():
208
210
  assert_optimizes(before=before, after=before, measure_only_moment=False, with_context=True)
209
211
 
210
212
 
211
- def test_multi_qubit():
213
+ def test_multi_qubit() -> None:
212
214
  q0, q1 = cirq.LineQubit.range(2)
213
215
  circuit = cirq.Circuit(cirq.H(q1), cirq.measure(q0, q1, key='m'))
214
216
  assert_optimizes(before=circuit, after=circuit)
215
217
 
216
218
 
217
- def test_classically_controlled_op():
219
+ def test_classically_controlled_op() -> None:
218
220
  q0, q1 = cirq.LineQubit.range(2)
219
221
  circuit = cirq.Circuit(
220
222
  cirq.H(q0), cirq.measure(q0, key='m'), cirq.X(q1).with_classical_controls('m')
@@ -0,0 +1,97 @@
1
+ # Copyright 2025 The Cirq Developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ import itertools
18
+ from typing import Callable, Hashable, TYPE_CHECKING
19
+
20
+ from cirq.transformers import transformer_api, transformer_primitives
21
+
22
+ if TYPE_CHECKING:
23
+ import cirq
24
+
25
+
26
+ @transformer_api.transformer
27
+ def index_tags(
28
+ circuit: cirq.AbstractCircuit,
29
+ *,
30
+ context: cirq.TransformerContext | None = None,
31
+ target_tags: set[Hashable] | None = None,
32
+ ) -> cirq.Circuit:
33
+ """Indexes tags in target_tags as tag_0, tag_1, ... per tag.
34
+
35
+ Args:
36
+ circuit: Input circuit to apply the transformations on. The input circuit is not mutated.
37
+ context: `cirq.TransformerContext` storing common configurable options for transformers.
38
+ target_tags: Tags to be indexed.
39
+
40
+ Returns:
41
+ Copy of the transformed input circuit.
42
+ """
43
+ if context and context.tags_to_ignore:
44
+ raise ValueError("index_tags doesn't support tags_to_ignore, use function args instead.")
45
+ if not target_tags:
46
+ return circuit.unfreeze(copy=False)
47
+ tag_iter_by_tags = {tag: itertools.count(start=0, step=1) for tag in target_tags}
48
+
49
+ def _map_func(op: cirq.Operation, _) -> cirq.OP_TREE:
50
+ tag_set = set(op.tags)
51
+ nonlocal tag_iter_by_tags
52
+ for tag in target_tags.intersection(op.tags):
53
+ tag_set.remove(tag)
54
+ tag_set.add(f"{tag}_{next(tag_iter_by_tags[tag])}")
55
+
56
+ return op.untagged.with_tags(*tag_set)
57
+
58
+ return transformer_primitives.map_operations(
59
+ circuit, _map_func, deep=context.deep if context else False
60
+ ).unfreeze(copy=False)
61
+
62
+
63
+ @transformer_api.transformer
64
+ def remove_tags(
65
+ circuit: cirq.AbstractCircuit,
66
+ *,
67
+ context: cirq.TransformerContext | None = None,
68
+ target_tags: set[Hashable] | None = None,
69
+ remove_if: Callable[[Hashable], bool] = lambda _: False,
70
+ ) -> cirq.Circuit:
71
+ """Removes tags from the operations based on the input args.
72
+
73
+ Args:
74
+ circuit: Input circuit to apply the transformations on. The input circuit is not mutated.
75
+ context: `cirq.TransformerContext` storing common configurable options for transformers.
76
+ target_tags: Tags to be removed.
77
+ remove_if: A callable(tag) that returns True if the tag should be removed.
78
+ Defaults to False.
79
+
80
+ Returns:
81
+ Copy of the transformed input circuit.
82
+ """
83
+ if context and context.tags_to_ignore:
84
+ raise ValueError("remove_tags doesn't support tags_to_ignore, use function args instead.")
85
+ target_tags = target_tags or set()
86
+
87
+ def _map_func(op: cirq.Operation, _) -> cirq.OP_TREE:
88
+ remaining_tags = set()
89
+ for tag in op.tags:
90
+ if not remove_if(tag) and tag not in target_tags:
91
+ remaining_tags.add(tag)
92
+
93
+ return op.untagged.with_tags(*remaining_tags)
94
+
95
+ return transformer_primitives.map_operations(
96
+ circuit, _map_func, deep=context.deep if context else False
97
+ ).unfreeze(copy=False)
@@ -0,0 +1,103 @@
1
+ # Copyright 2025 The Cirq Developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ import pytest
18
+
19
+ import cirq
20
+
21
+
22
+ def check_same_circuit_with_same_tag_sets(circuit1, circuit2):
23
+ for op1, op2 in zip(circuit1.all_operations(), circuit2.all_operations()):
24
+ assert set(op1.tags) == set(op2.tags)
25
+ assert op1.untagged == op2.untagged
26
+
27
+
28
+ def test_index_tags():
29
+ q0, q1 = cirq.LineQubit.range(2)
30
+ input_circuit = cirq.Circuit(
31
+ cirq.X(q0).with_tags("tag1", "tag2"),
32
+ cirq.Y(q1).with_tags("tag1"),
33
+ cirq.CZ(q0, q1).with_tags("tag2"),
34
+ )
35
+ expected_circuit = cirq.Circuit(
36
+ cirq.X(q0).with_tags("tag1_0", "tag2_0"),
37
+ cirq.Y(q1).with_tags("tag1_1"),
38
+ cirq.CZ(q0, q1).with_tags("tag2_1"),
39
+ )
40
+ check_same_circuit_with_same_tag_sets(
41
+ cirq.index_tags(input_circuit, target_tags={"tag1", "tag2"}), expected_circuit
42
+ )
43
+
44
+
45
+ def test_index_tags_empty_target_tags():
46
+ q0, q1 = cirq.LineQubit.range(2)
47
+ input_circuit = cirq.Circuit(
48
+ cirq.X(q0).with_tags("tag1", "tag2"),
49
+ cirq.Y(q1).with_tags("tag1"),
50
+ cirq.CZ(q0, q1).with_tags("tag2"),
51
+ )
52
+ check_same_circuit_with_same_tag_sets(
53
+ cirq.index_tags(input_circuit, target_tags={}), input_circuit
54
+ )
55
+
56
+
57
+ def test_remove_tags():
58
+ q0, q1 = cirq.LineQubit.range(2)
59
+ input_circuit = cirq.Circuit(
60
+ cirq.X(q0).with_tags("tag1", "tag2"),
61
+ cirq.Y(q1).with_tags("tag1"),
62
+ cirq.CZ(q0, q1).with_tags("tag2"),
63
+ )
64
+ expected_circuit = cirq.Circuit(
65
+ cirq.X(q0).with_tags("tag2"), cirq.Y(q1), cirq.CZ(q0, q1).with_tags("tag2")
66
+ )
67
+ check_same_circuit_with_same_tag_sets(
68
+ cirq.remove_tags(input_circuit, target_tags={"tag1"}), expected_circuit
69
+ )
70
+
71
+
72
+ def test_remove_tags_via_remove_if():
73
+ q0, q1 = cirq.LineQubit.range(2)
74
+ input_circuit = cirq.Circuit(
75
+ cirq.X(q0).with_tags("tag1", "tag2"),
76
+ cirq.Y(q1).with_tags("not_tag1"),
77
+ cirq.CZ(q0, q1).with_tags("tag2"),
78
+ )
79
+ expected_circuit = cirq.Circuit(cirq.X(q0), cirq.Y(q1).with_tags("not_tag1"), cirq.CZ(q0, q1))
80
+ check_same_circuit_with_same_tag_sets(
81
+ cirq.remove_tags(input_circuit, remove_if=lambda tag: tag.startswith("tag")),
82
+ expected_circuit,
83
+ )
84
+
85
+
86
+ def test_index_tags_with_tags_to_ignore():
87
+ with pytest.raises(
88
+ ValueError, match="index_tags doesn't support tags_to_ignore, use function args instead."
89
+ ):
90
+ cirq.index_tags(
91
+ circuit=cirq.Circuit(),
92
+ target_tags={"tag0"},
93
+ context=cirq.TransformerContext(tags_to_ignore=["tag0"]),
94
+ )
95
+
96
+
97
+ def test_remove_tags_with_tags_to_ignore():
98
+ with pytest.raises(
99
+ ValueError, match="remove_tags doesn't support tags_to_ignore, use function args instead."
100
+ ):
101
+ cirq.remove_tags(
102
+ circuit=cirq.Circuit(), context=cirq.TransformerContext(tags_to_ignore=["tag0"])
103
+ )