cirq-core 1.4.1__py3-none-any.whl → 1.5.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (590) hide show
  1. cirq/__init__.py +587 -569
  2. cirq/_compat.py +9 -0
  3. cirq/_compat_test.py +11 -9
  4. cirq/_import.py +7 -8
  5. cirq/_version.py +1 -1
  6. cirq/_version_test.py +1 -1
  7. cirq/circuits/__init__.py +15 -9
  8. cirq/circuits/_block_diagram_drawer.py +1 -2
  9. cirq/circuits/_block_diagram_drawer_test.py +3 -3
  10. cirq/circuits/_box_drawing_character_data.py +0 -1
  11. cirq/circuits/_box_drawing_character_data_test.py +2 -2
  12. cirq/circuits/_bucket_priority_queue.py +0 -1
  13. cirq/circuits/_bucket_priority_queue_test.py +1 -1
  14. cirq/circuits/circuit.py +336 -234
  15. cirq/circuits/circuit_operation.py +102 -52
  16. cirq/circuits/circuit_operation_test.py +85 -4
  17. cirq/circuits/circuit_test.py +101 -32
  18. cirq/circuits/frozen_circuit.py +36 -32
  19. cirq/circuits/insert_strategy.py +10 -0
  20. cirq/circuits/insert_strategy_test.py +20 -0
  21. cirq/circuits/moment.py +79 -80
  22. cirq/circuits/moment_test.py +105 -2
  23. cirq/circuits/optimization_pass.py +15 -15
  24. cirq/circuits/optimization_pass_test.py +8 -9
  25. cirq/circuits/qasm_output.py +64 -33
  26. cirq/circuits/qasm_output_test.py +63 -2
  27. cirq/circuits/text_diagram_drawer.py +26 -56
  28. cirq/circuits/text_diagram_drawer_test.py +5 -4
  29. cirq/contrib/__init__.py +2 -2
  30. cirq/contrib/acquaintance/__init__.py +44 -29
  31. cirq/contrib/acquaintance/bipartite.py +8 -7
  32. cirq/contrib/acquaintance/bipartite_test.py +11 -1
  33. cirq/contrib/acquaintance/devices.py +5 -4
  34. cirq/contrib/acquaintance/devices_test.py +5 -1
  35. cirq/contrib/acquaintance/executor.py +18 -21
  36. cirq/contrib/acquaintance/executor_test.py +3 -2
  37. cirq/contrib/acquaintance/gates.py +36 -27
  38. cirq/contrib/acquaintance/gates_test.py +1 -1
  39. cirq/contrib/acquaintance/inspection_utils.py +10 -9
  40. cirq/contrib/acquaintance/inspection_utils_test.py +6 -1
  41. cirq/contrib/acquaintance/mutation_utils.py +10 -10
  42. cirq/contrib/acquaintance/optimizers.py +7 -6
  43. cirq/contrib/acquaintance/optimizers_test.py +1 -1
  44. cirq/contrib/acquaintance/permutation.py +22 -21
  45. cirq/contrib/acquaintance/permutation_test.py +1 -1
  46. cirq/contrib/acquaintance/shift.py +8 -6
  47. cirq/contrib/acquaintance/shift_swap_network.py +6 -4
  48. cirq/contrib/acquaintance/strategies/__init__.py +9 -3
  49. cirq/contrib/acquaintance/strategies/complete.py +4 -3
  50. cirq/contrib/acquaintance/strategies/cubic.py +5 -3
  51. cirq/contrib/acquaintance/strategies/quartic_paired.py +8 -6
  52. cirq/contrib/acquaintance/topological_sort.py +4 -2
  53. cirq/contrib/bayesian_network/__init__.py +3 -1
  54. cirq/contrib/bayesian_network/bayesian_network_gate.py +5 -3
  55. cirq/contrib/circuitdag/__init__.py +1 -1
  56. cirq/contrib/circuitdag/circuit_dag.py +24 -24
  57. cirq/contrib/circuitdag/circuit_dag_test.py +1 -1
  58. cirq/contrib/custom_simulators/custom_state_simulator.py +10 -8
  59. cirq/contrib/custom_simulators/custom_state_simulator_test.py +15 -11
  60. cirq/contrib/graph_device/__init__.py +8 -8
  61. cirq/contrib/graph_device/graph_device.py +8 -8
  62. cirq/contrib/graph_device/graph_device_test.py +0 -1
  63. cirq/contrib/graph_device/hypergraph_test.py +1 -0
  64. cirq/contrib/json.py +1 -2
  65. cirq/contrib/json_test.py +2 -2
  66. cirq/contrib/noise_models/__init__.py +5 -6
  67. cirq/contrib/noise_models/noise_models.py +8 -6
  68. cirq/contrib/paulistring/__init__.py +22 -10
  69. cirq/contrib/paulistring/clifford_optimize.py +1 -1
  70. cirq/contrib/paulistring/clifford_optimize_test.py +0 -1
  71. cirq/contrib/paulistring/clifford_target_gateset.py +15 -12
  72. cirq/contrib/paulistring/optimize.py +2 -2
  73. cirq/contrib/paulistring/optimize_test.py +0 -1
  74. cirq/contrib/paulistring/pauli_string_dag_test.py +0 -1
  75. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +379 -0
  76. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +523 -0
  77. cirq/contrib/paulistring/pauli_string_optimize.py +3 -1
  78. cirq/contrib/paulistring/pauli_string_optimize_test.py +1 -3
  79. cirq/contrib/paulistring/recombine.py +2 -2
  80. cirq/contrib/paulistring/recombine_test.py +2 -2
  81. cirq/contrib/paulistring/separate.py +3 -4
  82. cirq/contrib/qasm_import/__init__.py +2 -2
  83. cirq/contrib/qasm_import/_lexer.py +21 -26
  84. cirq/contrib/qasm_import/_lexer_test.py +90 -6
  85. cirq/contrib/qasm_import/_parser.py +238 -47
  86. cirq/contrib/qasm_import/_parser_test.py +514 -59
  87. cirq/contrib/qasm_import/qasm_test.py +1 -1
  88. cirq/contrib/qcircuit/__init__.py +6 -4
  89. cirq/contrib/qcircuit/qcircuit_diagram.py +5 -2
  90. cirq/contrib/qcircuit/qcircuit_pdf.py +1 -2
  91. cirq/{experiments/grid_parallel_two_qubit_xeb_test.py → contrib/qcircuit/qcircuit_pdf_test.py} +13 -12
  92. cirq/contrib/qcircuit/qcircuit_test.py +1 -1
  93. cirq/contrib/quantum_volume/__init__.py +7 -7
  94. cirq/contrib/quantum_volume/quantum_volume.py +6 -11
  95. cirq/contrib/quantum_volume/quantum_volume_test.py +3 -1
  96. cirq/contrib/quimb/__init__.py +16 -13
  97. cirq/contrib/quimb/density_matrix.py +1 -1
  98. cirq/contrib/quimb/mps_simulator.py +27 -28
  99. cirq/contrib/quimb/mps_simulator_test.py +5 -0
  100. cirq/contrib/quimb/state_vector.py +3 -10
  101. cirq/contrib/quirk/__init__.py +1 -1
  102. cirq/contrib/quirk/export_to_quirk.py +3 -3
  103. cirq/contrib/routing/__init__.py +12 -9
  104. cirq/contrib/routing/device.py +1 -1
  105. cirq/contrib/routing/device_test.py +1 -2
  106. cirq/contrib/routing/greedy.py +7 -5
  107. cirq/contrib/routing/greedy_test.py +5 -3
  108. cirq/contrib/routing/initialization.py +3 -1
  109. cirq/contrib/routing/initialization_test.py +1 -1
  110. cirq/contrib/routing/swap_network.py +6 -6
  111. cirq/contrib/routing/utils.py +6 -4
  112. cirq/contrib/routing/utils_test.py +1 -2
  113. cirq/{type_workarounds.py → contrib/shuffle_circuits/__init__.py} +5 -10
  114. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +250 -0
  115. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking_test.py +363 -0
  116. cirq/contrib/svg/__init__.py +1 -1
  117. cirq/contrib/svg/svg.py +12 -10
  118. cirq/contrib/svg/svg_test.py +3 -2
  119. cirq/devices/__init__.py +34 -25
  120. cirq/devices/device.py +16 -12
  121. cirq/devices/device_test.py +1 -0
  122. cirq/devices/grid_device_metadata.py +16 -12
  123. cirq/devices/grid_device_metadata_test.py +2 -1
  124. cirq/devices/grid_qubit.py +31 -26
  125. cirq/devices/grid_qubit_test.py +30 -1
  126. cirq/devices/insertion_noise_model.py +6 -6
  127. cirq/devices/insertion_noise_model_test.py +1 -1
  128. cirq/devices/line_qubit.py +28 -20
  129. cirq/devices/line_qubit_test.py +26 -0
  130. cirq/devices/named_topologies.py +12 -10
  131. cirq/devices/named_topologies_test.py +5 -4
  132. cirq/devices/noise_model.py +29 -33
  133. cirq/devices/noise_properties.py +2 -2
  134. cirq/devices/noise_properties_test.py +2 -2
  135. cirq/devices/noise_utils.py +3 -3
  136. cirq/devices/superconducting_qubits_noise_properties.py +2 -2
  137. cirq/devices/superconducting_qubits_noise_properties_test.py +3 -3
  138. cirq/devices/thermal_noise_model.py +2 -1
  139. cirq/devices/unconstrained_device.py +1 -1
  140. cirq/devices/unconstrained_device_test.py +6 -0
  141. cirq/experiments/__init__.py +51 -34
  142. cirq/experiments/qubit_characterizations.py +17 -15
  143. cirq/experiments/qubit_characterizations_test.py +4 -6
  144. cirq/experiments/random_quantum_circuit_generation.py +10 -9
  145. cirq/experiments/random_quantum_circuit_generation_test.py +21 -4
  146. cirq/experiments/readout_confusion_matrix.py +73 -8
  147. cirq/experiments/readout_confusion_matrix_test.py +104 -1
  148. cirq/experiments/single_qubit_readout_calibration.py +8 -6
  149. cirq/experiments/single_qubit_readout_calibration_test.py +1 -1
  150. cirq/experiments/t1_decay_experiment.py +4 -5
  151. cirq/experiments/t1_decay_experiment_test.py +1 -2
  152. cirq/experiments/t2_decay_experiment.py +0 -1
  153. cirq/experiments/t2_decay_experiment_test.py +1 -2
  154. cirq/experiments/two_qubit_xeb.py +157 -33
  155. cirq/experiments/two_qubit_xeb_test.py +38 -22
  156. cirq/experiments/xeb_fitting.py +99 -19
  157. cirq/experiments/xeb_fitting_test.py +64 -25
  158. cirq/experiments/xeb_sampling.py +14 -18
  159. cirq/experiments/xeb_simulation.py +4 -3
  160. cirq/experiments/xeb_simulation_test.py +20 -14
  161. cirq/experiments/z_phase_calibration.py +368 -0
  162. cirq/experiments/z_phase_calibration_test.py +241 -0
  163. cirq/interop/__init__.py +4 -1
  164. cirq/interop/quirk/__init__.py +7 -4
  165. cirq/interop/quirk/cells/__init__.py +17 -6
  166. cirq/interop/quirk/cells/arithmetic_cells.py +8 -8
  167. cirq/interop/quirk/cells/arithmetic_cells_test.py +1 -1
  168. cirq/interop/quirk/cells/cell.py +6 -6
  169. cirq/interop/quirk/cells/composite_cell.py +5 -5
  170. cirq/interop/quirk/cells/composite_cell_test.py +1 -1
  171. cirq/interop/quirk/cells/control_cells.py +1 -1
  172. cirq/interop/quirk/cells/frequency_space_cells.py +2 -2
  173. cirq/interop/quirk/cells/ignored_cells.py +1 -1
  174. cirq/interop/quirk/cells/input_cells.py +1 -1
  175. cirq/interop/quirk/cells/input_cells_test.py +1 -1
  176. cirq/interop/quirk/cells/input_rotation_cells.py +1 -1
  177. cirq/interop/quirk/cells/input_rotation_cells_test.py +1 -1
  178. cirq/interop/quirk/cells/measurement_cells.py +1 -1
  179. cirq/interop/quirk/cells/parse.py +8 -7
  180. cirq/interop/quirk/cells/parse_test.py +2 -2
  181. cirq/interop/quirk/cells/single_qubit_rotation_cells.py +1 -1
  182. cirq/interop/quirk/cells/swap_cell_test.py +1 -1
  183. cirq/interop/quirk/cells/unsupported_cells.py +1 -1
  184. cirq/interop/quirk/url_to_circuit.py +7 -7
  185. cirq/interop/quirk/url_to_circuit_test.py +1 -1
  186. cirq/ion/__init__.py +4 -2
  187. cirq/json_resolver_cache.py +15 -7
  188. cirq/linalg/__init__.py +62 -51
  189. cirq/linalg/combinators.py +4 -4
  190. cirq/linalg/combinators_test.py +4 -1
  191. cirq/linalg/decompositions.py +15 -40
  192. cirq/linalg/decompositions_test.py +16 -22
  193. cirq/linalg/diagonalize.py +1 -1
  194. cirq/linalg/diagonalize_test.py +1 -1
  195. cirq/linalg/operator_spaces.py +20 -4
  196. cirq/linalg/operator_spaces_test.py +15 -2
  197. cirq/linalg/predicates.py +3 -3
  198. cirq/linalg/predicates_test.py +1 -0
  199. cirq/linalg/tolerance.py +2 -2
  200. cirq/linalg/transformations.py +30 -12
  201. cirq/linalg/transformations_test.py +13 -0
  202. cirq/neutral_atoms/__init__.py +2 -2
  203. cirq/neutral_atoms/convert_to_neutral_atom_gates_test.py +0 -1
  204. cirq/ops/__init__.py +172 -132
  205. cirq/ops/arithmetic_operation.py +2 -2
  206. cirq/ops/arithmetic_operation_test.py +2 -2
  207. cirq/ops/boolean_hamiltonian.py +3 -2
  208. cirq/ops/classically_controlled_operation.py +39 -12
  209. cirq/ops/classically_controlled_operation_test.py +147 -1
  210. cirq/ops/clifford_gate.py +38 -36
  211. cirq/ops/clifford_gate_test.py +75 -1
  212. cirq/ops/common_channels.py +16 -45
  213. cirq/ops/common_channels_test.py +10 -0
  214. cirq/ops/common_gate_families.py +1 -1
  215. cirq/ops/common_gate_families_test.py +1 -0
  216. cirq/ops/common_gates.py +48 -49
  217. cirq/ops/common_gates_test.py +18 -2
  218. cirq/ops/control_values.py +3 -3
  219. cirq/ops/control_values_test.py +2 -1
  220. cirq/ops/controlled_gate.py +36 -23
  221. cirq/ops/controlled_gate_test.py +70 -3
  222. cirq/ops/controlled_operation.py +6 -5
  223. cirq/ops/controlled_operation_test.py +7 -3
  224. cirq/ops/dense_pauli_string.py +11 -11
  225. cirq/ops/diagonal_gate.py +2 -2
  226. cirq/ops/diagonal_gate_test.py +1 -0
  227. cirq/ops/eigen_gate.py +16 -36
  228. cirq/ops/eigen_gate_test.py +60 -10
  229. cirq/ops/fourier_transform.py +1 -3
  230. cirq/ops/fourier_transform_test.py +2 -1
  231. cirq/ops/fsim_gate.py +42 -3
  232. cirq/ops/fsim_gate_test.py +21 -0
  233. cirq/ops/gate_operation.py +8 -8
  234. cirq/ops/gate_operation_test.py +4 -2
  235. cirq/ops/gateset_test.py +11 -2
  236. cirq/ops/global_phase_op.py +8 -7
  237. cirq/ops/global_phase_op_test.py +1 -1
  238. cirq/ops/greedy_qubit_manager_test.py +5 -0
  239. cirq/ops/identity.py +14 -4
  240. cirq/ops/identity_test.py +24 -0
  241. cirq/ops/kraus_channel.py +1 -0
  242. cirq/ops/kraus_channel_test.py +3 -1
  243. cirq/ops/linear_combinations.py +27 -21
  244. cirq/ops/linear_combinations_test.py +23 -4
  245. cirq/ops/matrix_gates.py +24 -8
  246. cirq/ops/measure_util.py +2 -2
  247. cirq/ops/measurement_gate.py +7 -4
  248. cirq/ops/measurement_gate_test.py +2 -1
  249. cirq/ops/mixed_unitary_channel.py +1 -0
  250. cirq/ops/mixed_unitary_channel_test.py +3 -1
  251. cirq/ops/named_qubit.py +8 -1
  252. cirq/ops/op_tree.py +3 -30
  253. cirq/ops/op_tree_test.py +4 -0
  254. cirq/ops/parallel_gate.py +2 -3
  255. cirq/ops/parallel_gate_test.py +2 -1
  256. cirq/ops/parity_gates.py +7 -8
  257. cirq/ops/parity_gates_test.py +1 -0
  258. cirq/ops/pauli_gates.py +5 -11
  259. cirq/ops/pauli_gates_test.py +1 -0
  260. cirq/ops/pauli_interaction_gate.py +11 -5
  261. cirq/ops/pauli_interaction_gate_test.py +2 -3
  262. cirq/ops/pauli_measurement_gate.py +6 -5
  263. cirq/ops/pauli_measurement_gate_test.py +1 -0
  264. cirq/ops/pauli_string.py +115 -130
  265. cirq/ops/pauli_string_phasor.py +21 -20
  266. cirq/ops/pauli_string_phasor_test.py +13 -3
  267. cirq/ops/pauli_string_raw_types.py +1 -0
  268. cirq/ops/pauli_string_test.py +192 -55
  269. cirq/ops/pauli_sum_exponential.py +3 -4
  270. cirq/ops/pauli_sum_exponential_test.py +0 -1
  271. cirq/ops/permutation_gate.py +2 -2
  272. cirq/ops/permutation_gate_test.py +1 -1
  273. cirq/ops/phased_iswap_gate.py +6 -7
  274. cirq/ops/phased_iswap_gate_test.py +21 -5
  275. cirq/ops/phased_x_gate.py +11 -25
  276. cirq/ops/phased_x_gate_test.py +19 -3
  277. cirq/ops/phased_x_z_gate.py +12 -11
  278. cirq/ops/projector.py +4 -5
  279. cirq/ops/qubit_manager.py +2 -1
  280. cirq/ops/qubit_manager_test.py +2 -1
  281. cirq/ops/qubit_order.py +1 -1
  282. cirq/ops/random_gate_channel.py +1 -1
  283. cirq/ops/random_gate_channel_test.py +0 -6
  284. cirq/ops/raw_types.py +146 -50
  285. cirq/ops/raw_types_test.py +37 -3
  286. cirq/ops/state_preparation_channel.py +2 -2
  287. cirq/ops/state_preparation_channel_test.py +2 -1
  288. cirq/ops/swap_gates.py +9 -4
  289. cirq/ops/three_qubit_gates.py +8 -8
  290. cirq/ops/three_qubit_gates_test.py +1 -0
  291. cirq/ops/two_qubit_diagonal_gate.py +4 -3
  292. cirq/ops/uniform_superposition_gate.py +4 -4
  293. cirq/ops/uniform_superposition_gate_test.py +1 -0
  294. cirq/ops/wait_gate.py +6 -8
  295. cirq/protocols/__init__.py +135 -83
  296. cirq/protocols/act_on_protocol.py +1 -1
  297. cirq/protocols/act_on_protocol_test.py +1 -1
  298. cirq/protocols/apply_channel_protocol.py +3 -3
  299. cirq/protocols/apply_mixture_protocol.py +15 -9
  300. cirq/protocols/apply_mixture_protocol_test.py +11 -0
  301. cirq/protocols/apply_unitary_protocol.py +2 -2
  302. cirq/protocols/apply_unitary_protocol_test.py +2 -1
  303. cirq/protocols/approximate_equality_protocol.py +7 -8
  304. cirq/protocols/approximate_equality_protocol_test.py +3 -1
  305. cirq/protocols/circuit_diagram_info_protocol.py +8 -6
  306. cirq/protocols/circuit_diagram_info_protocol_test.py +5 -0
  307. cirq/protocols/commutes_protocol.py +6 -6
  308. cirq/protocols/control_key_protocol.py +1 -1
  309. cirq/protocols/decompose_protocol.py +4 -5
  310. cirq/protocols/decompose_protocol_test.py +2 -1
  311. cirq/protocols/equal_up_to_global_phase_protocol.py +3 -3
  312. cirq/protocols/equal_up_to_global_phase_protocol_test.py +7 -0
  313. cirq/protocols/has_stabilizer_effect_protocol.py +5 -5
  314. cirq/protocols/has_unitary_protocol.py +1 -1
  315. cirq/protocols/has_unitary_protocol_test.py +8 -7
  316. cirq/protocols/hash_from_pickle_test.py +120 -0
  317. cirq/protocols/inverse_protocol.py +1 -1
  318. cirq/protocols/json_serialization.py +14 -1
  319. cirq/protocols/json_serialization_test.py +28 -7
  320. cirq/protocols/json_test_data/BitMaskKeyCondition.json +86 -0
  321. cirq/protocols/json_test_data/BitMaskKeyCondition.repr +7 -0
  322. cirq/protocols/json_test_data/Concat.json +19 -0
  323. cirq/protocols/json_test_data/Concat.repr +1 -0
  324. cirq/protocols/json_test_data/README.md +4 -2
  325. cirq/protocols/json_test_data/SympyCondition.json +60 -15
  326. cirq/protocols/json_test_data/SympyCondition.repr +4 -1
  327. cirq/protocols/json_test_data/_InverseCompositeGate.json +10 -0
  328. cirq/protocols/json_test_data/_InverseCompositeGate.repr +1 -0
  329. cirq/protocols/json_test_data/__init__.py +1 -1
  330. cirq/protocols/json_test_data/sympy.And.json +13 -0
  331. cirq/protocols/json_test_data/sympy.And.repr +1 -0
  332. cirq/protocols/json_test_data/sympy.Indexed.json +18 -0
  333. cirq/protocols/json_test_data/sympy.Indexed.repr +1 -0
  334. cirq/protocols/json_test_data/sympy.IndexedBase.json +9 -0
  335. cirq/protocols/json_test_data/sympy.IndexedBase.repr +1 -0
  336. cirq/protocols/json_test_data/sympy.Not.json +9 -0
  337. cirq/protocols/json_test_data/sympy.Not.repr +1 -0
  338. cirq/protocols/json_test_data/sympy.Or.json +13 -0
  339. cirq/protocols/json_test_data/sympy.Or.repr +1 -0
  340. cirq/protocols/json_test_data/sympy.Xor.json +13 -0
  341. cirq/protocols/json_test_data/sympy.Xor.repr +1 -0
  342. cirq/protocols/kraus_protocol.py +8 -8
  343. cirq/protocols/kraus_protocol_test.py +0 -1
  344. cirq/protocols/measurement_key_protocol.py +1 -1
  345. cirq/protocols/measurement_key_protocol_test.py +7 -7
  346. cirq/protocols/mixture_protocol.py +6 -4
  347. cirq/protocols/mixture_protocol_test.py +21 -13
  348. cirq/protocols/pauli_expansion_protocol.py +1 -0
  349. cirq/protocols/pow_protocol.py +1 -1
  350. cirq/protocols/qasm.py +25 -6
  351. cirq/protocols/qasm_test.py +17 -0
  352. cirq/protocols/qid_shape_protocol.py +2 -2
  353. cirq/protocols/resolve_parameters.py +2 -3
  354. cirq/protocols/resolve_parameters_test.py +2 -1
  355. cirq/protocols/trace_distance_bound.py +1 -1
  356. cirq/protocols/trace_distance_bound_test.py +1 -0
  357. cirq/protocols/unitary_protocol.py +3 -3
  358. cirq/protocols/unitary_protocol_test.py +1 -1
  359. cirq/qis/__init__.py +48 -35
  360. cirq/qis/channels_test.py +0 -9
  361. cirq/qis/clifford_tableau.py +46 -26
  362. cirq/qis/clifford_tableau_test.py +2 -1
  363. cirq/qis/entropy.py +115 -0
  364. cirq/qis/entropy_test.py +43 -0
  365. cirq/qis/measures.py +5 -4
  366. cirq/qis/measures_test.py +7 -0
  367. cirq/qis/noise_utils_test.py +4 -4
  368. cirq/qis/quantum_state_representation.py +1 -1
  369. cirq/qis/states.py +7 -7
  370. cirq/sim/__init__.py +55 -37
  371. cirq/sim/classical_simulator.py +7 -6
  372. cirq/sim/classical_simulator_test.py +3 -1
  373. cirq/sim/clifford/__init__.py +17 -9
  374. cirq/sim/clifford/clifford_simulator.py +5 -4
  375. cirq/sim/clifford/clifford_simulator_test.py +32 -9
  376. cirq/sim/clifford/clifford_tableau_simulation_state.py +1 -1
  377. cirq/sim/clifford/stabilizer_simulation_state.py +1 -1
  378. cirq/sim/clifford/stabilizer_state_ch_form.py +4 -3
  379. cirq/sim/density_matrix_simulator.py +3 -2
  380. cirq/sim/density_matrix_simulator_test.py +12 -4
  381. cirq/sim/density_matrix_utils.py +1 -1
  382. cirq/sim/mux.py +2 -2
  383. cirq/sim/simulation_state.py +4 -5
  384. cirq/sim/simulation_state_base.py +2 -2
  385. cirq/sim/simulation_state_test.py +1 -1
  386. cirq/sim/simulation_utils.py +3 -1
  387. cirq/sim/simulation_utils_test.py +2 -3
  388. cirq/sim/simulator.py +7 -6
  389. cirq/sim/simulator_base.py +5 -5
  390. cirq/sim/simulator_test.py +14 -3
  391. cirq/sim/sparse_simulator.py +4 -3
  392. cirq/sim/sparse_simulator_test.py +17 -9
  393. cirq/sim/state_vector.py +2 -2
  394. cirq/sim/state_vector_simulation_state_test.py +1 -1
  395. cirq/sim/state_vector_simulator.py +4 -4
  396. cirq/sim/state_vector_test.py +27 -32
  397. cirq/study/__init__.py +27 -21
  398. cirq/study/flatten_expressions.py +5 -6
  399. cirq/study/flatten_expressions_test.py +1 -1
  400. cirq/study/resolver.py +14 -11
  401. cirq/study/resolver_test.py +10 -1
  402. cirq/study/result.py +3 -3
  403. cirq/study/sweepable.py +15 -9
  404. cirq/study/sweepable_test.py +27 -0
  405. cirq/study/sweeps.py +65 -10
  406. cirq/study/sweeps_test.py +123 -0
  407. cirq/testing/__init__.py +86 -57
  408. cirq/testing/_compat_test_data/module_a/__init__.py +2 -2
  409. cirq/testing/_compat_test_data/module_a/sub/subsub/__init__.py +1 -1
  410. cirq/testing/circuit_compare.py +3 -4
  411. cirq/testing/circuit_compare_test.py +7 -8
  412. cirq/testing/consistent_act_on.py +3 -3
  413. cirq/testing/consistent_channels_test.py +2 -1
  414. cirq/testing/consistent_controlled_gate_op.py +3 -2
  415. cirq/testing/consistent_controlled_gate_op_test.py +2 -3
  416. cirq/testing/consistent_decomposition.py +1 -1
  417. cirq/testing/consistent_decomposition_test.py +1 -2
  418. cirq/testing/consistent_pauli_expansion_test.py +1 -1
  419. cirq/testing/consistent_phase_by.py +1 -1
  420. cirq/testing/consistent_phase_by_test.py +1 -2
  421. cirq/testing/consistent_protocols.py +11 -11
  422. cirq/testing/consistent_protocols_test.py +4 -5
  423. cirq/testing/consistent_qasm.py +8 -12
  424. cirq/testing/consistent_qasm_test.py +1 -1
  425. cirq/testing/consistent_resolve_parameters.py +2 -1
  426. cirq/testing/consistent_specified_has_unitary_test.py +1 -1
  427. cirq/testing/consistent_unitary.py +3 -1
  428. cirq/testing/consistent_unitary_test.py +3 -3
  429. cirq/testing/devices.py +1 -1
  430. cirq/testing/devices_test.py +1 -0
  431. cirq/testing/equals_tester.py +2 -4
  432. cirq/testing/equals_tester_test.py +6 -5
  433. cirq/testing/equivalent_basis_map.py +1 -0
  434. cirq/testing/equivalent_basis_map_test.py +0 -1
  435. cirq/testing/gate_features_test.py +5 -0
  436. cirq/testing/json.py +4 -4
  437. cirq/testing/lin_alg_utils_test.py +1 -1
  438. cirq/testing/order_tester.py +1 -1
  439. cirq/testing/order_tester_test.py +1 -1
  440. cirq/testing/pytest_utils.py +57 -0
  441. cirq/testing/pytest_utils_test.py +35 -0
  442. cirq/testing/random_circuit.py +2 -2
  443. cirq/testing/random_circuit_test.py +2 -2
  444. cirq/testing/routing_devices_test.py +2 -1
  445. cirq/testing/sample_circuits.py +1 -1
  446. cirq/testing/sample_gates.py +5 -4
  447. cirq/testing/sample_gates_test.py +2 -2
  448. cirq/transformers/__init__.py +101 -82
  449. cirq/transformers/align.py +12 -1
  450. cirq/transformers/align_test.py +13 -0
  451. cirq/transformers/analytical_decompositions/__init__.py +27 -24
  452. cirq/transformers/analytical_decompositions/clifford_decomposition.py +2 -1
  453. cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +1 -1
  454. cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +1 -1
  455. cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +2 -0
  456. cirq/transformers/analytical_decompositions/cphase_to_fsim.py +1 -1
  457. cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +1 -1
  458. cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +2 -2
  459. cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +4 -4
  460. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +99 -24
  461. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +105 -14
  462. cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +1 -1
  463. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +1 -1
  464. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +1 -0
  465. cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +3 -4
  466. cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +1 -1
  467. cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +2 -1
  468. cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +2 -1
  469. cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +5 -6
  470. cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +2 -2
  471. cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +1 -1
  472. cirq/transformers/analytical_decompositions/two_qubit_to_fsim_test.py +1 -2
  473. cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +2 -2
  474. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +2 -2
  475. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +2 -1
  476. cirq/transformers/drop_empty_moments.py +1 -0
  477. cirq/transformers/drop_negligible_operations.py +1 -0
  478. cirq/transformers/dynamical_decoupling.py +255 -43
  479. cirq/transformers/dynamical_decoupling_test.py +730 -17
  480. cirq/transformers/eject_phased_paulis.py +29 -15
  481. cirq/transformers/eject_phased_paulis_test.py +3 -8
  482. cirq/transformers/eject_z.py +3 -2
  483. cirq/transformers/eject_z_test.py +3 -3
  484. cirq/transformers/gauge_compiling/__init__.py +25 -9
  485. cirq/transformers/gauge_compiling/cphase_gauge.py +146 -0
  486. cirq/transformers/gauge_compiling/cphase_gauge_test.py +42 -0
  487. cirq/transformers/gauge_compiling/cz_gauge.py +4 -4
  488. cirq/transformers/gauge_compiling/gauge_compiling.py +245 -6
  489. cirq/transformers/gauge_compiling/gauge_compiling_test.py +107 -2
  490. cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +39 -2
  491. cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +10 -1
  492. cirq/transformers/gauge_compiling/iswap_gauge.py +2 -2
  493. cirq/transformers/gauge_compiling/spin_inversion_gauge.py +2 -2
  494. cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +23 -5
  495. cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +3 -2
  496. cirq/transformers/heuristic_decompositions/__init__.py +3 -3
  497. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +2 -1
  498. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +1 -1
  499. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +4 -4
  500. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation_test.py +4 -4
  501. cirq/transformers/insertion_sort.py +64 -0
  502. cirq/transformers/insertion_sort_test.py +34 -0
  503. cirq/transformers/measurement_transformers.py +14 -1
  504. cirq/transformers/measurement_transformers_test.py +35 -0
  505. cirq/transformers/merge_k_qubit_gates.py +2 -2
  506. cirq/transformers/merge_single_qubit_gates.py +1 -1
  507. cirq/transformers/merge_single_qubit_gates_test.py +1 -1
  508. cirq/transformers/noise_adding.py +115 -0
  509. cirq/transformers/noise_adding_test.py +54 -0
  510. cirq/transformers/optimize_for_target_gateset.py +1 -1
  511. cirq/transformers/optimize_for_target_gateset_test.py +3 -2
  512. cirq/transformers/qubit_management_transformers.py +1 -1
  513. cirq/transformers/randomized_measurements.py +171 -0
  514. cirq/transformers/randomized_measurements_test.py +68 -0
  515. cirq/transformers/routing/__init__.py +14 -5
  516. cirq/transformers/routing/initial_mapper.py +1 -1
  517. cirq/transformers/routing/initial_mapper_test.py +1 -0
  518. cirq/transformers/routing/line_initial_mapper.py +3 -2
  519. cirq/transformers/routing/mapping_manager.py +2 -2
  520. cirq/transformers/routing/mapping_manager_test.py +2 -2
  521. cirq/transformers/routing/route_circuit_cqc.py +3 -2
  522. cirq/transformers/routing/route_circuit_cqc_test.py +2 -1
  523. cirq/transformers/routing/visualize_routed_circuit.py +1 -0
  524. cirq/transformers/routing/visualize_routed_circuit_test.py +1 -0
  525. cirq/transformers/stratify.py +2 -2
  526. cirq/transformers/synchronize_terminal_measurements.py +2 -1
  527. cirq/transformers/target_gatesets/__init__.py +7 -5
  528. cirq/transformers/target_gatesets/compilation_target_gateset.py +16 -3
  529. cirq/transformers/target_gatesets/compilation_target_gateset_test.py +2 -0
  530. cirq/transformers/target_gatesets/cz_gateset.py +5 -1
  531. cirq/transformers/target_gatesets/cz_gateset_test.py +23 -2
  532. cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +1 -1
  533. cirq/transformers/target_gatesets/sqrt_iswap_gateset_test.py +3 -2
  534. cirq/transformers/transformer_api.py +5 -4
  535. cirq/transformers/transformer_api_test.py +11 -3
  536. cirq/transformers/transformer_primitives.py +9 -31
  537. cirq/transformers/transformer_primitives_test.py +6 -5
  538. cirq/value/__init__.py +51 -30
  539. cirq/value/abc_alt.py +1 -2
  540. cirq/value/angle.py +2 -0
  541. cirq/value/classical_data.py +1 -0
  542. cirq/value/condition.py +149 -3
  543. cirq/value/condition_test.py +254 -0
  544. cirq/value/digits.py +1 -1
  545. cirq/value/duration.py +4 -4
  546. cirq/value/duration_test.py +2 -1
  547. cirq/value/linear_dict.py +85 -24
  548. cirq/value/linear_dict_test.py +94 -3
  549. cirq/value/measurement_key.py +9 -2
  550. cirq/value/periodic_value.py +2 -3
  551. cirq/value/periodic_value_test.py +5 -0
  552. cirq/value/probability.py +1 -0
  553. cirq/value/random_state.py +1 -1
  554. cirq/value/timestamp.py +2 -4
  555. cirq/value/timestamp_test.py +2 -1
  556. cirq/value/type_alias.py +2 -2
  557. cirq/value/value_equality_attr.py +14 -2
  558. cirq/value/value_equality_attr_test.py +1 -1
  559. cirq/vis/__init__.py +9 -6
  560. cirq/vis/density_matrix.py +1 -1
  561. cirq/vis/density_matrix_test.py +2 -5
  562. cirq/vis/heatmap.py +49 -12
  563. cirq/vis/heatmap_test.py +168 -4
  564. cirq/vis/histogram.py +1 -1
  565. cirq/vis/histogram_test.py +1 -2
  566. cirq/vis/state_histogram.py +7 -5
  567. cirq/vis/state_histogram_test.py +2 -2
  568. cirq/work/__init__.py +19 -13
  569. cirq/work/collector.py +2 -2
  570. cirq/work/observable_grouping.py +2 -2
  571. cirq/work/observable_measurement.py +3 -3
  572. cirq/work/observable_measurement_data.py +5 -2
  573. cirq/work/observable_measurement_test.py +8 -8
  574. cirq/work/observable_readout_calibration.py +2 -2
  575. cirq/work/observable_readout_calibration_test.py +2 -1
  576. cirq/work/observable_settings.py +8 -7
  577. cirq/work/observable_settings_test.py +3 -2
  578. cirq/work/pauli_sum_collector.py +1 -1
  579. cirq/work/sampler.py +8 -20
  580. cirq/work/sampler_test.py +4 -3
  581. cirq/work/zeros_sampler.py +1 -1
  582. cirq_core-1.5.0.dist-info/METADATA +125 -0
  583. {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/RECORD +586 -552
  584. {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/WHEEL +1 -1
  585. cirq/experiments/grid_parallel_two_qubit_xeb.py +0 -62
  586. cirq/protocols/json_test_data/GridParallelXEBMetadata.json +0 -119
  587. cirq/protocols/json_test_data/GridParallelXEBMetadata.repr +0 -1
  588. cirq_core-1.4.1.dist-info/METADATA +0 -45
  589. {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/LICENSE +0 -0
  590. {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/top_level.txt +0 -0
@@ -18,9 +18,14 @@ A CircuitOperation is an Operation object that wraps a FrozenCircuit. When
18
18
  applied as part of a larger circuit, a CircuitOperation will execute all
19
19
  component operations in order, including any nested CircuitOperations.
20
20
  """
21
+
22
+ from __future__ import annotations
23
+
21
24
  import math
25
+ import warnings
22
26
  from functools import cached_property
23
27
  from typing import (
28
+ Any,
24
29
  Callable,
25
30
  cast,
26
31
  Dict,
@@ -38,13 +43,12 @@ from typing import (
38
43
  import numpy as np
39
44
  import sympy
40
45
 
41
- from cirq import circuits, ops, protocols, value, study
46
+ from cirq import circuits, ops, protocols, study, value
42
47
  from cirq._compat import proper_repr
43
48
 
44
49
  if TYPE_CHECKING:
45
50
  import cirq
46
51
 
47
-
48
52
  INT_CLASSES = (int, np.integer)
49
53
  INT_TYPE = Union[int, np.integer]
50
54
  IntParam = Union[INT_TYPE, sympy.Expr]
@@ -80,16 +84,16 @@ class CircuitOperation(ops.Operation):
80
84
 
81
85
  def __init__(
82
86
  self,
83
- circuit: 'cirq.FrozenCircuit',
87
+ circuit: cirq.FrozenCircuit,
84
88
  repetitions: INT_TYPE = 1,
85
- qubit_map: Optional[Dict['cirq.Qid', 'cirq.Qid']] = None,
89
+ qubit_map: Optional[Dict[cirq.Qid, cirq.Qid]] = None,
86
90
  measurement_key_map: Optional[Dict[str, str]] = None,
87
91
  param_resolver: Optional[study.ParamResolverOrSimilarType] = None,
88
92
  repetition_ids: Optional[Sequence[str]] = None,
89
93
  parent_path: Tuple[str, ...] = (),
90
- extern_keys: FrozenSet['cirq.MeasurementKey'] = frozenset(),
91
- use_repetition_ids: bool = True,
92
- repeat_until: Optional['cirq.Condition'] = None,
94
+ extern_keys: FrozenSet[cirq.MeasurementKey] = frozenset(),
95
+ use_repetition_ids: Optional[bool] = None,
96
+ repeat_until: Optional[cirq.Condition] = None,
93
97
  ):
94
98
  """Initializes a CircuitOperation.
95
99
 
@@ -119,7 +123,9 @@ class CircuitOperation(ops.Operation):
119
123
  use_repetition_ids: When True, any measurement key in the subcircuit
120
124
  will have its path prepended with the repetition id for each
121
125
  repetition. When False, this will not happen and the measurement
122
- key will be repeated.
126
+ key will be repeated. The default is True, but it will be changed
127
+ to False in the next release. Please pass an explicit argument
128
+ ``use_repetition_ids=True`` to preserve the current behavior.
123
129
  repeat_until: A condition that will be tested after each iteration of
124
130
  the subcircuit. The subcircuit will repeat until condition returns
125
131
  True, but will always run at least once, and the measurement key
@@ -155,7 +161,19 @@ class CircuitOperation(ops.Operation):
155
161
  # Ensure that the circuit is invertible if the repetitions are negative.
156
162
  self._repetitions = repetitions
157
163
  self._repetition_ids = None if repetition_ids is None else list(repetition_ids)
158
- self._use_repetition_ids = use_repetition_ids
164
+ if use_repetition_ids is None:
165
+ if repetition_ids is None:
166
+ msg = (
167
+ "In cirq 1.6 the default value of `use_repetition_ids` will change to\n"
168
+ "`use_repetition_ids=False`. To make this warning go away, please pass\n"
169
+ "explicit `use_repetition_ids`, e.g., to preserve current behavior, use\n"
170
+ "\n"
171
+ " CircuitOperations(..., use_repetition_ids=True)"
172
+ )
173
+ warnings.warn(msg, FutureWarning)
174
+ self._use_repetition_ids = True
175
+ else:
176
+ self._use_repetition_ids = use_repetition_ids
159
177
  if isinstance(self._repetitions, float):
160
178
  if math.isclose(self._repetitions, round(self._repetitions)):
161
179
  self._repetitions = round(self._repetitions)
@@ -200,16 +218,17 @@ class CircuitOperation(ops.Operation):
200
218
  )
201
219
 
202
220
  self._repeat_until = repeat_until
203
- if self._repeat_until:
221
+ mapped_repeat_until = self._mapped_repeat_until
222
+ if mapped_repeat_until:
204
223
  if self._use_repetition_ids or self._repetitions != 1:
205
224
  raise ValueError('Cannot use repetitions with repeat_until')
206
225
  if protocols.measurement_key_objs(self._mapped_single_loop()).isdisjoint(
207
- self._repeat_until.keys
226
+ mapped_repeat_until.keys
208
227
  ):
209
228
  raise ValueError('Infinite loop: condition is not modified in subcircuit.')
210
229
 
211
230
  @property
212
- def circuit(self) -> 'cirq.FrozenCircuit':
231
+ def circuit(self) -> cirq.FrozenCircuit:
213
232
  return self._circuit
214
233
 
215
234
  @property
@@ -225,11 +244,11 @@ class CircuitOperation(ops.Operation):
225
244
  return self._use_repetition_ids
226
245
 
227
246
  @property
228
- def repeat_until(self) -> Optional['cirq.Condition']:
247
+ def repeat_until(self) -> Optional[cirq.Condition]:
229
248
  return self._repeat_until
230
249
 
231
250
  @property
232
- def qubit_map(self) -> Mapping['cirq.Qid', 'cirq.Qid']:
251
+ def qubit_map(self) -> Mapping[cirq.Qid, cirq.Qid]:
233
252
  return self._qubit_map
234
253
 
235
254
  @property
@@ -244,14 +263,14 @@ class CircuitOperation(ops.Operation):
244
263
  def parent_path(self) -> Tuple[str, ...]:
245
264
  return self._parent_path
246
265
 
247
- def base_operation(self) -> 'cirq.CircuitOperation':
266
+ def base_operation(self) -> cirq.CircuitOperation:
248
267
  """Returns a copy of this operation with only the wrapped circuit.
249
268
 
250
269
  Key and qubit mappings, parameter values, and repetitions are not copied.
251
270
  """
252
271
  return CircuitOperation(self.circuit)
253
272
 
254
- def replace(self, **changes) -> 'cirq.CircuitOperation':
273
+ def replace(self, **changes) -> cirq.CircuitOperation:
255
274
  """Returns a copy of this operation with the specified changes."""
256
275
  kwargs = {
257
276
  'circuit': self.circuit,
@@ -266,7 +285,7 @@ class CircuitOperation(ops.Operation):
266
285
  'repeat_until': self.repeat_until,
267
286
  **changes,
268
287
  }
269
- return CircuitOperation(**kwargs) # type: ignore
288
+ return CircuitOperation(**kwargs)
270
289
 
271
290
  def __eq__(self, other) -> bool:
272
291
  if not isinstance(other, type(self)):
@@ -286,7 +305,7 @@ class CircuitOperation(ops.Operation):
286
305
  # Methods for getting post-mapping properties of the contained circuit.
287
306
 
288
307
  @property
289
- def qubits(self) -> Tuple['cirq.Qid', ...]:
308
+ def qubits(self) -> Tuple[cirq.Qid, ...]:
290
309
  """Returns the qubits operated on by this object."""
291
310
  ordered_qubits = ops.QubitOrder.DEFAULT.order_for(self.circuit.all_qubits())
292
311
  return tuple(self.qubit_map.get(q, q) for q in ordered_qubits)
@@ -312,7 +331,7 @@ class CircuitOperation(ops.Operation):
312
331
  raise ValueError('Cannot unroll circuit due to nondeterministic repetitions')
313
332
 
314
333
  @cached_property
315
- def _measurement_key_objs(self) -> FrozenSet['cirq.MeasurementKey']:
334
+ def _measurement_key_objs(self) -> FrozenSet[cirq.MeasurementKey]:
316
335
  circuit_keys = protocols.measurement_key_objs(self.circuit)
317
336
  if circuit_keys and self.use_repetition_ids:
318
337
  self._ensure_deterministic_loop_count()
@@ -330,24 +349,25 @@ class CircuitOperation(ops.Operation):
330
349
  for key in circuit_keys
331
350
  )
332
351
 
333
- def _measurement_key_objs_(self) -> FrozenSet['cirq.MeasurementKey']:
352
+ def _measurement_key_objs_(self) -> FrozenSet[cirq.MeasurementKey]:
334
353
  return self._measurement_key_objs
335
354
 
336
355
  def _measurement_key_names_(self) -> FrozenSet[str]:
337
356
  return frozenset(str(key) for key in self._measurement_key_objs_())
338
357
 
339
358
  @cached_property
340
- def _control_keys(self) -> FrozenSet['cirq.MeasurementKey']:
359
+ def _control_keys(self) -> FrozenSet[cirq.MeasurementKey]:
341
360
  keys = (
342
361
  frozenset()
343
362
  if not protocols.control_keys(self.circuit)
344
363
  else protocols.control_keys(self._mapped_single_loop())
345
364
  )
346
- if self.repeat_until is not None:
347
- keys |= frozenset(self.repeat_until.keys) - self._measurement_key_objs_()
365
+ mapped_repeat_until = self._mapped_repeat_until
366
+ if mapped_repeat_until is not None:
367
+ keys |= frozenset(mapped_repeat_until.keys) - self._measurement_key_objs_()
348
368
  return keys
349
369
 
350
- def _control_keys_(self) -> FrozenSet['cirq.MeasurementKey']:
370
+ def _control_keys_(self) -> FrozenSet[cirq.MeasurementKey]:
351
371
  return self._control_keys
352
372
 
353
373
  def _is_parameterized_(self) -> bool:
@@ -358,14 +378,11 @@ class CircuitOperation(ops.Operation):
358
378
 
359
379
  def _parameter_names_generator(self) -> Iterator[str]:
360
380
  yield from protocols.parameter_names(self.repetitions)
361
- for symbol in protocols.parameter_symbols(self.circuit):
362
- for name in protocols.parameter_names(
363
- protocols.resolve_parameters(symbol, self.param_resolver, recursive=False)
364
- ):
365
- yield name
381
+ yield from protocols.parameter_names(self._mapped_repeat_until)
382
+ yield from protocols.parameter_names(self._mapped_any_loop)
366
383
 
367
384
  @cached_property
368
- def _mapped_any_loop(self) -> 'cirq.Circuit':
385
+ def _mapped_any_loop(self) -> cirq.Circuit:
369
386
  circuit = self.circuit.unfreeze()
370
387
  if self.qubit_map:
371
388
  circuit = circuit.transform_qubits(lambda q: self.qubit_map.get(q, q))
@@ -377,7 +394,7 @@ class CircuitOperation(ops.Operation):
377
394
  circuit = protocols.resolve_parameters(circuit, self.param_resolver, recursive=False)
378
395
  return circuit.unfreeze(copy=False)
379
396
 
380
- def _mapped_single_loop(self, repetition_id: Optional[str] = None) -> 'cirq.Circuit':
397
+ def _mapped_single_loop(self, repetition_id: Optional[str] = None) -> cirq.Circuit:
381
398
  circuit = self._mapped_any_loop
382
399
  if repetition_id:
383
400
  circuit = protocols.with_rescoped_keys(circuit, (repetition_id,))
@@ -385,7 +402,27 @@ class CircuitOperation(ops.Operation):
385
402
  circuit, self.parent_path, bindable_keys=self._extern_keys
386
403
  )
387
404
 
388
- def mapped_circuit(self, deep: bool = False) -> 'cirq.Circuit':
405
+ @cached_property
406
+ def _mapped_repeat_until(self) -> Optional[cirq.Condition]:
407
+ """Applies measurement_key_map, param_resolver, and current scope to repeat_until."""
408
+ repeat_until = self.repeat_until
409
+ if not repeat_until:
410
+ return repeat_until
411
+ if self.measurement_key_map:
412
+ repeat_until = protocols.with_measurement_key_mapping(
413
+ repeat_until, self.measurement_key_map
414
+ )
415
+ if self.param_resolver:
416
+ repeat_until = protocols.resolve_parameters(
417
+ repeat_until, self.param_resolver, recursive=False
418
+ )
419
+ return protocols.with_rescoped_keys(
420
+ repeat_until,
421
+ self.parent_path,
422
+ bindable_keys=self._extern_keys | self._measurement_key_objs,
423
+ )
424
+
425
+ def mapped_circuit(self, deep: bool = False) -> cirq.Circuit:
389
426
  """Applies all maps to the contained circuit and returns the result.
390
427
 
391
428
  Args:
@@ -413,20 +450,21 @@ class CircuitOperation(ops.Operation):
413
450
  )
414
451
  return circuit
415
452
 
416
- def mapped_op(self, deep: bool = False) -> 'cirq.CircuitOperation':
453
+ def mapped_op(self, deep: bool = False) -> cirq.CircuitOperation:
417
454
  """As `mapped_circuit`, but wraps the result in a CircuitOperation."""
418
455
  return CircuitOperation(circuit=self.mapped_circuit(deep=deep).freeze())
419
456
 
420
- def _decompose_(self) -> Iterator['cirq.Operation']:
457
+ def _decompose_(self) -> Iterator[cirq.Operation]:
421
458
  return self.mapped_circuit(deep=False).all_operations()
422
459
 
423
- def _act_on_(self, sim_state: 'cirq.SimulationStateBase') -> bool:
424
- if self.repeat_until:
460
+ def _act_on_(self, sim_state: cirq.SimulationStateBase) -> bool:
461
+ mapped_repeat_until = self._mapped_repeat_until
462
+ if mapped_repeat_until:
425
463
  circuit = self._mapped_single_loop()
426
464
  while True:
427
465
  for op in circuit.all_operations():
428
466
  protocols.act_on(op, sim_state)
429
- if self.repeat_until.resolve(sim_state.classical_data):
467
+ if mapped_repeat_until.resolve(sim_state.classical_data):
430
468
  break
431
469
  else:
432
470
  for op in self._decompose_():
@@ -508,6 +546,16 @@ class CircuitOperation(ops.Operation):
508
546
  def __hash__(self) -> int:
509
547
  return self._hash
510
548
 
549
+ def __getstate__(self) -> Dict[str, Any]:
550
+ # clear cached hash value when pickling, see #6674
551
+ state = self.__dict__
552
+ # cached_property stores value in the property-named attribute
553
+ hash_attr = "_hash"
554
+ if hash_attr in state:
555
+ state = state.copy()
556
+ del state[hash_attr]
557
+ return state
558
+
511
559
  def _json_dict_(self):
512
560
  resp = {
513
561
  'circuit': self.circuit,
@@ -556,7 +604,7 @@ class CircuitOperation(ops.Operation):
556
604
 
557
605
  def repeat(
558
606
  self, repetitions: Optional[IntParam] = None, repetition_ids: Optional[Sequence[str]] = None
559
- ) -> 'CircuitOperation':
607
+ ) -> CircuitOperation:
560
608
  """Returns a copy of this operation repeated 'repetitions' times.
561
609
  Each repetition instance will be identified by a single repetition_id.
562
610
 
@@ -608,7 +656,7 @@ class CircuitOperation(ops.Operation):
608
656
  final_repetitions = protocols.mul(self.repetitions, repetitions)
609
657
  return self.replace(repetitions=final_repetitions, repetition_ids=repetition_ids)
610
658
 
611
- def __pow__(self, power: IntParam) -> 'cirq.CircuitOperation':
659
+ def __pow__(self, power: IntParam) -> cirq.CircuitOperation:
612
660
  return self.repeat(power)
613
661
 
614
662
  def _with_key_path_(self, path: Tuple[str, ...]):
@@ -618,7 +666,7 @@ class CircuitOperation(ops.Operation):
618
666
  return self.replace(parent_path=prefix + self.parent_path)
619
667
 
620
668
  def _with_rescoped_keys_(
621
- self, path: Tuple[str, ...], bindable_keys: FrozenSet['cirq.MeasurementKey']
669
+ self, path: Tuple[str, ...], bindable_keys: FrozenSet[cirq.MeasurementKey]
622
670
  ):
623
671
  # The following line prevents binding to measurement keys in previous repeated subcircuits
624
672
  # "just because their repetition ids matched". If we eventually decide to change that
@@ -642,7 +690,7 @@ class CircuitOperation(ops.Operation):
642
690
  """
643
691
  return self._with_key_path_(path)
644
692
 
645
- def with_repetition_ids(self, repetition_ids: List[str]) -> 'cirq.CircuitOperation':
693
+ def with_repetition_ids(self, repetition_ids: List[str]) -> cirq.CircuitOperation:
646
694
  """Returns a copy of this `CircuitOperation` with the given repetition IDs.
647
695
 
648
696
  Args:
@@ -655,8 +703,8 @@ class CircuitOperation(ops.Operation):
655
703
  return self.replace(repetition_ids=repetition_ids)
656
704
 
657
705
  def with_qubit_mapping(
658
- self, qubit_map: Union[Mapping['cirq.Qid', 'cirq.Qid'], Callable[['cirq.Qid'], 'cirq.Qid']]
659
- ) -> 'cirq.CircuitOperation':
706
+ self, qubit_map: Union[Mapping[cirq.Qid, cirq.Qid], Callable[[cirq.Qid], cirq.Qid]]
707
+ ) -> cirq.CircuitOperation:
660
708
  """Returns a copy of this operation with an updated qubit mapping.
661
709
 
662
710
  Users should pass either 'qubit_map' or 'transform' to this method.
@@ -677,7 +725,7 @@ class CircuitOperation(ops.Operation):
677
725
  if callable(qubit_map):
678
726
  transform = qubit_map
679
727
  elif isinstance(qubit_map, dict):
680
- transform = lambda q: qubit_map.get(q, q) # type: ignore
728
+ transform = lambda q: qubit_map.get(q, q)
681
729
  else:
682
730
  raise TypeError('qubit_map must be a function or dict mapping qubits to qubits.')
683
731
  new_map = {}
@@ -695,7 +743,7 @@ class CircuitOperation(ops.Operation):
695
743
  )
696
744
  return new_op
697
745
 
698
- def with_qubits(self, *new_qubits: 'cirq.Qid') -> 'cirq.CircuitOperation':
746
+ def with_qubits(self, *new_qubits: cirq.Qid) -> cirq.CircuitOperation:
699
747
  """Returns a copy of this operation with an updated qubit mapping.
700
748
 
701
749
  Args:
@@ -715,7 +763,7 @@ class CircuitOperation(ops.Operation):
715
763
  raise ValueError(f'Expected {expected} qubits, got {len(new_qubits)}.')
716
764
  return self.with_qubit_mapping(dict(zip(self.qubits, new_qubits)))
717
765
 
718
- def with_measurement_key_mapping(self, key_map: Mapping[str, str]) -> 'cirq.CircuitOperation':
766
+ def with_measurement_key_mapping(self, key_map: Mapping[str, str]) -> cirq.CircuitOperation:
719
767
  """Returns a copy of this operation with an updated key mapping.
720
768
 
721
769
  Args:
@@ -749,12 +797,12 @@ class CircuitOperation(ops.Operation):
749
797
  )
750
798
  return new_op
751
799
 
752
- def _with_measurement_key_mapping_(self, key_map: Mapping[str, str]) -> 'cirq.CircuitOperation':
800
+ def _with_measurement_key_mapping_(self, key_map: Mapping[str, str]) -> cirq.CircuitOperation:
753
801
  return self.with_measurement_key_mapping(key_map)
754
802
 
755
803
  def with_params(
756
- self, param_values: 'cirq.ParamResolverOrSimilarType', recursive: bool = False
757
- ) -> 'cirq.CircuitOperation':
804
+ self, param_values: cirq.ParamResolverOrSimilarType, recursive: bool = False
805
+ ) -> cirq.CircuitOperation:
758
806
  """Returns a copy of this operation with an updated ParamResolver.
759
807
 
760
808
  Any existing parameter mappings will have their values updated given
@@ -780,7 +828,9 @@ class CircuitOperation(ops.Operation):
780
828
  by param_values.
781
829
  """
782
830
  new_params = {}
783
- for k in protocols.parameter_symbols(self.circuit):
831
+ for k in protocols.parameter_symbols(self.circuit) | protocols.parameter_symbols(
832
+ self.repeat_until
833
+ ):
784
834
  v = self.param_resolver.value_of(k, recursive=False)
785
835
  v = protocols.resolve_parameters(v, param_values, recursive=recursive)
786
836
  if v != k:
@@ -788,8 +838,8 @@ class CircuitOperation(ops.Operation):
788
838
  return self.replace(param_resolver=new_params)
789
839
 
790
840
  def _resolve_parameters_(
791
- self, resolver: 'cirq.ParamResolver', recursive: bool
792
- ) -> 'cirq.CircuitOperation':
841
+ self, resolver: cirq.ParamResolver, recursive: bool
842
+ ) -> cirq.CircuitOperation:
793
843
  resolved = self.with_params(resolver.param_dict, recursive)
794
844
  # repetitions can resolve to a float, but this is ok since constructor converts to
795
845
  # nearby int.
@@ -168,7 +168,7 @@ def test_with_qubits():
168
168
 
169
169
  assert op_base.with_qubit_mapping({a: d, b: c, d: a}) == op_with_qubits
170
170
 
171
- def map_fn(qubit: 'cirq.Qid') -> 'cirq.Qid':
171
+ def map_fn(qubit: cirq.Qid) -> cirq.Qid:
172
172
  if qubit == a:
173
173
  return d
174
174
  if qubit == b:
@@ -327,9 +327,33 @@ def test_repeat(add_measurements: bool, use_default_ids_for_initial_rep: bool) -
327
327
  _ = op_base.repeat()
328
328
 
329
329
  with pytest.raises(TypeError, match='Only integer or sympy repetitions are allowed'):
330
- _ = op_base.repeat(1.3) # type: ignore[arg-type]
331
- assert op_base.repeat(3.00000000001).repetitions == 3 # type: ignore[arg-type]
332
- assert op_base.repeat(2.99999999999).repetitions == 3 # type: ignore[arg-type]
330
+ _ = op_base.repeat(1.3)
331
+ assert op_base.repeat(3.00000000001).repetitions == 3
332
+ assert op_base.repeat(2.99999999999).repetitions == 3
333
+
334
+
335
+ # TODO: #7232 - enable and fix immediately after the 1.5.0 release
336
+ @pytest.mark.xfail(reason='broken by rollback of use_repetition_ids for #7232')
337
+ def test_replace_repetition_ids() -> None:
338
+ a, b = cirq.LineQubit.range(2)
339
+ circuit = cirq.Circuit(cirq.H(a), cirq.CX(a, b), cirq.M(b, key='mb'), cirq.M(a, key='ma'))
340
+ op = cirq.CircuitOperation(circuit.freeze())
341
+ assert op.repetitions == 1
342
+ assert not op.use_repetition_ids
343
+
344
+ op2 = op.replace(repetitions=2)
345
+ assert op2.repetitions == 2
346
+ assert not op2.use_repetition_ids
347
+
348
+ op3 = op.replace(repetitions=3, repetition_ids=None)
349
+ assert op3.repetitions == 3
350
+ assert not op3.use_repetition_ids
351
+
352
+ # Passing `repetition_ids` will also enable `use_repetition_ids`
353
+ op4 = op.replace(repetitions=4, repetition_ids=['a', 'b', 'c', 'd'])
354
+ assert op4.repetitions == 4
355
+ assert op4.use_repetition_ids
356
+ assert op4.repetition_ids == ['a', 'b', 'c', 'd']
333
357
 
334
358
 
335
359
  @pytest.mark.parametrize('add_measurements', [True, False])
@@ -1204,4 +1228,61 @@ def test_repeat_until_error():
1204
1228
  )
1205
1229
 
1206
1230
 
1231
+ def test_repeat_until_protocols():
1232
+ q = cirq.LineQubit(0)
1233
+ op = cirq.CircuitOperation(
1234
+ cirq.FrozenCircuit(cirq.H(q) ** sympy.Symbol('p'), cirq.measure(q, key='a')),
1235
+ repeat_until=cirq.SympyCondition(sympy.Eq(sympy.Symbol('a'), 0)),
1236
+ # TODO: #7232 - remove immediately after the 1.5.0 release
1237
+ use_repetition_ids=False,
1238
+ )
1239
+ scoped = cirq.with_rescoped_keys(op, ('0',))
1240
+ # Ensure the _repeat_until has been mapped, the measurement has been mapped to the same key,
1241
+ # and the control keys of the subcircuit is empty (because the control key of the condition is
1242
+ # bound to the measurement).
1243
+ assert scoped._mapped_repeat_until.keys == (cirq.MeasurementKey('a', ('0',)),)
1244
+ assert cirq.measurement_key_objs(scoped) == {cirq.MeasurementKey('a', ('0',))}
1245
+ assert not cirq.control_keys(scoped)
1246
+ mapped = cirq.with_measurement_key_mapping(scoped, {'a': 'b'})
1247
+ assert mapped._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('0',)),)
1248
+ assert cirq.measurement_key_objs(mapped) == {cirq.MeasurementKey('b', ('0',))}
1249
+ assert not cirq.control_keys(mapped)
1250
+ prefixed = cirq.with_key_path_prefix(mapped, ('1',))
1251
+ assert prefixed._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('1', '0')),)
1252
+ assert cirq.measurement_key_objs(prefixed) == {cirq.MeasurementKey('b', ('1', '0'))}
1253
+ assert not cirq.control_keys(prefixed)
1254
+ setpath = cirq.with_key_path(prefixed, ('2',))
1255
+ assert setpath._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('2',)),)
1256
+ assert cirq.measurement_key_objs(setpath) == {cirq.MeasurementKey('b', ('2',))}
1257
+ assert not cirq.control_keys(setpath)
1258
+ resolved = cirq.resolve_parameters(setpath, {'p': 1})
1259
+ assert resolved._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('2',)),)
1260
+ assert cirq.measurement_key_objs(resolved) == {cirq.MeasurementKey('b', ('2',))}
1261
+ assert not cirq.control_keys(resolved)
1262
+
1263
+
1264
+ def test_inner_repeat_until_simulate():
1265
+ sim = cirq.Simulator()
1266
+ q = cirq.LineQubit(0)
1267
+ inner_loop = cirq.CircuitOperation(
1268
+ cirq.FrozenCircuit(cirq.H(q), cirq.measure(q, key="inner_loop")),
1269
+ repeat_until=cirq.SympyCondition(sympy.Eq(sympy.Symbol("inner_loop"), 0)),
1270
+ # TODO: #7232 - remove immediately after the 1.5.0 release
1271
+ use_repetition_ids=False,
1272
+ )
1273
+ outer_loop = cirq.Circuit(inner_loop, cirq.X(q), cirq.measure(q, key="outer_loop"))
1274
+ circuit = cirq.Circuit(
1275
+ cirq.CircuitOperation(
1276
+ cirq.FrozenCircuit(outer_loop), repetitions=2, use_repetition_ids=True
1277
+ )
1278
+ )
1279
+ result = sim.run(circuit, repetitions=1)
1280
+ assert all(len(v) == 1 and v[0] == 1 for v in result.records['0:inner_loop'][0][:-1])
1281
+ assert result.records['0:inner_loop'][0][-1] == [0]
1282
+ assert result.records['0:outer_loop'] == [[[1]]]
1283
+ assert all(len(v) == 1 and v[0] == 1 for v in result.records['1:inner_loop'][0][:-1])
1284
+ assert result.records['1:inner_loop'][0][-1] == [0]
1285
+ assert result.records['1:outer_loop'] == [[[1]]]
1286
+
1287
+
1207
1288
  # TODO: Operation has a "gate" property. What is this for a CircuitOperation?