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
@@ -0,0 +1,523 @@
1
+ # Copyright 2025 The Cirq Developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import random
16
+ from typing import Dict, Sequence
17
+
18
+ import numpy as np
19
+ import pytest
20
+
21
+ import cirq
22
+ from cirq.contrib.paulistring import measure_pauli_strings
23
+ from cirq.experiments import SingleQubitReadoutCalibrationResult
24
+ from cirq.experiments.single_qubit_readout_calibration_test import NoisySingleQubitReadoutSampler
25
+
26
+
27
+ def _create_ghz(number_of_qubits: int, qubits: Sequence[cirq.Qid]) -> cirq.Circuit:
28
+ ghz_circuit = cirq.Circuit(
29
+ cirq.H(qubits[0]),
30
+ *[cirq.CNOT(qubits[i - 1], qubits[i]) for i in range(1, number_of_qubits)],
31
+ )
32
+ return ghz_circuit
33
+
34
+
35
+ def _generate_random_pauli_string(qubits: Sequence[cirq.Qid], enable_coeff: bool = False):
36
+ pauli_ops = [cirq.I, cirq.X, cirq.Y, cirq.Z]
37
+
38
+ operators = {q: random.choice(pauli_ops) for q in qubits}
39
+ # Ensure at least one non-identity.
40
+ operators[random.choice(qubits)] = random.choice(pauli_ops[1:])
41
+
42
+ if enable_coeff:
43
+ coefficient = (2 * random.random() - 1) * 100
44
+ return coefficient * cirq.PauliString(operators)
45
+ return cirq.PauliString(operators)
46
+
47
+
48
+ def _ideal_expectation_based_on_pauli_string(
49
+ pauli_string: cirq.PauliString, final_state_vector: np.ndarray
50
+ ) -> float:
51
+ return pauli_string.expectation_from_state_vector(
52
+ final_state_vector, qubit_map={q: i for i, q in enumerate(pauli_string.qubits)}
53
+ )
54
+
55
+
56
+ def test_pauli_string_measurement_errors_no_noise() -> None:
57
+ """Test that the mitigated expectation is close to the ideal expectation
58
+ based on the Pauli string"""
59
+
60
+ qubits = cirq.LineQubit.range(5)
61
+ circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
62
+ sampler = cirq.Simulator()
63
+
64
+ circuits_to_pauli: Dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
65
+ circuits_to_pauli[circuit] = [_generate_random_pauli_string(qubits) for _ in range(3)]
66
+
67
+ circuits_with_pauli_expectations = measure_pauli_strings(
68
+ circuits_to_pauli, sampler, 1000, 1000, 1000, 1000
69
+ )
70
+
71
+ for circuit_with_pauli_expectations in circuits_with_pauli_expectations:
72
+ assert isinstance(circuit_with_pauli_expectations.circuit, cirq.FrozenCircuit)
73
+
74
+ expected_val_simulation = sampler.simulate(
75
+ circuit_with_pauli_expectations.circuit.unfreeze()
76
+ )
77
+ final_state_vector = expected_val_simulation.final_state_vector
78
+
79
+ for pauli_string_measurement_results in circuit_with_pauli_expectations.results:
80
+ # Since there is no noise, the mitigated and unmitigated expectations should be the same
81
+ assert np.isclose(
82
+ pauli_string_measurement_results.mitigated_expectation,
83
+ pauli_string_measurement_results.unmitigated_expectation,
84
+ )
85
+ assert np.isclose(
86
+ pauli_string_measurement_results.mitigated_expectation,
87
+ _ideal_expectation_based_on_pauli_string(
88
+ pauli_string_measurement_results.pauli_string, final_state_vector
89
+ ),
90
+ atol=4 * pauli_string_measurement_results.mitigated_stddev,
91
+ )
92
+ assert isinstance(
93
+ pauli_string_measurement_results.calibration_result,
94
+ SingleQubitReadoutCalibrationResult,
95
+ )
96
+ assert pauli_string_measurement_results.calibration_result.zero_state_errors == {
97
+ q: 0 for q in pauli_string_measurement_results.pauli_string.qubits
98
+ }
99
+ assert pauli_string_measurement_results.calibration_result.one_state_errors == {
100
+ q: 0 for q in pauli_string_measurement_results.pauli_string.qubits
101
+ }
102
+
103
+
104
+ def test_pauli_string_measurement_errors_with_coefficient_no_noise() -> None:
105
+ """Test that the mitigated expectation is close to the ideal expectation
106
+ based on the Pauli string"""
107
+
108
+ qubits = cirq.LineQubit.range(5)
109
+ circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
110
+ sampler = cirq.Simulator()
111
+
112
+ circuits_to_pauli: Dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
113
+ circuits_to_pauli[circuit] = [_generate_random_pauli_string(qubits, True) for _ in range(3)]
114
+
115
+ circuits_with_pauli_expectations = measure_pauli_strings(
116
+ circuits_to_pauli, sampler, 1000, 1000, 1000, 1000
117
+ )
118
+
119
+ for circuit_with_pauli_expectations in circuits_with_pauli_expectations:
120
+ assert isinstance(circuit_with_pauli_expectations.circuit, cirq.FrozenCircuit)
121
+
122
+ expected_val_simulation = sampler.simulate(
123
+ circuit_with_pauli_expectations.circuit.unfreeze()
124
+ )
125
+ final_state_vector = expected_val_simulation.final_state_vector
126
+
127
+ for pauli_string_measurement_results in circuit_with_pauli_expectations.results:
128
+ # Since there is no noise, the mitigated and unmitigated expectations should be the same
129
+ assert np.isclose(
130
+ pauli_string_measurement_results.mitigated_expectation,
131
+ pauli_string_measurement_results.unmitigated_expectation,
132
+ )
133
+ assert np.isclose(
134
+ pauli_string_measurement_results.mitigated_expectation,
135
+ _ideal_expectation_based_on_pauli_string(
136
+ pauli_string_measurement_results.pauli_string, final_state_vector
137
+ ),
138
+ atol=4 * pauli_string_measurement_results.mitigated_stddev,
139
+ )
140
+ assert isinstance(
141
+ pauli_string_measurement_results.calibration_result,
142
+ SingleQubitReadoutCalibrationResult,
143
+ )
144
+ assert pauli_string_measurement_results.calibration_result.zero_state_errors == {
145
+ q: 0 for q in pauli_string_measurement_results.pauli_string.qubits
146
+ }
147
+ assert pauli_string_measurement_results.calibration_result.one_state_errors == {
148
+ q: 0 for q in pauli_string_measurement_results.pauli_string.qubits
149
+ }
150
+
151
+
152
+ def test_pauli_string_measurement_errors_with_noise() -> None:
153
+ """Test that the mitigated expectation is close to the ideal expectation
154
+ based on the Pauli string"""
155
+ qubits = cirq.LineQubit.range(7)
156
+ circuit = cirq.FrozenCircuit(_create_ghz(7, qubits))
157
+ sampler = NoisySingleQubitReadoutSampler(p0=0.1, p1=0.005, seed=1234)
158
+ simulator = cirq.Simulator()
159
+
160
+ circuits_to_pauli: Dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
161
+ circuits_to_pauli[circuit] = [_generate_random_pauli_string(qubits) for _ in range(3)]
162
+
163
+ circuits_with_pauli_expectations = measure_pauli_strings(
164
+ circuits_to_pauli, sampler, 1000, 1000, 1000, np.random.default_rng()
165
+ )
166
+
167
+ for circuit_with_pauli_expectations in circuits_with_pauli_expectations:
168
+ assert isinstance(circuit_with_pauli_expectations.circuit, cirq.FrozenCircuit)
169
+
170
+ expected_val_simulation = simulator.simulate(
171
+ circuit_with_pauli_expectations.circuit.unfreeze()
172
+ )
173
+ final_state_vector = expected_val_simulation.final_state_vector
174
+
175
+ for pauli_string_measurement_results in circuit_with_pauli_expectations.results:
176
+ assert np.isclose(
177
+ pauli_string_measurement_results.mitigated_expectation,
178
+ _ideal_expectation_based_on_pauli_string(
179
+ pauli_string_measurement_results.pauli_string, final_state_vector
180
+ ),
181
+ atol=4 * pauli_string_measurement_results.mitigated_stddev,
182
+ )
183
+
184
+ assert isinstance(
185
+ pauli_string_measurement_results.calibration_result,
186
+ SingleQubitReadoutCalibrationResult,
187
+ )
188
+
189
+ for (
190
+ error
191
+ ) in pauli_string_measurement_results.calibration_result.zero_state_errors.values():
192
+ assert 0.08 < error < 0.12
193
+ for (
194
+ error
195
+ ) in pauli_string_measurement_results.calibration_result.one_state_errors.values():
196
+ assert 0.0045 < error < 0.0055
197
+
198
+
199
+ def test_many_circuits_input_measurement_with_noise() -> None:
200
+ """Test that the mitigated expectation is close to the ideal expectation
201
+ based on the Pauli string for multiple circuits"""
202
+ qubits_1 = cirq.LineQubit.range(3)
203
+ qubits_2 = [
204
+ cirq.GridQubit(0, 1),
205
+ cirq.GridQubit(1, 1),
206
+ cirq.GridQubit(1, 0),
207
+ cirq.GridQubit(1, 2),
208
+ cirq.GridQubit(2, 1),
209
+ ]
210
+ qubits_3 = cirq.LineQubit.range(8)
211
+
212
+ circuit_1 = cirq.FrozenCircuit(_create_ghz(3, qubits_1))
213
+ circuit_2 = cirq.FrozenCircuit(_create_ghz(5, qubits_2))
214
+ circuit_3 = cirq.FrozenCircuit(_create_ghz(8, qubits_3))
215
+
216
+ circuits_to_pauli: Dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
217
+ circuits_to_pauli[circuit_1] = [_generate_random_pauli_string(qubits_1) for _ in range(3)]
218
+ circuits_to_pauli[circuit_2] = [_generate_random_pauli_string(qubits_2) for _ in range(3)]
219
+ circuits_to_pauli[circuit_3] = [_generate_random_pauli_string(qubits_3) for _ in range(3)]
220
+
221
+ sampler = NoisySingleQubitReadoutSampler(p0=0.03, p1=0.005, seed=1234)
222
+ simulator = cirq.Simulator()
223
+
224
+ circuits_with_pauli_expectations = measure_pauli_strings(
225
+ circuits_to_pauli, sampler, 1000, 1000, 1000, np.random.default_rng()
226
+ )
227
+
228
+ for circuit_with_pauli_expectations in circuits_with_pauli_expectations:
229
+ assert isinstance(circuit_with_pauli_expectations.circuit, cirq.FrozenCircuit)
230
+
231
+ expected_val_simulation = simulator.simulate(
232
+ circuit_with_pauli_expectations.circuit.unfreeze()
233
+ )
234
+ final_state_vector = expected_val_simulation.final_state_vector
235
+
236
+ for pauli_string_measurement_results in circuit_with_pauli_expectations.results:
237
+ assert np.isclose(
238
+ pauli_string_measurement_results.mitigated_expectation,
239
+ _ideal_expectation_based_on_pauli_string(
240
+ pauli_string_measurement_results.pauli_string, final_state_vector
241
+ ),
242
+ atol=4 * pauli_string_measurement_results.mitigated_stddev,
243
+ )
244
+ assert isinstance(
245
+ pauli_string_measurement_results.calibration_result,
246
+ SingleQubitReadoutCalibrationResult,
247
+ )
248
+ for (
249
+ error
250
+ ) in pauli_string_measurement_results.calibration_result.zero_state_errors.values():
251
+ assert 0.025 < error < 0.035
252
+ for (
253
+ error
254
+ ) in pauli_string_measurement_results.calibration_result.one_state_errors.values():
255
+ assert 0.0045 < error < 0.0055
256
+
257
+
258
+ def test_allow_measurement_without_readout_mitigation() -> None:
259
+ """Test that the function allows to measure without error mitigation"""
260
+ qubits = cirq.LineQubit.range(7)
261
+ circuit = cirq.FrozenCircuit(_create_ghz(7, qubits))
262
+ sampler = NoisySingleQubitReadoutSampler(p0=0.1, p1=0.005, seed=1234)
263
+
264
+ circuits_to_pauli: Dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
265
+ circuits_to_pauli[circuit] = [
266
+ _generate_random_pauli_string(qubits, True),
267
+ _generate_random_pauli_string(qubits),
268
+ _generate_random_pauli_string(qubits),
269
+ ]
270
+
271
+ circuits_with_pauli_expectations = measure_pauli_strings(
272
+ circuits_to_pauli, sampler, 1000, 1000, 0, np.random.default_rng()
273
+ )
274
+
275
+ for circuit_with_pauli_expectations in circuits_with_pauli_expectations:
276
+ assert isinstance(circuit_with_pauli_expectations.circuit, cirq.FrozenCircuit)
277
+
278
+ for pauli_string_measurement_results in circuit_with_pauli_expectations.results:
279
+ # Since there's no mitigation, the mitigated and unmitigated expectations
280
+ # should be the same
281
+ assert np.isclose(
282
+ pauli_string_measurement_results.mitigated_expectation,
283
+ pauli_string_measurement_results.unmitigated_expectation,
284
+ )
285
+ assert pauli_string_measurement_results.calibration_result is None
286
+
287
+
288
+ def test_many_circuits_with_coefficient() -> None:
289
+ """Test that the mitigated expectation is close to the ideal expectation
290
+ based on the Pauli string for multiple circuits"""
291
+ qubits_1 = cirq.LineQubit.range(3)
292
+ qubits_2 = [
293
+ cirq.GridQubit(0, 1),
294
+ cirq.GridQubit(1, 1),
295
+ cirq.GridQubit(1, 0),
296
+ cirq.GridQubit(1, 2),
297
+ cirq.GridQubit(2, 1),
298
+ ]
299
+ qubits_3 = cirq.LineQubit.range(8)
300
+
301
+ circuit_1 = cirq.FrozenCircuit(_create_ghz(3, qubits_1))
302
+ circuit_2 = cirq.FrozenCircuit(_create_ghz(5, qubits_2))
303
+ circuit_3 = cirq.FrozenCircuit(_create_ghz(8, qubits_3))
304
+
305
+ circuits_to_pauli: Dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
306
+ circuits_to_pauli[circuit_1] = [_generate_random_pauli_string(qubits_1, True) for _ in range(3)]
307
+ circuits_to_pauli[circuit_2] = [_generate_random_pauli_string(qubits_2, True) for _ in range(3)]
308
+ circuits_to_pauli[circuit_3] = [_generate_random_pauli_string(qubits_3, True) for _ in range(3)]
309
+
310
+ sampler = NoisySingleQubitReadoutSampler(p0=0.03, p1=0.005, seed=1234)
311
+ simulator = cirq.Simulator()
312
+
313
+ circuits_with_pauli_expectations = measure_pauli_strings(
314
+ circuits_to_pauli, sampler, 1000, 1000, 1000, np.random.default_rng()
315
+ )
316
+
317
+ for circuit_with_pauli_expectations in circuits_with_pauli_expectations:
318
+ assert isinstance(circuit_with_pauli_expectations.circuit, cirq.FrozenCircuit)
319
+
320
+ expected_val_simulation = simulator.simulate(
321
+ circuit_with_pauli_expectations.circuit.unfreeze()
322
+ )
323
+ final_state_vector = expected_val_simulation.final_state_vector
324
+
325
+ for pauli_string_measurement_results in circuit_with_pauli_expectations.results:
326
+ assert np.isclose(
327
+ pauli_string_measurement_results.mitigated_expectation,
328
+ _ideal_expectation_based_on_pauli_string(
329
+ pauli_string_measurement_results.pauli_string, final_state_vector
330
+ ),
331
+ atol=4 * pauli_string_measurement_results.mitigated_stddev,
332
+ )
333
+ assert isinstance(
334
+ pauli_string_measurement_results.calibration_result,
335
+ SingleQubitReadoutCalibrationResult,
336
+ )
337
+ for (
338
+ error
339
+ ) in pauli_string_measurement_results.calibration_result.zero_state_errors.values():
340
+ assert 0.025 < error < 0.035
341
+ for (
342
+ error
343
+ ) in pauli_string_measurement_results.calibration_result.one_state_errors.values():
344
+ assert 0.0045 < error < 0.0055
345
+
346
+
347
+ def test_coefficient_not_real_number() -> None:
348
+ """Test that the coefficient of input pauli string is not real.
349
+ Should return error in this case"""
350
+ qubits_1 = cirq.LineQubit.range(3)
351
+ random_pauli_string = _generate_random_pauli_string(qubits_1, True) * (3 + 4j)
352
+ circuit_1 = cirq.FrozenCircuit(_create_ghz(3, qubits_1))
353
+
354
+ circuits_to_pauli: Dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
355
+ circuits_to_pauli[circuit_1] = [
356
+ random_pauli_string,
357
+ _generate_random_pauli_string(qubits_1, True),
358
+ _generate_random_pauli_string(qubits_1, True),
359
+ ]
360
+
361
+ with pytest.raises(
362
+ ValueError,
363
+ match="Cannot compute expectation value of a "
364
+ "non-Hermitian PauliString. Coefficient must be real.",
365
+ ):
366
+ measure_pauli_strings(
367
+ circuits_to_pauli, cirq.Simulator(), 1000, 1000, 1000, np.random.default_rng()
368
+ )
369
+
370
+
371
+ def test_empty_input_circuits_to_pauli_mapping() -> None:
372
+ """Test that the input circuits are empty."""
373
+
374
+ with pytest.raises(ValueError, match="Input circuits must not be empty."):
375
+ measure_pauli_strings(
376
+ [], # type: ignore[arg-type]
377
+ cirq.Simulator(),
378
+ 1000,
379
+ 1000,
380
+ 1000,
381
+ np.random.default_rng(),
382
+ )
383
+
384
+
385
+ def test_invalid_input_circuit_type() -> None:
386
+ """Test that the input circuit type is not frozen circuit"""
387
+ qubits = cirq.LineQubit.range(5)
388
+
389
+ qubits_to_pauli: Dict[tuple, list[cirq.PauliString]] = {}
390
+ qubits_to_pauli[tuple(qubits)] = [cirq.PauliString({q: cirq.X for q in qubits})]
391
+ with pytest.raises(
392
+ TypeError, match="All keys in 'circuits_to_pauli' must be FrozenCircuit instances."
393
+ ):
394
+ measure_pauli_strings(
395
+ qubits_to_pauli, # type: ignore[arg-type]
396
+ cirq.Simulator(),
397
+ 1000,
398
+ 1000,
399
+ 1000,
400
+ np.random.default_rng(),
401
+ )
402
+
403
+
404
+ def test_invalid_input_pauli_string_type() -> None:
405
+ """Test input circuit is not mapping to a paulistring"""
406
+ qubits_1 = cirq.LineQubit.range(5)
407
+ qubits_2 = [
408
+ cirq.GridQubit(0, 1),
409
+ cirq.GridQubit(1, 1),
410
+ cirq.GridQubit(1, 0),
411
+ cirq.GridQubit(1, 2),
412
+ cirq.GridQubit(2, 1),
413
+ ]
414
+
415
+ circuit_1 = cirq.FrozenCircuit(_create_ghz(5, qubits_1))
416
+ circuit_2 = cirq.FrozenCircuit(_create_ghz(5, qubits_2))
417
+
418
+ circuits_to_pauli: Dict[cirq.FrozenCircuit, cirq.FrozenCircuit] = {}
419
+ circuits_to_pauli[circuit_1] = circuit_2
420
+
421
+ with pytest.raises(
422
+ TypeError,
423
+ match="All elements in the Pauli string lists must be cirq.PauliString "
424
+ "instances, got <class 'cirq.circuits.moment.Moment'>.",
425
+ ):
426
+ measure_pauli_strings(
427
+ circuits_to_pauli, # type: ignore[arg-type]
428
+ cirq.Simulator(),
429
+ 1000,
430
+ 1000,
431
+ 1000,
432
+ np.random.default_rng(),
433
+ )
434
+
435
+
436
+ def test_all_pauli_strings_are_pauli_i() -> None:
437
+ """Test that all input pauli are pauli I"""
438
+ qubits_1 = cirq.LineQubit.range(5)
439
+ qubits_2 = [
440
+ cirq.GridQubit(0, 1),
441
+ cirq.GridQubit(1, 1),
442
+ cirq.GridQubit(1, 0),
443
+ cirq.GridQubit(1, 2),
444
+ cirq.GridQubit(2, 1),
445
+ ]
446
+
447
+ circuit_1 = cirq.FrozenCircuit(_create_ghz(5, qubits_1))
448
+ circuit_2 = cirq.FrozenCircuit(_create_ghz(5, qubits_2))
449
+
450
+ circuits_to_pauli: Dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
451
+ circuits_to_pauli[circuit_1] = [
452
+ cirq.PauliString({q: cirq.I for q in qubits_1}),
453
+ cirq.PauliString({q: cirq.X for q in qubits_1}),
454
+ ]
455
+ circuits_to_pauli[circuit_2] = [cirq.PauliString({q: cirq.X for q in qubits_2})]
456
+
457
+ with pytest.raises(
458
+ ValueError,
459
+ match="Empty Pauli strings or Pauli strings consisting "
460
+ "only of Pauli I are not allowed. Please provide "
461
+ "valid input Pauli strings.",
462
+ ):
463
+ measure_pauli_strings(
464
+ circuits_to_pauli, cirq.Simulator(), 1000, 1000, 1000, np.random.default_rng()
465
+ )
466
+
467
+
468
+ def test_zero_pauli_repetitions() -> None:
469
+ """Test that the pauli repetitions are zero."""
470
+ qubits = cirq.LineQubit.range(5)
471
+
472
+ circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
473
+
474
+ circuits_to_pauli: Dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
475
+ circuits_to_pauli[circuit] = [cirq.PauliString({q: cirq.X for q in qubits})]
476
+ with pytest.raises(ValueError, match="Must provide non-zero pauli_repetitions."):
477
+ measure_pauli_strings(
478
+ circuits_to_pauli, cirq.Simulator(), 0, 1000, 1000, np.random.default_rng()
479
+ )
480
+
481
+
482
+ def test_negative_num_random_bitstrings() -> None:
483
+ """Test that the number of random bitstrings is smaller than zero."""
484
+ qubits = cirq.LineQubit.range(5)
485
+
486
+ circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
487
+
488
+ circuits_to_pauli: Dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
489
+ circuits_to_pauli[circuit] = [cirq.PauliString({q: cirq.X for q in qubits})]
490
+ with pytest.raises(ValueError, match="Must provide zero or more num_random_bitstrings."):
491
+ measure_pauli_strings(
492
+ circuits_to_pauli, cirq.Simulator(), 1000, 1000, -1, np.random.default_rng()
493
+ )
494
+
495
+
496
+ def test_zero_readout_repetitions() -> None:
497
+ """Test that the readout repetitions is zero."""
498
+ qubits = cirq.LineQubit.range(5)
499
+
500
+ circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
501
+
502
+ circuits_to_pauli: Dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
503
+ circuits_to_pauli[circuit] = [cirq.PauliString({q: cirq.X for q in qubits})]
504
+ with pytest.raises(
505
+ ValueError, match="Must provide non-zero readout_repetitions for readout" + " calibration."
506
+ ):
507
+ measure_pauli_strings(
508
+ circuits_to_pauli, cirq.Simulator(), 1000, 0, 1000, np.random.default_rng()
509
+ )
510
+
511
+
512
+ def test_rng_type_mismatch() -> None:
513
+ """Test that the rng is not a numpy random generator or a seed."""
514
+ qubits = cirq.LineQubit.range(5)
515
+
516
+ circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
517
+
518
+ circuits_to_pauli: Dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
519
+ circuits_to_pauli[circuit] = [cirq.PauliString({q: cirq.X for q in qubits})]
520
+ with pytest.raises(ValueError, match="Must provide a numpy random generator or a seed"):
521
+ measure_pauli_strings(
522
+ circuits_to_pauli, cirq.Simulator(), 1000, 1000, 1000, "test" # type: ignore[arg-type]
523
+ )
@@ -46,7 +46,9 @@ def pauli_string_optimized_circuit(
46
46
  def assert_no_multi_qubit_pauli_strings(circuit: circuits.Circuit) -> None:
47
47
  for op in circuit.all_operations():
48
48
  if isinstance(op, PauliStringGateOperation):
49
- assert len(op.pauli_string) == 1, 'Multi qubit Pauli string left over'
49
+ assert (
50
+ len(op.pauli_string) == 1
51
+ ), 'Multi qubit Pauli string left over' # pragma: no cover
50
52
 
51
53
 
52
54
  def merge_equal_strings(string_dag: circuitdag.CircuitDag) -> None:
@@ -12,10 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
-
16
15
  import cirq
17
-
18
- from cirq.contrib.paulistring import pauli_string_optimized_circuit, CliffordTargetGateset
16
+ from cirq.contrib.paulistring import CliffordTargetGateset, pauli_string_optimized_circuit
19
17
 
20
18
 
21
19
  def test_optimize():
@@ -12,13 +12,13 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from typing import Any, Callable, Iterable, Sequence, Tuple, Union, cast, List
15
+ from typing import Any, Callable, cast, Iterable, List, Sequence, Tuple, Union
16
16
 
17
17
  from cirq import circuits, ops, protocols
18
18
  from cirq.contrib import circuitdag
19
19
  from cirq.contrib.paulistring.pauli_string_dag import (
20
- pauli_string_reorder_pred,
21
20
  pauli_string_dag_from_circuit,
21
+ pauli_string_reorder_pred,
22
22
  )
23
23
 
24
24
 
@@ -15,15 +15,15 @@
15
15
  import cirq
16
16
  from cirq.contrib.paulistring import (
17
17
  convert_and_separate_circuit,
18
- pauli_string_dag_from_circuit,
19
18
  move_pauli_strings_into_circuit,
19
+ pauli_string_dag_from_circuit,
20
20
  )
21
21
 
22
22
 
23
23
  def _assert_no_multi_qubit_pauli_strings(circuit: cirq.Circuit) -> None:
24
24
  for op in circuit.all_operations():
25
25
  if isinstance(op, cirq.PauliStringGateOperation):
26
- assert len(op.pauli_string) == 1
26
+ assert len(op.pauli_string) == 1 # pragma: no cover
27
27
 
28
28
 
29
29
  def test_move_non_clifford_into_clifford():
@@ -12,10 +12,9 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from typing import Tuple
16
-
17
- from cirq import ops, circuits, transformers
15
+ from typing import Iterator, Tuple
18
16
 
17
+ from cirq import circuits, ops, transformers
19
18
  from cirq.contrib.paulistring.clifford_target_gateset import CliffordTargetGateset
20
19
 
21
20
 
@@ -89,7 +88,7 @@ def pauli_string_half(circuit: circuits.Circuit) -> circuits.Circuit:
89
88
  )
90
89
 
91
90
 
92
- def _pull_non_clifford_before(circuit: circuits.Circuit) -> ops.OP_TREE:
91
+ def _pull_non_clifford_before(circuit: circuits.Circuit) -> Iterator[ops.OP_TREE]:
93
92
  def _iter_ops_range_reversed(moment_end):
94
93
  for i in reversed(range(moment_end)):
95
94
  moment = circuit[i]
@@ -12,5 +12,5 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from cirq.contrib.qasm_import.exception import QasmException
16
- from cirq.contrib.qasm_import.qasm import circuit_from_qasm
15
+ from cirq.contrib.qasm_import.exception import QasmException as QasmException
16
+ from cirq.contrib.qasm_import.qasm import circuit_from_qasm as circuit_from_qasm