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
@@ -15,6 +15,7 @@
15
15
  import abc
16
16
  import enum
17
17
  from typing import Dict, List, Mapping, Optional, Sequence, Tuple, TYPE_CHECKING
18
+
18
19
  from typing_extensions import Self
19
20
 
20
21
  from cirq.value import digits, value_equality_attr
cirq/value/condition.py CHANGED
@@ -14,8 +14,9 @@
14
14
 
15
15
  import abc
16
16
  import dataclasses
17
- from typing import Mapping, Tuple, TYPE_CHECKING, FrozenSet
17
+ from typing import Any, Dict, FrozenSet, Mapping, Optional, Tuple, TYPE_CHECKING
18
18
 
19
+ import attrs
19
20
  import sympy
20
21
 
21
22
  from cirq._compat import proper_repr
@@ -47,6 +48,9 @@ class Condition(abc.ABC):
47
48
  def qasm(self):
48
49
  """Returns the qasm of this condition."""
49
50
 
51
+ def _qasm_(self, args: 'cirq.QasmArgs', **kwargs) -> Optional[str]:
52
+ return self.qasm
53
+
50
54
  def _with_measurement_key_mapping_(self, key_map: Mapping[str, str]) -> 'cirq.Condition':
51
55
  condition = self
52
56
  for k in self.keys:
@@ -115,6 +119,128 @@ class KeyCondition(Condition):
115
119
  def qasm(self):
116
120
  raise ValueError('QASM is defined only for SympyConditions of type key == constant.')
117
121
 
122
+ def _qasm_(self, args: 'cirq.QasmArgs', **kwargs) -> Optional[str]:
123
+ args.validate_version('2.0', '3.0')
124
+ key_str = str(self.key)
125
+ if key_str not in args.meas_key_id_map:
126
+ raise ValueError(f'Key "{key_str}" not in QasmArgs.meas_key_id_map.')
127
+ key = args.meas_key_id_map[key_str]
128
+ # QASM 3.0 supports !=, so we return it directly.
129
+ if args.version == '3.0':
130
+ return f'{key}!=0'
131
+ # QASM 2.0 only has == operator, so we must limit to single-bit measurement keys == 1.
132
+ if key not in args.meas_key_bitcount:
133
+ raise ValueError(f'Key "{key}" not in QasmArgs.meas_key_bitcount.')
134
+ if args.meas_key_bitcount[str(key)] != 1:
135
+ raise ValueError('QASM is defined only for single-bit classical conditions.')
136
+ return f'{key}==1'
137
+
138
+
139
+ @attrs.frozen
140
+ class BitMaskKeyCondition(Condition):
141
+ """A multiqubit classical control condition with a bitmask.
142
+
143
+ The control is based on a single measurement key and allows comparing equality or inequality
144
+ after taking the bitwise and with a bitmask.
145
+
146
+ Examples:
147
+ - BitMaskKeyCondition('a') -> a != 0
148
+ - BitMaskKeyCondition('a', bitmask=13) -> (a & 13) != 0
149
+ - BitMaskKeyCondition('a', bitmask=13, target_value=9) -> (a & 13) != 9
150
+ - BitMaskKeyCondition('a', bitmask=13, target_value=9, equal_target=True) -> (a & 13) == 9
151
+ - BitMaskKeyCondition.create_equal_mask('a', 13) -> (a & 13) == 13
152
+ - BitMaskKeyCondition.create_not_equal_mask('a', 13) -> (a & 13) != 13
153
+
154
+ The bits in the bitmask have the same order as the qubits passed to `cirq.measure(...)`. That's
155
+ the most significant bit corresponds to the the first (left most) qubit.
156
+
157
+ Attributes:
158
+ - key: Measurement key.
159
+ - index: integer index (same as KeyCondition.index).
160
+ - target_value: The value we compare with.
161
+ - equal_target: Whether to comapre with == or !=.
162
+ - bitmask: Optional bitmask to apply before doing the comparison.
163
+ """
164
+
165
+ key: 'cirq.MeasurementKey' = attrs.field(
166
+ converter=lambda x: (
167
+ x
168
+ if isinstance(x, measurement_key.MeasurementKey)
169
+ else measurement_key.MeasurementKey(x)
170
+ )
171
+ )
172
+ index: int = -1
173
+ target_value: int = 0
174
+ equal_target: bool = False
175
+ bitmask: Optional[int] = None
176
+
177
+ @property
178
+ def keys(self):
179
+ return (self.key,)
180
+
181
+ @staticmethod
182
+ def create_equal_mask(
183
+ key: 'cirq.MeasurementKey', bitmask: int, *, index: int = -1
184
+ ) -> 'BitMaskKeyCondition':
185
+ """Creates a condition that evaluates (meas & bitmask) == bitmask."""
186
+ return BitMaskKeyCondition(
187
+ key, index, target_value=bitmask, equal_target=True, bitmask=bitmask
188
+ )
189
+
190
+ @staticmethod
191
+ def create_not_equal_mask(
192
+ key: 'cirq.MeasurementKey', bitmask: int, *, index: int = -1
193
+ ) -> 'BitMaskKeyCondition':
194
+ """Creates a condition that evaluates (meas & bitmask) != bitmask."""
195
+ return BitMaskKeyCondition(
196
+ key, index, target_value=bitmask, equal_target=False, bitmask=bitmask
197
+ )
198
+
199
+ def replace_key(self, current: 'cirq.MeasurementKey', replacement: 'cirq.MeasurementKey'):
200
+ return BitMaskKeyCondition(replacement) if self.key == current else self
201
+
202
+ def __str__(self):
203
+ s = str(self.key) if self.index == -1 else f'{self.key}[{self.index}]'
204
+ if self.bitmask is not None:
205
+ s = f'{s} & {self.bitmask}'
206
+ if self.equal_target:
207
+ if self.bitmask is not None:
208
+ s = f'({s})'
209
+ s = f'{s} == {self.target_value}'
210
+ elif self.target_value != 0:
211
+ if self.bitmask is not None:
212
+ s = f'({s})'
213
+ s = f'{s} != {self.target_value}'
214
+ return s
215
+
216
+ def __repr__(self):
217
+ values = attrs.asdict(self)
218
+ parameters = ', '.join(f'{f.name}={repr(values[f.name])}' for f in attrs.fields(type(self)))
219
+ return f'cirq.BitMaskKeyCondition({parameters})'
220
+
221
+ def resolve(self, classical_data: 'cirq.ClassicalDataStoreReader') -> bool:
222
+ if self.key not in classical_data.keys():
223
+ raise ValueError(f'Measurement key {self.key} missing when testing classical control')
224
+ value = classical_data.get_int(self.key, self.index)
225
+ if self.bitmask is not None:
226
+ value &= self.bitmask
227
+ if self.equal_target:
228
+ return value == self.target_value
229
+ return value != self.target_value
230
+
231
+ def _json_dict_(self):
232
+ return json_serialization.attrs_json_dict(self)
233
+
234
+ @classmethod
235
+ def _from_json_dict_(cls, key, **kwargs):
236
+ parameter_names = [f.name for f in attrs.fields(cls)[1:]]
237
+ parameters = {k: kwargs[k] for k in parameter_names if k in kwargs}
238
+ return cls(key=key, **parameters)
239
+
240
+ @property
241
+ def qasm(self):
242
+ raise NotImplementedError()
243
+
118
244
 
119
245
  @dataclasses.dataclass(frozen=True)
120
246
  class SympyCondition(Condition):
@@ -123,6 +249,12 @@ class SympyCondition(Condition):
123
249
  This condition resolves to True iff the sympy expression resolves to a
124
250
  truthy value (i.e. `bool(x) == True`) when the measurement keys are
125
251
  substituted in as the free variables.
252
+
253
+ `sympy.IndexedBase` can be used for bitwise conditions. For example, the
254
+ following will create a condition that is controlled by the XOR of the
255
+ first two bits (big-endian) of measurement 'a'.
256
+ >>> a = sympy.IndexedBase('a')
257
+ >>> cond = cirq.SympyCondition(sympy.Xor(a[0], a[1]))
126
258
  """
127
259
 
128
260
  expr: sympy.Basic
@@ -132,6 +264,9 @@ class SympyCondition(Condition):
132
264
  return tuple(
133
265
  measurement_key.MeasurementKey.parse_serialized(symbol.name)
134
266
  for symbol in self.expr.free_symbols
267
+ if isinstance(symbol, sympy.Symbol)
268
+ # For bitwise ops, both Symbol ('a') and Indexed ('a[0]') are returned. We only want to
269
+ # keep the former here.
135
270
  )
136
271
 
137
272
  def replace_key(self, current: 'cirq.MeasurementKey', replacement: 'cirq.MeasurementKey'):
@@ -148,8 +283,19 @@ class SympyCondition(Condition):
148
283
  if missing:
149
284
  raise ValueError(f'Measurement keys {missing} missing when testing classical control')
150
285
 
151
- replacements = {str(k): classical_data.get_int(k) for k in self.keys}
152
- return bool(self.expr.subs(replacements))
286
+ replacements: Dict[str, Any] = {}
287
+ for symbol in self.expr.free_symbols:
288
+ if isinstance(symbol, sympy.Symbol):
289
+ name = symbol.name
290
+ key = measurement_key.MeasurementKey.parse_serialized(name)
291
+ replacements[str(key)] = classical_data.get_int(key)
292
+ for symbol in self.expr.free_symbols:
293
+ if isinstance(symbol, sympy.Indexed):
294
+ name = symbol.base.name
295
+ key = measurement_key.MeasurementKey.parse_serialized(name)
296
+ replacements[str(key)] = tuple(classical_data.get_digits(key))
297
+ value = self.expr.subs(replacements)
298
+ return bool(value)
153
299
 
154
300
  def _json_dict_(self):
155
301
  return json_serialization.dataclass_json_dict(self)
@@ -71,6 +71,35 @@ def test_key_condition_qasm():
71
71
  _ = cirq.KeyCondition(cirq.MeasurementKey('a')).qasm
72
72
 
73
73
 
74
+ def test_key_condition_qasm_protocol():
75
+ cond = cirq.KeyCondition(cirq.MeasurementKey('a'))
76
+ args = cirq.QasmArgs(meas_key_id_map={'a': 'm_a'}, meas_key_bitcount={'m_a': 1})
77
+ qasm = cirq.qasm(cond, args=args)
78
+ assert qasm == 'm_a==1'
79
+
80
+
81
+ def test_key_condition_qasm_protocol_v3():
82
+ cond = cirq.KeyCondition(cirq.MeasurementKey('a'))
83
+ args = cirq.QasmArgs(meas_key_id_map={'a': 'm_a'}, version='3.0')
84
+ qasm = cirq.qasm(cond, args=args)
85
+ assert qasm == 'm_a!=0'
86
+
87
+
88
+ def test_key_condition_qasm_protocol_invalid_args():
89
+ cond = cirq.KeyCondition(cirq.MeasurementKey('a'))
90
+ args = cirq.QasmArgs()
91
+ with pytest.raises(ValueError, match='Key "a" not in QasmArgs.meas_key_id_map.'):
92
+ _ = cirq.qasm(cond, args=args)
93
+ args = cirq.QasmArgs(meas_key_id_map={'a': 'm_a'})
94
+ with pytest.raises(ValueError, match='Key "m_a" not in QasmArgs.meas_key_bitcount.'):
95
+ _ = cirq.qasm(cond, args=args)
96
+ args = cirq.QasmArgs(meas_key_id_map={'a': 'm_a'}, meas_key_bitcount={'m_a': 2})
97
+ with pytest.raises(
98
+ ValueError, match='QASM is defined only for single-bit classical conditions.'
99
+ ):
100
+ _ = cirq.qasm(cond, args=args)
101
+
102
+
74
103
  def test_sympy_condition_with_keys():
75
104
  c = init_sympy_condition.replace_key(key_a, key_b)
76
105
  assert c.keys == (key_b,)
@@ -111,6 +140,52 @@ def test_sympy_condition_resolve():
111
140
  _ = resolve({'0:b': [[1]]})
112
141
 
113
142
 
143
+ def test_sympy_indexed_condition():
144
+ a = sympy.IndexedBase('a')
145
+ cond = cirq.SympyCondition(sympy.Xor(a[0], a[1]))
146
+ assert cond.keys == (cirq.MeasurementKey('a'),)
147
+ assert str(cond) == 'a[0] ^ a[1]'
148
+
149
+ def resolve(records):
150
+ classical_data = cirq.ClassicalDataDictionaryStore(_records=records)
151
+ return cond.resolve(classical_data)
152
+
153
+ assert not resolve({'a': [(0, 0)]})
154
+ assert resolve({'a': [(1, 0)]})
155
+ assert resolve({'a': [(0, 1)]})
156
+ assert not resolve({'a': [(1, 1)]})
157
+ assert resolve({'a': [(0, 1, 0)]})
158
+ assert resolve({'a': [(0, 1, 1)]})
159
+ assert not resolve({'a': [(1, 1, 0)]})
160
+ assert not resolve({'a': [(1, 1, 1)]})
161
+ with pytest.raises(IndexError):
162
+ assert resolve({'a': [()]})
163
+ with pytest.raises(IndexError):
164
+ assert resolve({'a': [(0,)]})
165
+ with pytest.raises(IndexError):
166
+ assert resolve({'a': [(1,)]})
167
+
168
+
169
+ def test_sympy_indexed_condition_qudits():
170
+ a = sympy.IndexedBase('a')
171
+ cond = cirq.SympyCondition(sympy.And(a[1] >= 2, a[2] <= 3))
172
+ assert cond.keys == (cirq.MeasurementKey('a'),)
173
+ assert str(cond) == '(a[1] >= 2) & (a[2] <= 3)'
174
+
175
+ def resolve(records):
176
+ classical_data = cirq.ClassicalDataDictionaryStore(_records=records)
177
+ return cond.resolve(classical_data)
178
+
179
+ assert not resolve({'a': [(0, 0, 0)]})
180
+ assert not resolve({'a': [(0, 1, 0)]})
181
+ assert resolve({'a': [(0, 2, 0)]})
182
+ assert resolve({'a': [(0, 3, 0)]})
183
+ assert not resolve({'a': [(0, 0, 4)]})
184
+ assert not resolve({'a': [(0, 1, 4)]})
185
+ assert not resolve({'a': [(0, 2, 4)]})
186
+ assert not resolve({'a': [(0, 3, 4)]})
187
+
188
+
114
189
  def test_sympy_condition_qasm():
115
190
  # Measurements get prepended with "m_", so the condition needs to be too.
116
191
  assert cirq.SympyCondition(sympy.Eq(sympy.Symbol('a'), 2)).qasm == 'm_a==2'
@@ -118,3 +193,182 @@ def test_sympy_condition_qasm():
118
193
  ValueError, match='QASM is defined only for SympyConditions of type key == constant'
119
194
  ):
120
195
  _ = cirq.SympyCondition(sympy.Symbol('a') != 2).qasm
196
+
197
+
198
+ @pytest.mark.parametrize(
199
+ ['cond', 'cond_str'],
200
+ [
201
+ (
202
+ cirq.BitMaskKeyCondition(
203
+ bitmask=None, equal_target=False, index=59, key='a', target_value=0
204
+ ),
205
+ 'a[59]',
206
+ ),
207
+ (
208
+ cirq.BitMaskKeyCondition(
209
+ bitmask=None, equal_target=False, index=-1, key='a', target_value=0
210
+ ),
211
+ 'a',
212
+ ),
213
+ (
214
+ cirq.BitMaskKeyCondition(
215
+ bitmask=None, equal_target=False, index=58, key='b', target_value=3
216
+ ),
217
+ 'b[58] != 3',
218
+ ),
219
+ (
220
+ cirq.BitMaskKeyCondition(
221
+ bitmask=None, equal_target=False, index=-1, key='b', target_value=3
222
+ ),
223
+ 'b != 3',
224
+ ),
225
+ (
226
+ cirq.BitMaskKeyCondition(
227
+ bitmask=13, equal_target=False, index=57, key='c', target_value=0
228
+ ),
229
+ 'c[57] & 13',
230
+ ),
231
+ (
232
+ cirq.BitMaskKeyCondition(
233
+ bitmask=13, equal_target=False, index=-1, key='c', target_value=0
234
+ ),
235
+ 'c & 13',
236
+ ),
237
+ (
238
+ cirq.BitMaskKeyCondition(
239
+ bitmask=13, equal_target=False, index=56, key='d', target_value=12
240
+ ),
241
+ '(d[56] & 13) != 12',
242
+ ),
243
+ (
244
+ cirq.BitMaskKeyCondition(
245
+ bitmask=13, equal_target=False, index=-1, key='d', target_value=12
246
+ ),
247
+ '(d & 13) != 12',
248
+ ),
249
+ (
250
+ cirq.BitMaskKeyCondition(
251
+ bitmask=13, equal_target=True, index=55, key='d', target_value=12
252
+ ),
253
+ '(d[55] & 13) == 12',
254
+ ),
255
+ (
256
+ cirq.BitMaskKeyCondition(
257
+ bitmask=13, equal_target=True, index=-1, key='d', target_value=12
258
+ ),
259
+ '(d & 13) == 12',
260
+ ),
261
+ (
262
+ cirq.BitMaskKeyCondition(
263
+ bitmask=11, equal_target=True, index=54, key='e', target_value=11
264
+ ),
265
+ '(e[54] & 11) == 11',
266
+ ),
267
+ (
268
+ cirq.BitMaskKeyCondition(
269
+ bitmask=11, equal_target=True, index=-1, key='e', target_value=11
270
+ ),
271
+ '(e & 11) == 11',
272
+ ),
273
+ (
274
+ cirq.BitMaskKeyCondition(
275
+ bitmask=9, equal_target=False, index=53, key='e', target_value=9
276
+ ),
277
+ '(e[53] & 9) != 9',
278
+ ),
279
+ (
280
+ cirq.BitMaskKeyCondition(
281
+ bitmask=9, equal_target=False, index=-1, key='e', target_value=9
282
+ ),
283
+ '(e & 9) != 9',
284
+ ),
285
+ ],
286
+ )
287
+ def test_bitmask_condition_str(cond: cirq.BitMaskKeyCondition, cond_str: str):
288
+ assert str(cond) == cond_str
289
+
290
+
291
+ @pytest.mark.parametrize(
292
+ ['cond', 'value'],
293
+ [
294
+ (cirq.BitMaskKeyCondition('c', bitmask=13, target_value=9), False),
295
+ (cirq.BitMaskKeyCondition('d', bitmask=13, target_value=12, equal_target=True), True),
296
+ ],
297
+ )
298
+ def test_bitmask_condition_resolve(cond: cirq.BitMaskKeyCondition, value: bool):
299
+ resolver = cirq.ClassicalDataDictionaryStore(
300
+ _records={
301
+ cirq.MeasurementKey('c'): [(1, 0, 0, 1)],
302
+ cirq.MeasurementKey('d'): [(1, 0, 1, 1, 0, 0)],
303
+ }
304
+ )
305
+ assert cond.resolve(resolver) == value
306
+
307
+
308
+ def test_bitmask_condition_resolve_invalid_input_raises():
309
+ cond = cirq.BitMaskKeyCondition('a')
310
+ resolver = cirq.ClassicalDataDictionaryStore(
311
+ _records={
312
+ cirq.MeasurementKey('c'): [(1, 0, 0, 1)],
313
+ cirq.MeasurementKey('d'): [(1, 0, 1, 1, 0, 0)],
314
+ }
315
+ )
316
+ with pytest.raises(ValueError):
317
+ _ = cond.resolve(resolver)
318
+
319
+
320
+ @pytest.mark.parametrize(
321
+ 'cond',
322
+ [
323
+ cirq.BitMaskKeyCondition(
324
+ bitmask=None, equal_target=False, index=59, key='a', target_value=0
325
+ ),
326
+ cirq.BitMaskKeyCondition(
327
+ bitmask=None, equal_target=False, index=-1, key='a', target_value=0
328
+ ),
329
+ cirq.BitMaskKeyCondition(
330
+ bitmask=None, equal_target=False, index=58, key='b', target_value=3
331
+ ),
332
+ cirq.BitMaskKeyCondition(
333
+ bitmask=None, equal_target=False, index=-1, key='b', target_value=3
334
+ ),
335
+ cirq.BitMaskKeyCondition(bitmask=13, equal_target=False, index=57, key='c', target_value=0),
336
+ cirq.BitMaskKeyCondition(bitmask=13, equal_target=False, index=-1, key='c', target_value=0),
337
+ cirq.BitMaskKeyCondition(
338
+ bitmask=13, equal_target=False, index=56, key='d', target_value=12
339
+ ),
340
+ cirq.BitMaskKeyCondition(
341
+ bitmask=13, equal_target=False, index=-1, key='d', target_value=12
342
+ ),
343
+ cirq.BitMaskKeyCondition(bitmask=13, equal_target=True, index=55, key='d', target_value=12),
344
+ cirq.BitMaskKeyCondition(bitmask=13, equal_target=True, index=-1, key='d', target_value=12),
345
+ cirq.BitMaskKeyCondition(bitmask=11, equal_target=True, index=54, key='e', target_value=11),
346
+ cirq.BitMaskKeyCondition(bitmask=11, equal_target=True, index=-1, key='e', target_value=11),
347
+ cirq.BitMaskKeyCondition(bitmask=9, equal_target=False, index=53, key='e', target_value=9),
348
+ cirq.BitMaskKeyCondition(bitmask=9, equal_target=False, index=-1, key='e', target_value=9),
349
+ ],
350
+ )
351
+ def test_bitmask_condition_repr(cond):
352
+ cirq.testing.assert_equivalent_repr(cond)
353
+
354
+
355
+ def test_bitmask_condition_keys():
356
+ assert cirq.BitMaskKeyCondition('test').keys == ('test',)
357
+
358
+
359
+ def test_bitmask_create_equal_mask():
360
+ assert cirq.BitMaskKeyCondition.create_equal_mask('a', 9) == cirq.BitMaskKeyCondition(
361
+ 'a', equal_target=True, bitmask=9, target_value=9
362
+ )
363
+
364
+
365
+ def test_bitmask_create_not_equal_mask():
366
+ assert cirq.BitMaskKeyCondition.create_not_equal_mask('b', 14) == cirq.BitMaskKeyCondition(
367
+ 'b', equal_target=False, bitmask=14, target_value=14
368
+ )
369
+
370
+
371
+ def test_bitmask_replace_key():
372
+ cond = cirq.BitMaskKeyCondition('a')
373
+ assert cond.replace_key('a', 'b') == cirq.BitMaskKeyCondition('b')
374
+ assert cond.replace_key('c', 'd') is cond
cirq/value/digits.py CHANGED
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from typing import List, Iterable, Any, Union, Optional, overload
15
+ from typing import Any, Iterable, List, Optional, overload, Union
16
16
 
17
17
 
18
18
  def big_endian_bits_to_int(bits: Iterable[Any]) -> int:
cirq/value/duration.py CHANGED
@@ -13,14 +13,14 @@
13
13
  # limitations under the License.
14
14
  """A typed time delta that supports picosecond accuracy."""
15
15
 
16
- from typing import AbstractSet, Any, Dict, Optional, Tuple, TYPE_CHECKING, Union, List
17
16
  import datetime
17
+ from typing import AbstractSet, Any, Dict, List, Optional, Tuple, TYPE_CHECKING, Union
18
18
 
19
- import sympy
20
19
  import numpy as np
20
+ import sympy
21
21
 
22
22
  from cirq import protocols
23
- from cirq._compat import proper_repr, cached_method
23
+ from cirq._compat import cached_method, proper_repr
24
24
  from cirq._doc import document
25
25
 
26
26
  if TYPE_CHECKING:
@@ -165,7 +165,7 @@ class Duration:
165
165
  if other_duration is not None:
166
166
  return self.total_picos() / other_duration.total_picos()
167
167
 
168
- return NotImplemented
168
+ return NotImplemented # pragma: no cover
169
169
 
170
170
  def __eq__(self, other):
171
171
  other = _attempt_duration_like_to_duration(other)
@@ -13,9 +13,10 @@
13
13
  # limitations under the License.
14
14
 
15
15
  from datetime import timedelta
16
+
17
+ import numpy as np
16
18
  import pytest
17
19
  import sympy
18
- import numpy as np
19
20
 
20
21
  import cirq
21
22
  from cirq.value import Duration