cirq-core 1.7.0.dev20250825174419__py3-none-any.whl → 1.7.0.dev20251203004401__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.
Files changed (426) hide show
  1. cirq/__init__.py +1 -0
  2. cirq/_compat.py +3 -2
  3. cirq/_compat_test.py +16 -15
  4. cirq/_doc.py +4 -3
  5. cirq/_import.py +2 -1
  6. cirq/_version.py +1 -1
  7. cirq/_version_test.py +1 -1
  8. cirq/circuits/_bucket_priority_queue.py +2 -1
  9. cirq/circuits/circuit.py +19 -17
  10. cirq/circuits/circuit_operation.py +2 -1
  11. cirq/circuits/circuit_operation_test.py +19 -0
  12. cirq/circuits/circuit_test.py +31 -12
  13. cirq/circuits/frozen_circuit.py +3 -2
  14. cirq/circuits/moment.py +3 -15
  15. cirq/circuits/optimization_pass.py +2 -1
  16. cirq/circuits/qasm_output.py +39 -10
  17. cirq/circuits/qasm_output_test.py +51 -2
  18. cirq/circuits/text_diagram_drawer.py +2 -1
  19. cirq/contrib/acquaintance/bipartite.py +2 -1
  20. cirq/contrib/acquaintance/devices.py +1 -1
  21. cirq/contrib/acquaintance/executor.py +4 -5
  22. cirq/contrib/acquaintance/executor_test.py +2 -1
  23. cirq/contrib/acquaintance/gates.py +2 -1
  24. cirq/contrib/acquaintance/gates_test.py +1 -1
  25. cirq/contrib/acquaintance/inspection_utils.py +2 -1
  26. cirq/contrib/acquaintance/mutation_utils.py +2 -1
  27. cirq/contrib/acquaintance/optimizers.py +2 -1
  28. cirq/contrib/acquaintance/permutation.py +2 -1
  29. cirq/contrib/acquaintance/permutation_test.py +1 -1
  30. cirq/contrib/acquaintance/shift.py +2 -1
  31. cirq/contrib/acquaintance/shift_swap_network.py +2 -1
  32. cirq/contrib/acquaintance/strategies/complete.py +3 -2
  33. cirq/contrib/acquaintance/strategies/cubic.py +2 -1
  34. cirq/contrib/acquaintance/strategies/quartic_paired.py +2 -1
  35. cirq/contrib/acquaintance/strategies/quartic_paired_test.py +1 -1
  36. cirq/contrib/acquaintance/testing.py +2 -1
  37. cirq/contrib/acquaintance/topological_sort.py +2 -1
  38. cirq/contrib/bayesian_network/bayesian_network_gate.py +3 -2
  39. cirq/contrib/circuitdag/circuit_dag.py +4 -2
  40. cirq/contrib/custom_simulators/custom_state_simulator.py +2 -1
  41. cirq/contrib/custom_simulators/custom_state_simulator_test.py +1 -1
  42. cirq/contrib/graph_device/graph_device.py +2 -1
  43. cirq/contrib/graph_device/graph_device_test.py +2 -1
  44. cirq/contrib/graph_device/hypergraph.py +2 -1
  45. cirq/contrib/graph_device/uniform_graph_device.py +2 -1
  46. cirq/contrib/json.py +14 -2
  47. cirq/contrib/json_test_data/BayesianNetworkGate.json +10 -0
  48. cirq/contrib/json_test_data/BayesianNetworkGate.repr +3 -0
  49. cirq/contrib/json_test_data/QuantumVolumeResult.json +169 -0
  50. cirq/contrib/json_test_data/QuantumVolumeResult.repr +22 -0
  51. cirq/contrib/json_test_data/SwapPermutationGate.json +3 -0
  52. cirq/contrib/json_test_data/SwapPermutationGate.repr +1 -0
  53. cirq/contrib/json_test_data/spec.py +0 -2
  54. cirq/contrib/noise_models/noise_models.py +2 -1
  55. cirq/contrib/paulistring/clifford_optimize.py +20 -2
  56. cirq/contrib/paulistring/optimize.py +1 -1
  57. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +146 -35
  58. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +81 -178
  59. cirq/contrib/paulistring/recombine.py +5 -2
  60. cirq/contrib/paulistring/separate.py +1 -1
  61. cirq/contrib/qasm_import/_lexer.py +6 -1
  62. cirq/contrib/qasm_import/_lexer_test.py +1 -1
  63. cirq/contrib/qasm_import/_parser.py +24 -8
  64. cirq/contrib/qasm_import/_parser_test.py +44 -6
  65. cirq/contrib/qcircuit/qcircuit_pdf_test.py +6 -9
  66. cirq/contrib/quantikz/__init__.py +21 -0
  67. cirq/contrib/quantikz/circuit_to_latex_quantikz.py +680 -0
  68. cirq/contrib/quantikz/circuit_to_latex_quantikz_test.py +253 -0
  69. cirq/contrib/quantikz/circuit_to_latex_render.py +424 -0
  70. cirq/contrib/quantikz/circuit_to_latex_render_test.py +44 -0
  71. cirq/contrib/quantum_volume/quantum_volume.py +2 -1
  72. cirq/contrib/quimb/density_matrix.py +1 -1
  73. cirq/contrib/quimb/grid_circuits.py +2 -1
  74. cirq/contrib/quimb/grid_circuits_test.py +1 -1
  75. cirq/contrib/quimb/mps_simulator.py +4 -3
  76. cirq/contrib/quimb/state_vector.py +2 -1
  77. cirq/contrib/quirk/export_to_quirk.py +2 -1
  78. cirq/contrib/quirk/linearize_circuit.py +1 -1
  79. cirq/contrib/quirk/quirk_gate.py +2 -1
  80. cirq/contrib/routing/device.py +1 -1
  81. cirq/contrib/routing/greedy.py +2 -1
  82. cirq/contrib/routing/initialization.py +2 -1
  83. cirq/contrib/routing/router.py +2 -1
  84. cirq/contrib/routing/swap_network.py +2 -1
  85. cirq/contrib/routing/utils.py +2 -1
  86. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +7 -5
  87. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking_test.py +6 -6
  88. cirq/devices/device.py +2 -1
  89. cirq/devices/grid_device_metadata.py +2 -1
  90. cirq/devices/grid_qubit.py +7 -6
  91. cirq/devices/insertion_noise_model.py +2 -1
  92. cirq/devices/line_qubit.py +2 -1
  93. cirq/devices/named_topologies.py +2 -1
  94. cirq/devices/noise_model.py +2 -1
  95. cirq/devices/noise_model_test.py +1 -1
  96. cirq/devices/noise_properties.py +2 -1
  97. cirq/devices/superconducting_qubits_noise_properties_test.py +2 -1
  98. cirq/devices/thermal_noise_model.py +2 -1
  99. cirq/experiments/__init__.py +2 -0
  100. cirq/experiments/benchmarking/parallel_xeb.py +2 -1
  101. cirq/experiments/benchmarking/parallel_xeb_test.py +1 -1
  102. cirq/experiments/fidelity_estimation.py +2 -1
  103. cirq/experiments/fidelity_estimation_test.py +1 -1
  104. cirq/experiments/ghz_2d.py +150 -0
  105. cirq/experiments/ghz_2d_test.py +155 -0
  106. cirq/experiments/n_qubit_tomography.py +2 -1
  107. cirq/experiments/n_qubit_tomography_test.py +1 -1
  108. cirq/experiments/purity_estimation.py +1 -1
  109. cirq/experiments/qubit_characterizations.py +33 -4
  110. cirq/experiments/qubit_characterizations_test.py +16 -0
  111. cirq/experiments/random_quantum_circuit_generation.py +2 -1
  112. cirq/experiments/random_quantum_circuit_generation_test.py +2 -1
  113. cirq/experiments/readout_confusion_matrix.py +2 -1
  114. cirq/experiments/readout_confusion_matrix_test.py +1 -1
  115. cirq/experiments/single_qubit_readout_calibration.py +2 -1
  116. cirq/experiments/single_qubit_readout_calibration_test.py +1 -1
  117. cirq/experiments/t1_decay_experiment.py +2 -1
  118. cirq/experiments/two_qubit_xeb.py +2 -1
  119. cirq/experiments/two_qubit_xeb_test.py +1 -1
  120. cirq/experiments/xeb_fitting.py +2 -1
  121. cirq/experiments/xeb_fitting_test.py +1 -1
  122. cirq/experiments/xeb_sampling.py +5 -3
  123. cirq/experiments/xeb_sampling_test.py +1 -1
  124. cirq/experiments/xeb_simulation.py +2 -1
  125. cirq/experiments/xeb_simulation_test.py +2 -1
  126. cirq/experiments/z_phase_calibration.py +2 -1
  127. cirq/experiments/z_phase_calibration_test.py +18 -3
  128. cirq/interop/quirk/cells/__init__.py +1 -2
  129. cirq/interop/quirk/cells/all_cells.py +2 -1
  130. cirq/interop/quirk/cells/arithmetic_cells.py +2 -1
  131. cirq/interop/quirk/cells/cell.py +2 -1
  132. cirq/interop/quirk/cells/composite_cell.py +2 -1
  133. cirq/interop/quirk/cells/composite_cell_test.py +1 -1
  134. cirq/interop/quirk/cells/control_cells.py +2 -1
  135. cirq/interop/quirk/cells/frequency_space_cells.py +1 -1
  136. cirq/interop/quirk/cells/ignored_cells.py +1 -1
  137. cirq/interop/quirk/cells/input_cells.py +2 -1
  138. cirq/interop/quirk/cells/input_rotation_cells.py +2 -1
  139. cirq/interop/quirk/cells/measurement_cells.py +2 -1
  140. cirq/interop/quirk/cells/parse.py +2 -11
  141. cirq/interop/quirk/cells/qubit_permutation_cells.py +2 -1
  142. cirq/interop/quirk/cells/scalar_cells.py +2 -1
  143. cirq/interop/quirk/cells/single_qubit_rotation_cells.py +2 -1
  144. cirq/interop/quirk/cells/swap_cell.py +2 -1
  145. cirq/interop/quirk/cells/unsupported_cells.py +1 -1
  146. cirq/interop/quirk/url_to_circuit.py +2 -1
  147. cirq/json_resolver_cache.py +0 -2
  148. cirq/linalg/decompositions.py +6 -2
  149. cirq/linalg/decompositions_test.py +1 -0
  150. cirq/linalg/diagonalize.py +1 -1
  151. cirq/linalg/predicates.py +2 -1
  152. cirq/linalg/tolerance.py +2 -1
  153. cirq/linalg/transformations.py +3 -2
  154. cirq/ops/arithmetic_operation.py +4 -3
  155. cirq/ops/arithmetic_operation_test.py +1 -1
  156. cirq/ops/boolean_hamiltonian.py +4 -3
  157. cirq/ops/classically_controlled_operation.py +11 -11
  158. cirq/ops/classically_controlled_operation_test.py +26 -2
  159. cirq/ops/clifford_gate.py +3 -2
  160. cirq/ops/clifford_gate_test.py +1 -2
  161. cirq/ops/common_channels.py +2 -1
  162. cirq/ops/common_gates.py +3 -2
  163. cirq/ops/control_values.py +2 -1
  164. cirq/ops/controlled_gate.py +3 -2
  165. cirq/ops/controlled_gate_test.py +2 -1
  166. cirq/ops/controlled_operation.py +3 -2
  167. cirq/ops/controlled_operation_test.py +2 -1
  168. cirq/ops/dense_pauli_string.py +44 -81
  169. cirq/ops/dense_pauli_string_test.py +21 -0
  170. cirq/ops/diagonal_gate.py +3 -2
  171. cirq/ops/eigen_gate.py +9 -7
  172. cirq/ops/fourier_transform.py +3 -2
  173. cirq/ops/fourier_transform_test.py +2 -4
  174. cirq/ops/fsim_gate.py +3 -2
  175. cirq/ops/gate_operation.py +23 -12
  176. cirq/ops/gateset.py +22 -2
  177. cirq/ops/global_phase_op.py +3 -2
  178. cirq/ops/greedy_qubit_manager.py +2 -1
  179. cirq/ops/identity.py +2 -1
  180. cirq/ops/kraus_channel.py +2 -1
  181. cirq/ops/linear_combinations.py +12 -17
  182. cirq/ops/linear_combinations_test.py +23 -1
  183. cirq/ops/matrix_gates.py +2 -1
  184. cirq/ops/measure_util.py +8 -6
  185. cirq/ops/measurement_gate.py +2 -1
  186. cirq/ops/mixed_unitary_channel.py +2 -1
  187. cirq/ops/named_qubit.py +2 -2
  188. cirq/ops/op_tree.py +2 -1
  189. cirq/ops/parallel_gate.py +3 -2
  190. cirq/ops/parity_gates.py +2 -1
  191. cirq/ops/parity_gates_test.py +35 -0
  192. cirq/ops/pauli_interaction_gate.py +2 -1
  193. cirq/ops/pauli_measurement_gate.py +2 -1
  194. cirq/ops/pauli_string.py +37 -57
  195. cirq/ops/pauli_string_phasor.py +6 -5
  196. cirq/ops/pauli_string_raw_types.py +2 -1
  197. cirq/ops/pauli_string_test.py +49 -6
  198. cirq/ops/pauli_sum_exponential.py +2 -1
  199. cirq/ops/permutation_gate.py +2 -1
  200. cirq/ops/phased_iswap_gate.py +3 -2
  201. cirq/ops/phased_x_gate.py +5 -4
  202. cirq/ops/phased_x_z_gate.py +12 -5
  203. cirq/ops/projector.py +2 -1
  204. cirq/ops/qubit_manager.py +2 -1
  205. cirq/ops/qubit_order.py +2 -1
  206. cirq/ops/qubit_order_or_list.py +1 -1
  207. cirq/ops/random_gate_channel.py +3 -2
  208. cirq/ops/raw_types.py +33 -16
  209. cirq/ops/raw_types_test.py +4 -3
  210. cirq/ops/state_preparation_channel.py +2 -1
  211. cirq/ops/three_qubit_gates.py +3 -2
  212. cirq/ops/two_qubit_diagonal_gate.py +3 -2
  213. cirq/ops/uniform_superposition_gate.py +2 -1
  214. cirq/ops/wait_gate.py +10 -4
  215. cirq/protocols/act_on_protocol.py +2 -1
  216. cirq/protocols/act_on_protocol_test.py +2 -1
  217. cirq/protocols/apply_channel_protocol.py +2 -1
  218. cirq/protocols/apply_mixture_protocol.py +2 -1
  219. cirq/protocols/apply_mixture_protocol_test.py +2 -1
  220. cirq/protocols/apply_unitary_protocol.py +2 -1
  221. cirq/protocols/apply_unitary_protocol_test.py +2 -0
  222. cirq/protocols/approximate_equality_protocol.py +2 -1
  223. cirq/protocols/circuit_diagram_info_protocol.py +2 -1
  224. cirq/protocols/control_key_protocol.py +7 -0
  225. cirq/protocols/decompose_protocol.py +2 -12
  226. cirq/protocols/has_stabilizer_effect_protocol.py +1 -1
  227. cirq/protocols/has_stabilizer_effect_protocol_test.py +11 -9
  228. cirq/protocols/has_unitary_protocol_test.py +3 -3
  229. cirq/protocols/hash_from_pickle_test.py +2 -2
  230. cirq/protocols/inverse_protocol.py +2 -1
  231. cirq/protocols/json_serialization.py +5 -4
  232. cirq/protocols/json_serialization_test.py +31 -31
  233. cirq/protocols/kraus_protocol.py +4 -3
  234. cirq/protocols/kraus_protocol_test.py +7 -7
  235. cirq/protocols/measurement_key_protocol.py +32 -8
  236. cirq/protocols/mixture_protocol.py +3 -2
  237. cirq/protocols/mixture_protocol_test.py +7 -7
  238. cirq/protocols/mul_protocol_test.py +4 -4
  239. cirq/protocols/phase_protocol.py +13 -4
  240. cirq/protocols/pow_protocol.py +2 -1
  241. cirq/protocols/pow_protocol_test.py +5 -5
  242. cirq/protocols/qasm.py +2 -1
  243. cirq/protocols/qid_shape_protocol.py +2 -1
  244. cirq/protocols/resolve_parameters.py +17 -15
  245. cirq/protocols/trace_distance_bound.py +2 -1
  246. cirq/protocols/unitary_protocol.py +21 -21
  247. cirq/protocols/unitary_protocol_test.py +31 -19
  248. cirq/qis/channels.py +1 -1
  249. cirq/qis/channels_test.py +1 -1
  250. cirq/qis/clifford_tableau.py +16 -15
  251. cirq/qis/clifford_tableau_test.py +17 -17
  252. cirq/qis/entropy.py +3 -3
  253. cirq/qis/entropy_test.py +1 -1
  254. cirq/qis/quantum_state_representation.py +2 -1
  255. cirq/qis/states.py +7 -2
  256. cirq/qis/states_test.py +54 -54
  257. cirq/sim/classical_simulator.py +25 -14
  258. cirq/sim/classical_simulator_test.py +85 -30
  259. cirq/sim/clifford/clifford_simulator.py +7 -6
  260. cirq/sim/clifford/clifford_simulator_test.py +51 -50
  261. cirq/sim/clifford/clifford_tableau_simulation_state.py +2 -1
  262. cirq/sim/clifford/stabilizer_ch_form_simulation_state.py +2 -1
  263. cirq/sim/clifford/stabilizer_sampler.py +1 -1
  264. cirq/sim/clifford/stabilizer_simulation_state.py +2 -1
  265. cirq/sim/clifford/stabilizer_state_ch_form.py +16 -15
  266. cirq/sim/clifford/stabilizer_state_ch_form_test.py +0 -1
  267. cirq/sim/density_matrix_simulation_state.py +7 -6
  268. cirq/sim/density_matrix_simulator.py +3 -2
  269. cirq/sim/density_matrix_simulator_test.py +94 -84
  270. cirq/sim/density_matrix_utils.py +2 -1
  271. cirq/sim/density_matrix_utils_test.py +1 -1
  272. cirq/sim/mux.py +35 -8
  273. cirq/sim/mux_test.py +39 -26
  274. cirq/sim/simulation_product_state.py +2 -1
  275. cirq/sim/simulation_product_state_test.py +8 -7
  276. cirq/sim/simulation_state.py +6 -5
  277. cirq/sim/simulation_state_base.py +3 -2
  278. cirq/sim/simulation_state_test.py +7 -6
  279. cirq/sim/simulation_utils.py +2 -1
  280. cirq/sim/simulator.py +4 -3
  281. cirq/sim/simulator_base.py +2 -1
  282. cirq/sim/simulator_base_test.py +51 -36
  283. cirq/sim/simulator_test.py +41 -36
  284. cirq/sim/sparse_simulator.py +3 -2
  285. cirq/sim/sparse_simulator_test.py +92 -82
  286. cirq/sim/state_vector.py +5 -6
  287. cirq/sim/state_vector_simulation_state.py +10 -9
  288. cirq/sim/state_vector_simulator.py +2 -1
  289. cirq/sim/state_vector_simulator_test.py +9 -9
  290. cirq/sim/state_vector_test.py +40 -39
  291. cirq/study/__init__.py +1 -0
  292. cirq/study/flatten_expressions.py +2 -1
  293. cirq/study/resolver.py +31 -18
  294. cirq/study/resolver_test.py +1 -1
  295. cirq/study/result.py +2 -1
  296. cirq/study/result_test.py +20 -20
  297. cirq/study/sweepable.py +2 -1
  298. cirq/study/sweepable_test.py +20 -20
  299. cirq/study/sweeps.py +26 -1
  300. cirq/study/sweeps_test.py +67 -43
  301. cirq/testing/_compat_test_data/__init__.py +3 -3
  302. cirq/testing/circuit_compare.py +2 -1
  303. cirq/testing/circuit_compare_test.py +16 -14
  304. cirq/testing/consistent_act_on_test.py +1 -1
  305. cirq/testing/consistent_channels.py +2 -2
  306. cirq/testing/consistent_controlled_gate_op.py +2 -2
  307. cirq/testing/consistent_controlled_gate_op_test.py +2 -1
  308. cirq/testing/consistent_decomposition.py +4 -2
  309. cirq/testing/consistent_phase_by.py +1 -1
  310. cirq/testing/consistent_protocols.py +2 -1
  311. cirq/testing/consistent_protocols_test.py +3 -3
  312. cirq/testing/consistent_qasm.py +4 -3
  313. cirq/testing/consistent_qasm_test.py +3 -3
  314. cirq/testing/consistent_resolve_parameters.py +1 -1
  315. cirq/testing/consistent_unitary.py +1 -1
  316. cirq/testing/consistent_unitary_test.py +1 -1
  317. cirq/testing/deprecation.py +1 -1
  318. cirq/testing/devices.py +3 -2
  319. cirq/testing/equals_tester.py +4 -3
  320. cirq/testing/equivalent_basis_map.py +4 -2
  321. cirq/testing/json.py +3 -2
  322. cirq/testing/lin_alg_utils.py +1 -1
  323. cirq/testing/logs.py +1 -1
  324. cirq/testing/op_tree.py +1 -1
  325. cirq/testing/order_tester.py +2 -2
  326. cirq/testing/pytest_utils.py +2 -1
  327. cirq/testing/random_circuit.py +2 -1
  328. cirq/testing/random_circuit_test.py +2 -1
  329. cirq/testing/repr_pretty_tester.py +3 -3
  330. cirq/transformers/__init__.py +1 -0
  331. cirq/transformers/_connected_component.py +231 -0
  332. cirq/transformers/_connected_component_test.py +200 -0
  333. cirq/transformers/align_test.py +13 -13
  334. cirq/transformers/analytical_decompositions/clifford_decomposition.py +8 -7
  335. cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +5 -5
  336. cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +11 -10
  337. cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +6 -6
  338. cirq/transformers/analytical_decompositions/cphase_to_fsim.py +3 -2
  339. cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +11 -10
  340. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +8 -7
  341. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +17 -20
  342. cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py +33 -27
  343. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +1 -1
  344. cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +1 -1
  345. cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +12 -11
  346. cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +5 -2
  347. cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +3 -3
  348. cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +2 -1
  349. cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +2 -1
  350. cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py +2 -2
  351. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +2 -1
  352. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +32 -30
  353. cirq/transformers/drop_negligible_operations_test.py +7 -7
  354. cirq/transformers/dynamical_decoupling.py +185 -112
  355. cirq/transformers/dynamical_decoupling_test.py +195 -201
  356. cirq/transformers/eject_phased_paulis.py +2 -1
  357. cirq/transformers/eject_phased_paulis_test.py +3 -2
  358. cirq/transformers/eject_z.py +5 -3
  359. cirq/transformers/eject_z_test.py +23 -25
  360. cirq/transformers/expand_composite.py +3 -2
  361. cirq/transformers/expand_composite_test.py +14 -14
  362. cirq/transformers/gauge_compiling/__init__.py +13 -0
  363. cirq/transformers/gauge_compiling/gauge_compiling.py +3 -2
  364. cirq/transformers/gauge_compiling/gauge_compiling_test.py +14 -12
  365. cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +3 -3
  366. cirq/transformers/gauge_compiling/idle_moments_gauge.py +225 -0
  367. cirq/transformers/gauge_compiling/idle_moments_gauge_test.py +193 -0
  368. cirq/transformers/gauge_compiling/multi_moment_cphase_gauge.py +242 -0
  369. cirq/transformers/gauge_compiling/multi_moment_cphase_gauge_test.py +243 -0
  370. cirq/transformers/gauge_compiling/multi_moment_gauge_compiling.py +151 -0
  371. cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +2 -1
  372. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +1 -1
  373. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +6 -6
  374. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +3 -2
  375. cirq/transformers/measurement_transformers.py +2 -1
  376. cirq/transformers/measurement_transformers_test.py +45 -39
  377. cirq/transformers/merge_k_qubit_gates.py +2 -1
  378. cirq/transformers/merge_k_qubit_gates_test.py +1 -1
  379. cirq/transformers/merge_single_qubit_gates.py +9 -5
  380. cirq/transformers/merge_single_qubit_gates_test.py +22 -22
  381. cirq/transformers/noise_adding_test.py +2 -2
  382. cirq/transformers/optimize_for_target_gateset.py +2 -1
  383. cirq/transformers/optimize_for_target_gateset_test.py +11 -9
  384. cirq/transformers/qubit_management_transformers_test.py +6 -2
  385. cirq/transformers/routing/mapping_manager.py +2 -1
  386. cirq/transformers/routing/route_circuit_cqc.py +2 -1
  387. cirq/transformers/stratify.py +2 -1
  388. cirq/transformers/symbolize.py +2 -1
  389. cirq/transformers/tag_transformers.py +2 -1
  390. cirq/transformers/target_gatesets/compilation_target_gateset.py +2 -1
  391. cirq/transformers/target_gatesets/cz_gateset.py +2 -1
  392. cirq/transformers/target_gatesets/cz_gateset_test.py +1 -1
  393. cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +2 -1
  394. cirq/transformers/transformer_api.py +2 -1
  395. cirq/transformers/transformer_primitives.py +271 -145
  396. cirq/transformers/transformer_primitives_test.py +185 -1
  397. cirq/value/abc_alt.py +2 -1
  398. cirq/value/classical_data.py +2 -1
  399. cirq/value/condition.py +2 -1
  400. cirq/value/digits.py +9 -2
  401. cirq/value/duration.py +6 -5
  402. cirq/value/linear_dict.py +4 -9
  403. cirq/value/measurement_key.py +2 -1
  404. cirq/value/periodic_value.py +3 -2
  405. cirq/value/product_state.py +2 -1
  406. cirq/value/value_equality_attr.py +2 -1
  407. cirq/vis/density_matrix.py +1 -1
  408. cirq/vis/heatmap.py +2 -1
  409. cirq/vis/histogram.py +2 -1
  410. cirq/vis/state_histogram.py +2 -1
  411. cirq/work/collector.py +2 -1
  412. cirq/work/observable_grouping.py +2 -1
  413. cirq/work/observable_measurement.py +2 -1
  414. cirq/work/observable_measurement_data.py +2 -1
  415. cirq/work/observable_measurement_test.py +1 -1
  416. cirq/work/observable_readout_calibration.py +2 -1
  417. cirq/work/observable_readout_calibration_test.py +1 -1
  418. cirq/work/observable_settings.py +2 -1
  419. cirq/work/sampler.py +2 -1
  420. cirq/work/sampler_test.py +1 -1
  421. {cirq_core-1.7.0.dev20250825174419.dist-info → cirq_core-1.7.0.dev20251203004401.dist-info}/METADATA +5 -6
  422. {cirq_core-1.7.0.dev20250825174419.dist-info → cirq_core-1.7.0.dev20251203004401.dist-info}/RECORD +425 -406
  423. cirq/contrib/json_test.py +0 -33
  424. {cirq_core-1.7.0.dev20250825174419.dist-info → cirq_core-1.7.0.dev20251203004401.dist-info}/WHEEL +0 -0
  425. {cirq_core-1.7.0.dev20250825174419.dist-info → cirq_core-1.7.0.dev20251203004401.dist-info}/licenses/LICENSE +0 -0
  426. {cirq_core-1.7.0.dev20250825174419.dist-info → cirq_core-1.7.0.dev20251203004401.dist-info}/top_level.txt +0 -0
@@ -975,10 +975,16 @@ def test_paulisum_validation() -> None:
975
975
  ps += cirq.I(cirq.LineQubit(0))
976
976
  assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(1)}))
977
977
 
978
+ ps = cirq.I(cirq.LineQubit(0)) + cirq.PauliSum()
979
+ assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(1)}))
980
+
978
981
  ps = cirq.PauliSum()
979
982
  ps -= cirq.I(cirq.LineQubit(0))
980
983
  assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(-1)}))
981
984
 
985
+ ps = cirq.I(cirq.LineQubit(0)) - cirq.PauliSum()
986
+ assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(1)}))
987
+
982
988
 
983
989
  def test_add_number_paulisum() -> None:
984
990
  q = cirq.LineQubit.range(2)
@@ -1008,6 +1014,22 @@ def test_add_number_paulistring() -> None:
1008
1014
  == cirq.PauliSum.from_pauli_strings([cirq.PauliString() * 2, cirq.PauliString({a: cirq.X})])
1009
1015
  )
1010
1016
 
1017
+ assert (
1018
+ cirq.X(a) - 2
1019
+ == -2 + cirq.X(a)
1020
+ == cirq.PauliSum.from_pauli_strings(
1021
+ [cirq.PauliString() * -2, cirq.PauliString({a: cirq.X})]
1022
+ )
1023
+ )
1024
+
1025
+ assert (
1026
+ 2 - cirq.X(a)
1027
+ == 2 + -cirq.X(a)
1028
+ == cirq.PauliSum.from_pauli_strings(
1029
+ [cirq.PauliString() * 2, -cirq.PauliString({a: cirq.X})]
1030
+ )
1031
+ )
1032
+
1011
1033
 
1012
1034
  def test_pauli_sum_formatting() -> None:
1013
1035
  q = cirq.LineQubit.range(2)
@@ -1430,7 +1452,7 @@ def test_expectation_from_density_matrix_invalid_input() -> None:
1430
1452
  with pytest.raises(ValueError, match='shape'):
1431
1453
  psum.expectation_from_density_matrix(rho.reshape((8, 8, 1)), q_map)
1432
1454
  with pytest.raises(ValueError, match='shape'):
1433
- psum.expectation_from_density_matrix(rho.reshape((-1)), q_map)
1455
+ psum.expectation_from_density_matrix(rho.reshape((-1,)), q_map)
1434
1456
 
1435
1457
 
1436
1458
  def test_expectation_from_density_matrix_check_preconditions() -> None:
cirq/ops/matrix_gates.py CHANGED
@@ -16,7 +16,8 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- from typing import Any, Iterable, TYPE_CHECKING
19
+ from collections.abc import Iterable
20
+ from typing import Any, TYPE_CHECKING
20
21
 
21
22
  import numpy as np
22
23
 
cirq/ops/measure_util.py CHANGED
@@ -14,12 +14,13 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import Callable, Iterable, overload, TYPE_CHECKING
17
+ from collections.abc import Callable, Iterable
18
+ from typing import cast, overload, TYPE_CHECKING
18
19
 
19
20
  import numpy as np
20
21
 
21
22
  from cirq import protocols
22
- from cirq.ops import pauli_string, raw_types
23
+ from cirq.ops import gate_operation, pauli_string, raw_types
23
24
  from cirq.ops.measurement_gate import MeasurementGate
24
25
  from cirq.ops.pauli_measurement_gate import PauliMeasurementGate
25
26
 
@@ -96,7 +97,7 @@ def measure(
96
97
  key: str | cirq.MeasurementKey | None = None,
97
98
  invert_mask: tuple[bool, ...] = (),
98
99
  confusion_map: dict[tuple[int, ...], np.ndarray] | None = None,
99
- ) -> raw_types.Operation:
100
+ ) -> gate_operation.GateOperation:
100
101
  pass
101
102
 
102
103
 
@@ -107,7 +108,7 @@ def measure(
107
108
  key: str | cirq.MeasurementKey | None = None,
108
109
  invert_mask: tuple[bool, ...] = (),
109
110
  confusion_map: dict[tuple[int, ...], np.ndarray] | None = None,
110
- ) -> raw_types.Operation:
111
+ ) -> gate_operation.GateOperation:
111
112
  pass
112
113
 
113
114
 
@@ -116,7 +117,7 @@ def measure(
116
117
  key: str | cirq.MeasurementKey | None = None,
117
118
  invert_mask: tuple[bool, ...] = (),
118
119
  confusion_map: dict[tuple[int, ...], np.ndarray] | None = None,
119
- ) -> raw_types.Operation:
120
+ ) -> gate_operation.GateOperation:
120
121
  """Returns a single MeasurementGate applied to all the given qubits.
121
122
 
122
123
  The qubits are measured in the computational basis. This can also be
@@ -161,7 +162,8 @@ def measure(
161
162
  if key is None:
162
163
  key = _default_measurement_key(targets)
163
164
  qid_shape = protocols.qid_shape(targets)
164
- return MeasurementGate(len(targets), key, invert_mask, qid_shape, confusion_map).on(*targets)
165
+ gate = MeasurementGate(len(targets), key, invert_mask, qid_shape, confusion_map)
166
+ return cast(gate_operation.GateOperation, gate.on(*targets))
165
167
 
166
168
 
167
169
  M = measure
@@ -14,7 +14,8 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import Any, Iterable, Mapping, Sequence, TYPE_CHECKING
17
+ from collections.abc import Iterable, Mapping, Sequence
18
+ from typing import Any, TYPE_CHECKING
18
19
 
19
20
  import numpy as np
20
21
 
@@ -2,7 +2,8 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Any, Iterable, Mapping, TYPE_CHECKING
5
+ from collections.abc import Iterable, Mapping
6
+ from typing import Any, TYPE_CHECKING
6
7
 
7
8
  import numpy as np
8
9
 
cirq/ops/named_qubit.py CHANGED
@@ -148,7 +148,7 @@ class NamedQid(_BaseNamedQid):
148
148
 
149
149
  @staticmethod
150
150
  def range(*args, prefix: str, dimension: int) -> list[NamedQid]:
151
- """Returns a range of ``NamedQid``\\s.
151
+ """Returns a range of ``NamedQid``s.
152
152
 
153
153
  The range returned starts with the prefix, and followed by a qid for
154
154
  each number in the range, e.g.:
@@ -166,7 +166,7 @@ class NamedQid(_BaseNamedQid):
166
166
  dimension: The dimension of the qid's Hilbert space, i.e.
167
167
  the number of quantum levels.
168
168
  Returns:
169
- A list of ``NamedQid``\\s.
169
+ A list of ``NamedQid``s.
170
170
  """
171
171
  return [NamedQid(f"{prefix}{i}", dimension=dimension) for i in range(*args)]
172
172
 
cirq/ops/op_tree.py CHANGED
@@ -16,7 +16,8 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- from typing import Callable, Iterable, Iterator, NoReturn, TYPE_CHECKING
19
+ from collections.abc import Callable, Iterable, Iterator
20
+ from typing import NoReturn, TYPE_CHECKING
20
21
 
21
22
  from cirq._doc import document
22
23
  from cirq._import import LazyLoader
cirq/ops/parallel_gate.py CHANGED
@@ -14,8 +14,9 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
+ from collections.abc import Set
17
18
  from types import NotImplementedType
18
- from typing import AbstractSet, Any, TYPE_CHECKING
19
+ from typing import Any, TYPE_CHECKING
19
20
 
20
21
  import numpy as np
21
22
 
@@ -90,7 +91,7 @@ class ParallelGate(raw_types.Gate):
90
91
  def _is_parameterized_(self) -> bool:
91
92
  return protocols.is_parameterized(self.sub_gate)
92
93
 
93
- def _parameter_names_(self) -> AbstractSet[str]:
94
+ def _parameter_names_(self) -> Set[str]:
94
95
  return protocols.parameter_names(self.sub_gate)
95
96
 
96
97
  def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> ParallelGate:
cirq/ops/parity_gates.py CHANGED
@@ -16,7 +16,8 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- from typing import Any, Iterator, Self, Sequence, TYPE_CHECKING
19
+ from collections.abc import Iterator, Sequence
20
+ from typing import Any, Self, TYPE_CHECKING
20
21
 
21
22
  import numpy as np
22
23
 
@@ -352,3 +352,38 @@ def test_clifford_protocols(
352
352
  else:
353
353
  assert not cirq.has_stabilizer_effect(gate)
354
354
  assert gate._decompose_into_clifford_with_qubits_(cirq.LineQubit.range(2)) is NotImplemented
355
+
356
+
357
+ def test_parity_gate_multiplication():
358
+ q1, q2, q3 = cirq.LineQubit.range(3)
359
+
360
+ # XX gate
361
+ xx_12 = cirq.XX(q1, q2)
362
+ xx_23 = cirq.XX(q2, q3)
363
+ result = xx_12 * xx_23
364
+ expected = cirq.PauliString({q1: cirq.X, q3: cirq.X})
365
+ assert result == expected
366
+
367
+ # YY gate
368
+ yy_12 = cirq.YY(q1, q2)
369
+ yy_23 = cirq.YY(q2, q3)
370
+ result_yy = yy_12 * yy_23
371
+ expected_yy = cirq.PauliString({q1: cirq.Y, q3: cirq.Y})
372
+ assert result_yy == expected_yy
373
+
374
+ # ZZ gate
375
+ zz_12 = cirq.ZZ(q1, q2)
376
+ zz_23 = cirq.ZZ(q2, q3)
377
+ result_zz = zz_12 * zz_23
378
+ expected_zz = cirq.PauliString({q1: cirq.Z, q3: cirq.Z})
379
+ assert result_zz == expected_zz
380
+
381
+
382
+ def test_parity_gate_multiplication_same_qubits():
383
+ q1, q2 = cirq.LineQubit.range(2)
384
+
385
+ # XX * XX should be identity
386
+ xx = cirq.XX(q1, q2)
387
+ result = xx * xx
388
+ expected = cirq.PauliString({q1: cirq.I, q2: cirq.I})
389
+ assert result == expected
@@ -14,7 +14,8 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import Any, Iterator, Sequence, TYPE_CHECKING
17
+ from collections.abc import Iterator, Sequence
18
+ from typing import Any, TYPE_CHECKING
18
19
 
19
20
  import numpy as np
20
21
 
@@ -14,7 +14,8 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import Any, cast, Iterable, Iterator, Mapping, Sequence, TYPE_CHECKING
17
+ from collections.abc import Iterable, Iterator, Mapping, Sequence
18
+ from typing import Any, cast, TYPE_CHECKING
18
19
 
19
20
  from cirq import protocols, value
20
21
  from cirq.ops import (
cirq/ops/pauli_string.py CHANGED
@@ -17,25 +17,19 @@ from __future__ import annotations
17
17
  import cmath
18
18
  import math
19
19
  import numbers
20
- from types import NotImplementedType
21
- from typing import (
22
- AbstractSet,
23
- Any,
20
+ from collections.abc import (
24
21
  Callable,
25
- cast,
26
- Generic,
27
22
  ItemsView,
28
23
  Iterable,
29
24
  Iterator,
30
25
  KeysView,
31
26
  Mapping,
32
- overload,
33
27
  Sequence,
34
- TYPE_CHECKING,
35
- TypeVar,
36
- Union,
28
+ Set,
37
29
  ValuesView,
38
30
  )
31
+ from types import NotImplementedType
32
+ from typing import Any, cast, Generic, overload, TYPE_CHECKING, TypeVar, Union
39
33
 
40
34
  import numpy as np
41
35
  import sympy
@@ -266,16 +260,9 @@ class PauliString(raw_types.Operation, Generic[TKey]):
266
260
  pass
267
261
 
268
262
  def __mul__(self, other):
269
- known = False
270
- if isinstance(other, raw_types.Operation) and isinstance(other.gate, identity.IdentityGate):
271
- known = True
272
- elif isinstance(other, (PauliString, numbers.Number)):
273
- known = True
274
- if known:
263
+ if isinstance(other, (PauliString, numbers.Number)):
275
264
  return PauliString(
276
- cast(PAULI_STRING_LIKE, other),
277
- qubit_pauli_map=self._qubit_pauli_map,
278
- coefficient=self.coefficient,
265
+ other, qubit_pauli_map=self._qubit_pauli_map, coefficient=self.coefficient
279
266
  )
280
267
  return NotImplemented
281
268
 
@@ -295,9 +282,6 @@ class PauliString(raw_types.Operation, Generic[TKey]):
295
282
  qubit_pauli_map=self._qubit_pauli_map, coefficient=self._coefficient * other
296
283
  )
297
284
 
298
- if isinstance(other, raw_types.Operation) and isinstance(other.gate, identity.IdentityGate):
299
- return self # pragma: no cover
300
-
301
285
  # Note: PauliString case handled by __mul__.
302
286
  return NotImplemented
303
287
 
@@ -1008,7 +992,7 @@ class PauliString(raw_types.Operation, Generic[TKey]):
1008
992
  """
1009
993
  return self.conjugated_by(ops)
1010
994
 
1011
- @deprecated(deadline="v2.0", fix="Use conjuagetd_by()/before()/after() instead.")
995
+ @deprecated(deadline="v2.0", fix="Use conjugated_by(), before(), or after() instead.")
1012
996
  def pass_operations_over(
1013
997
  self, ops: Iterable[cirq.Operation], after_to_before: bool = False
1014
998
  ) -> PauliString: # pragma: no cover
@@ -1050,7 +1034,7 @@ class PauliString(raw_types.Operation, Generic[TKey]):
1050
1034
  def _is_parameterized_(self) -> bool:
1051
1035
  return protocols.is_parameterized(self.coefficient)
1052
1036
 
1053
- def _parameter_names_(self) -> AbstractSet[str]:
1037
+ def _parameter_names_(self) -> Set[str]:
1054
1038
  return protocols.parameter_names(self.coefficient)
1055
1039
 
1056
1040
  def _resolve_parameters_(
@@ -1100,21 +1084,33 @@ def _validate_qubit_mapping(
1100
1084
  )
1101
1085
 
1102
1086
 
1103
- def _try_interpret_as_pauli_string(op: Any):
1087
+ def _try_interpret_as_pauli_string(op: Any) -> PauliString | None:
1104
1088
  """Return a reprepresentation of an operation as a pauli string, if it is possible."""
1105
- if isinstance(op, gate_operation.GateOperation):
1106
- gates = {
1107
- common_gates.XPowGate: pauli_gates.X,
1108
- common_gates.YPowGate: pauli_gates.Y,
1109
- common_gates.ZPowGate: pauli_gates.Z,
1110
- }
1111
- if (pauli := gates.get(type(op.gate), None)) is not None:
1112
- exponent = op.gate.exponent # type: ignore
1113
- if exponent % 2 == 0:
1114
- return PauliString()
1115
- if exponent % 2 == 1:
1116
- return pauli.on(op.qubits[0])
1117
- return None
1089
+ if not isinstance(op, raw_types.Operation):
1090
+ return None
1091
+
1092
+ if isinstance(op, PauliString):
1093
+ return op
1094
+
1095
+ # optimize for integer exponents of Pauli gates
1096
+ cached_gates: dict[type[cirq.Gate | None], cirq.Pauli] = {
1097
+ common_gates.XPowGate: pauli_gates.X,
1098
+ common_gates.YPowGate: pauli_gates.Y,
1099
+ common_gates.ZPowGate: pauli_gates.Z,
1100
+ }
1101
+ if (pauli := cached_gates.get(type(op.gate))) is not None:
1102
+ exponent = op.gate.exponent # type: ignore
1103
+ if exponent % 2 == 0:
1104
+ return PauliString()
1105
+ if exponent % 2 == 1:
1106
+ return pauli.on(op.qubits[0])
1107
+ return None
1108
+
1109
+ pauli_expansion_op = protocols.pauli_expansion(op, default=None)
1110
+ if pauli_expansion_op is None or len(pauli_expansion_op) != 1:
1111
+ return None
1112
+ gates, coef = next(iter(pauli_expansion_op.items()))
1113
+ return PauliString(dict(zip(op.qubits, gates)), coefficient=coef)
1118
1114
 
1119
1115
 
1120
1116
  # Ignoring type because mypy believes `with_qubits` methods are incompatible.
@@ -1148,27 +1144,11 @@ class SingleQubitPauliStringGateOperation( # type: ignore
1148
1144
  assert len(self.qubits) == 1
1149
1145
  return self.qubits[0]
1150
1146
 
1151
- def _as_pauli_string(self) -> PauliString:
1152
- return PauliString(qubit_pauli_map={self.qubit: self.pauli})
1153
-
1154
1147
  def __mul__(self, other):
1155
- if isinstance(other, SingleQubitPauliStringGateOperation):
1156
- return self._as_pauli_string() * other._as_pauli_string()
1157
- if isinstance(other, (PauliString, numbers.Complex)):
1158
- return self._as_pauli_string() * other
1159
- if (as_pauli_string := _try_interpret_as_pauli_string(other)) is not None:
1160
- return self * as_pauli_string
1161
- return NotImplemented
1148
+ return PauliString.__mul__(self, other)
1162
1149
 
1163
1150
  def __rmul__(self, other):
1164
- if isinstance(other, (PauliString, numbers.Complex)):
1165
- return other * self._as_pauli_string()
1166
- if (as_pauli_string := _try_interpret_as_pauli_string(other)) is not None:
1167
- return as_pauli_string * self
1168
- return NotImplemented
1169
-
1170
- def __neg__(self):
1171
- return -self._as_pauli_string()
1151
+ return PauliString.__rmul__(self, other)
1172
1152
 
1173
1153
  def _json_dict_(self) -> dict[str, Any]:
1174
1154
  return protocols.obj_to_dict_helper(self, ['pauli', 'qubit'])
@@ -1247,7 +1227,7 @@ class MutablePauliString(Generic[TKey]):
1247
1227
  return sign
1248
1228
  return -sign
1249
1229
 
1250
- def keys(self) -> AbstractSet[TKey]:
1230
+ def keys(self) -> Set[TKey]:
1251
1231
  """Returns the sequence of qubits on which this pauli string acts."""
1252
1232
  return self.pauli_int_dict.keys()
1253
1233
 
@@ -15,7 +15,8 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import numbers
18
- from typing import AbstractSet, cast, Iterable, Iterator, Sequence, TYPE_CHECKING
18
+ from collections.abc import Iterable, Iterator, Sequence, Set
19
+ from typing import cast, TYPE_CHECKING
19
20
 
20
21
  from cirq import protocols, value
21
22
  from cirq._compat import deprecated, proper_repr
@@ -73,9 +74,9 @@ class PauliStringPhasor(gate_operation.GateOperation):
73
74
  `pauli_string` are acted upon by identity. The order of
74
75
  these qubits must match the order in `pauli_string`.
75
76
  exponent_neg: How much to phase vectors in the negative eigenspace,
76
- in the form of the t in (-1)**t = exp(i pi t).
77
+ in the form of the t in ``(-1)**t = exp(i*pi*t)``.
77
78
  exponent_pos: How much to phase vectors in the positive eigenspace,
78
- in the form of the t in (-1)**t = exp(i pi t).
79
+ in the form of the t in ``(-1)**t = exp(i*pi*t)``.
79
80
 
80
81
  Raises:
81
82
  ValueError: If coefficient is not 1 or -1 or the qubits of
@@ -200,7 +201,7 @@ class PauliStringPhasor(gate_operation.GateOperation):
200
201
  pn = self.exponent_neg
201
202
  return PauliStringPhasor(new_pauli_string, exponent_pos=pp, exponent_neg=pn)
202
203
 
203
- @deprecated(deadline="v2.0", fix="Use conjuagetd_by() instead.")
204
+ @deprecated(deadline="v2.0", fix="Use conjugated_by() instead.")
204
205
  def pass_operations_over(
205
206
  self, ops: Iterable[raw_types.Operation], after_to_before: bool = False
206
207
  ) -> PauliStringPhasor: # pragma: no cover
@@ -388,7 +389,7 @@ class PauliStringPhasorGate(raw_types.Gate):
388
389
  self.exponent_pos
389
390
  )
390
391
 
391
- def _parameter_names_(self) -> AbstractSet[str]:
392
+ def _parameter_names_(self) -> Set[str]:
392
393
  return protocols.parameter_names(self.exponent_neg) | protocols.parameter_names(
393
394
  self.exponent_pos
394
395
  )
@@ -15,7 +15,8 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import abc
18
- from typing import Any, Self, Sequence, TYPE_CHECKING
18
+ from collections.abc import Sequence
19
+ from typing import Any, Self, TYPE_CHECKING
19
20
 
20
21
  from cirq import protocols
21
22
  from cirq.ops import pauli_string as ps, raw_types
@@ -16,7 +16,7 @@ from __future__ import annotations
16
16
 
17
17
  import itertools
18
18
  import math
19
- from typing import Iterator
19
+ from collections.abc import Iterator
20
20
 
21
21
  import numpy as np
22
22
  import pytest
@@ -323,6 +323,7 @@ def test_constructor_flexibility() -> None:
323
323
  @pytest.mark.parametrize('qubit_pauli_map', _sample_qubit_pauli_maps())
324
324
  def test_getitem(qubit_pauli_map) -> None:
325
325
  other = cirq.NamedQubit('other')
326
+ pauli_string: cirq.PauliString[cirq.NamedQubit]
326
327
  pauli_string = cirq.PauliString(qubit_pauli_map=qubit_pauli_map)
327
328
  for key in qubit_pauli_map:
328
329
  assert qubit_pauli_map[key] == pauli_string[key]
@@ -1190,7 +1191,7 @@ def test_expectation_from_density_matrix_invalid_input() -> None:
1190
1191
  with pytest.raises(ValueError, match='shape'):
1191
1192
  ps.expectation_from_density_matrix(rho.reshape((4, 4, 1)), q_map_2)
1192
1193
  with pytest.raises(ValueError, match='shape'):
1193
- ps.expectation_from_density_matrix(rho.reshape((-1)), q_map_2)
1194
+ ps.expectation_from_density_matrix(rho.reshape((-1,)), q_map_2)
1194
1195
 
1195
1196
  # Correctly shaped state_vectors.
1196
1197
  with pytest.raises(ValueError, match='shape'):
@@ -2085,15 +2086,57 @@ def test_resolve(resolve_fn) -> None:
2085
2086
  ids=str,
2086
2087
  )
2087
2088
  def test_pauli_ops_identity_gate_operation(gate1: cirq.Pauli, gate2: cirq.Pauli) -> None:
2088
- # TODO: Issue #7280 - Support addition and subtraction of identity gate operations.
2089
- if gate1 == gate2 == cirq.I:
2090
- pytest.skip('Not yet implemented per #7280')
2091
2089
  q = cirq.LineQubit(0)
2092
2090
  pauli1, pauli2 = gate1.on(q), gate2.on(q)
2093
- unitary1, unitary2 = cirq.unitary(gate1), cirq.unitary(gate2)
2091
+ if gate1 == gate2 == cirq.I:
2092
+ # PauliSum swallows I qubits, so resulting unitaries are dimensionless
2093
+ unitary1 = unitary2 = np.array([[1]])
2094
+ else:
2095
+ unitary1, unitary2 = cirq.unitary(gate1), cirq.unitary(gate2)
2094
2096
  addition = pauli1 + pauli2
2095
2097
  assert isinstance(addition, cirq.PauliSum)
2096
2098
  assert np.array_equal(addition.matrix(), unitary1 + unitary2)
2097
2099
  subtraction = pauli1 - pauli2
2098
2100
  assert isinstance(subtraction, cirq.PauliSum)
2099
2101
  assert np.array_equal(subtraction.matrix(), unitary1 - unitary2)
2102
+
2103
+
2104
+ def test_pauli_gate_multiplication_with_power() -> None:
2105
+ q = cirq.LineQubit(0)
2106
+
2107
+ # Test all Pauli gates (X, Y, Z)
2108
+ pauli_gates = [cirq.X, cirq.Y, cirq.Z]
2109
+ for pauli_gate in pauli_gates:
2110
+ gate = pauli_gate(q)
2111
+
2112
+ # Test multiplication
2113
+ assert gate**2 * gate * gate * gate == gate**5
2114
+ assert gate * gate**2 * gate * gate == gate**5
2115
+ assert gate * gate * gate**2 * gate == gate**5
2116
+ assert gate * gate * gate * gate**2 == gate**5
2117
+
2118
+ # Test with different powers
2119
+ assert gate**0 * gate**5 == gate**5
2120
+ assert gate**1 * gate**4 == gate**5
2121
+ assert gate**2 * gate**3 == gate**5
2122
+ assert gate**3 * gate**2 == gate**5
2123
+ assert gate**4 * gate**1 == gate**5
2124
+ assert gate**5 * gate**0 == gate**5
2125
+
2126
+
2127
+ def test_try_interpret_as_pauli_string() -> None:
2128
+ from cirq.ops.pauli_string import _try_interpret_as_pauli_string
2129
+
2130
+ q = cirq.LineQubit(0)
2131
+
2132
+ # Pauli gate operation
2133
+ x_gate = cirq.X(q)
2134
+ assert _try_interpret_as_pauli_string(x_gate) == cirq.PauliString({q: cirq.X})
2135
+
2136
+ # powered gates
2137
+ x_squared = x_gate**2
2138
+ assert _try_interpret_as_pauli_string(x_squared) == cirq.PauliString({q: cirq.I})
2139
+
2140
+ # non-Pauli operation
2141
+ h_gate = cirq.H(q)
2142
+ assert _try_interpret_as_pauli_string(h_gate) is None
@@ -14,7 +14,8 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import Any, Iterator, TYPE_CHECKING
17
+ from collections.abc import Iterator
18
+ from typing import Any, TYPE_CHECKING
18
19
 
19
20
  import numpy as np
20
21
 
@@ -14,7 +14,8 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import Any, Iterator, Sequence, TYPE_CHECKING
17
+ from collections.abc import Iterator, Sequence
18
+ from typing import Any, TYPE_CHECKING
18
19
 
19
20
  from cirq import protocols, value
20
21
  from cirq.ops import raw_types, swap_gates
@@ -15,7 +15,8 @@
15
15
 
16
16
  from __future__ import annotations
17
17
 
18
- from typing import AbstractSet, Any, cast, Iterator, Sequence
18
+ from collections.abc import Iterator, Sequence, Set
19
+ from typing import Any, cast
19
20
 
20
21
  import numpy as np
21
22
  import sympy
@@ -108,7 +109,7 @@ class PhasedISwapPowGate(eigen_gate.EigenGate):
108
109
  self._phase_exponent
109
110
  )
110
111
 
111
- def _parameter_names_(self) -> AbstractSet[str]:
112
+ def _parameter_names_(self) -> Set[str]:
112
113
  return protocols.parameter_names(self._iswap) | protocols.parameter_names(
113
114
  self._phase_exponent
114
115
  )
cirq/ops/phased_x_gate.py CHANGED
@@ -18,8 +18,9 @@ from __future__ import annotations
18
18
 
19
19
  import math
20
20
  import numbers
21
+ from collections.abc import Sequence, Set
21
22
  from types import NotImplementedType
22
- from typing import AbstractSet, Any, cast, Sequence
23
+ from typing import Any, cast
23
24
 
24
25
  import numpy as np
25
26
  import sympy
@@ -166,7 +167,7 @@ class PhasedXPowGate(raw_types.Gate):
166
167
  self._phase_exponent
167
168
  )
168
169
 
169
- def _parameter_names_(self) -> AbstractSet[str]:
170
+ def _parameter_names_(self) -> Set[str]:
170
171
  """See `cirq.SupportsParameterization`."""
171
172
  return protocols.parameter_names(self._exponent) | protocols.parameter_names(
172
173
  self._phase_exponent
@@ -176,12 +177,12 @@ class PhasedXPowGate(raw_types.Gate):
176
177
  """See `cirq.SupportsParameterization`."""
177
178
  phase_exponent = resolver.value_of(self._phase_exponent, recursive)
178
179
  exponent = resolver.value_of(self._exponent, recursive)
179
- if isinstance(phase_exponent, numbers.Complex):
180
+ if not isinstance(phase_exponent, float) and isinstance(phase_exponent, numbers.Complex):
180
181
  if isinstance(phase_exponent, numbers.Real):
181
182
  phase_exponent = float(phase_exponent)
182
183
  else:
183
184
  raise ValueError(f'PhasedXPowGate does not support complex value {phase_exponent}')
184
- if isinstance(exponent, numbers.Complex):
185
+ if not isinstance(exponent, float) and isinstance(exponent, numbers.Complex):
185
186
  if isinstance(exponent, numbers.Real):
186
187
  exponent = float(exponent)
187
188
  else: