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
@@ -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 re
16
18
  import textwrap
17
19
  from typing import Callable
@@ -29,7 +31,7 @@ from cirq.contrib.qasm_import._parser import QasmParser
29
31
  from cirq.testing import consistent_qasm as cq
30
32
 
31
33
 
32
- def test_format_header_circuit():
34
+ def test_format_header_circuit() -> None:
33
35
  parser = QasmParser()
34
36
 
35
37
  parsed_qasm = parser.parse("OPENQASM 2.0;")
@@ -39,7 +41,7 @@ def test_format_header_circuit():
39
41
  ct.assert_same_circuits(parsed_qasm.circuit, Circuit())
40
42
 
41
43
 
42
- def test_unsupported_format():
44
+ def test_unsupported_format() -> None:
43
45
  qasm = "OPENQASM 2.1;"
44
46
  parser = QasmParser()
45
47
 
@@ -47,7 +49,7 @@ def test_unsupported_format():
47
49
  parser.parse(qasm)
48
50
 
49
51
 
50
- def test_format_header_with_quelibinc_circuit():
52
+ def test_format_header_with_quelibinc_circuit() -> None:
51
53
  qasm = """OPENQASM 2.0;
52
54
  include "qelib1.inc";
53
55
  """
@@ -61,14 +63,14 @@ include "qelib1.inc";
61
63
 
62
64
 
63
65
  @pytest.mark.parametrize('qasm', ["include \"qelib1.inc\";", "", "qreg q[3];"])
64
- def test_error_not_starting_with_format(qasm: str):
66
+ def test_error_not_starting_with_format(qasm: str) -> None:
65
67
  parser = QasmParser()
66
68
 
67
69
  with pytest.raises(QasmException, match="Missing 'OPENQASM 2.0;' statement"):
68
70
  parser.parse(qasm)
69
71
 
70
72
 
71
- def test_comments():
73
+ def test_comments() -> None:
72
74
  parser = QasmParser()
73
75
 
74
76
  parsed_qasm = parser.parse(
@@ -87,7 +89,7 @@ def test_comments():
87
89
  ct.assert_same_circuits(parsed_qasm.circuit, Circuit())
88
90
 
89
91
 
90
- def test_multiple_qreg_declaration():
92
+ def test_multiple_qreg_declaration() -> None:
91
93
  qasm = """OPENQASM 2.0;
92
94
  include "qelib1.inc";
93
95
  qreg a_quantum_register [ 1337 ];
@@ -116,7 +118,7 @@ def test_multiple_qreg_declaration():
116
118
  """,
117
119
  ],
118
120
  )
119
- def test_already_defined_error(qasm: str):
121
+ def test_already_defined_error(qasm: str) -> None:
120
122
  parser = QasmParser()
121
123
 
122
124
  with pytest.raises(QasmException, match=r"q.*already defined.* line 3"):
@@ -134,14 +136,14 @@ def test_already_defined_error(qasm: str):
134
136
  """,
135
137
  ],
136
138
  )
137
- def test_zero_length_register(qasm: str):
139
+ def test_zero_length_register(qasm: str) -> None:
138
140
  parser = QasmParser()
139
141
 
140
142
  with pytest.raises(QasmException, match=".* zero-length.*'q'.*line 2"):
141
143
  parser.parse(qasm)
142
144
 
143
145
 
144
- def test_unexpected_end_of_file():
146
+ def test_unexpected_end_of_file() -> None:
145
147
  qasm = """OPENQASM 2.0;
146
148
  include "qelib1.inc";
147
149
  creg
@@ -152,7 +154,7 @@ def test_unexpected_end_of_file():
152
154
  parser.parse(qasm)
153
155
 
154
156
 
155
- def test_multiple_creg_declaration():
157
+ def test_multiple_creg_declaration() -> None:
156
158
  qasm = """OPENQASM 2.0;
157
159
  include "qelib1.inc";
158
160
  creg a_classical_register [1337];
@@ -170,7 +172,7 @@ def test_multiple_creg_declaration():
170
172
  assert parsed_qasm.cregs == {'a_classical_register': 1337, 'c': 42}
171
173
 
172
174
 
173
- def test_syntax_error():
175
+ def test_syntax_error() -> None:
174
176
  qasm = """OPENQASM 2.0;
175
177
  qreg q[2] bla;
176
178
  foobar q[0];
@@ -181,7 +183,7 @@ def test_syntax_error():
181
183
  parser.parse(qasm)
182
184
 
183
185
 
184
- def test_CX_gate():
186
+ def test_CX_gate() -> None:
185
187
  qasm = """OPENQASM 2.0;
186
188
  qreg q1[2];
187
189
  qreg q2[2];
@@ -214,8 +216,10 @@ def test_CX_gate():
214
216
  ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
215
217
  assert parsed_qasm.qregs == {'q1': 2, 'q2': 2}
216
218
 
219
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
220
+
217
221
 
218
- def test_classical_control():
222
+ def test_classical_control() -> None:
219
223
  qasm = """OPENQASM 2.0;
220
224
  qreg q[2];
221
225
  creg a[1];
@@ -259,7 +263,7 @@ if (m_a_0==1) cx q[0],q[1];
259
263
  assert cirq.qasm(parsed_qasm.circuit) == expected_generated_qasm
260
264
 
261
265
 
262
- def test_classical_control_multi_bit():
266
+ def test_classical_control_multi_bit() -> None:
263
267
  qasm = """OPENQASM 2.0;
264
268
  qreg q[2];
265
269
  creg a[2];
@@ -296,7 +300,7 @@ def test_classical_control_multi_bit():
296
300
  _ = cirq.qasm(parsed_qasm.circuit)
297
301
 
298
302
 
299
- def test_CX_gate_not_enough_args():
303
+ def test_CX_gate_not_enough_args() -> None:
300
304
  qasm = """OPENQASM 2.0;
301
305
  qreg q[2];
302
306
  CX q[0];
@@ -307,7 +311,7 @@ def test_CX_gate_not_enough_args():
307
311
  parser.parse(qasm)
308
312
 
309
313
 
310
- def test_CX_gate_mismatched_registers():
314
+ def test_CX_gate_mismatched_registers() -> None:
311
315
  qasm = """OPENQASM 2.0;
312
316
  qreg q1[2];
313
317
  qreg q2[3];
@@ -319,7 +323,7 @@ def test_CX_gate_mismatched_registers():
319
323
  parser.parse(qasm)
320
324
 
321
325
 
322
- def test_CX_gate_bounds():
326
+ def test_CX_gate_bounds() -> None:
323
327
  qasm = """OPENQASM 2.0;
324
328
  qreg q1[2];
325
329
  qreg q2[3];
@@ -331,7 +335,7 @@ def test_CX_gate_bounds():
331
335
  parser.parse(qasm)
332
336
 
333
337
 
334
- def test_CX_gate_arg_overlap():
338
+ def test_CX_gate_arg_overlap() -> None:
335
339
  qasm = """OPENQASM 2.0;
336
340
  qreg q1[2];
337
341
  qreg q2[3];
@@ -343,7 +347,7 @@ def test_CX_gate_arg_overlap():
343
347
  parser.parse(qasm)
344
348
 
345
349
 
346
- def test_U_gate():
350
+ def test_U_gate() -> None:
347
351
  qasm = """
348
352
  OPENQASM 2.0;
349
353
  qreg q[2];
@@ -375,8 +379,10 @@ def test_U_gate():
375
379
  ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
376
380
  assert parsed_qasm.qregs == {'q': 2}
377
381
 
382
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
383
+
378
384
 
379
- def test_U_angles():
385
+ def test_U_angles() -> None:
380
386
  qasm = """
381
387
  OPENQASM 2.0;
382
388
  qreg q[1];
@@ -389,7 +395,7 @@ def test_U_angles():
389
395
  )
390
396
 
391
397
 
392
- def test_U_gate_zero_params_error():
398
+ def test_U_gate_zero_params_error() -> None:
393
399
  qasm = """OPENQASM 2.0;
394
400
  qreg q[2];
395
401
  U q[1];"""
@@ -400,7 +406,7 @@ def test_U_gate_zero_params_error():
400
406
  parser.parse(qasm)
401
407
 
402
408
 
403
- def test_U_gate_too_much_params_error():
409
+ def test_U_gate_too_much_params_error() -> None:
404
410
  qasm = """OPENQASM 2.0;
405
411
  qreg q[2];
406
412
  U(pi, pi, pi, pi) q[1];"""
@@ -439,7 +445,7 @@ def test_U_gate_too_much_params_error():
439
445
  'atan(0.2)',
440
446
  ],
441
447
  )
442
- def test_expressions(expr: str):
448
+ def test_expressions(expr: str) -> None:
443
449
  qasm = f"""OPENQASM 2.0;
444
450
  qreg q[1];
445
451
  U({expr}, 2 * pi, pi / 2.0) q[0];
@@ -462,8 +468,10 @@ def test_expressions(expr: str):
462
468
  )
463
469
  assert parsed_qasm.qregs == {'q': 1}
464
470
 
471
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
465
472
 
466
- def test_unknown_function():
473
+
474
+ def test_unknown_function() -> None:
467
475
  qasm = """OPENQASM 2.0;
468
476
  qreg q[1];
469
477
  U(nonexistent(3), 2 * pi, pi / 3.0) q[0];
@@ -478,6 +486,7 @@ rotation_gates = [('rx', cirq.rx), ('ry', cirq.ry), ('rz', cirq.rz)]
478
486
 
479
487
 
480
488
  single_qubit_gates = [
489
+ ('id', cirq.I),
481
490
  ('x', cirq.X),
482
491
  ('y', cirq.Y),
483
492
  ('z', cirq.Z),
@@ -487,11 +496,12 @@ single_qubit_gates = [
487
496
  ('sdg', cirq.S**-1),
488
497
  ('tdg', cirq.T**-1),
489
498
  ('sx', cirq.XPowGate(exponent=0.5)),
499
+ ('sxdg', cirq.XPowGate(exponent=-0.5)),
490
500
  ]
491
501
 
492
502
 
493
503
  @pytest.mark.parametrize('qasm_gate,cirq_gate', rotation_gates)
494
- def test_rotation_gates(qasm_gate: str, cirq_gate: Callable[[float], cirq.Gate]):
504
+ def test_rotation_gates(qasm_gate: str, cirq_gate: Callable[[float], cirq.Gate]) -> None:
495
505
  qasm = f"""OPENQASM 2.0;
496
506
  include "qelib1.inc";
497
507
  qreg q[2];
@@ -516,9 +526,11 @@ def test_rotation_gates(qasm_gate: str, cirq_gate: Callable[[float], cirq.Gate])
516
526
  ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
517
527
  assert parsed_qasm.qregs == {'q': 2}
518
528
 
529
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
530
+
519
531
 
520
532
  @pytest.mark.parametrize('qasm_gate', [g[0] for g in rotation_gates])
521
- def test_rotation_gates_wrong_number_of_args(qasm_gate: str):
533
+ def test_rotation_gates_wrong_number_of_args(qasm_gate: str) -> None:
522
534
  qasm = f"""
523
535
  OPENQASM 2.0;
524
536
  include "qelib1.inc";
@@ -533,7 +545,7 @@ def test_rotation_gates_wrong_number_of_args(qasm_gate: str):
533
545
 
534
546
 
535
547
  @pytest.mark.parametrize('qasm_gate', [g[0] for g in rotation_gates])
536
- def test_rotation_gates_zero_params_error(qasm_gate: str):
548
+ def test_rotation_gates_zero_params_error(qasm_gate: str) -> None:
537
549
  qasm = f"""OPENQASM 2.0;
538
550
  include "qelib1.inc";
539
551
  qreg q[2];
@@ -546,7 +558,7 @@ def test_rotation_gates_zero_params_error(qasm_gate: str):
546
558
  parser.parse(qasm)
547
559
 
548
560
 
549
- def test_qelib_gate_without_include_statement():
561
+ def test_qelib_gate_without_include_statement() -> None:
550
562
  qasm = """OPENQASM 2.0;
551
563
  qreg q[2];
552
564
  x q[0];
@@ -557,7 +569,7 @@ def test_qelib_gate_without_include_statement():
557
569
  parser.parse(qasm)
558
570
 
559
571
 
560
- def test_undefined_register_from_qubit_arg():
572
+ def test_undefined_register_from_qubit_arg() -> None:
561
573
  qasm = """OPENQASM 2.0;
562
574
  qreg q[2];
563
575
  CX q[0], q2[1];
@@ -568,7 +580,7 @@ def test_undefined_register_from_qubit_arg():
568
580
  parser.parse(qasm)
569
581
 
570
582
 
571
- def test_undefined_register_from_register_arg():
583
+ def test_undefined_register_from_register_arg() -> None:
572
584
  qasm = """OPENQASM 2.0;
573
585
  qreg q[2];
574
586
  qreg q2[2];
@@ -580,7 +592,7 @@ def test_undefined_register_from_register_arg():
580
592
  parser.parse(qasm)
581
593
 
582
594
 
583
- def test_measure_individual_bits():
595
+ def test_measure_individual_bits() -> None:
584
596
  qasm = """
585
597
  OPENQASM 2.0;
586
598
  include "qelib1.inc";
@@ -608,8 +620,10 @@ def test_measure_individual_bits():
608
620
  assert parsed_qasm.qregs == {'q1': 2}
609
621
  assert parsed_qasm.cregs == {'c1': 2}
610
622
 
623
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
624
+
611
625
 
612
- def test_measure_registers():
626
+ def test_measure_registers() -> None:
613
627
  qasm = """OPENQASM 2.0;
614
628
  include "qelib1.inc";
615
629
  qreg q1[3];
@@ -637,8 +651,10 @@ def test_measure_registers():
637
651
  assert parsed_qasm.qregs == {'q1': 3}
638
652
  assert parsed_qasm.cregs == {'c1': 3}
639
653
 
654
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
640
655
 
641
- def test_measure_mismatched_register_size():
656
+
657
+ def test_measure_mismatched_register_size() -> None:
642
658
  qasm = """OPENQASM 2.0;
643
659
  include "qelib1.inc";
644
660
  qreg q1[2];
@@ -652,7 +668,7 @@ def test_measure_mismatched_register_size():
652
668
  parser.parse(qasm)
653
669
 
654
670
 
655
- def test_measure_to_quantum_register():
671
+ def test_measure_to_quantum_register() -> None:
656
672
  qasm = """OPENQASM 2.0;
657
673
  include "qelib1.inc";
658
674
  qreg q1[3];
@@ -667,7 +683,7 @@ def test_measure_to_quantum_register():
667
683
  parser.parse(qasm)
668
684
 
669
685
 
670
- def test_measure_undefined_classical_bit():
686
+ def test_measure_undefined_classical_bit() -> None:
671
687
  qasm = """OPENQASM 2.0;
672
688
  include "qelib1.inc";
673
689
  qreg q1[3];
@@ -681,7 +697,7 @@ def test_measure_undefined_classical_bit():
681
697
  parser.parse(qasm)
682
698
 
683
699
 
684
- def test_measure_from_classical_register():
700
+ def test_measure_from_classical_register() -> None:
685
701
  qasm = """OPENQASM 2.0;
686
702
  include "qelib1.inc";
687
703
  qreg q1[2];
@@ -696,7 +712,7 @@ def test_measure_from_classical_register():
696
712
  parser.parse(qasm)
697
713
 
698
714
 
699
- def test_measurement_bounds():
715
+ def test_measurement_bounds() -> None:
700
716
  qasm = """OPENQASM 2.0;
701
717
  qreg q1[3];
702
718
  creg c1[3];
@@ -708,7 +724,7 @@ def test_measurement_bounds():
708
724
  parser.parse(qasm)
709
725
 
710
726
 
711
- def test_reset():
727
+ def test_reset() -> None:
712
728
  qasm = textwrap.dedent(
713
729
  """\
714
730
  OPENQASM 2.0;
@@ -737,7 +753,32 @@ def test_reset():
737
753
  assert parsed_qasm.cregs == {'c': 1}
738
754
 
739
755
 
740
- def test_u1_gate():
756
+ def test_u0_gate() -> None:
757
+ qasm = """
758
+ OPENQASM 2.0;
759
+ include "qelib1.inc";
760
+ qreg q[1];
761
+ u0(0) q[0];
762
+ """
763
+ parser = QasmParser()
764
+
765
+ q0 = cirq.NamedQubit('q_0')
766
+
767
+ expected_circuit = Circuit()
768
+ expected_circuit.append(cirq.I(q0))
769
+
770
+ parsed_qasm = parser.parse(qasm)
771
+
772
+ assert parsed_qasm.supportedFormat
773
+ assert parsed_qasm.qelib1Include
774
+
775
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
776
+ assert parsed_qasm.qregs == {'q': 1}
777
+
778
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
779
+
780
+
781
+ def test_u1_gate() -> None:
741
782
  qasm = """
742
783
  OPENQASM 2.0;
743
784
  include "qelib1.inc";
@@ -759,8 +800,35 @@ def test_u1_gate():
759
800
  ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
760
801
  assert parsed_qasm.qregs == {'q': 1}
761
802
 
803
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
804
+
805
+
806
+ def test_p_gate() -> None:
807
+ qasm = """
808
+ OPENQASM 2.0;
809
+ include "qelib1.inc";
810
+ qreg q[1];
811
+ p(pi / 3.0) q[0];
812
+ """
813
+ parser = QasmParser()
814
+
815
+ q0 = cirq.NamedQubit('q_0')
816
+
817
+ expected_circuit = Circuit()
818
+ expected_circuit.append(cirq.ZPowGate(exponent=1.0 / 3.0)(q0))
819
+
820
+ parsed_qasm = parser.parse(qasm)
821
+
822
+ assert parsed_qasm.supportedFormat
823
+ assert parsed_qasm.qelib1Include
824
+
825
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
826
+ assert parsed_qasm.qregs == {'q': 1}
827
+
828
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
762
829
 
763
- def test_u2_gate():
830
+
831
+ def test_u2_gate() -> None:
764
832
  qasm = """
765
833
  OPENQASM 2.0;
766
834
  include "qelib1.inc";
@@ -782,8 +850,10 @@ def test_u2_gate():
782
850
  ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
783
851
  assert parsed_qasm.qregs == {'q': 1}
784
852
 
853
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
854
+
785
855
 
786
- def test_id_gate():
856
+ def test_id_gate() -> None:
787
857
  qasm = """
788
858
  OPENQASM 2.0;
789
859
  include "qelib1.inc";
@@ -807,8 +877,10 @@ def test_id_gate():
807
877
  ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
808
878
  assert parsed_qasm.qregs == {'q': 2}
809
879
 
880
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
881
+
810
882
 
811
- def test_u3_gate():
883
+ def test_u3_gate() -> None:
812
884
  qasm = """
813
885
  OPENQASM 2.0;
814
886
  include "qelib1.inc";
@@ -841,8 +913,46 @@ def test_u3_gate():
841
913
  ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
842
914
  assert parsed_qasm.qregs == {'q': 2}
843
915
 
916
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
917
+
918
+
919
+ def test_u_gate() -> None:
920
+ qasm = """
921
+ OPENQASM 2.0;
922
+ include "qelib1.inc";
923
+ qreg q[2];
924
+ u(pi, 2.3, 3) q[0];
925
+ u(+3.14, -pi, (8)) q;
926
+ """
927
+ parser = QasmParser()
928
+
929
+ q0 = cirq.NamedQubit('q_0')
930
+ q1 = cirq.NamedQubit('q_1')
931
+
932
+ expected_circuit = Circuit()
933
+ expected_circuit.append(
934
+ cirq.Moment(
935
+ [
936
+ QasmUGate(1.0, 2.3 / np.pi, 3 / np.pi)(q0),
937
+ QasmUGate(3.14 / np.pi, -1.0, 8 / np.pi)(q1),
938
+ ]
939
+ )
940
+ )
941
+
942
+ expected_circuit.append(cirq.Moment([QasmUGate(3.14 / np.pi, -1.0, 8 / np.pi)(q0)]))
943
+
944
+ parsed_qasm = parser.parse(qasm)
945
+
946
+ assert parsed_qasm.supportedFormat
947
+ assert parsed_qasm.qelib1Include
948
+
949
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
950
+ assert parsed_qasm.qregs == {'q': 2}
951
+
952
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
844
953
 
845
- def test_r_gate():
954
+
955
+ def test_r_gate() -> None:
846
956
  qasm = """
847
957
  OPENQASM 2.0;
848
958
  include "qelib1.inc";
@@ -855,7 +965,6 @@ def test_r_gate():
855
965
 
856
966
  expected_circuit = Circuit()
857
967
  expected_circuit.append(QasmUGate(1.0, 0.0, 0.0)(q0))
858
-
859
968
  parsed_qasm = parser.parse(qasm)
860
969
 
861
970
  assert parsed_qasm.supportedFormat
@@ -867,9 +976,11 @@ def test_r_gate():
867
976
 
868
977
  @pytest.mark.parametrize(
869
978
  'qasm_gate',
870
- ['id', 'u2', 'u3', 'r'] + [g[0] for g in rotation_gates] + [g[0] for g in single_qubit_gates],
979
+ ['p', 'u0', 'u1', 'u2', 'r', 'u3']
980
+ + [g[0] for g in rotation_gates]
981
+ + [g[0] for g in single_qubit_gates],
871
982
  )
872
- def test_standard_single_qubit_gates_wrong_number_of_args(qasm_gate):
983
+ def test_standard_single_qubit_gates_wrong_number_of_args(qasm_gate) -> None:
873
984
  qasm = f"""
874
985
  OPENQASM 2.0;
875
986
  include "qelib1.inc";
@@ -885,10 +996,21 @@ def test_standard_single_qubit_gates_wrong_number_of_args(qasm_gate):
885
996
 
886
997
  @pytest.mark.parametrize(
887
998
  ['qasm_gate', 'num_params'],
888
- [['id', 0], ['u2', 2], ['u3', 3], ['rx', 1], ['ry', 1], ['rz', 1], ['r', 2]]
999
+ [
1000
+ ['u0', 1],
1001
+ ['rx', 1],
1002
+ ['ry', 1],
1003
+ ['rz', 1],
1004
+ ['p', 1],
1005
+ ['u1', 1],
1006
+ ['u2', 2],
1007
+ ['r', 2],
1008
+ ['u3', 3],
1009
+ ['u', 3],
1010
+ ]
889
1011
  + [[g[0], 0] for g in single_qubit_gates],
890
1012
  )
891
- def test_standard_gates_wrong_params_error(qasm_gate: str, num_params: int):
1013
+ def test_standard_gates_wrong_params_error(qasm_gate: str, num_params: int) -> None:
892
1014
  qasm = f"""OPENQASM 2.0;
893
1015
  include "qelib1.inc";
894
1016
  qreg q[2];
@@ -922,19 +1044,25 @@ two_qubit_gates = [
922
1044
  ('cy', cirq.ControlledGate(cirq.Y)),
923
1045
  ('swap', cirq.SWAP),
924
1046
  ('ch', cirq.ControlledGate(cirq.H)),
1047
+ ('csx', cirq.ControlledGate(cirq.XPowGate(exponent=0.5))),
925
1048
  ]
926
1049
 
927
1050
 
928
1051
  # Mapping of two-qubit gates and `num_params`
929
1052
  two_qubit_param_gates = {
930
- ('cu1', cirq.ControlledGate(QasmUGate(0, 0, 0.1 / np.pi))): 1,
931
- ('cu3', cirq.ControlledGate(QasmUGate(0.1 / np.pi, 0.2 / np.pi, 0.3 / np.pi))): 3,
1053
+ # TODO: fix and enable commented gates below
1054
+ # ('cu1', cirq.ControlledGate(QasmUGate(0, 0, 0.1 / np.pi))): 1,
1055
+ # ('cu3', cirq.ControlledGate(QasmUGate(0.1 / np.pi, 0.2 / np.pi, 0.3 / np.pi))): 3,
1056
+ # ('cu', cirq.ControlledGate(QasmUGate(0.1 / np.pi, 0.2 / np.pi, 0.3 / np.pi))): 3,
1057
+ ('crx', cirq.ControlledGate(cirq.rx(0.1))): 1,
1058
+ ('cry', cirq.ControlledGate(cirq.ry(0.1))): 1,
932
1059
  ('crz', cirq.ControlledGate(cirq.rz(0.1))): 1,
1060
+ ('cp', cirq.ControlledGate(cirq.ZPowGate(exponent=0.1 / np.pi))): 1,
933
1061
  }
934
1062
 
935
1063
 
936
1064
  @pytest.mark.parametrize('qasm_gate,cirq_gate', two_qubit_gates)
937
- def test_two_qubit_gates(qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate):
1065
+ def test_two_qubit_gates(qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate) -> None:
938
1066
  qasm = f"""
939
1067
  OPENQASM 2.0;
940
1068
  include "qelib1.inc";
@@ -969,6 +1097,8 @@ def test_two_qubit_gates(qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate):
969
1097
  ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
970
1098
  assert parsed_qasm.qregs == {'q1': 2, 'q2': 2}
971
1099
 
1100
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
1101
+
972
1102
 
973
1103
  @pytest.mark.parametrize(
974
1104
  'qasm_gate,cirq_gate,num_params',
@@ -979,8 +1109,9 @@ def test_two_qubit_gates(qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate):
979
1109
  )
980
1110
  def test_two_qubit_param_gates(
981
1111
  qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate, num_params: int
982
- ):
983
- params = '(0.1, 0.2, 0.3)' if num_params == 3 else '(0.1)'
1112
+ ) -> None:
1113
+ params = f"({', '.join(f'{0.1 * (x + 1):g}' for x in range(num_params))})"
1114
+
984
1115
  qasm = f"""
985
1116
  OPENQASM 2.0;
986
1117
  include "qelib1.inc";
@@ -1011,31 +1142,30 @@ def test_two_qubit_param_gates(
1011
1142
  ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
1012
1143
  assert parsed_qasm.qregs == {'q1': 2, 'q2': 2}
1013
1144
 
1145
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
1146
+
1014
1147
 
1015
1148
  @pytest.mark.parametrize(
1016
1149
  'qasm_gate', [g[0] for g in two_qubit_gates] + [g[0] for g in two_qubit_param_gates.keys()]
1017
1150
  )
1018
- def test_two_qubit_gates_not_enough_qubits(qasm_gate: str):
1019
- if qasm_gate in ('cu1', 'crz'):
1020
- qasm = f"""
1021
- OPENQASM 2.0;
1022
- include "qelib1.inc";
1023
- qreg q[2];
1024
- {qasm_gate}(0.1) q[0];
1025
- """
1026
- elif qasm_gate == 'cu3':
1027
- qasm = f"""
1028
- OPENQASM 2.0;
1029
- include "qelib1.inc";
1030
- qreg q[2];
1031
- {qasm_gate}(0.1, 0.2, 0.3) q[0];
1032
- """
1033
- else:
1034
- qasm = f"""
1151
+ def test_two_qubit_gates_not_enough_qubits(qasm_gate: str) -> None:
1152
+ gate_mapping = {
1153
+ 'crx': '(0.1)',
1154
+ 'cry': '(0.1)',
1155
+ 'crz': '(0.1)',
1156
+ 'cp': '(0.1)',
1157
+ 'cu1': '(0.1)',
1158
+ 'cu3': '(0.1, 0.2, 0.3)',
1159
+ 'cu': '(0.1, 0.2, 0.3)',
1160
+ }
1161
+
1162
+ qasm_param = gate_mapping.get(qasm_gate, '')
1163
+
1164
+ qasm = f"""
1035
1165
  OPENQASM 2.0;
1036
1166
  include "qelib1.inc";
1037
1167
  qreg q[2];
1038
- {qasm_gate} q[0];
1168
+ {qasm_gate}{qasm_param} q[0];
1039
1169
  """
1040
1170
 
1041
1171
  parser = QasmParser()
@@ -1045,13 +1175,13 @@ def test_two_qubit_gates_not_enough_qubits(qasm_gate: str):
1045
1175
 
1046
1176
 
1047
1177
  @pytest.mark.parametrize('qasm_gate', [g[0] for g in two_qubit_param_gates.keys()])
1048
- def test_two_qubit_gates_not_enough_args(qasm_gate: str):
1178
+ def test_two_qubit_gates_not_enough_args(qasm_gate: str) -> None:
1049
1179
  qasm = f"""
1050
1180
  OPENQASM 2.0;
1051
1181
  include "qelib1.inc";
1052
1182
  qreg q[2];
1053
1183
  {qasm_gate} q[0];
1054
- """
1184
+ """
1055
1185
 
1056
1186
  parser = QasmParser()
1057
1187
 
@@ -1062,11 +1192,10 @@ def test_two_qubit_gates_not_enough_args(qasm_gate: str):
1062
1192
  @pytest.mark.parametrize(
1063
1193
  'qasm_gate', [g[0] for g in two_qubit_gates] + [g[0] for g in two_qubit_param_gates.keys()]
1064
1194
  )
1065
- def test_two_qubit_gates_with_too_much_parameters(qasm_gate: str):
1066
- if qasm_gate in ('cu1', 'cu3', 'crz'):
1067
- num_params_needed = 3 if qasm_gate == 'cu3' else 1
1068
- else:
1069
- num_params_needed = 0
1195
+ def test_two_qubit_gates_with_too_much_parameters(qasm_gate: str) -> None:
1196
+ params_mapping = {'crx': 1, 'cry': 1, 'crz': 1, 'cp': 1, 'cu1': 1, 'cu3': 3, 'cu': 3}
1197
+
1198
+ num_params_needed = params_mapping.get(qasm_gate, 0)
1070
1199
 
1071
1200
  qasm = f"""
1072
1201
  OPENQASM 2.0;
@@ -1084,11 +1213,103 @@ def test_two_qubit_gates_with_too_much_parameters(qasm_gate: str):
1084
1213
  parser.parse(qasm)
1085
1214
 
1086
1215
 
1087
- three_qubit_gates = [('ccx', cirq.TOFFOLI), ('cswap', cirq.CSWAP)]
1216
+ three_qubit_gates = [
1217
+ ('ccx', cirq.TOFFOLI),
1218
+ ('cswap', cirq.CSWAP),
1219
+ (
1220
+ 'rccx',
1221
+ cirq.MatrixGate(
1222
+ np.array(
1223
+ [
1224
+ [
1225
+ 1.0 + 0.0j,
1226
+ 0.0 + 0.0j,
1227
+ 0.0 + 0.0j,
1228
+ 0.0 + 0.0j,
1229
+ 0.0 + 0.0j,
1230
+ 0.0 + 0.0j,
1231
+ 0.0 + 0.0j,
1232
+ 0.0 + 0.0j,
1233
+ ],
1234
+ [
1235
+ 0.0 + 0.0j,
1236
+ 1.0 + 0.0j,
1237
+ 0.0 + 0.0j,
1238
+ 0.0 + 0.0j,
1239
+ 0.0 + 0.0j,
1240
+ 0.0 + 0.0j,
1241
+ 0.0 + 0.0j,
1242
+ 0.0 + 0.0j,
1243
+ ],
1244
+ [
1245
+ 0.0 + 0.0j,
1246
+ 0.0 + 0.0j,
1247
+ 1.0 + 0.0j,
1248
+ 0.0 + 0.0j,
1249
+ 0.0 + 0.0j,
1250
+ 0.0 + 0.0j,
1251
+ 0.0 + 0.0j,
1252
+ 0.0 + 0.0j,
1253
+ ],
1254
+ [
1255
+ 0.0 + 0.0j,
1256
+ 0.0 + 0.0j,
1257
+ 0.0 + 0.0j,
1258
+ 1.0 + 0.0j,
1259
+ 0.0 + 0.0j,
1260
+ 0.0 + 0.0j,
1261
+ 0.0 + 0.0j,
1262
+ 0.0 + 0.0j,
1263
+ ],
1264
+ [
1265
+ 0.0 + 0.0j,
1266
+ 0.0 + 0.0j,
1267
+ 0.0 + 0.0j,
1268
+ 0.0 + 0.0j,
1269
+ 1.0 + 0.0j,
1270
+ 0.0 + 0.0j,
1271
+ 0.0 + 0.0j,
1272
+ 0.0 + 0.0j,
1273
+ ],
1274
+ [
1275
+ 0.0 + 0.0j,
1276
+ 0.0 + 0.0j,
1277
+ 0.0 + 0.0j,
1278
+ 0.0 + 0.0j,
1279
+ 0.0 + 0.0j,
1280
+ -1.0 + 0.0j,
1281
+ 0.0 + 0.0j,
1282
+ 0.0 + 0.0j,
1283
+ ],
1284
+ [
1285
+ 0.0 + 0.0j,
1286
+ 0.0 + 0.0j,
1287
+ 0.0 + 0.0j,
1288
+ 0.0 + 0.0j,
1289
+ 0.0 + 0.0j,
1290
+ 0.0 + 0.0j,
1291
+ 0.0 + 0.0j,
1292
+ 0.0 - 1.0j,
1293
+ ],
1294
+ [
1295
+ 0.0 + 0.0j,
1296
+ 0.0 + 0.0j,
1297
+ 0.0 + 0.0j,
1298
+ 0.0 + 0.0j,
1299
+ 0.0 + 0.0j,
1300
+ 0.0 + 0.0j,
1301
+ 0.0 + 1.0j,
1302
+ 0.0 + 0.0j,
1303
+ ],
1304
+ ]
1305
+ )
1306
+ ),
1307
+ ),
1308
+ ]
1088
1309
 
1089
1310
 
1090
1311
  @pytest.mark.parametrize('qasm_gate,cirq_gate', three_qubit_gates)
1091
- def test_three_qubit_gates(qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate):
1312
+ def test_three_qubit_gates(qasm_gate: str, cirq_gate: cirq.Gate) -> None:
1092
1313
  qasm = f"""
1093
1314
  OPENQASM 2.0;
1094
1315
  include "qelib1.inc";
@@ -1126,9 +1347,11 @@ def test_three_qubit_gates(qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate)
1126
1347
  ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
1127
1348
  assert parsed_qasm.qregs == {'q1': 2, 'q2': 2, 'q3': 2}
1128
1349
 
1350
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
1351
+
1129
1352
 
1130
1353
  @pytest.mark.parametrize('qasm_gate', [g[0] for g in three_qubit_gates])
1131
- def test_three_qubit_gates_not_enough_args(qasm_gate: str):
1354
+ def test_three_qubit_gates_not_enough_args(qasm_gate: str) -> None:
1132
1355
  qasm = f"""OPENQASM 2.0;
1133
1356
  include "qelib1.inc";
1134
1357
  qreg q[2];
@@ -1142,7 +1365,7 @@ def test_three_qubit_gates_not_enough_args(qasm_gate: str):
1142
1365
 
1143
1366
 
1144
1367
  @pytest.mark.parametrize('qasm_gate', [g[0] for g in three_qubit_gates])
1145
- def test_three_qubit_gates_with_too_much_parameters(qasm_gate: str):
1368
+ def test_three_qubit_gates_with_too_much_parameters(qasm_gate: str) -> None:
1146
1369
  qasm = f"""OPENQASM 2.0;
1147
1370
  include "qelib1.inc";
1148
1371
  qreg q[3];
@@ -1155,8 +1378,463 @@ def test_three_qubit_gates_with_too_much_parameters(qasm_gate: str):
1155
1378
  parser.parse(qasm)
1156
1379
 
1157
1380
 
1381
+ four_qubit_gates = [
1382
+ ('c3x', cirq.ControlledGate(cirq.X, num_controls=3)),
1383
+ ('c3sqrtx', cirq.ControlledGate(cirq.XPowGate(exponent=0.5), num_controls=3)),
1384
+ (
1385
+ 'rc3x',
1386
+ cirq.MatrixGate(
1387
+ np.array(
1388
+ [
1389
+ [
1390
+ 1.0 + 0.0j,
1391
+ 0.0 + 0.0j,
1392
+ 0.0 + 0.0j,
1393
+ 0.0 + 0.0j,
1394
+ 0.0 + 0.0j,
1395
+ 0.0 + 0.0j,
1396
+ 0.0 + 0.0j,
1397
+ 0.0 + 0.0j,
1398
+ 0.0 + 0.0j,
1399
+ 0.0 + 0.0j,
1400
+ 0.0 + 0.0j,
1401
+ 0.0 + 0.0j,
1402
+ 0.0 + 0.0j,
1403
+ 0.0 + 0.0j,
1404
+ 0.0 + 0.0j,
1405
+ 0.0 + 0.0j,
1406
+ ],
1407
+ [
1408
+ 0.0 + 0.0j,
1409
+ 1.0 + 0.0j,
1410
+ 0.0 + 0.0j,
1411
+ 0.0 + 0.0j,
1412
+ 0.0 + 0.0j,
1413
+ 0.0 + 0.0j,
1414
+ 0.0 + 0.0j,
1415
+ 0.0 + 0.0j,
1416
+ 0.0 + 0.0j,
1417
+ 0.0 + 0.0j,
1418
+ 0.0 + 0.0j,
1419
+ 0.0 + 0.0j,
1420
+ 0.0 + 0.0j,
1421
+ 0.0 + 0.0j,
1422
+ 0.0 + 0.0j,
1423
+ 0.0 + 0.0j,
1424
+ ],
1425
+ [
1426
+ 0.0 + 0.0j,
1427
+ 0.0 + 0.0j,
1428
+ 1.0 + 0.0j,
1429
+ 0.0 + 0.0j,
1430
+ 0.0 + 0.0j,
1431
+ 0.0 + 0.0j,
1432
+ 0.0 + 0.0j,
1433
+ 0.0 + 0.0j,
1434
+ 0.0 + 0.0j,
1435
+ 0.0 + 0.0j,
1436
+ 0.0 + 0.0j,
1437
+ 0.0 + 0.0j,
1438
+ 0.0 + 0.0j,
1439
+ 0.0 + 0.0j,
1440
+ 0.0 + 0.0j,
1441
+ 0.0 + 0.0j,
1442
+ ],
1443
+ [
1444
+ 0.0 + 0.0j,
1445
+ 0.0 + 0.0j,
1446
+ 0.0 + 0.0j,
1447
+ 1.0 + 0.0j,
1448
+ 0.0 + 0.0j,
1449
+ 0.0 + 0.0j,
1450
+ 0.0 + 0.0j,
1451
+ 0.0 + 0.0j,
1452
+ 0.0 + 0.0j,
1453
+ 0.0 + 0.0j,
1454
+ 0.0 + 0.0j,
1455
+ 0.0 + 0.0j,
1456
+ 0.0 + 0.0j,
1457
+ 0.0 + 0.0j,
1458
+ 0.0 + 0.0j,
1459
+ 0.0 + 0.0j,
1460
+ ],
1461
+ [
1462
+ 0.0 + 0.0j,
1463
+ 0.0 + 0.0j,
1464
+ 0.0 + 0.0j,
1465
+ 0.0 + 0.0j,
1466
+ 1.0 + 0.0j,
1467
+ 0.0 + 0.0j,
1468
+ 0.0 + 0.0j,
1469
+ 0.0 + 0.0j,
1470
+ 0.0 + 0.0j,
1471
+ 0.0 + 0.0j,
1472
+ 0.0 + 0.0j,
1473
+ 0.0 + 0.0j,
1474
+ 0.0 + 0.0j,
1475
+ 0.0 + 0.0j,
1476
+ 0.0 + 0.0j,
1477
+ 0.0 + 0.0j,
1478
+ ],
1479
+ [
1480
+ 0.0 + 0.0j,
1481
+ 0.0 + 0.0j,
1482
+ 0.0 + 0.0j,
1483
+ 0.0 + 0.0j,
1484
+ 0.0 + 0.0j,
1485
+ 1.0 + 0.0j,
1486
+ 0.0 + 0.0j,
1487
+ 0.0 + 0.0j,
1488
+ 0.0 + 0.0j,
1489
+ 0.0 + 0.0j,
1490
+ 0.0 + 0.0j,
1491
+ 0.0 + 0.0j,
1492
+ 0.0 + 0.0j,
1493
+ 0.0 + 0.0j,
1494
+ 0.0 + 0.0j,
1495
+ 0.0 + 0.0j,
1496
+ ],
1497
+ [
1498
+ 0.0 + 0.0j,
1499
+ 0.0 + 0.0j,
1500
+ 0.0 + 0.0j,
1501
+ 0.0 + 0.0j,
1502
+ 0.0 + 0.0j,
1503
+ 0.0 + 0.0j,
1504
+ 1.0 + 0.0j,
1505
+ 0.0 + 0.0j,
1506
+ 0.0 + 0.0j,
1507
+ 0.0 + 0.0j,
1508
+ 0.0 + 0.0j,
1509
+ 0.0 + 0.0j,
1510
+ 0.0 + 0.0j,
1511
+ 0.0 + 0.0j,
1512
+ 0.0 + 0.0j,
1513
+ 0.0 + 0.0j,
1514
+ ],
1515
+ [
1516
+ 0.0 + 0.0j,
1517
+ 0.0 + 0.0j,
1518
+ 0.0 + 0.0j,
1519
+ 0.0 + 0.0j,
1520
+ 0.0 + 0.0j,
1521
+ 0.0 + 0.0j,
1522
+ 0.0 + 0.0j,
1523
+ 1.0 + 0.0j,
1524
+ 0.0 + 0.0j,
1525
+ 0.0 + 0.0j,
1526
+ 0.0 + 0.0j,
1527
+ 0.0 + 0.0j,
1528
+ 0.0 + 0.0j,
1529
+ 0.0 + 0.0j,
1530
+ 0.0 + 0.0j,
1531
+ 0.0 + 0.0j,
1532
+ ],
1533
+ [
1534
+ 0.0 + 0.0j,
1535
+ 0.0 + 0.0j,
1536
+ 0.0 + 0.0j,
1537
+ 0.0 + 0.0j,
1538
+ 0.0 + 0.0j,
1539
+ 0.0 + 0.0j,
1540
+ 0.0 + 0.0j,
1541
+ 0.0 + 0.0j,
1542
+ 1.0 + 0.0j,
1543
+ 0.0 + 0.0j,
1544
+ 0.0 + 0.0j,
1545
+ 0.0 + 0.0j,
1546
+ 0.0 + 0.0j,
1547
+ 0.0 + 0.0j,
1548
+ 0.0 + 0.0j,
1549
+ 0.0 + 0.0j,
1550
+ ],
1551
+ [
1552
+ 0.0 + 0.0j,
1553
+ 0.0 + 0.0j,
1554
+ 0.0 + 0.0j,
1555
+ 0.0 + 0.0j,
1556
+ 0.0 + 0.0j,
1557
+ 0.0 + 0.0j,
1558
+ 0.0 + 0.0j,
1559
+ 0.0 + 0.0j,
1560
+ 0.0 + 0.0j,
1561
+ 1.0 + 0.0j,
1562
+ 0.0 + 0.0j,
1563
+ 0.0 + 0.0j,
1564
+ 0.0 + 0.0j,
1565
+ 0.0 + 0.0j,
1566
+ 0.0 + 0.0j,
1567
+ 0.0 + 0.0j,
1568
+ ],
1569
+ [
1570
+ 0.0 + 0.0j,
1571
+ 0.0 + 0.0j,
1572
+ 0.0 + 0.0j,
1573
+ 0.0 + 0.0j,
1574
+ 0.0 + 0.0j,
1575
+ 0.0 + 0.0j,
1576
+ 0.0 + 0.0j,
1577
+ 0.0 + 0.0j,
1578
+ 0.0 + 0.0j,
1579
+ 0.0 + 0.0j,
1580
+ 1.0 + 0.0j,
1581
+ 0.0 + 0.0j,
1582
+ 0.0 + 0.0j,
1583
+ 0.0 + 0.0j,
1584
+ 0.0 + 0.0j,
1585
+ 0.0 + 0.0j,
1586
+ ],
1587
+ [
1588
+ 0.0 + 0.0j,
1589
+ 0.0 + 0.0j,
1590
+ 0.0 + 0.0j,
1591
+ 0.0 + 0.0j,
1592
+ 0.0 + 0.0j,
1593
+ 0.0 + 0.0j,
1594
+ 0.0 + 0.0j,
1595
+ 0.0 + 0.0j,
1596
+ 0.0 + 0.0j,
1597
+ 0.0 + 0.0j,
1598
+ 0.0 + 0.0j,
1599
+ 1.0 + 0.0j,
1600
+ 0.0 + 0.0j,
1601
+ 0.0 + 0.0j,
1602
+ 0.0 + 0.0j,
1603
+ 0.0 + 0.0j,
1604
+ ],
1605
+ [
1606
+ 0.0 + 0.0j,
1607
+ 0.0 + 0.0j,
1608
+ 0.0 + 0.0j,
1609
+ 0.0 + 0.0j,
1610
+ 0.0 + 0.0j,
1611
+ 0.0 + 0.0j,
1612
+ 0.0 + 0.0j,
1613
+ 0.0 + 0.0j,
1614
+ 0.0 + 0.0j,
1615
+ 0.0 + 0.0j,
1616
+ 0.0 + 0.0j,
1617
+ 0.0 + 0.0j,
1618
+ 0.0 + 1.0j,
1619
+ 0.0 + 0.0j,
1620
+ 0.0 + 0.0j,
1621
+ 0.0 + 0.0j,
1622
+ ],
1623
+ [
1624
+ 0.0 + 0.0j,
1625
+ 0.0 + 0.0j,
1626
+ 0.0 + 0.0j,
1627
+ 0.0 + 0.0j,
1628
+ 0.0 + 0.0j,
1629
+ 0.0 + 0.0j,
1630
+ 0.0 + 0.0j,
1631
+ 0.0 + 0.0j,
1632
+ 0.0 + 0.0j,
1633
+ 0.0 + 0.0j,
1634
+ 0.0 + 0.0j,
1635
+ 0.0 + 0.0j,
1636
+ 0.0 + 0.0j,
1637
+ 0.0 - 1.0j,
1638
+ 0.0 + 0.0j,
1639
+ 0.0 + 0.0j,
1640
+ ],
1641
+ [
1642
+ 0.0 + 0.0j,
1643
+ 0.0 + 0.0j,
1644
+ 0.0 + 0.0j,
1645
+ 0.0 + 0.0j,
1646
+ 0.0 + 0.0j,
1647
+ 0.0 + 0.0j,
1648
+ 0.0 + 0.0j,
1649
+ 0.0 + 0.0j,
1650
+ 0.0 + 0.0j,
1651
+ 0.0 + 0.0j,
1652
+ 0.0 + 0.0j,
1653
+ 0.0 + 0.0j,
1654
+ 0.0 + 0.0j,
1655
+ 0.0 + 0.0j,
1656
+ 0.0 + 0.0j,
1657
+ 1.0 + 0.0j,
1658
+ ],
1659
+ [
1660
+ 0.0 + 0.0j,
1661
+ 0.0 + 0.0j,
1662
+ 0.0 + 0.0j,
1663
+ 0.0 + 0.0j,
1664
+ 0.0 + 0.0j,
1665
+ 0.0 + 0.0j,
1666
+ 0.0 + 0.0j,
1667
+ 0.0 + 0.0j,
1668
+ 0.0 + 0.0j,
1669
+ 0.0 + 0.0j,
1670
+ 0.0 + 0.0j,
1671
+ 0.0 + 0.0j,
1672
+ 0.0 + 0.0j,
1673
+ 0.0 + 0.0j,
1674
+ -1.0 + 0.0j,
1675
+ 0.0 + 0.0j,
1676
+ ],
1677
+ ]
1678
+ )
1679
+ ),
1680
+ ),
1681
+ ]
1682
+
1683
+
1684
+ @pytest.mark.parametrize('qasm_gate,cirq_gate', four_qubit_gates)
1685
+ def test_four_qubit_gates(qasm_gate: str, cirq_gate: cirq.Gate) -> None:
1686
+ qasm = f"""
1687
+ OPENQASM 2.0;
1688
+ include "qelib1.inc";
1689
+ qreg q1[2];
1690
+ qreg q2[2];
1691
+ qreg q3[2];
1692
+ qreg q4[2];
1693
+ {qasm_gate} q1[0], q1[1], q2[0], q3[0];
1694
+ {qasm_gate} q1, q2[0], q3[0], q4[0];
1695
+ {qasm_gate} q1, q2, q3, q4;
1696
+ """
1697
+ parser = QasmParser()
1698
+
1699
+ q1_0 = cirq.NamedQubit('q1_0')
1700
+ q1_1 = cirq.NamedQubit('q1_1')
1701
+ q2_0 = cirq.NamedQubit('q2_0')
1702
+ q2_1 = cirq.NamedQubit('q2_1')
1703
+ q3_0 = cirq.NamedQubit('q3_0')
1704
+ q3_1 = cirq.NamedQubit('q3_1')
1705
+ q4_0 = cirq.NamedQubit('q4_0')
1706
+ q4_1 = cirq.NamedQubit('q4_1')
1707
+
1708
+ expected_circuit = Circuit()
1709
+
1710
+ expected_circuit.append(cirq_gate(q1_0, q1_1, q2_0, q3_0))
1711
+
1712
+ expected_circuit.append(cirq_gate(q1_0, q2_0, q3_0, q4_0))
1713
+ expected_circuit.append(cirq_gate(q1_1, q2_0, q3_0, q4_0))
1714
+
1715
+ expected_circuit.append(cirq_gate(q1_0, q2_0, q3_0, q4_0))
1716
+ expected_circuit.append(cirq_gate(q1_1, q2_1, q3_1, q4_1))
1717
+
1718
+ parsed_qasm = parser.parse(qasm)
1719
+
1720
+ assert parsed_qasm.supportedFormat
1721
+ assert parsed_qasm.qelib1Include
1722
+
1723
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
1724
+ assert parsed_qasm.qregs == {'q1': 2, 'q2': 2, 'q3': 2, 'q4': 2}
1725
+
1726
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
1727
+
1728
+
1729
+ @pytest.mark.parametrize('qasm_gate', [g[0] for g in four_qubit_gates])
1730
+ def test_four_qubit_gates_not_enough_args(qasm_gate: str) -> None:
1731
+ qasm = f"""OPENQASM 2.0;
1732
+ include "qelib1.inc";
1733
+ qreg q[2];
1734
+ {qasm_gate} q[0];
1735
+ """
1736
+
1737
+ parser = QasmParser()
1738
+
1739
+ with pytest.raises(QasmException, match=rf".*{qasm_gate}.* takes 4 arg\(s\).*got.*1.*line 4"):
1740
+ parser.parse(qasm)
1741
+
1742
+
1743
+ @pytest.mark.parametrize('qasm_gate', [g[0] for g in four_qubit_gates])
1744
+ def test_four_qubit_gates_with_too_much_parameters(qasm_gate: str) -> None:
1745
+ qasm = f"""OPENQASM 2.0;
1746
+ include "qelib1.inc";
1747
+ qreg q[4];
1748
+ {qasm_gate}(pi) q[0],q[1],q[2],q[3];
1749
+ """
1750
+
1751
+ parser = QasmParser()
1752
+
1753
+ with pytest.raises(QasmException, match=f".*{qasm_gate}.*parameter.*line 4.*"):
1754
+ parser.parse(qasm)
1755
+
1756
+
1757
+ five_qubit_gates = [('c4x', cirq.ControlledGate(cirq.X, num_controls=4))]
1758
+
1759
+
1760
+ @pytest.mark.parametrize('qasm_gate,cirq_gate', five_qubit_gates)
1761
+ def test_five_qubit_gates(qasm_gate: str, cirq_gate: cirq.Gate) -> None:
1762
+ qasm = f"""
1763
+ OPENQASM 2.0;
1764
+ include "qelib1.inc";
1765
+ qreg q1[2];
1766
+ qreg q2[2];
1767
+ qreg q3[2];
1768
+ qreg q4[2];
1769
+ qreg q5[2];
1770
+ {qasm_gate} q1[0], q1[1], q2[0], q3[0], q4[0];
1771
+ {qasm_gate} q1, q2[0], q3[0], q4[0], q5[0];
1772
+ {qasm_gate} q1, q2, q3, q4, q5;
1773
+ """
1774
+ parser = QasmParser()
1775
+
1776
+ q1_0 = cirq.NamedQubit('q1_0')
1777
+ q1_1 = cirq.NamedQubit('q1_1')
1778
+ q2_0 = cirq.NamedQubit('q2_0')
1779
+ q2_1 = cirq.NamedQubit('q2_1')
1780
+ q3_0 = cirq.NamedQubit('q3_0')
1781
+ q3_1 = cirq.NamedQubit('q3_1')
1782
+ q4_0 = cirq.NamedQubit('q4_0')
1783
+ q4_1 = cirq.NamedQubit('q4_1')
1784
+ q5_0 = cirq.NamedQubit('q5_0')
1785
+ q5_1 = cirq.NamedQubit('q5_1')
1786
+
1787
+ expected_circuit = Circuit()
1788
+
1789
+ expected_circuit.append(cirq_gate(q1_0, q1_1, q2_0, q3_0, q4_0))
1790
+
1791
+ expected_circuit.append(cirq_gate(q1_0, q2_0, q3_0, q4_0, q5_0))
1792
+ expected_circuit.append(cirq_gate(q1_1, q2_0, q3_0, q4_0, q5_0))
1793
+
1794
+ expected_circuit.append(cirq_gate(q1_0, q2_0, q3_0, q4_0, q5_0))
1795
+ expected_circuit.append(cirq_gate(q1_1, q2_1, q3_1, q4_1, q5_1))
1796
+
1797
+ parsed_qasm = parser.parse(qasm)
1798
+
1799
+ assert parsed_qasm.supportedFormat
1800
+ assert parsed_qasm.qelib1Include
1801
+
1802
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
1803
+ assert parsed_qasm.qregs == {'q1': 2, 'q2': 2, 'q3': 2, 'q4': 2, 'q5': 2}
1804
+
1805
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
1806
+
1807
+
1808
+ @pytest.mark.parametrize('qasm_gate', [g[0] for g in five_qubit_gates])
1809
+ def test_five_qubit_gates_not_enough_args(qasm_gate: str) -> None:
1810
+ qasm = f"""OPENQASM 2.0;
1811
+ include "qelib1.inc";
1812
+ qreg q[2];
1813
+ {qasm_gate} q[0];
1814
+ """
1815
+
1816
+ parser = QasmParser()
1817
+
1818
+ with pytest.raises(QasmException, match=rf".*{qasm_gate}.* takes 5 arg\(s\).*got.*1.*line 4"):
1819
+ parser.parse(qasm)
1820
+
1821
+
1822
+ @pytest.mark.parametrize('qasm_gate', [g[0] for g in five_qubit_gates])
1823
+ def test_five_qubit_gates_with_too_much_parameters(qasm_gate: str) -> None:
1824
+ qasm = f"""OPENQASM 2.0;
1825
+ include "qelib1.inc";
1826
+ qreg q[5];
1827
+ {qasm_gate}(pi) q[0],q[1],q[2],q[3],q[4];
1828
+ """
1829
+
1830
+ parser = QasmParser()
1831
+
1832
+ with pytest.raises(QasmException, match=f".*{qasm_gate}.*parameter.*line 4.*"):
1833
+ parser.parse(qasm)
1834
+
1835
+
1158
1836
  @pytest.mark.parametrize('qasm_gate,cirq_gate', single_qubit_gates)
1159
- def test_single_qubit_gates(qasm_gate: str, cirq_gate: cirq.Gate):
1837
+ def test_single_qubit_gates(qasm_gate: str, cirq_gate: cirq.Gate) -> None:
1160
1838
  qasm = f"""OPENQASM 2.0;
1161
1839
  include "qelib1.inc";
1162
1840
  qreg q[2];
@@ -1179,8 +1857,10 @@ def test_single_qubit_gates(qasm_gate: str, cirq_gate: cirq.Gate):
1179
1857
  ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
1180
1858
  assert parsed_qasm.qregs == {'q': 2}
1181
1859
 
1860
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
1861
+
1182
1862
 
1183
- def test_openqasm_3_0_qubits():
1863
+ def test_openqasm_3_0_qubits() -> None:
1184
1864
  qasm = """OPENQASM 3.0;
1185
1865
  include "stdgates.inc";
1186
1866
  qubit[2] q;
@@ -1205,7 +1885,7 @@ def test_openqasm_3_0_qubits():
1205
1885
  assert parsed_qasm.qregs == {'q': 2}
1206
1886
 
1207
1887
 
1208
- def test_openqasm_3_0_scalar_qubit():
1888
+ def test_openqasm_3_0_scalar_qubit() -> None:
1209
1889
  qasm = """OPENQASM 3.0;
1210
1890
  include "stdgates.inc";
1211
1891
  qubit q;
@@ -1230,7 +1910,7 @@ def test_openqasm_3_0_scalar_qubit():
1230
1910
  assert parsed_qasm.qregs == {'q': 1}
1231
1911
 
1232
1912
 
1233
- def test_custom_gate():
1913
+ def test_custom_gate() -> None:
1234
1914
  qasm = """OPENQASM 2.0;
1235
1915
  include "qelib1.inc";
1236
1916
  qreg q[2];
@@ -1271,7 +1951,7 @@ def test_custom_gate():
1271
1951
  cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(unrolled))
1272
1952
 
1273
1953
 
1274
- def test_custom_gate_parameterized():
1954
+ def test_custom_gate_parameterized() -> None:
1275
1955
  qasm = """OPENQASM 2.0;
1276
1956
  include "qelib1.inc";
1277
1957
  qreg q[2];
@@ -1320,7 +2000,7 @@ def test_custom_gate_parameterized():
1320
2000
  cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(unrolled))
1321
2001
 
1322
2002
 
1323
- def test_custom_gate_broadcast():
2003
+ def test_custom_gate_broadcast() -> None:
1324
2004
  qasm = """OPENQASM 2.0;
1325
2005
  include "qelib1.inc";
1326
2006
  qreg q[3];
@@ -1370,7 +2050,7 @@ def test_custom_gate_broadcast():
1370
2050
  cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(unrolled))
1371
2051
 
1372
2052
 
1373
- def test_custom_gate_undefined_qubit_error():
2053
+ def test_custom_gate_undefined_qubit_error() -> None:
1374
2054
  qasm = """OPENQASM 2.0;
1375
2055
  include "qelib1.inc";
1376
2056
  qreg q[1];
@@ -1384,7 +2064,7 @@ def test_custom_gate_undefined_qubit_error():
1384
2064
  )
1385
2065
 
1386
2066
 
1387
- def test_custom_gate_qubit_scope_closure_error():
2067
+ def test_custom_gate_qubit_scope_closure_error() -> None:
1388
2068
  qasm = """OPENQASM 2.0;
1389
2069
  include "qelib1.inc";
1390
2070
  qreg q[1];
@@ -1398,7 +2078,7 @@ def test_custom_gate_qubit_scope_closure_error():
1398
2078
  )
1399
2079
 
1400
2080
 
1401
- def test_custom_gate_qubit_index_error():
2081
+ def test_custom_gate_qubit_index_error() -> None:
1402
2082
  qasm = """OPENQASM 2.0;
1403
2083
  include "qelib1.inc";
1404
2084
  qreg q[1];
@@ -1412,7 +2092,7 @@ def test_custom_gate_qubit_index_error():
1412
2092
  )
1413
2093
 
1414
2094
 
1415
- def test_custom_gate_qreg_count_error():
2095
+ def test_custom_gate_qreg_count_error() -> None:
1416
2096
  qasm = """OPENQASM 2.0;
1417
2097
  include "qelib1.inc";
1418
2098
  qreg q[2];
@@ -1426,7 +2106,7 @@ def test_custom_gate_qreg_count_error():
1426
2106
  )
1427
2107
 
1428
2108
 
1429
- def test_custom_gate_missing_param_error():
2109
+ def test_custom_gate_missing_param_error() -> None:
1430
2110
  qasm = """OPENQASM 2.0;
1431
2111
  include "qelib1.inc";
1432
2112
  qreg q[1];
@@ -1440,7 +2120,7 @@ def test_custom_gate_missing_param_error():
1440
2120
  )
1441
2121
 
1442
2122
 
1443
- def test_custom_gate_extra_param_error():
2123
+ def test_custom_gate_extra_param_error() -> None:
1444
2124
  qasm = """OPENQASM 2.0;
1445
2125
  include "qelib1.inc";
1446
2126
  qreg q[1];
@@ -1454,7 +2134,7 @@ def test_custom_gate_extra_param_error():
1454
2134
  )
1455
2135
 
1456
2136
 
1457
- def test_custom_gate_undefined_param_error():
2137
+ def test_custom_gate_undefined_param_error() -> None:
1458
2138
  qasm = """OPENQASM 2.0;
1459
2139
  include "qelib1.inc";
1460
2140
  qreg q[1];
@@ -1468,7 +2148,7 @@ def test_custom_gate_undefined_param_error():
1468
2148
  )
1469
2149
 
1470
2150
 
1471
- def test_top_level_param_error():
2151
+ def test_top_level_param_error() -> None:
1472
2152
  qasm = """OPENQASM 2.0;
1473
2153
  include "qelib1.inc";
1474
2154
  qreg q[1];
@@ -1495,7 +2175,7 @@ def _test_parse_exception(qasm: str, cirq_err: str, qiskit_err: str | None):
1495
2175
  qiskit.QuantumCircuit.from_qasm_str(qasm)
1496
2176
 
1497
2177
 
1498
- def test_nested_custom_gate_has_keyword_in_name():
2178
+ def test_nested_custom_gate_has_keyword_in_name() -> None:
1499
2179
  qasm = """OPENQASM 2.0;
1500
2180
  include "qelib1.inc";
1501
2181
  qreg q[1];
@@ -1512,3 +2192,214 @@ def test_nested_custom_gate_has_keyword_in_name():
1512
2192
  parser = QasmParser()
1513
2193
  parsed_qasm = parser.parse(qasm)
1514
2194
  assert parsed_qasm.circuit == expected
2195
+
2196
+
2197
+ def test_rzz_gate() -> None:
2198
+ qasm = """
2199
+ OPENQASM 2.0;
2200
+ include "qelib1.inc";
2201
+ qreg q[2];
2202
+ rzz(pi/2) q[0],q[1];
2203
+ """
2204
+ parser = QasmParser()
2205
+
2206
+ q0, q1 = cirq.NamedQubit('q_0'), cirq.NamedQubit('q_1')
2207
+
2208
+ expected_circuit = Circuit()
2209
+ expected_circuit.append(cirq.ZZPowGate(exponent=0.5).on(q0, q1))
2210
+
2211
+ parsed_qasm = parser.parse(qasm)
2212
+
2213
+ assert parsed_qasm.supportedFormat
2214
+ assert parsed_qasm.qelib1Include
2215
+
2216
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
2217
+ assert parsed_qasm.qregs == {'q': 2}
2218
+
2219
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
2220
+
2221
+
2222
+ def test_ryy_gate() -> None:
2223
+ qasm = """
2224
+ OPENQASM 2.0;
2225
+ include "qelib1.inc";
2226
+ qreg q[2];
2227
+ ryy(pi/3) q[0],q[1];
2228
+ """
2229
+ parser = QasmParser()
2230
+
2231
+ q0, q1 = cirq.NamedQubit('q_0'), cirq.NamedQubit('q_1')
2232
+
2233
+ expected_circuit = Circuit()
2234
+ expected_circuit.append(cirq.YYPowGate(exponent=1 / 3).on(q0, q1))
2235
+
2236
+ parsed_qasm = parser.parse(qasm)
2237
+
2238
+ assert parsed_qasm.supportedFormat
2239
+ assert parsed_qasm.qelib1Include
2240
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
2241
+ assert parsed_qasm.qregs == {'q': 2}
2242
+
2243
+
2244
+ def test_rxx_gate() -> None:
2245
+ qasm = """
2246
+ OPENQASM 2.0;
2247
+ include "qelib1.inc";
2248
+ qreg q[2];
2249
+ rxx(pi/4) q[0],q[1];
2250
+ """
2251
+ parser = QasmParser()
2252
+
2253
+ q0, q1 = cirq.NamedQubit('q_0'), cirq.NamedQubit('q_1')
2254
+
2255
+ expected_circuit = Circuit()
2256
+ expected_circuit.append(cirq.XXPowGate(exponent=0.25).on(q0, q1))
2257
+
2258
+ parsed_qasm = parser.parse(qasm)
2259
+
2260
+ assert parsed_qasm.supportedFormat
2261
+ assert parsed_qasm.qelib1Include
2262
+
2263
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
2264
+ assert parsed_qasm.qregs == {'q': 2}
2265
+
2266
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
2267
+
2268
+
2269
+ def test_crx_gate() -> None:
2270
+ qasm = """
2271
+ OPENQASM 2.0;
2272
+ include "qelib1.inc";
2273
+ qreg q[2];
2274
+ crx(pi/7) q[0],q[1];
2275
+ """
2276
+ parser = QasmParser()
2277
+
2278
+ q0, q1 = cirq.NamedQubit('q_0'), cirq.NamedQubit('q_1')
2279
+
2280
+ expected_circuit = Circuit()
2281
+ expected_circuit.append(cirq.ControlledGate(cirq.rx(np.pi / 7)).on(q0, q1))
2282
+
2283
+ parsed_qasm = parser.parse(qasm)
2284
+
2285
+ assert parsed_qasm.supportedFormat
2286
+ assert parsed_qasm.qelib1Include
2287
+
2288
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
2289
+ assert parsed_qasm.qregs == {'q': 2}
2290
+
2291
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
2292
+
2293
+
2294
+ def test_cry_gate() -> None:
2295
+ qasm = """
2296
+ OPENQASM 2.0;
2297
+ include "qelib1.inc";
2298
+ qreg q[2];
2299
+ cry(pi/7) q[0],q[1];
2300
+ """
2301
+ parser = QasmParser()
2302
+
2303
+ q0, q1 = cirq.NamedQubit('q_0'), cirq.NamedQubit('q_1')
2304
+
2305
+ expected_circuit = Circuit()
2306
+ expected_circuit.append(cirq.ControlledGate(cirq.ry(np.pi / 7)).on(q0, q1))
2307
+
2308
+ parsed_qasm = parser.parse(qasm)
2309
+
2310
+ assert parsed_qasm.supportedFormat
2311
+ assert parsed_qasm.qelib1Include
2312
+
2313
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
2314
+ assert parsed_qasm.qregs == {'q': 2}
2315
+
2316
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
2317
+
2318
+
2319
+ def test_crz_gate() -> None:
2320
+ qasm = """
2321
+ OPENQASM 2.0;
2322
+ include "qelib1.inc";
2323
+ qreg q[2];
2324
+ crz(pi/7) q[0],q[1];
2325
+ """
2326
+ parser = QasmParser()
2327
+
2328
+ q0, q1 = cirq.NamedQubit('q_0'), cirq.NamedQubit('q_1')
2329
+
2330
+ expected_circuit = Circuit()
2331
+ expected_circuit.append(cirq.ControlledGate(cirq.rz(np.pi / 7)).on(q0, q1))
2332
+
2333
+ parsed_qasm = parser.parse(qasm)
2334
+
2335
+ assert parsed_qasm.supportedFormat
2336
+ assert parsed_qasm.qelib1Include
2337
+
2338
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
2339
+ assert parsed_qasm.qregs == {'q': 2}
2340
+
2341
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(expected_circuit))
2342
+
2343
+
2344
+ def test_iswap_gate() -> None:
2345
+ qasm = """
2346
+ OPENQASM 2.0;
2347
+ include "qelib1.inc";
2348
+ qreg q[2];
2349
+ iswap q[0],q[1];
2350
+ """
2351
+ parser = QasmParser()
2352
+
2353
+ q0, q1 = cirq.NamedQubit('q_0'), cirq.NamedQubit('q_1')
2354
+
2355
+ expected_circuit = Circuit()
2356
+ expected_circuit.append(cirq.ISwapPowGate().on(q0, q1))
2357
+
2358
+ parsed_qasm = parser.parse(qasm)
2359
+
2360
+ assert parsed_qasm.supportedFormat
2361
+ assert parsed_qasm.qelib1Include
2362
+
2363
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
2364
+ assert parsed_qasm.qregs == {'q': 2}
2365
+
2366
+
2367
+ @pytest.mark.parametrize(
2368
+ "qasm_gate,cirq_gate,num_params,num_args",
2369
+ [
2370
+ (name, stmt.cirq_gate, stmt.num_params, stmt.num_args)
2371
+ for name, stmt in QasmParser.qelib_gates.items()
2372
+ ],
2373
+ )
2374
+ @pytest.mark.parametrize(
2375
+ "theta,theta_str", [(np.pi / 4, "pi/4"), (np.pi / 2, "pi/2"), (np.pi, "pi")]
2376
+ )
2377
+ def test_all_qelib_gates_unitary_equivalence(
2378
+ qasm_gate, cirq_gate, num_params, num_args, theta, theta_str
2379
+ ):
2380
+ thetas = [theta] * num_params
2381
+ params_str = f"({','.join(theta_str for _ in range(num_params))})" if num_params else ""
2382
+ qubit_names, qubits = [], []
2383
+ for i in range(num_args):
2384
+ qubit_names.append(f"q[{i}]")
2385
+ qubits.append(cirq.NamedQubit(f"q_{i}"))
2386
+ qasm = f"""
2387
+ OPENQASM 2.0;
2388
+ include "qelib1.inc";
2389
+ qreg q[{num_args}];
2390
+ {qasm_gate}{params_str} {','.join(qubit_names)};
2391
+ """
2392
+
2393
+ parser = QasmParser()
2394
+ parsed_qasm = parser.parse(qasm)
2395
+ if num_params:
2396
+ gate = cirq_gate(thetas)
2397
+ else:
2398
+ gate = cirq_gate
2399
+ expected = Circuit()
2400
+ expected.append(gate.on(*qubits))
2401
+ imported = list(parsed_qasm.circuit.all_operations())[0].gate
2402
+ U_native = cirq.unitary(gate)
2403
+ U_import = cirq.unitary(imported)
2404
+ assert np.allclose(U_import, U_native, atol=1e-8)
2405
+ assert parsed_qasm.qregs == {'q': num_args}