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
cirq/__init__.py CHANGED
@@ -509,6 +509,7 @@ from cirq.study import (
509
509
  flatten_with_sweep as flatten_with_sweep,
510
510
  ResultDict as ResultDict,
511
511
  Linspace as Linspace,
512
+ list_of_dicts_to_zip as list_of_dicts_to_zip,
512
513
  ListSweep as ListSweep,
513
514
  ParamDictType as ParamDictType,
514
515
  ParamMappingType as ParamMappingType,
cirq/_compat.py CHANGED
@@ -20,15 +20,16 @@ import contextlib
20
20
  import contextvars
21
21
  import dataclasses
22
22
  import functools
23
- import importlib
23
+ import importlib.util
24
24
  import inspect
25
25
  import os
26
26
  import re
27
27
  import sys
28
28
  import traceback
29
29
  import warnings
30
+ from collections.abc import Callable, Iterator
30
31
  from types import ModuleType
31
- from typing import Any, Callable, Iterator, overload, TypeVar
32
+ from typing import Any, overload, TypeVar
32
33
 
33
34
  import numpy as np
34
35
  import pandas as pd
cirq/_compat_test.py CHANGED
@@ -25,9 +25,10 @@ import sys
25
25
  import traceback
26
26
  import types
27
27
  import warnings
28
+ from collections.abc import Callable
28
29
  from importlib.machinery import ModuleSpec
29
30
  from types import ModuleType
30
- from typing import Any, Callable
31
+ from typing import Any
31
32
  from unittest import mock
32
33
 
33
34
  import duet
@@ -159,7 +160,7 @@ def test_deprecated_with_name():
159
160
 
160
161
 
161
162
  def test_deprecated_with_property():
162
- class AClass(object):
163
+ class AClass:
163
164
  def __init__(self, a):
164
165
  self.a = a
165
166
 
@@ -554,11 +555,11 @@ def _import_deprecated_same_name_in_earlier_subtree():
554
555
 
555
556
 
556
557
  def _import_top_level_deprecated():
557
- import time
558
+ import numpy.random
558
559
 
559
- from cirq.testing._compat_test_data.fake_freezegun import api # type: ignore
560
+ from cirq.testing._compat_test_data.fake_numpy import random # type: ignore
560
561
 
561
- assert api.real_time == time.time
562
+ assert random.normal is numpy.random.normal
562
563
 
563
564
 
564
565
  def _repeated_import_path():
@@ -611,9 +612,9 @@ _fake_ops_deprecation_msg = [
611
612
 
612
613
 
613
614
  # see cirq_compat_test_data/__init__.py for the setup code
614
- _fake_freezegun_deprecation_msg = [
615
- f'{old_parent}.fake_freezegun was used but is deprecated',
616
- 'Use freezegun instead',
615
+ _fake_numpy_deprecation_msg = [
616
+ f'{old_parent}.fake_numpy was used but is deprecated',
617
+ 'Use numpy instead',
617
618
  ] + _deprecation_origin
618
619
 
619
620
  # see cirq_compat_test_data/__init__.py for the setup code
@@ -686,7 +687,7 @@ def run_in_subprocess(test_func, *args):
686
687
  (_import_parent_use_constant_from_deprecated_module_attribute, [_fake_a_deprecation_msg]),
687
688
  (_import_deprecated_sub_use_constant, [_fake_a_deprecation_msg]),
688
689
  (_import_deprecated_same_name_in_earlier_subtree, [_fake_a_deprecation_msg]),
689
- (_import_top_level_deprecated, [_fake_freezegun_deprecation_msg]),
690
+ (_import_top_level_deprecated, [_fake_numpy_deprecation_msg]),
690
691
  (_from_deprecated_import_sub_of_sub, [_fake_a_deprecation_msg]),
691
692
  (_repeated_import_path, [_repeated_child_deprecation_msg]),
692
693
  (_type_repr_in_deprecated_module, [_fake_a_deprecation_msg]),
@@ -746,7 +747,7 @@ def test_metadata_search_path():
746
747
  run_in_subprocess(_test_metadata_search_path_inner)
747
748
 
748
749
 
749
- def _test_metadata_search_path_inner(): # pragma: no cover
750
+ def _test_metadata_search_path_inner():
750
751
  # initialize the DeprecatedModuleFinders
751
752
  assert importlib.metadata.metadata('numpy')
752
753
 
@@ -855,13 +856,13 @@ def test_new_module_is_top_level():
855
856
 
856
857
 
857
858
  def _test_new_module_is_top_level_inner():
858
- # sets up the DeprecationFinders
859
- import time
859
+ from numpy.random import normal
860
860
 
861
- # imports a top level module that was also deprecated
862
- from freezegun import api
861
+ # sets up the DeprecationFinders
862
+ import cirq.testing._compat_test_data # noqa: F401
863
863
 
864
- assert api.real_time == time.time
864
+ # imports a top level new module replacing deprecated module
865
+ assert normal is importlib.import_module('numpy').random.normal
865
866
 
866
867
 
867
868
  def test_import_deprecated_with_no_attribute():
cirq/_doc.py CHANGED
@@ -15,12 +15,13 @@
15
15
 
16
16
  from __future__ import annotations
17
17
 
18
- from typing import Any
18
+ from typing import TypeVar
19
19
 
20
+ T = TypeVar('T')
20
21
  RECORDED_CONST_DOCS: dict[int, str] = {}
21
22
 
22
23
 
23
- def document(value: Any, doc_string: str = ''):
24
+ def document(value: T, doc_string: str = '') -> T:
24
25
  """Stores documentation details about the given value.
25
26
 
26
27
  This method is used to associate a docstring with global constants. It is
@@ -64,7 +65,7 @@ def document(value: Any, doc_string: str = ''):
64
65
  _DOC_PRIVATE = "_tf_docs_doc_private"
65
66
 
66
67
 
67
- def doc_private(obj):
68
+ def doc_private(obj: T) -> T:
68
69
  """A decorator: Generates docs for private methods/functions.
69
70
 
70
71
  For example:
cirq/_import.py CHANGED
@@ -16,12 +16,13 @@ from __future__ import annotations
16
16
 
17
17
  import importlib
18
18
  import sys
19
+ from collections.abc import Callable
19
20
  from contextlib import contextmanager
20
21
  from importlib import abc
21
22
  from importlib.abc import Loader
22
23
  from importlib.machinery import ModuleSpec
23
24
  from types import ModuleType
24
- from typing import Any, Callable, cast
25
+ from typing import Any, cast
25
26
 
26
27
 
27
28
  class InstrumentedFinder(abc.MetaPathFinder):
cirq/_version.py CHANGED
@@ -28,4 +28,4 @@ if sys.version_info < (3, 11, 0): # pragma: no cover
28
28
  'of Cirq (e.g. "python -m pip install cirq==1.5.0")'
29
29
  )
30
30
 
31
- __version__ = "1.7.0.dev20250825174419"
31
+ __version__ = "1.7.0.dev20251203004401"
cirq/_version_test.py CHANGED
@@ -3,4 +3,4 @@ import cirq
3
3
 
4
4
 
5
5
  def test_version() -> None:
6
- assert cirq.__version__ == "1.7.0.dev20250825174419"
6
+ assert cirq.__version__ == "1.7.0.dev20251203004401"
@@ -14,7 +14,8 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import Any, Generic, Iterable, Iterator, TypeVar
17
+ from collections.abc import Iterable, Iterator
18
+ from typing import Any, Generic, TypeVar
18
19
 
19
20
  TItem = TypeVar('TItem')
20
21
 
cirq/circuits/circuit.py CHANGED
@@ -27,24 +27,18 @@ import html
27
27
  import itertools
28
28
  import math
29
29
  from collections import defaultdict
30
- from types import NotImplementedType
31
- from typing import (
32
- AbstractSet,
33
- Any,
30
+ from collections.abc import (
34
31
  Callable,
35
- cast,
36
32
  Hashable,
37
33
  Iterable,
38
34
  Iterator,
39
35
  Mapping,
40
36
  MutableSequence,
41
- overload,
42
- Self,
43
37
  Sequence,
44
- TYPE_CHECKING,
45
- TypeVar,
46
- Union,
38
+ Set,
47
39
  )
40
+ from types import NotImplementedType
41
+ from typing import Any, cast, overload, Self, TYPE_CHECKING, TypeVar, Union
48
42
 
49
43
  import networkx
50
44
  import numpy as np
@@ -1341,7 +1335,7 @@ class AbstractCircuit(abc.ABC):
1341
1335
  protocols.is_parameterized(tag) for tag in self.tags
1342
1336
  )
1343
1337
 
1344
- def _parameter_names_(self) -> AbstractSet[str]:
1338
+ def _parameter_names_(self) -> Set[str]:
1345
1339
  op_params = {name for op in self.all_operations() for name in protocols.parameter_names(op)}
1346
1340
  tag_params = {name for tag in self.tags for name in protocols.parameter_names(tag)}
1347
1341
  return op_params | tag_params
@@ -1666,8 +1660,14 @@ class AbstractCircuit(abc.ABC):
1666
1660
  )
1667
1661
 
1668
1662
  def _control_keys_(self) -> frozenset[cirq.MeasurementKey]:
1669
- controls = frozenset(k for op in self.all_operations() for k in protocols.control_keys(op))
1670
- return controls - protocols.measurement_key_objs(self)
1663
+ measures: set[cirq.MeasurementKey] = set()
1664
+ controls: set[cirq.MeasurementKey] = set()
1665
+ for op in self.all_operations():
1666
+ # Only require keys that haven't already been measured earlier
1667
+ controls.update(k for k in protocols.control_keys(op) if k not in measures)
1668
+ # Record any measurement keys produced by this op
1669
+ measures.update(protocols.measurement_key_objs(op))
1670
+ return frozenset(controls)
1671
1671
 
1672
1672
 
1673
1673
  def _overlap_collision_time(
@@ -1839,7 +1839,7 @@ class Circuit(AbstractCircuit):
1839
1839
  self._frozen: cirq.FrozenCircuit | None = None
1840
1840
  self._is_measurement: bool | None = None
1841
1841
  self._is_parameterized: bool | None = None
1842
- self._parameter_names: AbstractSet[str] | None = None
1842
+ self._parameter_names: Set[str] | None = None
1843
1843
  if not contents:
1844
1844
  return
1845
1845
  flattened_contents = tuple(ops.flatten_to_ops_or_moments(contents))
@@ -1948,7 +1948,7 @@ class Circuit(AbstractCircuit):
1948
1948
  self._is_parameterized = super()._is_parameterized_()
1949
1949
  return self._is_parameterized
1950
1950
 
1951
- def _parameter_names_(self) -> AbstractSet[str]:
1951
+ def _parameter_names_(self) -> Set[str]:
1952
1952
  if self._parameter_names is None:
1953
1953
  self._parameter_names = super()._parameter_names_()
1954
1954
  return self._parameter_names
@@ -3002,13 +3002,15 @@ def get_earliest_accommodating_moment_index(
3002
3002
  mop_index = last_conflict + 1
3003
3003
 
3004
3004
  # Update our dicts with data from this `mop` placement. Note `mop_index` will always be greater
3005
- # than the existing value for all of these, by construction.
3005
+ # than the existing value for qubits and measurement keys, by construction.
3006
3006
  for qubit in mop_qubits:
3007
3007
  qubit_indices[qubit] = mop_index
3008
3008
  for key in mop_mkeys:
3009
3009
  mkey_indices[key] = mop_index
3010
+ # For control keys, keep the maximum moment index seen so far because ops with the same control
3011
+ # keys can commute past each other.
3010
3012
  for key in mop_ckeys:
3011
- ckey_indices[key] = mop_index
3013
+ ckey_indices[key] = max(mop_index, ckey_indices.get(key, -1))
3012
3014
 
3013
3015
  return mop_index
3014
3016
 
@@ -22,8 +22,9 @@ component operations in order, including any nested CircuitOperations.
22
22
  from __future__ import annotations
23
23
 
24
24
  import math
25
+ from collections.abc import Callable, Iterator, Mapping, Sequence
25
26
  from functools import cached_property
26
- from typing import Any, Callable, cast, Iterator, Mapping, Sequence, TYPE_CHECKING, TypeAlias
27
+ from typing import Any, cast, TYPE_CHECKING, TypeAlias
27
28
 
28
29
  import numpy as np
29
30
  import sympy
@@ -1253,22 +1253,27 @@ def test_repeat_until_protocols() -> None:
1253
1253
  # Ensure the _repeat_until has been mapped, the measurement has been mapped to the same key,
1254
1254
  # and the control keys of the subcircuit is empty (because the control key of the condition is
1255
1255
  # bound to the measurement).
1256
+ assert scoped._mapped_repeat_until is not None
1256
1257
  assert scoped._mapped_repeat_until.keys == (cirq.MeasurementKey('a', ('0',)),)
1257
1258
  assert cirq.measurement_key_objs(scoped) == {cirq.MeasurementKey('a', ('0',))}
1258
1259
  assert not cirq.control_keys(scoped)
1259
1260
  mapped = cirq.with_measurement_key_mapping(scoped, {'a': 'b'})
1261
+ assert mapped._mapped_repeat_until is not None
1260
1262
  assert mapped._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('0',)),)
1261
1263
  assert cirq.measurement_key_objs(mapped) == {cirq.MeasurementKey('b', ('0',))}
1262
1264
  assert not cirq.control_keys(mapped)
1263
1265
  prefixed = cirq.with_key_path_prefix(mapped, ('1',))
1266
+ assert prefixed._mapped_repeat_until is not None
1264
1267
  assert prefixed._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('1', '0')),)
1265
1268
  assert cirq.measurement_key_objs(prefixed) == {cirq.MeasurementKey('b', ('1', '0'))}
1266
1269
  assert not cirq.control_keys(prefixed)
1267
1270
  setpath = cirq.with_key_path(prefixed, ('2',))
1271
+ assert setpath._mapped_repeat_until is not None
1268
1272
  assert setpath._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('2',)),)
1269
1273
  assert cirq.measurement_key_objs(setpath) == {cirq.MeasurementKey('b', ('2',))}
1270
1274
  assert not cirq.control_keys(setpath)
1271
1275
  resolved = cirq.resolve_parameters(setpath, {'p': 1})
1276
+ assert resolved._mapped_repeat_until is not None
1272
1277
  assert resolved._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('2',)),)
1273
1278
  assert cirq.measurement_key_objs(resolved) == {cirq.MeasurementKey('b', ('2',))}
1274
1279
  assert not cirq.control_keys(resolved)
@@ -1324,3 +1329,17 @@ def test_has_unitary_protocol_returns_true_if_all_params_resolve() -> None:
1324
1329
  exp = sympy.Symbol('exp')
1325
1330
  op = cirq.CircuitOperation(cirq.FrozenCircuit(cirq.X(q) ** exp), param_resolver={exp: 0.5})
1326
1331
  assert protocols.has_unitary(op)
1332
+
1333
+
1334
+ def test_control_keys_respects_internal_measurement_order() -> None:
1335
+ q = cirq.LineQubit(0)
1336
+
1337
+ # Control BEFORE measurement inside the subcircuit: external key required
1338
+ fc_before = cirq.FrozenCircuit(cirq.X(q).with_classical_controls('a'), cirq.measure(q, key='a'))
1339
+ op_before = cirq.CircuitOperation(fc_before)
1340
+ assert cirq.control_keys(op_before) == {cirq.MeasurementKey('a')}
1341
+
1342
+ # Measurement BEFORE control inside the subcircuit: no external key required
1343
+ fc_after = cirq.FrozenCircuit(cirq.measure(q, key='a'), cirq.X(q).with_classical_controls('a'))
1344
+ op_after = cirq.CircuitOperation(fc_after)
1345
+ assert cirq.control_keys(op_after) == set()
@@ -18,8 +18,8 @@ import itertools
18
18
  import os
19
19
  import time
20
20
  from collections import defaultdict
21
+ from collections.abc import Iterator, Sequence
21
22
  from random import randint, random, randrange, sample
22
- from typing import Iterator, Sequence
23
23
 
24
24
  import numpy as np
25
25
  import pytest
@@ -208,6 +208,24 @@ def test_append_control_key() -> None:
208
208
  assert len(c) == 1
209
209
 
210
210
 
211
+ def test_append_control_key_before_measure() -> None:
212
+ c = cirq.Circuit()
213
+ q1, q2 = cirq.LineQubit.range(2)
214
+ c.append(cirq.X(q1))
215
+ c.append(cirq.X(q1))
216
+ c.append(cirq.X(q1).with_classical_controls('a'))
217
+ c.append(cirq.X(q2).with_classical_controls('a'))
218
+ c.append(cirq.measure(q2, key='a'))
219
+ assert c == cirq.Circuit(
220
+ [
221
+ cirq.Moment(cirq.X(q1), cirq.X(q2).with_classical_controls('a')),
222
+ cirq.Moment(cirq.X(q1)),
223
+ cirq.Moment(cirq.X(q1).with_classical_controls('a')),
224
+ cirq.Moment(cirq.measure(q2, key='a')),
225
+ ]
226
+ )
227
+
228
+
211
229
  def test_append_multiple() -> None:
212
230
  a = cirq.NamedQubit('a')
213
231
  b = cirq.NamedQubit('b')
@@ -338,20 +356,21 @@ def test_add_op_tree(circuit_cls) -> None:
338
356
 
339
357
 
340
358
  @pytest.mark.parametrize('circuit_cls', [cirq.Circuit, cirq.FrozenCircuit])
341
- def test_radd_op_tree(circuit_cls) -> None:
359
+ @pytest.mark.parametrize('gate', [cirq.X, cirq.H])
360
+ def test_radd_op_tree(circuit_cls, gate) -> None:
342
361
  a = cirq.NamedQubit('a')
343
362
  b = cirq.NamedQubit('b')
344
363
 
345
364
  c = circuit_cls()
346
- assert [cirq.X(a), cirq.Y(b)] + c == circuit_cls([cirq.Moment([cirq.X(a), cirq.Y(b)])])
365
+ assert [gate(a), cirq.Y(b)] + c == circuit_cls([cirq.Moment([gate(a), cirq.Y(b)])])
347
366
 
348
- assert cirq.X(a) + c == circuit_cls(cirq.X(a))
349
- assert [cirq.X(a)] + c == circuit_cls(cirq.X(a))
350
- assert [[[cirq.X(a)], []]] + c == circuit_cls(cirq.X(a))
351
- assert (cirq.X(a),) + c == circuit_cls(cirq.X(a))
352
- assert (cirq.X(a) for _ in range(1)) + c == circuit_cls(cirq.X(a))
367
+ assert gate(a) + c == circuit_cls(gate(a))
368
+ assert [gate(a)] + c == circuit_cls(gate(a))
369
+ assert [[[gate(a)], []]] + c == circuit_cls(gate(a))
370
+ assert (gate(a),) + c == circuit_cls(gate(a))
371
+ assert (gate(a) for _ in range(1)) + c == circuit_cls(gate(a))
353
372
  with pytest.raises(AttributeError):
354
- _ = cirq.X + c
373
+ _ = gate + c
355
374
  with pytest.raises(TypeError):
356
375
  _ = 0 + c
357
376
 
@@ -362,9 +381,9 @@ def test_radd_op_tree(circuit_cls) -> None:
362
381
  else:
363
382
  d = cirq.Circuit()
364
383
  d.append(cirq.Y(b))
365
- assert [cirq.X(a)] + d == circuit_cls([cirq.Moment([cirq.X(a)]), cirq.Moment([cirq.Y(b)])])
366
- assert cirq.Moment([cirq.X(a)]) + d == circuit_cls(
367
- [cirq.Moment([cirq.X(a)]), cirq.Moment([cirq.Y(b)])]
384
+ assert [gate(a)] + d == circuit_cls([cirq.Moment([gate(a)]), cirq.Moment([cirq.Y(b)])])
385
+ assert cirq.Moment([gate(a)]) + d == circuit_cls(
386
+ [cirq.Moment([gate(a)]), cirq.Moment([cirq.Y(b)])]
368
387
  )
369
388
 
370
389
 
@@ -16,9 +16,10 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
+ from collections.abc import Hashable, Iterable, Iterator, Sequence, Set
19
20
  from functools import cached_property
20
21
  from types import NotImplementedType
21
- from typing import AbstractSet, Hashable, Iterable, Iterator, Sequence, TYPE_CHECKING
22
+ from typing import TYPE_CHECKING
22
23
 
23
24
  from cirq import _compat, protocols
24
25
  from cirq.circuits import AbstractCircuit, Alignment, Circuit
@@ -172,7 +173,7 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
172
173
  return super()._is_parameterized_()
173
174
 
174
175
  @_compat.cached_method
175
- def _parameter_names_(self) -> AbstractSet[str]:
176
+ def _parameter_names_(self) -> Set[str]:
176
177
  return super()._parameter_names_()
177
178
 
178
179
  def _measurement_key_names_(self) -> frozenset[str]:
cirq/circuits/moment.py CHANGED
@@ -17,22 +17,10 @@
17
17
  from __future__ import annotations
18
18
 
19
19
  import itertools
20
+ from collections.abc import Callable, Hashable, Iterable, Iterator, Mapping, Sequence, Set
20
21
  from functools import cached_property
21
22
  from types import NotImplementedType
22
- from typing import (
23
- AbstractSet,
24
- Any,
25
- Callable,
26
- cast,
27
- Hashable,
28
- Iterable,
29
- Iterator,
30
- Mapping,
31
- overload,
32
- Self,
33
- Sequence,
34
- TYPE_CHECKING,
35
- )
23
+ from typing import Any, cast, overload, Self, TYPE_CHECKING
36
24
 
37
25
  import numpy as np
38
26
 
@@ -307,7 +295,7 @@ class Moment:
307
295
  return any(protocols.is_parameterized(op) for op in self)
308
296
 
309
297
  @_compat.cached_method()
310
- def _parameter_names_(self) -> AbstractSet[str]:
298
+ def _parameter_names_(self) -> Set[str]:
311
299
  return {name for op in self for name in protocols.parameter_names(op)}
312
300
 
313
301
  def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> cirq.Moment:
@@ -18,7 +18,8 @@ from __future__ import annotations
18
18
 
19
19
  import abc
20
20
  from collections import defaultdict
21
- from typing import Callable, cast, Iterable, Sequence, TYPE_CHECKING
21
+ from collections.abc import Callable, Iterable, Sequence
22
+ from typing import cast, TYPE_CHECKING
22
23
 
23
24
  from cirq import ops
24
25
 
@@ -17,11 +17,14 @@
17
17
  from __future__ import annotations
18
18
 
19
19
  import re
20
- from typing import Callable, Iterator, Sequence, TYPE_CHECKING
20
+ from collections.abc import Callable, Iterator, Sequence, Set
21
+ from typing import TYPE_CHECKING
21
22
 
22
23
  import numpy as np
24
+ import sympy
23
25
 
24
26
  from cirq import linalg, ops, protocols, value
27
+ from cirq._compat import proper_repr
25
28
 
26
29
  if TYPE_CHECKING:
27
30
  import cirq
@@ -29,7 +32,7 @@ if TYPE_CHECKING:
29
32
 
30
33
  @value.value_equality(approximate=True)
31
34
  class QasmUGate(ops.Gate):
32
- def __init__(self, theta, phi, lmda) -> None:
35
+ def __init__(self, theta: cirq.TParamVal, phi: cirq.TParamVal, lmda: cirq.TParamVal) -> None:
33
36
  """A QASM gate representing any single qubit unitary with a series of
34
37
  three rotations, Z, Y, and Z.
35
38
 
@@ -40,9 +43,9 @@ class QasmUGate(ops.Gate):
40
43
  phi: Half turns to rotate about Z (applied last).
41
44
  lmda: Half turns to rotate about Z (applied first).
42
45
  """
43
- self.lmda = lmda % 2
44
46
  self.theta = theta % 2
45
47
  self.phi = phi % 2
48
+ self.lmda = lmda % 2
46
49
 
47
50
  def _num_qubits_(self) -> int:
48
51
  return 1
@@ -53,7 +56,28 @@ class QasmUGate(ops.Gate):
53
56
  return QasmUGate(rotation / np.pi, post_phase / np.pi, pre_phase / np.pi)
54
57
 
55
58
  def _has_unitary_(self):
56
- return True
59
+ return not self._is_parameterized_()
60
+
61
+ def _is_parameterized_(self) -> bool:
62
+ return (
63
+ protocols.is_parameterized(self.theta)
64
+ or protocols.is_parameterized(self.phi)
65
+ or protocols.is_parameterized(self.lmda)
66
+ )
67
+
68
+ def _parameter_names_(self) -> Set[str]:
69
+ return (
70
+ protocols.parameter_names(self.theta)
71
+ | protocols.parameter_names(self.phi)
72
+ | protocols.parameter_names(self.lmda)
73
+ )
74
+
75
+ def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> QasmUGate:
76
+ return QasmUGate(
77
+ protocols.resolve_parameters(self.theta, resolver, recursive),
78
+ protocols.resolve_parameters(self.phi, resolver, recursive),
79
+ protocols.resolve_parameters(self.lmda, resolver, recursive),
80
+ )
57
81
 
58
82
  def _qasm_(self, qubits: tuple[cirq.Qid, ...], args: cirq.QasmArgs) -> str:
59
83
  args.validate_version('2.0', '3.0')
@@ -68,17 +92,22 @@ class QasmUGate(ops.Gate):
68
92
  def __repr__(self) -> str:
69
93
  return (
70
94
  f'cirq.circuits.qasm_output.QasmUGate('
71
- f'theta={self.theta!r}, '
72
- f'phi={self.phi!r}, '
73
- f'lmda={self.lmda})'
95
+ f'theta={proper_repr(self.theta)}, '
96
+ f'phi={proper_repr(self.phi)}, '
97
+ f'lmda={proper_repr(self.lmda)})'
74
98
  )
75
99
 
76
100
  def _decompose_(self, qubits):
101
+ def mul_pi(x):
102
+ return x * (sympy.pi if protocols.is_parameterized(x) else np.pi)
103
+
77
104
  q = qubits[0]
105
+ phase_correction_half_turns = (self.phi + self.lmda) / 2
78
106
  return [
79
- ops.rz(self.lmda * np.pi).on(q),
80
- ops.ry(self.theta * np.pi).on(q),
81
- ops.rz(self.phi * np.pi).on(q),
107
+ ops.rz(mul_pi(self.lmda)).on(q),
108
+ ops.ry(mul_pi(self.theta)).on(q),
109
+ ops.rz(mul_pi(self.phi)).on(q),
110
+ ops.global_phase_operation(1j ** (2 * phase_correction_half_turns)),
82
111
  ]
83
112
 
84
113
  def _value_equality_values_(self):
@@ -19,6 +19,7 @@ import re
19
19
 
20
20
  import numpy as np
21
21
  import pytest
22
+ import sympy
22
23
 
23
24
  import cirq
24
25
  from cirq.circuits.qasm_output import QasmTwoQubitGate, QasmUGate
@@ -29,6 +30,17 @@ def _make_qubits(n):
29
30
  return [cirq.NamedQubit(f'q{i}') for i in range(n)]
30
31
 
31
32
 
33
+ def _qiskit_ugate_unitary(gate: QasmUGate) -> np.ndarray:
34
+ # Ref: https://quantum.cloud.ibm.com/docs/en/api/qiskit/qiskit.circuit.library.U3Gate#u3gate
35
+ th, ph, lm = np.pi * np.array([gate.theta, gate.phi, gate.lmda])
36
+ return np.array(
37
+ [
38
+ [np.cos(th / 2), -np.exp(1j * lm) * np.sin(th / 2)],
39
+ [np.exp(1j * ph) * np.sin(th / 2), np.exp(1j * (ph + lm)) * np.cos(th / 2)],
40
+ ]
41
+ )
42
+
43
+
32
44
  def test_u_gate_repr() -> None:
33
45
  gate = QasmUGate(0.1, 0.2, 0.3)
34
46
  assert repr(gate) == 'cirq.circuits.qasm_output.QasmUGate(theta=0.1, phi=0.2, lmda=0.3)'
@@ -43,6 +55,42 @@ def test_u_gate_eq() -> None:
43
55
  cirq.approx_eq(gate4, gate3, atol=1e-16)
44
56
 
45
57
 
58
+ @pytest.mark.parametrize("_", range(10))
59
+ def test_u_gate_from_qiskit_ugate_unitary(_) -> None:
60
+ # QasmUGate at (theta, phi, lmda) is the same as QasmUGate at
61
+ # (2 - theta, phi + 1, lmda + 1) and a global phase factor of -1.
62
+ # QasmUGate.from_matrix resolves theta at [0, 1] and ignores possible global
63
+ # phase. To avoid phase discrepancy we limit theta to the [0, 1] interval.
64
+ theta = np.random.uniform(0, 1)
65
+ phi = np.random.uniform(0, 2)
66
+ lmda = np.random.uniform(0, 2)
67
+ u = _qiskit_ugate_unitary(QasmUGate(theta, phi, lmda))
68
+ g = QasmUGate.from_matrix(u)
69
+ np.testing.assert_allclose(cirq.unitary(g), u, atol=1e-7)
70
+
71
+
72
+ def test_u_gate_params() -> None:
73
+ q = cirq.LineQubit(0)
74
+ a, b, c = sympy.symbols('a b c')
75
+ u_gate = QasmUGate(a, b, c)
76
+ assert u_gate == QasmUGate(a, b + 2, c - 2)
77
+ assert u_gate != QasmUGate(a, b + 1, c - 1)
78
+ assert cirq.is_parameterized(u_gate)
79
+ assert cirq.parameter_names(u_gate) == {'a', 'b', 'c'}
80
+ assert not cirq.has_unitary(u_gate)
81
+ cirq.testing.assert_equivalent_repr(u_gate)
82
+ cirq.testing.assert_implements_consistent_protocols(u_gate)
83
+ u_gate_caps = cirq.resolve_parameters(u_gate, {'a': 'A', 'b': 'B', 'c': 'C'})
84
+ assert u_gate_caps == QasmUGate(*sympy.symbols('A B C'))
85
+ resolver = {'A': 0.1, 'B': 2.2, 'C': -1.7}
86
+ resolved = cirq.resolve_parameters(u_gate_caps, resolver)
87
+ assert cirq.approx_eq(resolved, QasmUGate(0.1, 0.2, 0.3))
88
+ resolved_then_decomposed = cirq.decompose_once_with_qubits(resolved, [q])
89
+ decomposed = cirq.decompose_once_with_qubits(u_gate_caps, [q])
90
+ decomposed_then_resolved = [cirq.resolve_parameters(g, resolver) for g in decomposed]
91
+ assert resolved_then_decomposed == decomposed_then_resolved
92
+
93
+
46
94
  def test_qasm_two_qubit_gate_repr() -> None:
47
95
  cirq.testing.assert_equivalent_repr(
48
96
  QasmTwoQubitGate.from_matrix(cirq.testing.random_unitary(4))
@@ -53,13 +101,14 @@ def test_qasm_u_qubit_gate_unitary() -> None:
53
101
  u = cirq.testing.random_unitary(2)
54
102
  g = QasmUGate.from_matrix(u)
55
103
  cirq.testing.assert_allclose_up_to_global_phase(cirq.unitary(g), u, atol=1e-7)
56
-
57
104
  cirq.testing.assert_implements_consistent_protocols(g)
105
+ np.testing.assert_allclose(cirq.unitary(g), _qiskit_ugate_unitary(g), atol=1e-7)
58
106
 
59
107
  u = cirq.unitary(cirq.Y)
60
108
  g = QasmUGate.from_matrix(u)
61
109
  cirq.testing.assert_allclose_up_to_global_phase(cirq.unitary(g), u, atol=1e-7)
62
110
  cirq.testing.assert_implements_consistent_protocols(g)
111
+ np.testing.assert_allclose(cirq.unitary(g), _qiskit_ugate_unitary(g), atol=1e-7)
63
112
 
64
113
 
65
114
  def test_qasm_two_qubit_gate_unitary() -> None:
@@ -200,7 +249,7 @@ ry(pi*-0.25) q[0];
200
249
  )
201
250
 
202
251
 
203
- def test_qasm_global_pahse() -> None:
252
+ def test_qasm_global_phase() -> None:
204
253
  output = cirq.QasmOutput((cirq.global_phase_operation(np.exp(1j * 5))), ())
205
254
  assert (
206
255
  str(output)
@@ -14,7 +14,8 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from typing import Any, Callable, cast, Iterable, Mapping, NamedTuple, Self, Sequence, TYPE_CHECKING
17
+ from collections.abc import Callable, Iterable, Mapping, Sequence
18
+ from typing import Any, cast, NamedTuple, Self, TYPE_CHECKING
18
19
 
19
20
  import numpy as np
20
21