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

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

Potentially problematic release.


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

Files changed (590) hide show
  1. cirq/__init__.py +587 -569
  2. cirq/_compat.py +9 -0
  3. cirq/_compat_test.py +11 -9
  4. cirq/_import.py +7 -8
  5. cirq/_version.py +31 -1
  6. cirq/_version_test.py +1 -1
  7. cirq/circuits/__init__.py +15 -9
  8. cirq/circuits/_block_diagram_drawer.py +1 -2
  9. cirq/circuits/_block_diagram_drawer_test.py +3 -3
  10. cirq/circuits/_box_drawing_character_data.py +0 -1
  11. cirq/circuits/_box_drawing_character_data_test.py +2 -2
  12. cirq/circuits/_bucket_priority_queue.py +0 -1
  13. cirq/circuits/_bucket_priority_queue_test.py +1 -1
  14. cirq/circuits/circuit.py +336 -234
  15. cirq/circuits/circuit_operation.py +102 -52
  16. cirq/circuits/circuit_operation_test.py +85 -4
  17. cirq/circuits/circuit_test.py +101 -32
  18. cirq/circuits/frozen_circuit.py +36 -32
  19. cirq/circuits/insert_strategy.py +10 -0
  20. cirq/circuits/insert_strategy_test.py +20 -0
  21. cirq/circuits/moment.py +79 -80
  22. cirq/circuits/moment_test.py +105 -2
  23. cirq/circuits/optimization_pass.py +15 -15
  24. cirq/circuits/optimization_pass_test.py +8 -9
  25. cirq/circuits/qasm_output.py +64 -33
  26. cirq/circuits/qasm_output_test.py +63 -2
  27. cirq/circuits/text_diagram_drawer.py +26 -56
  28. cirq/circuits/text_diagram_drawer_test.py +5 -4
  29. cirq/contrib/__init__.py +2 -2
  30. cirq/contrib/acquaintance/__init__.py +44 -29
  31. cirq/contrib/acquaintance/bipartite.py +8 -7
  32. cirq/contrib/acquaintance/bipartite_test.py +11 -1
  33. cirq/contrib/acquaintance/devices.py +5 -4
  34. cirq/contrib/acquaintance/devices_test.py +5 -1
  35. cirq/contrib/acquaintance/executor.py +18 -21
  36. cirq/contrib/acquaintance/executor_test.py +3 -2
  37. cirq/contrib/acquaintance/gates.py +36 -27
  38. cirq/contrib/acquaintance/gates_test.py +1 -1
  39. cirq/contrib/acquaintance/inspection_utils.py +10 -9
  40. cirq/contrib/acquaintance/inspection_utils_test.py +6 -1
  41. cirq/contrib/acquaintance/mutation_utils.py +10 -10
  42. cirq/contrib/acquaintance/optimizers.py +7 -6
  43. cirq/contrib/acquaintance/optimizers_test.py +1 -1
  44. cirq/contrib/acquaintance/permutation.py +22 -21
  45. cirq/contrib/acquaintance/permutation_test.py +1 -1
  46. cirq/contrib/acquaintance/shift.py +8 -6
  47. cirq/contrib/acquaintance/shift_swap_network.py +6 -4
  48. cirq/contrib/acquaintance/strategies/__init__.py +9 -3
  49. cirq/contrib/acquaintance/strategies/complete.py +4 -3
  50. cirq/contrib/acquaintance/strategies/cubic.py +5 -3
  51. cirq/contrib/acquaintance/strategies/quartic_paired.py +8 -6
  52. cirq/contrib/acquaintance/topological_sort.py +4 -2
  53. cirq/contrib/bayesian_network/__init__.py +3 -1
  54. cirq/contrib/bayesian_network/bayesian_network_gate.py +5 -3
  55. cirq/contrib/circuitdag/__init__.py +1 -1
  56. cirq/contrib/circuitdag/circuit_dag.py +24 -24
  57. cirq/contrib/circuitdag/circuit_dag_test.py +1 -1
  58. cirq/contrib/custom_simulators/custom_state_simulator.py +10 -8
  59. cirq/contrib/custom_simulators/custom_state_simulator_test.py +15 -11
  60. cirq/contrib/graph_device/__init__.py +8 -8
  61. cirq/contrib/graph_device/graph_device.py +8 -8
  62. cirq/contrib/graph_device/graph_device_test.py +0 -1
  63. cirq/contrib/graph_device/hypergraph_test.py +1 -0
  64. cirq/contrib/json.py +1 -2
  65. cirq/contrib/json_test.py +2 -2
  66. cirq/contrib/noise_models/__init__.py +5 -6
  67. cirq/contrib/noise_models/noise_models.py +8 -6
  68. cirq/contrib/paulistring/__init__.py +22 -10
  69. cirq/contrib/paulistring/clifford_optimize.py +1 -1
  70. cirq/contrib/paulistring/clifford_optimize_test.py +0 -1
  71. cirq/contrib/paulistring/clifford_target_gateset.py +15 -12
  72. cirq/contrib/paulistring/optimize.py +2 -2
  73. cirq/contrib/paulistring/optimize_test.py +0 -1
  74. cirq/contrib/paulistring/pauli_string_dag_test.py +0 -1
  75. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +379 -0
  76. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +523 -0
  77. cirq/contrib/paulistring/pauli_string_optimize.py +3 -1
  78. cirq/contrib/paulistring/pauli_string_optimize_test.py +1 -3
  79. cirq/contrib/paulistring/recombine.py +2 -2
  80. cirq/contrib/paulistring/recombine_test.py +2 -2
  81. cirq/contrib/paulistring/separate.py +3 -4
  82. cirq/contrib/qasm_import/__init__.py +2 -2
  83. cirq/contrib/qasm_import/_lexer.py +21 -26
  84. cirq/contrib/qasm_import/_lexer_test.py +90 -6
  85. cirq/contrib/qasm_import/_parser.py +238 -47
  86. cirq/contrib/qasm_import/_parser_test.py +514 -59
  87. cirq/contrib/qasm_import/qasm_test.py +1 -1
  88. cirq/contrib/qcircuit/__init__.py +6 -4
  89. cirq/contrib/qcircuit/qcircuit_diagram.py +5 -2
  90. cirq/contrib/qcircuit/qcircuit_pdf.py +1 -2
  91. cirq/{experiments/grid_parallel_two_qubit_xeb_test.py → contrib/qcircuit/qcircuit_pdf_test.py} +13 -12
  92. cirq/contrib/qcircuit/qcircuit_test.py +1 -1
  93. cirq/contrib/quantum_volume/__init__.py +7 -7
  94. cirq/contrib/quantum_volume/quantum_volume.py +6 -11
  95. cirq/contrib/quantum_volume/quantum_volume_test.py +3 -1
  96. cirq/contrib/quimb/__init__.py +16 -13
  97. cirq/contrib/quimb/density_matrix.py +1 -1
  98. cirq/contrib/quimb/mps_simulator.py +27 -28
  99. cirq/contrib/quimb/mps_simulator_test.py +5 -0
  100. cirq/contrib/quimb/state_vector.py +3 -10
  101. cirq/contrib/quirk/__init__.py +1 -1
  102. cirq/contrib/quirk/export_to_quirk.py +3 -3
  103. cirq/contrib/routing/__init__.py +12 -9
  104. cirq/contrib/routing/device.py +1 -1
  105. cirq/contrib/routing/device_test.py +1 -2
  106. cirq/contrib/routing/greedy.py +7 -5
  107. cirq/contrib/routing/greedy_test.py +5 -3
  108. cirq/contrib/routing/initialization.py +3 -1
  109. cirq/contrib/routing/initialization_test.py +1 -1
  110. cirq/contrib/routing/swap_network.py +6 -6
  111. cirq/contrib/routing/utils.py +6 -4
  112. cirq/contrib/routing/utils_test.py +1 -2
  113. cirq/{type_workarounds.py → contrib/shuffle_circuits/__init__.py} +5 -10
  114. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +250 -0
  115. cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking_test.py +363 -0
  116. cirq/contrib/svg/__init__.py +1 -1
  117. cirq/contrib/svg/svg.py +12 -10
  118. cirq/contrib/svg/svg_test.py +3 -2
  119. cirq/devices/__init__.py +34 -25
  120. cirq/devices/device.py +16 -12
  121. cirq/devices/device_test.py +1 -0
  122. cirq/devices/grid_device_metadata.py +16 -12
  123. cirq/devices/grid_device_metadata_test.py +2 -1
  124. cirq/devices/grid_qubit.py +31 -26
  125. cirq/devices/grid_qubit_test.py +30 -1
  126. cirq/devices/insertion_noise_model.py +6 -6
  127. cirq/devices/insertion_noise_model_test.py +1 -1
  128. cirq/devices/line_qubit.py +28 -20
  129. cirq/devices/line_qubit_test.py +26 -0
  130. cirq/devices/named_topologies.py +12 -10
  131. cirq/devices/named_topologies_test.py +5 -4
  132. cirq/devices/noise_model.py +29 -33
  133. cirq/devices/noise_properties.py +2 -2
  134. cirq/devices/noise_properties_test.py +2 -2
  135. cirq/devices/noise_utils.py +3 -3
  136. cirq/devices/superconducting_qubits_noise_properties.py +2 -2
  137. cirq/devices/superconducting_qubits_noise_properties_test.py +3 -3
  138. cirq/devices/thermal_noise_model.py +2 -1
  139. cirq/devices/unconstrained_device.py +1 -1
  140. cirq/devices/unconstrained_device_test.py +6 -0
  141. cirq/experiments/__init__.py +51 -34
  142. cirq/experiments/qubit_characterizations.py +17 -15
  143. cirq/experiments/qubit_characterizations_test.py +4 -6
  144. cirq/experiments/random_quantum_circuit_generation.py +10 -9
  145. cirq/experiments/random_quantum_circuit_generation_test.py +21 -4
  146. cirq/experiments/readout_confusion_matrix.py +73 -8
  147. cirq/experiments/readout_confusion_matrix_test.py +104 -1
  148. cirq/experiments/single_qubit_readout_calibration.py +8 -6
  149. cirq/experiments/single_qubit_readout_calibration_test.py +1 -1
  150. cirq/experiments/t1_decay_experiment.py +4 -5
  151. cirq/experiments/t1_decay_experiment_test.py +1 -2
  152. cirq/experiments/t2_decay_experiment.py +0 -1
  153. cirq/experiments/t2_decay_experiment_test.py +1 -2
  154. cirq/experiments/two_qubit_xeb.py +157 -33
  155. cirq/experiments/two_qubit_xeb_test.py +38 -22
  156. cirq/experiments/xeb_fitting.py +99 -19
  157. cirq/experiments/xeb_fitting_test.py +64 -25
  158. cirq/experiments/xeb_sampling.py +14 -18
  159. cirq/experiments/xeb_simulation.py +4 -3
  160. cirq/experiments/xeb_simulation_test.py +20 -14
  161. cirq/experiments/z_phase_calibration.py +368 -0
  162. cirq/experiments/z_phase_calibration_test.py +241 -0
  163. cirq/interop/__init__.py +4 -1
  164. cirq/interop/quirk/__init__.py +7 -4
  165. cirq/interop/quirk/cells/__init__.py +17 -6
  166. cirq/interop/quirk/cells/arithmetic_cells.py +8 -8
  167. cirq/interop/quirk/cells/arithmetic_cells_test.py +1 -1
  168. cirq/interop/quirk/cells/cell.py +6 -6
  169. cirq/interop/quirk/cells/composite_cell.py +5 -5
  170. cirq/interop/quirk/cells/composite_cell_test.py +1 -1
  171. cirq/interop/quirk/cells/control_cells.py +1 -1
  172. cirq/interop/quirk/cells/frequency_space_cells.py +2 -2
  173. cirq/interop/quirk/cells/ignored_cells.py +1 -1
  174. cirq/interop/quirk/cells/input_cells.py +1 -1
  175. cirq/interop/quirk/cells/input_cells_test.py +1 -1
  176. cirq/interop/quirk/cells/input_rotation_cells.py +1 -1
  177. cirq/interop/quirk/cells/input_rotation_cells_test.py +1 -1
  178. cirq/interop/quirk/cells/measurement_cells.py +1 -1
  179. cirq/interop/quirk/cells/parse.py +8 -7
  180. cirq/interop/quirk/cells/parse_test.py +2 -2
  181. cirq/interop/quirk/cells/single_qubit_rotation_cells.py +1 -1
  182. cirq/interop/quirk/cells/swap_cell_test.py +1 -1
  183. cirq/interop/quirk/cells/unsupported_cells.py +1 -1
  184. cirq/interop/quirk/url_to_circuit.py +7 -7
  185. cirq/interop/quirk/url_to_circuit_test.py +1 -1
  186. cirq/ion/__init__.py +4 -2
  187. cirq/json_resolver_cache.py +15 -7
  188. cirq/linalg/__init__.py +62 -51
  189. cirq/linalg/combinators.py +4 -4
  190. cirq/linalg/combinators_test.py +4 -1
  191. cirq/linalg/decompositions.py +15 -40
  192. cirq/linalg/decompositions_test.py +16 -22
  193. cirq/linalg/diagonalize.py +1 -1
  194. cirq/linalg/diagonalize_test.py +1 -1
  195. cirq/linalg/operator_spaces.py +20 -4
  196. cirq/linalg/operator_spaces_test.py +15 -2
  197. cirq/linalg/predicates.py +3 -3
  198. cirq/linalg/predicates_test.py +1 -0
  199. cirq/linalg/tolerance.py +2 -2
  200. cirq/linalg/transformations.py +30 -12
  201. cirq/linalg/transformations_test.py +13 -0
  202. cirq/neutral_atoms/__init__.py +2 -2
  203. cirq/neutral_atoms/convert_to_neutral_atom_gates_test.py +0 -1
  204. cirq/ops/__init__.py +172 -132
  205. cirq/ops/arithmetic_operation.py +2 -2
  206. cirq/ops/arithmetic_operation_test.py +2 -2
  207. cirq/ops/boolean_hamiltonian.py +3 -2
  208. cirq/ops/classically_controlled_operation.py +39 -12
  209. cirq/ops/classically_controlled_operation_test.py +147 -1
  210. cirq/ops/clifford_gate.py +38 -36
  211. cirq/ops/clifford_gate_test.py +75 -1
  212. cirq/ops/common_channels.py +16 -45
  213. cirq/ops/common_channels_test.py +10 -0
  214. cirq/ops/common_gate_families.py +1 -1
  215. cirq/ops/common_gate_families_test.py +1 -0
  216. cirq/ops/common_gates.py +48 -49
  217. cirq/ops/common_gates_test.py +18 -2
  218. cirq/ops/control_values.py +3 -3
  219. cirq/ops/control_values_test.py +2 -1
  220. cirq/ops/controlled_gate.py +36 -23
  221. cirq/ops/controlled_gate_test.py +70 -3
  222. cirq/ops/controlled_operation.py +6 -5
  223. cirq/ops/controlled_operation_test.py +7 -3
  224. cirq/ops/dense_pauli_string.py +11 -11
  225. cirq/ops/diagonal_gate.py +2 -2
  226. cirq/ops/diagonal_gate_test.py +1 -0
  227. cirq/ops/eigen_gate.py +16 -36
  228. cirq/ops/eigen_gate_test.py +60 -10
  229. cirq/ops/fourier_transform.py +1 -3
  230. cirq/ops/fourier_transform_test.py +2 -1
  231. cirq/ops/fsim_gate.py +42 -3
  232. cirq/ops/fsim_gate_test.py +21 -0
  233. cirq/ops/gate_operation.py +8 -8
  234. cirq/ops/gate_operation_test.py +4 -2
  235. cirq/ops/gateset_test.py +11 -2
  236. cirq/ops/global_phase_op.py +8 -7
  237. cirq/ops/global_phase_op_test.py +1 -1
  238. cirq/ops/greedy_qubit_manager_test.py +5 -0
  239. cirq/ops/identity.py +14 -4
  240. cirq/ops/identity_test.py +24 -0
  241. cirq/ops/kraus_channel.py +1 -0
  242. cirq/ops/kraus_channel_test.py +3 -1
  243. cirq/ops/linear_combinations.py +27 -21
  244. cirq/ops/linear_combinations_test.py +23 -4
  245. cirq/ops/matrix_gates.py +24 -8
  246. cirq/ops/measure_util.py +2 -2
  247. cirq/ops/measurement_gate.py +7 -4
  248. cirq/ops/measurement_gate_test.py +2 -1
  249. cirq/ops/mixed_unitary_channel.py +1 -0
  250. cirq/ops/mixed_unitary_channel_test.py +3 -1
  251. cirq/ops/named_qubit.py +8 -1
  252. cirq/ops/op_tree.py +3 -30
  253. cirq/ops/op_tree_test.py +4 -0
  254. cirq/ops/parallel_gate.py +2 -3
  255. cirq/ops/parallel_gate_test.py +2 -1
  256. cirq/ops/parity_gates.py +7 -8
  257. cirq/ops/parity_gates_test.py +1 -0
  258. cirq/ops/pauli_gates.py +5 -11
  259. cirq/ops/pauli_gates_test.py +1 -0
  260. cirq/ops/pauli_interaction_gate.py +11 -5
  261. cirq/ops/pauli_interaction_gate_test.py +2 -3
  262. cirq/ops/pauli_measurement_gate.py +6 -5
  263. cirq/ops/pauli_measurement_gate_test.py +1 -0
  264. cirq/ops/pauli_string.py +115 -130
  265. cirq/ops/pauli_string_phasor.py +21 -20
  266. cirq/ops/pauli_string_phasor_test.py +13 -3
  267. cirq/ops/pauli_string_raw_types.py +1 -0
  268. cirq/ops/pauli_string_test.py +192 -55
  269. cirq/ops/pauli_sum_exponential.py +3 -4
  270. cirq/ops/pauli_sum_exponential_test.py +0 -1
  271. cirq/ops/permutation_gate.py +2 -2
  272. cirq/ops/permutation_gate_test.py +1 -1
  273. cirq/ops/phased_iswap_gate.py +6 -7
  274. cirq/ops/phased_iswap_gate_test.py +21 -5
  275. cirq/ops/phased_x_gate.py +11 -25
  276. cirq/ops/phased_x_gate_test.py +19 -3
  277. cirq/ops/phased_x_z_gate.py +12 -11
  278. cirq/ops/projector.py +4 -5
  279. cirq/ops/qubit_manager.py +2 -1
  280. cirq/ops/qubit_manager_test.py +2 -1
  281. cirq/ops/qubit_order.py +1 -1
  282. cirq/ops/random_gate_channel.py +1 -1
  283. cirq/ops/random_gate_channel_test.py +0 -6
  284. cirq/ops/raw_types.py +146 -50
  285. cirq/ops/raw_types_test.py +37 -3
  286. cirq/ops/state_preparation_channel.py +2 -2
  287. cirq/ops/state_preparation_channel_test.py +2 -1
  288. cirq/ops/swap_gates.py +9 -4
  289. cirq/ops/three_qubit_gates.py +8 -8
  290. cirq/ops/three_qubit_gates_test.py +1 -0
  291. cirq/ops/two_qubit_diagonal_gate.py +4 -3
  292. cirq/ops/uniform_superposition_gate.py +4 -4
  293. cirq/ops/uniform_superposition_gate_test.py +1 -0
  294. cirq/ops/wait_gate.py +6 -8
  295. cirq/protocols/__init__.py +135 -83
  296. cirq/protocols/act_on_protocol.py +1 -1
  297. cirq/protocols/act_on_protocol_test.py +1 -1
  298. cirq/protocols/apply_channel_protocol.py +3 -3
  299. cirq/protocols/apply_mixture_protocol.py +15 -9
  300. cirq/protocols/apply_mixture_protocol_test.py +11 -0
  301. cirq/protocols/apply_unitary_protocol.py +2 -2
  302. cirq/protocols/apply_unitary_protocol_test.py +2 -1
  303. cirq/protocols/approximate_equality_protocol.py +7 -8
  304. cirq/protocols/approximate_equality_protocol_test.py +3 -1
  305. cirq/protocols/circuit_diagram_info_protocol.py +8 -6
  306. cirq/protocols/circuit_diagram_info_protocol_test.py +5 -0
  307. cirq/protocols/commutes_protocol.py +6 -6
  308. cirq/protocols/control_key_protocol.py +1 -1
  309. cirq/protocols/decompose_protocol.py +4 -5
  310. cirq/protocols/decompose_protocol_test.py +2 -1
  311. cirq/protocols/equal_up_to_global_phase_protocol.py +3 -3
  312. cirq/protocols/equal_up_to_global_phase_protocol_test.py +7 -0
  313. cirq/protocols/has_stabilizer_effect_protocol.py +5 -5
  314. cirq/protocols/has_unitary_protocol.py +1 -1
  315. cirq/protocols/has_unitary_protocol_test.py +8 -7
  316. cirq/protocols/hash_from_pickle_test.py +120 -0
  317. cirq/protocols/inverse_protocol.py +1 -1
  318. cirq/protocols/json_serialization.py +14 -1
  319. cirq/protocols/json_serialization_test.py +28 -7
  320. cirq/protocols/json_test_data/BitMaskKeyCondition.json +86 -0
  321. cirq/protocols/json_test_data/BitMaskKeyCondition.repr +7 -0
  322. cirq/protocols/json_test_data/Concat.json +19 -0
  323. cirq/protocols/json_test_data/Concat.repr +1 -0
  324. cirq/protocols/json_test_data/README.md +4 -2
  325. cirq/protocols/json_test_data/SympyCondition.json +60 -15
  326. cirq/protocols/json_test_data/SympyCondition.repr +4 -1
  327. cirq/protocols/json_test_data/_InverseCompositeGate.json +10 -0
  328. cirq/protocols/json_test_data/_InverseCompositeGate.repr +1 -0
  329. cirq/protocols/json_test_data/__init__.py +1 -1
  330. cirq/protocols/json_test_data/sympy.And.json +13 -0
  331. cirq/protocols/json_test_data/sympy.And.repr +1 -0
  332. cirq/protocols/json_test_data/sympy.Indexed.json +18 -0
  333. cirq/protocols/json_test_data/sympy.Indexed.repr +1 -0
  334. cirq/protocols/json_test_data/sympy.IndexedBase.json +9 -0
  335. cirq/protocols/json_test_data/sympy.IndexedBase.repr +1 -0
  336. cirq/protocols/json_test_data/sympy.Not.json +9 -0
  337. cirq/protocols/json_test_data/sympy.Not.repr +1 -0
  338. cirq/protocols/json_test_data/sympy.Or.json +13 -0
  339. cirq/protocols/json_test_data/sympy.Or.repr +1 -0
  340. cirq/protocols/json_test_data/sympy.Xor.json +13 -0
  341. cirq/protocols/json_test_data/sympy.Xor.repr +1 -0
  342. cirq/protocols/kraus_protocol.py +8 -8
  343. cirq/protocols/kraus_protocol_test.py +0 -1
  344. cirq/protocols/measurement_key_protocol.py +1 -1
  345. cirq/protocols/measurement_key_protocol_test.py +7 -7
  346. cirq/protocols/mixture_protocol.py +6 -4
  347. cirq/protocols/mixture_protocol_test.py +21 -13
  348. cirq/protocols/pauli_expansion_protocol.py +1 -0
  349. cirq/protocols/pow_protocol.py +1 -1
  350. cirq/protocols/qasm.py +25 -6
  351. cirq/protocols/qasm_test.py +17 -0
  352. cirq/protocols/qid_shape_protocol.py +2 -2
  353. cirq/protocols/resolve_parameters.py +2 -3
  354. cirq/protocols/resolve_parameters_test.py +2 -1
  355. cirq/protocols/trace_distance_bound.py +1 -1
  356. cirq/protocols/trace_distance_bound_test.py +1 -0
  357. cirq/protocols/unitary_protocol.py +3 -3
  358. cirq/protocols/unitary_protocol_test.py +1 -1
  359. cirq/qis/__init__.py +48 -35
  360. cirq/qis/channels_test.py +0 -9
  361. cirq/qis/clifford_tableau.py +46 -26
  362. cirq/qis/clifford_tableau_test.py +2 -1
  363. cirq/qis/entropy.py +115 -0
  364. cirq/qis/entropy_test.py +43 -0
  365. cirq/qis/measures.py +5 -4
  366. cirq/qis/measures_test.py +7 -0
  367. cirq/qis/noise_utils_test.py +4 -4
  368. cirq/qis/quantum_state_representation.py +1 -1
  369. cirq/qis/states.py +7 -7
  370. cirq/sim/__init__.py +55 -37
  371. cirq/sim/classical_simulator.py +7 -6
  372. cirq/sim/classical_simulator_test.py +3 -1
  373. cirq/sim/clifford/__init__.py +17 -9
  374. cirq/sim/clifford/clifford_simulator.py +5 -4
  375. cirq/sim/clifford/clifford_simulator_test.py +32 -9
  376. cirq/sim/clifford/clifford_tableau_simulation_state.py +1 -1
  377. cirq/sim/clifford/stabilizer_simulation_state.py +1 -1
  378. cirq/sim/clifford/stabilizer_state_ch_form.py +4 -3
  379. cirq/sim/density_matrix_simulator.py +3 -2
  380. cirq/sim/density_matrix_simulator_test.py +12 -4
  381. cirq/sim/density_matrix_utils.py +1 -1
  382. cirq/sim/mux.py +2 -2
  383. cirq/sim/simulation_state.py +4 -5
  384. cirq/sim/simulation_state_base.py +2 -2
  385. cirq/sim/simulation_state_test.py +1 -1
  386. cirq/sim/simulation_utils.py +3 -1
  387. cirq/sim/simulation_utils_test.py +2 -3
  388. cirq/sim/simulator.py +7 -6
  389. cirq/sim/simulator_base.py +5 -5
  390. cirq/sim/simulator_test.py +14 -3
  391. cirq/sim/sparse_simulator.py +4 -3
  392. cirq/sim/sparse_simulator_test.py +17 -9
  393. cirq/sim/state_vector.py +2 -2
  394. cirq/sim/state_vector_simulation_state_test.py +1 -1
  395. cirq/sim/state_vector_simulator.py +4 -4
  396. cirq/sim/state_vector_test.py +27 -32
  397. cirq/study/__init__.py +27 -21
  398. cirq/study/flatten_expressions.py +5 -6
  399. cirq/study/flatten_expressions_test.py +1 -1
  400. cirq/study/resolver.py +14 -11
  401. cirq/study/resolver_test.py +10 -1
  402. cirq/study/result.py +3 -3
  403. cirq/study/sweepable.py +15 -9
  404. cirq/study/sweepable_test.py +27 -0
  405. cirq/study/sweeps.py +65 -10
  406. cirq/study/sweeps_test.py +123 -0
  407. cirq/testing/__init__.py +86 -57
  408. cirq/testing/_compat_test_data/module_a/__init__.py +2 -2
  409. cirq/testing/_compat_test_data/module_a/sub/subsub/__init__.py +1 -1
  410. cirq/testing/circuit_compare.py +3 -4
  411. cirq/testing/circuit_compare_test.py +7 -8
  412. cirq/testing/consistent_act_on.py +3 -3
  413. cirq/testing/consistent_channels_test.py +2 -1
  414. cirq/testing/consistent_controlled_gate_op.py +3 -2
  415. cirq/testing/consistent_controlled_gate_op_test.py +2 -3
  416. cirq/testing/consistent_decomposition.py +1 -1
  417. cirq/testing/consistent_decomposition_test.py +1 -2
  418. cirq/testing/consistent_pauli_expansion_test.py +1 -1
  419. cirq/testing/consistent_phase_by.py +1 -1
  420. cirq/testing/consistent_phase_by_test.py +1 -2
  421. cirq/testing/consistent_protocols.py +11 -11
  422. cirq/testing/consistent_protocols_test.py +4 -5
  423. cirq/testing/consistent_qasm.py +8 -12
  424. cirq/testing/consistent_qasm_test.py +1 -1
  425. cirq/testing/consistent_resolve_parameters.py +2 -1
  426. cirq/testing/consistent_specified_has_unitary_test.py +1 -1
  427. cirq/testing/consistent_unitary.py +3 -1
  428. cirq/testing/consistent_unitary_test.py +3 -3
  429. cirq/testing/devices.py +1 -1
  430. cirq/testing/devices_test.py +1 -0
  431. cirq/testing/equals_tester.py +2 -4
  432. cirq/testing/equals_tester_test.py +6 -5
  433. cirq/testing/equivalent_basis_map.py +1 -0
  434. cirq/testing/equivalent_basis_map_test.py +0 -1
  435. cirq/testing/gate_features_test.py +5 -0
  436. cirq/testing/json.py +4 -4
  437. cirq/testing/lin_alg_utils_test.py +1 -1
  438. cirq/testing/order_tester.py +1 -1
  439. cirq/testing/order_tester_test.py +1 -1
  440. cirq/testing/pytest_utils.py +57 -0
  441. cirq/testing/pytest_utils_test.py +35 -0
  442. cirq/testing/random_circuit.py +2 -2
  443. cirq/testing/random_circuit_test.py +2 -2
  444. cirq/testing/routing_devices_test.py +2 -1
  445. cirq/testing/sample_circuits.py +1 -1
  446. cirq/testing/sample_gates.py +5 -4
  447. cirq/testing/sample_gates_test.py +2 -2
  448. cirq/transformers/__init__.py +101 -82
  449. cirq/transformers/align.py +12 -1
  450. cirq/transformers/align_test.py +13 -0
  451. cirq/transformers/analytical_decompositions/__init__.py +27 -24
  452. cirq/transformers/analytical_decompositions/clifford_decomposition.py +2 -1
  453. cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +1 -1
  454. cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +1 -1
  455. cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +2 -0
  456. cirq/transformers/analytical_decompositions/cphase_to_fsim.py +1 -1
  457. cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +1 -1
  458. cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +2 -2
  459. cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +4 -4
  460. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +99 -24
  461. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +105 -14
  462. cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +1 -1
  463. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +1 -1
  464. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +1 -0
  465. cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +3 -4
  466. cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +1 -1
  467. cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +2 -1
  468. cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +2 -1
  469. cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +5 -6
  470. cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +2 -2
  471. cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +1 -1
  472. cirq/transformers/analytical_decompositions/two_qubit_to_fsim_test.py +1 -2
  473. cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +2 -2
  474. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +2 -2
  475. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +2 -1
  476. cirq/transformers/drop_empty_moments.py +1 -0
  477. cirq/transformers/drop_negligible_operations.py +1 -0
  478. cirq/transformers/dynamical_decoupling.py +255 -43
  479. cirq/transformers/dynamical_decoupling_test.py +730 -17
  480. cirq/transformers/eject_phased_paulis.py +29 -15
  481. cirq/transformers/eject_phased_paulis_test.py +3 -8
  482. cirq/transformers/eject_z.py +3 -2
  483. cirq/transformers/eject_z_test.py +3 -3
  484. cirq/transformers/gauge_compiling/__init__.py +25 -9
  485. cirq/transformers/gauge_compiling/cphase_gauge.py +146 -0
  486. cirq/transformers/gauge_compiling/cphase_gauge_test.py +42 -0
  487. cirq/transformers/gauge_compiling/cz_gauge.py +4 -4
  488. cirq/transformers/gauge_compiling/gauge_compiling.py +245 -6
  489. cirq/transformers/gauge_compiling/gauge_compiling_test.py +107 -2
  490. cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +39 -2
  491. cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +10 -1
  492. cirq/transformers/gauge_compiling/iswap_gauge.py +2 -2
  493. cirq/transformers/gauge_compiling/spin_inversion_gauge.py +2 -2
  494. cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +23 -5
  495. cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +3 -2
  496. cirq/transformers/heuristic_decompositions/__init__.py +3 -3
  497. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +2 -1
  498. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +1 -1
  499. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +4 -4
  500. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation_test.py +4 -4
  501. cirq/transformers/insertion_sort.py +64 -0
  502. cirq/transformers/insertion_sort_test.py +34 -0
  503. cirq/transformers/measurement_transformers.py +14 -1
  504. cirq/transformers/measurement_transformers_test.py +35 -0
  505. cirq/transformers/merge_k_qubit_gates.py +2 -2
  506. cirq/transformers/merge_single_qubit_gates.py +1 -1
  507. cirq/transformers/merge_single_qubit_gates_test.py +1 -1
  508. cirq/transformers/noise_adding.py +115 -0
  509. cirq/transformers/noise_adding_test.py +54 -0
  510. cirq/transformers/optimize_for_target_gateset.py +1 -1
  511. cirq/transformers/optimize_for_target_gateset_test.py +3 -2
  512. cirq/transformers/qubit_management_transformers.py +1 -1
  513. cirq/transformers/randomized_measurements.py +171 -0
  514. cirq/transformers/randomized_measurements_test.py +68 -0
  515. cirq/transformers/routing/__init__.py +14 -5
  516. cirq/transformers/routing/initial_mapper.py +1 -1
  517. cirq/transformers/routing/initial_mapper_test.py +1 -0
  518. cirq/transformers/routing/line_initial_mapper.py +3 -2
  519. cirq/transformers/routing/mapping_manager.py +2 -2
  520. cirq/transformers/routing/mapping_manager_test.py +2 -2
  521. cirq/transformers/routing/route_circuit_cqc.py +3 -2
  522. cirq/transformers/routing/route_circuit_cqc_test.py +2 -1
  523. cirq/transformers/routing/visualize_routed_circuit.py +1 -0
  524. cirq/transformers/routing/visualize_routed_circuit_test.py +1 -0
  525. cirq/transformers/stratify.py +2 -2
  526. cirq/transformers/synchronize_terminal_measurements.py +2 -1
  527. cirq/transformers/target_gatesets/__init__.py +7 -5
  528. cirq/transformers/target_gatesets/compilation_target_gateset.py +16 -3
  529. cirq/transformers/target_gatesets/compilation_target_gateset_test.py +2 -0
  530. cirq/transformers/target_gatesets/cz_gateset.py +5 -1
  531. cirq/transformers/target_gatesets/cz_gateset_test.py +23 -2
  532. cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +1 -1
  533. cirq/transformers/target_gatesets/sqrt_iswap_gateset_test.py +3 -2
  534. cirq/transformers/transformer_api.py +5 -4
  535. cirq/transformers/transformer_api_test.py +11 -3
  536. cirq/transformers/transformer_primitives.py +9 -31
  537. cirq/transformers/transformer_primitives_test.py +6 -5
  538. cirq/value/__init__.py +51 -30
  539. cirq/value/abc_alt.py +1 -2
  540. cirq/value/angle.py +2 -0
  541. cirq/value/classical_data.py +1 -0
  542. cirq/value/condition.py +149 -3
  543. cirq/value/condition_test.py +254 -0
  544. cirq/value/digits.py +1 -1
  545. cirq/value/duration.py +4 -4
  546. cirq/value/duration_test.py +2 -1
  547. cirq/value/linear_dict.py +85 -24
  548. cirq/value/linear_dict_test.py +94 -3
  549. cirq/value/measurement_key.py +9 -2
  550. cirq/value/periodic_value.py +2 -3
  551. cirq/value/periodic_value_test.py +5 -0
  552. cirq/value/probability.py +1 -0
  553. cirq/value/random_state.py +1 -1
  554. cirq/value/timestamp.py +2 -4
  555. cirq/value/timestamp_test.py +2 -1
  556. cirq/value/type_alias.py +2 -2
  557. cirq/value/value_equality_attr.py +14 -2
  558. cirq/value/value_equality_attr_test.py +1 -1
  559. cirq/vis/__init__.py +9 -6
  560. cirq/vis/density_matrix.py +1 -1
  561. cirq/vis/density_matrix_test.py +2 -5
  562. cirq/vis/heatmap.py +49 -12
  563. cirq/vis/heatmap_test.py +168 -4
  564. cirq/vis/histogram.py +1 -1
  565. cirq/vis/histogram_test.py +1 -2
  566. cirq/vis/state_histogram.py +7 -5
  567. cirq/vis/state_histogram_test.py +2 -2
  568. cirq/work/__init__.py +19 -13
  569. cirq/work/collector.py +2 -2
  570. cirq/work/observable_grouping.py +2 -2
  571. cirq/work/observable_measurement.py +3 -3
  572. cirq/work/observable_measurement_data.py +5 -2
  573. cirq/work/observable_measurement_test.py +8 -8
  574. cirq/work/observable_readout_calibration.py +2 -2
  575. cirq/work/observable_readout_calibration_test.py +2 -1
  576. cirq/work/observable_settings.py +8 -7
  577. cirq/work/observable_settings_test.py +3 -2
  578. cirq/work/pauli_sum_collector.py +1 -1
  579. cirq/work/sampler.py +8 -20
  580. cirq/work/sampler_test.py +4 -3
  581. cirq/work/zeros_sampler.py +1 -1
  582. cirq_core-1.5.0.dist-info/METADATA +125 -0
  583. {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/RECORD +586 -552
  584. {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/WHEEL +1 -1
  585. cirq/experiments/grid_parallel_two_qubit_xeb.py +0 -62
  586. cirq/protocols/json_test_data/GridParallelXEBMetadata.json +0 -119
  587. cirq/protocols/json_test_data/GridParallelXEBMetadata.repr +0 -1
  588. cirq_core-1.4.0.dev20240529225110.dist-info/METADATA +0 -50
  589. {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/LICENSE +0 -0
  590. {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/top_level.txt +0 -0
@@ -11,20 +11,20 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
+
14
15
  import itertools
15
16
  import os
16
17
  import time
17
18
  from collections import defaultdict
18
- from random import randint, random, sample, randrange
19
- from typing import Iterator, Optional, Tuple, TYPE_CHECKING
19
+ from random import randint, random, randrange, sample
20
+ from typing import Iterator, Optional, Tuple
20
21
 
21
22
  import numpy as np
22
23
  import pytest
23
24
  import sympy
24
25
 
25
26
  import cirq
26
- from cirq import circuits
27
- from cirq import ops
27
+ from cirq import circuits, ops
28
28
  from cirq.testing.devices import ValidatingTestDevice
29
29
 
30
30
 
@@ -50,25 +50,9 @@ BCONE = ValidatingTestDevice(
50
50
  )
51
51
 
52
52
 
53
- if TYPE_CHECKING:
54
- import cirq
55
-
56
53
  q0, q1, q2, q3 = cirq.LineQubit.range(4)
57
54
 
58
55
 
59
- class _MomentAndOpTypeValidatingDeviceType(cirq.Device):
60
- def validate_operation(self, operation):
61
- if not isinstance(operation, cirq.Operation):
62
- raise ValueError(f'not isinstance({operation!r}, {cirq.Operation!r})')
63
-
64
- def validate_moment(self, moment):
65
- if not isinstance(moment, cirq.Moment):
66
- raise ValueError(f'not isinstance({moment!r}, {cirq.Moment!r})')
67
-
68
-
69
- moment_and_op_type_validating_device = _MomentAndOpTypeValidatingDeviceType()
70
-
71
-
72
56
  def test_from_moments():
73
57
  a, b, c, d = cirq.LineQubit.range(4)
74
58
  moment = cirq.Moment(cirq.Z(a), cirq.Z(b))
@@ -80,6 +64,7 @@ def test_from_moments():
80
64
  [cirq.X(c)],
81
65
  [],
82
66
  cirq.Z(d),
67
+ None,
83
68
  [cirq.measure(a, b, key='ab'), cirq.measure(c, d, key='cd')],
84
69
  )
85
70
  assert circuit == cirq.Circuit(
@@ -906,8 +891,8 @@ def test_insert_at_frontier():
906
891
  self.replacer = replacer
907
892
 
908
893
  def optimization_at(
909
- self, circuit: 'cirq.Circuit', index: int, op: 'cirq.Operation'
910
- ) -> Optional['cirq.PointOptimizationSummary']:
894
+ self, circuit: cirq.Circuit, index: int, op: cirq.Operation
895
+ ) -> Optional[cirq.PointOptimizationSummary]:
911
896
  new_ops = self.replacer(op)
912
897
  return cirq.PointOptimizationSummary(
913
898
  clear_span=1, clear_qubits=op.qubits, new_operations=new_ops
@@ -3554,6 +3539,52 @@ def test_insert_operations_random_circuits(circuit):
3554
3539
  assert circuit == other_circuit
3555
3540
 
3556
3541
 
3542
+ def test_insert_zero_index():
3543
+ # Should always go to moment[0], independent of qubit order or earliest/inline strategy.
3544
+ q0, q1 = cirq.LineQubit.range(2)
3545
+ c0 = cirq.Circuit(cirq.X(q0))
3546
+ c0.insert(0, cirq.Y.on_each(q0, q1), strategy=cirq.InsertStrategy.EARLIEST)
3547
+ c1 = cirq.Circuit(cirq.X(q0))
3548
+ c1.insert(0, cirq.Y.on_each(q1, q0), strategy=cirq.InsertStrategy.EARLIEST)
3549
+ c2 = cirq.Circuit(cirq.X(q0))
3550
+ c2.insert(0, cirq.Y.on_each(q0, q1), strategy=cirq.InsertStrategy.INLINE)
3551
+ c3 = cirq.Circuit(cirq.X(q0))
3552
+ c3.insert(0, cirq.Y.on_each(q1, q0), strategy=cirq.InsertStrategy.INLINE)
3553
+ expected = cirq.Circuit(cirq.Moment(cirq.Y(q0), cirq.Y(q1)), cirq.Moment(cirq.X(q0)))
3554
+ assert c0 == expected
3555
+ assert c1 == expected
3556
+ assert c2 == expected
3557
+ assert c3 == expected
3558
+
3559
+
3560
+ def test_insert_earliest_on_previous_moment():
3561
+ q = cirq.LineQubit(0)
3562
+ c = cirq.Circuit(cirq.Moment(cirq.X(q)), cirq.Moment(), cirq.Moment(), cirq.Moment(cirq.Z(q)))
3563
+ c.insert(3, cirq.Y(q), strategy=cirq.InsertStrategy.EARLIEST)
3564
+ # Should fall back to moment[1] since EARLIEST
3565
+ assert c == cirq.Circuit(
3566
+ cirq.Moment(cirq.X(q)), cirq.Moment(cirq.Y(q)), cirq.Moment(), cirq.Moment(cirq.Z(q))
3567
+ )
3568
+
3569
+
3570
+ def test_insert_inline_end_of_circuit():
3571
+ # If end index is specified, INLINE should place all ops there independent of qubit order.
3572
+ q0, q1 = cirq.LineQubit.range(2)
3573
+ c0 = cirq.Circuit(cirq.X(q0))
3574
+ c0.insert(1, cirq.Y.on_each(q0, q1), strategy=cirq.InsertStrategy.INLINE)
3575
+ c1 = cirq.Circuit(cirq.X(q0))
3576
+ c1.insert(1, cirq.Y.on_each(q1, q0), strategy=cirq.InsertStrategy.INLINE)
3577
+ c2 = cirq.Circuit(cirq.X(q0))
3578
+ c2.insert(5, cirq.Y.on_each(q0, q1), strategy=cirq.InsertStrategy.INLINE)
3579
+ c3 = cirq.Circuit(cirq.X(q0))
3580
+ c3.insert(5, cirq.Y.on_each(q1, q0), strategy=cirq.InsertStrategy.INLINE)
3581
+ expected = cirq.Circuit(cirq.Moment(cirq.X(q0)), cirq.Moment(cirq.Y(q0), cirq.Y(q1)))
3582
+ assert c0 == expected
3583
+ assert c1 == expected
3584
+ assert c2 == expected
3585
+ assert c3 == expected
3586
+
3587
+
3557
3588
  def test_insert_operations_errors():
3558
3589
  a, b, c = (cirq.NamedQubit(s) for s in 'abc')
3559
3590
  with pytest.raises(ValueError):
@@ -3578,7 +3609,7 @@ def test_insert_operations_errors():
3578
3609
  @pytest.mark.parametrize('circuit_cls', [cirq.Circuit, cirq.FrozenCircuit])
3579
3610
  def test_to_qasm(circuit_cls):
3580
3611
  q0 = cirq.NamedQubit('q0')
3581
- circuit = circuit_cls(cirq.X(q0))
3612
+ circuit = circuit_cls(cirq.X(q0), cirq.measure(q0, key='mmm'))
3582
3613
  assert circuit.to_qasm() == cirq.qasm(circuit)
3583
3614
  assert (
3584
3615
  circuit.to_qasm()
@@ -3590,9 +3621,29 @@ include "qelib1.inc";
3590
3621
 
3591
3622
  // Qubits: [q0]
3592
3623
  qreg q[1];
3624
+ creg m_mmm[1];
3625
+
3626
+
3627
+ x q[0];
3628
+ measure q[0] -> m_mmm[0];
3629
+ """
3630
+ )
3631
+ assert circuit.to_qasm(version="3.0") == cirq.qasm(circuit, args=cirq.QasmArgs(version="3.0"))
3632
+ assert (
3633
+ circuit.to_qasm(version="3.0")
3634
+ == f"""// Generated from Cirq v{cirq.__version__}
3635
+
3636
+ OPENQASM 3.0;
3637
+ include "stdgates.inc";
3638
+
3639
+
3640
+ // Qubits: [q0]
3641
+ qubit[1] q;
3642
+ bit[1] m_mmm;
3593
3643
 
3594
3644
 
3595
3645
  x q[0];
3646
+ m_mmm[0] = measure q[0];
3596
3647
  """
3597
3648
  )
3598
3649
 
@@ -4824,18 +4875,36 @@ global phase: 0.5π
4824
4875
  def test_create_speed():
4825
4876
  # Added in https://github.com/quantumlib/Cirq/pull/5332
4826
4877
  # Previously this took ~30s to run. Now it should take ~150ms. However the coverage test can
4827
- # run this slowly, so allowing 2 sec to account for things like that. Feel free to increase the
4878
+ # run this slowly, so allowing 4 sec to account for things like that. Feel free to increase the
4828
4879
  # buffer time or delete the test entirely if it ends up causing flakes.
4829
- #
4830
- # Updated in https://github.com/quantumlib/Cirq/pull/5756
4831
- # After several tiny overtime failures of the GitHub CI Pytest MacOS (3.7)
4832
- # the timeout was increased to 4 sec. A more thorough investigation or test
4833
- # removal should be considered if this continues to time out.
4834
4880
  qs = 100
4835
4881
  moments = 500
4836
4882
  xs = [cirq.X(cirq.LineQubit(i)) for i in range(qs)]
4837
- opa = [xs[i] for i in range(qs) for _ in range(moments)]
4883
+ ops = [xs[i] for i in range(qs) for _ in range(moments)]
4884
+ t = time.perf_counter()
4885
+ c = cirq.Circuit(ops)
4886
+ duration = time.perf_counter() - t
4887
+ assert len(c) == moments
4888
+ assert duration < 4
4889
+
4890
+
4891
+ def test_append_speed():
4892
+ # Previously this took ~17s to run. Now it should take ~150ms. However the coverage test can
4893
+ # run this slowly, so allowing 5 sec to account for things like that. Feel free to increase the
4894
+ # buffer time or delete the test entirely if it ends up causing flakes.
4895
+ #
4896
+ # The `append` improvement mainly helps for deep circuits. It is less useful for wide circuits
4897
+ # because the Moment (immutable) needs verified and reconstructed each time an op is added.
4898
+ qs = 2
4899
+ moments = 10000
4900
+ xs = [cirq.X(cirq.LineQubit(i)) for i in range(qs)]
4901
+ c = cirq.Circuit()
4838
4902
  t = time.perf_counter()
4839
- c = cirq.Circuit(opa)
4903
+ # Iterating with the moments in the inner loop highlights the improvement: when filling in the
4904
+ # second qubit, we no longer have to search backwards from moment 10000 for a placement index.
4905
+ for q in range(qs):
4906
+ for _ in range(moments):
4907
+ c.append(xs[q])
4908
+ duration = time.perf_counter() - t
4840
4909
  assert len(c) == moments
4841
- assert time.perf_counter() - t < 4
4910
+ assert duration < 5
@@ -11,8 +11,13 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
+
14
15
  """An immutable version of the Circuit data structure."""
16
+
17
+ from __future__ import annotations
18
+
15
19
  from functools import cached_property
20
+ from types import NotImplementedType
16
21
  from typing import (
17
22
  AbstractSet,
18
23
  FrozenSet,
@@ -27,10 +32,9 @@ from typing import (
27
32
 
28
33
  import numpy as np
29
34
 
30
- from cirq import protocols, _compat
35
+ from cirq import _compat, protocols
31
36
  from cirq.circuits import AbstractCircuit, Alignment, Circuit
32
37
  from cirq.circuits.insert_strategy import InsertStrategy
33
- from cirq.type_workarounds import NotImplementedType
34
38
 
35
39
  if TYPE_CHECKING:
36
40
  import cirq
@@ -46,8 +50,8 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
46
50
 
47
51
  def __init__(
48
52
  self,
49
- *contents: 'cirq.OP_TREE',
50
- strategy: 'cirq.InsertStrategy' = InsertStrategy.EARLIEST,
53
+ *contents: cirq.OP_TREE,
54
+ strategy: cirq.InsertStrategy = InsertStrategy.EARLIEST,
51
55
  tags: Sequence[Hashable] = (),
52
56
  ) -> None:
53
57
  """Initializes a frozen circuit.
@@ -71,20 +75,20 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
71
75
  self._tags = tuple(tags)
72
76
 
73
77
  @classmethod
74
- def _from_moments(cls, moments: Iterable['cirq.Moment']) -> 'FrozenCircuit':
78
+ def _from_moments(cls, moments: Iterable[cirq.Moment]) -> FrozenCircuit:
75
79
  new_circuit = FrozenCircuit()
76
80
  new_circuit._moments = tuple(moments)
77
81
  return new_circuit
78
82
 
79
83
  @property
80
- def moments(self) -> Sequence['cirq.Moment']:
84
+ def moments(self) -> Sequence[cirq.Moment]:
81
85
  return self._moments
82
86
 
83
- def freeze(self) -> 'cirq.FrozenCircuit':
87
+ def freeze(self) -> cirq.FrozenCircuit:
84
88
  return self
85
89
 
86
- def unfreeze(self, copy: bool = True) -> 'cirq.Circuit':
87
- return Circuit.from_moments(*self)
90
+ def unfreeze(self, copy: bool = True) -> cirq.Circuit:
91
+ return Circuit._from_moments(self._moments)
88
92
 
89
93
  @property
90
94
  def tags(self) -> Tuple[Hashable, ...]:
@@ -92,11 +96,11 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
92
96
  return self._tags
93
97
 
94
98
  @cached_property
95
- def untagged(self) -> 'cirq.FrozenCircuit':
99
+ def untagged(self) -> cirq.FrozenCircuit:
96
100
  """Returns the underlying FrozenCircuit without any tags."""
97
101
  return self._from_moments(self._moments) if self.tags else self
98
102
 
99
- def with_tags(self, *new_tags: Hashable) -> 'cirq.FrozenCircuit':
103
+ def with_tags(self, *new_tags: Hashable) -> cirq.FrozenCircuit:
100
104
  """Creates a new tagged `FrozenCircuit` with `self.tags` and `new_tags` combined."""
101
105
  if not new_tags:
102
106
  return self
@@ -119,10 +123,10 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
119
123
  def __getstate__(self):
120
124
  # Don't save hash when pickling; see #3777.
121
125
  state = self.__dict__
122
- hash_cache = _compat._method_cache_name(self.__hash__)
123
- if hash_cache in state:
126
+ hash_attr = _compat._method_cache_name(self.__hash__)
127
+ if hash_attr in state:
124
128
  state = state.copy()
125
- del state[hash_cache]
129
+ del state[hash_attr]
126
130
  return state
127
131
 
128
132
  @_compat.cached_method
@@ -146,28 +150,28 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
146
150
  return protocols.is_measurement(self.unfreeze())
147
151
 
148
152
  @_compat.cached_method
149
- def all_qubits(self) -> FrozenSet['cirq.Qid']:
153
+ def all_qubits(self) -> FrozenSet[cirq.Qid]:
150
154
  return super().all_qubits()
151
155
 
152
156
  @cached_property
153
- def _all_operations(self) -> Tuple['cirq.Operation', ...]:
157
+ def _all_operations(self) -> Tuple[cirq.Operation, ...]:
154
158
  return tuple(super().all_operations())
155
159
 
156
- def all_operations(self) -> Iterator['cirq.Operation']:
160
+ def all_operations(self) -> Iterator[cirq.Operation]:
157
161
  return iter(self._all_operations)
158
162
 
159
163
  def has_measurements(self) -> bool:
160
164
  return self._is_measurement_()
161
165
 
162
166
  @_compat.cached_method
163
- def all_measurement_key_objs(self) -> FrozenSet['cirq.MeasurementKey']:
167
+ def all_measurement_key_objs(self) -> FrozenSet[cirq.MeasurementKey]:
164
168
  return super().all_measurement_key_objs()
165
169
 
166
- def _measurement_key_objs_(self) -> FrozenSet['cirq.MeasurementKey']:
170
+ def _measurement_key_objs_(self) -> FrozenSet[cirq.MeasurementKey]:
167
171
  return self.all_measurement_key_objs()
168
172
 
169
173
  @_compat.cached_method
170
- def _control_keys_(self) -> FrozenSet['cirq.MeasurementKey']:
174
+ def _control_keys_(self) -> FrozenSet[cirq.MeasurementKey]:
171
175
  return super()._control_keys_()
172
176
 
173
177
  @_compat.cached_method
@@ -190,8 +194,8 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
190
194
  return super()._parameter_names_() | tag_params
191
195
 
192
196
  def _resolve_parameters_(
193
- self, resolver: 'cirq.ParamResolver', recursive: bool
194
- ) -> 'cirq.FrozenCircuit':
197
+ self, resolver: cirq.ParamResolver, recursive: bool
198
+ ) -> cirq.FrozenCircuit:
195
199
  resolved_circuit = super()._resolve_parameters_(resolver, recursive)
196
200
  resolved_tags = [
197
201
  protocols.resolve_parameters(tag, resolver, recursive) for tag in self.tags
@@ -201,23 +205,23 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
201
205
  def _measurement_key_names_(self) -> FrozenSet[str]:
202
206
  return self.all_measurement_key_names()
203
207
 
204
- def __add__(self, other) -> 'cirq.FrozenCircuit':
208
+ def __add__(self, other) -> cirq.FrozenCircuit:
205
209
  return (self.unfreeze() + other).freeze()
206
210
 
207
- def __radd__(self, other) -> 'cirq.FrozenCircuit':
211
+ def __radd__(self, other) -> cirq.FrozenCircuit:
208
212
  return (other + self.unfreeze()).freeze()
209
213
 
210
214
  # Needed for numpy to handle multiplication by np.int64 correctly.
211
215
  __array_priority__ = 10000
212
216
 
213
217
  # TODO: handle multiplication / powers differently?
214
- def __mul__(self, other) -> 'cirq.FrozenCircuit':
218
+ def __mul__(self, other) -> cirq.FrozenCircuit:
215
219
  return (self.unfreeze() * other).freeze()
216
220
 
217
- def __rmul__(self, other) -> 'cirq.FrozenCircuit':
221
+ def __rmul__(self, other) -> cirq.FrozenCircuit:
218
222
  return (other * self.unfreeze()).freeze()
219
223
 
220
- def __pow__(self, other) -> 'cirq.FrozenCircuit':
224
+ def __pow__(self, other) -> cirq.FrozenCircuit:
221
225
  try:
222
226
  return (self.unfreeze() ** other).freeze()
223
227
  except:
@@ -238,20 +242,20 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
238
242
  return cls(moments, strategy=InsertStrategy.EARLIEST, tags=tags)
239
243
 
240
244
  def concat_ragged(
241
- *circuits: 'cirq.AbstractCircuit', align: Union['cirq.Alignment', str] = Alignment.LEFT
242
- ) -> 'cirq.FrozenCircuit':
245
+ *circuits: cirq.AbstractCircuit, align: Union[cirq.Alignment, str] = Alignment.LEFT
246
+ ) -> cirq.FrozenCircuit:
243
247
  return AbstractCircuit.concat_ragged(*circuits, align=align).freeze()
244
248
 
245
249
  concat_ragged.__doc__ = AbstractCircuit.concat_ragged.__doc__
246
250
 
247
251
  def zip(
248
- *circuits: 'cirq.AbstractCircuit', align: Union['cirq.Alignment', str] = Alignment.LEFT
249
- ) -> 'cirq.FrozenCircuit':
252
+ *circuits: cirq.AbstractCircuit, align: Union[cirq.Alignment, str] = Alignment.LEFT
253
+ ) -> cirq.FrozenCircuit:
250
254
  return AbstractCircuit.zip(*circuits, align=align).freeze()
251
255
 
252
256
  zip.__doc__ = AbstractCircuit.zip.__doc__
253
257
 
254
- def to_op(self) -> 'cirq.CircuitOperation':
258
+ def to_op(self) -> cirq.CircuitOperation:
255
259
  """Creates a CircuitOperation wrapping this circuit."""
256
260
  from cirq.circuits import CircuitOperation
257
261
 
@@ -23,6 +23,16 @@ class InsertStrategy:
23
23
  INLINE: 'InsertStrategy'
24
24
  EARLIEST: 'InsertStrategy'
25
25
 
26
+ def __new__(cls, name: str, doc: str) -> 'InsertStrategy':
27
+ inst = getattr(cls, name, None)
28
+ if not inst or not isinstance(inst, cls):
29
+ inst = super().__new__(cls)
30
+ return inst
31
+
32
+ def __getnewargs__(self):
33
+ """Returns a tuple of args to pass to __new__ when unpickling."""
34
+ return (self.name, self.__doc__)
35
+
26
36
  def __init__(self, name: str, doc: str):
27
37
  self.name = name
28
38
  self.__doc__ = doc
@@ -12,8 +12,28 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import pickle
16
+
17
+ import pytest
18
+
15
19
  import cirq
16
20
 
17
21
 
18
22
  def test_repr():
19
23
  assert repr(cirq.InsertStrategy.NEW) == 'cirq.InsertStrategy.NEW'
24
+ assert str(cirq.InsertStrategy.NEW) == 'NEW'
25
+
26
+
27
+ @pytest.mark.parametrize(
28
+ 'strategy',
29
+ [
30
+ cirq.InsertStrategy.NEW,
31
+ cirq.InsertStrategy.NEW_THEN_INLINE,
32
+ cirq.InsertStrategy.INLINE,
33
+ cirq.InsertStrategy.EARLIEST,
34
+ ],
35
+ ids=lambda strategy: strategy.name,
36
+ )
37
+ def test_identity_after_pickling(strategy: cirq.InsertStrategy):
38
+ unpickled_strategy = pickle.loads(pickle.dumps(strategy))
39
+ assert unpickled_strategy is strategy