cirq-core 1.4.0.dev20240529225110__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 +31 -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.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/RECORD +586 -552
  584. {cirq_core-1.4.0.dev20240529225110.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.0.dev20240529225110.dist-info/METADATA +0 -50
  589. {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/LICENSE +0 -0
  590. {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/top_level.txt +0 -0
@@ -14,7 +14,7 @@
14
14
 
15
15
  import re
16
16
  from typing import Optional
17
- import numpy as np
17
+
18
18
  import ply.lex as lex
19
19
 
20
20
  from cirq.contrib.qasm_import.exception import QasmException
@@ -24,20 +24,30 @@ class QasmLexer:
24
24
  def __init__(self):
25
25
  self.lex = lex.lex(object=self, debug=False)
26
26
 
27
- literals = "{}[]();,+/*-^"
27
+ literals = "{}[]();,+/*-^="
28
28
 
29
29
  reserved = {
30
+ 'qubit': 'QUBIT',
30
31
  'qreg': 'QREG',
32
+ 'bit': 'BIT',
31
33
  'creg': 'CREG',
32
34
  'measure': 'MEASURE',
35
+ 'reset': 'RESET',
36
+ 'gate': 'GATE',
33
37
  'if': 'IF',
34
- '->': 'ARROW',
35
- '==': 'EQ',
38
+ 'pi': 'PI',
36
39
  }
37
40
 
38
- tokens = ['FORMAT_SPEC', 'NUMBER', 'NATURAL_NUMBER', 'QELIBINC', 'ID', 'PI'] + list(
39
- reserved.values()
40
- )
41
+ tokens = [
42
+ 'FORMAT_SPEC',
43
+ 'NUMBER',
44
+ 'NATURAL_NUMBER',
45
+ 'STDGATESINC',
46
+ 'QELIBINC',
47
+ 'ID',
48
+ 'ARROW',
49
+ 'EQ',
50
+ ] + list(reserved.values())
41
51
 
42
52
  def t_newline(self, t):
43
53
  r"""\n+"""
@@ -45,11 +55,6 @@ class QasmLexer:
45
55
 
46
56
  t_ignore = ' \t'
47
57
 
48
- def t_PI(self, t):
49
- r"""pi"""
50
- t.value = np.pi
51
- return t
52
-
53
58
  # all numbers except NATURAL_NUMBERs:
54
59
  # it's useful to have this separation to be able to handle indices
55
60
  # separately. In case of the parameter expressions, we are "OR"-ing
@@ -83,20 +88,8 @@ class QasmLexer:
83
88
  r"""include(\s+)"qelib1.inc";"""
84
89
  return t
85
90
 
86
- def t_QREG(self, t):
87
- r"""qreg"""
88
- return t
89
-
90
- def t_CREG(self, t):
91
- r"""creg"""
92
- return t
93
-
94
- def t_MEASURE(self, t):
95
- r"""measure"""
96
- return t
97
-
98
- def t_IF(self, t):
99
- r"""if"""
91
+ def t_STDGATESINC(self, t):
92
+ r"""include(\s+)"stdgates.inc";"""
100
93
  return t
101
94
 
102
95
  def t_ARROW(self, t):
@@ -109,6 +102,8 @@ class QasmLexer:
109
102
 
110
103
  def t_ID(self, t):
111
104
  r"""[a-zA-Z][a-zA-Z\d_]*"""
105
+ if t.value in QasmLexer.reserved:
106
+ t.type = QasmLexer.reserved[t.value]
112
107
  return t
113
108
 
114
109
  def t_COMMENT(self, t):
@@ -13,7 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import pytest
16
- import numpy as np
16
+
17
17
  from cirq.contrib.qasm_import import QasmException
18
18
  from cirq.contrib.qasm_import._lexer import QasmLexer
19
19
 
@@ -103,12 +103,28 @@ def test_numbers(number: str):
103
103
  assert token.value == float(number)
104
104
 
105
105
 
106
- def test_pi():
106
+ @pytest.mark.parametrize('token', QasmLexer.reserved.keys())
107
+ def test_keywords(token):
107
108
  lexer = QasmLexer()
108
- lexer.input('pi')
109
- token = lexer.token()
110
- assert token.type == "PI"
111
- assert token.value == np.pi
109
+ identifier = f'{token} {token}'
110
+ lexer.input(identifier)
111
+ t = lexer.token()
112
+ assert t.type == QasmLexer.reserved[token]
113
+ assert t.value == token
114
+ t2 = lexer.token()
115
+ assert t2.type == QasmLexer.reserved[token]
116
+ assert t2.value == token
117
+
118
+
119
+ @pytest.mark.parametrize('token', QasmLexer.reserved.keys())
120
+ @pytest.mark.parametrize('separator', ['', '_'])
121
+ def test_identifier_starts_or_ends_with_keyword(token, separator):
122
+ lexer = QasmLexer()
123
+ identifier = f'{token}{separator}{token}'
124
+ lexer.input(identifier)
125
+ t = lexer.token()
126
+ assert t.type == "ID"
127
+ assert t.value == identifier
112
128
 
113
129
 
114
130
  def test_qreg():
@@ -159,6 +175,74 @@ def test_creg():
159
175
  assert token.value == ";"
160
176
 
161
177
 
178
+ def test_custom_gate():
179
+ lexer = QasmLexer()
180
+ lexer.input('gate name(param1,param2) q1, q2 {X(q1)}')
181
+ token = lexer.token()
182
+ assert token.type == "GATE"
183
+ assert token.value == "gate"
184
+
185
+ token = lexer.token()
186
+ assert token.type == "ID"
187
+ assert token.value == "name"
188
+
189
+ token = lexer.token()
190
+ assert token.type == "("
191
+ assert token.value == "("
192
+
193
+ token = lexer.token()
194
+ assert token.type == "ID"
195
+ assert token.value == "param1"
196
+
197
+ token = lexer.token()
198
+ assert token.type == ","
199
+ assert token.value == ","
200
+
201
+ token = lexer.token()
202
+ assert token.type == "ID"
203
+ assert token.value == "param2"
204
+
205
+ token = lexer.token()
206
+ assert token.type == ")"
207
+ assert token.value == ")"
208
+
209
+ token = lexer.token()
210
+ assert token.type == "ID"
211
+ assert token.value == "q1"
212
+
213
+ token = lexer.token()
214
+ assert token.type == ","
215
+ assert token.value == ","
216
+
217
+ token = lexer.token()
218
+ assert token.type == "ID"
219
+ assert token.value == "q2"
220
+
221
+ token = lexer.token()
222
+ assert token.type == "{"
223
+ assert token.value == "{"
224
+
225
+ token = lexer.token()
226
+ assert token.type == "ID"
227
+ assert token.value == "X"
228
+
229
+ token = lexer.token()
230
+ assert token.type == "("
231
+ assert token.value == "("
232
+
233
+ token = lexer.token()
234
+ assert token.type == "ID"
235
+ assert token.value == "q1"
236
+
237
+ token = lexer.token()
238
+ assert token.type == ")"
239
+ assert token.value == ")"
240
+
241
+ token = lexer.token()
242
+ assert token.type == "}"
243
+ assert token.value == "}"
244
+
245
+
162
246
  def test_error():
163
247
  lexer = QasmLexer()
164
248
  lexer.input('θ')
@@ -12,20 +12,32 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import dataclasses
15
16
  import functools
16
17
  import operator
17
- from typing import Any, Callable, cast, Dict, Iterable, List, Optional, Union, TYPE_CHECKING
18
+ from typing import (
19
+ Any,
20
+ Callable,
21
+ cast,
22
+ Dict,
23
+ Iterable,
24
+ List,
25
+ Optional,
26
+ Set,
27
+ Tuple,
28
+ TYPE_CHECKING,
29
+ Union,
30
+ )
18
31
 
19
32
  import numpy as np
20
33
  import sympy
21
34
  from ply import yacc
22
35
 
23
- from cirq import ops, Circuit, NamedQubit, CX
36
+ from cirq import Circuit, CircuitOperation, CX, FrozenCircuit, NamedQubit, ops, value
24
37
  from cirq.circuits.qasm_output import QasmUGate
25
38
  from cirq.contrib.qasm_import._lexer import QasmLexer
26
39
  from cirq.contrib.qasm_import.exception import QasmException
27
40
 
28
-
29
41
  if TYPE_CHECKING:
30
42
  import cirq
31
43
 
@@ -47,6 +59,31 @@ class Qasm:
47
59
  self.circuit = c
48
60
 
49
61
 
62
+ def _generate_op_qubits(args: List[List[ops.Qid]], lineno: int) -> List[List[ops.Qid]]:
63
+ """Generates the Cirq qubits for an operation from the OpenQASM qregs.
64
+
65
+ OpenQASM gates can be applied on single qubits and qubit registers.
66
+ We represent single qubits as registers of size 1.
67
+ Based on the OpenQASM spec (https://arxiv.org/abs/1707.03429),
68
+ single qubit arguments can be mixed with qubit registers.
69
+ Given quantum registers of length reg_size and single qubits are both
70
+ used as arguments, we generate reg_size GateOperations via iterating
71
+ through each qubit of the registers 0 to n-1 and use the same one
72
+ qubit from the "single-qubit registers" for each operation."""
73
+ reg_sizes = np.unique([len(reg) for reg in args])
74
+ if len(reg_sizes) > 2 or (len(reg_sizes) > 1 and reg_sizes[0] != 1):
75
+ raise QasmException(
76
+ f"Non matching quantum registers of length {reg_sizes} at line {lineno}"
77
+ )
78
+ op_qubits_gen = functools.reduce(
79
+ cast(Callable[[List['cirq.Qid'], List['cirq.Qid']], List['cirq.Qid']], np.broadcast), args
80
+ )
81
+ op_qubits = [[q] if isinstance(q, ops.Qid) else q for q in op_qubits_gen]
82
+ if any(len(set(q)) < len(q) for q in op_qubits):
83
+ raise QasmException(f"Overlapping qubits in arguments at line {lineno}")
84
+ return op_qubits
85
+
86
+
50
87
  class QasmGateStatement:
51
88
  """Specifies how to convert a call to an OpenQASM gate
52
89
  to a list of `cirq.GateOperation`s.
@@ -87,7 +124,7 @@ class QasmGateStatement:
87
124
  f"got: {len(args)}, at line {lineno}"
88
125
  )
89
126
 
90
- def _validate_params(self, params: List[float], lineno: int):
127
+ def _validate_params(self, params: List[value.TParamVal], lineno: int):
91
128
  if len(params) != self.num_params:
92
129
  raise QasmException(
93
130
  f"{self.qasm_gate} takes {self.num_params} parameter(s), "
@@ -95,41 +132,47 @@ class QasmGateStatement:
95
132
  )
96
133
 
97
134
  def on(
98
- self, params: List[float], args: List[List[ops.Qid]], lineno: int
135
+ self, params: List[value.TParamVal], args: List[List[ops.Qid]], lineno: int
99
136
  ) -> Iterable[ops.Operation]:
100
137
  self._validate_args(args, lineno)
101
138
  self._validate_params(params, lineno)
102
139
 
103
- reg_sizes = np.unique([len(reg) for reg in args])
104
- if len(reg_sizes) > 2 or (len(reg_sizes) > 1 and reg_sizes[0] != 1):
105
- raise QasmException(
106
- f"Non matching quantum registers of length {reg_sizes} at line {lineno}"
107
- )
108
-
109
140
  # the actual gate we'll apply the arguments to might be a parameterized
110
141
  # or non-parameterized gate
111
142
  final_gate: ops.Gate = (
112
143
  self.cirq_gate if isinstance(self.cirq_gate, ops.Gate) else self.cirq_gate(params)
113
144
  )
114
- # OpenQASM gates can be applied on single qubits and qubit registers.
115
- # We represent single qubits as registers of size 1.
116
- # Based on the OpenQASM spec (https://arxiv.org/abs/1707.03429),
117
- # single qubit arguments can be mixed with qubit registers.
118
- # Given quantum registers of length reg_size and single qubits are both
119
- # used as arguments, we generate reg_size GateOperations via iterating
120
- # through each qubit of the registers 0 to n-1 and use the same one
121
- # qubit from the "single-qubit registers" for each operation.
122
- op_qubits = functools.reduce(
123
- cast(Callable[[List['cirq.Qid'], List['cirq.Qid']], List['cirq.Qid']], np.broadcast),
124
- args,
125
- )
126
- for qubits in op_qubits:
127
- if isinstance(qubits, ops.Qid):
128
- yield final_gate.on(qubits)
129
- elif len(np.unique(qubits)) < len(qubits):
130
- raise QasmException(f"Overlapping qubits in arguments at line {lineno}")
131
- else:
132
- yield final_gate.on(*qubits)
145
+ for qubits in _generate_op_qubits(args, lineno):
146
+ yield final_gate.on(*qubits)
147
+
148
+
149
+ @dataclasses.dataclass
150
+ class CustomGate:
151
+ """Represents an invocation of a user-defined gate.
152
+
153
+ The custom gate definition is encoded here as a `FrozenCircuit`, and the
154
+ arguments (params and qubits) of the specific invocation of that gate are
155
+ stored here too. When `on` is called, we create a CircuitOperation, mapping
156
+ the qubits and params to the values provided."""
157
+
158
+ name: str
159
+ circuit: FrozenCircuit
160
+ params: Tuple[str, ...]
161
+ qubits: Tuple[ops.Qid, ...]
162
+
163
+ def on(
164
+ self, params: List[value.TParamVal], args: List[List[ops.Qid]], lineno: int
165
+ ) -> Iterable[ops.Operation]:
166
+ if len(params) != len(self.params):
167
+ raise QasmException(f"Wrong number of params for '{self.name}' at line {lineno}")
168
+ if len(args) != len(self.qubits):
169
+ raise QasmException(f"Wrong number of qregs for '{self.name}' at line {lineno}")
170
+ for qubits in _generate_op_qubits(args, lineno):
171
+ yield CircuitOperation(
172
+ self.circuit,
173
+ param_resolver={k: v for k, v in zip(self.params, params)},
174
+ qubit_map={k: v for k, v in zip(self.qubits, qubits)},
175
+ )
133
176
 
134
177
 
135
178
  class QasmParser:
@@ -146,6 +189,18 @@ class QasmParser:
146
189
  self.circuit = Circuit()
147
190
  self.qregs: Dict[str, int] = {}
148
191
  self.cregs: Dict[str, int] = {}
192
+ self.gate_set: Dict[str, Union[CustomGate, QasmGateStatement]] = {**self.basic_gates}
193
+ """The gates available to use in the circuit, including those from libraries, and
194
+ user-defined ones."""
195
+ self.in_custom_gate_scope = False
196
+ """This is set to True when the parser is in the middle of parsing a custom gate
197
+ definition."""
198
+ self.custom_gate_scoped_params: Set[str] = set()
199
+ """The params declared within the current custom gate definition. Empty if not in
200
+ custom gate scope."""
201
+ self.custom_gate_scoped_qubits: Dict[str, ops.Qid] = {}
202
+ """The qubits declared within the current custom gate definition. Empty if not in
203
+ custom gate scope."""
149
204
  self.qelibinc = False
150
205
  self.lexer = QasmLexer()
151
206
  self.supported_format = False
@@ -243,6 +298,24 @@ class QasmParser:
243
298
  'ch': QasmGateStatement(
244
299
  qasm_gate='ch', cirq_gate=ops.ControlledGate(ops.H), num_params=0, num_args=2
245
300
  ),
301
+ 'cu1': QasmGateStatement(
302
+ qasm_gate='cu1',
303
+ num_params=1,
304
+ num_args=2,
305
+ cirq_gate=(lambda params: ops.ControlledGate(QasmUGate(0, 0, params[0] / np.pi))),
306
+ ),
307
+ 'cu3': QasmGateStatement(
308
+ qasm_gate='cu3',
309
+ num_params=3,
310
+ num_args=2,
311
+ cirq_gate=(lambda params: ops.ControlledGate(QasmUGate(*[p / np.pi for p in params]))),
312
+ ),
313
+ 'crz': QasmGateStatement(
314
+ qasm_gate='crz',
315
+ num_params=1,
316
+ num_args=2,
317
+ cirq_gate=(lambda params: ops.ControlledGate(ops.rz(params[0]))),
318
+ ),
246
319
  'swap': QasmGateStatement(qasm_gate='swap', cirq_gate=ops.SWAP, num_params=0, num_args=2),
247
320
  'cswap': QasmGateStatement(
248
321
  qasm_gate='cswap', num_params=0, num_args=3, cirq_gate=ops.CSWAP
@@ -252,8 +325,6 @@ class QasmParser:
252
325
  'tdg': QasmGateStatement(qasm_gate='tdg', num_params=0, num_args=1, cirq_gate=ops.T**-1),
253
326
  }
254
327
 
255
- all_gates = {**basic_gates, **qelib_gates}
256
-
257
328
  tokens = QasmLexer.tokens
258
329
  start = 'start'
259
330
 
@@ -270,6 +341,7 @@ class QasmParser:
270
341
 
271
342
  def p_qasm_no_format_specified_error(self, p):
272
343
  """qasm : QELIBINC
344
+ | STDGATESINC
273
345
  | circuit"""
274
346
  if self.supported_format is False:
275
347
  raise QasmException("Missing 'OPENQASM 2.0;' statement")
@@ -277,6 +349,13 @@ class QasmParser:
277
349
  def p_qasm_include(self, p):
278
350
  """qasm : qasm QELIBINC"""
279
351
  self.qelibinc = True
352
+ self.gate_set |= self.qelib_gates
353
+ p[0] = Qasm(self.supported_format, self.qelibinc, self.qregs, self.cregs, self.circuit)
354
+
355
+ def p_qasm_include_stdgates(self, p):
356
+ """qasm : qasm STDGATESINC"""
357
+ self.qelibinc = True
358
+ self.gate_set |= self.qelib_gates
280
359
  p[0] = Qasm(self.supported_format, self.qelibinc, self.qregs, self.cregs, self.circuit)
281
360
 
282
361
  def p_qasm_circuit(self, p):
@@ -285,14 +364,16 @@ class QasmParser:
285
364
 
286
365
  def p_format(self, p):
287
366
  """format : FORMAT_SPEC"""
288
- if p[1] != "2.0":
367
+ if p[1] not in ["2.0", "3.0"]:
289
368
  raise QasmException(
290
- f"Unsupported OpenQASM version: {p[1]}, only 2.0 is supported currently by Cirq"
369
+ f"Unsupported OpenQASM version: {p[1]}, "
370
+ "only 2.0 and 3.0 are supported currently by Cirq"
291
371
  )
292
372
 
293
373
  # circuit : new_reg circuit
294
374
  # | gate_op circuit
295
375
  # | measurement circuit
376
+ # | reset circuit
296
377
  # | if circuit
297
378
  # | empty
298
379
 
@@ -303,6 +384,7 @@ class QasmParser:
303
384
  def p_circuit_gate_or_measurement_or_if(self, p):
304
385
  """circuit : circuit gate_op
305
386
  | circuit measurement
387
+ | circuit reset
306
388
  | circuit if"""
307
389
  self.circuit.append(p[2])
308
390
  p[0] = self.circuit
@@ -311,17 +393,36 @@ class QasmParser:
311
393
  """circuit : empty"""
312
394
  p[0] = self.circuit
313
395
 
396
+ def p_circuit_gate_def(self, p):
397
+ """circuit : gate_def"""
398
+ p[0] = self.circuit
399
+
314
400
  # qreg and creg
315
401
 
316
402
  def p_new_reg(self, p):
317
403
  """new_reg : QREG ID '[' NATURAL_NUMBER ']' ';'
318
- | CREG ID '[' NATURAL_NUMBER ']' ';'"""
319
- name, length = p[2], p[4]
404
+ | QUBIT '[' NATURAL_NUMBER ']' ID ';'
405
+ | QUBIT ID ';'
406
+ | CREG ID '[' NATURAL_NUMBER ']' ';'
407
+ | BIT '[' NATURAL_NUMBER ']' ID ';'
408
+ | BIT ID ';'
409
+ """
410
+ if p[1] == "qreg" or p[1] == "creg":
411
+ # QREG ID '[' NATURAL_NUMBER ']' ';'
412
+ name, length = p[2], p[4]
413
+ else:
414
+ if len(p) < 5:
415
+ # QUBIT ID ';' | BIT ID ';'
416
+ name = p[2]
417
+ length = 1
418
+ else:
419
+ # QUBIT '[' NATURAL_NUMBER ']' ID ';'
420
+ name, length = p[5], p[3]
320
421
  if name in self.qregs.keys() or name in self.cregs.keys():
321
422
  raise QasmException(f"{name} is already defined at line {p.lineno(2)}")
322
423
  if length == 0:
323
424
  raise QasmException(f"Illegal, zero-length register '{name}' at line {p.lineno(4)}")
324
- if p[1] == "qreg":
425
+ if p[1] == "qreg" or p[1] == "qubit":
325
426
  self.qregs[name] = length
326
427
  else:
327
428
  self.cregs[name] = length
@@ -340,14 +441,13 @@ class QasmParser:
340
441
  self._resolve_gate_operation(args=p[5], gate=p[1], p=p, params=p[3])
341
442
 
342
443
  def _resolve_gate_operation(
343
- self, args: List[List[ops.Qid]], gate: str, p: Any, params: List[float]
444
+ self, args: List[List[ops.Qid]], gate: str, p: Any, params: List[value.TParamVal]
344
445
  ):
345
- gate_set = self.basic_gates if not self.qelibinc else self.all_gates
346
- if gate not in gate_set.keys():
446
+ if gate not in self.gate_set:
347
447
  tip = ", did you forget to include qelib1.inc?" if not self.qelibinc else ""
348
448
  msg = f'Unknown gate "{gate}" at line {p.lineno(1)}{tip}'
349
449
  raise QasmException(msg)
350
- p[0] = gate_set[gate].on(args=args, params=params, lineno=p.lineno(1))
450
+ p[0] = self.gate_set[gate].on(args=args, params=params, lineno=p.lineno(1))
351
451
 
352
452
  # params : parameter ',' params
353
453
  # | parameter
@@ -362,7 +462,8 @@ class QasmParser:
362
462
  p[0] = [p[1]]
363
463
 
364
464
  # expr : term
365
- # | func '(' expression ')' """
465
+ # | ID
466
+ # | func '(' expression ')'
366
467
  # | binary_op
367
468
  # | unary_op
368
469
 
@@ -370,6 +471,14 @@ class QasmParser:
370
471
  """expr : term"""
371
472
  p[0] = p[1]
372
473
 
474
+ def p_expr_identifier(self, p):
475
+ """expr : ID"""
476
+ if not self.in_custom_gate_scope:
477
+ raise QasmException(f"Parameter '{p[1]}' in line {p.lineno(1)} not supported")
478
+ if p[1] not in self.custom_gate_scoped_params:
479
+ raise QasmException(f"Undefined parameter '{p[1]}' in line {p.lineno(1)}'")
480
+ p[0] = sympy.Symbol(p[1])
481
+
373
482
  def p_expr_parens(self, p):
374
483
  """expr : '(' expr ')'"""
375
484
  p[0] = p[2]
@@ -400,10 +509,13 @@ class QasmParser:
400
509
 
401
510
  def p_term(self, p):
402
511
  """term : NUMBER
403
- | NATURAL_NUMBER
404
- | PI"""
512
+ | NATURAL_NUMBER"""
405
513
  p[0] = p[1]
406
514
 
515
+ def p_pi(self, p):
516
+ """term : PI"""
517
+ p[0] = np.pi
518
+
407
519
  # qargs : qarg ',' qargs
408
520
  # | qarg ';'
409
521
 
@@ -422,6 +534,15 @@ class QasmParser:
422
534
  def p_quantum_arg_register(self, p):
423
535
  """qarg : ID"""
424
536
  reg = p[1]
537
+ if self.in_custom_gate_scope:
538
+ if reg not in self.custom_gate_scoped_qubits:
539
+ if reg not in self.qregs:
540
+ msg = f"Undefined qubit '{reg}'"
541
+ else:
542
+ msg = f"'{reg}' is a register, not a qubit"
543
+ raise QasmException(f"{msg} at line {p.lineno(1)}")
544
+ p[0] = [self.custom_gate_scoped_qubits[reg]]
545
+ return
425
546
  if reg not in self.qregs.keys():
426
547
  raise QasmException(f'Undefined quantum register "{reg}" at line {p.lineno(1)}')
427
548
  qubits = []
@@ -450,6 +571,8 @@ class QasmParser:
450
571
  """qarg : ID '[' NATURAL_NUMBER ']'"""
451
572
  reg = p[1]
452
573
  idx = p[3]
574
+ if self.in_custom_gate_scope:
575
+ raise QasmException(f"Unsupported indexed qreg '{reg}[{idx}]' at line {p.lineno(1)}")
453
576
  arg_name = self.make_name(idx, reg)
454
577
  if reg not in self.qregs.keys():
455
578
  raise QasmException(f'Undefined quantum register "{reg}" at line {p.lineno(1)}')
@@ -485,9 +608,14 @@ class QasmParser:
485
608
  # measurement : MEASURE qarg ARROW carg
486
609
 
487
610
  def p_measurement(self, p):
488
- """measurement : MEASURE qarg ARROW carg ';'"""
489
- qreg = p[2]
490
- creg = p[4]
611
+ """measurement : MEASURE qarg ARROW carg ';'
612
+ | carg '=' MEASURE qarg ';'"""
613
+ if p[1] == 'measure':
614
+ qreg = p[2]
615
+ creg = p[4]
616
+ else:
617
+ qreg = p[4]
618
+ creg = p[1]
491
619
 
492
620
  if len(qreg) != len(creg):
493
621
  raise QasmException(
@@ -499,6 +627,15 @@ class QasmParser:
499
627
  ops.MeasurementGate(num_qubits=1, key=creg[i]).on(qreg[i]) for i in range(len(qreg))
500
628
  ]
501
629
 
630
+ # reset operations
631
+ # reset : RESET qarg
632
+
633
+ def p_reset(self, p):
634
+ """reset : RESET qarg ';'"""
635
+ qreg = p[2]
636
+
637
+ p[0] = [ops.ResetChannel().on(qreg[i]) for i in range(len(qreg))]
638
+
502
639
  # if operations
503
640
  # if : IF '(' carg EQ NATURAL_NUMBER ')' ID qargs
504
641
 
@@ -514,6 +651,60 @@ class QasmParser:
514
651
  ops.ClassicallyControlledOperation(conditions=conditions, sub_operation=tuple(p[7])[0])
515
652
  ]
516
653
 
654
+ def p_gate_params_multiple(self, p):
655
+ """gate_params : ID ',' gate_params"""
656
+ self.p_gate_params_single(p)
657
+ p[0] += p[3]
658
+
659
+ def p_gate_params_single(self, p):
660
+ """gate_params : ID"""
661
+ self.in_custom_gate_scope = True
662
+ self.custom_gate_scoped_params.add(p[1])
663
+ p[0] = [p[1]]
664
+
665
+ def p_gate_qubits_multiple(self, p):
666
+ """gate_qubits : ID ',' gate_qubits"""
667
+ self.p_gate_qubits_single(p)
668
+ p[0] += p[3]
669
+
670
+ def p_gate_qubits_single(self, p):
671
+ """gate_qubits : ID"""
672
+ self.in_custom_gate_scope = True
673
+ q = NamedQubit(p[1])
674
+ self.custom_gate_scoped_qubits[p[1]] = q
675
+ p[0] = [q]
676
+
677
+ def p_gate_ops(self, p):
678
+ """gate_ops : gate_op gate_ops"""
679
+ p[0] = [p[1]] + p[2]
680
+
681
+ def p_gate_ops_empty(self, p):
682
+ """gate_ops : empty"""
683
+ self.in_custom_gate_scope = True
684
+ p[0] = []
685
+
686
+ def p_gate_def_parameterized(self, p):
687
+ """gate_def : GATE ID '(' gate_params ')' gate_qubits '{' gate_ops '}'"""
688
+ self._gate_def(p, has_params=True)
689
+
690
+ def p_gate_def(self, p):
691
+ """gate_def : GATE ID gate_qubits '{' gate_ops '}'"""
692
+ self._gate_def(p, has_params=False)
693
+
694
+ def _gate_def(self, p: List[Any], *, has_params: bool):
695
+ name = p[2]
696
+ gate_params = tuple(p[4]) if has_params else ()
697
+ offset = 3 if has_params else 0
698
+ gate_qubits = tuple(p[3 + offset])
699
+ gate_ops = p[5 + offset]
700
+ circuit = Circuit(gate_ops).freeze()
701
+ gate_def = CustomGate(name, circuit, gate_params, gate_qubits)
702
+ self.gate_set[name] = gate_def
703
+ self.custom_gate_scoped_params.clear()
704
+ self.custom_gate_scoped_qubits.clear()
705
+ self.in_custom_gate_scope = False
706
+ p[0] = gate_def
707
+
517
708
  def p_error(self, p):
518
709
  if p is None:
519
710
  raise QasmException('Unexpected end of file')