cirq-core 1.4.0.dev20240529225110__py3-none-any.whl → 1.5.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (590) hide show
  1. cirq/__init__.py +587 -569
  2. cirq/_compat.py +9 -0
  3. cirq/_compat_test.py +11 -9
  4. cirq/_import.py +7 -8
  5. cirq/_version.py +31 -1
  6. cirq/_version_test.py +1 -1
  7. cirq/circuits/__init__.py +15 -9
  8. cirq/circuits/_block_diagram_drawer.py +1 -2
  9. cirq/circuits/_block_diagram_drawer_test.py +3 -3
  10. cirq/circuits/_box_drawing_character_data.py +0 -1
  11. cirq/circuits/_box_drawing_character_data_test.py +2 -2
  12. cirq/circuits/_bucket_priority_queue.py +0 -1
  13. cirq/circuits/_bucket_priority_queue_test.py +1 -1
  14. cirq/circuits/circuit.py +336 -234
  15. cirq/circuits/circuit_operation.py +102 -52
  16. cirq/circuits/circuit_operation_test.py +85 -4
  17. cirq/circuits/circuit_test.py +101 -32
  18. cirq/circuits/frozen_circuit.py +36 -32
  19. cirq/circuits/insert_strategy.py +10 -0
  20. cirq/circuits/insert_strategy_test.py +20 -0
  21. cirq/circuits/moment.py +79 -80
  22. cirq/circuits/moment_test.py +105 -2
  23. cirq/circuits/optimization_pass.py +15 -15
  24. cirq/circuits/optimization_pass_test.py +8 -9
  25. cirq/circuits/qasm_output.py +64 -33
  26. cirq/circuits/qasm_output_test.py +63 -2
  27. cirq/circuits/text_diagram_drawer.py +26 -56
  28. cirq/circuits/text_diagram_drawer_test.py +5 -4
  29. cirq/contrib/__init__.py +2 -2
  30. cirq/contrib/acquaintance/__init__.py +44 -29
  31. cirq/contrib/acquaintance/bipartite.py +8 -7
  32. cirq/contrib/acquaintance/bipartite_test.py +11 -1
  33. cirq/contrib/acquaintance/devices.py +5 -4
  34. cirq/contrib/acquaintance/devices_test.py +5 -1
  35. cirq/contrib/acquaintance/executor.py +18 -21
  36. cirq/contrib/acquaintance/executor_test.py +3 -2
  37. cirq/contrib/acquaintance/gates.py +36 -27
  38. cirq/contrib/acquaintance/gates_test.py +1 -1
  39. cirq/contrib/acquaintance/inspection_utils.py +10 -9
  40. cirq/contrib/acquaintance/inspection_utils_test.py +6 -1
  41. cirq/contrib/acquaintance/mutation_utils.py +10 -10
  42. cirq/contrib/acquaintance/optimizers.py +7 -6
  43. cirq/contrib/acquaintance/optimizers_test.py +1 -1
  44. cirq/contrib/acquaintance/permutation.py +22 -21
  45. cirq/contrib/acquaintance/permutation_test.py +1 -1
  46. cirq/contrib/acquaintance/shift.py +8 -6
  47. cirq/contrib/acquaintance/shift_swap_network.py +6 -4
  48. cirq/contrib/acquaintance/strategies/__init__.py +9 -3
  49. cirq/contrib/acquaintance/strategies/complete.py +4 -3
  50. cirq/contrib/acquaintance/strategies/cubic.py +5 -3
  51. cirq/contrib/acquaintance/strategies/quartic_paired.py +8 -6
  52. cirq/contrib/acquaintance/topological_sort.py +4 -2
  53. cirq/contrib/bayesian_network/__init__.py +3 -1
  54. cirq/contrib/bayesian_network/bayesian_network_gate.py +5 -3
  55. cirq/contrib/circuitdag/__init__.py +1 -1
  56. cirq/contrib/circuitdag/circuit_dag.py +24 -24
  57. cirq/contrib/circuitdag/circuit_dag_test.py +1 -1
  58. cirq/contrib/custom_simulators/custom_state_simulator.py +10 -8
  59. cirq/contrib/custom_simulators/custom_state_simulator_test.py +15 -11
  60. cirq/contrib/graph_device/__init__.py +8 -8
  61. cirq/contrib/graph_device/graph_device.py +8 -8
  62. cirq/contrib/graph_device/graph_device_test.py +0 -1
  63. cirq/contrib/graph_device/hypergraph_test.py +1 -0
  64. cirq/contrib/json.py +1 -2
  65. cirq/contrib/json_test.py +2 -2
  66. cirq/contrib/noise_models/__init__.py +5 -6
  67. cirq/contrib/noise_models/noise_models.py +8 -6
  68. cirq/contrib/paulistring/__init__.py +22 -10
  69. cirq/contrib/paulistring/clifford_optimize.py +1 -1
  70. cirq/contrib/paulistring/clifford_optimize_test.py +0 -1
  71. cirq/contrib/paulistring/clifford_target_gateset.py +15 -12
  72. cirq/contrib/paulistring/optimize.py +2 -2
  73. cirq/contrib/paulistring/optimize_test.py +0 -1
  74. cirq/contrib/paulistring/pauli_string_dag_test.py +0 -1
  75. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +379 -0
  76. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +523 -0
  77. cirq/contrib/paulistring/pauli_string_optimize.py +3 -1
  78. cirq/contrib/paulistring/pauli_string_optimize_test.py +1 -3
  79. cirq/contrib/paulistring/recombine.py +2 -2
  80. cirq/contrib/paulistring/recombine_test.py +2 -2
  81. cirq/contrib/paulistring/separate.py +3 -4
  82. cirq/contrib/qasm_import/__init__.py +2 -2
  83. cirq/contrib/qasm_import/_lexer.py +21 -26
  84. cirq/contrib/qasm_import/_lexer_test.py +90 -6
  85. cirq/contrib/qasm_import/_parser.py +238 -47
  86. cirq/contrib/qasm_import/_parser_test.py +514 -59
  87. cirq/contrib/qasm_import/qasm_test.py +1 -1
  88. cirq/contrib/qcircuit/__init__.py +6 -4
  89. cirq/contrib/qcircuit/qcircuit_diagram.py +5 -2
  90. cirq/contrib/qcircuit/qcircuit_pdf.py +1 -2
  91. cirq/{experiments/grid_parallel_two_qubit_xeb_test.py → contrib/qcircuit/qcircuit_pdf_test.py} +13 -12
  92. cirq/contrib/qcircuit/qcircuit_test.py +1 -1
  93. cirq/contrib/quantum_volume/__init__.py +7 -7
  94. cirq/contrib/quantum_volume/quantum_volume.py +6 -11
  95. cirq/contrib/quantum_volume/quantum_volume_test.py +3 -1
  96. cirq/contrib/quimb/__init__.py +16 -13
  97. cirq/contrib/quimb/density_matrix.py +1 -1
  98. cirq/contrib/quimb/mps_simulator.py +27 -28
  99. cirq/contrib/quimb/mps_simulator_test.py +5 -0
  100. cirq/contrib/quimb/state_vector.py +3 -10
  101. cirq/contrib/quirk/__init__.py +1 -1
  102. cirq/contrib/quirk/export_to_quirk.py +3 -3
  103. cirq/contrib/routing/__init__.py +12 -9
  104. cirq/contrib/routing/device.py +1 -1
  105. cirq/contrib/routing/device_test.py +1 -2
  106. cirq/contrib/routing/greedy.py +7 -5
  107. cirq/contrib/routing/greedy_test.py +5 -3
  108. cirq/contrib/routing/initialization.py +3 -1
  109. cirq/contrib/routing/initialization_test.py +1 -1
  110. cirq/contrib/routing/swap_network.py +6 -6
  111. cirq/contrib/routing/utils.py +6 -4
  112. cirq/contrib/routing/utils_test.py +1 -2
  113. cirq/{type_workarounds.py → contrib/shuffle_circuits/__init__.py} +5 -10
  114. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +250 -0
  115. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking_test.py +363 -0
  116. cirq/contrib/svg/__init__.py +1 -1
  117. cirq/contrib/svg/svg.py +12 -10
  118. cirq/contrib/svg/svg_test.py +3 -2
  119. cirq/devices/__init__.py +34 -25
  120. cirq/devices/device.py +16 -12
  121. cirq/devices/device_test.py +1 -0
  122. cirq/devices/grid_device_metadata.py +16 -12
  123. cirq/devices/grid_device_metadata_test.py +2 -1
  124. cirq/devices/grid_qubit.py +31 -26
  125. cirq/devices/grid_qubit_test.py +30 -1
  126. cirq/devices/insertion_noise_model.py +6 -6
  127. cirq/devices/insertion_noise_model_test.py +1 -1
  128. cirq/devices/line_qubit.py +28 -20
  129. cirq/devices/line_qubit_test.py +26 -0
  130. cirq/devices/named_topologies.py +12 -10
  131. cirq/devices/named_topologies_test.py +5 -4
  132. cirq/devices/noise_model.py +29 -33
  133. cirq/devices/noise_properties.py +2 -2
  134. cirq/devices/noise_properties_test.py +2 -2
  135. cirq/devices/noise_utils.py +3 -3
  136. cirq/devices/superconducting_qubits_noise_properties.py +2 -2
  137. cirq/devices/superconducting_qubits_noise_properties_test.py +3 -3
  138. cirq/devices/thermal_noise_model.py +2 -1
  139. cirq/devices/unconstrained_device.py +1 -1
  140. cirq/devices/unconstrained_device_test.py +6 -0
  141. cirq/experiments/__init__.py +51 -34
  142. cirq/experiments/qubit_characterizations.py +17 -15
  143. cirq/experiments/qubit_characterizations_test.py +4 -6
  144. cirq/experiments/random_quantum_circuit_generation.py +10 -9
  145. cirq/experiments/random_quantum_circuit_generation_test.py +21 -4
  146. cirq/experiments/readout_confusion_matrix.py +73 -8
  147. cirq/experiments/readout_confusion_matrix_test.py +104 -1
  148. cirq/experiments/single_qubit_readout_calibration.py +8 -6
  149. cirq/experiments/single_qubit_readout_calibration_test.py +1 -1
  150. cirq/experiments/t1_decay_experiment.py +4 -5
  151. cirq/experiments/t1_decay_experiment_test.py +1 -2
  152. cirq/experiments/t2_decay_experiment.py +0 -1
  153. cirq/experiments/t2_decay_experiment_test.py +1 -2
  154. cirq/experiments/two_qubit_xeb.py +157 -33
  155. cirq/experiments/two_qubit_xeb_test.py +38 -22
  156. cirq/experiments/xeb_fitting.py +99 -19
  157. cirq/experiments/xeb_fitting_test.py +64 -25
  158. cirq/experiments/xeb_sampling.py +14 -18
  159. cirq/experiments/xeb_simulation.py +4 -3
  160. cirq/experiments/xeb_simulation_test.py +20 -14
  161. cirq/experiments/z_phase_calibration.py +368 -0
  162. cirq/experiments/z_phase_calibration_test.py +241 -0
  163. cirq/interop/__init__.py +4 -1
  164. cirq/interop/quirk/__init__.py +7 -4
  165. cirq/interop/quirk/cells/__init__.py +17 -6
  166. cirq/interop/quirk/cells/arithmetic_cells.py +8 -8
  167. cirq/interop/quirk/cells/arithmetic_cells_test.py +1 -1
  168. cirq/interop/quirk/cells/cell.py +6 -6
  169. cirq/interop/quirk/cells/composite_cell.py +5 -5
  170. cirq/interop/quirk/cells/composite_cell_test.py +1 -1
  171. cirq/interop/quirk/cells/control_cells.py +1 -1
  172. cirq/interop/quirk/cells/frequency_space_cells.py +2 -2
  173. cirq/interop/quirk/cells/ignored_cells.py +1 -1
  174. cirq/interop/quirk/cells/input_cells.py +1 -1
  175. cirq/interop/quirk/cells/input_cells_test.py +1 -1
  176. cirq/interop/quirk/cells/input_rotation_cells.py +1 -1
  177. cirq/interop/quirk/cells/input_rotation_cells_test.py +1 -1
  178. cirq/interop/quirk/cells/measurement_cells.py +1 -1
  179. cirq/interop/quirk/cells/parse.py +8 -7
  180. cirq/interop/quirk/cells/parse_test.py +2 -2
  181. cirq/interop/quirk/cells/single_qubit_rotation_cells.py +1 -1
  182. cirq/interop/quirk/cells/swap_cell_test.py +1 -1
  183. cirq/interop/quirk/cells/unsupported_cells.py +1 -1
  184. cirq/interop/quirk/url_to_circuit.py +7 -7
  185. cirq/interop/quirk/url_to_circuit_test.py +1 -1
  186. cirq/ion/__init__.py +4 -2
  187. cirq/json_resolver_cache.py +15 -7
  188. cirq/linalg/__init__.py +62 -51
  189. cirq/linalg/combinators.py +4 -4
  190. cirq/linalg/combinators_test.py +4 -1
  191. cirq/linalg/decompositions.py +15 -40
  192. cirq/linalg/decompositions_test.py +16 -22
  193. cirq/linalg/diagonalize.py +1 -1
  194. cirq/linalg/diagonalize_test.py +1 -1
  195. cirq/linalg/operator_spaces.py +20 -4
  196. cirq/linalg/operator_spaces_test.py +15 -2
  197. cirq/linalg/predicates.py +3 -3
  198. cirq/linalg/predicates_test.py +1 -0
  199. cirq/linalg/tolerance.py +2 -2
  200. cirq/linalg/transformations.py +30 -12
  201. cirq/linalg/transformations_test.py +13 -0
  202. cirq/neutral_atoms/__init__.py +2 -2
  203. cirq/neutral_atoms/convert_to_neutral_atom_gates_test.py +0 -1
  204. cirq/ops/__init__.py +172 -132
  205. cirq/ops/arithmetic_operation.py +2 -2
  206. cirq/ops/arithmetic_operation_test.py +2 -2
  207. cirq/ops/boolean_hamiltonian.py +3 -2
  208. cirq/ops/classically_controlled_operation.py +39 -12
  209. cirq/ops/classically_controlled_operation_test.py +147 -1
  210. cirq/ops/clifford_gate.py +38 -36
  211. cirq/ops/clifford_gate_test.py +75 -1
  212. cirq/ops/common_channels.py +16 -45
  213. cirq/ops/common_channels_test.py +10 -0
  214. cirq/ops/common_gate_families.py +1 -1
  215. cirq/ops/common_gate_families_test.py +1 -0
  216. cirq/ops/common_gates.py +48 -49
  217. cirq/ops/common_gates_test.py +18 -2
  218. cirq/ops/control_values.py +3 -3
  219. cirq/ops/control_values_test.py +2 -1
  220. cirq/ops/controlled_gate.py +36 -23
  221. cirq/ops/controlled_gate_test.py +70 -3
  222. cirq/ops/controlled_operation.py +6 -5
  223. cirq/ops/controlled_operation_test.py +7 -3
  224. cirq/ops/dense_pauli_string.py +11 -11
  225. cirq/ops/diagonal_gate.py +2 -2
  226. cirq/ops/diagonal_gate_test.py +1 -0
  227. cirq/ops/eigen_gate.py +16 -36
  228. cirq/ops/eigen_gate_test.py +60 -10
  229. cirq/ops/fourier_transform.py +1 -3
  230. cirq/ops/fourier_transform_test.py +2 -1
  231. cirq/ops/fsim_gate.py +42 -3
  232. cirq/ops/fsim_gate_test.py +21 -0
  233. cirq/ops/gate_operation.py +8 -8
  234. cirq/ops/gate_operation_test.py +4 -2
  235. cirq/ops/gateset_test.py +11 -2
  236. cirq/ops/global_phase_op.py +8 -7
  237. cirq/ops/global_phase_op_test.py +1 -1
  238. cirq/ops/greedy_qubit_manager_test.py +5 -0
  239. cirq/ops/identity.py +14 -4
  240. cirq/ops/identity_test.py +24 -0
  241. cirq/ops/kraus_channel.py +1 -0
  242. cirq/ops/kraus_channel_test.py +3 -1
  243. cirq/ops/linear_combinations.py +27 -21
  244. cirq/ops/linear_combinations_test.py +23 -4
  245. cirq/ops/matrix_gates.py +24 -8
  246. cirq/ops/measure_util.py +2 -2
  247. cirq/ops/measurement_gate.py +7 -4
  248. cirq/ops/measurement_gate_test.py +2 -1
  249. cirq/ops/mixed_unitary_channel.py +1 -0
  250. cirq/ops/mixed_unitary_channel_test.py +3 -1
  251. cirq/ops/named_qubit.py +8 -1
  252. cirq/ops/op_tree.py +3 -30
  253. cirq/ops/op_tree_test.py +4 -0
  254. cirq/ops/parallel_gate.py +2 -3
  255. cirq/ops/parallel_gate_test.py +2 -1
  256. cirq/ops/parity_gates.py +7 -8
  257. cirq/ops/parity_gates_test.py +1 -0
  258. cirq/ops/pauli_gates.py +5 -11
  259. cirq/ops/pauli_gates_test.py +1 -0
  260. cirq/ops/pauli_interaction_gate.py +11 -5
  261. cirq/ops/pauli_interaction_gate_test.py +2 -3
  262. cirq/ops/pauli_measurement_gate.py +6 -5
  263. cirq/ops/pauli_measurement_gate_test.py +1 -0
  264. cirq/ops/pauli_string.py +115 -130
  265. cirq/ops/pauli_string_phasor.py +21 -20
  266. cirq/ops/pauli_string_phasor_test.py +13 -3
  267. cirq/ops/pauli_string_raw_types.py +1 -0
  268. cirq/ops/pauli_string_test.py +192 -55
  269. cirq/ops/pauli_sum_exponential.py +3 -4
  270. cirq/ops/pauli_sum_exponential_test.py +0 -1
  271. cirq/ops/permutation_gate.py +2 -2
  272. cirq/ops/permutation_gate_test.py +1 -1
  273. cirq/ops/phased_iswap_gate.py +6 -7
  274. cirq/ops/phased_iswap_gate_test.py +21 -5
  275. cirq/ops/phased_x_gate.py +11 -25
  276. cirq/ops/phased_x_gate_test.py +19 -3
  277. cirq/ops/phased_x_z_gate.py +12 -11
  278. cirq/ops/projector.py +4 -5
  279. cirq/ops/qubit_manager.py +2 -1
  280. cirq/ops/qubit_manager_test.py +2 -1
  281. cirq/ops/qubit_order.py +1 -1
  282. cirq/ops/random_gate_channel.py +1 -1
  283. cirq/ops/random_gate_channel_test.py +0 -6
  284. cirq/ops/raw_types.py +146 -50
  285. cirq/ops/raw_types_test.py +37 -3
  286. cirq/ops/state_preparation_channel.py +2 -2
  287. cirq/ops/state_preparation_channel_test.py +2 -1
  288. cirq/ops/swap_gates.py +9 -4
  289. cirq/ops/three_qubit_gates.py +8 -8
  290. cirq/ops/three_qubit_gates_test.py +1 -0
  291. cirq/ops/two_qubit_diagonal_gate.py +4 -3
  292. cirq/ops/uniform_superposition_gate.py +4 -4
  293. cirq/ops/uniform_superposition_gate_test.py +1 -0
  294. cirq/ops/wait_gate.py +6 -8
  295. cirq/protocols/__init__.py +135 -83
  296. cirq/protocols/act_on_protocol.py +1 -1
  297. cirq/protocols/act_on_protocol_test.py +1 -1
  298. cirq/protocols/apply_channel_protocol.py +3 -3
  299. cirq/protocols/apply_mixture_protocol.py +15 -9
  300. cirq/protocols/apply_mixture_protocol_test.py +11 -0
  301. cirq/protocols/apply_unitary_protocol.py +2 -2
  302. cirq/protocols/apply_unitary_protocol_test.py +2 -1
  303. cirq/protocols/approximate_equality_protocol.py +7 -8
  304. cirq/protocols/approximate_equality_protocol_test.py +3 -1
  305. cirq/protocols/circuit_diagram_info_protocol.py +8 -6
  306. cirq/protocols/circuit_diagram_info_protocol_test.py +5 -0
  307. cirq/protocols/commutes_protocol.py +6 -6
  308. cirq/protocols/control_key_protocol.py +1 -1
  309. cirq/protocols/decompose_protocol.py +4 -5
  310. cirq/protocols/decompose_protocol_test.py +2 -1
  311. cirq/protocols/equal_up_to_global_phase_protocol.py +3 -3
  312. cirq/protocols/equal_up_to_global_phase_protocol_test.py +7 -0
  313. cirq/protocols/has_stabilizer_effect_protocol.py +5 -5
  314. cirq/protocols/has_unitary_protocol.py +1 -1
  315. cirq/protocols/has_unitary_protocol_test.py +8 -7
  316. cirq/protocols/hash_from_pickle_test.py +120 -0
  317. cirq/protocols/inverse_protocol.py +1 -1
  318. cirq/protocols/json_serialization.py +14 -1
  319. cirq/protocols/json_serialization_test.py +28 -7
  320. cirq/protocols/json_test_data/BitMaskKeyCondition.json +86 -0
  321. cirq/protocols/json_test_data/BitMaskKeyCondition.repr +7 -0
  322. cirq/protocols/json_test_data/Concat.json +19 -0
  323. cirq/protocols/json_test_data/Concat.repr +1 -0
  324. cirq/protocols/json_test_data/README.md +4 -2
  325. cirq/protocols/json_test_data/SympyCondition.json +60 -15
  326. cirq/protocols/json_test_data/SympyCondition.repr +4 -1
  327. cirq/protocols/json_test_data/_InverseCompositeGate.json +10 -0
  328. cirq/protocols/json_test_data/_InverseCompositeGate.repr +1 -0
  329. cirq/protocols/json_test_data/__init__.py +1 -1
  330. cirq/protocols/json_test_data/sympy.And.json +13 -0
  331. cirq/protocols/json_test_data/sympy.And.repr +1 -0
  332. cirq/protocols/json_test_data/sympy.Indexed.json +18 -0
  333. cirq/protocols/json_test_data/sympy.Indexed.repr +1 -0
  334. cirq/protocols/json_test_data/sympy.IndexedBase.json +9 -0
  335. cirq/protocols/json_test_data/sympy.IndexedBase.repr +1 -0
  336. cirq/protocols/json_test_data/sympy.Not.json +9 -0
  337. cirq/protocols/json_test_data/sympy.Not.repr +1 -0
  338. cirq/protocols/json_test_data/sympy.Or.json +13 -0
  339. cirq/protocols/json_test_data/sympy.Or.repr +1 -0
  340. cirq/protocols/json_test_data/sympy.Xor.json +13 -0
  341. cirq/protocols/json_test_data/sympy.Xor.repr +1 -0
  342. cirq/protocols/kraus_protocol.py +8 -8
  343. cirq/protocols/kraus_protocol_test.py +0 -1
  344. cirq/protocols/measurement_key_protocol.py +1 -1
  345. cirq/protocols/measurement_key_protocol_test.py +7 -7
  346. cirq/protocols/mixture_protocol.py +6 -4
  347. cirq/protocols/mixture_protocol_test.py +21 -13
  348. cirq/protocols/pauli_expansion_protocol.py +1 -0
  349. cirq/protocols/pow_protocol.py +1 -1
  350. cirq/protocols/qasm.py +25 -6
  351. cirq/protocols/qasm_test.py +17 -0
  352. cirq/protocols/qid_shape_protocol.py +2 -2
  353. cirq/protocols/resolve_parameters.py +2 -3
  354. cirq/protocols/resolve_parameters_test.py +2 -1
  355. cirq/protocols/trace_distance_bound.py +1 -1
  356. cirq/protocols/trace_distance_bound_test.py +1 -0
  357. cirq/protocols/unitary_protocol.py +3 -3
  358. cirq/protocols/unitary_protocol_test.py +1 -1
  359. cirq/qis/__init__.py +48 -35
  360. cirq/qis/channels_test.py +0 -9
  361. cirq/qis/clifford_tableau.py +46 -26
  362. cirq/qis/clifford_tableau_test.py +2 -1
  363. cirq/qis/entropy.py +115 -0
  364. cirq/qis/entropy_test.py +43 -0
  365. cirq/qis/measures.py +5 -4
  366. cirq/qis/measures_test.py +7 -0
  367. cirq/qis/noise_utils_test.py +4 -4
  368. cirq/qis/quantum_state_representation.py +1 -1
  369. cirq/qis/states.py +7 -7
  370. cirq/sim/__init__.py +55 -37
  371. cirq/sim/classical_simulator.py +7 -6
  372. cirq/sim/classical_simulator_test.py +3 -1
  373. cirq/sim/clifford/__init__.py +17 -9
  374. cirq/sim/clifford/clifford_simulator.py +5 -4
  375. cirq/sim/clifford/clifford_simulator_test.py +32 -9
  376. cirq/sim/clifford/clifford_tableau_simulation_state.py +1 -1
  377. cirq/sim/clifford/stabilizer_simulation_state.py +1 -1
  378. cirq/sim/clifford/stabilizer_state_ch_form.py +4 -3
  379. cirq/sim/density_matrix_simulator.py +3 -2
  380. cirq/sim/density_matrix_simulator_test.py +12 -4
  381. cirq/sim/density_matrix_utils.py +1 -1
  382. cirq/sim/mux.py +2 -2
  383. cirq/sim/simulation_state.py +4 -5
  384. cirq/sim/simulation_state_base.py +2 -2
  385. cirq/sim/simulation_state_test.py +1 -1
  386. cirq/sim/simulation_utils.py +3 -1
  387. cirq/sim/simulation_utils_test.py +2 -3
  388. cirq/sim/simulator.py +7 -6
  389. cirq/sim/simulator_base.py +5 -5
  390. cirq/sim/simulator_test.py +14 -3
  391. cirq/sim/sparse_simulator.py +4 -3
  392. cirq/sim/sparse_simulator_test.py +17 -9
  393. cirq/sim/state_vector.py +2 -2
  394. cirq/sim/state_vector_simulation_state_test.py +1 -1
  395. cirq/sim/state_vector_simulator.py +4 -4
  396. cirq/sim/state_vector_test.py +27 -32
  397. cirq/study/__init__.py +27 -21
  398. cirq/study/flatten_expressions.py +5 -6
  399. cirq/study/flatten_expressions_test.py +1 -1
  400. cirq/study/resolver.py +14 -11
  401. cirq/study/resolver_test.py +10 -1
  402. cirq/study/result.py +3 -3
  403. cirq/study/sweepable.py +15 -9
  404. cirq/study/sweepable_test.py +27 -0
  405. cirq/study/sweeps.py +65 -10
  406. cirq/study/sweeps_test.py +123 -0
  407. cirq/testing/__init__.py +86 -57
  408. cirq/testing/_compat_test_data/module_a/__init__.py +2 -2
  409. cirq/testing/_compat_test_data/module_a/sub/subsub/__init__.py +1 -1
  410. cirq/testing/circuit_compare.py +3 -4
  411. cirq/testing/circuit_compare_test.py +7 -8
  412. cirq/testing/consistent_act_on.py +3 -3
  413. cirq/testing/consistent_channels_test.py +2 -1
  414. cirq/testing/consistent_controlled_gate_op.py +3 -2
  415. cirq/testing/consistent_controlled_gate_op_test.py +2 -3
  416. cirq/testing/consistent_decomposition.py +1 -1
  417. cirq/testing/consistent_decomposition_test.py +1 -2
  418. cirq/testing/consistent_pauli_expansion_test.py +1 -1
  419. cirq/testing/consistent_phase_by.py +1 -1
  420. cirq/testing/consistent_phase_by_test.py +1 -2
  421. cirq/testing/consistent_protocols.py +11 -11
  422. cirq/testing/consistent_protocols_test.py +4 -5
  423. cirq/testing/consistent_qasm.py +8 -12
  424. cirq/testing/consistent_qasm_test.py +1 -1
  425. cirq/testing/consistent_resolve_parameters.py +2 -1
  426. cirq/testing/consistent_specified_has_unitary_test.py +1 -1
  427. cirq/testing/consistent_unitary.py +3 -1
  428. cirq/testing/consistent_unitary_test.py +3 -3
  429. cirq/testing/devices.py +1 -1
  430. cirq/testing/devices_test.py +1 -0
  431. cirq/testing/equals_tester.py +2 -4
  432. cirq/testing/equals_tester_test.py +6 -5
  433. cirq/testing/equivalent_basis_map.py +1 -0
  434. cirq/testing/equivalent_basis_map_test.py +0 -1
  435. cirq/testing/gate_features_test.py +5 -0
  436. cirq/testing/json.py +4 -4
  437. cirq/testing/lin_alg_utils_test.py +1 -1
  438. cirq/testing/order_tester.py +1 -1
  439. cirq/testing/order_tester_test.py +1 -1
  440. cirq/testing/pytest_utils.py +57 -0
  441. cirq/testing/pytest_utils_test.py +35 -0
  442. cirq/testing/random_circuit.py +2 -2
  443. cirq/testing/random_circuit_test.py +2 -2
  444. cirq/testing/routing_devices_test.py +2 -1
  445. cirq/testing/sample_circuits.py +1 -1
  446. cirq/testing/sample_gates.py +5 -4
  447. cirq/testing/sample_gates_test.py +2 -2
  448. cirq/transformers/__init__.py +101 -82
  449. cirq/transformers/align.py +12 -1
  450. cirq/transformers/align_test.py +13 -0
  451. cirq/transformers/analytical_decompositions/__init__.py +27 -24
  452. cirq/transformers/analytical_decompositions/clifford_decomposition.py +2 -1
  453. cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +1 -1
  454. cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +1 -1
  455. cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +2 -0
  456. cirq/transformers/analytical_decompositions/cphase_to_fsim.py +1 -1
  457. cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +1 -1
  458. cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +2 -2
  459. cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +4 -4
  460. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +99 -24
  461. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +105 -14
  462. cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +1 -1
  463. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +1 -1
  464. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +1 -0
  465. cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +3 -4
  466. cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +1 -1
  467. cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +2 -1
  468. cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +2 -1
  469. cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +5 -6
  470. cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +2 -2
  471. cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +1 -1
  472. cirq/transformers/analytical_decompositions/two_qubit_to_fsim_test.py +1 -2
  473. cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +2 -2
  474. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +2 -2
  475. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +2 -1
  476. cirq/transformers/drop_empty_moments.py +1 -0
  477. cirq/transformers/drop_negligible_operations.py +1 -0
  478. cirq/transformers/dynamical_decoupling.py +255 -43
  479. cirq/transformers/dynamical_decoupling_test.py +730 -17
  480. cirq/transformers/eject_phased_paulis.py +29 -15
  481. cirq/transformers/eject_phased_paulis_test.py +3 -8
  482. cirq/transformers/eject_z.py +3 -2
  483. cirq/transformers/eject_z_test.py +3 -3
  484. cirq/transformers/gauge_compiling/__init__.py +25 -9
  485. cirq/transformers/gauge_compiling/cphase_gauge.py +146 -0
  486. cirq/transformers/gauge_compiling/cphase_gauge_test.py +42 -0
  487. cirq/transformers/gauge_compiling/cz_gauge.py +4 -4
  488. cirq/transformers/gauge_compiling/gauge_compiling.py +245 -6
  489. cirq/transformers/gauge_compiling/gauge_compiling_test.py +107 -2
  490. cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +39 -2
  491. cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +10 -1
  492. cirq/transformers/gauge_compiling/iswap_gauge.py +2 -2
  493. cirq/transformers/gauge_compiling/spin_inversion_gauge.py +2 -2
  494. cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +23 -5
  495. cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +3 -2
  496. cirq/transformers/heuristic_decompositions/__init__.py +3 -3
  497. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +2 -1
  498. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +1 -1
  499. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +4 -4
  500. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation_test.py +4 -4
  501. cirq/transformers/insertion_sort.py +64 -0
  502. cirq/transformers/insertion_sort_test.py +34 -0
  503. cirq/transformers/measurement_transformers.py +14 -1
  504. cirq/transformers/measurement_transformers_test.py +35 -0
  505. cirq/transformers/merge_k_qubit_gates.py +2 -2
  506. cirq/transformers/merge_single_qubit_gates.py +1 -1
  507. cirq/transformers/merge_single_qubit_gates_test.py +1 -1
  508. cirq/transformers/noise_adding.py +115 -0
  509. cirq/transformers/noise_adding_test.py +54 -0
  510. cirq/transformers/optimize_for_target_gateset.py +1 -1
  511. cirq/transformers/optimize_for_target_gateset_test.py +3 -2
  512. cirq/transformers/qubit_management_transformers.py +1 -1
  513. cirq/transformers/randomized_measurements.py +171 -0
  514. cirq/transformers/randomized_measurements_test.py +68 -0
  515. cirq/transformers/routing/__init__.py +14 -5
  516. cirq/transformers/routing/initial_mapper.py +1 -1
  517. cirq/transformers/routing/initial_mapper_test.py +1 -0
  518. cirq/transformers/routing/line_initial_mapper.py +3 -2
  519. cirq/transformers/routing/mapping_manager.py +2 -2
  520. cirq/transformers/routing/mapping_manager_test.py +2 -2
  521. cirq/transformers/routing/route_circuit_cqc.py +3 -2
  522. cirq/transformers/routing/route_circuit_cqc_test.py +2 -1
  523. cirq/transformers/routing/visualize_routed_circuit.py +1 -0
  524. cirq/transformers/routing/visualize_routed_circuit_test.py +1 -0
  525. cirq/transformers/stratify.py +2 -2
  526. cirq/transformers/synchronize_terminal_measurements.py +2 -1
  527. cirq/transformers/target_gatesets/__init__.py +7 -5
  528. cirq/transformers/target_gatesets/compilation_target_gateset.py +16 -3
  529. cirq/transformers/target_gatesets/compilation_target_gateset_test.py +2 -0
  530. cirq/transformers/target_gatesets/cz_gateset.py +5 -1
  531. cirq/transformers/target_gatesets/cz_gateset_test.py +23 -2
  532. cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +1 -1
  533. cirq/transformers/target_gatesets/sqrt_iswap_gateset_test.py +3 -2
  534. cirq/transformers/transformer_api.py +5 -4
  535. cirq/transformers/transformer_api_test.py +11 -3
  536. cirq/transformers/transformer_primitives.py +9 -31
  537. cirq/transformers/transformer_primitives_test.py +6 -5
  538. cirq/value/__init__.py +51 -30
  539. cirq/value/abc_alt.py +1 -2
  540. cirq/value/angle.py +2 -0
  541. cirq/value/classical_data.py +1 -0
  542. cirq/value/condition.py +149 -3
  543. cirq/value/condition_test.py +254 -0
  544. cirq/value/digits.py +1 -1
  545. cirq/value/duration.py +4 -4
  546. cirq/value/duration_test.py +2 -1
  547. cirq/value/linear_dict.py +85 -24
  548. cirq/value/linear_dict_test.py +94 -3
  549. cirq/value/measurement_key.py +9 -2
  550. cirq/value/periodic_value.py +2 -3
  551. cirq/value/periodic_value_test.py +5 -0
  552. cirq/value/probability.py +1 -0
  553. cirq/value/random_state.py +1 -1
  554. cirq/value/timestamp.py +2 -4
  555. cirq/value/timestamp_test.py +2 -1
  556. cirq/value/type_alias.py +2 -2
  557. cirq/value/value_equality_attr.py +14 -2
  558. cirq/value/value_equality_attr_test.py +1 -1
  559. cirq/vis/__init__.py +9 -6
  560. cirq/vis/density_matrix.py +1 -1
  561. cirq/vis/density_matrix_test.py +2 -5
  562. cirq/vis/heatmap.py +49 -12
  563. cirq/vis/heatmap_test.py +168 -4
  564. cirq/vis/histogram.py +1 -1
  565. cirq/vis/histogram_test.py +1 -2
  566. cirq/vis/state_histogram.py +7 -5
  567. cirq/vis/state_histogram_test.py +2 -2
  568. cirq/work/__init__.py +19 -13
  569. cirq/work/collector.py +2 -2
  570. cirq/work/observable_grouping.py +2 -2
  571. cirq/work/observable_measurement.py +3 -3
  572. cirq/work/observable_measurement_data.py +5 -2
  573. cirq/work/observable_measurement_test.py +8 -8
  574. cirq/work/observable_readout_calibration.py +2 -2
  575. cirq/work/observable_readout_calibration_test.py +2 -1
  576. cirq/work/observable_settings.py +8 -7
  577. cirq/work/observable_settings_test.py +3 -2
  578. cirq/work/pauli_sum_collector.py +1 -1
  579. cirq/work/sampler.py +8 -20
  580. cirq/work/sampler_test.py +4 -3
  581. cirq/work/zeros_sampler.py +1 -1
  582. cirq_core-1.5.0.dist-info/METADATA +125 -0
  583. {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/RECORD +586 -552
  584. {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/WHEEL +1 -1
  585. cirq/experiments/grid_parallel_two_qubit_xeb.py +0 -62
  586. cirq/protocols/json_test_data/GridParallelXEBMetadata.json +0 -119
  587. cirq/protocols/json_test_data/GridParallelXEBMetadata.repr +0 -1
  588. cirq_core-1.4.0.dev20240529225110.dist-info/METADATA +0 -50
  589. {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/LICENSE +0 -0
  590. {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,368 @@
1
+ # Copyright 2024 The Cirq Developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Provides a method to do z-phase calibration for excitation-preserving gates."""
16
+ import multiprocessing
17
+ import multiprocessing.pool
18
+ from typing import Any, Dict, List, Optional, Sequence, Tuple, TYPE_CHECKING, Union
19
+
20
+ import matplotlib.pyplot as plt
21
+ import numpy as np
22
+
23
+ from cirq import circuits, ops, protocols
24
+ from cirq.experiments import xeb_fitting
25
+ from cirq.experiments.two_qubit_xeb import parallel_xeb_workflow
26
+ from cirq.transformers import transformer_api
27
+
28
+ if TYPE_CHECKING:
29
+ import pandas as pd
30
+
31
+ import cirq
32
+
33
+
34
+ def z_phase_calibration_workflow(
35
+ sampler: 'cirq.Sampler',
36
+ qubits: Optional[Sequence['cirq.GridQubit']] = None,
37
+ two_qubit_gate: 'cirq.Gate' = ops.CZ,
38
+ options: Optional[xeb_fitting.XEBPhasedFSimCharacterizationOptions] = None,
39
+ n_repetitions: int = 10**4,
40
+ n_combinations: int = 10,
41
+ n_circuits: int = 20,
42
+ cycle_depths: Sequence[int] = tuple(np.arange(3, 100, 20)),
43
+ random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
44
+ atol: float = 1e-3,
45
+ num_workers_or_pool: Union[int, 'multiprocessing.pool.Pool'] = -1,
46
+ pairs: Optional[Sequence[Tuple['cirq.GridQubit', 'cirq.GridQubit']]] = None,
47
+ tags: Sequence[Any] = (),
48
+ ) -> Tuple[xeb_fitting.XEBCharacterizationResult, 'pd.DataFrame']:
49
+ """Perform z-phase calibration for excitation-preserving gates.
50
+
51
+ For a given excitation-preserving two-qubit gate we assume an error model that can be described
52
+ using Z-rotations:
53
+ 0: ───Rz(a)───two_qubit_gate───Rz(c)───
54
+
55
+ 1: ───Rz(b)───two_qubit_gate───Rz(d)───
56
+ for some angles a, b, c, and d.
57
+
58
+ Since the two-qubit gate is a excitation-preserving-gate, it can be represented by an FSimGate
59
+ and the effect of rotations turns it into a PhasedFSimGate. Using XEB-data we find the
60
+ PhasedFSimGate parameters that minimize the infidelity of the gate.
61
+
62
+ References:
63
+ - https://arxiv.org/abs/2001.08343
64
+ - https://arxiv.org/abs/2010.07965
65
+ - https://arxiv.org/abs/1910.11333
66
+
67
+ Args:
68
+ sampler: The quantum engine or simulator to run the circuits.
69
+ qubits: Qubits to use. If none, use all qubits on the sampler's device.
70
+ two_qubit_gate: The entangling gate to use.
71
+ options: The XEB-fitting options. If None, calibrate only the three phase angles
72
+ (chi, gamma, zeta) using the representation of a two-qubit gate as an FSimGate
73
+ for the initial guess.
74
+ n_repetitions: The number of repetitions to use.
75
+ n_combinations: The number of combinations to generate.
76
+ n_circuits: The number of circuits to generate.
77
+ cycle_depths: The cycle depths to use.
78
+ random_state: The random state to use.
79
+ atol: Absolute tolerance to be used by the minimizer.
80
+ num_workers_or_pool: An optional multi-processing pool or number of workers.
81
+ A zero value means no multiprocessing.
82
+ A positive integer value will create a pool with the given number of workers.
83
+ A negative value will create pool with maximum number of workers.
84
+ pairs: Pairs to use. If not specified, use all pairs between adjacent qubits.
85
+ tags: Tags to add to two qubit operations.
86
+ Returns:
87
+ - An `XEBCharacterizationResult` object that contains the calibration result.
88
+ - A `pd.DataFrame` comparing the before and after fidelities.
89
+ """
90
+
91
+ pool: Optional['multiprocessing.pool.Pool'] = None
92
+ local_pool = False
93
+ if isinstance(num_workers_or_pool, multiprocessing.pool.Pool):
94
+ pool = num_workers_or_pool # pragma: no cover
95
+ elif num_workers_or_pool != 0:
96
+ pool = multiprocessing.Pool(num_workers_or_pool if num_workers_or_pool > 0 else None)
97
+ local_pool = True
98
+
99
+ fids_df_0, circuits, sampled_df = parallel_xeb_workflow(
100
+ sampler=sampler,
101
+ qubits=qubits,
102
+ entangling_gate=two_qubit_gate,
103
+ n_repetitions=n_repetitions,
104
+ cycle_depths=cycle_depths,
105
+ n_circuits=n_circuits,
106
+ n_combinations=n_combinations,
107
+ random_state=random_state,
108
+ pool=pool,
109
+ tags=tags,
110
+ pairs=pairs,
111
+ )
112
+
113
+ if options is None:
114
+ options = xeb_fitting.XEBPhasedFSimCharacterizationOptions(
115
+ characterize_chi=True,
116
+ characterize_gamma=True,
117
+ characterize_zeta=True,
118
+ characterize_theta=False,
119
+ characterize_phi=False,
120
+ ).with_defaults_from_gate(two_qubit_gate)
121
+
122
+ p_circuits = [
123
+ xeb_fitting.parameterize_circuit(circuit, options, ops.GateFamily(two_qubit_gate))
124
+ for circuit in circuits
125
+ ]
126
+
127
+ result = xeb_fitting.characterize_phased_fsim_parameters_with_xeb_by_pair(
128
+ sampled_df=sampled_df,
129
+ parameterized_circuits=p_circuits,
130
+ cycle_depths=cycle_depths,
131
+ options=options,
132
+ fatol=atol,
133
+ xatol=atol,
134
+ pool=pool,
135
+ )
136
+
137
+ before_after = xeb_fitting.before_and_after_characterization(
138
+ fids_df_0, characterization_result=result
139
+ )
140
+
141
+ if local_pool:
142
+ assert isinstance(pool, multiprocessing.pool.Pool)
143
+ pool.close()
144
+ return result, before_after
145
+
146
+
147
+ def calibrate_z_phases(
148
+ sampler: 'cirq.Sampler',
149
+ qubits: Optional[Sequence['cirq.GridQubit']] = None,
150
+ two_qubit_gate: 'cirq.Gate' = ops.CZ,
151
+ options: Optional[xeb_fitting.XEBPhasedFSimCharacterizationOptions] = None,
152
+ n_repetitions: int = 10**4,
153
+ n_combinations: int = 10,
154
+ n_circuits: int = 20,
155
+ cycle_depths: Sequence[int] = tuple(np.arange(3, 100, 20)),
156
+ random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
157
+ atol: float = 1e-3,
158
+ num_workers_or_pool: Union[int, 'multiprocessing.pool.Pool'] = -1,
159
+ pairs: Optional[Sequence[Tuple['cirq.GridQubit', 'cirq.GridQubit']]] = None,
160
+ tags: Sequence[Any] = (),
161
+ ) -> Dict[Tuple['cirq.Qid', 'cirq.Qid'], 'cirq.PhasedFSimGate']:
162
+ """Perform z-phase calibration for excitation-preserving gates.
163
+
164
+ For a given excitation-preserving two-qubit gate we assume an error model that can be described
165
+ using Z-rotations:
166
+ 0: ───Rz(a)───two_qubit_gate───Rz(c)───
167
+
168
+ 1: ───Rz(b)───two_qubit_gate───Rz(d)───
169
+ for some angles a, b, c, and d.
170
+
171
+ Since the two-qubit gate is a excitation-preserving gate, it can be represented by an FSimGate
172
+ and the effect of rotations turns it into a PhasedFSimGate. Using XEB-data we find the
173
+ PhasedFSimGate parameters that minimize the infidelity of the gate.
174
+
175
+ References:
176
+ - https://arxiv.org/abs/2001.08343
177
+ - https://arxiv.org/abs/2010.07965
178
+ - https://arxiv.org/abs/1910.11333
179
+
180
+ Args:
181
+ sampler: The quantum engine or simulator to run the circuits.
182
+ qubits: Qubits to use. If none, use all qubits on the sampler's device.
183
+ two_qubit_gate: The entangling gate to use.
184
+ options: The XEB-fitting options. If None, calibrate only the three phase angles
185
+ (chi, gamma, zeta) using the representation of a two-qubit gate as an FSimGate
186
+ for the initial guess.
187
+ n_repetitions: The number of repetitions to use.
188
+ n_combinations: The number of combinations to generate.
189
+ n_circuits: The number of circuits to generate.
190
+ cycle_depths: The cycle depths to use.
191
+ random_state: The random state to use.
192
+ atol: Absolute tolerance to be used by the minimizer.
193
+ num_workers_or_pool: An optional multi-processing pool or number of workers.
194
+ A zero value means no multiprocessing.
195
+ A positive integer value will create a pool with the given number of workers.
196
+ A negative value will create pool with maximum number of workers.
197
+ pairs: Pairs to use. If not specified, use all pairs between adjacent qubits.
198
+ tags: Tags to add to two qubit operations.
199
+
200
+ Returns:
201
+ - A dictionary mapping qubit pairs to the calibrated PhasedFSimGates.
202
+ """
203
+
204
+ if options is None:
205
+ options = xeb_fitting.XEBPhasedFSimCharacterizationOptions(
206
+ characterize_chi=True,
207
+ characterize_gamma=True,
208
+ characterize_zeta=True,
209
+ characterize_theta=False,
210
+ characterize_phi=False,
211
+ ).with_defaults_from_gate(two_qubit_gate)
212
+
213
+ result, _ = z_phase_calibration_workflow(
214
+ sampler=sampler,
215
+ qubits=qubits,
216
+ two_qubit_gate=two_qubit_gate,
217
+ options=options,
218
+ n_repetitions=n_repetitions,
219
+ n_combinations=n_combinations,
220
+ n_circuits=n_circuits,
221
+ cycle_depths=cycle_depths,
222
+ random_state=random_state,
223
+ atol=atol,
224
+ num_workers_or_pool=num_workers_or_pool,
225
+ tags=tags,
226
+ pairs=pairs,
227
+ )
228
+
229
+ gates = {}
230
+ for pair, params in result.final_params.items():
231
+ params['theta'] = params.get('theta', options.theta_default or 0)
232
+ params['phi'] = params.get('phi', options.phi_default or 0)
233
+ params['zeta'] = params.get('zeta', options.zeta_default or 0)
234
+ params['chi'] = params.get('chi', options.chi_default or 0)
235
+ params['gamma'] = params.get('gamma', options.gamma_default or 0)
236
+ gates[pair] = ops.PhasedFSimGate(**params)
237
+ return gates
238
+
239
+
240
+ def plot_z_phase_calibration_result(
241
+ before_after_df: 'pd.DataFrame',
242
+ axes: Optional[np.ndarray[Sequence[Sequence['plt.Axes']], np.dtype[np.object_]]] = None,
243
+ pairs: Optional[Sequence[Tuple['cirq.Qid', 'cirq.Qid']]] = None,
244
+ *,
245
+ with_error_bars: bool = False,
246
+ ) -> np.ndarray[Sequence[Sequence['plt.Axes']], np.dtype[np.object_]]:
247
+ """A helper method to plot the result of running z-phase calibration.
248
+
249
+ Note that the plotted fidelity is a statistical estimate of the true fidelity and as a result
250
+ may be outside the [0, 1] range.
251
+
252
+ Args:
253
+ before_after_df: The second return object of running `z_phase_calibration_workflow`.
254
+ axes: And ndarray of the axes to plot on.
255
+ The number of axes is expected to be >= number of qubit pairs.
256
+ pairs: If provided, only the given pairs are plotted.
257
+ with_error_bars: Whether to add error bars or not.
258
+ The width of the bar is an upper bound on standard variation of the estimated fidelity.
259
+ """
260
+ if pairs is None:
261
+ pairs = before_after_df.index
262
+ if axes is None:
263
+ # Create a 16x9 rectangle.
264
+ ncols = int(np.ceil(np.sqrt(9 / 16 * len(pairs))))
265
+ nrows = (len(pairs) + ncols - 1) // ncols
266
+ _, axes = plt.subplots(nrows=nrows, ncols=ncols)
267
+ axes = axes if isinstance(axes, np.ndarray) else np.array(axes)
268
+ for pair, ax in zip(pairs, axes.flatten()):
269
+ row = before_after_df.loc[[pair]].iloc[0]
270
+ ax.errorbar(
271
+ row.cycle_depths_0,
272
+ row.fidelities_0,
273
+ yerr=row.layer_fid_std_0 * with_error_bars,
274
+ label='original',
275
+ )
276
+ ax.errorbar(
277
+ row.cycle_depths_0,
278
+ row.fidelities_c,
279
+ yerr=row.layer_fid_std_c * with_error_bars,
280
+ label='calibrated',
281
+ )
282
+ ax.axhline(1, linestyle='--')
283
+ ax.set_xlabel('cycle depth')
284
+ ax.set_ylabel('fidelity estimate')
285
+ ax.set_title('-'.join(str(q) for q in pair))
286
+ ax.legend()
287
+ return axes
288
+
289
+
290
+ def _z_angles(old: ops.PhasedFSimGate, new: ops.PhasedFSimGate) -> Tuple[float, float, float]:
291
+ """Computes a set of possible 3 z-phases that result in the change in gamma, zeta, and chi."""
292
+ # This procedure is the inverse of PhasedFSimGate.from_fsim_rz
293
+ delta_gamma = new.gamma - old.gamma
294
+ delta_zeta = new.zeta - old.zeta
295
+ delta_chi = new.chi - old.chi
296
+ return (-delta_gamma + delta_chi, -delta_gamma - delta_zeta, delta_zeta - delta_chi)
297
+
298
+
299
+ @transformer_api.transformer
300
+ class CalibrationTransformer:
301
+
302
+ def __init__(
303
+ self,
304
+ target: 'cirq.Gate',
305
+ calibration_map: Dict[Tuple['cirq.Qid', 'cirq.Qid'], 'cirq.PhasedFSimGate'],
306
+ ):
307
+ """Create a CalibrationTransformer.
308
+
309
+ The transformer adds 3 ZPowGates around each calibrated gate to cancel the
310
+ effect of z-phases.
311
+
312
+ Args:
313
+ target: The target gate. Any gate matching this
314
+ will be replaced based on the content of `calibration_map`.
315
+ calibration_map:
316
+ A map mapping qubit pairs to calibrated gates. This is the output of
317
+ calling `calibrate_z_phases`.
318
+ """
319
+ self.target = target
320
+ if isinstance(target, ops.PhasedFSimGate):
321
+ self.target_as_fsim = target
322
+ elif (gate := ops.PhasedFSimGate.from_matrix(protocols.unitary(target))) is not None:
323
+ self.target_as_fsim = gate
324
+ else:
325
+ raise ValueError(f"{target} is not equivalent to a PhasedFSimGate")
326
+ self.calibration_map = calibration_map
327
+
328
+ def __call__(
329
+ self,
330
+ circuit: 'cirq.AbstractCircuit',
331
+ *,
332
+ context: Optional[transformer_api.TransformerContext] = None,
333
+ ) -> 'cirq.Circuit':
334
+ """Adds 3 ZPowGates around each calibrated gate to cancel the effect of Z phases.
335
+
336
+ Args:
337
+ circuit: Circuit to transform.
338
+ context: Optional transformer context (not used).
339
+
340
+ Returns:
341
+ New circuit with the extra ZPowGates.
342
+ """
343
+ new_moments: List[Union[List[cirq.Operation], 'cirq.Moment']] = []
344
+ for moment in circuit:
345
+ before = []
346
+ after = []
347
+ for op in moment:
348
+ if op.gate != self.target:
349
+ # not a target.
350
+ continue
351
+ assert len(op.qubits) == 2
352
+ gate = self.calibration_map.get(op.qubits, None) or self.calibration_map.get(
353
+ op.qubits[::-1], None
354
+ )
355
+ if gate is None:
356
+ # no calibration available.
357
+ continue
358
+ angles = np.array(_z_angles(self.target_as_fsim, gate)) / np.pi
359
+ angles = -angles # Take the negative to cancel the effect.
360
+ before.append(ops.Z(op.qubits[0]) ** angles[0])
361
+ before.append(ops.Z(op.qubits[1]) ** angles[1])
362
+ after.append(ops.Z(op.qubits[0]) ** angles[2])
363
+ if before:
364
+ new_moments.append(before)
365
+ new_moments.append(moment)
366
+ if after:
367
+ new_moments.append(after)
368
+ return circuits.Circuit.from_moments(*new_moments)
@@ -0,0 +1,241 @@
1
+ # Copyright 2024 The Cirq Developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import numpy as np
16
+ import pandas as pd
17
+ import pytest
18
+
19
+ import cirq
20
+ from cirq.experiments.xeb_fitting import XEBPhasedFSimCharacterizationOptions
21
+ from cirq.experiments.z_phase_calibration import (
22
+ calibrate_z_phases,
23
+ CalibrationTransformer,
24
+ plot_z_phase_calibration_result,
25
+ z_phase_calibration_workflow,
26
+ )
27
+
28
+ _ANGLES = ['theta', 'phi', 'chi', 'zeta', 'gamma']
29
+ # fix random generator seed to ensure reproducibility and faster convergence
30
+ _SEED = 276154030
31
+
32
+
33
+ def _create_tests(n, with_options: bool = False):
34
+ rng = np.random.default_rng(_SEED)
35
+ angles = (rng.random((n, 5)) * 2 - 1) * np.pi
36
+ # Add errors to the last 3 angles (chi, zeta, gamma).
37
+ # The errors are in the union (-2, -1) U (1, 2).
38
+ # This is because we run the tests with few repetitions so a small error might not get fixed.
39
+ error = np.concatenate(
40
+ [np.zeros((n, 2)), (rng.random((n, 3)) + 1) * rng.choice([-1, 1], (n, 3))], axis=-1
41
+ )
42
+ if with_options:
43
+ options = []
44
+ for _ in range(n):
45
+ v = [False, False, False]
46
+ # Calibrate only one to keep the run time down.
47
+ v[rng.integers(0, 3)] = True
48
+ options.append(
49
+ {
50
+ 'characterize_chi': v[0],
51
+ 'characterize_gamma': v[1],
52
+ 'characterize_zeta': v[2],
53
+ 'characterize_phi': False,
54
+ 'characterize_theta': False,
55
+ }
56
+ )
57
+
58
+ return zip(angles, error, options)
59
+ return zip(angles, error)
60
+
61
+
62
+ def _trace_distance(A, B):
63
+ return 0.5 * np.abs(np.linalg.eigvals(A - B)).sum()
64
+
65
+
66
+ class _TestSimulator(cirq.Simulator):
67
+ """A simulator that replaces a specific gate by another."""
68
+
69
+ def __init__(self, gate: cirq.Gate, replacement: cirq.Gate, **kwargs):
70
+ super().__init__(**kwargs)
71
+ self.gate = gate
72
+ self.replacement = replacement
73
+
74
+ def _core_iterator(
75
+ self,
76
+ circuit: 'cirq.AbstractCircuit',
77
+ sim_state,
78
+ all_measurements_are_terminal: bool = False,
79
+ ):
80
+ new_circuit = cirq.Circuit(
81
+ [
82
+ [op if op.gate != self.gate else self.replacement(*op.qubits) for op in m]
83
+ for m in circuit
84
+ ]
85
+ )
86
+ yield from super()._core_iterator(new_circuit, sim_state, all_measurements_are_terminal)
87
+
88
+
89
+ @pytest.mark.parametrize(
90
+ ['angles', 'error', 'characterization_flags'], _create_tests(n=10, with_options=True)
91
+ )
92
+ def test_calibrate_z_phases(angles, error, characterization_flags):
93
+
94
+ original_gate = cirq.PhasedFSimGate(**{k: v for k, v in zip(_ANGLES, angles)})
95
+ actual_gate = cirq.PhasedFSimGate(**{k: v + e for k, v, e in zip(_ANGLES, angles, error)})
96
+
97
+ options = XEBPhasedFSimCharacterizationOptions(
98
+ **{f'{n}_default': t for n, t in zip(_ANGLES, angles)}, **characterization_flags
99
+ )
100
+
101
+ sampler = _TestSimulator(original_gate, actual_gate, seed=_SEED)
102
+ qubits = cirq.q(0, 0), cirq.q(0, 1)
103
+ calibrated_gate = calibrate_z_phases(
104
+ sampler,
105
+ qubits,
106
+ original_gate,
107
+ options,
108
+ n_repetitions=10,
109
+ n_combinations=10,
110
+ n_circuits=10,
111
+ cycle_depths=range(3, 10),
112
+ random_state=_SEED,
113
+ )[qubits]
114
+
115
+ initial_unitary = cirq.unitary(original_gate)
116
+ final_unitary = cirq.unitary(calibrated_gate)
117
+ target_unitary = cirq.unitary(actual_gate)
118
+ maximally_mixed_state = np.eye(4) / 2
119
+ dm_initial = initial_unitary @ maximally_mixed_state @ initial_unitary.T.conj()
120
+ dm_final = final_unitary @ maximally_mixed_state @ final_unitary.T.conj()
121
+ dm_target = target_unitary @ maximally_mixed_state @ target_unitary.T.conj()
122
+
123
+ original_dist = _trace_distance(dm_initial, dm_target)
124
+ new_dist = _trace_distance(dm_final, dm_target)
125
+
126
+ # Either we reduced the error or the error is small enough.
127
+ assert new_dist < original_dist or new_dist < 1e-6
128
+
129
+
130
+ @pytest.mark.parametrize(['angles', 'error'], _create_tests(n=3))
131
+ def test_calibrate_z_phases_no_options(angles, error):
132
+
133
+ original_gate = cirq.PhasedFSimGate(**{k: v for k, v in zip(_ANGLES, angles)})
134
+ actual_gate = cirq.PhasedFSimGate(**{k: v + e for k, v, e in zip(_ANGLES, angles, error)})
135
+
136
+ sampler = _TestSimulator(original_gate, actual_gate, seed=_SEED)
137
+ qubits = cirq.q(0, 0), cirq.q(0, 1)
138
+ calibrated_gate = calibrate_z_phases(
139
+ sampler,
140
+ qubits,
141
+ original_gate,
142
+ options=None,
143
+ n_repetitions=10,
144
+ n_combinations=10,
145
+ n_circuits=10,
146
+ cycle_depths=range(3, 10),
147
+ random_state=_SEED,
148
+ )[qubits]
149
+
150
+ initial_unitary = cirq.unitary(original_gate)
151
+ final_unitary = cirq.unitary(calibrated_gate)
152
+ target_unitary = cirq.unitary(actual_gate)
153
+ maximally_mixed_state = np.eye(4) / 2
154
+ dm_initial = initial_unitary @ maximally_mixed_state @ initial_unitary.T.conj()
155
+ dm_final = final_unitary @ maximally_mixed_state @ final_unitary.T.conj()
156
+ dm_target = target_unitary @ maximally_mixed_state @ target_unitary.T.conj()
157
+
158
+ original_dist = _trace_distance(dm_initial, dm_target)
159
+ new_dist = _trace_distance(dm_final, dm_target)
160
+
161
+ # Either we reduced the error or the error is small enough.
162
+ assert new_dist < original_dist or new_dist < 1e-6
163
+
164
+
165
+ @pytest.mark.parametrize(['angles', 'error'], _create_tests(n=3))
166
+ def test_calibrate_z_phases_workflow_no_options(angles, error):
167
+
168
+ original_gate = cirq.PhasedFSimGate(**{k: v for k, v in zip(_ANGLES, angles)})
169
+ actual_gate = cirq.PhasedFSimGate(**{k: v + e for k, v, e in zip(_ANGLES, angles, error)})
170
+
171
+ sampler = _TestSimulator(original_gate, actual_gate, seed=_SEED)
172
+ qubits = cirq.q(0, 0), cirq.q(0, 1)
173
+ result, _ = z_phase_calibration_workflow(
174
+ sampler,
175
+ qubits,
176
+ original_gate,
177
+ options=None,
178
+ n_repetitions=1,
179
+ n_combinations=1,
180
+ n_circuits=1,
181
+ cycle_depths=(1, 2),
182
+ random_state=_SEED,
183
+ )
184
+
185
+ for params in result.final_params.values():
186
+ assert 'zeta' in params
187
+ assert 'chi' in params
188
+ assert 'gamma' in params
189
+ assert 'phi' not in params
190
+ assert 'theta' not in params
191
+
192
+
193
+ def test_plot_z_phase_calibration_result():
194
+ df = pd.DataFrame()
195
+ qs = cirq.q(0, 0), cirq.q(0, 1), cirq.q(0, 2)
196
+ df.index = [qs[:2], qs[-2:]]
197
+ df['cycle_depths_0'] = [[1, 2, 3]] * 2
198
+ df['fidelities_0'] = [[0.9, 0.8, 0.7], [0.6, 0.4, 0.1]]
199
+ df['layer_fid_std_0'] = [0.1, 0.2]
200
+ df['fidelities_c'] = [[0.9, 0.92, 0.93], [0.7, 0.77, 0.8]]
201
+ df['layer_fid_std_c'] = [0.2, 0.3]
202
+
203
+ axes = plot_z_phase_calibration_result(before_after_df=df)
204
+
205
+ np.testing.assert_allclose(axes[0].lines[0].get_xdata().astype(float), [1, 2, 3])
206
+ np.testing.assert_allclose(axes[0].lines[0].get_ydata().astype(float), [0.9, 0.8, 0.7])
207
+ np.testing.assert_allclose(axes[0].lines[1].get_ydata().astype(float), [0.9, 0.92, 0.93])
208
+
209
+ np.testing.assert_allclose(axes[1].lines[0].get_xdata().astype(float), [1, 2, 3])
210
+ np.testing.assert_allclose(axes[1].lines[0].get_ydata().astype(float), [0.6, 0.4, 0.1])
211
+ np.testing.assert_allclose(axes[1].lines[1].get_ydata().astype(float), [0.7, 0.77, 0.8])
212
+
213
+
214
+ @pytest.mark.parametrize('angles', 2 * np.pi * np.random.random((10, 10)))
215
+ def test_transform_circuit(angles):
216
+ theta, phi = angles[:2]
217
+ old_zs = angles[2:6]
218
+ new_zs = angles[6:]
219
+ gate = cirq.PhasedFSimGate.from_fsim_rz(theta, phi, old_zs[:2], old_zs[2:])
220
+ fsim = cirq.PhasedFSimGate.from_fsim_rz(theta, phi, new_zs[:2], new_zs[2:])
221
+ c = cirq.Circuit(gate(cirq.q(0), cirq.q(1)))
222
+ replacement_map = {(cirq.q(1), cirq.q(0)): fsim}
223
+
224
+ new_circuit = CalibrationTransformer(gate, replacement_map)(c)
225
+
226
+ # we replace the old gate with the `fsim` gate the result should be that the overall
227
+ # unitary equals the unitary of the original (ideal) gate.
228
+ circuit_with_replacement_gate = cirq.Circuit(
229
+ op if op.gate != gate else fsim(*op.qubits) for op in new_circuit.all_operations()
230
+ )
231
+ np.testing.assert_allclose(cirq.unitary(circuit_with_replacement_gate), cirq.unitary(c))
232
+
233
+
234
+ def test_transform_circuit_invalid_gate_raises():
235
+ with pytest.raises(ValueError, match="is not equivalent to a PhasedFSimGate"):
236
+ _ = CalibrationTransformer(cirq.XX, {})
237
+
238
+
239
+ def test_transform_circuit_uncalibrated_gates_pass():
240
+ c = cirq.Circuit(cirq.CZ(cirq.q(0), cirq.q(1)), cirq.measure(cirq.q(0)))
241
+ assert c == CalibrationTransformer(cirq.CZ, {})(c)
cirq/interop/__init__.py CHANGED
@@ -13,4 +13,7 @@
13
13
  # limitations under the License.
14
14
  """Methods for interoperating with other quantum software."""
15
15
 
16
- from cirq.interop.quirk import quirk_json_to_circuit, quirk_url_to_circuit
16
+ from cirq.interop.quirk import (
17
+ quirk_json_to_circuit as quirk_json_to_circuit,
18
+ quirk_url_to_circuit as quirk_url_to_circuit,
19
+ )
@@ -20,9 +20,12 @@ References:
20
20
 
21
21
  # Imports from cells are only to ensure operation reprs work correctly.
22
22
  from cirq.interop.quirk.cells import (
23
- QuirkArithmeticGate,
24
- QuirkInputRotationOperation,
25
- QuirkQubitPermutationGate,
23
+ QuirkArithmeticGate as QuirkArithmeticGate,
24
+ QuirkInputRotationOperation as QuirkInputRotationOperation,
25
+ QuirkQubitPermutationGate as QuirkQubitPermutationGate,
26
26
  )
27
27
 
28
- from cirq.interop.quirk.url_to_circuit import quirk_json_to_circuit, quirk_url_to_circuit
28
+ from cirq.interop.quirk.url_to_circuit import (
29
+ quirk_json_to_circuit as quirk_json_to_circuit,
30
+ quirk_url_to_circuit as quirk_url_to_circuit,
31
+ )
@@ -13,17 +13,28 @@
13
13
  # limitations under the License.
14
14
  """This module defines building blocks for parsing Quirk circuits."""
15
15
 
16
- from cirq.interop.quirk.cells.all_cells import generate_all_quirk_cell_makers
16
+ from cirq.interop.quirk.cells.all_cells import (
17
+ generate_all_quirk_cell_makers as generate_all_quirk_cell_makers,
18
+ )
17
19
 
18
- from cirq.interop.quirk.cells.cell import Cell, CellMaker, CellMakerArgs, ExplicitOperationsCell
20
+ from cirq.interop.quirk.cells.cell import (
21
+ Cell as Cell,
22
+ CellMaker as CellMaker,
23
+ CellMakerArgs as CellMakerArgs,
24
+ ExplicitOperationsCell as ExplicitOperationsCell,
25
+ )
19
26
 
20
- from cirq.interop.quirk.cells.composite_cell import CompositeCell
27
+ from cirq.interop.quirk.cells.composite_cell import CompositeCell as CompositeCell
21
28
 
22
- from cirq.interop.quirk.cells.qubit_permutation_cells import QuirkQubitPermutationGate
29
+ from cirq.interop.quirk.cells.qubit_permutation_cells import (
30
+ QuirkQubitPermutationGate as QuirkQubitPermutationGate,
31
+ )
23
32
 
24
- from cirq.interop.quirk.cells.arithmetic_cells import QuirkArithmeticGate
33
+ from cirq.interop.quirk.cells.arithmetic_cells import QuirkArithmeticGate as QuirkArithmeticGate
25
34
 
26
- from cirq.interop.quirk.cells.input_rotation_cells import QuirkInputRotationOperation
35
+ from cirq.interop.quirk.cells.input_rotation_cells import (
36
+ QuirkInputRotationOperation as QuirkInputRotationOperation,
37
+ )
27
38
 
28
39
  import cirq.interop.quirk.cells.swap_cell
29
40
  import cirq.interop.quirk.cells.control_cells