cirq-core 1.5.0.dev20250409225226__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.dev20250409225226.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.dev20250409225226.dist-info → cirq_core-1.6.0.dist-info}/WHEEL +1 -1
  730. cirq_core-1.5.0.dev20250409225226.dist-info/RECORD +0 -1216
  731. {cirq_core-1.5.0.dev20250409225226.dist-info → cirq_core-1.6.0.dist-info}/licenses/LICENSE +0 -0
  732. {cirq_core-1.5.0.dev20250409225226.dist-info → cirq_core-1.6.0.dist-info}/top_level.txt +0 -0
@@ -13,35 +13,24 @@
13
13
  # limitations under the License.
14
14
  """Code for generating random quantum circuits."""
15
15
 
16
+ from __future__ import annotations
17
+
16
18
  import dataclasses
17
19
  import itertools
18
- from typing import (
19
- Any,
20
- Callable,
21
- cast,
22
- Container,
23
- Dict,
24
- Iterable,
25
- Iterator,
26
- List,
27
- Optional,
28
- Sequence,
29
- Tuple,
30
- TYPE_CHECKING,
31
- Union,
32
- )
20
+ from typing import Any, Callable, Container, Iterable, Iterator, Sequence, TYPE_CHECKING
33
21
 
34
- import networkx as nx
35
22
  import numpy as np
36
23
 
37
24
  from cirq import circuits, devices, ops, protocols, value
38
25
  from cirq._doc import document
39
26
 
40
27
  if TYPE_CHECKING:
28
+ import networkx as nx
29
+
41
30
  import cirq
42
31
 
43
- QidPairT = Tuple['cirq.Qid', 'cirq.Qid']
44
- GridQubitPairT = Tuple['cirq.GridQubit', 'cirq.GridQubit']
32
+ QidPairT = tuple['cirq.Qid', 'cirq.Qid']
33
+ GridQubitPairT = tuple['cirq.GridQubit', 'cirq.GridQubit']
45
34
 
46
35
 
47
36
  @dataclasses.dataclass(frozen=True)
@@ -114,7 +103,7 @@ class GridInteractionLayer(Container[GridQubitPairT]):
114
103
  pos = a.row % 2, (a.col - self.col_offset) % 2
115
104
  return pos == (0, 0) or pos == (1, self.stagger)
116
105
 
117
- def _json_dict_(self) -> Dict[str, Any]:
106
+ def _json_dict_(self) -> dict[str, Any]:
118
107
  return protocols.obj_to_dict_helper(self, ['col_offset', 'vertical', 'stagger'])
119
108
 
120
109
  def __repr__(self) -> str:
@@ -179,20 +168,20 @@ document(
179
168
 
180
169
 
181
170
  def random_rotations_between_two_qubit_circuit(
182
- q0: 'cirq.Qid',
183
- q1: 'cirq.Qid',
171
+ q0: cirq.Qid,
172
+ q1: cirq.Qid,
184
173
  depth: int,
185
174
  two_qubit_op_factory: Callable[
186
- ['cirq.Qid', 'cirq.Qid', 'np.random.RandomState'], 'cirq.OP_TREE'
175
+ [cirq.Qid, cirq.Qid, np.random.RandomState], cirq.OP_TREE
187
176
  ] = lambda a, b, _: ops.CZPowGate()(a, b),
188
- single_qubit_gates: Sequence['cirq.Gate'] = (
177
+ single_qubit_gates: Sequence[cirq.Gate] = (
189
178
  ops.X**0.5,
190
179
  ops.Y**0.5,
191
180
  ops.PhasedXPowGate(phase_exponent=0.25, exponent=0.5),
192
181
  ),
193
182
  add_final_single_qubit_layer: bool = True,
194
- seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
195
- ) -> 'cirq.Circuit':
183
+ seed: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
184
+ ) -> cirq.Circuit:
196
185
  """Generate a random two-qubit quantum circuit.
197
186
 
198
187
  This construction uses a similar structure to those in the paper
@@ -243,14 +232,14 @@ def random_rotations_between_two_qubit_circuit(
243
232
 
244
233
  def generate_library_of_2q_circuits(
245
234
  n_library_circuits: int,
246
- two_qubit_gate: 'cirq.Gate',
235
+ two_qubit_gate: cirq.Gate,
247
236
  *,
248
237
  max_cycle_depth: int = 100,
249
- q0: 'cirq.Qid' = devices.LineQubit(0),
250
- q1: 'cirq.Qid' = devices.LineQubit(1),
251
- random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
238
+ q0: cirq.Qid = devices.LineQubit(0),
239
+ q1: cirq.Qid = devices.LineQubit(1),
240
+ random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
252
241
  tags: Sequence[Any] = (),
253
- ) -> List['cirq.Circuit']:
242
+ ) -> list[cirq.Circuit]:
254
243
  """Generate a library of two-qubit Circuits.
255
244
 
256
245
  For single-qubit gates, this uses PhasedXZGates where the axis-in-XY-plane is one
@@ -306,18 +295,18 @@ class CircuitLibraryCombination:
306
295
  `get_random_combinations_for_pairs`.
307
296
  """
308
297
 
309
- layer: Optional[Any]
298
+ layer: Any | None
310
299
  combinations: np.ndarray
311
- pairs: List[QidPairT]
300
+ pairs: list[QidPairT]
312
301
 
313
302
 
314
303
  def _get_random_combinations(
315
304
  n_library_circuits: int,
316
305
  n_combinations: int,
317
306
  *,
318
- pair_gen: Iterator[Tuple[List[QidPairT], Any]],
319
- random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
320
- ) -> List[CircuitLibraryCombination]:
307
+ pair_gen: Iterator[tuple[list[QidPairT], Any]],
308
+ random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
309
+ ) -> list[CircuitLibraryCombination]:
321
310
  """For qubit pairs, prepare a set of combinations to efficiently sample
322
311
  parallel two-qubit XEB circuits.
323
312
 
@@ -366,8 +355,8 @@ def get_random_combinations_for_device(
366
355
  device_graph: nx.Graph,
367
356
  *,
368
357
  pattern: Sequence[GridInteractionLayer] = HALF_GRID_STAGGERED_PATTERN,
369
- random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
370
- ) -> List[CircuitLibraryCombination]:
358
+ random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
359
+ ) -> list[CircuitLibraryCombination]:
371
360
  """For a given device, prepare a set of combinations to efficiently sample
372
361
  parallel two-qubit XEB circuits.
373
362
 
@@ -419,9 +408,9 @@ def get_random_combinations_for_device(
419
408
  def get_random_combinations_for_pairs(
420
409
  n_library_circuits: int,
421
410
  n_combinations: int,
422
- all_pairs: List[List[QidPairT]],
423
- random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
424
- ) -> List[CircuitLibraryCombination]:
411
+ all_pairs: list[list[QidPairT]],
412
+ random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
413
+ ) -> list[CircuitLibraryCombination]:
425
414
  """For an explicit nested list of pairs, prepare a set of combinations to efficiently sample
426
415
  parallel two-qubit XEB circuits.
427
416
 
@@ -460,26 +449,25 @@ def get_random_combinations_for_pairs(
460
449
  )
461
450
 
462
451
 
463
- def _pairs_from_moment(moment: 'cirq.Moment') -> List[QidPairT]:
452
+ def _pairs_from_moment(moment: cirq.Moment) -> list[QidPairT]:
464
453
  """Helper function in `get_random_combinations_for_layer_circuit` pair generator.
465
454
 
466
455
  The moment should contain only two qubit operations, which define a list of qubit pairs.
467
456
  """
468
- pairs: List[QidPairT] = []
457
+ pairs: list[QidPairT] = []
469
458
  for op in moment.operations:
470
459
  if len(op.qubits) != 2:
471
460
  raise ValueError("Layer circuit contains non-2-qubit operations.")
472
- qpair = cast(QidPairT, op.qubits)
473
- pairs.append(qpair)
461
+ pairs.append(op.qubits)
474
462
  return pairs
475
463
 
476
464
 
477
465
  def get_random_combinations_for_layer_circuit(
478
466
  n_library_circuits: int,
479
467
  n_combinations: int,
480
- layer_circuit: 'cirq.Circuit',
481
- random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
482
- ) -> List[CircuitLibraryCombination]:
468
+ layer_circuit: cirq.Circuit,
469
+ random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
470
+ ) -> list[CircuitLibraryCombination]:
483
471
  """For a layer circuit, prepare a set of combinations to efficiently sample
484
472
  parallel two-qubit XEB circuits.
485
473
 
@@ -523,7 +511,7 @@ def get_grid_interaction_layer_circuit(
523
511
  device_graph: nx.Graph,
524
512
  pattern: Sequence[GridInteractionLayer] = HALF_GRID_STAGGERED_PATTERN,
525
513
  two_qubit_gate=ops.ISWAP**0.5,
526
- ) -> 'cirq.Circuit':
514
+ ) -> cirq.Circuit:
527
515
  """Create a circuit representation of a grid interaction pattern on a given device topology.
528
516
 
529
517
  The resulting circuit is deterministic, of depth len(pattern), and consists of `two_qubit_gate`
@@ -547,21 +535,21 @@ def get_grid_interaction_layer_circuit(
547
535
 
548
536
 
549
537
  def random_rotations_between_grid_interaction_layers_circuit(
550
- qubits: Iterable['cirq.GridQubit'],
538
+ qubits: Iterable[cirq.GridQubit],
551
539
  depth: int,
552
540
  *, # forces keyword arguments
553
541
  two_qubit_op_factory: Callable[
554
- ['cirq.GridQubit', 'cirq.GridQubit', 'np.random.RandomState'], 'cirq.OP_TREE'
542
+ [cirq.GridQubit, cirq.GridQubit, np.random.RandomState], cirq.OP_TREE
555
543
  ] = lambda a, b, _: ops.CZPowGate()(a, b),
556
544
  pattern: Sequence[GridInteractionLayer] = GRID_STAGGERED_PATTERN,
557
- single_qubit_gates: Sequence['cirq.Gate'] = (
545
+ single_qubit_gates: Sequence[cirq.Gate] = (
558
546
  ops.X**0.5,
559
547
  ops.Y**0.5,
560
548
  ops.PhasedXPowGate(phase_exponent=0.25, exponent=0.5),
561
549
  ),
562
550
  add_final_single_qubit_layer: bool = True,
563
- seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
564
- ) -> 'cirq.Circuit':
551
+ seed: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
552
+ ) -> cirq.Circuit:
565
553
  """Generate a random quantum circuit of a particular form.
566
554
 
567
555
  This construction is based on the circuits used in the paper
@@ -619,12 +607,12 @@ def random_rotations_between_grid_interaction_layers_circuit(
619
607
  return circuit
620
608
 
621
609
 
622
- def _coupled_qubit_pairs(qubits: List['cirq.GridQubit']) -> List[GridQubitPairT]:
610
+ def _coupled_qubit_pairs(qubits: list[cirq.GridQubit]) -> list[GridQubitPairT]:
623
611
  pairs = []
624
612
  qubit_set = set(qubits)
625
613
  for qubit in qubits:
626
614
 
627
- def add_pair(neighbor: 'cirq.GridQubit'):
615
+ def add_pair(neighbor: cirq.GridQubit):
628
616
  if neighbor in qubit_set:
629
617
  pairs.append((qubit, neighbor))
630
618
 
@@ -637,16 +625,16 @@ def _coupled_qubit_pairs(qubits: List['cirq.GridQubit']) -> List[GridQubitPairT]
637
625
  class _RandomSingleQubitLayerFactory:
638
626
  def __init__(
639
627
  self,
640
- qubits: Sequence['cirq.Qid'],
641
- single_qubit_gates: Sequence['cirq.Gate'],
642
- prng: 'np.random.RandomState',
628
+ qubits: Sequence[cirq.Qid],
629
+ single_qubit_gates: Sequence[cirq.Gate],
630
+ prng: np.random.RandomState,
643
631
  ) -> None:
644
632
  self.qubits = qubits
645
633
  self.single_qubit_gates = single_qubit_gates
646
634
  self.prng = prng
647
635
 
648
- def new_layer(self, previous_single_qubit_layer: 'cirq.Moment') -> 'cirq.Moment':
649
- def random_gate(qubit: 'cirq.Qid') -> 'cirq.Gate':
636
+ def new_layer(self, previous_single_qubit_layer: cirq.Moment) -> cirq.Moment:
637
+ def random_gate(qubit: cirq.Qid) -> cirq.Gate:
650
638
  excluded_op = previous_single_qubit_layer.operation_at(qubit)
651
639
  excluded_gate = excluded_op.gate if excluded_op is not None else None
652
640
  g = self.single_qubit_gates[self.prng.randint(0, len(self.single_qubit_gates))]
@@ -658,20 +646,18 @@ class _RandomSingleQubitLayerFactory:
658
646
 
659
647
 
660
648
  class _FixedSingleQubitLayerFactory:
661
- def __init__(self, fixed_single_qubit_layer: Dict['cirq.Qid', 'cirq.Gate']) -> None:
649
+ def __init__(self, fixed_single_qubit_layer: dict[cirq.Qid, cirq.Gate]) -> None:
662
650
  self.fixed_single_qubit_layer = fixed_single_qubit_layer
663
651
 
664
- def new_layer(self, previous_single_qubit_layer: 'cirq.Moment') -> 'cirq.Moment':
652
+ def new_layer(self, previous_single_qubit_layer: cirq.Moment) -> cirq.Moment:
665
653
  return circuits.Moment(v.on(q) for q, v in self.fixed_single_qubit_layer.items())
666
654
 
667
655
 
668
- _SingleQubitLayerFactory = Union[_FixedSingleQubitLayerFactory, _RandomSingleQubitLayerFactory]
656
+ _SingleQubitLayerFactory = _FixedSingleQubitLayerFactory | _RandomSingleQubitLayerFactory
669
657
 
670
658
 
671
659
  def _single_qubit_gates_arg_to_factory(
672
- single_qubit_gates: Sequence['cirq.Gate'],
673
- qubits: Sequence['cirq.Qid'],
674
- prng: 'np.random.RandomState',
660
+ single_qubit_gates: Sequence[cirq.Gate], qubits: Sequence[cirq.Qid], prng: np.random.RandomState
675
661
  ) -> _SingleQubitLayerFactory:
676
662
  """Parse the `single_qubit_gates` argument for circuit generation functions.
677
663
 
@@ -686,13 +672,13 @@ def _single_qubit_gates_arg_to_factory(
686
672
 
687
673
 
688
674
  def _two_qubit_layer(
689
- coupled_qubit_pairs: List[GridQubitPairT],
675
+ coupled_qubit_pairs: list[GridQubitPairT],
690
676
  two_qubit_op_factory: Callable[
691
- ['cirq.GridQubit', 'cirq.GridQubit', 'np.random.RandomState'], 'cirq.OP_TREE'
677
+ [cirq.GridQubit, cirq.GridQubit, np.random.RandomState], cirq.OP_TREE
692
678
  ],
693
679
  layer: GridInteractionLayer,
694
- prng: 'np.random.RandomState',
695
- ) -> Iterator['cirq.OP_TREE']:
680
+ prng: np.random.RandomState,
681
+ ) -> Iterator[cirq.OP_TREE]:
696
682
  for a, b in coupled_qubit_pairs:
697
683
  if (a, b) in layer or (b, a) in layer:
698
684
  yield two_qubit_op_factory(a, b, prng)
@@ -11,8 +11,11 @@
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
+
15
+ from __future__ import annotations
16
+
14
17
  import itertools
15
- from typing import Callable, cast, Dict, Iterable, List, Optional, Sequence, Set, Tuple
18
+ from typing import Callable, cast, Iterable, Sequence
16
19
 
17
20
  import networkx as nx
18
21
  import numpy as np
@@ -32,7 +35,7 @@ from cirq.experiments.random_quantum_circuit_generation import (
32
35
  random_rotations_between_two_qubit_circuit,
33
36
  )
34
37
 
35
- SINGLE_QUBIT_LAYER = Dict[cirq.GridQubit, Optional[cirq.Gate]]
38
+ SINGLE_QUBIT_LAYER = dict[cirq.GridQubit, cirq.Gate | None]
36
39
 
37
40
 
38
41
  def test_random_rotation_between_two_qubit_circuit():
@@ -366,7 +369,7 @@ def test_random_rotations_between_grid_interaction_layers(
366
369
  pattern: Sequence[GridInteractionLayer],
367
370
  single_qubit_gates: Sequence[cirq.Gate],
368
371
  add_final_single_qubit_layer: bool,
369
- seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE',
372
+ seed: cirq.RANDOM_STATE_OR_SEED_LIKE,
370
373
  expected_circuit_length: int,
371
374
  single_qubit_layers_slice: slice,
372
375
  two_qubit_layers_slice: slice,
@@ -401,7 +404,7 @@ def test_grid_interaction_layer_repr():
401
404
 
402
405
 
403
406
  def _validate_single_qubit_layers(
404
- qubits: Set[cirq.GridQubit], moments: Sequence[cirq.Moment], non_repeating_layers: bool = True
407
+ qubits: set[cirq.GridQubit], moments: Sequence[cirq.Moment], non_repeating_layers: bool = True
405
408
  ) -> None:
406
409
  previous_single_qubit_gates: SINGLE_QUBIT_LAYER = {q: None for q in qubits}
407
410
 
@@ -419,7 +422,7 @@ def _validate_single_qubit_layers(
419
422
 
420
423
 
421
424
  def _validate_two_qubit_layers(
422
- qubits: Set[cirq.GridQubit],
425
+ qubits: set[cirq.GridQubit],
423
426
  moments: Sequence[cirq.Moment],
424
427
  pattern: Sequence[cirq.experiments.GridInteractionLayer],
425
428
  ) -> None:
@@ -444,12 +447,12 @@ def _validate_two_qubit_layers(
444
447
 
445
448
 
446
449
  def _coupled_qubit_pairs(
447
- qubits: Set['cirq.GridQubit'],
448
- ) -> List[Tuple['cirq.GridQubit', 'cirq.GridQubit']]:
450
+ qubits: set[cirq.GridQubit],
451
+ ) -> list[tuple[cirq.GridQubit, cirq.GridQubit]]:
449
452
  pairs = []
450
453
  for qubit in qubits:
451
454
 
452
- def add_pair(neighbor: 'cirq.GridQubit'):
455
+ def add_pair(neighbor: cirq.GridQubit):
453
456
  if neighbor in qubits:
454
457
  pairs.append((qubit, neighbor))
455
458
 
@@ -14,8 +14,10 @@
14
14
 
15
15
  """Utilities to compute readout confusion matrix and use it for readout error mitigation."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import time
18
- from typing import Any, cast, Dict, List, Optional, Sequence, Tuple, TYPE_CHECKING, Union
20
+ from typing import Any, cast, Sequence, TYPE_CHECKING
19
21
 
20
22
  import numpy as np
21
23
  import scipy.optimize
@@ -59,8 +61,8 @@ class TensoredConfusionMatrices:
59
61
 
60
62
  def __init__(
61
63
  self,
62
- confusion_matrices: Union[np.ndarray, Sequence[np.ndarray]],
63
- measure_qubits: Union[Sequence['cirq.Qid'], Sequence[Sequence['cirq.Qid']]],
64
+ confusion_matrices: np.ndarray | Sequence[np.ndarray],
65
+ measure_qubits: Sequence[cirq.Qid] | Sequence[Sequence[cirq.Qid]],
64
66
  *,
65
67
  repetitions: int,
66
68
  timestamp: float,
@@ -112,14 +114,14 @@ class TensoredConfusionMatrices:
112
114
  self._measure_qubits = tuple(tuple(q) for q in measure_qubits)
113
115
  self._qubits = tuple(sorted(set(q for ql in measure_qubits for q in ql)))
114
116
  self._qubits_to_idx = {q: i for i, q in enumerate(self._qubits)}
115
- self._cache: Dict[Tuple['cirq.Qid', ...], np.ndarray] = {}
117
+ self._cache: dict[tuple[cirq.Qid, ...], np.ndarray] = {}
116
118
  if sum(len(q) for q in self._measure_qubits) != len(self._qubits):
117
119
  raise ValueError(f"Repeated qubits not allowed in measure_qubits: {measure_qubits}.")
118
120
 
119
121
  @classmethod
120
122
  def from_measurement(
121
- cls, gate: ops.MeasurementGate, qubits: Sequence['cirq.Qid']
122
- ) -> 'TensoredConfusionMatrices':
123
+ cls, gate: ops.MeasurementGate, qubits: Sequence[cirq.Qid]
124
+ ) -> TensoredConfusionMatrices:
123
125
  """Generates TCM for the confusion map in a MeasurementGate.
124
126
 
125
127
  This ignores any invert_mask defined for the gate - it only replicates the confusion map.
@@ -155,27 +157,27 @@ class TensoredConfusionMatrices:
155
157
  return self._timestamp
156
158
 
157
159
  @property
158
- def confusion_matrices(self) -> Tuple[np.ndarray, ...]:
160
+ def confusion_matrices(self) -> tuple[np.ndarray, ...]:
159
161
  """List of confusion matrices corresponding to `measure_qubits` qubit pattern."""
160
162
  return self._confusion_matrices
161
163
 
162
164
  @property
163
- def measure_qubits(self) -> Tuple[Tuple['cirq.Qid', ...], ...]:
165
+ def measure_qubits(self) -> tuple[tuple[cirq.Qid, ...], ...]:
164
166
  """Calibrated qubit pattern for which individual confusion matrices were computed."""
165
167
  return self._measure_qubits
166
168
 
167
169
  @property
168
- def qubits(self) -> Tuple['cirq.Qid', ...]:
170
+ def qubits(self) -> tuple[cirq.Qid, ...]:
169
171
  """Sorted list of all calibrated qubits."""
170
172
  return self._qubits
171
173
 
172
- def _get_vars(self, qubit_pattern: Sequence['cirq.Qid']) -> List[int]:
174
+ def _get_vars(self, qubit_pattern: Sequence[cirq.Qid]) -> list[int]:
173
175
  in_vars = [2 * self._qubits_to_idx[q] for q in qubit_pattern]
174
176
  out_vars = [2 * self._qubits_to_idx[q] + 1 for q in qubit_pattern]
175
177
  return in_vars + out_vars
176
178
 
177
- def _confusion_matrix(self, qubits: Sequence['cirq.Qid']) -> np.ndarray:
178
- ein_input: List[np.ndarray | List[int]] = []
179
+ def _confusion_matrix(self, qubits: Sequence[cirq.Qid]) -> np.ndarray:
180
+ ein_input: list[np.ndarray | list[int]] = []
179
181
  for qs, cm in zip(self.measure_qubits, self.confusion_matrices):
180
182
  ein_input.extend([cm.reshape((2, 2) * len(qs)), self._get_vars(qs)])
181
183
  ein_out = self._get_vars(qubits)
@@ -183,7 +185,7 @@ class TensoredConfusionMatrices:
183
185
  ret = np.einsum(*ein_input, ein_out).reshape((2 ** len(qubits),) * 2)
184
186
  return ret / ret.sum(axis=1)
185
187
 
186
- def confusion_matrix(self, qubits: Optional[Sequence['cirq.Qid']] = None) -> np.ndarray:
188
+ def confusion_matrix(self, qubits: Sequence[cirq.Qid] | None = None) -> np.ndarray:
187
189
  """Returns a single confusion matrix constructed for the given set of qubits.
188
190
 
189
191
  The single `2 ** len(qubits) x 2 ** len(qubits)` confusion matrix is constructed
@@ -211,7 +213,7 @@ class TensoredConfusionMatrices:
211
213
  self._cache[key] = self._confusion_matrix(qubits)
212
214
  return self._cache[key]
213
215
 
214
- def correction_matrix(self, qubits: Optional[Sequence['cirq.Qid']] = None) -> np.ndarray:
216
+ def correction_matrix(self, qubits: Sequence[cirq.Qid] | None = None) -> np.ndarray:
215
217
  """Returns a single correction matrix constructed for the given set of qubits.
216
218
 
217
219
  A correction matrix is the inverse of confusion matrix and can be used to apply corrections
@@ -240,7 +242,7 @@ class TensoredConfusionMatrices:
240
242
  def apply(
241
243
  self,
242
244
  result: np.ndarray,
243
- qubits: Optional[Sequence['cirq.Qid']] = None,
245
+ qubits: Sequence[cirq.Qid] | None = None,
244
246
  *,
245
247
  method='least_squares',
246
248
  ) -> np.ndarray:
@@ -300,7 +302,7 @@ class TensoredConfusionMatrices:
300
302
  return res.x
301
303
 
302
304
  def readout_mitigation_pauli_uncorrelated(
303
- self, qubits: Sequence['cirq.Qid'], measured_bitstrings: np.ndarray
305
+ self, qubits: Sequence[cirq.Qid], measured_bitstrings: np.ndarray
304
306
  ) -> tuple[float, float]:
305
307
  r"""Uncorrelated readout error mitigation for a multi-qubit Pauli operator.
306
308
 
@@ -345,8 +347,8 @@ class TensoredConfusionMatrices:
345
347
  idx = self.measure_qubits.index((qubit,))
346
348
  except: # pragma: no cover
347
349
  raise NotImplementedError(
348
- "The response matrix must be a tensor product of single-qu"
349
- + f"bit response matrices, including that of qubit {qubit}."
350
+ "The response matrix must be a tensor product of single-qubit "
351
+ f"response matrices, including that of qubit {qubit}."
350
352
  )
351
353
  cm_all.append(self.confusion_matrices[idx])
352
354
 
@@ -373,7 +375,7 @@ class TensoredConfusionMatrices:
373
375
  f")"
374
376
  )
375
377
 
376
- def _json_dict_(self) -> Dict[str, Any]:
378
+ def _json_dict_(self) -> dict[str, Any]:
377
379
  return {
378
380
  'confusion_matrices': self.confusion_matrices,
379
381
  'measure_qubits': self.measure_qubits,
@@ -384,7 +386,7 @@ class TensoredConfusionMatrices:
384
386
  @classmethod
385
387
  def _from_json_dict_(
386
388
  cls, confusion_matrices, measure_qubits, repetitions, timestamp, **kwargs
387
- ) -> 'TensoredConfusionMatrices':
389
+ ) -> TensoredConfusionMatrices:
388
390
  return cls(
389
391
  [np.asarray(cm) for cm in confusion_matrices],
390
392
  measure_qubits,
@@ -423,8 +425,8 @@ class TensoredConfusionMatrices:
423
425
 
424
426
 
425
427
  def measure_confusion_matrix(
426
- sampler: 'cirq.Sampler',
427
- qubits: Union[Sequence['cirq.Qid'], Sequence[Sequence['cirq.Qid']]],
428
+ sampler: cirq.Sampler,
429
+ qubits: Sequence[cirq.Qid] | Sequence[Sequence[cirq.Qid]],
428
430
  repetitions: int = 1000,
429
431
  ) -> TensoredConfusionMatrices:
430
432
  """Prepares `TensoredConfusionMatrices` for the n qubits in the input.
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import numpy as np
16
18
  import pytest
17
19
 
@@ -11,10 +11,14 @@
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
  """Single qubit readout experiments using parallel or isolated statistics."""
16
+
17
+ from __future__ import annotations
18
+
15
19
  import dataclasses
16
20
  import time
17
- from typing import Any, cast, Dict, Iterable, List, Optional, TYPE_CHECKING
21
+ from typing import Any, cast, Iterable, TYPE_CHECKING
18
22
 
19
23
  import matplotlib.pyplot as plt
20
24
  import numpy as np
@@ -43,12 +47,12 @@ class SingleQubitReadoutCalibrationResult:
43
47
  timestamp: The time the data was taken, in seconds since the epoch.
44
48
  """
45
49
 
46
- zero_state_errors: Dict['cirq.Qid', float]
47
- one_state_errors: Dict['cirq.Qid', float]
50
+ zero_state_errors: dict[cirq.Qid, float]
51
+ one_state_errors: dict[cirq.Qid, float]
48
52
  repetitions: int
49
53
  timestamp: float
50
54
 
51
- def _json_dict_(self) -> Dict[str, Any]:
55
+ def _json_dict_(self) -> dict[str, Any]:
52
56
  return {
53
57
  'zero_state_errors': list(self.zero_state_errors.items()),
54
58
  'one_state_errors': list(self.one_state_errors.items()),
@@ -58,7 +62,7 @@ class SingleQubitReadoutCalibrationResult:
58
62
 
59
63
  def plot_heatmap(
60
64
  self,
61
- axs: Optional[tuple[plt.Axes, plt.Axes]] = None,
65
+ axs: tuple[plt.Axes, plt.Axes] | None = None,
62
66
  annotation_format: str = '0.1%',
63
67
  **plot_kwargs: Any,
64
68
  ) -> tuple[plt.Axes, plt.Axes]:
@@ -106,16 +110,16 @@ class SingleQubitReadoutCalibrationResult:
106
110
 
107
111
  def plot_integrated_histogram(
108
112
  self,
109
- ax: Optional[plt.Axes] = None,
113
+ ax: plt.Axes | None = None,
110
114
  cdf_on_x: bool = False,
111
115
  axis_label: str = 'Readout error rate',
112
116
  semilog: bool = True,
113
117
  median_line: bool = True,
114
- median_label: Optional[str] = 'median',
118
+ median_label: str | None = 'median',
115
119
  mean_line: bool = False,
116
- mean_label: Optional[str] = 'mean',
120
+ mean_label: str | None = 'mean',
117
121
  show_zero: bool = False,
118
- title: Optional[str] = None,
122
+ title: str | None = None,
119
123
  **kwargs,
120
124
  ) -> plt.Axes:
121
125
  """Plot the readout errors using cirq.integrated_histogram().
@@ -175,6 +179,17 @@ class SingleQubitReadoutCalibrationResult:
175
179
  ax.set_ylabel('Percentile')
176
180
  return ax
177
181
 
182
+ def readout_result_for_qubits(
183
+ self, readout_qubits: list[ops.Qid]
184
+ ) -> SingleQubitReadoutCalibrationResult:
185
+ """Builds a calibration result for the specific readout qubits."""
186
+ return SingleQubitReadoutCalibrationResult(
187
+ zero_state_errors={qubit: self.zero_state_errors[qubit] for qubit in readout_qubits},
188
+ one_state_errors={qubit: self.one_state_errors[qubit] for qubit in readout_qubits},
189
+ timestamp=self.timestamp,
190
+ repetitions=self.repetitions,
191
+ )
192
+
178
193
  @classmethod
179
194
  def _from_json_dict_(
180
195
  cls, zero_state_errors, one_state_errors, repetitions, timestamp, **kwargs
@@ -197,7 +212,7 @@ class SingleQubitReadoutCalibrationResult:
197
212
 
198
213
 
199
214
  def estimate_single_qubit_readout_errors(
200
- sampler: 'cirq.Sampler', *, qubits: Iterable['cirq.Qid'], repetitions: int = 1000
215
+ sampler: cirq.Sampler, *, qubits: Iterable[cirq.Qid], repetitions: int = 1000
201
216
  ) -> SingleQubitReadoutCalibrationResult:
202
217
  """Estimate single-qubit readout error.
203
218
 
@@ -229,13 +244,13 @@ def estimate_single_qubit_readout_errors(
229
244
 
230
245
 
231
246
  def estimate_parallel_single_qubit_readout_errors(
232
- sampler: 'cirq.Sampler',
247
+ sampler: cirq.Sampler,
233
248
  *,
234
- qubits: Iterable['cirq.Qid'],
249
+ qubits: Iterable[cirq.Qid],
235
250
  trials: int = 20,
236
251
  repetitions: int = 1000,
237
- trials_per_batch: Optional[int] = None,
238
- bit_strings: Optional[np.ndarray] = None,
252
+ trials_per_batch: int | None = None,
253
+ bit_strings: np.ndarray | None = None,
239
254
  ) -> SingleQubitReadoutCalibrationResult:
240
255
  """Estimate single qubit readout error using parallel operations.
241
256
 
@@ -296,7 +311,7 @@ def estimate_parallel_single_qubit_readout_errors(
296
311
  if trials_per_batch <= 0:
297
312
  raise ValueError("Must provide non-zero trials_per_batch for readout calibration.")
298
313
 
299
- all_sweeps: List[study.Sweepable] = []
314
+ all_sweeps: list[study.Sweepable] = []
300
315
  num_batches = (trials + trials_per_batch - 1) // trials_per_batch
301
316
 
302
317
  # Initialize circuits
@@ -11,6 +11,9 @@
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
+
15
+ from __future__ import annotations
16
+
14
17
  from typing import Sequence
15
18
 
16
19
  import numpy as np
@@ -30,7 +33,7 @@ def test_single_qubit_readout_result_repr():
30
33
 
31
34
 
32
35
  class NoisySingleQubitReadoutSampler(cirq.Sampler):
33
- def __init__(self, p0: float, p1: float, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None):
36
+ def __init__(self, p0: float, p1: float, seed: cirq.RANDOM_STATE_OR_SEED_LIKE = None):
34
37
  """Sampler that flips some bits upon readout.
35
38
 
36
39
  Args:
@@ -44,7 +47,7 @@ class NoisySingleQubitReadoutSampler(cirq.Sampler):
44
47
  self.simulator = cirq.Simulator(seed=self.prng, split_untangled_states=False)
45
48
 
46
49
  def run_sweep(
47
- self, program: 'cirq.AbstractCircuit', params: cirq.Sweepable, repetitions: int = 1
50
+ self, program: cirq.AbstractCircuit, params: cirq.Sweepable, repetitions: int = 1
48
51
  ) -> Sequence[cirq.Result]:
49
52
  results = self.simulator.run_sweep(program, params, repetitions)
50
53
  for result in results: