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
cirq/ops/parity_gates.py CHANGED
@@ -14,24 +14,23 @@
14
14
 
15
15
  """Quantum gates that phase with respect to product-of-pauli observables."""
16
16
 
17
- from typing import Any, Dict, List, Optional, Tuple, Union, TYPE_CHECKING, Sequence
18
- from typing_extensions import Self
17
+ from typing import Any, Dict, Iterator, List, Optional, Sequence, Tuple, TYPE_CHECKING, Union
19
18
 
20
19
  import numpy as np
20
+ from typing_extensions import Self
21
21
 
22
22
  from cirq import protocols, value
23
23
  from cirq._compat import proper_repr
24
24
  from cirq._doc import document
25
25
  from cirq.ops import (
26
- gate_features,
27
- eigen_gate,
26
+ clifford_gate,
28
27
  common_gates,
28
+ eigen_gate,
29
+ gate_features,
29
30
  pauli_gates,
30
- clifford_gate,
31
31
  pauli_interaction_gate,
32
32
  )
33
33
 
34
-
35
34
  if TYPE_CHECKING:
36
35
  import cirq
37
36
 
@@ -118,7 +117,7 @@ class XXPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
118
117
  def _has_stabilizer_effect_(self) -> bool:
119
118
  return self.exponent % 2 in (0, 0.5, 1, 1.5)
120
119
 
121
- def _decompose_(self, qubits: Tuple['cirq.Qid', ...]) -> 'cirq.OP_TREE':
120
+ def _decompose_(self, qubits: Tuple['cirq.Qid', ...]) -> Iterator['cirq.OP_TREE']:
122
121
  yield common_gates.YPowGate(exponent=-0.5).on_each(*qubits)
123
122
  yield ZZPowGate(exponent=self.exponent, global_shift=self.global_shift)(*qubits)
124
123
  yield common_gates.YPowGate(exponent=0.5).on_each(*qubits)
@@ -227,7 +226,7 @@ class YYPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
227
226
  def _has_stabilizer_effect_(self) -> bool:
228
227
  return self.exponent % 2 in (0, 0.5, 1, 1.5)
229
228
 
230
- def _decompose_(self, qubits: Tuple['cirq.Qid', ...]) -> 'cirq.OP_TREE':
229
+ def _decompose_(self, qubits: Tuple['cirq.Qid', ...]) -> Iterator['cirq.OP_TREE']:
231
230
  yield common_gates.XPowGate(exponent=0.5).on_each(*qubits)
232
231
  yield ZZPowGate(exponent=self.exponent, global_shift=self.global_shift)(*qubits)
233
232
  yield common_gates.XPowGate(exponent=-0.5).on_each(*qubits)
@@ -39,6 +39,7 @@ def test_xx_eq():
39
39
  cirq.XXPowGate(),
40
40
  cirq.XXPowGate(exponent=1, global_shift=0),
41
41
  cirq.XXPowGate(exponent=3, global_shift=0),
42
+ cirq.XXPowGate(global_shift=100000),
42
43
  )
43
44
  eq.add_equality_group(cirq.XX**0.5, cirq.XX**2.5, cirq.XX**4.5)
44
45
  eq.add_equality_group(cirq.XX**0.25, cirq.XX**2.25, cirq.XX**-1.75)
cirq/ops/pauli_gates.py CHANGED
@@ -12,22 +12,21 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  import abc
15
- from typing import Any, cast, Tuple, TYPE_CHECKING, Union, Dict
15
+ from types import NotImplementedType
16
+ from typing import Any, cast, Dict, Tuple, TYPE_CHECKING, Union
16
17
 
17
18
  from cirq._doc import document
18
19
  from cirq._import import LazyLoader
19
- from cirq.ops import common_gates, raw_types, identity
20
- from cirq.type_workarounds import NotImplementedType
21
-
20
+ from cirq.ops import common_gates, identity, raw_types
22
21
 
23
22
  if TYPE_CHECKING:
24
23
  import cirq
25
24
  from cirq.ops.pauli_string import SingleQubitPauliStringGateOperation
26
- from cirq.value.product_state import (
25
+ from cirq.value.product_state import ( # pragma: no cover
27
26
  _XEigenState,
28
27
  _YEigenState,
29
28
  _ZEigenState,
30
- ) # pragma: no cover
29
+ )
31
30
 
32
31
 
33
32
  pauli_string = LazyLoader("pauli_string", globals(), "cirq.ops.pauli_string")
@@ -104,11 +103,6 @@ class Pauli(raw_types.Gate, metaclass=abc.ABCMeta):
104
103
 
105
104
  return pauli_string.SingleQubitPauliStringGateOperation(self, qubits[0])
106
105
 
107
- @property
108
- def _canonical_exponent(self):
109
- """Overrides EigenGate._canonical_exponent in subclasses."""
110
- return 1
111
-
112
106
 
113
107
  class _PauliX(Pauli, common_gates.XPowGate):
114
108
  def __init__(self):
@@ -16,6 +16,7 @@ import itertools
16
16
 
17
17
  import numpy as np
18
18
  import pytest
19
+
19
20
  import cirq
20
21
 
21
22
 
@@ -12,13 +12,13 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from typing import Any, Dict, List, Sequence, TYPE_CHECKING, Tuple
15
+ from typing import Any, Dict, Iterator, List, Sequence, Tuple, TYPE_CHECKING
16
16
 
17
17
  import numpy as np
18
18
 
19
- from cirq import value, protocols
19
+ from cirq import protocols, value
20
20
  from cirq._compat import proper_repr
21
- from cirq.ops import gate_features, common_gates, eigen_gate, pauli_gates
21
+ from cirq.ops import common_gates, eigen_gate, gate_features, pauli_gates
22
22
  from cirq.ops.clifford_gate import SingleQubitCliffordGate
23
23
 
24
24
  if TYPE_CHECKING:
@@ -85,7 +85,13 @@ class PauliInteractionGate(gate_features.InterchangeableQubitsGate, eigen_gate.E
85
85
  return 2
86
86
 
87
87
  def _value_equality_values_(self):
88
- return (self.pauli0, self.invert0, self.pauli1, self.invert1, self._canonical_exponent)
88
+ return (
89
+ self.pauli0,
90
+ self.invert0,
91
+ self.pauli1,
92
+ self.invert1,
93
+ value.PeriodicValue(self.exponent, 2),
94
+ )
89
95
 
90
96
  def qubit_index_to_equivalence_group_key(self, index: int) -> int:
91
97
  if self.pauli0 == self.pauli1 and self.invert0 == self.invert1:
@@ -108,7 +114,7 @@ class PauliInteractionGate(gate_features.InterchangeableQubitsGate, eigen_gate.E
108
114
  comp0 = np.eye(4) - comp1
109
115
  return [(0, comp0), (1, comp1)]
110
116
 
111
- def _decompose_(self, qubits: Sequence['cirq.Qid']) -> 'cirq.OP_TREE':
117
+ def _decompose_(self, qubits: Sequence['cirq.Qid']) -> Iterator['cirq.OP_TREE']:
112
118
  q0, q1 = qubits
113
119
  right_gate0 = SingleQubitCliffordGate.from_single_map(z_to=(self.pauli0, self.invert0))
114
120
  right_gate1 = SingleQubitCliffordGate.from_single_map(z_to=(self.pauli1, self.invert1))
@@ -13,14 +13,13 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import itertools
16
- import pytest
16
+
17
17
  import numpy as np
18
+ import pytest
18
19
  import sympy
19
20
 
20
-
21
21
  import cirq
22
22
 
23
-
24
23
  _bools = (False, True)
25
24
  _paulis = (cirq.X, cirq.Y, cirq.Z)
26
25
 
@@ -14,25 +14,26 @@
14
14
 
15
15
  from typing import (
16
16
  Any,
17
+ cast,
17
18
  Dict,
18
19
  FrozenSet,
19
20
  Iterable,
21
+ Iterator,
20
22
  Mapping,
21
- Tuple,
22
23
  Sequence,
24
+ Tuple,
23
25
  TYPE_CHECKING,
24
26
  Union,
25
- cast,
26
27
  )
27
28
 
28
29
  from cirq import protocols, value
29
30
  from cirq.ops import (
30
- raw_types,
31
+ dense_pauli_string as dps,
31
32
  measurement_gate,
32
33
  op_tree,
33
- dense_pauli_string as dps,
34
34
  pauli_gates,
35
35
  pauli_string_phasor,
36
+ raw_types,
36
37
  )
37
38
 
38
39
  if TYPE_CHECKING:
@@ -144,7 +145,7 @@ class PauliMeasurementGate(raw_types.Gate):
144
145
 
145
146
  def _decompose_(
146
147
  self, qubits: Tuple['cirq.Qid', ...]
147
- ) -> 'protocols.decompose_protocol.DecomposeResult':
148
+ ) -> Iterator['protocols.decompose_protocol.DecomposeResult']:
148
149
  any_qubit = qubits[0]
149
150
  to_z_ops = op_tree.freeze_op_tree(self._observable.on(*qubits).to_z_basis_ops())
150
151
  xor_decomp = tuple(pauli_string_phasor.xor_nonlocal_decompose(qubits, any_qubit))
@@ -63,6 +63,7 @@ def test_measurement_eq():
63
63
  [
64
64
  (None, None, 'b'),
65
65
  (cirq.with_key_path, ('p', 'q'), 'p:q:a'),
66
+ (cirq.with_key_path_prefix, ('p', 'q'), 'p:q:a'),
66
67
  (cirq.with_measurement_key_mapping, {'a': 'b'}, 'b'),
67
68
  ],
68
69
  )
cirq/ops/pauli_string.py CHANGED
@@ -14,10 +14,14 @@
14
14
  import cmath
15
15
  import math
16
16
  import numbers
17
+ from types import NotImplementedType
17
18
  from typing import (
19
+ AbstractSet,
18
20
  Any,
21
+ Callable,
19
22
  cast,
20
23
  Dict,
24
+ Generic,
21
25
  ItemsView,
22
26
  Iterable,
23
27
  Iterator,
@@ -27,27 +31,23 @@ from typing import (
27
31
  Optional,
28
32
  overload,
29
33
  Sequence,
30
- SupportsComplex,
31
34
  Tuple,
32
35
  TYPE_CHECKING,
33
36
  TypeVar,
34
37
  Union,
35
38
  ValuesView,
36
- AbstractSet,
37
- Callable,
38
- Generic,
39
39
  )
40
40
 
41
41
  import numpy as np
42
42
  import sympy
43
43
 
44
- import cirq
45
- from cirq import value, protocols, linalg, qis, _compat
44
+ from cirq import _compat, linalg, protocols, qis, value
46
45
  from cirq._doc import document
47
46
  from cirq._import import LazyLoader
48
47
  from cirq.ops import (
49
48
  clifford_gate,
50
49
  common_gates,
50
+ dense_pauli_string,
51
51
  gate_operation,
52
52
  global_phase_op,
53
53
  identity,
@@ -56,7 +56,6 @@ from cirq.ops import (
56
56
  pauli_interaction_gate,
57
57
  raw_types,
58
58
  )
59
- from cirq.type_workarounds import NotImplementedType
60
59
 
61
60
  if TYPE_CHECKING:
62
61
  import cirq
@@ -271,9 +270,7 @@ class PauliString(raw_types.Operation, Generic[TKey]):
271
270
  pass
272
271
 
273
272
  @overload
274
- def __mul__(
275
- self, other: Union[complex, int, float, numbers.Number]
276
- ) -> 'cirq.PauliString[TKey]':
273
+ def __mul__(self, other: complex) -> 'cirq.PauliString[TKey]':
277
274
  pass
278
275
 
279
276
  def __mul__(self, other):
@@ -308,23 +305,21 @@ class PauliString(raw_types.Operation, Generic[TKey]):
308
305
  )
309
306
 
310
307
  def __rmul__(self, other) -> 'PauliString':
311
- if isinstance(other, numbers.Number):
308
+ if isinstance(other, numbers.Complex):
312
309
  return PauliString(
313
- qubit_pauli_map=self._qubit_pauli_map,
314
- coefficient=self._coefficient * complex(cast(SupportsComplex, other)),
310
+ qubit_pauli_map=self._qubit_pauli_map, coefficient=self._coefficient * other
315
311
  )
316
312
 
317
313
  if isinstance(other, raw_types.Operation) and isinstance(other.gate, identity.IdentityGate):
318
- return self
314
+ return self # pragma: no cover
319
315
 
320
316
  # Note: PauliString case handled by __mul__.
321
317
  return NotImplemented
322
318
 
323
319
  def __truediv__(self, other):
324
- if isinstance(other, numbers.Number):
320
+ if isinstance(other, numbers.Complex):
325
321
  return PauliString(
326
- qubit_pauli_map=self._qubit_pauli_map,
327
- coefficient=self._coefficient / complex(cast(SupportsComplex, other)),
322
+ qubit_pauli_map=self._qubit_pauli_map, coefficient=self._coefficient / other
328
323
  )
329
324
  return NotImplemented
330
325
 
@@ -467,7 +462,7 @@ class PauliString(raw_types.Operation, Generic[TKey]):
467
462
  fused = prefix + '*'.join(factors)
468
463
  if len(factors) > 1:
469
464
  return f'({fused})'
470
- return fused
465
+ return fused # pragma: no cover
471
466
 
472
467
  def __str__(self) -> str:
473
468
  ordered_qubits = sorted(self.qubits)
@@ -500,7 +495,7 @@ class PauliString(raw_types.Operation, Generic[TKey]):
500
495
  """
501
496
  qubits = self.qubits if qubits is None else qubits
502
497
  factors = [self.get(q, default=identity.I) for q in qubits]
503
- if cirq.is_parameterized(self):
498
+ if protocols.is_parameterized(self):
504
499
  raise NotImplementedError('Cannot express as matrix when parameterized')
505
500
  assert isinstance(self.coefficient, complex)
506
501
  return linalg.kron(self.coefficient, *[protocols.unitary(f) for f in factors])
@@ -518,7 +513,7 @@ class PauliString(raw_types.Operation, Generic[TKey]):
518
513
  def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'):
519
514
  if not self._has_unitary_():
520
515
  return None
521
- assert isinstance(self.coefficient, complex)
516
+ assert isinstance(self.coefficient, numbers.Complex)
522
517
  if self.coefficient != 1:
523
518
  args.target_tensor *= self.coefficient
524
519
  return protocols.apply_unitaries([self[q].on(q) for q in self.qubits], self.qubits, args)
@@ -792,9 +787,11 @@ class PauliString(raw_types.Operation, Generic[TKey]):
792
787
  return self
793
788
 
794
789
  def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
795
- """Override behavior of numpy's exp method."""
790
+ """Override numpy behavior."""
796
791
  if ufunc == np.exp and len(inputs) == 1 and inputs[0] is self:
797
792
  return math.e**self
793
+ if ufunc == np.multiply and len(inputs) == 2 and inputs[1] is self:
794
+ return self * inputs[0]
798
795
  return NotImplemented
799
796
 
800
797
  def __pow__(self, power):
@@ -910,14 +907,13 @@ class PauliString(raw_types.Operation, Generic[TKey]):
910
907
  Raises:
911
908
  ValueError: If the number of qubits is too small.
912
909
  """
913
- from cirq.ops.dense_pauli_string import DensePauliString
914
910
 
915
911
  if not self.keys() <= set(qubits):
916
912
  raise ValueError('not self.keys() <= set(qubits)')
917
913
  # pylint: disable=too-many-function-args
918
914
  pauli_mask = [self.get(q, identity.I) for q in qubits]
919
915
  # pylint: enable=too-many-function-args
920
- return DensePauliString(pauli_mask, coefficient=self.coefficient)
916
+ return dense_pauli_string.DensePauliString(pauli_mask, coefficient=self.coefficient)
921
917
 
922
918
  def conjugated_by(self, clifford: 'cirq.OP_TREE') -> 'PauliString':
923
919
  r"""Returns the Pauli string conjugated by a clifford operation.
@@ -979,17 +975,65 @@ class PauliString(raw_types.Operation, Generic[TKey]):
979
975
  Returns:
980
976
  The Pauli string conjugated by the given Clifford operation.
981
977
  """
982
- pauli_map = dict(self._qubit_pauli_map)
983
- should_negate = False
984
- for op in list(op_tree.flatten_to_ops(clifford))[::-1]:
985
- if pauli_map.keys().isdisjoint(set(op.qubits)):
986
- continue
987
- for clifford_op in _decompose_into_cliffords(op)[::-1]:
988
- if pauli_map.keys().isdisjoint(set(clifford_op.qubits)):
989
- continue
990
- should_negate ^= _pass_operation_over(pauli_map, clifford_op, False)
991
- coef = -self._coefficient if should_negate else self.coefficient
992
- return PauliString(qubit_pauli_map=pauli_map, coefficient=coef)
978
+
979
+ # Initialize the ps the same as self.
980
+ ps = PauliString(qubit_pauli_map=self._qubit_pauli_map, coefficient=self.coefficient)
981
+ all_ops = list(op_tree.flatten_to_ops(clifford))
982
+ all_qubits = set.union(set(self.qubits), [q for op in all_ops for q in op.qubits])
983
+ # Iteratively calculate the conjugation in reverse order of ops.
984
+ for op in all_ops[::-1]:
985
+ # To calcuate the conjugation of P (`ps`) with respect to C (`op`)
986
+ # Decompose P = Pc⊗R, where Pc acts on the same qubits as C, R acts on the remaining.
987
+ # Then the conjugation = (C^{-1}⊗I·Pc⊗R·C⊗I) = (C^{-1}·Pc·C)⊗R.
988
+
989
+ # Isolate R
990
+ remain: 'cirq.PauliString' = PauliString(
991
+ *(pauli(q) for q in all_qubits - set(op.qubits) if (pauli := ps.get(q)) is not None)
992
+ )
993
+
994
+ # Initialize the conjugation of Pc.
995
+ conjugated: 'cirq.DensePauliString' = (
996
+ dense_pauli_string.DensePauliString(pauli_mask=[identity.I for _ in op.qubits])
997
+ * ps.coefficient
998
+ )
999
+
1000
+ # Calculate the conjugation via CliffordGate's clifford_tableau.
1001
+ # Note the clifford_tableau in CliffordGate represents C·P·C^-1 instead of C^-1·P·C.
1002
+ # So we take the inverse of the tableau to match the definition of the conjugation here.
1003
+ gate_in_clifford: 'cirq.CliffordGate'
1004
+ if isinstance(op.gate, clifford_gate.CliffordGate):
1005
+ gate_in_clifford = op.gate
1006
+ else:
1007
+ # Convert the clifford gate to CliffordGate type.
1008
+ gate_in_clifford = clifford_gate.CliffordGate.from_op_list([op], op.qubits)
1009
+ tableau = gate_in_clifford.clifford_tableau.inverse()
1010
+
1011
+ # Calculate the conjugation by `op` via mutiplying the conjugation of each Pauli:
1012
+ # C^{-1}·(P_1⊗...⊗P_n)·C
1013
+ # = C^{-1}·(P_1⊗I) ...·(P_n⊗I)·C
1014
+ # = (C^{-1}(P_1⊗I)C)·...·(C^{-1}(P_n⊗I)C)
1015
+ # For the Pauli on the kth qubit P_k. The conjugation is calculated as following.
1016
+ # Puali X_k's conjugation is from the destabilzer table;
1017
+ # Puali Z_k's conjugation is from the stabilzer table;
1018
+ # Puali Y_k's conjugation is calcluated according to Y = iXZ. E.g., for the kth qubit,
1019
+ # C^{-1}·Y_k⊗I·C = C^{-1}·(iX_k⊗I·Z_k⊗I)·C = i (C^{-1}·X_k⊗I·C)·(C^{-1}·Z_k⊗I·C).
1020
+ for qid, qubit in enumerate(op.qubits):
1021
+ pauli = ps.get(qubit)
1022
+ match pauli:
1023
+ case None:
1024
+ continue
1025
+ case pauli_gates.X:
1026
+ conjugated *= tableau.destabilizers()[qid]
1027
+ case pauli_gates.Z:
1028
+ conjugated *= tableau.stabilizers()[qid]
1029
+ case pauli_gates.Y:
1030
+ conjugated *= (
1031
+ 1j
1032
+ * tableau.destabilizers()[qid] # conj X first
1033
+ * tableau.stabilizers()[qid] # then conj Z
1034
+ )
1035
+ ps = remain * conjugated.on(*op.qubits)
1036
+ return ps
993
1037
 
994
1038
  def after(self, ops: 'cirq.OP_TREE') -> 'cirq.PauliString':
995
1039
  r"""Determines the equivalent pauli string after some operations.
@@ -1052,20 +1096,17 @@ class PauliString(raw_types.Operation, Generic[TKey]):
1052
1096
  pauli string, instead of before (and so are moving in the
1053
1097
  opposite direction).
1054
1098
  """
1055
- pauli_map = dict(self._qubit_pauli_map)
1056
- should_negate = False
1057
- for op in ops:
1058
- if pauli_map.keys().isdisjoint(set(op.qubits)):
1059
- continue
1060
- decomposed = _decompose_into_cliffords(op)
1061
- if not after_to_before:
1062
- decomposed = decomposed[::-1]
1063
- for clifford_op in decomposed:
1064
- if pauli_map.keys().isdisjoint(set(clifford_op.qubits)):
1065
- continue
1066
- should_negate ^= _pass_operation_over(pauli_map, clifford_op, after_to_before)
1067
- coef = -self._coefficient if should_negate else self.coefficient
1068
- return PauliString(qubit_pauli_map=pauli_map, coefficient=coef)
1099
+ # TODO(#6946): deprecate this method.
1100
+ # Note: This method is supposed to be replaced by conjugated_by()
1101
+ # (see #2351 for details).
1102
+ if after_to_before:
1103
+ return self.after(ops)
1104
+
1105
+ if isinstance(ops, gate_operation.GateOperation):
1106
+ return self.before(ops)
1107
+
1108
+ all_ops = list(op_tree.flatten_to_ops(ops))
1109
+ return self.before(all_ops[::-1])
1069
1110
 
1070
1111
  def _is_parameterized_(self) -> bool:
1071
1112
  return protocols.is_parameterized(self.coefficient)
@@ -1120,6 +1161,23 @@ def _validate_qubit_mapping(
1120
1161
  )
1121
1162
 
1122
1163
 
1164
+ def _try_interpret_as_pauli_string(op: Any):
1165
+ """Return a reprepresentation of an operation as a pauli string, if it is possible."""
1166
+ if isinstance(op, gate_operation.GateOperation):
1167
+ gates = {
1168
+ common_gates.XPowGate: pauli_gates.X,
1169
+ common_gates.YPowGate: pauli_gates.Y,
1170
+ common_gates.ZPowGate: pauli_gates.Z,
1171
+ }
1172
+ if (pauli := gates.get(type(op.gate), None)) is not None:
1173
+ exponent = op.gate.exponent # type: ignore
1174
+ if exponent % 2 == 0:
1175
+ return PauliString()
1176
+ if exponent % 2 == 1:
1177
+ return pauli.on(op.qubits[0])
1178
+ return None
1179
+
1180
+
1123
1181
  # Ignoring type because mypy believes `with_qubits` methods are incompatible.
1124
1182
  class SingleQubitPauliStringGateOperation( # type: ignore
1125
1183
  gate_operation.GateOperation, PauliString
@@ -1157,13 +1215,17 @@ class SingleQubitPauliStringGateOperation( # type: ignore
1157
1215
  def __mul__(self, other):
1158
1216
  if isinstance(other, SingleQubitPauliStringGateOperation):
1159
1217
  return self._as_pauli_string() * other._as_pauli_string()
1160
- if isinstance(other, (PauliString, complex, float, int)):
1218
+ if isinstance(other, (PauliString, numbers.Complex)):
1161
1219
  return self._as_pauli_string() * other
1220
+ if (as_pauli_string := _try_interpret_as_pauli_string(other)) is not None:
1221
+ return self * as_pauli_string
1162
1222
  return NotImplemented
1163
1223
 
1164
1224
  def __rmul__(self, other):
1165
- if isinstance(other, (PauliString, complex, float, int)):
1225
+ if isinstance(other, (PauliString, numbers.Complex)):
1166
1226
  return other * self._as_pauli_string()
1227
+ if (as_pauli_string := _try_interpret_as_pauli_string(other)) is not None:
1228
+ return as_pauli_string * self
1167
1229
  return NotImplemented
1168
1230
 
1169
1231
  def __neg__(self):
@@ -1409,8 +1471,8 @@ class MutablePauliString(Generic[TKey]):
1409
1471
  pauli_int = _pauli_like_to_pauli_int(qubit, pauli_gate_like)
1410
1472
  phase_log_i += self._imul_atom_helper(cast(TKey, qubit), pauli_int, sign)
1411
1473
  self.coefficient *= 1j ** (phase_log_i & 3)
1412
- elif isinstance(other, numbers.Number):
1413
- self.coefficient *= complex(cast(SupportsComplex, other))
1474
+ elif isinstance(other, numbers.Complex):
1475
+ self.coefficient *= other
1414
1476
  elif isinstance(other, raw_types.Operation) and isinstance(
1415
1477
  other.gate, identity.IdentityGate
1416
1478
  ):
@@ -1584,88 +1646,11 @@ def _decompose_into_cliffords(op: 'cirq.Operation') -> List['cirq.Operation']:
1584
1646
  if decomposed is not None:
1585
1647
  return [out for sub_op in decomposed for out in _decompose_into_cliffords(sub_op)]
1586
1648
 
1587
- raise TypeError(
1649
+ raise TypeError( # pragma: no cover
1588
1650
  f'Operation is not a known Clifford and did not decompose into known Cliffords: {op!r}'
1589
1651
  )
1590
1652
 
1591
1653
 
1592
- def _pass_operation_over(
1593
- pauli_map: Dict[TKey, pauli_gates.Pauli], op: 'cirq.Operation', after_to_before: bool = False
1594
- ) -> bool:
1595
- if isinstance(op, gate_operation.GateOperation):
1596
- gate = op.gate
1597
- if isinstance(gate, clifford_gate.SingleQubitCliffordGate):
1598
- return _pass_single_clifford_gate_over(
1599
- pauli_map, gate, cast(TKey, op.qubits[0]), after_to_before=after_to_before
1600
- )
1601
- if isinstance(gate, pauli_interaction_gate.PauliInteractionGate):
1602
- return _pass_pauli_interaction_gate_over(
1603
- pauli_map,
1604
- gate,
1605
- cast(TKey, op.qubits[0]),
1606
- cast(TKey, op.qubits[1]),
1607
- after_to_before=after_to_before,
1608
- )
1609
- raise NotImplementedError(f'Unsupported operation: {op!r}')
1610
-
1611
-
1612
- def _pass_single_clifford_gate_over(
1613
- pauli_map: Dict[TKey, pauli_gates.Pauli],
1614
- gate: clifford_gate.SingleQubitCliffordGate,
1615
- qubit: TKey,
1616
- after_to_before: bool = False,
1617
- ) -> bool:
1618
- if qubit not in pauli_map:
1619
- return False # pragma: no cover
1620
- if not after_to_before:
1621
- gate **= -1
1622
- pauli, inv = gate.pauli_tuple(pauli_map[qubit])
1623
- pauli_map[qubit] = pauli
1624
- return inv
1625
-
1626
-
1627
- def _pass_pauli_interaction_gate_over(
1628
- pauli_map: Dict[TKey, pauli_gates.Pauli],
1629
- gate: pauli_interaction_gate.PauliInteractionGate,
1630
- qubit0: TKey,
1631
- qubit1: TKey,
1632
- after_to_before: bool = False,
1633
- ) -> bool:
1634
- def merge_and_kickback(
1635
- qubit: TKey,
1636
- pauli_left: Optional[pauli_gates.Pauli],
1637
- pauli_right: Optional[pauli_gates.Pauli],
1638
- inv: bool,
1639
- ) -> int:
1640
- assert pauli_left is not None or pauli_right is not None
1641
- if pauli_left is None or pauli_right is None:
1642
- pauli_map[qubit] = cast(pauli_gates.Pauli, pauli_left or pauli_right)
1643
- return 0
1644
- if pauli_left == pauli_right:
1645
- del pauli_map[qubit]
1646
- return 0
1647
-
1648
- pauli_map[qubit] = pauli_left.third(pauli_right)
1649
- if (pauli_left < pauli_right) ^ after_to_before:
1650
- return int(inv) * 2 + 1
1651
-
1652
- return int(inv) * 2 - 1
1653
-
1654
- quarter_kickback = 0
1655
- if qubit0 in pauli_map and not protocols.commutes(pauli_map[qubit0], gate.pauli0):
1656
- quarter_kickback += merge_and_kickback(
1657
- qubit1, gate.pauli1, pauli_map.get(qubit1), gate.invert1
1658
- )
1659
- if qubit1 in pauli_map and not protocols.commutes(pauli_map[qubit1], gate.pauli1):
1660
- quarter_kickback += merge_and_kickback(
1661
- qubit0, pauli_map.get(qubit0), gate.pauli0, gate.invert0
1662
- )
1663
- assert (
1664
- quarter_kickback % 2 == 0
1665
- ), 'Impossible condition. quarter_kickback is either incremented twice or never.'
1666
- return quarter_kickback % 4 == 2
1667
-
1668
-
1669
1654
  # Mypy has extreme difficulty with these constants for some reason.
1670
1655
  _i = cast(identity.IdentityGate, identity.I) # type: ignore
1671
1656
  _x = cast(pauli_gates.Pauli, pauli_gates.X) # type: ignore