cirq-core 1.5.0.dev20250409222543__py3-none-any.whl → 1.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cirq-core might be problematic. Click here for more details.

Files changed (732) hide show
  1. cirq/__init__.py +16 -17
  2. cirq/_compat.py +21 -20
  3. cirq/_compat_test.py +14 -34
  4. cirq/_doc.py +4 -2
  5. cirq/_import.py +8 -6
  6. cirq/_import_test.py +4 -2
  7. cirq/_version.py +6 -6
  8. cirq/_version_test.py +2 -2
  9. cirq/circuits/_block_diagram_drawer.py +11 -10
  10. cirq/circuits/_block_diagram_drawer_test.py +8 -6
  11. cirq/circuits/_box_drawing_character_data.py +8 -8
  12. cirq/circuits/_box_drawing_character_data_test.py +3 -1
  13. cirq/circuits/_bucket_priority_queue.py +9 -7
  14. cirq/circuits/_bucket_priority_queue_test.py +22 -20
  15. cirq/circuits/circuit.py +248 -172
  16. cirq/circuits/circuit_operation.py +73 -83
  17. cirq/circuits/circuit_operation_test.py +128 -90
  18. cirq/circuits/circuit_test.py +211 -151
  19. cirq/circuits/frozen_circuit.py +23 -60
  20. cirq/circuits/frozen_circuit_test.py +31 -8
  21. cirq/circuits/insert_strategy.py +7 -5
  22. cirq/circuits/insert_strategy_test.py +4 -2
  23. cirq/circuits/moment.py +88 -40
  24. cirq/circuits/moment_test.py +128 -51
  25. cirq/circuits/optimization_pass.py +5 -5
  26. cirq/circuits/optimization_pass_test.py +10 -10
  27. cirq/circuits/qasm_output.py +11 -11
  28. cirq/circuits/qasm_output_test.py +25 -22
  29. cirq/circuits/text_diagram_drawer.py +23 -38
  30. cirq/circuits/text_diagram_drawer_test.py +19 -17
  31. cirq/conftest.py +4 -3
  32. cirq/contrib/__init__.py +4 -4
  33. cirq/contrib/acquaintance/__init__.py +1 -1
  34. cirq/contrib/acquaintance/bipartite.py +5 -8
  35. cirq/contrib/acquaintance/bipartite_test.py +18 -13
  36. cirq/contrib/acquaintance/devices.py +2 -2
  37. cirq/contrib/acquaintance/devices_test.py +5 -3
  38. cirq/contrib/acquaintance/executor.py +5 -5
  39. cirq/contrib/acquaintance/executor_test.py +13 -9
  40. cirq/contrib/acquaintance/gates.py +18 -28
  41. cirq/contrib/acquaintance/gates_test.py +24 -20
  42. cirq/contrib/acquaintance/inspection_utils.py +8 -4
  43. cirq/contrib/acquaintance/inspection_utils_test.py +4 -2
  44. cirq/contrib/acquaintance/mutation_utils.py +4 -4
  45. cirq/contrib/acquaintance/mutation_utils_test.py +4 -2
  46. cirq/contrib/acquaintance/optimizers.py +4 -4
  47. cirq/contrib/acquaintance/optimizers_test.py +4 -1
  48. cirq/contrib/acquaintance/permutation.py +15 -27
  49. cirq/contrib/acquaintance/permutation_test.py +26 -17
  50. cirq/contrib/acquaintance/shift.py +4 -4
  51. cirq/contrib/acquaintance/shift_swap_network.py +4 -4
  52. cirq/contrib/acquaintance/shift_swap_network_test.py +9 -6
  53. cirq/contrib/acquaintance/shift_test.py +8 -6
  54. cirq/contrib/acquaintance/strategies/cubic.py +2 -2
  55. cirq/contrib/acquaintance/strategies/cubic_test.py +4 -2
  56. cirq/contrib/acquaintance/strategies/quartic_paired.py +6 -6
  57. cirq/contrib/acquaintance/strategies/quartic_paired_test.py +10 -6
  58. cirq/contrib/acquaintance/testing.py +2 -0
  59. cirq/contrib/acquaintance/topological_sort.py +2 -2
  60. cirq/contrib/acquaintance/topological_sort_test.py +3 -1
  61. cirq/contrib/bayesian_network/bayesian_network_gate.py +9 -10
  62. cirq/contrib/bayesian_network/bayesian_network_gate_test.py +14 -9
  63. cirq/contrib/circuitdag/circuit_dag.py +4 -4
  64. cirq/contrib/circuitdag/circuit_dag_test.py +17 -15
  65. cirq/contrib/custom_simulators/custom_state_simulator.py +5 -5
  66. cirq/contrib/custom_simulators/custom_state_simulator_test.py +22 -17
  67. cirq/contrib/graph_device/graph_device.py +12 -11
  68. cirq/contrib/graph_device/graph_device_test.py +18 -14
  69. cirq/contrib/graph_device/hypergraph.py +16 -14
  70. cirq/contrib/graph_device/hypergraph_test.py +13 -11
  71. cirq/contrib/graph_device/uniform_graph_device.py +6 -4
  72. cirq/contrib/graph_device/uniform_graph_device_test.py +11 -3
  73. cirq/contrib/hacks/disable_validation.py +6 -1
  74. cirq/contrib/hacks/disable_validation_test.py +3 -1
  75. cirq/contrib/json.py +31 -5
  76. cirq/contrib/json_test.py +6 -3
  77. cirq/contrib/json_test_data/DampedReadoutNoiseModel.json +12 -0
  78. cirq/contrib/json_test_data/DampedReadoutNoiseModel.repr +4 -0
  79. cirq/contrib/json_test_data/DepolarizingNoiseModel.json +12 -0
  80. cirq/contrib/json_test_data/DepolarizingNoiseModel.repr +4 -0
  81. cirq/contrib/json_test_data/DepolarizingWithDampedReadoutNoiseModel.json +6 -0
  82. cirq/contrib/json_test_data/DepolarizingWithDampedReadoutNoiseModel.repr +1 -0
  83. cirq/contrib/json_test_data/DepolarizingWithReadoutNoiseModel.json +5 -0
  84. cirq/contrib/json_test_data/DepolarizingWithReadoutNoiseModel.repr +1 -0
  85. cirq/contrib/json_test_data/ReadoutNoiseModel.json +12 -0
  86. cirq/contrib/json_test_data/ReadoutNoiseModel.repr +4 -0
  87. cirq/contrib/json_test_data/__init__.py +17 -0
  88. cirq/contrib/json_test_data/spec.py +32 -0
  89. cirq/contrib/noise_models/noise_models.py +119 -5
  90. cirq/contrib/noise_models/noise_models_test.py +37 -9
  91. cirq/contrib/paulistring/clifford_optimize.py +6 -4
  92. cirq/contrib/paulistring/clifford_optimize_test.py +6 -5
  93. cirq/contrib/paulistring/clifford_target_gateset.py +10 -10
  94. cirq/contrib/paulistring/clifford_target_gateset_test.py +13 -11
  95. cirq/contrib/paulistring/optimize.py +2 -0
  96. cirq/contrib/paulistring/optimize_test.py +4 -3
  97. cirq/contrib/paulistring/pauli_string_dag.py +2 -0
  98. cirq/contrib/paulistring/pauli_string_dag_test.py +3 -1
  99. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +255 -120
  100. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +398 -19
  101. cirq/contrib/paulistring/pauli_string_optimize.py +7 -1
  102. cirq/contrib/paulistring/pauli_string_optimize_test.py +5 -3
  103. cirq/contrib/paulistring/recombine.py +6 -4
  104. cirq/contrib/paulistring/recombine_test.py +3 -1
  105. cirq/contrib/paulistring/separate.py +9 -6
  106. cirq/contrib/paulistring/separate_test.py +3 -1
  107. cirq/contrib/qasm_import/_lexer.py +3 -2
  108. cirq/contrib/qasm_import/_lexer_test.py +49 -13
  109. cirq/contrib/qasm_import/_parser.py +547 -83
  110. cirq/contrib/qasm_import/_parser_test.py +988 -97
  111. cirq/contrib/qasm_import/exception.py +2 -0
  112. cirq/contrib/qasm_import/qasm.py +8 -2
  113. cirq/contrib/qasm_import/qasm_test.py +7 -4
  114. cirq/contrib/qcircuit/qcircuit_diagram_info.py +5 -5
  115. cirq/contrib/qcircuit/qcircuit_diagram_info_test.py +4 -1
  116. cirq/contrib/qcircuit/qcircuit_pdf.py +7 -3
  117. cirq/contrib/qcircuit/qcircuit_pdf_test.py +3 -1
  118. cirq/contrib/qcircuit/qcircuit_test.py +10 -8
  119. cirq/contrib/quantum_volume/quantum_volume.py +31 -27
  120. cirq/contrib/quantum_volume/quantum_volume_test.py +19 -16
  121. cirq/contrib/quimb/density_matrix.py +15 -14
  122. cirq/contrib/quimb/density_matrix_test.py +10 -7
  123. cirq/contrib/quimb/grid_circuits.py +5 -2
  124. cirq/contrib/quimb/grid_circuits_test.py +3 -0
  125. cirq/contrib/quimb/mps_simulator.py +20 -20
  126. cirq/contrib/quimb/mps_simulator_test.py +3 -0
  127. cirq/contrib/quimb/state_vector.py +12 -11
  128. cirq/contrib/quimb/state_vector_test.py +3 -0
  129. cirq/contrib/quirk/export_to_quirk.py +5 -3
  130. cirq/contrib/quirk/export_to_quirk_test.py +18 -16
  131. cirq/contrib/quirk/linearize_circuit.py +2 -0
  132. cirq/contrib/quirk/quirk_gate.py +18 -17
  133. cirq/contrib/routing/device.py +5 -3
  134. cirq/contrib/routing/device_test.py +2 -0
  135. cirq/contrib/routing/greedy.py +10 -21
  136. cirq/contrib/routing/greedy_test.py +4 -2
  137. cirq/contrib/routing/initialization.py +2 -2
  138. cirq/contrib/routing/initialization_test.py +5 -3
  139. cirq/contrib/routing/router.py +9 -5
  140. cirq/contrib/routing/router_test.py +2 -0
  141. cirq/contrib/routing/swap_network.py +3 -3
  142. cirq/contrib/routing/swap_network_test.py +3 -1
  143. cirq/contrib/routing/utils.py +2 -2
  144. cirq/contrib/routing/utils_test.py +3 -0
  145. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +15 -9
  146. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking_test.py +3 -0
  147. cirq/contrib/svg/svg.py +3 -3
  148. cirq/contrib/svg/svg_test.py +8 -5
  149. cirq/devices/device.py +4 -4
  150. cirq/devices/device_test.py +7 -4
  151. cirq/devices/grid_device_metadata.py +10 -10
  152. cirq/devices/grid_device_metadata_test.py +3 -0
  153. cirq/devices/grid_qubit.py +29 -21
  154. cirq/devices/grid_qubit_test.py +3 -0
  155. cirq/devices/insertion_noise_model.py +7 -7
  156. cirq/devices/insertion_noise_model_test.py +7 -5
  157. cirq/devices/line_qubit.py +13 -13
  158. cirq/devices/line_qubit_test.py +2 -0
  159. cirq/devices/named_topologies.py +18 -29
  160. cirq/devices/named_topologies_test.py +13 -10
  161. cirq/devices/noise_model.py +3 -3
  162. cirq/devices/noise_model_test.py +19 -15
  163. cirq/devices/noise_properties.py +15 -6
  164. cirq/devices/noise_properties_test.py +34 -3
  165. cirq/devices/noise_utils.py +11 -9
  166. cirq/devices/noise_utils_test.py +2 -0
  167. cirq/devices/superconducting_qubits_noise_properties.py +23 -22
  168. cirq/devices/superconducting_qubits_noise_properties_test.py +6 -6
  169. cirq/devices/thermal_noise_model.py +107 -37
  170. cirq/devices/thermal_noise_model_test.py +21 -0
  171. cirq/devices/unconstrained_device.py +5 -3
  172. cirq/devices/unconstrained_device_test.py +2 -0
  173. cirq/experiments/__init__.py +4 -2
  174. cirq/experiments/benchmarking/__init__.py +17 -0
  175. cirq/experiments/benchmarking/parallel_xeb.py +677 -0
  176. cirq/experiments/benchmarking/parallel_xeb_test.py +447 -0
  177. cirq/experiments/fidelity_estimation.py +14 -8
  178. cirq/experiments/fidelity_estimation_test.py +3 -0
  179. cirq/experiments/n_qubit_tomography.py +17 -16
  180. cirq/experiments/n_qubit_tomography_test.py +8 -5
  181. cirq/experiments/purity_estimation.py +2 -0
  182. cirq/experiments/purity_estimation_test.py +2 -0
  183. cirq/experiments/qubit_characterizations.py +207 -103
  184. cirq/experiments/qubit_characterizations_test.py +40 -12
  185. cirq/experiments/random_quantum_circuit_generation.py +56 -70
  186. cirq/experiments/random_quantum_circuit_generation_test.py +11 -8
  187. cirq/experiments/readout_confusion_matrix.py +24 -22
  188. cirq/experiments/readout_confusion_matrix_test.py +2 -0
  189. cirq/experiments/single_qubit_readout_calibration.py +30 -15
  190. cirq/experiments/single_qubit_readout_calibration_test.py +5 -2
  191. cirq/experiments/t1_decay_experiment.py +9 -7
  192. cirq/experiments/t1_decay_experiment_test.py +13 -11
  193. cirq/experiments/t2_decay_experiment.py +16 -13
  194. cirq/experiments/t2_decay_experiment_test.py +2 -0
  195. cirq/experiments/two_qubit_xeb.py +64 -57
  196. cirq/experiments/two_qubit_xeb_test.py +10 -6
  197. cirq/experiments/xeb_fitting.py +39 -35
  198. cirq/experiments/xeb_sampling.py +37 -44
  199. cirq/experiments/xeb_sampling_test.py +3 -0
  200. cirq/experiments/xeb_simulation.py +14 -10
  201. cirq/experiments/xeb_simulation_test.py +5 -5
  202. cirq/experiments/z_phase_calibration.py +32 -29
  203. cirq/experiments/z_phase_calibration_test.py +3 -4
  204. cirq/interop/quirk/cells/__init__.py +1 -1
  205. cirq/interop/quirk/cells/all_cells.py +7 -2
  206. cirq/interop/quirk/cells/arithmetic_cells.py +29 -41
  207. cirq/interop/quirk/cells/arithmetic_cells_test.py +17 -14
  208. cirq/interop/quirk/cells/cell.py +19 -28
  209. cirq/interop/quirk/cells/cell_test.py +3 -0
  210. cirq/interop/quirk/cells/composite_cell.py +13 -28
  211. cirq/interop/quirk/cells/composite_cell_test.py +2 -0
  212. cirq/interop/quirk/cells/control_cells.py +15 -15
  213. cirq/interop/quirk/cells/control_cells_test.py +7 -5
  214. cirq/interop/quirk/cells/frequency_space_cells.py +4 -3
  215. cirq/interop/quirk/cells/frequency_space_cells_test.py +3 -1
  216. cirq/interop/quirk/cells/ignored_cells.py +3 -0
  217. cirq/interop/quirk/cells/ignored_cells_test.py +3 -1
  218. cirq/interop/quirk/cells/input_cells.py +7 -5
  219. cirq/interop/quirk/cells/input_cells_test.py +7 -5
  220. cirq/interop/quirk/cells/input_rotation_cells.py +15 -13
  221. cirq/interop/quirk/cells/input_rotation_cells_test.py +9 -7
  222. cirq/interop/quirk/cells/measurement_cells.py +5 -2
  223. cirq/interop/quirk/cells/measurement_cells_test.py +3 -1
  224. cirq/interop/quirk/cells/parse.py +22 -23
  225. cirq/interop/quirk/cells/parse_test.py +12 -10
  226. cirq/interop/quirk/cells/qubit_permutation_cells.py +5 -3
  227. cirq/interop/quirk/cells/qubit_permutation_cells_test.py +9 -7
  228. cirq/interop/quirk/cells/scalar_cells.py +4 -1
  229. cirq/interop/quirk/cells/scalar_cells_test.py +3 -1
  230. cirq/interop/quirk/cells/single_qubit_rotation_cells.py +5 -2
  231. cirq/interop/quirk/cells/single_qubit_rotation_cells_test.py +5 -3
  232. cirq/interop/quirk/cells/swap_cell.py +8 -6
  233. cirq/interop/quirk/cells/swap_cell_test.py +6 -4
  234. cirq/interop/quirk/cells/testing.py +6 -6
  235. cirq/interop/quirk/cells/testing_test.py +8 -6
  236. cirq/interop/quirk/cells/unsupported_cells.py +3 -0
  237. cirq/interop/quirk/cells/unsupported_cells_test.py +4 -2
  238. cirq/interop/quirk/url_to_circuit.py +23 -36
  239. cirq/interop/quirk/url_to_circuit_test.py +4 -1
  240. cirq/json_resolver_cache.py +14 -12
  241. cirq/linalg/__init__.py +4 -6
  242. cirq/linalg/combinators.py +7 -5
  243. cirq/linalg/combinators_test.py +10 -7
  244. cirq/linalg/decompositions.py +24 -35
  245. cirq/linalg/decompositions_test.py +3 -1
  246. cirq/linalg/diagonalize.py +6 -4
  247. cirq/linalg/diagonalize_test.py +15 -14
  248. cirq/linalg/operator_spaces.py +14 -14
  249. cirq/linalg/operator_spaces_test.py +13 -11
  250. cirq/linalg/predicates.py +18 -9
  251. cirq/linalg/predicates_test.py +5 -0
  252. cirq/linalg/tolerance.py +6 -3
  253. cirq/linalg/tolerance_test.py +6 -4
  254. cirq/linalg/transformations.py +23 -20
  255. cirq/linalg/transformations_test.py +73 -43
  256. cirq/neutral_atoms/convert_to_neutral_atom_gates.py +9 -3
  257. cirq/neutral_atoms/convert_to_neutral_atom_gates_test.py +3 -1
  258. cirq/neutral_atoms/neutral_atom_devices.py +2 -0
  259. cirq/ops/__init__.py +2 -0
  260. cirq/ops/arithmetic_operation.py +21 -21
  261. cirq/ops/arithmetic_operation_test.py +7 -8
  262. cirq/ops/boolean_hamiltonian.py +23 -22
  263. cirq/ops/boolean_hamiltonian_test.py +12 -9
  264. cirq/ops/classically_controlled_operation.py +31 -36
  265. cirq/ops/classically_controlled_operation_test.py +121 -117
  266. cirq/ops/clifford_gate.py +98 -81
  267. cirq/ops/clifford_gate_test.py +72 -57
  268. cirq/ops/common_channels.py +44 -44
  269. cirq/ops/common_channels_test.py +83 -81
  270. cirq/ops/common_gate_families.py +9 -7
  271. cirq/ops/common_gate_families_test.py +11 -7
  272. cirq/ops/common_gates.py +164 -183
  273. cirq/ops/common_gates_test.py +135 -95
  274. cirq/ops/control_values.py +23 -26
  275. cirq/ops/control_values_test.py +22 -20
  276. cirq/ops/controlled_gate.py +64 -112
  277. cirq/ops/controlled_gate_test.py +130 -35
  278. cirq/ops/controlled_operation.py +24 -35
  279. cirq/ops/controlled_operation_test.py +8 -6
  280. cirq/ops/dense_pauli_string.py +38 -49
  281. cirq/ops/dense_pauli_string_test.py +4 -2
  282. cirq/ops/diagonal_gate.py +18 -31
  283. cirq/ops/diagonal_gate_test.py +13 -13
  284. cirq/ops/eigen_gate.py +29 -29
  285. cirq/ops/eigen_gate_test.py +45 -28
  286. cirq/ops/fourier_transform.py +14 -20
  287. cirq/ops/fourier_transform_test.py +15 -12
  288. cirq/ops/fsim_gate.py +43 -42
  289. cirq/ops/fsim_gate_test.py +29 -29
  290. cirq/ops/gate_features.py +2 -0
  291. cirq/ops/gate_features_test.py +5 -3
  292. cirq/ops/gate_operation.py +43 -65
  293. cirq/ops/gate_operation_test.py +46 -42
  294. cirq/ops/gateset.py +28 -40
  295. cirq/ops/gateset_test.py +4 -2
  296. cirq/ops/global_phase_op.py +45 -20
  297. cirq/ops/global_phase_op_test.py +44 -20
  298. cirq/ops/greedy_qubit_manager.py +10 -8
  299. cirq/ops/greedy_qubit_manager_test.py +5 -3
  300. cirq/ops/identity.py +14 -12
  301. cirq/ops/identity_test.py +24 -20
  302. cirq/ops/kraus_channel.py +11 -8
  303. cirq/ops/kraus_channel_test.py +14 -11
  304. cirq/ops/linear_combinations.py +65 -77
  305. cirq/ops/linear_combinations_test.py +14 -9
  306. cirq/ops/matrix_gates.py +21 -18
  307. cirq/ops/matrix_gates_test.py +16 -0
  308. cirq/ops/measure_util.py +15 -20
  309. cirq/ops/measure_util_test.py +2 -0
  310. cirq/ops/measurement_gate.py +26 -37
  311. cirq/ops/measurement_gate_test.py +2 -0
  312. cirq/ops/mixed_unitary_channel.py +12 -9
  313. cirq/ops/mixed_unitary_channel_test.py +14 -11
  314. cirq/ops/named_qubit.py +16 -13
  315. cirq/ops/named_qubit_test.py +15 -13
  316. cirq/ops/op_tree.py +9 -7
  317. cirq/ops/op_tree_test.py +22 -19
  318. cirq/ops/parallel_gate.py +15 -17
  319. cirq/ops/parallel_gate_test.py +18 -16
  320. cirq/ops/parity_gates.py +23 -25
  321. cirq/ops/parity_gates_test.py +36 -32
  322. cirq/ops/pauli_gates.py +22 -21
  323. cirq/ops/pauli_gates_test.py +29 -20
  324. cirq/ops/pauli_interaction_gate.py +15 -19
  325. cirq/ops/pauli_interaction_gate_test.py +10 -8
  326. cirq/ops/pauli_measurement_gate.py +23 -35
  327. cirq/ops/pauli_measurement_gate_test.py +2 -0
  328. cirq/ops/pauli_string.py +92 -120
  329. cirq/ops/pauli_string_phasor.py +52 -45
  330. cirq/ops/pauli_string_phasor_test.py +4 -5
  331. cirq/ops/pauli_string_raw_types.py +9 -7
  332. cirq/ops/pauli_string_raw_types_test.py +2 -0
  333. cirq/ops/pauli_string_test.py +31 -154
  334. cirq/ops/pauli_sum_exponential.py +12 -12
  335. cirq/ops/pauli_sum_exponential_test.py +12 -10
  336. cirq/ops/permutation_gate.py +8 -6
  337. cirq/ops/permutation_gate_test.py +10 -8
  338. cirq/ops/phased_iswap_gate.py +16 -16
  339. cirq/ops/phased_iswap_gate_test.py +17 -15
  340. cirq/ops/phased_x_gate.py +16 -17
  341. cirq/ops/phased_x_gate_test.py +18 -16
  342. cirq/ops/phased_x_z_gate.py +24 -22
  343. cirq/ops/phased_x_z_gate_test.py +17 -11
  344. cirq/ops/projector.py +16 -11
  345. cirq/ops/projector_test.py +19 -16
  346. cirq/ops/qid_util.py +7 -5
  347. cirq/ops/qid_util_test.py +2 -0
  348. cirq/ops/qubit_manager.py +11 -9
  349. cirq/ops/qubit_manager_test.py +6 -4
  350. cirq/ops/qubit_order.py +11 -14
  351. cirq/ops/qubit_order_or_list.py +4 -2
  352. cirq/ops/qubit_order_test.py +12 -10
  353. cirq/ops/random_gate_channel.py +12 -10
  354. cirq/ops/random_gate_channel_test.py +14 -11
  355. cirq/ops/raw_types.py +109 -129
  356. cirq/ops/raw_types_test.py +63 -57
  357. cirq/ops/state_preparation_channel.py +7 -7
  358. cirq/ops/state_preparation_channel_test.py +11 -9
  359. cirq/ops/swap_gates.py +13 -15
  360. cirq/ops/swap_gates_test.py +19 -17
  361. cirq/ops/tags.py +5 -3
  362. cirq/ops/tags_test.py +4 -2
  363. cirq/ops/three_qubit_gates.py +43 -76
  364. cirq/ops/three_qubit_gates_test.py +19 -17
  365. cirq/ops/two_qubit_diagonal_gate.py +13 -13
  366. cirq/ops/two_qubit_diagonal_gate_test.py +10 -8
  367. cirq/ops/uniform_superposition_gate.py +5 -3
  368. cirq/ops/uniform_superposition_gate_test.py +5 -3
  369. cirq/ops/wait_gate.py +17 -14
  370. cirq/ops/wait_gate_test.py +9 -6
  371. cirq/protocols/__init__.py +0 -3
  372. cirq/protocols/act_on_protocol.py +8 -6
  373. cirq/protocols/act_on_protocol_test.py +15 -12
  374. cirq/protocols/apply_channel_protocol.py +10 -14
  375. cirq/protocols/apply_channel_protocol_test.py +2 -0
  376. cirq/protocols/apply_mixture_protocol.py +13 -42
  377. cirq/protocols/apply_mixture_protocol_test.py +7 -5
  378. cirq/protocols/apply_unitary_protocol.py +39 -34
  379. cirq/protocols/apply_unitary_protocol_test.py +4 -1
  380. cirq/protocols/approximate_equality_protocol.py +2 -0
  381. cirq/protocols/approximate_equality_protocol_test.py +2 -0
  382. cirq/protocols/circuit_diagram_info_protocol.py +58 -42
  383. cirq/protocols/circuit_diagram_info_protocol_test.py +70 -12
  384. cirq/protocols/commutes_protocol.py +8 -7
  385. cirq/protocols/commutes_protocol_test.py +2 -0
  386. cirq/protocols/control_key_protocol.py +6 -4
  387. cirq/protocols/control_key_protocol_test.py +3 -1
  388. cirq/protocols/decompose_protocol.py +49 -48
  389. cirq/protocols/decompose_protocol_test.py +27 -16
  390. cirq/protocols/equal_up_to_global_phase_protocol.py +2 -0
  391. cirq/protocols/equal_up_to_global_phase_protocol_test.py +9 -6
  392. cirq/protocols/has_stabilizer_effect_protocol.py +7 -5
  393. cirq/protocols/has_stabilizer_effect_protocol_test.py +7 -5
  394. cirq/protocols/has_unitary_protocol.py +10 -6
  395. cirq/protocols/has_unitary_protocol_test.py +13 -8
  396. cirq/protocols/hash_from_pickle_test.py +2 -11
  397. cirq/protocols/inverse_protocol.py +13 -16
  398. cirq/protocols/inverse_protocol_test.py +5 -3
  399. cirq/protocols/json_serialization.py +35 -54
  400. cirq/protocols/json_serialization_test.py +14 -21
  401. cirq/protocols/json_test_data/CXSWAP.json +46 -0
  402. cirq/protocols/json_test_data/CXSWAP.repr +13 -0
  403. cirq/protocols/json_test_data/CZSWAP.json +46 -0
  404. cirq/protocols/json_test_data/CZSWAP.repr +13 -0
  405. cirq/protocols/json_test_data/CircuitOperation.json +6 -3
  406. cirq/protocols/json_test_data/CircuitOperation.repr_inward +4 -2
  407. cirq/protocols/json_test_data/Moment.json +24 -1
  408. cirq/protocols/json_test_data/Moment.repr +6 -1
  409. cirq/protocols/json_test_data/ThermalNoiseModel.json +32 -0
  410. cirq/protocols/json_test_data/ThermalNoiseModel.repr +1 -0
  411. cirq/protocols/json_test_data/spec.py +6 -2
  412. cirq/protocols/kraus_protocol.py +47 -7
  413. cirq/protocols/kraus_protocol_test.py +86 -12
  414. cirq/protocols/measurement_key_protocol.py +15 -16
  415. cirq/protocols/measurement_key_protocol_test.py +13 -11
  416. cirq/protocols/mixture_protocol.py +7 -5
  417. cirq/protocols/mixture_protocol_test.py +4 -2
  418. cirq/protocols/mul_protocol.py +2 -3
  419. cirq/protocols/mul_protocol_test.py +2 -0
  420. cirq/protocols/pauli_expansion_protocol.py +6 -3
  421. cirq/protocols/pauli_expansion_protocol_test.py +5 -3
  422. cirq/protocols/phase_protocol.py +2 -0
  423. cirq/protocols/phase_protocol_test.py +3 -1
  424. cirq/protocols/pow_protocol.py +11 -16
  425. cirq/protocols/pow_protocol_test.py +2 -0
  426. cirq/protocols/qasm.py +14 -20
  427. cirq/protocols/qasm_test.py +6 -3
  428. cirq/protocols/qid_shape_protocol.py +8 -8
  429. cirq/protocols/qid_shape_protocol_test.py +3 -1
  430. cirq/protocols/resolve_parameters.py +5 -3
  431. cirq/protocols/resolve_parameters_test.py +8 -7
  432. cirq/protocols/trace_distance_bound.py +6 -4
  433. cirq/protocols/trace_distance_bound_test.py +3 -1
  434. cirq/protocols/unitary_protocol.py +17 -7
  435. cirq/protocols/unitary_protocol_test.py +12 -2
  436. cirq/qis/channels.py +6 -2
  437. cirq/qis/channels_test.py +20 -16
  438. cirq/qis/clifford_tableau.py +21 -19
  439. cirq/qis/clifford_tableau_test.py +2 -2
  440. cirq/qis/entropy.py +14 -3
  441. cirq/qis/entropy_test.py +3 -1
  442. cirq/qis/measures.py +13 -13
  443. cirq/qis/measures_test.py +20 -14
  444. cirq/qis/noise_utils.py +2 -0
  445. cirq/qis/noise_utils_test.py +9 -7
  446. cirq/qis/quantum_state_representation.py +7 -8
  447. cirq/qis/states.py +58 -56
  448. cirq/qis/states_test.py +2 -0
  449. cirq/sim/classical_simulator.py +23 -22
  450. cirq/sim/classical_simulator_test.py +2 -0
  451. cirq/sim/clifford/clifford_simulator.py +23 -21
  452. cirq/sim/clifford/clifford_simulator_test.py +7 -4
  453. cirq/sim/clifford/clifford_tableau_simulation_state.py +10 -7
  454. cirq/sim/clifford/clifford_tableau_simulation_state_test.py +5 -5
  455. cirq/sim/clifford/stabilizer_ch_form_simulation_state.py +8 -6
  456. cirq/sim/clifford/stabilizer_ch_form_simulation_state_test.py +8 -6
  457. cirq/sim/clifford/stabilizer_sampler.py +9 -7
  458. cirq/sim/clifford/stabilizer_sampler_test.py +4 -2
  459. cirq/sim/clifford/stabilizer_simulation_state.py +14 -13
  460. cirq/sim/clifford/stabilizer_simulation_state_test.py +6 -4
  461. cirq/sim/clifford/stabilizer_state_ch_form.py +13 -11
  462. cirq/sim/clifford/stabilizer_state_ch_form_test.py +4 -2
  463. cirq/sim/density_matrix_simulation_state.py +26 -27
  464. cirq/sim/density_matrix_simulation_state_test.py +10 -8
  465. cirq/sim/density_matrix_simulator.py +30 -28
  466. cirq/sim/density_matrix_simulator_test.py +48 -48
  467. cirq/sim/density_matrix_utils.py +13 -11
  468. cirq/sim/density_matrix_utils_test.py +38 -36
  469. cirq/sim/mux.py +33 -31
  470. cirq/sim/mux_test.py +3 -0
  471. cirq/sim/simulation_product_state.py +15 -15
  472. cirq/sim/simulation_product_state_test.py +29 -26
  473. cirq/sim/simulation_state.py +29 -38
  474. cirq/sim/simulation_state_base.py +21 -32
  475. cirq/sim/simulation_state_test.py +15 -13
  476. cirq/sim/simulation_utils.py +5 -2
  477. cirq/sim/simulation_utils_test.py +5 -2
  478. cirq/sim/simulator.py +90 -106
  479. cirq/sim/simulator_base.py +33 -45
  480. cirq/sim/simulator_base_test.py +20 -15
  481. cirq/sim/simulator_test.py +23 -14
  482. cirq/sim/sparse_simulator.py +19 -17
  483. cirq/sim/sparse_simulator_test.py +41 -40
  484. cirq/sim/state_vector.py +15 -12
  485. cirq/sim/state_vector_simulation_state.py +31 -31
  486. cirq/sim/state_vector_simulation_state_test.py +16 -14
  487. cirq/sim/state_vector_simulator.py +17 -14
  488. cirq/sim/state_vector_simulator_test.py +2 -0
  489. cirq/sim/state_vector_test.py +6 -3
  490. cirq/study/flatten_expressions.py +16 -15
  491. cirq/study/flatten_expressions_test.py +13 -11
  492. cirq/study/resolver.py +18 -17
  493. cirq/study/resolver_test.py +22 -20
  494. cirq/study/result.py +17 -27
  495. cirq/study/result_test.py +2 -0
  496. cirq/study/sweepable.py +12 -10
  497. cirq/study/sweepable_test.py +3 -0
  498. cirq/study/sweeps.py +42 -61
  499. cirq/study/sweeps_test.py +33 -0
  500. cirq/testing/__init__.py +7 -11
  501. cirq/testing/_compat_test_data/module_a/__init__.py +1 -0
  502. cirq/testing/_compat_test_data/module_a/module_b/__init__.py +1 -0
  503. cirq/testing/_compat_test_data/module_a/sub/__init__.py +1 -0
  504. cirq/testing/circuit_compare.py +8 -17
  505. cirq/testing/circuit_compare_test.py +2 -0
  506. cirq/testing/consistent_act_on.py +13 -11
  507. cirq/testing/consistent_act_on_test.py +5 -3
  508. cirq/testing/consistent_channels.py +2 -0
  509. cirq/testing/consistent_channels_test.py +10 -8
  510. cirq/testing/consistent_controlled_gate_op.py +5 -5
  511. cirq/testing/consistent_controlled_gate_op_test.py +18 -18
  512. cirq/testing/consistent_decomposition.py +2 -2
  513. cirq/testing/consistent_decomposition_test.py +4 -2
  514. cirq/testing/consistent_pauli_expansion.py +2 -0
  515. cirq/testing/consistent_pauli_expansion_test.py +3 -1
  516. cirq/testing/consistent_phase_by.py +2 -0
  517. cirq/testing/consistent_phase_by_test.py +3 -1
  518. cirq/testing/consistent_protocols.py +14 -20
  519. cirq/testing/consistent_protocols_test.py +13 -11
  520. cirq/testing/consistent_qasm.py +6 -4
  521. cirq/testing/consistent_qasm_test.py +7 -7
  522. cirq/testing/consistent_resolve_parameters.py +2 -0
  523. cirq/testing/consistent_specified_has_unitary.py +2 -2
  524. cirq/testing/consistent_specified_has_unitary_test.py +6 -4
  525. cirq/testing/consistent_unitary.py +1 -0
  526. cirq/testing/consistent_unitary_test.py +4 -2
  527. cirq/testing/deprecation.py +5 -2
  528. cirq/testing/deprecation_test.py +5 -2
  529. cirq/testing/devices.py +7 -4
  530. cirq/testing/devices_test.py +7 -4
  531. cirq/testing/equals_tester.py +4 -2
  532. cirq/testing/equals_tester_test.py +21 -17
  533. cirq/testing/equivalent_basis_map.py +6 -4
  534. cirq/testing/equivalent_basis_map_test.py +6 -4
  535. cirq/testing/equivalent_repr_eval.py +6 -4
  536. cirq/testing/equivalent_repr_eval_test.py +5 -3
  537. cirq/testing/gate_features.py +2 -0
  538. cirq/testing/gate_features_test.py +7 -5
  539. cirq/testing/json.py +19 -15
  540. cirq/testing/json_test.py +5 -3
  541. cirq/testing/lin_alg_utils.py +10 -11
  542. cirq/testing/lin_alg_utils_test.py +14 -12
  543. cirq/testing/logs.py +7 -6
  544. cirq/testing/logs_test.py +9 -7
  545. cirq/testing/no_identifier_qubit.py +4 -2
  546. cirq/testing/no_identifier_qubit_test.py +5 -3
  547. cirq/testing/op_tree.py +2 -0
  548. cirq/testing/op_tree_test.py +4 -1
  549. cirq/testing/order_tester.py +2 -0
  550. cirq/testing/order_tester_test.py +8 -6
  551. cirq/testing/pytest_utils.py +2 -0
  552. cirq/testing/pytest_utils_test.py +4 -2
  553. cirq/testing/random_circuit.py +21 -20
  554. cirq/testing/random_circuit_test.py +12 -9
  555. cirq/testing/repr_pretty_tester.py +1 -0
  556. cirq/testing/repr_pretty_tester_test.py +5 -3
  557. cirq/testing/routing_devices.py +4 -1
  558. cirq/testing/routing_devices_test.py +9 -6
  559. cirq/testing/sample_circuits.py +4 -1
  560. cirq/testing/sample_circuits_test.py +3 -1
  561. cirq/testing/sample_gates.py +3 -0
  562. cirq/testing/sample_gates_test.py +5 -2
  563. cirq/transformers/__init__.py +11 -4
  564. cirq/transformers/align.py +9 -7
  565. cirq/transformers/align_test.py +2 -0
  566. cirq/transformers/analytical_decompositions/__init__.py +3 -6
  567. cirq/transformers/analytical_decompositions/clifford_decomposition.py +18 -16
  568. cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +2 -0
  569. cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +19 -16
  570. cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +2 -0
  571. cirq/transformers/analytical_decompositions/cphase_to_fsim.py +11 -9
  572. cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +5 -3
  573. cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +5 -3
  574. cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +5 -3
  575. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +141 -44
  576. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +35 -1
  577. cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +8 -7
  578. cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py +2 -0
  579. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +7 -4
  580. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +3 -0
  581. cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +11 -19
  582. cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +8 -33
  583. cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +9 -11
  584. cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +2 -0
  585. cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +91 -27
  586. cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +36 -7
  587. cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +20 -21
  588. cirq/transformers/analytical_decompositions/two_qubit_to_fsim_test.py +8 -6
  589. cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +13 -15
  590. cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py +3 -1
  591. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +39 -41
  592. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +2 -0
  593. cirq/transformers/drop_empty_moments.py +5 -3
  594. cirq/transformers/drop_empty_moments_test.py +4 -2
  595. cirq/transformers/drop_negligible_operations.py +7 -5
  596. cirq/transformers/drop_negligible_operations_test.py +2 -0
  597. cirq/transformers/dynamical_decoupling.py +49 -42
  598. cirq/transformers/dynamical_decoupling_test.py +223 -205
  599. cirq/transformers/eject_phased_paulis.py +28 -26
  600. cirq/transformers/eject_phased_paulis_test.py +12 -9
  601. cirq/transformers/eject_z.py +12 -12
  602. cirq/transformers/eject_z_test.py +2 -2
  603. cirq/transformers/expand_composite.py +6 -4
  604. cirq/transformers/expand_composite_test.py +3 -1
  605. cirq/transformers/gauge_compiling/__init__.py +3 -1
  606. cirq/transformers/gauge_compiling/cphase_gauge.py +2 -0
  607. cirq/transformers/gauge_compiling/cphase_gauge_test.py +2 -0
  608. cirq/transformers/gauge_compiling/cz_gauge.py +2 -0
  609. cirq/transformers/gauge_compiling/cz_gauge_test.py +1 -0
  610. cirq/transformers/gauge_compiling/gauge_compiling.py +45 -41
  611. cirq/transformers/gauge_compiling/gauge_compiling_test.py +2 -0
  612. cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +1 -0
  613. cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +5 -1
  614. cirq/transformers/gauge_compiling/iswap_gauge.py +2 -0
  615. cirq/transformers/gauge_compiling/iswap_gauge_test.py +1 -0
  616. cirq/transformers/gauge_compiling/spin_inversion_gauge.py +2 -0
  617. cirq/transformers/gauge_compiling/spin_inversion_gauge_test.py +2 -0
  618. cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +7 -6
  619. cirq/transformers/gauge_compiling/sqrt_cz_gauge_test.py +2 -0
  620. cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +2 -0
  621. cirq/transformers/gauge_compiling/sqrt_iswap_gauge_test.py +2 -0
  622. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +6 -3
  623. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +3 -0
  624. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +12 -9
  625. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation_test.py +9 -7
  626. cirq/transformers/insertion_sort.py +8 -6
  627. cirq/transformers/insertion_sort_test.py +3 -1
  628. cirq/transformers/measurement_transformers.py +29 -29
  629. cirq/transformers/measurement_transformers_test.py +2 -0
  630. cirq/transformers/merge_k_qubit_gates.py +12 -10
  631. cirq/transformers/merge_k_qubit_gates_test.py +18 -18
  632. cirq/transformers/merge_single_qubit_gates.py +197 -20
  633. cirq/transformers/merge_single_qubit_gates_test.py +177 -5
  634. cirq/transformers/noise_adding.py +5 -3
  635. cirq/transformers/noise_adding_test.py +2 -0
  636. cirq/transformers/optimize_for_target_gateset.py +19 -17
  637. cirq/transformers/optimize_for_target_gateset_test.py +11 -8
  638. cirq/transformers/qubit_management_transformers.py +13 -11
  639. cirq/transformers/qubit_management_transformers_test.py +5 -3
  640. cirq/transformers/randomized_measurements.py +16 -14
  641. cirq/transformers/randomized_measurements_test.py +10 -4
  642. cirq/transformers/routing/initial_mapper.py +6 -4
  643. cirq/transformers/routing/initial_mapper_test.py +2 -0
  644. cirq/transformers/routing/line_initial_mapper.py +16 -14
  645. cirq/transformers/routing/line_initial_mapper_test.py +9 -7
  646. cirq/transformers/routing/mapping_manager.py +10 -10
  647. cirq/transformers/routing/mapping_manager_test.py +2 -0
  648. cirq/transformers/routing/route_circuit_cqc.py +33 -31
  649. cirq/transformers/routing/route_circuit_cqc_test.py +15 -13
  650. cirq/transformers/routing/visualize_routed_circuit.py +8 -7
  651. cirq/transformers/routing/visualize_routed_circuit_test.py +4 -2
  652. cirq/transformers/stratify.py +17 -15
  653. cirq/transformers/stratify_test.py +3 -0
  654. cirq/transformers/symbolize.py +103 -0
  655. cirq/transformers/symbolize_test.py +62 -0
  656. cirq/transformers/synchronize_terminal_measurements.py +10 -10
  657. cirq/transformers/synchronize_terminal_measurements_test.py +12 -10
  658. cirq/transformers/tag_transformers.py +97 -0
  659. cirq/transformers/tag_transformers_test.py +103 -0
  660. cirq/transformers/target_gatesets/compilation_target_gateset.py +21 -19
  661. cirq/transformers/target_gatesets/compilation_target_gateset_test.py +20 -16
  662. cirq/transformers/target_gatesets/cz_gateset.py +7 -5
  663. cirq/transformers/target_gatesets/cz_gateset_test.py +21 -19
  664. cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +9 -7
  665. cirq/transformers/target_gatesets/sqrt_iswap_gateset_test.py +25 -25
  666. cirq/transformers/transformer_api.py +34 -47
  667. cirq/transformers/transformer_api_test.py +9 -8
  668. cirq/transformers/transformer_primitives.py +39 -49
  669. cirq/transformers/transformer_primitives_test.py +10 -17
  670. cirq/value/abc_alt.py +6 -4
  671. cirq/value/abc_alt_test.py +5 -3
  672. cirq/value/angle.py +11 -12
  673. cirq/value/angle_test.py +5 -3
  674. cirq/value/classical_data.py +27 -27
  675. cirq/value/classical_data_test.py +11 -8
  676. cirq/value/condition.py +26 -24
  677. cirq/value/condition_test.py +2 -0
  678. cirq/value/digits.py +14 -11
  679. cirq/value/digits_test.py +2 -0
  680. cirq/value/duration.py +23 -20
  681. cirq/value/duration_test.py +2 -0
  682. cirq/value/linear_dict.py +25 -30
  683. cirq/value/linear_dict_test.py +10 -8
  684. cirq/value/measurement_key.py +12 -12
  685. cirq/value/measurement_key_test.py +2 -0
  686. cirq/value/periodic_value.py +4 -4
  687. cirq/value/periodic_value_test.py +11 -7
  688. cirq/value/probability.py +3 -1
  689. cirq/value/probability_test.py +4 -2
  690. cirq/value/product_state.py +15 -13
  691. cirq/value/product_state_test.py +4 -1
  692. cirq/value/random_state.py +2 -0
  693. cirq/value/random_state_test.py +5 -3
  694. cirq/value/timestamp.py +11 -7
  695. cirq/value/timestamp_test.py +14 -12
  696. cirq/value/type_alias.py +4 -4
  697. cirq/value/value_equality_attr.py +8 -9
  698. cirq/value/value_equality_attr_test.py +14 -11
  699. cirq/vis/density_matrix.py +3 -3
  700. cirq/vis/density_matrix_test.py +20 -17
  701. cirq/vis/heatmap.py +24 -37
  702. cirq/vis/heatmap_test.py +3 -0
  703. cirq/vis/histogram.py +9 -6
  704. cirq/vis/histogram_test.py +5 -2
  705. cirq/vis/state_histogram.py +10 -8
  706. cirq/vis/state_histogram_test.py +7 -5
  707. cirq/vis/vis_utils.py +4 -1
  708. cirq/vis/vis_utils_test.py +4 -1
  709. cirq/work/collector.py +12 -18
  710. cirq/work/collector_test.py +15 -10
  711. cirq/work/observable_grouping.py +6 -7
  712. cirq/work/observable_grouping_test.py +10 -9
  713. cirq/work/observable_measurement.py +47 -45
  714. cirq/work/observable_measurement_data.py +22 -17
  715. cirq/work/observable_measurement_data_test.py +4 -1
  716. cirq/work/observable_measurement_test.py +48 -29
  717. cirq/work/observable_readout_calibration.py +5 -2
  718. cirq/work/observable_readout_calibration_test.py +5 -2
  719. cirq/work/observable_settings.py +13 -22
  720. cirq/work/observable_settings_test.py +9 -7
  721. cirq/work/pauli_sum_collector.py +12 -10
  722. cirq/work/pauli_sum_collector_test.py +9 -9
  723. cirq/work/sampler.py +42 -43
  724. cirq/work/sampler_test.py +31 -24
  725. cirq/work/zeros_sampler.py +6 -4
  726. cirq/work/zeros_sampler_test.py +7 -5
  727. {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/METADATA +7 -8
  728. cirq_core-1.6.0.dist-info/RECORD +1241 -0
  729. {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/WHEEL +1 -1
  730. cirq_core-1.5.0.dev20250409222543.dist-info/RECORD +0 -1216
  731. {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/licenses/LICENSE +0 -0
  732. {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/top_level.txt +0 -0
@@ -11,18 +11,27 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
+
14
15
  """Tools for measuring expectation values of Pauli strings with readout error mitigation."""
16
+
17
+ from __future__ import annotations
18
+
19
+ import itertools
15
20
  import time
16
- from typing import Dict, List, Optional, Tuple, Union
21
+ from typing import cast, Sequence, TYPE_CHECKING
17
22
 
18
23
  import attrs
19
24
  import numpy as np
20
25
 
21
26
  from cirq import circuits, ops, work
22
27
  from cirq.contrib.shuffle_circuits import run_shuffled_with_readout_benchmarking
23
- from cirq.experiments import SingleQubitReadoutCalibrationResult
24
28
  from cirq.experiments.readout_confusion_matrix import TensoredConfusionMatrices
25
- from cirq.study import ResultDict
29
+
30
+ if TYPE_CHECKING:
31
+ from cirq.experiments.single_qubit_readout_calibration import (
32
+ SingleQubitReadoutCalibrationResult,
33
+ )
34
+ from cirq.study import ResultDict
26
35
 
27
36
 
28
37
  @attrs.frozen
@@ -43,7 +52,7 @@ class PauliStringMeasurementResult:
43
52
  mitigated_stddev: float
44
53
  unmitigated_expectation: float
45
54
  unmitigated_stddev: float
46
- calibration_result: Optional[SingleQubitReadoutCalibrationResult] = None
55
+ calibration_result: SingleQubitReadoutCalibrationResult | None = None
47
56
 
48
57
 
49
58
  @attrs.frozen
@@ -56,15 +65,81 @@ class CircuitToPauliStringsMeasurementResult:
56
65
  """
57
66
 
58
67
  circuit: circuits.FrozenCircuit
59
- results: List[PauliStringMeasurementResult]
68
+ results: list[PauliStringMeasurementResult]
69
+
70
+
71
+ def _commute_or_identity(
72
+ op1: ops.Pauli | ops.IdentityGate, op2: ops.Pauli | ops.IdentityGate
73
+ ) -> bool:
74
+ if op1 == ops.I or op2 == ops.I:
75
+ return True
76
+ return op1 == op2
77
+
78
+
79
+ def _are_two_pauli_strings_qubit_wise_commuting(
80
+ pauli_str1: ops.PauliString,
81
+ pauli_str2: ops.PauliString,
82
+ all_qubits: list[ops.Qid] | frozenset[ops.Qid],
83
+ ) -> bool:
84
+ for qubit in all_qubits:
85
+ op1 = pauli_str1.get(qubit, default=ops.I)
86
+ op2 = pauli_str2.get(qubit, default=ops.I)
87
+
88
+ if not _commute_or_identity(op1, op2):
89
+ return False
90
+ return True
91
+
92
+
93
+ def _validate_group_paulis_qwc(
94
+ pauli_strs: list[ops.PauliString], all_qubits: list[ops.Qid] | frozenset[ops.Qid]
95
+ ):
96
+ """Checks if a group of Pauli strings are Qubit-Wise Commuting.
97
+
98
+ Args:
99
+ pauli_strings: A list of cirq.PauliString objects.
100
+ all_qubits: A list of all qubits to consider for the QWC check.
101
+ The check is performed for each qubit in this list.
102
+
103
+ Returns:
104
+ True if the group is QWC, False otherwise.
105
+ """
106
+ if len(pauli_strs) <= 1:
107
+ return True
108
+ for p1, p2 in itertools.combinations(pauli_strs, 2):
109
+ if not _are_two_pauli_strings_qubit_wise_commuting(p1, p2, all_qubits):
110
+ return False
111
+ return True
112
+
113
+
114
+ def _validate_single_pauli_string(pauli_str: ops.PauliString):
115
+ if not isinstance(pauli_str, ops.PauliString):
116
+ raise TypeError(
117
+ f"All elements in the Pauli string lists must be cirq.PauliString "
118
+ f"instances, got {type(pauli_str)}."
119
+ )
120
+
121
+ if all(q == ops.I for q in pauli_str) or not pauli_str:
122
+ raise ValueError(
123
+ "Empty Pauli strings or Pauli strings consisting "
124
+ "only of Pauli I are not allowed. Please provide "
125
+ "valid input Pauli strings."
126
+ )
127
+ if pauli_str.coefficient.imag != 0:
128
+ raise ValueError(
129
+ "Cannot compute expectation value of a non-Hermitian PauliString. "
130
+ "Coefficient must be real."
131
+ )
60
132
 
61
133
 
62
134
  def _validate_input(
63
- circuits_to_pauli: Dict[circuits.FrozenCircuit, list[ops.PauliString]],
135
+ circuits_to_pauli: (
136
+ dict[circuits.FrozenCircuit, list[ops.PauliString]]
137
+ | dict[circuits.FrozenCircuit, list[list[ops.PauliString]]]
138
+ ),
64
139
  pauli_repetitions: int,
65
140
  readout_repetitions: int,
66
141
  num_random_bitstrings: int,
67
- rng_or_seed: Union[np.random.Generator, int],
142
+ rng_or_seed: np.random.Generator | int,
68
143
  ):
69
144
  if not circuits_to_pauli:
70
145
  raise ValueError("Input circuits must not be empty.")
@@ -73,25 +148,39 @@ def _validate_input(
73
148
  if not isinstance(circuit, circuits.FrozenCircuit):
74
149
  raise TypeError("All keys in 'circuits_to_pauli' must be FrozenCircuit instances.")
75
150
 
76
- for pauli_strings in circuits_to_pauli.values():
77
- for pauli_str in pauli_strings:
78
- if not isinstance(pauli_str, ops.PauliString):
79
- raise TypeError(
80
- f"All elements in the Pauli string lists must be cirq.PauliString "
81
- f"instances, got {type(pauli_str)}."
82
- )
83
-
84
- if all(q == ops.I for q in pauli_str):
85
- raise ValueError(
86
- "Empty Pauli strings or Pauli strings consisting "
87
- "only of Pauli I are not allowed. Please provide "
88
- "valid input Pauli strings."
89
- )
90
- if pauli_str.coefficient.imag != 0:
91
- raise ValueError(
92
- "Cannot compute expectation value of a non-Hermitian PauliString. "
93
- "Coefficient must be real."
94
- )
151
+ first_value: list[ops.PauliString] | list[list[ops.PauliString]] = next(
152
+ iter(circuits_to_pauli.values()) # type: ignore
153
+ )
154
+ for circuit, pauli_strs_list in circuits_to_pauli.items():
155
+ if isinstance(pauli_strs_list, Sequence) and isinstance(first_value[0], Sequence):
156
+ for pauli_strs in pauli_strs_list:
157
+ if not pauli_strs:
158
+ raise ValueError("Empty group of Pauli strings is not allowed")
159
+ if not (
160
+ isinstance(pauli_strs, Sequence) and isinstance(pauli_strs[0], ops.PauliString)
161
+ ):
162
+ raise TypeError(
163
+ f"Inconsistent type in list for circuit {circuit}. "
164
+ f"Expected all elements to be sequences of ops.PauliString, "
165
+ f"but found {type(pauli_strs)}."
166
+ )
167
+ if not _validate_group_paulis_qwc(pauli_strs, circuit.all_qubits()):
168
+ raise ValueError(
169
+ f"Pauli group containing {pauli_strs} is invalid: "
170
+ f"The group of Pauli strings are not "
171
+ f"Qubit-Wise Commuting with each other."
172
+ )
173
+ for pauli_str in pauli_strs:
174
+ _validate_single_pauli_string(pauli_str)
175
+ elif isinstance(pauli_strs_list, Sequence) and isinstance(first_value[0], ops.PauliString):
176
+ for pauli_str in pauli_strs_list: # type: ignore
177
+ _validate_single_pauli_string(pauli_str)
178
+ else:
179
+ raise TypeError(
180
+ f"Expected all elements to be either a sequence of PauliStrings"
181
+ f" or sequences of ops.PauliStrings. "
182
+ f"Got {type(pauli_strs_list)} instead."
183
+ )
95
184
 
96
185
  # Check rng is a numpy random generator
97
186
  if not isinstance(rng_or_seed, np.random.Generator) and not isinstance(rng_or_seed, int):
@@ -110,32 +199,44 @@ def _validate_input(
110
199
  raise ValueError("Must provide non-zero readout_repetitions for readout calibration.")
111
200
 
112
201
 
113
- def _pauli_string_to_basis_change_ops(
114
- pauli_string: ops.PauliString, qid_list: list[ops.Qid]
115
- ) -> List[ops.Operation]:
116
- """Creates operations to change to the eigenbasis of the given Pauli string.
117
-
118
- This function constructs a list of ops.Operation that performs basis changes
119
- necessary to measure the given pauli_string in the computational basis.
120
-
121
- Args:
122
- pauli_string: The Pauli string to diagonalize.
123
- qid_list: An ordered list of the qubits in the circuit.
124
-
125
- Returns:
126
- A list of Operations that, when applied before measurement in the
127
- computational basis, effectively measures in the eigenbasis of
128
- pauli_strings.
129
- """
202
+ def _normalize_input_paulis(
203
+ circuits_to_pauli: (
204
+ dict[circuits.FrozenCircuit, list[ops.PauliString]]
205
+ | dict[circuits.FrozenCircuit, list[list[ops.PauliString]]]
206
+ ),
207
+ ) -> dict[circuits.FrozenCircuit, list[list[ops.PauliString]]]:
208
+ first_value = next(iter(circuits_to_pauli.values()))
209
+ if (
210
+ first_value
211
+ and isinstance(first_value, list)
212
+ and isinstance(first_value[0], ops.PauliString)
213
+ ):
214
+ input_dict = cast(dict[circuits.FrozenCircuit, list[ops.PauliString]], circuits_to_pauli)
215
+ normalized_circuits_to_pauli: dict[circuits.FrozenCircuit, list[list[ops.PauliString]]] = {}
216
+ for circuit, paulis in input_dict.items():
217
+ normalized_circuits_to_pauli[circuit] = [[ps] for ps in paulis]
218
+ return normalized_circuits_to_pauli
219
+ return cast(dict[circuits.FrozenCircuit, list[list[ops.PauliString]]], circuits_to_pauli)
220
+
221
+
222
+ def _extract_readout_qubits(pauli_strings: list[ops.PauliString]) -> list[ops.Qid]:
223
+ """Extracts unique qubits from a list of QWC Pauli strings."""
224
+ return sorted(set(q for ps in pauli_strings for q in ps.qubits))
225
+
226
+
227
+ def _pauli_strings_to_basis_change_ops(
228
+ pauli_strings: list[ops.PauliString], qid_list: list[ops.Qid]
229
+ ):
130
230
  operations = []
131
- for qubit in qid_list: # Iterate over ALL qubits in the circuit
132
- if qubit in pauli_string:
133
- pauli_op = pauli_string[qubit]
231
+ for qubit in qid_list:
232
+ for pauli_str in pauli_strings:
233
+ pauli_op = pauli_str.get(qubit, default=ops.I)
134
234
  if pauli_op == ops.X:
135
235
  operations.append(ops.ry(-np.pi / 2)(qubit)) # =cirq.H
236
+ break
136
237
  elif pauli_op == ops.Y:
137
238
  operations.append(ops.rx(np.pi / 2)(qubit))
138
- # If pauli_op is Z or I, no operation needed
239
+ break
139
240
  return operations
140
241
 
141
242
 
@@ -185,14 +286,14 @@ def _build_many_one_qubits_empty_confusion_matrix(qubits_length: int) -> list[np
185
286
 
186
287
 
187
288
  def _process_pauli_measurement_results(
188
- qubits: List[ops.Qid],
189
- pauli_strings: List[ops.PauliString],
190
- circuit_results: List[ResultDict],
191
- calibration_results: Dict[Tuple[ops.Qid, ...], SingleQubitReadoutCalibrationResult],
289
+ qubits: Sequence[ops.Qid],
290
+ pauli_string_groups: list[list[ops.PauliString]],
291
+ circuit_results: list[ResultDict],
292
+ calibration_results: dict[tuple[ops.Qid, ...], SingleQubitReadoutCalibrationResult],
192
293
  pauli_repetitions: int,
193
294
  timestamp: float,
194
295
  disable_readout_mitigation: bool = False,
195
- ) -> List[PauliStringMeasurementResult]:
296
+ ) -> list[PauliStringMeasurementResult]:
196
297
  """Calculates both error-mitigated expectation values and unmitigated expectation values
197
298
  from measurement results.
198
299
 
@@ -203,10 +304,11 @@ def _process_pauli_measurement_results(
203
304
 
204
305
  Args:
205
306
  qubits: Qubits to build confusion matrices for. In a sorted order.
206
- pauli_strings: The list of PauliStrings that are measured.
307
+ pauli_string_groups: The lists of QWC Pauli string groups that are measured.
207
308
  circuit_results: A list of ResultDict obtained
208
309
  from running the Pauli measurement circuits.
209
- confusion_matrices: A list of confusion matrices from calibration results.
310
+ calibration_results: A dictionary of SingleQubitReadoutCalibrationResult
311
+ for tuples of qubits present in `pauli_string_groups`.
210
312
  pauli_repetitions: The number of repetitions used for Pauli string measurements.
211
313
  timestamp: The timestamp of the calibration results.
212
314
  disable_readout_mitigation: If set to True, returns no error-mitigated error
@@ -216,75 +318,97 @@ def _process_pauli_measurement_results(
216
318
  A list of PauliStringMeasurementResult.
217
319
  """
218
320
 
219
- pauli_measurement_results: List[PauliStringMeasurementResult] = []
321
+ pauli_measurement_results: list[PauliStringMeasurementResult] = []
220
322
 
221
- for pauli_index, circuit_result in enumerate(circuit_results):
323
+ for pauli_group_index, circuit_result in enumerate(circuit_results):
222
324
  measurement_results = circuit_result.measurements["m"]
325
+ pauli_strs = pauli_string_groups[pauli_group_index]
326
+ pauli_readout_qubits = _extract_readout_qubits(pauli_strs)
223
327
 
224
- pauli_string = pauli_strings[pauli_index]
225
- qubits_sorted = sorted(pauli_string.qubits)
226
- qubit_indices = [qubits.index(q) for q in qubits_sorted]
227
-
228
- confusion_matrices = (
229
- _build_many_one_qubits_confusion_matrix(calibration_results[tuple(qubits_sorted)])
230
- if disable_readout_mitigation is False
231
- else _build_many_one_qubits_empty_confusion_matrix(len(qubits_sorted))
232
- )
233
- tensored_cm = TensoredConfusionMatrices(
234
- confusion_matrices,
235
- [[q] for q in qubits_sorted],
236
- repetitions=pauli_repetitions,
237
- timestamp=timestamp,
328
+ calibration_result = (
329
+ calibration_results[tuple(pauli_readout_qubits)]
330
+ if not disable_readout_mitigation
331
+ else None
238
332
  )
239
333
 
240
- # Create a mask for the relevant qubits in the measurement results
241
- relevant_bits = measurement_results[:, qubit_indices]
334
+ for pauli_str in pauli_strs:
335
+ qubits_sorted = sorted(pauli_str.qubits)
336
+ qubit_indices = [qubits.index(q) for q in qubits_sorted]
242
337
 
243
- # Calculate the mitigated expectation.
244
- raw_mitigated_values, raw_d_m = tensored_cm.readout_mitigation_pauli_uncorrelated(
245
- qubits_sorted, relevant_bits
246
- )
247
- mitigated_values_with_coefficient = raw_mitigated_values * pauli_string.coefficient.real
248
- d_m_with_coefficient = raw_d_m * abs(pauli_string.coefficient.real)
249
-
250
- # Calculate the unmitigated expectation.
251
- parity = np.sum(relevant_bits, axis=1) % 2
252
- raw_unmitigated_values = 1 - 2 * np.mean(parity)
253
- raw_d_unmit = 2 * np.sqrt(np.mean(parity) * (1 - np.mean(parity)) / pauli_repetitions)
254
- unmitigated_value_with_coefficient = raw_unmitigated_values * pauli_string.coefficient
255
- d_unmit_with_coefficient = raw_d_unmit * abs(pauli_string.coefficient)
256
-
257
- pauli_measurement_results.append(
258
- PauliStringMeasurementResult(
259
- pauli_string=pauli_strings[pauli_index],
260
- mitigated_expectation=mitigated_values_with_coefficient,
261
- mitigated_stddev=d_m_with_coefficient,
262
- unmitigated_expectation=unmitigated_value_with_coefficient,
263
- unmitigated_stddev=d_unmit_with_coefficient,
264
- calibration_result=(
265
- calibration_results[tuple(qubits_sorted)]
266
- if disable_readout_mitigation is False
267
- else None
268
- ),
338
+ if disable_readout_mitigation:
339
+ pauli_str_calibration_result = None
340
+ confusion_matrices = _build_many_one_qubits_empty_confusion_matrix(
341
+ len(qubits_sorted)
342
+ )
343
+ else:
344
+ if calibration_result is None:
345
+ # This case should be logically impossible if mitigation is on,
346
+ # so we raise an error.
347
+ raise ValueError(
348
+ f"Readout mitigation is enabled, but no calibration result was "
349
+ f"found for qubits {pauli_readout_qubits}."
350
+ )
351
+ pauli_str_calibration_result = calibration_result.readout_result_for_qubits(
352
+ qubits_sorted
353
+ )
354
+ confusion_matrices = _build_many_one_qubits_confusion_matrix(
355
+ pauli_str_calibration_result
356
+ )
357
+
358
+ tensored_cm = TensoredConfusionMatrices(
359
+ confusion_matrices,
360
+ [[q] for q in qubits_sorted],
361
+ repetitions=pauli_repetitions,
362
+ timestamp=timestamp,
363
+ )
364
+
365
+ # Create a mask for the relevant qubits in the measurement results
366
+ relevant_bits = measurement_results[:, qubit_indices]
367
+
368
+ # Calculate the mitigated expectation.
369
+ raw_mitigated_values, raw_d_m = tensored_cm.readout_mitigation_pauli_uncorrelated(
370
+ qubits_sorted, relevant_bits
371
+ )
372
+ mitigated_values_with_coefficient = raw_mitigated_values * pauli_str.coefficient.real
373
+ d_m_with_coefficient = raw_d_m * abs(pauli_str.coefficient.real)
374
+
375
+ # Calculate the unmitigated expectation.
376
+ parity = np.sum(relevant_bits, axis=1) % 2
377
+ raw_unmitigated_values = 1 - 2 * np.mean(parity)
378
+ raw_d_unmit = 2 * np.sqrt(np.mean(parity) * (1 - np.mean(parity)) / pauli_repetitions)
379
+ unmitigated_value_with_coefficient = raw_unmitigated_values * pauli_str.coefficient.real
380
+ d_unmit_with_coefficient = raw_d_unmit * abs(pauli_str.coefficient.real)
381
+
382
+ pauli_measurement_results.append(
383
+ PauliStringMeasurementResult(
384
+ pauli_string=pauli_str,
385
+ mitigated_expectation=mitigated_values_with_coefficient,
386
+ mitigated_stddev=d_m_with_coefficient,
387
+ unmitigated_expectation=unmitigated_value_with_coefficient,
388
+ unmitigated_stddev=d_unmit_with_coefficient,
389
+ calibration_result=pauli_str_calibration_result,
390
+ )
269
391
  )
270
- )
271
392
 
272
393
  return pauli_measurement_results
273
394
 
274
395
 
275
396
  def measure_pauli_strings(
276
- circuits_to_pauli: Dict[circuits.FrozenCircuit, list[ops.PauliString]],
397
+ circuits_to_pauli: (
398
+ dict[circuits.FrozenCircuit, list[ops.PauliString]]
399
+ | dict[circuits.FrozenCircuit, list[list[ops.PauliString]]]
400
+ ),
277
401
  sampler: work.Sampler,
278
402
  pauli_repetitions: int,
279
403
  readout_repetitions: int,
280
404
  num_random_bitstrings: int,
281
- rng_or_seed: Union[np.random.Generator, int],
282
- ) -> List[CircuitToPauliStringsMeasurementResult]:
405
+ rng_or_seed: np.random.Generator | int,
406
+ ) -> list[CircuitToPauliStringsMeasurementResult]:
283
407
  """Measures expectation values of Pauli strings on given circuits with/without
284
408
  readout error mitigation.
285
409
 
286
- This function takes a list of circuits and corresponding List[PauliString] to measure.
287
- For each circuit-List[PauliString] pair, it:
410
+ This function takes a dictionary mapping circuits to lists of QWC Pauli string groups.
411
+ For each circuit and its associated list of QWC pauli string group, it:
288
412
  1. Constructs circuits to measure the Pauli string expectation value by
289
413
  adding basis change moments and measurement operations.
290
414
  2. Runs shuffled readout benchmarking on these circuits to calibrate readout errors.
@@ -293,8 +417,13 @@ def measure_pauli_strings(
293
417
  each Pauli string.
294
418
 
295
419
  Args:
296
- circuits_to_pauli: A dictionary mapping circuits to a list of Pauli strings
297
- to measure.
420
+ circuits_to_pauli: A dictionary mapping circuits to either:
421
+ - A list of QWC groups (list[list[ops.PauliString]]). Each QWC group
422
+ is a list of PauliStrings that are mutually Qubit-Wise Commuting.
423
+ Pauli strings within the same group will be calculated using the
424
+ same measurement results.
425
+ - A list of PauliStrings (list[ops.PauliString]). In this case, each
426
+ PauliString is treated as its own measurement group.
298
427
  sampler: The sampler to use.
299
428
  pauli_repetitions: The number of repetitions for each circuit when measuring
300
429
  Pauli strings.
@@ -319,24 +448,26 @@ def measure_pauli_strings(
319
448
  rng_or_seed,
320
449
  )
321
450
 
451
+ normalized_circuits_to_pauli = _normalize_input_paulis(circuits_to_pauli)
452
+
322
453
  # Extract unique qubit tuples from input pauli strings
323
454
  unique_qubit_tuples = set()
324
- for pauli_strings in circuits_to_pauli.values():
325
- for pauli_string in pauli_strings:
326
- unique_qubit_tuples.add(tuple(sorted(pauli_string.qubits)))
455
+ for pauli_string_groups in normalized_circuits_to_pauli.values():
456
+ for pauli_strings in pauli_string_groups:
457
+ unique_qubit_tuples.add(tuple(_extract_readout_qubits(pauli_strings)))
327
458
  # qubits_list is a list of qubit tuples
328
459
  qubits_list = sorted(unique_qubit_tuples)
329
460
 
330
- # Build the basis-change circuits for each Pauli string
331
- pauli_measurement_circuits = list[circuits.Circuit]()
332
- for input_circuit, pauli_strings in circuits_to_pauli.items():
333
- qid_list = list(sorted(input_circuit.all_qubits()))
461
+ # Build the basis-change circuits for each Pauli string group
462
+ pauli_measurement_circuits: list[circuits.Circuit] = []
463
+ for input_circuit, pauli_string_groups in normalized_circuits_to_pauli.items():
464
+ qid_list = sorted(input_circuit.all_qubits())
334
465
  basis_change_circuits = []
335
466
  input_circuit_unfrozen = input_circuit.unfreeze()
336
- for pauli_string in pauli_strings:
467
+ for pauli_strings in pauli_string_groups:
337
468
  basis_change_circuit = (
338
469
  input_circuit_unfrozen
339
- + _pauli_string_to_basis_change_ops(pauli_string, qid_list)
470
+ + _pauli_strings_to_basis_change_ops(pauli_strings, qid_list)
340
471
  + ops.measure(*qid_list, key="m")
341
472
  )
342
473
  basis_change_circuits.append(basis_change_circuit)
@@ -354,16 +485,20 @@ def measure_pauli_strings(
354
485
  )
355
486
 
356
487
  # Process the results to calculate expectation values
357
- results: List[CircuitToPauliStringsMeasurementResult] = []
488
+ results: list[CircuitToPauliStringsMeasurementResult] = []
358
489
  circuit_result_index = 0
359
- for input_circuit, pauli_strings in circuits_to_pauli.items():
490
+ for input_circuit, pauli_string_groups in normalized_circuits_to_pauli.items():
491
+
360
492
  qubits_in_circuit = tuple(sorted(input_circuit.all_qubits()))
361
493
 
362
494
  disable_readout_mitigation = False if num_random_bitstrings != 0 else True
495
+
363
496
  pauli_measurement_results = _process_pauli_measurement_results(
364
497
  list(qubits_in_circuit),
365
- pauli_strings,
366
- circuits_results[circuit_result_index : circuit_result_index + len(pauli_strings)],
498
+ pauli_string_groups,
499
+ circuits_results[
500
+ circuit_result_index : circuit_result_index + len(pauli_string_groups)
501
+ ],
367
502
  calibration_results,
368
503
  pauli_repetitions,
369
504
  time.time(),
@@ -375,5 +510,5 @@ def measure_pauli_strings(
375
510
  )
376
511
  )
377
512
 
378
- circuit_result_index += len(pauli_strings)
513
+ circuit_result_index += len(pauli_string_groups)
379
514
  return results