cirq-core 1.4.1__py3-none-any.whl → 1.5.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 (590) hide show
  1. cirq/__init__.py +587 -569
  2. cirq/_compat.py +9 -0
  3. cirq/_compat_test.py +11 -9
  4. cirq/_import.py +7 -8
  5. cirq/_version.py +1 -1
  6. cirq/_version_test.py +1 -1
  7. cirq/circuits/__init__.py +15 -9
  8. cirq/circuits/_block_diagram_drawer.py +1 -2
  9. cirq/circuits/_block_diagram_drawer_test.py +3 -3
  10. cirq/circuits/_box_drawing_character_data.py +0 -1
  11. cirq/circuits/_box_drawing_character_data_test.py +2 -2
  12. cirq/circuits/_bucket_priority_queue.py +0 -1
  13. cirq/circuits/_bucket_priority_queue_test.py +1 -1
  14. cirq/circuits/circuit.py +336 -234
  15. cirq/circuits/circuit_operation.py +102 -52
  16. cirq/circuits/circuit_operation_test.py +85 -4
  17. cirq/circuits/circuit_test.py +101 -32
  18. cirq/circuits/frozen_circuit.py +36 -32
  19. cirq/circuits/insert_strategy.py +10 -0
  20. cirq/circuits/insert_strategy_test.py +20 -0
  21. cirq/circuits/moment.py +79 -80
  22. cirq/circuits/moment_test.py +105 -2
  23. cirq/circuits/optimization_pass.py +15 -15
  24. cirq/circuits/optimization_pass_test.py +8 -9
  25. cirq/circuits/qasm_output.py +64 -33
  26. cirq/circuits/qasm_output_test.py +63 -2
  27. cirq/circuits/text_diagram_drawer.py +26 -56
  28. cirq/circuits/text_diagram_drawer_test.py +5 -4
  29. cirq/contrib/__init__.py +2 -2
  30. cirq/contrib/acquaintance/__init__.py +44 -29
  31. cirq/contrib/acquaintance/bipartite.py +8 -7
  32. cirq/contrib/acquaintance/bipartite_test.py +11 -1
  33. cirq/contrib/acquaintance/devices.py +5 -4
  34. cirq/contrib/acquaintance/devices_test.py +5 -1
  35. cirq/contrib/acquaintance/executor.py +18 -21
  36. cirq/contrib/acquaintance/executor_test.py +3 -2
  37. cirq/contrib/acquaintance/gates.py +36 -27
  38. cirq/contrib/acquaintance/gates_test.py +1 -1
  39. cirq/contrib/acquaintance/inspection_utils.py +10 -9
  40. cirq/contrib/acquaintance/inspection_utils_test.py +6 -1
  41. cirq/contrib/acquaintance/mutation_utils.py +10 -10
  42. cirq/contrib/acquaintance/optimizers.py +7 -6
  43. cirq/contrib/acquaintance/optimizers_test.py +1 -1
  44. cirq/contrib/acquaintance/permutation.py +22 -21
  45. cirq/contrib/acquaintance/permutation_test.py +1 -1
  46. cirq/contrib/acquaintance/shift.py +8 -6
  47. cirq/contrib/acquaintance/shift_swap_network.py +6 -4
  48. cirq/contrib/acquaintance/strategies/__init__.py +9 -3
  49. cirq/contrib/acquaintance/strategies/complete.py +4 -3
  50. cirq/contrib/acquaintance/strategies/cubic.py +5 -3
  51. cirq/contrib/acquaintance/strategies/quartic_paired.py +8 -6
  52. cirq/contrib/acquaintance/topological_sort.py +4 -2
  53. cirq/contrib/bayesian_network/__init__.py +3 -1
  54. cirq/contrib/bayesian_network/bayesian_network_gate.py +5 -3
  55. cirq/contrib/circuitdag/__init__.py +1 -1
  56. cirq/contrib/circuitdag/circuit_dag.py +24 -24
  57. cirq/contrib/circuitdag/circuit_dag_test.py +1 -1
  58. cirq/contrib/custom_simulators/custom_state_simulator.py +10 -8
  59. cirq/contrib/custom_simulators/custom_state_simulator_test.py +15 -11
  60. cirq/contrib/graph_device/__init__.py +8 -8
  61. cirq/contrib/graph_device/graph_device.py +8 -8
  62. cirq/contrib/graph_device/graph_device_test.py +0 -1
  63. cirq/contrib/graph_device/hypergraph_test.py +1 -0
  64. cirq/contrib/json.py +1 -2
  65. cirq/contrib/json_test.py +2 -2
  66. cirq/contrib/noise_models/__init__.py +5 -6
  67. cirq/contrib/noise_models/noise_models.py +8 -6
  68. cirq/contrib/paulistring/__init__.py +22 -10
  69. cirq/contrib/paulistring/clifford_optimize.py +1 -1
  70. cirq/contrib/paulistring/clifford_optimize_test.py +0 -1
  71. cirq/contrib/paulistring/clifford_target_gateset.py +15 -12
  72. cirq/contrib/paulistring/optimize.py +2 -2
  73. cirq/contrib/paulistring/optimize_test.py +0 -1
  74. cirq/contrib/paulistring/pauli_string_dag_test.py +0 -1
  75. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +379 -0
  76. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +523 -0
  77. cirq/contrib/paulistring/pauli_string_optimize.py +3 -1
  78. cirq/contrib/paulistring/pauli_string_optimize_test.py +1 -3
  79. cirq/contrib/paulistring/recombine.py +2 -2
  80. cirq/contrib/paulistring/recombine_test.py +2 -2
  81. cirq/contrib/paulistring/separate.py +3 -4
  82. cirq/contrib/qasm_import/__init__.py +2 -2
  83. cirq/contrib/qasm_import/_lexer.py +21 -26
  84. cirq/contrib/qasm_import/_lexer_test.py +90 -6
  85. cirq/contrib/qasm_import/_parser.py +238 -47
  86. cirq/contrib/qasm_import/_parser_test.py +514 -59
  87. cirq/contrib/qasm_import/qasm_test.py +1 -1
  88. cirq/contrib/qcircuit/__init__.py +6 -4
  89. cirq/contrib/qcircuit/qcircuit_diagram.py +5 -2
  90. cirq/contrib/qcircuit/qcircuit_pdf.py +1 -2
  91. cirq/{experiments/grid_parallel_two_qubit_xeb_test.py → contrib/qcircuit/qcircuit_pdf_test.py} +13 -12
  92. cirq/contrib/qcircuit/qcircuit_test.py +1 -1
  93. cirq/contrib/quantum_volume/__init__.py +7 -7
  94. cirq/contrib/quantum_volume/quantum_volume.py +6 -11
  95. cirq/contrib/quantum_volume/quantum_volume_test.py +3 -1
  96. cirq/contrib/quimb/__init__.py +16 -13
  97. cirq/contrib/quimb/density_matrix.py +1 -1
  98. cirq/contrib/quimb/mps_simulator.py +27 -28
  99. cirq/contrib/quimb/mps_simulator_test.py +5 -0
  100. cirq/contrib/quimb/state_vector.py +3 -10
  101. cirq/contrib/quirk/__init__.py +1 -1
  102. cirq/contrib/quirk/export_to_quirk.py +3 -3
  103. cirq/contrib/routing/__init__.py +12 -9
  104. cirq/contrib/routing/device.py +1 -1
  105. cirq/contrib/routing/device_test.py +1 -2
  106. cirq/contrib/routing/greedy.py +7 -5
  107. cirq/contrib/routing/greedy_test.py +5 -3
  108. cirq/contrib/routing/initialization.py +3 -1
  109. cirq/contrib/routing/initialization_test.py +1 -1
  110. cirq/contrib/routing/swap_network.py +6 -6
  111. cirq/contrib/routing/utils.py +6 -4
  112. cirq/contrib/routing/utils_test.py +1 -2
  113. cirq/{type_workarounds.py → contrib/shuffle_circuits/__init__.py} +5 -10
  114. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +250 -0
  115. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking_test.py +363 -0
  116. cirq/contrib/svg/__init__.py +1 -1
  117. cirq/contrib/svg/svg.py +12 -10
  118. cirq/contrib/svg/svg_test.py +3 -2
  119. cirq/devices/__init__.py +34 -25
  120. cirq/devices/device.py +16 -12
  121. cirq/devices/device_test.py +1 -0
  122. cirq/devices/grid_device_metadata.py +16 -12
  123. cirq/devices/grid_device_metadata_test.py +2 -1
  124. cirq/devices/grid_qubit.py +31 -26
  125. cirq/devices/grid_qubit_test.py +30 -1
  126. cirq/devices/insertion_noise_model.py +6 -6
  127. cirq/devices/insertion_noise_model_test.py +1 -1
  128. cirq/devices/line_qubit.py +28 -20
  129. cirq/devices/line_qubit_test.py +26 -0
  130. cirq/devices/named_topologies.py +12 -10
  131. cirq/devices/named_topologies_test.py +5 -4
  132. cirq/devices/noise_model.py +29 -33
  133. cirq/devices/noise_properties.py +2 -2
  134. cirq/devices/noise_properties_test.py +2 -2
  135. cirq/devices/noise_utils.py +3 -3
  136. cirq/devices/superconducting_qubits_noise_properties.py +2 -2
  137. cirq/devices/superconducting_qubits_noise_properties_test.py +3 -3
  138. cirq/devices/thermal_noise_model.py +2 -1
  139. cirq/devices/unconstrained_device.py +1 -1
  140. cirq/devices/unconstrained_device_test.py +6 -0
  141. cirq/experiments/__init__.py +51 -34
  142. cirq/experiments/qubit_characterizations.py +17 -15
  143. cirq/experiments/qubit_characterizations_test.py +4 -6
  144. cirq/experiments/random_quantum_circuit_generation.py +10 -9
  145. cirq/experiments/random_quantum_circuit_generation_test.py +21 -4
  146. cirq/experiments/readout_confusion_matrix.py +73 -8
  147. cirq/experiments/readout_confusion_matrix_test.py +104 -1
  148. cirq/experiments/single_qubit_readout_calibration.py +8 -6
  149. cirq/experiments/single_qubit_readout_calibration_test.py +1 -1
  150. cirq/experiments/t1_decay_experiment.py +4 -5
  151. cirq/experiments/t1_decay_experiment_test.py +1 -2
  152. cirq/experiments/t2_decay_experiment.py +0 -1
  153. cirq/experiments/t2_decay_experiment_test.py +1 -2
  154. cirq/experiments/two_qubit_xeb.py +157 -33
  155. cirq/experiments/two_qubit_xeb_test.py +38 -22
  156. cirq/experiments/xeb_fitting.py +99 -19
  157. cirq/experiments/xeb_fitting_test.py +64 -25
  158. cirq/experiments/xeb_sampling.py +14 -18
  159. cirq/experiments/xeb_simulation.py +4 -3
  160. cirq/experiments/xeb_simulation_test.py +20 -14
  161. cirq/experiments/z_phase_calibration.py +368 -0
  162. cirq/experiments/z_phase_calibration_test.py +241 -0
  163. cirq/interop/__init__.py +4 -1
  164. cirq/interop/quirk/__init__.py +7 -4
  165. cirq/interop/quirk/cells/__init__.py +17 -6
  166. cirq/interop/quirk/cells/arithmetic_cells.py +8 -8
  167. cirq/interop/quirk/cells/arithmetic_cells_test.py +1 -1
  168. cirq/interop/quirk/cells/cell.py +6 -6
  169. cirq/interop/quirk/cells/composite_cell.py +5 -5
  170. cirq/interop/quirk/cells/composite_cell_test.py +1 -1
  171. cirq/interop/quirk/cells/control_cells.py +1 -1
  172. cirq/interop/quirk/cells/frequency_space_cells.py +2 -2
  173. cirq/interop/quirk/cells/ignored_cells.py +1 -1
  174. cirq/interop/quirk/cells/input_cells.py +1 -1
  175. cirq/interop/quirk/cells/input_cells_test.py +1 -1
  176. cirq/interop/quirk/cells/input_rotation_cells.py +1 -1
  177. cirq/interop/quirk/cells/input_rotation_cells_test.py +1 -1
  178. cirq/interop/quirk/cells/measurement_cells.py +1 -1
  179. cirq/interop/quirk/cells/parse.py +8 -7
  180. cirq/interop/quirk/cells/parse_test.py +2 -2
  181. cirq/interop/quirk/cells/single_qubit_rotation_cells.py +1 -1
  182. cirq/interop/quirk/cells/swap_cell_test.py +1 -1
  183. cirq/interop/quirk/cells/unsupported_cells.py +1 -1
  184. cirq/interop/quirk/url_to_circuit.py +7 -7
  185. cirq/interop/quirk/url_to_circuit_test.py +1 -1
  186. cirq/ion/__init__.py +4 -2
  187. cirq/json_resolver_cache.py +15 -7
  188. cirq/linalg/__init__.py +62 -51
  189. cirq/linalg/combinators.py +4 -4
  190. cirq/linalg/combinators_test.py +4 -1
  191. cirq/linalg/decompositions.py +15 -40
  192. cirq/linalg/decompositions_test.py +16 -22
  193. cirq/linalg/diagonalize.py +1 -1
  194. cirq/linalg/diagonalize_test.py +1 -1
  195. cirq/linalg/operator_spaces.py +20 -4
  196. cirq/linalg/operator_spaces_test.py +15 -2
  197. cirq/linalg/predicates.py +3 -3
  198. cirq/linalg/predicates_test.py +1 -0
  199. cirq/linalg/tolerance.py +2 -2
  200. cirq/linalg/transformations.py +30 -12
  201. cirq/linalg/transformations_test.py +13 -0
  202. cirq/neutral_atoms/__init__.py +2 -2
  203. cirq/neutral_atoms/convert_to_neutral_atom_gates_test.py +0 -1
  204. cirq/ops/__init__.py +172 -132
  205. cirq/ops/arithmetic_operation.py +2 -2
  206. cirq/ops/arithmetic_operation_test.py +2 -2
  207. cirq/ops/boolean_hamiltonian.py +3 -2
  208. cirq/ops/classically_controlled_operation.py +39 -12
  209. cirq/ops/classically_controlled_operation_test.py +147 -1
  210. cirq/ops/clifford_gate.py +38 -36
  211. cirq/ops/clifford_gate_test.py +75 -1
  212. cirq/ops/common_channels.py +16 -45
  213. cirq/ops/common_channels_test.py +10 -0
  214. cirq/ops/common_gate_families.py +1 -1
  215. cirq/ops/common_gate_families_test.py +1 -0
  216. cirq/ops/common_gates.py +48 -49
  217. cirq/ops/common_gates_test.py +18 -2
  218. cirq/ops/control_values.py +3 -3
  219. cirq/ops/control_values_test.py +2 -1
  220. cirq/ops/controlled_gate.py +36 -23
  221. cirq/ops/controlled_gate_test.py +70 -3
  222. cirq/ops/controlled_operation.py +6 -5
  223. cirq/ops/controlled_operation_test.py +7 -3
  224. cirq/ops/dense_pauli_string.py +11 -11
  225. cirq/ops/diagonal_gate.py +2 -2
  226. cirq/ops/diagonal_gate_test.py +1 -0
  227. cirq/ops/eigen_gate.py +16 -36
  228. cirq/ops/eigen_gate_test.py +60 -10
  229. cirq/ops/fourier_transform.py +1 -3
  230. cirq/ops/fourier_transform_test.py +2 -1
  231. cirq/ops/fsim_gate.py +42 -3
  232. cirq/ops/fsim_gate_test.py +21 -0
  233. cirq/ops/gate_operation.py +8 -8
  234. cirq/ops/gate_operation_test.py +4 -2
  235. cirq/ops/gateset_test.py +11 -2
  236. cirq/ops/global_phase_op.py +8 -7
  237. cirq/ops/global_phase_op_test.py +1 -1
  238. cirq/ops/greedy_qubit_manager_test.py +5 -0
  239. cirq/ops/identity.py +14 -4
  240. cirq/ops/identity_test.py +24 -0
  241. cirq/ops/kraus_channel.py +1 -0
  242. cirq/ops/kraus_channel_test.py +3 -1
  243. cirq/ops/linear_combinations.py +27 -21
  244. cirq/ops/linear_combinations_test.py +23 -4
  245. cirq/ops/matrix_gates.py +24 -8
  246. cirq/ops/measure_util.py +2 -2
  247. cirq/ops/measurement_gate.py +7 -4
  248. cirq/ops/measurement_gate_test.py +2 -1
  249. cirq/ops/mixed_unitary_channel.py +1 -0
  250. cirq/ops/mixed_unitary_channel_test.py +3 -1
  251. cirq/ops/named_qubit.py +8 -1
  252. cirq/ops/op_tree.py +3 -30
  253. cirq/ops/op_tree_test.py +4 -0
  254. cirq/ops/parallel_gate.py +2 -3
  255. cirq/ops/parallel_gate_test.py +2 -1
  256. cirq/ops/parity_gates.py +7 -8
  257. cirq/ops/parity_gates_test.py +1 -0
  258. cirq/ops/pauli_gates.py +5 -11
  259. cirq/ops/pauli_gates_test.py +1 -0
  260. cirq/ops/pauli_interaction_gate.py +11 -5
  261. cirq/ops/pauli_interaction_gate_test.py +2 -3
  262. cirq/ops/pauli_measurement_gate.py +6 -5
  263. cirq/ops/pauli_measurement_gate_test.py +1 -0
  264. cirq/ops/pauli_string.py +115 -130
  265. cirq/ops/pauli_string_phasor.py +21 -20
  266. cirq/ops/pauli_string_phasor_test.py +13 -3
  267. cirq/ops/pauli_string_raw_types.py +1 -0
  268. cirq/ops/pauli_string_test.py +192 -55
  269. cirq/ops/pauli_sum_exponential.py +3 -4
  270. cirq/ops/pauli_sum_exponential_test.py +0 -1
  271. cirq/ops/permutation_gate.py +2 -2
  272. cirq/ops/permutation_gate_test.py +1 -1
  273. cirq/ops/phased_iswap_gate.py +6 -7
  274. cirq/ops/phased_iswap_gate_test.py +21 -5
  275. cirq/ops/phased_x_gate.py +11 -25
  276. cirq/ops/phased_x_gate_test.py +19 -3
  277. cirq/ops/phased_x_z_gate.py +12 -11
  278. cirq/ops/projector.py +4 -5
  279. cirq/ops/qubit_manager.py +2 -1
  280. cirq/ops/qubit_manager_test.py +2 -1
  281. cirq/ops/qubit_order.py +1 -1
  282. cirq/ops/random_gate_channel.py +1 -1
  283. cirq/ops/random_gate_channel_test.py +0 -6
  284. cirq/ops/raw_types.py +146 -50
  285. cirq/ops/raw_types_test.py +37 -3
  286. cirq/ops/state_preparation_channel.py +2 -2
  287. cirq/ops/state_preparation_channel_test.py +2 -1
  288. cirq/ops/swap_gates.py +9 -4
  289. cirq/ops/three_qubit_gates.py +8 -8
  290. cirq/ops/three_qubit_gates_test.py +1 -0
  291. cirq/ops/two_qubit_diagonal_gate.py +4 -3
  292. cirq/ops/uniform_superposition_gate.py +4 -4
  293. cirq/ops/uniform_superposition_gate_test.py +1 -0
  294. cirq/ops/wait_gate.py +6 -8
  295. cirq/protocols/__init__.py +135 -83
  296. cirq/protocols/act_on_protocol.py +1 -1
  297. cirq/protocols/act_on_protocol_test.py +1 -1
  298. cirq/protocols/apply_channel_protocol.py +3 -3
  299. cirq/protocols/apply_mixture_protocol.py +15 -9
  300. cirq/protocols/apply_mixture_protocol_test.py +11 -0
  301. cirq/protocols/apply_unitary_protocol.py +2 -2
  302. cirq/protocols/apply_unitary_protocol_test.py +2 -1
  303. cirq/protocols/approximate_equality_protocol.py +7 -8
  304. cirq/protocols/approximate_equality_protocol_test.py +3 -1
  305. cirq/protocols/circuit_diagram_info_protocol.py +8 -6
  306. cirq/protocols/circuit_diagram_info_protocol_test.py +5 -0
  307. cirq/protocols/commutes_protocol.py +6 -6
  308. cirq/protocols/control_key_protocol.py +1 -1
  309. cirq/protocols/decompose_protocol.py +4 -5
  310. cirq/protocols/decompose_protocol_test.py +2 -1
  311. cirq/protocols/equal_up_to_global_phase_protocol.py +3 -3
  312. cirq/protocols/equal_up_to_global_phase_protocol_test.py +7 -0
  313. cirq/protocols/has_stabilizer_effect_protocol.py +5 -5
  314. cirq/protocols/has_unitary_protocol.py +1 -1
  315. cirq/protocols/has_unitary_protocol_test.py +8 -7
  316. cirq/protocols/hash_from_pickle_test.py +120 -0
  317. cirq/protocols/inverse_protocol.py +1 -1
  318. cirq/protocols/json_serialization.py +14 -1
  319. cirq/protocols/json_serialization_test.py +28 -7
  320. cirq/protocols/json_test_data/BitMaskKeyCondition.json +86 -0
  321. cirq/protocols/json_test_data/BitMaskKeyCondition.repr +7 -0
  322. cirq/protocols/json_test_data/Concat.json +19 -0
  323. cirq/protocols/json_test_data/Concat.repr +1 -0
  324. cirq/protocols/json_test_data/README.md +4 -2
  325. cirq/protocols/json_test_data/SympyCondition.json +60 -15
  326. cirq/protocols/json_test_data/SympyCondition.repr +4 -1
  327. cirq/protocols/json_test_data/_InverseCompositeGate.json +10 -0
  328. cirq/protocols/json_test_data/_InverseCompositeGate.repr +1 -0
  329. cirq/protocols/json_test_data/__init__.py +1 -1
  330. cirq/protocols/json_test_data/sympy.And.json +13 -0
  331. cirq/protocols/json_test_data/sympy.And.repr +1 -0
  332. cirq/protocols/json_test_data/sympy.Indexed.json +18 -0
  333. cirq/protocols/json_test_data/sympy.Indexed.repr +1 -0
  334. cirq/protocols/json_test_data/sympy.IndexedBase.json +9 -0
  335. cirq/protocols/json_test_data/sympy.IndexedBase.repr +1 -0
  336. cirq/protocols/json_test_data/sympy.Not.json +9 -0
  337. cirq/protocols/json_test_data/sympy.Not.repr +1 -0
  338. cirq/protocols/json_test_data/sympy.Or.json +13 -0
  339. cirq/protocols/json_test_data/sympy.Or.repr +1 -0
  340. cirq/protocols/json_test_data/sympy.Xor.json +13 -0
  341. cirq/protocols/json_test_data/sympy.Xor.repr +1 -0
  342. cirq/protocols/kraus_protocol.py +8 -8
  343. cirq/protocols/kraus_protocol_test.py +0 -1
  344. cirq/protocols/measurement_key_protocol.py +1 -1
  345. cirq/protocols/measurement_key_protocol_test.py +7 -7
  346. cirq/protocols/mixture_protocol.py +6 -4
  347. cirq/protocols/mixture_protocol_test.py +21 -13
  348. cirq/protocols/pauli_expansion_protocol.py +1 -0
  349. cirq/protocols/pow_protocol.py +1 -1
  350. cirq/protocols/qasm.py +25 -6
  351. cirq/protocols/qasm_test.py +17 -0
  352. cirq/protocols/qid_shape_protocol.py +2 -2
  353. cirq/protocols/resolve_parameters.py +2 -3
  354. cirq/protocols/resolve_parameters_test.py +2 -1
  355. cirq/protocols/trace_distance_bound.py +1 -1
  356. cirq/protocols/trace_distance_bound_test.py +1 -0
  357. cirq/protocols/unitary_protocol.py +3 -3
  358. cirq/protocols/unitary_protocol_test.py +1 -1
  359. cirq/qis/__init__.py +48 -35
  360. cirq/qis/channels_test.py +0 -9
  361. cirq/qis/clifford_tableau.py +46 -26
  362. cirq/qis/clifford_tableau_test.py +2 -1
  363. cirq/qis/entropy.py +115 -0
  364. cirq/qis/entropy_test.py +43 -0
  365. cirq/qis/measures.py +5 -4
  366. cirq/qis/measures_test.py +7 -0
  367. cirq/qis/noise_utils_test.py +4 -4
  368. cirq/qis/quantum_state_representation.py +1 -1
  369. cirq/qis/states.py +7 -7
  370. cirq/sim/__init__.py +55 -37
  371. cirq/sim/classical_simulator.py +7 -6
  372. cirq/sim/classical_simulator_test.py +3 -1
  373. cirq/sim/clifford/__init__.py +17 -9
  374. cirq/sim/clifford/clifford_simulator.py +5 -4
  375. cirq/sim/clifford/clifford_simulator_test.py +32 -9
  376. cirq/sim/clifford/clifford_tableau_simulation_state.py +1 -1
  377. cirq/sim/clifford/stabilizer_simulation_state.py +1 -1
  378. cirq/sim/clifford/stabilizer_state_ch_form.py +4 -3
  379. cirq/sim/density_matrix_simulator.py +3 -2
  380. cirq/sim/density_matrix_simulator_test.py +12 -4
  381. cirq/sim/density_matrix_utils.py +1 -1
  382. cirq/sim/mux.py +2 -2
  383. cirq/sim/simulation_state.py +4 -5
  384. cirq/sim/simulation_state_base.py +2 -2
  385. cirq/sim/simulation_state_test.py +1 -1
  386. cirq/sim/simulation_utils.py +3 -1
  387. cirq/sim/simulation_utils_test.py +2 -3
  388. cirq/sim/simulator.py +7 -6
  389. cirq/sim/simulator_base.py +5 -5
  390. cirq/sim/simulator_test.py +14 -3
  391. cirq/sim/sparse_simulator.py +4 -3
  392. cirq/sim/sparse_simulator_test.py +17 -9
  393. cirq/sim/state_vector.py +2 -2
  394. cirq/sim/state_vector_simulation_state_test.py +1 -1
  395. cirq/sim/state_vector_simulator.py +4 -4
  396. cirq/sim/state_vector_test.py +27 -32
  397. cirq/study/__init__.py +27 -21
  398. cirq/study/flatten_expressions.py +5 -6
  399. cirq/study/flatten_expressions_test.py +1 -1
  400. cirq/study/resolver.py +14 -11
  401. cirq/study/resolver_test.py +10 -1
  402. cirq/study/result.py +3 -3
  403. cirq/study/sweepable.py +15 -9
  404. cirq/study/sweepable_test.py +27 -0
  405. cirq/study/sweeps.py +65 -10
  406. cirq/study/sweeps_test.py +123 -0
  407. cirq/testing/__init__.py +86 -57
  408. cirq/testing/_compat_test_data/module_a/__init__.py +2 -2
  409. cirq/testing/_compat_test_data/module_a/sub/subsub/__init__.py +1 -1
  410. cirq/testing/circuit_compare.py +3 -4
  411. cirq/testing/circuit_compare_test.py +7 -8
  412. cirq/testing/consistent_act_on.py +3 -3
  413. cirq/testing/consistent_channels_test.py +2 -1
  414. cirq/testing/consistent_controlled_gate_op.py +3 -2
  415. cirq/testing/consistent_controlled_gate_op_test.py +2 -3
  416. cirq/testing/consistent_decomposition.py +1 -1
  417. cirq/testing/consistent_decomposition_test.py +1 -2
  418. cirq/testing/consistent_pauli_expansion_test.py +1 -1
  419. cirq/testing/consistent_phase_by.py +1 -1
  420. cirq/testing/consistent_phase_by_test.py +1 -2
  421. cirq/testing/consistent_protocols.py +11 -11
  422. cirq/testing/consistent_protocols_test.py +4 -5
  423. cirq/testing/consistent_qasm.py +8 -12
  424. cirq/testing/consistent_qasm_test.py +1 -1
  425. cirq/testing/consistent_resolve_parameters.py +2 -1
  426. cirq/testing/consistent_specified_has_unitary_test.py +1 -1
  427. cirq/testing/consistent_unitary.py +3 -1
  428. cirq/testing/consistent_unitary_test.py +3 -3
  429. cirq/testing/devices.py +1 -1
  430. cirq/testing/devices_test.py +1 -0
  431. cirq/testing/equals_tester.py +2 -4
  432. cirq/testing/equals_tester_test.py +6 -5
  433. cirq/testing/equivalent_basis_map.py +1 -0
  434. cirq/testing/equivalent_basis_map_test.py +0 -1
  435. cirq/testing/gate_features_test.py +5 -0
  436. cirq/testing/json.py +4 -4
  437. cirq/testing/lin_alg_utils_test.py +1 -1
  438. cirq/testing/order_tester.py +1 -1
  439. cirq/testing/order_tester_test.py +1 -1
  440. cirq/testing/pytest_utils.py +57 -0
  441. cirq/testing/pytest_utils_test.py +35 -0
  442. cirq/testing/random_circuit.py +2 -2
  443. cirq/testing/random_circuit_test.py +2 -2
  444. cirq/testing/routing_devices_test.py +2 -1
  445. cirq/testing/sample_circuits.py +1 -1
  446. cirq/testing/sample_gates.py +5 -4
  447. cirq/testing/sample_gates_test.py +2 -2
  448. cirq/transformers/__init__.py +101 -82
  449. cirq/transformers/align.py +12 -1
  450. cirq/transformers/align_test.py +13 -0
  451. cirq/transformers/analytical_decompositions/__init__.py +27 -24
  452. cirq/transformers/analytical_decompositions/clifford_decomposition.py +2 -1
  453. cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +1 -1
  454. cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +1 -1
  455. cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +2 -0
  456. cirq/transformers/analytical_decompositions/cphase_to_fsim.py +1 -1
  457. cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +1 -1
  458. cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +2 -2
  459. cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +4 -4
  460. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +99 -24
  461. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +105 -14
  462. cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +1 -1
  463. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +1 -1
  464. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +1 -0
  465. cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +3 -4
  466. cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +1 -1
  467. cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +2 -1
  468. cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +2 -1
  469. cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +5 -6
  470. cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +2 -2
  471. cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +1 -1
  472. cirq/transformers/analytical_decompositions/two_qubit_to_fsim_test.py +1 -2
  473. cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +2 -2
  474. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +2 -2
  475. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +2 -1
  476. cirq/transformers/drop_empty_moments.py +1 -0
  477. cirq/transformers/drop_negligible_operations.py +1 -0
  478. cirq/transformers/dynamical_decoupling.py +255 -43
  479. cirq/transformers/dynamical_decoupling_test.py +730 -17
  480. cirq/transformers/eject_phased_paulis.py +29 -15
  481. cirq/transformers/eject_phased_paulis_test.py +3 -8
  482. cirq/transformers/eject_z.py +3 -2
  483. cirq/transformers/eject_z_test.py +3 -3
  484. cirq/transformers/gauge_compiling/__init__.py +25 -9
  485. cirq/transformers/gauge_compiling/cphase_gauge.py +146 -0
  486. cirq/transformers/gauge_compiling/cphase_gauge_test.py +42 -0
  487. cirq/transformers/gauge_compiling/cz_gauge.py +4 -4
  488. cirq/transformers/gauge_compiling/gauge_compiling.py +245 -6
  489. cirq/transformers/gauge_compiling/gauge_compiling_test.py +107 -2
  490. cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +39 -2
  491. cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +10 -1
  492. cirq/transformers/gauge_compiling/iswap_gauge.py +2 -2
  493. cirq/transformers/gauge_compiling/spin_inversion_gauge.py +2 -2
  494. cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +23 -5
  495. cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +3 -2
  496. cirq/transformers/heuristic_decompositions/__init__.py +3 -3
  497. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +2 -1
  498. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +1 -1
  499. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +4 -4
  500. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation_test.py +4 -4
  501. cirq/transformers/insertion_sort.py +64 -0
  502. cirq/transformers/insertion_sort_test.py +34 -0
  503. cirq/transformers/measurement_transformers.py +14 -1
  504. cirq/transformers/measurement_transformers_test.py +35 -0
  505. cirq/transformers/merge_k_qubit_gates.py +2 -2
  506. cirq/transformers/merge_single_qubit_gates.py +1 -1
  507. cirq/transformers/merge_single_qubit_gates_test.py +1 -1
  508. cirq/transformers/noise_adding.py +115 -0
  509. cirq/transformers/noise_adding_test.py +54 -0
  510. cirq/transformers/optimize_for_target_gateset.py +1 -1
  511. cirq/transformers/optimize_for_target_gateset_test.py +3 -2
  512. cirq/transformers/qubit_management_transformers.py +1 -1
  513. cirq/transformers/randomized_measurements.py +171 -0
  514. cirq/transformers/randomized_measurements_test.py +68 -0
  515. cirq/transformers/routing/__init__.py +14 -5
  516. cirq/transformers/routing/initial_mapper.py +1 -1
  517. cirq/transformers/routing/initial_mapper_test.py +1 -0
  518. cirq/transformers/routing/line_initial_mapper.py +3 -2
  519. cirq/transformers/routing/mapping_manager.py +2 -2
  520. cirq/transformers/routing/mapping_manager_test.py +2 -2
  521. cirq/transformers/routing/route_circuit_cqc.py +3 -2
  522. cirq/transformers/routing/route_circuit_cqc_test.py +2 -1
  523. cirq/transformers/routing/visualize_routed_circuit.py +1 -0
  524. cirq/transformers/routing/visualize_routed_circuit_test.py +1 -0
  525. cirq/transformers/stratify.py +2 -2
  526. cirq/transformers/synchronize_terminal_measurements.py +2 -1
  527. cirq/transformers/target_gatesets/__init__.py +7 -5
  528. cirq/transformers/target_gatesets/compilation_target_gateset.py +16 -3
  529. cirq/transformers/target_gatesets/compilation_target_gateset_test.py +2 -0
  530. cirq/transformers/target_gatesets/cz_gateset.py +5 -1
  531. cirq/transformers/target_gatesets/cz_gateset_test.py +23 -2
  532. cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +1 -1
  533. cirq/transformers/target_gatesets/sqrt_iswap_gateset_test.py +3 -2
  534. cirq/transformers/transformer_api.py +5 -4
  535. cirq/transformers/transformer_api_test.py +11 -3
  536. cirq/transformers/transformer_primitives.py +9 -31
  537. cirq/transformers/transformer_primitives_test.py +6 -5
  538. cirq/value/__init__.py +51 -30
  539. cirq/value/abc_alt.py +1 -2
  540. cirq/value/angle.py +2 -0
  541. cirq/value/classical_data.py +1 -0
  542. cirq/value/condition.py +149 -3
  543. cirq/value/condition_test.py +254 -0
  544. cirq/value/digits.py +1 -1
  545. cirq/value/duration.py +4 -4
  546. cirq/value/duration_test.py +2 -1
  547. cirq/value/linear_dict.py +85 -24
  548. cirq/value/linear_dict_test.py +94 -3
  549. cirq/value/measurement_key.py +9 -2
  550. cirq/value/periodic_value.py +2 -3
  551. cirq/value/periodic_value_test.py +5 -0
  552. cirq/value/probability.py +1 -0
  553. cirq/value/random_state.py +1 -1
  554. cirq/value/timestamp.py +2 -4
  555. cirq/value/timestamp_test.py +2 -1
  556. cirq/value/type_alias.py +2 -2
  557. cirq/value/value_equality_attr.py +14 -2
  558. cirq/value/value_equality_attr_test.py +1 -1
  559. cirq/vis/__init__.py +9 -6
  560. cirq/vis/density_matrix.py +1 -1
  561. cirq/vis/density_matrix_test.py +2 -5
  562. cirq/vis/heatmap.py +49 -12
  563. cirq/vis/heatmap_test.py +168 -4
  564. cirq/vis/histogram.py +1 -1
  565. cirq/vis/histogram_test.py +1 -2
  566. cirq/vis/state_histogram.py +7 -5
  567. cirq/vis/state_histogram_test.py +2 -2
  568. cirq/work/__init__.py +19 -13
  569. cirq/work/collector.py +2 -2
  570. cirq/work/observable_grouping.py +2 -2
  571. cirq/work/observable_measurement.py +3 -3
  572. cirq/work/observable_measurement_data.py +5 -2
  573. cirq/work/observable_measurement_test.py +8 -8
  574. cirq/work/observable_readout_calibration.py +2 -2
  575. cirq/work/observable_readout_calibration_test.py +2 -1
  576. cirq/work/observable_settings.py +8 -7
  577. cirq/work/observable_settings_test.py +3 -2
  578. cirq/work/pauli_sum_collector.py +1 -1
  579. cirq/work/sampler.py +8 -20
  580. cirq/work/sampler_test.py +4 -3
  581. cirq/work/zeros_sampler.py +1 -1
  582. cirq_core-1.5.0.dist-info/METADATA +125 -0
  583. {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/RECORD +586 -552
  584. {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/WHEEL +1 -1
  585. cirq/experiments/grid_parallel_two_qubit_xeb.py +0 -62
  586. cirq/protocols/json_test_data/GridParallelXEBMetadata.json +0 -119
  587. cirq/protocols/json_test_data/GridParallelXEBMetadata.repr +0 -1
  588. cirq_core-1.4.1.dist-info/METADATA +0 -45
  589. {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/LICENSE +0 -0
  590. {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/top_level.txt +0 -0
@@ -12,19 +12,21 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import re
16
+ import textwrap
15
17
  from typing import Callable
16
18
 
17
19
  import numpy as np
18
20
  import pytest
19
21
  import sympy
20
22
 
21
-
22
23
  import cirq
23
24
  import cirq.testing as ct
24
25
  from cirq import Circuit
25
26
  from cirq.circuits.qasm_output import QasmUGate
26
27
  from cirq.contrib.qasm_import import QasmException
27
28
  from cirq.contrib.qasm_import._parser import QasmParser
29
+ from cirq.testing import consistent_qasm as cq
28
30
 
29
31
 
30
32
  def test_format_header_circuit():
@@ -185,7 +187,7 @@ def test_CX_gate():
185
187
  qreg q2[2];
186
188
  CX q1[0], q1[1];
187
189
  CX q1, q2[0];
188
- CX q2, q1;
190
+ CX q2, q1;
189
191
  """
190
192
  parser = QasmParser()
191
193
 
@@ -389,7 +391,7 @@ def test_U_angles():
389
391
 
390
392
  def test_U_gate_zero_params_error():
391
393
  qasm = """OPENQASM 2.0;
392
- qreg q[2];
394
+ qreg q[2];
393
395
  U q[1];"""
394
396
 
395
397
  parser = QasmParser()
@@ -400,7 +402,7 @@ def test_U_gate_zero_params_error():
400
402
 
401
403
  def test_U_gate_too_much_params_error():
402
404
  qasm = """OPENQASM 2.0;
403
- qreg q[2];
405
+ qreg q[2];
404
406
  U(pi, pi, pi, pi) q[1];"""
405
407
 
406
408
  parser = QasmParser()
@@ -519,9 +521,9 @@ def test_rotation_gates(qasm_gate: str, cirq_gate: Callable[[float], cirq.Gate])
519
521
  def test_rotation_gates_wrong_number_of_args(qasm_gate: str):
520
522
  qasm = f"""
521
523
  OPENQASM 2.0;
522
- include "qelib1.inc";
523
- qreg q[2];
524
- {qasm_gate}(pi) q[0], q[1];
524
+ include "qelib1.inc";
525
+ qreg q[2];
526
+ {qasm_gate}(pi) q[0], q[1];
525
527
  """
526
528
 
527
529
  parser = QasmParser()
@@ -533,9 +535,9 @@ def test_rotation_gates_wrong_number_of_args(qasm_gate: str):
533
535
  @pytest.mark.parametrize('qasm_gate', [g[0] for g in rotation_gates])
534
536
  def test_rotation_gates_zero_params_error(qasm_gate: str):
535
537
  qasm = f"""OPENQASM 2.0;
536
- include "qelib1.inc";
537
- qreg q[2];
538
- {qasm_gate} q[1];
538
+ include "qelib1.inc";
539
+ qreg q[2];
540
+ {qasm_gate} q[1];
539
541
  """
540
542
 
541
543
  parser = QasmParser()
@@ -583,7 +585,7 @@ def test_measure_individual_bits():
583
585
  OPENQASM 2.0;
584
586
  include "qelib1.inc";
585
587
  qreg q1[2];
586
- creg c1[2];
588
+ creg c1[2];
587
589
  measure q1[0] -> c1[0];
588
590
  measure q1[1] -> c1[1];
589
591
  """
@@ -611,8 +613,8 @@ def test_measure_registers():
611
613
  qasm = """OPENQASM 2.0;
612
614
  include "qelib1.inc";
613
615
  qreg q1[3];
614
- creg c1[3];
615
- measure q1 -> c1;
616
+ creg c1[3];
617
+ measure q1 -> c1;
616
618
  """
617
619
  parser = QasmParser()
618
620
 
@@ -638,10 +640,10 @@ def test_measure_registers():
638
640
 
639
641
  def test_measure_mismatched_register_size():
640
642
  qasm = """OPENQASM 2.0;
641
- include "qelib1.inc";
643
+ include "qelib1.inc";
642
644
  qreg q1[2];
643
- creg c1[3];
644
- measure q1 -> c1;
645
+ creg c1[3];
646
+ measure q1 -> c1;
645
647
  """
646
648
 
647
649
  parser = QasmParser()
@@ -652,11 +654,11 @@ def test_measure_mismatched_register_size():
652
654
 
653
655
  def test_measure_to_quantum_register():
654
656
  qasm = """OPENQASM 2.0;
655
- include "qelib1.inc";
657
+ include "qelib1.inc";
656
658
  qreg q1[3];
657
659
  qreg q2[3];
658
- creg c1[3];
659
- measure q2 -> q1;
660
+ creg c1[3];
661
+ measure q2 -> q1;
660
662
  """
661
663
 
662
664
  parser = QasmParser()
@@ -667,10 +669,10 @@ def test_measure_to_quantum_register():
667
669
 
668
670
  def test_measure_undefined_classical_bit():
669
671
  qasm = """OPENQASM 2.0;
670
- include "qelib1.inc";
671
- qreg q1[3];
672
- creg c1[3];
673
- measure q1[1] -> c2[1];
672
+ include "qelib1.inc";
673
+ qreg q1[3];
674
+ creg c1[3];
675
+ measure q1[1] -> c2[1];
674
676
  """
675
677
 
676
678
  parser = QasmParser()
@@ -681,11 +683,11 @@ def test_measure_undefined_classical_bit():
681
683
 
682
684
  def test_measure_from_classical_register():
683
685
  qasm = """OPENQASM 2.0;
684
- include "qelib1.inc";
686
+ include "qelib1.inc";
685
687
  qreg q1[2];
686
- creg c1[3];
687
- creg c2[3];
688
- measure c1 -> c2;
688
+ creg c1[3];
689
+ creg c2[3];
690
+ measure c1 -> c2;
689
691
  """
690
692
 
691
693
  parser = QasmParser()
@@ -697,8 +699,8 @@ def test_measure_from_classical_register():
697
699
  def test_measurement_bounds():
698
700
  qasm = """OPENQASM 2.0;
699
701
  qreg q1[3];
700
- creg c1[3];
701
- measure q1[0] -> c1[4];
702
+ creg c1[3];
703
+ measure q1[0] -> c1[4];
702
704
  """
703
705
  parser = QasmParser()
704
706
 
@@ -706,12 +708,41 @@ def test_measurement_bounds():
706
708
  parser.parse(qasm)
707
709
 
708
710
 
711
+ def test_reset():
712
+ qasm = textwrap.dedent(
713
+ """\
714
+ OPENQASM 2.0;
715
+ include "qelib1.inc";
716
+ qreg q[1];
717
+ creg c[1];
718
+ x q[0];
719
+ reset q[0];
720
+ measure q[0] -> c[0];
721
+ """
722
+ )
723
+
724
+ parser = QasmParser()
725
+
726
+ q_0 = cirq.NamedQubit('q_0')
727
+
728
+ expected_circuit = Circuit([cirq.X(q_0), cirq.reset(q_0), cirq.measure(q_0, key='c_0')])
729
+
730
+ parsed_qasm = parser.parse(qasm)
731
+
732
+ assert parsed_qasm.supportedFormat
733
+ assert parsed_qasm.qelib1Include
734
+
735
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
736
+ assert parsed_qasm.qregs == {'q': 1}
737
+ assert parsed_qasm.cregs == {'c': 1}
738
+
739
+
709
740
  def test_u1_gate():
710
741
  qasm = """
711
742
  OPENQASM 2.0;
712
743
  include "qelib1.inc";
713
744
  qreg q[1];
714
- u1(pi / 3.0) q[0];
745
+ u1(pi / 3.0) q[0];
715
746
  """
716
747
  parser = QasmParser()
717
748
 
@@ -734,7 +765,7 @@ def test_u2_gate():
734
765
  OPENQASM 2.0;
735
766
  include "qelib1.inc";
736
767
  qreg q[1];
737
- u2(2 * pi, pi / 3.0) q[0];
768
+ u2(2 * pi, pi / 3.0) q[0];
738
769
  """
739
770
  parser = QasmParser()
740
771
 
@@ -757,7 +788,7 @@ def test_id_gate():
757
788
  OPENQASM 2.0;
758
789
  include "qelib1.inc";
759
790
  qreg q[2];
760
- id q;
791
+ id q;
761
792
  """
762
793
  parser = QasmParser()
763
794
 
@@ -816,7 +847,7 @@ def test_r_gate():
816
847
  OPENQASM 2.0;
817
848
  include "qelib1.inc";
818
849
  qreg q[1];
819
- r(pi, pi / 2.0) q[0];
850
+ r(pi, pi / 2.0) q[0];
820
851
  """
821
852
  parser = QasmParser()
822
853
 
@@ -841,9 +872,9 @@ def test_r_gate():
841
872
  def test_standard_single_qubit_gates_wrong_number_of_args(qasm_gate):
842
873
  qasm = f"""
843
874
  OPENQASM 2.0;
844
- include "qelib1.inc";
845
- qreg q[2];
846
- {qasm_gate} q[0], q[1];
875
+ include "qelib1.inc";
876
+ qreg q[2];
877
+ {qasm_gate} q[0], q[1];
847
878
  """
848
879
 
849
880
  parser = QasmParser()
@@ -859,9 +890,9 @@ def test_standard_single_qubit_gates_wrong_number_of_args(qasm_gate):
859
890
  )
860
891
  def test_standard_gates_wrong_params_error(qasm_gate: str, num_params: int):
861
892
  qasm = f"""OPENQASM 2.0;
862
- include "qelib1.inc";
863
- qreg q[2];
864
- {qasm_gate}(pi, 2*pi, 3*pi, 4*pi, 5*pi) q[1];
893
+ include "qelib1.inc";
894
+ qreg q[2];
895
+ {qasm_gate}(pi, 2*pi, 3*pi, 4*pi, 5*pi) q[1];
865
896
  """
866
897
 
867
898
  parser = QasmParser()
@@ -873,9 +904,9 @@ def test_standard_gates_wrong_params_error(qasm_gate: str, num_params: int):
873
904
  return
874
905
 
875
906
  qasm = f"""OPENQASM 2.0;
876
- include "qelib1.inc";
877
- qreg q[2];
878
- {qasm_gate} q[1];
907
+ include "qelib1.inc";
908
+ qreg q[2];
909
+ {qasm_gate} q[1];
879
910
  """
880
911
 
881
912
  parser = QasmParser()
@@ -894,16 +925,24 @@ two_qubit_gates = [
894
925
  ]
895
926
 
896
927
 
928
+ # Mapping of two-qubit gates and `num_params`
929
+ 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,
932
+ ('crz', cirq.ControlledGate(cirq.rz(0.1))): 1,
933
+ }
934
+
935
+
897
936
  @pytest.mark.parametrize('qasm_gate,cirq_gate', two_qubit_gates)
898
937
  def test_two_qubit_gates(qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate):
899
938
  qasm = f"""
900
- OPENQASM 2.0;
901
- include "qelib1.inc";
902
- qreg q1[2];
903
- qreg q2[2];
904
- {qasm_gate} q1[0], q1[1];
905
- {qasm_gate} q1, q2[0];
906
- {qasm_gate} q2, q1;
939
+ OPENQASM 2.0;
940
+ include "qelib1.inc";
941
+ qreg q1[2];
942
+ qreg q2[2];
943
+ {qasm_gate} q1[0], q1[1];
944
+ {qasm_gate} q1, q2[0];
945
+ {qasm_gate} q2, q1;
907
946
  """
908
947
  parser = QasmParser()
909
948
 
@@ -931,11 +970,85 @@ def test_two_qubit_gates(qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate):
931
970
  assert parsed_qasm.qregs == {'q1': 2, 'q2': 2}
932
971
 
933
972
 
934
- @pytest.mark.parametrize('qasm_gate', [g[0] for g in two_qubit_gates])
973
+ @pytest.mark.parametrize(
974
+ 'qasm_gate,cirq_gate,num_params',
975
+ [
976
+ (gate_map[0], gate_map[1], num_param)
977
+ for gate_map, num_param in two_qubit_param_gates.items()
978
+ ],
979
+ )
980
+ def test_two_qubit_param_gates(
981
+ 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)'
984
+ qasm = f"""
985
+ OPENQASM 2.0;
986
+ include "qelib1.inc";
987
+ qreg q1[2];
988
+ qreg q2[2];
989
+ {qasm_gate}{params} q1[0], q1[1];
990
+ {qasm_gate}{params} q1, q2[0];
991
+ {qasm_gate}{params} q2, q1;
992
+ """
993
+ parser = QasmParser()
994
+
995
+ q1_0 = cirq.NamedQubit('q1_0')
996
+ q1_1 = cirq.NamedQubit('q1_1')
997
+ q2_0 = cirq.NamedQubit('q2_0')
998
+ q2_1 = cirq.NamedQubit('q2_1')
999
+
1000
+ expected_circuit = cirq.Circuit()
1001
+ expected_circuit.append(cirq_gate.on(q1_0, q1_1))
1002
+ expected_circuit.append(cirq_gate.on(q1_0, q2_0))
1003
+ expected_circuit.append(cirq_gate.on(q1_1, q2_0))
1004
+ expected_circuit.append(cirq_gate.on(q2_0, q1_0))
1005
+ expected_circuit.append(cirq_gate.on(q2_1, q1_1))
1006
+ parsed_qasm = parser.parse(qasm)
1007
+
1008
+ assert parsed_qasm.supportedFormat
1009
+ assert parsed_qasm.qelib1Include
1010
+
1011
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
1012
+ assert parsed_qasm.qregs == {'q1': 2, 'q2': 2}
1013
+
1014
+
1015
+ @pytest.mark.parametrize(
1016
+ 'qasm_gate', [g[0] for g in two_qubit_gates] + [g[0] for g in two_qubit_param_gates.keys()]
1017
+ )
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"""
1035
+ OPENQASM 2.0;
1036
+ include "qelib1.inc";
1037
+ qreg q[2];
1038
+ {qasm_gate} q[0];
1039
+ """
1040
+
1041
+ parser = QasmParser()
1042
+
1043
+ with pytest.raises(QasmException, match=rf".*{qasm_gate}.* takes 2 arg\(s\).*got.*1.*line 5"):
1044
+ parser.parse(qasm)
1045
+
1046
+
1047
+ @pytest.mark.parametrize('qasm_gate', [g[0] for g in two_qubit_param_gates.keys()])
935
1048
  def test_two_qubit_gates_not_enough_args(qasm_gate: str):
936
1049
  qasm = f"""
937
- OPENQASM 2.0;
938
- include "qelib1.inc";
1050
+ OPENQASM 2.0;
1051
+ include "qelib1.inc";
939
1052
  qreg q[2];
940
1053
  {qasm_gate} q[0];
941
1054
  """
@@ -946,19 +1059,27 @@ def test_two_qubit_gates_not_enough_args(qasm_gate: str):
946
1059
  parser.parse(qasm)
947
1060
 
948
1061
 
949
- @pytest.mark.parametrize('qasm_gate', [g[0] for g in two_qubit_gates])
1062
+ @pytest.mark.parametrize(
1063
+ 'qasm_gate', [g[0] for g in two_qubit_gates] + [g[0] for g in two_qubit_param_gates.keys()]
1064
+ )
950
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
1070
+
951
1071
  qasm = f"""
952
- OPENQASM 2.0;
953
- include "qelib1.inc";
954
- qreg q[2];
955
- {qasm_gate}(pi) q[0],q[1];
956
- """
1072
+ OPENQASM 2.0;
1073
+ include "qelib1.inc";
1074
+ qreg q[2];
1075
+ {qasm_gate}(pi, pi/2, pi/3, pi/4) q[0],q[1];
1076
+ """
957
1077
 
958
1078
  parser = QasmParser()
959
1079
 
960
1080
  with pytest.raises(
961
- QasmException, match=rf".*{qasm_gate}.* takes 0 parameter\(s\).*got.*1.*line 5"
1081
+ QasmException,
1082
+ match=rf".*{qasm_gate}*. takes {num_params_needed} parameter\(s\).*got.*4.*line 5",
962
1083
  ):
963
1084
  parser.parse(qasm)
964
1085
 
@@ -1057,3 +1178,337 @@ def test_single_qubit_gates(qasm_gate: str, cirq_gate: cirq.Gate):
1057
1178
 
1058
1179
  ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
1059
1180
  assert parsed_qasm.qregs == {'q': 2}
1181
+
1182
+
1183
+ def test_openqasm_3_0_qubits():
1184
+ qasm = """OPENQASM 3.0;
1185
+ include "stdgates.inc";
1186
+ qubit[2] q;
1187
+ bit[2] b;
1188
+
1189
+ x q[0];
1190
+
1191
+ b[0] = measure q[0];
1192
+ reset q[0];
1193
+ """
1194
+ parser = QasmParser()
1195
+
1196
+ q0 = cirq.NamedQubit('q_0')
1197
+
1198
+ expected_circuit = Circuit([cirq.X.on(q0), cirq.measure(q0, key='b_0'), cirq.reset(q0)])
1199
+
1200
+ parsed_qasm = parser.parse(qasm)
1201
+
1202
+ assert parsed_qasm.supportedFormat
1203
+
1204
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
1205
+ assert parsed_qasm.qregs == {'q': 2}
1206
+
1207
+
1208
+ def test_openqasm_3_0_scalar_qubit():
1209
+ qasm = """OPENQASM 3.0;
1210
+ include "stdgates.inc";
1211
+ qubit q;
1212
+ bit b;
1213
+
1214
+ x q;
1215
+
1216
+ b = measure q;
1217
+ reset q;
1218
+ """
1219
+ parser = QasmParser()
1220
+
1221
+ q0 = cirq.NamedQubit('q_0')
1222
+
1223
+ expected_circuit = Circuit([cirq.X.on(q0), cirq.measure(q0, key='b_0'), cirq.reset(q0)])
1224
+
1225
+ parsed_qasm = parser.parse(qasm)
1226
+
1227
+ assert parsed_qasm.supportedFormat
1228
+
1229
+ ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
1230
+ assert parsed_qasm.qregs == {'q': 1}
1231
+
1232
+
1233
+ def test_custom_gate():
1234
+ qasm = """OPENQASM 2.0;
1235
+ include "qelib1.inc";
1236
+ qreg q[2];
1237
+ gate g q0, q1 {
1238
+ x q0;
1239
+ y q0;
1240
+ z q1;
1241
+ }
1242
+ g q[0], q[1];
1243
+ g q[1], q[0];
1244
+ """
1245
+
1246
+ # The gate definition should translate to this
1247
+ q0, q1 = cirq.NamedQubit.range(2, prefix='q')
1248
+ g = cirq.FrozenCircuit(cirq.X(q0), cirq.Y(q0), cirq.Z(q1))
1249
+
1250
+ # The outer circuit should then translate to this
1251
+ q_0, q_1 = cirq.NamedQubit.range(2, prefix='q_') # The outer qreg array
1252
+ expected = cirq.Circuit(
1253
+ cirq.CircuitOperation(g, qubit_map={q0: q_0, q1: q_1}),
1254
+ cirq.CircuitOperation(g, qubit_map={q0: q_1, q1: q_0}),
1255
+ )
1256
+
1257
+ # Verify
1258
+ parser = QasmParser()
1259
+ parsed_qasm = parser.parse(qasm)
1260
+ assert parsed_qasm.circuit == expected
1261
+
1262
+ # Sanity check that this unrolls to a valid circuit
1263
+ unrolled_expected = cirq.Circuit(
1264
+ cirq.X(q_0), cirq.Y(q_0), cirq.Z(q_1), cirq.X(q_1), cirq.Y(q_1), cirq.Z(q_0)
1265
+ )
1266
+ unrolled = cirq.align_left(cirq.unroll_circuit_op(parsed_qasm.circuit, tags_to_check=None))
1267
+ assert unrolled == unrolled_expected
1268
+
1269
+ # Sanity check that these have the same unitaries as the QASM.
1270
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(parsed_qasm.circuit))
1271
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(unrolled))
1272
+
1273
+
1274
+ def test_custom_gate_parameterized():
1275
+ qasm = """OPENQASM 2.0;
1276
+ include "qelib1.inc";
1277
+ qreg q[2];
1278
+ gate g(p0, p1) q0, q1 {
1279
+ rx(p0) q0;
1280
+ ry(p0+p1+3) q0;
1281
+ rz(p1) q1;
1282
+ }
1283
+ g(1,2) q[0], q[1];
1284
+ g(0,4) q[1], q[0];
1285
+ """
1286
+
1287
+ # The gate definition should translate to this
1288
+ p0, p1 = sympy.symbols('p0, p1')
1289
+ q0, q1 = cirq.NamedQubit.range(2, prefix='q')
1290
+ g = cirq.FrozenCircuit(
1291
+ cirq.Rx(rads=p0).on(q0), cirq.Ry(rads=p0 + p1 + 3).on(q0), cirq.Rz(rads=p1).on(q1)
1292
+ )
1293
+
1294
+ # The outer circuit should then translate to this
1295
+ q_0, q_1 = cirq.NamedQubit.range(2, prefix='q_') # The outer qreg array
1296
+ expected = cirq.Circuit(
1297
+ cirq.CircuitOperation(g, qubit_map={q0: q_0, q1: q_1}, param_resolver={'p0': 1, 'p1': 2}),
1298
+ cirq.CircuitOperation(g, qubit_map={q0: q_1, q1: q_0}, param_resolver={'p0': 0, 'p1': 4}),
1299
+ )
1300
+
1301
+ # Verify
1302
+ parser = QasmParser()
1303
+ parsed_qasm = parser.parse(qasm)
1304
+ assert parsed_qasm.circuit == expected
1305
+
1306
+ # Sanity check that this unrolls to a valid circuit
1307
+ unrolled_expected = cirq.Circuit(
1308
+ cirq.Rx(rads=1).on(q_0),
1309
+ cirq.Ry(rads=6).on(q_0),
1310
+ cirq.Rz(rads=2).on(q_1),
1311
+ cirq.Rx(rads=0).on(q_1),
1312
+ cirq.Ry(rads=7).on(q_1),
1313
+ cirq.Rz(rads=4).on(q_0),
1314
+ )
1315
+ unrolled = cirq.align_left(cirq.unroll_circuit_op(parsed_qasm.circuit, tags_to_check=None))
1316
+ assert unrolled == unrolled_expected
1317
+
1318
+ # Sanity check that these have the same unitaries as the QASM.
1319
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(parsed_qasm.circuit))
1320
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(unrolled))
1321
+
1322
+
1323
+ def test_custom_gate_broadcast():
1324
+ qasm = """OPENQASM 2.0;
1325
+ include "qelib1.inc";
1326
+ qreg q[3];
1327
+ gate g q0 {
1328
+ x q0;
1329
+ y q0;
1330
+ z q0;
1331
+ }
1332
+ g q; // broadcast to all qubits in register
1333
+ """
1334
+
1335
+ # The gate definition should translate to this
1336
+ q0 = cirq.NamedQubit('q0')
1337
+ g = cirq.FrozenCircuit(cirq.X(q0), cirq.Y(q0), cirq.Z(q0))
1338
+
1339
+ # The outer circuit should then translate to this
1340
+ q_0, q_1, q_2 = cirq.NamedQubit.range(3, prefix='q_') # The outer qreg array
1341
+ expected = cirq.Circuit(
1342
+ # It is broadcast to all qubits in the qreg
1343
+ cirq.CircuitOperation(g, qubit_map={q0: q_0}),
1344
+ cirq.CircuitOperation(g, qubit_map={q0: q_1}),
1345
+ cirq.CircuitOperation(g, qubit_map={q0: q_2}),
1346
+ )
1347
+
1348
+ # Verify
1349
+ parser = QasmParser()
1350
+ parsed_qasm = parser.parse(qasm)
1351
+ assert parsed_qasm.circuit == expected
1352
+
1353
+ # Sanity check that this unrolls to a valid circuit
1354
+ unrolled_expected = cirq.Circuit(
1355
+ cirq.X(q_0),
1356
+ cirq.Y(q_0),
1357
+ cirq.Z(q_0),
1358
+ cirq.X(q_1),
1359
+ cirq.Y(q_1),
1360
+ cirq.Z(q_1),
1361
+ cirq.X(q_2),
1362
+ cirq.Y(q_2),
1363
+ cirq.Z(q_2),
1364
+ )
1365
+ unrolled = cirq.align_left(cirq.unroll_circuit_op(parsed_qasm.circuit, tags_to_check=None))
1366
+ assert unrolled == unrolled_expected
1367
+
1368
+ # Sanity check that these have the same unitaries as the QASM.
1369
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(parsed_qasm.circuit))
1370
+ cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(unrolled))
1371
+
1372
+
1373
+ def test_custom_gate_undefined_qubit_error():
1374
+ qasm = """OPENQASM 2.0;
1375
+ include "qelib1.inc";
1376
+ qreg q[1];
1377
+ gate g q0 { x q1; }
1378
+ g q
1379
+ """
1380
+ _test_parse_exception(
1381
+ qasm,
1382
+ cirq_err="Undefined qubit 'q1' at line 4",
1383
+ qiskit_err="4,19: 'q1' is not defined in this scope",
1384
+ )
1385
+
1386
+
1387
+ def test_custom_gate_qubit_scope_closure_error():
1388
+ qasm = """OPENQASM 2.0;
1389
+ include "qelib1.inc";
1390
+ qreg q[1];
1391
+ gate g q0 { x q; }
1392
+ g q
1393
+ """
1394
+ _test_parse_exception(
1395
+ qasm,
1396
+ cirq_err="'q' is a register, not a qubit at line 4",
1397
+ qiskit_err="4,19: 'q' is a quantum register, not a qubit",
1398
+ )
1399
+
1400
+
1401
+ def test_custom_gate_qubit_index_error():
1402
+ qasm = """OPENQASM 2.0;
1403
+ include "qelib1.inc";
1404
+ qreg q[1];
1405
+ gate g q0 { x q0[0]; }
1406
+ g q
1407
+ """
1408
+ _test_parse_exception(
1409
+ qasm,
1410
+ cirq_err="Unsupported indexed qreg 'q0[0]' at line 4",
1411
+ qiskit_err="4,21: needed ';', but instead saw [",
1412
+ )
1413
+
1414
+
1415
+ def test_custom_gate_qreg_count_error():
1416
+ qasm = """OPENQASM 2.0;
1417
+ include "qelib1.inc";
1418
+ qreg q[2];
1419
+ gate g q0 { x q0; }
1420
+ g q[0], q[1];
1421
+ """
1422
+ _test_parse_exception(
1423
+ qasm,
1424
+ cirq_err="Wrong number of qregs for 'g' at line 5",
1425
+ qiskit_err="5,5: 'g' takes 1 quantum argument, but got 2",
1426
+ )
1427
+
1428
+
1429
+ def test_custom_gate_missing_param_error():
1430
+ qasm = """OPENQASM 2.0;
1431
+ include "qelib1.inc";
1432
+ qreg q[1];
1433
+ gate g(p) q0 { rx(p) q0; }
1434
+ g q;
1435
+ """
1436
+ _test_parse_exception(
1437
+ qasm,
1438
+ cirq_err="Wrong number of params for 'g' at line 5",
1439
+ qiskit_err=None, # Qiskit bug? It's an invalid circuit that won't simulate.
1440
+ )
1441
+
1442
+
1443
+ def test_custom_gate_extra_param_error():
1444
+ qasm = """OPENQASM 2.0;
1445
+ include "qelib1.inc";
1446
+ qreg q[1];
1447
+ gate g q0 { x q0; }
1448
+ g(3) q;
1449
+ """
1450
+ _test_parse_exception(
1451
+ qasm,
1452
+ cirq_err="Wrong number of params for 'g' at line 5",
1453
+ qiskit_err="5,5: 'g' takes 0 parameters, but got 1",
1454
+ )
1455
+
1456
+
1457
+ def test_custom_gate_undefined_param_error():
1458
+ qasm = """OPENQASM 2.0;
1459
+ include "qelib1.inc";
1460
+ qreg q[1];
1461
+ gate g q0 { rx(p) q0; }
1462
+ g q;
1463
+ """
1464
+ _test_parse_exception(
1465
+ qasm,
1466
+ cirq_err="Undefined parameter 'p' in line 4",
1467
+ qiskit_err="4,20: 'p' is not a parameter",
1468
+ )
1469
+
1470
+
1471
+ def test_top_level_param_error():
1472
+ qasm = """OPENQASM 2.0;
1473
+ include "qelib1.inc";
1474
+ qreg q[1];
1475
+ rx(p) q;
1476
+ """
1477
+ _test_parse_exception(
1478
+ qasm,
1479
+ cirq_err="Parameter 'p' in line 4 not supported",
1480
+ qiskit_err="4,8: 'p' is not a parameter",
1481
+ )
1482
+
1483
+
1484
+ def _test_parse_exception(qasm: str, cirq_err: str, qiskit_err: str | None):
1485
+ parser = QasmParser()
1486
+ with pytest.raises(QasmException, match=re.escape(cirq_err)):
1487
+ parser.parse(qasm)
1488
+ pytest.importorskip("qiskit")
1489
+ import qiskit.qasm2
1490
+
1491
+ if qiskit_err is None:
1492
+ qiskit.QuantumCircuit.from_qasm_str(qasm)
1493
+ return
1494
+ with pytest.raises(qiskit.qasm2.exceptions.QASM2ParseError, match=re.escape(qiskit_err)):
1495
+ qiskit.QuantumCircuit.from_qasm_str(qasm)
1496
+
1497
+
1498
+ def test_nested_custom_gate_has_keyword_in_name():
1499
+ qasm = """OPENQASM 2.0;
1500
+ include "qelib1.inc";
1501
+ qreg q[1];
1502
+ gate gateGate qb { x qb; }
1503
+ gate qregGate qa { gateGate qa; }
1504
+ qregGate q;
1505
+ """
1506
+ qb = cirq.NamedQubit('qb')
1507
+ inner = cirq.FrozenCircuit(cirq.X(qb))
1508
+ qa = cirq.NamedQubit('qa')
1509
+ middle = cirq.FrozenCircuit(cirq.CircuitOperation(inner, qubit_map={qb: qa}))
1510
+ q_0 = cirq.NamedQubit('q_0')
1511
+ expected = cirq.Circuit(cirq.CircuitOperation(middle, qubit_map={qa: q_0}))
1512
+ parser = QasmParser()
1513
+ parsed_qasm = parser.parse(qasm)
1514
+ assert parsed_qasm.circuit == expected