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
@@ -12,38 +12,39 @@
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 dataclasses
16
18
  import functools
17
19
  import itertools
18
- from typing import (
19
- Any,
20
- cast,
21
- Dict,
22
- Iterator,
23
- List,
24
- Mapping,
25
- Optional,
26
- Sequence,
27
- Tuple,
28
- TYPE_CHECKING,
29
- )
20
+ import uuid
21
+ from typing import Any, cast, Iterator, Mapping, Sequence, TYPE_CHECKING
30
22
 
23
+ import attrs
31
24
  import numpy as np
32
25
  from matplotlib import pyplot as plt
33
26
 
34
27
  # this is for older systems with matplotlib <3.2 otherwise 3d projections fail
35
- from mpl_toolkits import mplot3d
36
28
  from scipy.optimize import curve_fit
37
29
 
38
30
  import cirq.vis.heatmap as cirq_heatmap
39
31
  import cirq.vis.histogram as cirq_histogram
40
32
  from cirq import circuits, ops, protocols
33
+ from cirq._compat import deprecated
41
34
  from cirq.devices import grid_qubit
42
35
 
43
36
  if TYPE_CHECKING:
37
+ from mpl_toolkits import mplot3d
38
+
44
39
  import cirq
45
40
 
46
41
 
42
+ def _canonize_clifford_sequences(
43
+ sequences: list[list[ops.SingleQubitCliffordGate]],
44
+ ) -> list[list[ops.SingleQubitCliffordGate]]:
45
+ return [[_reduce_gate_seq(seq)] for seq in sequences]
46
+
47
+
47
48
  @dataclasses.dataclass
48
49
  class Cliffords:
49
50
  """The single-qubit Clifford group, decomposed into elementary gates.
@@ -62,11 +63,11 @@ class Cliffords:
62
63
  s1_y
63
64
  """
64
65
 
65
- c1_in_xy: List[List[ops.SingleQubitCliffordGate]]
66
- c1_in_xz: List[List[ops.SingleQubitCliffordGate]]
67
- s1: List[List[ops.SingleQubitCliffordGate]]
68
- s1_x: List[List[ops.SingleQubitCliffordGate]]
69
- s1_y: List[List[ops.SingleQubitCliffordGate]]
66
+ c1_in_xy: list[list[ops.SingleQubitCliffordGate]]
67
+ c1_in_xz: list[list[ops.SingleQubitCliffordGate]]
68
+ s1: list[list[ops.SingleQubitCliffordGate]]
69
+ s1_x: list[list[ops.SingleQubitCliffordGate]]
70
+ s1_y: list[list[ops.SingleQubitCliffordGate]]
70
71
 
71
72
 
72
73
  class RandomizedBenchMarkResult:
@@ -85,14 +86,14 @@ class RandomizedBenchMarkResult:
85
86
  self._gnd_state_probs = ground_state_probabilities
86
87
 
87
88
  @property
88
- def data(self) -> Sequence[Tuple[int, float]]:
89
+ def data(self) -> Sequence[tuple[int, float]]:
89
90
  """Returns a sequence of tuple pairs with the first item being a
90
91
  number of Cliffords and the second item being the corresponding average
91
92
  ground state probability.
92
93
  """
93
94
  return [(num, prob) for num, prob in zip(self._num_cfds_seq, self._gnd_state_probs)]
94
95
 
95
- def plot(self, ax: Optional[plt.Axes] = None, **plot_kwargs: Any) -> plt.Axes:
96
+ def plot(self, ax: plt.Axes | None = None, **plot_kwargs: Any) -> plt.Axes:
96
97
  """Plots the average ground state probability vs the number of
97
98
  Cliffords in the RB study.
98
99
 
@@ -135,14 +136,14 @@ class RandomizedBenchMarkResult:
135
136
  p = opt_params[2]
136
137
  return (1.0 - 1.0 / 4.0) * (1.0 - p)
137
138
 
138
- def _fit_exponential(self) -> Tuple[np.ndarray, np.ndarray]:
139
+ def _fit_exponential(self) -> tuple[np.ndarray, np.ndarray]:
139
140
  exp_fit = lambda x, A, B, p: A * p**x + B
140
141
  return curve_fit(
141
142
  f=exp_fit,
142
143
  xdata=self._num_cfds_seq,
143
144
  ydata=self._gnd_state_probs,
144
145
  p0=[0.5, 0.5, 1.0 - 1e-3],
145
- bounds=([0, 0.25, 0], [0.5, 0.75, 1]),
146
+ bounds=([0, -1, 0], [1, 1, 1]),
146
147
  )
147
148
 
148
149
 
@@ -150,10 +151,10 @@ class RandomizedBenchMarkResult:
150
151
  class ParallelRandomizedBenchmarkingResult:
151
152
  """Results from a parallel randomized benchmarking experiment."""
152
153
 
153
- results_dictionary: Mapping['cirq.Qid', 'RandomizedBenchMarkResult']
154
+ results_dictionary: Mapping[cirq.Qid, RandomizedBenchMarkResult]
154
155
 
155
156
  def plot_single_qubit(
156
- self, qubit: 'cirq.Qid', ax: Optional[plt.Axes] = None, **plot_kwargs: Any
157
+ self, qubit: cirq.Qid, ax: plt.Axes | None = None, **plot_kwargs: Any
157
158
  ) -> plt.Axes:
158
159
  """Plot the raw data for the specified qubit.
159
160
 
@@ -168,7 +169,7 @@ class ParallelRandomizedBenchmarkingResult:
168
169
 
169
170
  return self.results_dictionary[qubit].plot(ax, **plot_kwargs)
170
171
 
171
- def pauli_error(self) -> Mapping['cirq.Qid', float]:
172
+ def pauli_error(self) -> Mapping[cirq.Qid, float]:
172
173
  """Return a dictionary of Pauli errors.
173
174
  Returns:
174
175
  A dictionary containing the Pauli errors for all qubits.
@@ -180,7 +181,7 @@ class ParallelRandomizedBenchmarkingResult:
180
181
 
181
182
  def plot_heatmap(
182
183
  self,
183
- ax: Optional[plt.Axes] = None,
184
+ ax: plt.Axes | None = None,
184
185
  annotation_format: str = '0.1%',
185
186
  title: str = 'Single-qubit Pauli error',
186
187
  **plot_kwargs: Any,
@@ -213,16 +214,16 @@ class ParallelRandomizedBenchmarkingResult:
213
214
 
214
215
  def plot_integrated_histogram(
215
216
  self,
216
- ax: Optional[plt.Axes] = None,
217
+ ax: plt.Axes | None = None,
217
218
  cdf_on_x: bool = False,
218
219
  axis_label: str = 'Pauli error',
219
220
  semilog: bool = True,
220
221
  median_line: bool = True,
221
- median_label: Optional[str] = 'median',
222
+ median_label: str | None = 'median',
222
223
  mean_line: bool = False,
223
- mean_label: Optional[str] = 'mean',
224
+ mean_label: str | None = 'mean',
224
225
  show_zero: bool = False,
225
- title: Optional[str] = None,
226
+ title: str | None = None,
226
227
  **kwargs,
227
228
  ) -> plt.Axes:
228
229
  """Plot the Pauli errors using cirq.integrated_histogram().
@@ -286,8 +287,8 @@ class TomographyResult:
286
287
  return self._density_matrix
287
288
 
288
289
  def plot(
289
- self, axes: Optional[List[plt.Axes]] = None, **plot_kwargs: Any
290
- ) -> List[plt.Axes]: # pragma: no cover
290
+ self, axes: list[plt.Axes] | None = None, **plot_kwargs: Any
291
+ ) -> list[plt.Axes]: # pragma: no cover
291
292
  """Plots the real and imaginary parts of the density matrix as two 3D bar plots.
292
293
 
293
294
  Args:
@@ -341,9 +342,47 @@ class TomographyResult:
341
342
  return axes
342
343
 
343
344
 
345
+ @attrs.frozen
346
+ class RBParameters:
347
+ r"""Parameters for running randomized benchmarking.
348
+
349
+ Arguments:
350
+ num_clifford_range: The different numbers of Cliffords in the RB study.
351
+ num_circuits: The number of random circuits generated for each
352
+ number of Cliffords.
353
+ repetitions: The number of repetitions of each circuit.
354
+ use_xy_basis: Determines if the Clifford gates are built with x and y
355
+ rotations (True) or x and z rotations (False).
356
+ strict_basis: whether to use only cliffords that can be represented by at
357
+ most 2 gates of the choses basis. For example,
358
+ if True and use_xy_basis is True, this excludes $I, Z, \sqrt(Z), \-sqrt(Z)^\dagger$.
359
+ if True and use_xy_basis is False, this excludes $I, Y, \sqrt(Y), -\sqrt(Y)^\dagger$.
360
+ """
361
+
362
+ num_clifford_range: Sequence[int] = tuple(np.logspace(np.log10(5), 3, 5, dtype=int))
363
+ num_circuits: int = 10
364
+ repetitions: int = 600
365
+ use_xy_basis: bool = False
366
+ strict_basis: bool = True
367
+
368
+ def gateset(self) -> list[list[ops.SingleQubitCliffordGate]]:
369
+ clifford_group = _single_qubit_cliffords()
370
+ sequences = clifford_group.c1_in_xy if self.use_xy_basis else clifford_group.c1_in_xz
371
+ sequences = _canonize_clifford_sequences(sequences)
372
+ if self.strict_basis:
373
+ if self.use_xy_basis:
374
+ excluded_gates = ops.Gateset(ops.I, ops.Z, ops.Z**0.5, ops.Z**-0.5)
375
+ else:
376
+ excluded_gates = ops.Gateset(ops.I, ops.Y, ops.Y**0.5, ops.Y**-0.5)
377
+
378
+ sequences = [[g] for (g,) in sequences if g not in excluded_gates]
379
+ return sequences
380
+
381
+
382
+ @deprecated(deadline='v2.0', fix='please use single_qubit_rb instead')
344
383
  def single_qubit_randomized_benchmarking(
345
- sampler: 'cirq.Sampler',
346
- qubit: 'cirq.Qid',
384
+ sampler: cirq.Sampler,
385
+ qubit: cirq.Qid,
347
386
  use_xy_basis: bool = True,
348
387
  *,
349
388
  num_clifford_range: Sequence[int] = tuple(np.logspace(np.log10(5), 3, 5, dtype=int)),
@@ -384,20 +423,23 @@ def single_qubit_randomized_benchmarking(
384
423
  A RandomizedBenchMarkResult object that stores and plots the result.
385
424
  """
386
425
 
387
- result = parallel_single_qubit_randomized_benchmarking(
426
+ return single_qubit_rb(
388
427
  sampler,
389
- (qubit,),
390
- use_xy_basis,
391
- num_clifford_range=num_clifford_range,
392
- num_circuits=num_circuits,
393
- repetitions=repetitions,
428
+ qubit,
429
+ RBParameters(
430
+ num_clifford_range=num_clifford_range,
431
+ num_circuits=num_circuits,
432
+ repetitions=repetitions,
433
+ use_xy_basis=use_xy_basis,
434
+ strict_basis=False,
435
+ ),
394
436
  )
395
- return result.results_dictionary[qubit]
396
437
 
397
438
 
439
+ @deprecated(deadline='v2.0', fix='please use parallel_single_qubit_rb instead')
398
440
  def parallel_single_qubit_randomized_benchmarking(
399
- sampler: 'cirq.Sampler',
400
- qubits: Sequence['cirq.Qid'],
441
+ sampler: cirq.Sampler,
442
+ qubits: Sequence[cirq.Qid],
401
443
  use_xy_basis: bool = True,
402
444
  *,
403
445
  num_clifford_range: Sequence[int] = tuple(
@@ -405,7 +447,7 @@ def parallel_single_qubit_randomized_benchmarking(
405
447
  ),
406
448
  num_circuits: int = 10,
407
449
  repetitions: int = 1000,
408
- ) -> 'ParallelRandomizedBenchmarkingResult':
450
+ ) -> ParallelRandomizedBenchmarkingResult:
409
451
  """Clifford-based randomized benchmarking (RB) single qubits in parallel.
410
452
 
411
453
  This is the same as `single_qubit_randomized_benchmarking` except on all
@@ -421,42 +463,97 @@ def parallel_single_qubit_randomized_benchmarking(
421
463
  num_circuits: The number of random circuits generated for each
422
464
  number of Cliffords.
423
465
  repetitions: The number of repetitions of each circuit.
466
+ Returns:
467
+ A dictionary from qubits to RandomizedBenchMarkResult objects.
468
+ """
469
+ return parallel_single_qubit_rb(
470
+ sampler,
471
+ qubits,
472
+ RBParameters(
473
+ num_clifford_range=num_clifford_range,
474
+ num_circuits=num_circuits,
475
+ repetitions=repetitions,
476
+ use_xy_basis=use_xy_basis,
477
+ strict_basis=False,
478
+ ),
479
+ )
480
+
424
481
 
482
+ def single_qubit_rb(
483
+ sampler: cirq.Sampler,
484
+ qubit: cirq.Qid,
485
+ parameters: RBParameters = RBParameters(),
486
+ rng_or_seed: np.random.Generator | int | None = None,
487
+ ) -> RandomizedBenchMarkResult:
488
+ """Clifford-based randomized benchmarking (RB) on a single qubit.
489
+
490
+ Args:
491
+ sampler: The quantum engine or simulator to run the circuits.
492
+ qubit: The qubit(s) to benchmark.
493
+ parameters: The parameters of the experiment.
494
+ rng_or_seed: A np.random.Generator object or seed.
425
495
  Returns:
426
496
  A dictionary from qubits to RandomizedBenchMarkResult objects.
427
497
  """
498
+ return parallel_single_qubit_rb(sampler, [qubit], parameters, rng_or_seed).results_dictionary[
499
+ qubit
500
+ ]
501
+
428
502
 
429
- clifford_group = _single_qubit_cliffords()
430
- c1 = clifford_group.c1_in_xy if use_xy_basis else clifford_group.c1_in_xz
503
+ def parallel_single_qubit_rb(
504
+ sampler: cirq.Sampler,
505
+ qubits: Sequence[cirq.Qid],
506
+ parameters: RBParameters = RBParameters(),
507
+ rng_or_seed: np.random.Generator | int | None = None,
508
+ ) -> ParallelRandomizedBenchmarkingResult:
509
+ """Clifford-based randomized benchmarking (RB) single qubits in parallel.
510
+
511
+ Args:
512
+ sampler: The quantum engine or simulator to run the circuits.
513
+ qubits: The qubit(s) to benchmark.
514
+ parameters: The parameters of the experiment.
515
+ rng_or_seed: A np.random.Generator object or seed.
516
+ Returns:
517
+ A dictionary from qubits to RandomizedBenchMarkResult objects.
518
+ """
519
+
520
+ rng_or_seed = (
521
+ rng_or_seed
522
+ if isinstance(rng_or_seed, np.random.Generator)
523
+ else np.random.default_rng(rng_or_seed)
524
+ )
525
+
526
+ c1 = parameters.gateset()
431
527
 
432
528
  # create circuits
433
- circuits_all: List['cirq.AbstractCircuit'] = []
434
- for num_cliffords in num_clifford_range:
435
- for _ in range(num_circuits):
436
- circuits_all.append(_create_parallel_rb_circuit(qubits, num_cliffords, c1))
529
+ circuits_all: list[cirq.AbstractCircuit] = []
530
+ for num_cliffords in parameters.num_clifford_range:
531
+ for _ in range(parameters.num_circuits):
532
+ circuits_all.append(_create_parallel_rb_circuit(qubits, num_cliffords, c1, rng_or_seed))
437
533
 
438
534
  # run circuits
439
- results = sampler.run_batch(circuits_all, repetitions=repetitions)
535
+ results = sampler.run_batch(circuits_all, repetitions=parameters.repetitions)
440
536
  gnd_probs: dict = {q: [] for q in qubits}
441
537
  idx = 0
442
- for num_cliffords in num_clifford_range:
443
- excited_probs: Dict['cirq.Qid', List[float]] = {q: [] for q in qubits}
444
- for _ in range(num_circuits):
538
+ for num_cliffords in parameters.num_clifford_range:
539
+ excited_probs: dict[cirq.Qid, list[float]] = {q: [] for q in qubits}
540
+ for _ in range(parameters.num_circuits):
445
541
  result = results[idx][0]
446
542
  for qubit in qubits:
447
543
  excited_probs[qubit].append(np.mean(result.measurements[str(qubit)]))
448
544
  idx += 1
449
545
  for qubit in qubits:
450
546
  gnd_probs[qubit].append(1.0 - np.mean(excited_probs[qubit]))
547
+
451
548
  return ParallelRandomizedBenchmarkingResult(
452
- {q: RandomizedBenchMarkResult(num_clifford_range, gnd_probs[q]) for q in qubits}
549
+ {q: RandomizedBenchMarkResult(parameters.num_clifford_range, gnd_probs[q]) for q in qubits}
453
550
  )
454
551
 
455
552
 
456
553
  def two_qubit_randomized_benchmarking(
457
- sampler: 'cirq.Sampler',
458
- first_qubit: 'cirq.Qid',
459
- second_qubit: 'cirq.Qid',
554
+ sampler: cirq.Sampler,
555
+ first_qubit: cirq.Qid,
556
+ second_qubit: cirq.Qid,
460
557
  *,
461
558
  num_clifford_range: Sequence[int] = range(5, 50, 5),
462
559
  num_circuits: int = 20,
@@ -514,10 +611,7 @@ def two_qubit_randomized_benchmarking(
514
611
 
515
612
 
516
613
  def single_qubit_state_tomography(
517
- sampler: 'cirq.Sampler',
518
- qubit: 'cirq.Qid',
519
- circuit: 'cirq.AbstractCircuit',
520
- repetitions: int = 1000,
614
+ sampler: cirq.Sampler, qubit: cirq.Qid, circuit: cirq.AbstractCircuit, repetitions: int = 1000
521
615
  ) -> TomographyResult:
522
616
  """Single-qubit state tomography.
523
617
 
@@ -538,18 +632,24 @@ def single_qubit_state_tomography(
538
632
  Returns:
539
633
  A TomographyResult object that stores and plots the density matrix.
540
634
  """
541
- circuit_z = circuit + circuits.Circuit(ops.measure(qubit, key='z'))
635
+ keys = protocols.measurement_key_names(circuit)
636
+ tomo_key = "tomo_key"
637
+ while tomo_key in keys:
638
+ tomo_key = f"tomo_key{uuid.uuid4().hex}"
639
+
640
+ circuit_z = circuit + circuits.Circuit(ops.measure(qubit, key=tomo_key))
641
+
542
642
  results = sampler.run(circuit_z, repetitions=repetitions)
543
- rho_11 = np.mean(results.measurements['z'])
643
+ rho_11 = np.mean(results.records[tomo_key][:, -1, :])
544
644
  rho_00 = 1.0 - rho_11
545
645
 
546
- circuit_x = circuits.Circuit(circuit, ops.X(qubit) ** 0.5, ops.measure(qubit, key='z'))
646
+ circuit_x = circuits.Circuit(circuit, ops.X(qubit) ** 0.5, ops.measure(qubit, key=tomo_key))
547
647
  results = sampler.run(circuit_x, repetitions=repetitions)
548
- rho_01_im = np.mean(results.measurements['z']) - 0.5
648
+ rho_01_im = np.mean(results.records[tomo_key][:, -1, :]) - 0.5
549
649
 
550
- circuit_y = circuits.Circuit(circuit, ops.Y(qubit) ** -0.5, ops.measure(qubit, key='z'))
650
+ circuit_y = circuits.Circuit(circuit, ops.Y(qubit) ** -0.5, ops.measure(qubit, key=tomo_key))
551
651
  results = sampler.run(circuit_y, repetitions=repetitions)
552
- rho_01_re = 0.5 - np.mean(results.measurements['z'])
652
+ rho_01_re = 0.5 - np.mean(results.records[tomo_key][:, -1, :])
553
653
 
554
654
  rho_01 = rho_01_re + 1j * rho_01_im
555
655
  rho_10 = np.conj(rho_01)
@@ -560,10 +660,10 @@ def single_qubit_state_tomography(
560
660
 
561
661
 
562
662
  def two_qubit_state_tomography(
563
- sampler: 'cirq.Sampler',
564
- first_qubit: 'cirq.Qid',
565
- second_qubit: 'cirq.Qid',
566
- circuit: 'cirq.AbstractCircuit',
663
+ sampler: cirq.Sampler,
664
+ first_qubit: cirq.Qid,
665
+ second_qubit: cirq.Qid,
666
+ circuit: cirq.AbstractCircuit,
567
667
  repetitions: int = 1000,
568
668
  ) -> TomographyResult:
569
669
  r"""Two-qubit state tomography.
@@ -688,9 +788,14 @@ def two_qubit_state_tomography(
688
788
 
689
789
 
690
790
  def _create_parallel_rb_circuit(
691
- qubits: Sequence['cirq.Qid'], num_cliffords: int, c1: list
692
- ) -> 'cirq.Circuit':
693
- sequences_to_zip = [_random_single_q_clifford(qubit, num_cliffords, c1) for qubit in qubits]
791
+ qubits: Sequence[cirq.Qid],
792
+ num_cliffords: int,
793
+ c1: list[list[ops.SingleQubitCliffordGate]],
794
+ rng: np.random.Generator | None = None,
795
+ ) -> cirq.Circuit:
796
+ sequences_to_zip = [
797
+ _random_single_q_clifford(qubit, num_cliffords, c1, rng) for qubit in qubits
798
+ ]
694
799
  # Ensure each sequence has the same number of moments.
695
800
  num_moments = max(len(sequence) for sequence in sequences_to_zip)
696
801
  for q, sequence in zip(qubits, sequences_to_zip):
@@ -702,7 +807,7 @@ def _create_parallel_rb_circuit(
702
807
  return circuits.Circuit.from_moments(*moments, ops.measure_each(*qubits))
703
808
 
704
809
 
705
- def _indices_after_basis_rot(i: int, j: int) -> Tuple[int, Sequence[int], Sequence[int]]:
810
+ def _indices_after_basis_rot(i: int, j: int) -> tuple[int, Sequence[int], Sequence[int]]:
706
811
  mat_idx = 3 * (3 * i + j)
707
812
  q_0_i = 3 - i
708
813
  q_1_j = 3 - j
@@ -711,9 +816,7 @@ def _indices_after_basis_rot(i: int, j: int) -> Tuple[int, Sequence[int], Sequen
711
816
  return mat_idx, indices, signs
712
817
 
713
818
 
714
- def _two_qubit_clifford_matrices(
715
- q_0: 'cirq.Qid', q_1: 'cirq.Qid', cliffords: Cliffords
716
- ) -> np.ndarray:
819
+ def _two_qubit_clifford_matrices(q_0: cirq.Qid, q_1: cirq.Qid, cliffords: Cliffords) -> np.ndarray:
717
820
  mats = []
718
821
 
719
822
  # Total number of different gates in the two-qubit Clifford group.
@@ -743,11 +846,14 @@ def _two_qubit_clifford_matrices(
743
846
 
744
847
 
745
848
  def _random_single_q_clifford(
746
- qubit: 'cirq.Qid', num_cfds: int, cfds: Sequence[Sequence['cirq.ops.SingleQubitCliffordGate']]
747
- ) -> List['cirq.Operation']:
748
- clifford_group_size = 24
849
+ qubit: cirq.Qid,
850
+ num_cfds: int,
851
+ cfds: Sequence[Sequence[cirq.ops.SingleQubitCliffordGate]],
852
+ rng: np.random.Generator | None = None,
853
+ ) -> list[cirq.Operation]:
749
854
  operations = [[gate.to_phased_xz_gate()(qubit) for gate in gates] for gates in cfds]
750
- gate_ids = list(np.random.choice(clifford_group_size, num_cfds))
855
+ choice_fn = rng.choice if rng else np.random.choice
856
+ gate_ids = choice_fn(len(cfds), num_cfds).tolist()
751
857
  adjoint = _reduce_gate_seq([gate for gate_id in gate_ids for gate in cfds[gate_id]]) ** -1
752
858
  return [op for gate_id in gate_ids for op in operations[gate_id]] + [
753
859
  adjoint.to_phased_xz_gate()(qubit)
@@ -755,10 +861,10 @@ def _random_single_q_clifford(
755
861
 
756
862
 
757
863
  def _random_two_q_clifford(
758
- q_0: 'cirq.Qid', q_1: 'cirq.Qid', num_cfds: int, cfd_matrices: np.ndarray, cliffords: Cliffords
759
- ) -> 'cirq.Circuit':
864
+ q_0: cirq.Qid, q_1: cirq.Qid, num_cfds: int, cfd_matrices: np.ndarray, cliffords: Cliffords
865
+ ) -> cirq.Circuit:
760
866
  clifford_group_size = 11520
761
- idx_list = list(np.random.choice(clifford_group_size, num_cfds))
867
+ idx_list = np.random.choice(clifford_group_size, num_cfds).tolist()
762
868
  circuit = circuits.Circuit()
763
869
  for idx in idx_list:
764
870
  circuit.append(_two_qubit_clifford(q_0, q_1, idx, cliffords))
@@ -778,9 +884,9 @@ def _matrix_bar_plot(
778
884
  mat: np.ndarray,
779
885
  z_label: str,
780
886
  ax: mplot3d.axes3d.Axes3D,
781
- kets: Optional[Sequence[str]] = None,
782
- title: Optional[str] = None,
783
- ylim: Tuple[int, int] = (-1, 1),
887
+ kets: Sequence[str] | None = None,
888
+ title: str | None = None,
889
+ ylim: tuple[int, int] = (-1, 1),
784
890
  **bar3d_kwargs: Any,
785
891
  ) -> None: # pragma: no cover
786
892
  num_rows, num_cols = mat.shape
@@ -819,8 +925,8 @@ def _reduce_gate_seq(
819
925
 
820
926
 
821
927
  def _two_qubit_clifford(
822
- q_0: 'cirq.Qid', q_1: 'cirq.Qid', idx: int, cliffords: Cliffords
823
- ) -> Iterator['cirq.OP_TREE']:
928
+ q_0: cirq.Qid, q_1: cirq.Qid, idx: int, cliffords: Cliffords
929
+ ) -> Iterator[cirq.OP_TREE]:
824
930
  """Generates a two-qubit Clifford gate.
825
931
 
826
932
  An integer (idx) from 0 to 11519 is used to generate a two-qubit Clifford
@@ -875,8 +981,8 @@ def _split_two_q_clifford_idx(idx: int):
875
981
 
876
982
 
877
983
  def _two_qubit_clifford_starters(
878
- q_0: 'cirq.Qid', q_1: 'cirq.Qid', idx_0: int, idx_1: int, cliffords: Cliffords
879
- ) -> Iterator['cirq.OP_TREE']:
984
+ q_0: cirq.Qid, q_1: cirq.Qid, idx_0: int, idx_1: int, cliffords: Cliffords
985
+ ) -> Iterator[cirq.OP_TREE]:
880
986
  """Fulfills part (a) for two-qubit Cliffords."""
881
987
  c1 = cliffords.c1_in_xy
882
988
  yield _single_qubit_gates(c1[idx_0], q_0)
@@ -884,8 +990,8 @@ def _two_qubit_clifford_starters(
884
990
 
885
991
 
886
992
  def _two_qubit_clifford_mixers(
887
- q_0: 'cirq.Qid', q_1: 'cirq.Qid', idx_2: int, cliffords: Cliffords
888
- ) -> Iterator['cirq.OP_TREE']:
993
+ q_0: cirq.Qid, q_1: cirq.Qid, idx_2: int, cliffords: Cliffords
994
+ ) -> Iterator[cirq.OP_TREE]:
889
995
  """Fulfills parts (b-d) for two-qubit Cliffords."""
890
996
  s1 = cliffords.s1
891
997
  s1_x = cliffords.s1_x
@@ -916,9 +1022,7 @@ def _two_qubit_clifford_mixers(
916
1022
  yield _single_qubit_gates(s1_x[idx_4], q_1)
917
1023
 
918
1024
 
919
- def _single_qubit_gates(
920
- gate_seq: Sequence['cirq.Gate'], qubit: 'cirq.Qid'
921
- ) -> Iterator['cirq.OP_TREE']:
1025
+ def _single_qubit_gates(gate_seq: Sequence[cirq.Gate], qubit: cirq.Qid) -> Iterator[cirq.OP_TREE]:
922
1026
  for gate in gate_seq:
923
1027
  yield gate(qubit)
924
1028
 
@@ -931,8 +1035,8 @@ def _single_qubit_cliffords() -> Cliffords:
931
1035
  ops.SingleQubitCliffordGate.Z,
932
1036
  )
933
1037
 
934
- c1_in_xy: List[List[ops.SingleQubitCliffordGate]] = []
935
- c1_in_xz: List[List[ops.SingleQubitCliffordGate]] = []
1038
+ c1_in_xy: list[list[ops.SingleQubitCliffordGate]] = []
1039
+ c1_in_xz: list[list[ops.SingleQubitCliffordGate]] = []
936
1040
 
937
1041
  for phi_0, phi_1 in itertools.product([1.0, 0.5, -0.5], [0.0, 0.5, -0.5]):
938
1042
  c1_in_xy.append([X**phi_0, Y**phi_1])
@@ -955,9 +1059,9 @@ def _single_qubit_cliffords() -> Cliffords:
955
1059
  for z0, x, z1 in phi_xz:
956
1060
  c1_in_xz.append([Z**z0, X**x, Z**z1])
957
1061
 
958
- s1: List[List[ops.SingleQubitCliffordGate]] = [[X**0.0], [Y**0.5, X**0.5], [X**-0.5, Y**-0.5]]
959
- s1_x: List[List[ops.SingleQubitCliffordGate]] = [[X**0.5], [X**0.5, Y**0.5, X**0.5], [Y**-0.5]]
960
- s1_y: List[List[ops.SingleQubitCliffordGate]] = [
1062
+ s1: list[list[ops.SingleQubitCliffordGate]] = [[X**0.0], [Y**0.5, X**0.5], [X**-0.5, Y**-0.5]]
1063
+ s1_x: list[list[ops.SingleQubitCliffordGate]] = [[X**0.5], [X**0.5, Y**0.5, X**0.5], [Y**-0.5]]
1064
+ s1_y: list[list[ops.SingleQubitCliffordGate]] = [
961
1065
  [Y**0.5],
962
1066
  [X**-0.5, Y**-0.5, X**0.5],
963
1067
  [Y, X**0.5],
@@ -12,6 +12,11 @@
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
+
17
+ import os
18
+ from unittest import mock
19
+
15
20
  import matplotlib.pyplot as plt
16
21
  import numpy as np
17
22
  import pytest
@@ -102,6 +107,7 @@ def test_single_qubit_cliffords():
102
107
  assert num_x <= 1
103
108
 
104
109
 
110
+ @mock.patch.dict(os.environ, clear='CIRQ_TESTING')
105
111
  def test_single_qubit_randomized_benchmarking():
106
112
  # Check that the ground state population at the end of the Clifford
107
113
  # sequences is always unity.
@@ -114,7 +120,8 @@ def test_single_qubit_randomized_benchmarking():
114
120
  assert np.isclose(results.pauli_error(), 0.0, atol=1e-7) # warning is expected
115
121
 
116
122
 
117
- def test_parallel_single_qubit_randomized_benchmarking():
123
+ @mock.patch.dict(os.environ, clear='CIRQ_TESTING')
124
+ def test_parallel_single_qubit_parallel_single_qubit_randomized_benchmarking():
118
125
  # Check that the ground state population at the end of the Clifford
119
126
  # sequences is always unity.
120
127
  simulator = sim.Simulator()
@@ -150,24 +157,34 @@ def test_two_qubit_randomized_benchmarking():
150
157
  def test_single_qubit_state_tomography():
151
158
  # Check that the density matrices of the output states of X/2, Y/2 and
152
159
  # H + Y gates closely match the ideal cases.
160
+ # Checks that unique tomography keys are generated
153
161
  simulator = sim.Simulator()
154
- qubit = GridQubit(0, 0)
162
+ q_0 = GridQubit(0, 0)
163
+ q_1 = GridQubit(0, 1)
155
164
 
156
- circuit_1 = circuits.Circuit(ops.X(qubit) ** 0.5)
157
- circuit_2 = circuits.Circuit(ops.Y(qubit) ** 0.5)
158
- circuit_3 = circuits.Circuit(ops.H(qubit), ops.Y(qubit))
165
+ circuit_1 = circuits.Circuit(ops.X(q_0) ** 0.5)
166
+ circuit_2 = circuits.Circuit(ops.Y(q_0) ** 0.5)
167
+ circuit_3 = circuits.Circuit(ops.H(q_0), ops.Y(q_0))
168
+ circuit_4 = circuits.Circuit(ops.H(q_0), ops.Y(q_0), cirq.measure(q_1, key='z'))
169
+ circuit_5 = circuits.Circuit(ops.H(q_0), ops.Y(q_0), cirq.measure(q_1, key='tomo_key'))
159
170
 
160
- act_rho_1 = single_qubit_state_tomography(simulator, qubit, circuit_1, 1000).data
161
- act_rho_2 = single_qubit_state_tomography(simulator, qubit, circuit_2, 1000).data
162
- act_rho_3 = single_qubit_state_tomography(simulator, qubit, circuit_3, 1000).data
171
+ act_rho_1 = single_qubit_state_tomography(simulator, q_0, circuit_1, 1000).data
172
+ act_rho_2 = single_qubit_state_tomography(simulator, q_0, circuit_2, 1000).data
173
+ act_rho_3 = single_qubit_state_tomography(simulator, q_0, circuit_3, 1000).data
174
+ act_rho_4 = single_qubit_state_tomography(simulator, q_0, circuit_4, 1000).data
175
+ act_rho_5 = single_qubit_state_tomography(simulator, q_0, circuit_5, 1000).data
163
176
 
164
177
  tar_rho_1 = np.array([[0.5, 0.5j], [-0.5j, 0.5]])
165
178
  tar_rho_2 = np.array([[0.5, 0.5], [0.5, 0.5]])
166
179
  tar_rho_3 = np.array([[0.5, -0.5], [-0.5, 0.5]])
180
+ tar_rho_4 = np.array([[0.5, -0.5], [-0.5, 0.5]])
181
+ tar_rho_5 = np.array([[0.5, -0.5], [-0.5, 0.5]])
167
182
 
168
183
  np.testing.assert_almost_equal(act_rho_1, tar_rho_1, decimal=1)
169
184
  np.testing.assert_almost_equal(act_rho_2, tar_rho_2, decimal=1)
170
185
  np.testing.assert_almost_equal(act_rho_3, tar_rho_3, decimal=1)
186
+ np.testing.assert_almost_equal(act_rho_4, tar_rho_4, decimal=1)
187
+ np.testing.assert_almost_equal(act_rho_5, tar_rho_5, decimal=1)
171
188
 
172
189
 
173
190
  def test_two_qubit_state_tomography():
@@ -219,7 +236,7 @@ def test_tomography_plot_raises_for_incorrect_number_of_axes():
219
236
  qubit = GridQubit(0, 0)
220
237
  circuit = circuits.Circuit(ops.X(qubit) ** 0.5)
221
238
  result = single_qubit_state_tomography(simulator, qubit, circuit, 1000)
222
- with pytest.raises(TypeError): # ax is not a List[plt.Axes]
239
+ with pytest.raises(TypeError): # ax is not a list[plt.Axes]
223
240
  ax = plt.subplot()
224
241
  result.plot(ax)
225
242
  with pytest.raises(ValueError):
@@ -227,13 +244,24 @@ def test_tomography_plot_raises_for_incorrect_number_of_axes():
227
244
  result.plot(axes)
228
245
 
229
246
 
230
- def test_single_qubit_cliffords_gateset():
247
+ @pytest.mark.parametrize('num_cliffords', range(5, 10))
248
+ @pytest.mark.parametrize('use_xy_basis', [False, True])
249
+ @pytest.mark.parametrize('strict_basis', [False, True])
250
+ def test_single_qubit_cliffords_gateset(num_cliffords, use_xy_basis, strict_basis):
231
251
  qubits = [GridQubit(0, i) for i in range(4)]
232
- clifford_group = cirq.experiments.qubit_characterizations._single_qubit_cliffords()
252
+ c1_in_xy = cirq.experiments.qubit_characterizations.RBParameters(
253
+ use_xy_basis=use_xy_basis, strict_basis=strict_basis
254
+ ).gateset()
255
+ if strict_basis:
256
+ assert len(c1_in_xy) == 20
257
+ else:
258
+ assert len(c1_in_xy) == 24
233
259
  c = cirq.experiments.qubit_characterizations._create_parallel_rb_circuit(
234
- qubits, 5, clifford_group.c1_in_xy
260
+ qubits, num_cliffords, c1_in_xy
235
261
  )
236
262
  device = cirq.testing.ValidatingTestDevice(
237
263
  qubits=qubits, allowed_gates=(cirq.ops.PhasedXZGate, cirq.MeasurementGate)
238
264
  )
239
265
  device.validate_circuit(c)
266
+
267
+ assert len(c) == num_cliffords + 2