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
@@ -14,16 +14,24 @@
14
14
  """Tests for state_vector.py"""
15
15
 
16
16
  import itertools
17
- from typing import Optional
18
- import pytest
17
+ from typing import Iterator, Optional
18
+ from unittest import mock
19
19
 
20
20
  import numpy as np
21
+ import pytest
21
22
 
22
23
  import cirq
23
24
  import cirq.testing
24
25
  from cirq import linalg
25
26
 
26
27
 
28
+ @pytest.fixture
29
+ def use_np_transpose(request) -> Iterator[bool]:
30
+ value: bool = request.param
31
+ with mock.patch.object(linalg, 'can_numpy_support_shape', lambda shape: value):
32
+ yield value
33
+
34
+
27
35
  def test_state_mixin():
28
36
  class TestClass(cirq.StateVectorMixin):
29
37
  def state_vector(self, copy: Optional[bool] = None) -> np.ndarray:
@@ -173,9 +181,10 @@ def test_sample_no_indices_repetitions():
173
181
  )
174
182
 
175
183
 
176
- @pytest.mark.parametrize('use_np_transpose', [False, True])
184
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
177
185
  def test_measure_state_computational_basis(use_np_transpose: bool):
178
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
186
+ # verify patching of can_numpy_support_shape in the use_np_transpose fixture
187
+ assert linalg.can_numpy_support_shape([1]) is use_np_transpose
179
188
  results = []
180
189
  for x in range(8):
181
190
  initial_state = cirq.to_valid_state_vector(x, 3)
@@ -186,9 +195,8 @@ def test_measure_state_computational_basis(use_np_transpose: bool):
186
195
  assert results == expected
187
196
 
188
197
 
189
- @pytest.mark.parametrize('use_np_transpose', [False, True])
198
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
190
199
  def test_measure_state_reshape(use_np_transpose: bool):
191
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
192
200
  results = []
193
201
  for x in range(8):
194
202
  initial_state = np.reshape(cirq.to_valid_state_vector(x, 3), [2] * 3)
@@ -199,9 +207,8 @@ def test_measure_state_reshape(use_np_transpose: bool):
199
207
  assert results == expected
200
208
 
201
209
 
202
- @pytest.mark.parametrize('use_np_transpose', [False, True])
210
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
203
211
  def test_measure_state_partial_indices(use_np_transpose: bool):
204
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
205
212
  for index in range(3):
206
213
  for x in range(8):
207
214
  initial_state = cirq.to_valid_state_vector(x, 3)
@@ -210,9 +217,8 @@ def test_measure_state_partial_indices(use_np_transpose: bool):
210
217
  assert bits == [bool(1 & (x >> (2 - index)))]
211
218
 
212
219
 
213
- @pytest.mark.parametrize('use_np_transpose', [False, True])
220
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
214
221
  def test_measure_state_partial_indices_order(use_np_transpose: bool):
215
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
216
222
  for x in range(8):
217
223
  initial_state = cirq.to_valid_state_vector(x, 3)
218
224
  bits, state = cirq.measure_state_vector(initial_state, [2, 1])
@@ -220,9 +226,8 @@ def test_measure_state_partial_indices_order(use_np_transpose: bool):
220
226
  assert bits == [bool(1 & (x >> 0)), bool(1 & (x >> 1))]
221
227
 
222
228
 
223
- @pytest.mark.parametrize('use_np_transpose', [False, True])
229
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
224
230
  def test_measure_state_partial_indices_all_orders(use_np_transpose: bool):
225
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
226
231
  for perm in itertools.permutations([0, 1, 2]):
227
232
  for x in range(8):
228
233
  initial_state = cirq.to_valid_state_vector(x, 3)
@@ -231,9 +236,8 @@ def test_measure_state_partial_indices_all_orders(use_np_transpose: bool):
231
236
  assert bits == [bool(1 & (x >> (2 - p))) for p in perm]
232
237
 
233
238
 
234
- @pytest.mark.parametrize('use_np_transpose', [False, True])
239
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
235
240
  def test_measure_state_collapse(use_np_transpose: bool):
236
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
237
241
  initial_state = np.zeros(8, dtype=np.complex64)
238
242
  initial_state[0] = 1 / np.sqrt(2)
239
243
  initial_state[2] = 1 / np.sqrt(2)
@@ -256,9 +260,8 @@ def test_measure_state_collapse(use_np_transpose: bool):
256
260
  assert bits == [False]
257
261
 
258
262
 
259
- @pytest.mark.parametrize('use_np_transpose', [False, True])
263
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
260
264
  def test_measure_state_seed(use_np_transpose: bool):
261
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
262
265
  n = 10
263
266
  initial_state = np.ones(2**n) / 2 ** (n / 2)
264
267
 
@@ -277,9 +280,8 @@ def test_measure_state_seed(use_np_transpose: bool):
277
280
  np.testing.assert_allclose(state1, state2)
278
281
 
279
282
 
280
- @pytest.mark.parametrize('use_np_transpose', [False, True])
283
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
281
284
  def test_measure_state_out_is_state(use_np_transpose: bool):
282
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
283
285
  initial_state = np.zeros(8, dtype=np.complex64)
284
286
  initial_state[0] = 1 / np.sqrt(2)
285
287
  initial_state[2] = 1 / np.sqrt(2)
@@ -290,9 +292,8 @@ def test_measure_state_out_is_state(use_np_transpose: bool):
290
292
  assert state is initial_state
291
293
 
292
294
 
293
- @pytest.mark.parametrize('use_np_transpose', [False, True])
295
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
294
296
  def test_measure_state_out_is_not_state(use_np_transpose: bool):
295
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
296
297
  initial_state = np.zeros(8, dtype=np.complex64)
297
298
  initial_state[0] = 1 / np.sqrt(2)
298
299
  initial_state[2] = 1 / np.sqrt(2)
@@ -302,18 +303,16 @@ def test_measure_state_out_is_not_state(use_np_transpose: bool):
302
303
  assert out is state
303
304
 
304
305
 
305
- @pytest.mark.parametrize('use_np_transpose', [False, True])
306
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
306
307
  def test_measure_state_not_power_of_two(use_np_transpose: bool):
307
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
308
308
  with pytest.raises(ValueError, match='3'):
309
309
  _, _ = cirq.measure_state_vector(np.array([1, 0, 0]), [1])
310
310
  with pytest.raises(ValueError, match='5'):
311
311
  cirq.measure_state_vector(np.array([0, 1, 0, 0, 0]), [1])
312
312
 
313
313
 
314
- @pytest.mark.parametrize('use_np_transpose', [False, True])
314
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
315
315
  def test_measure_state_index_out_of_range(use_np_transpose: bool):
316
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
317
316
  state = cirq.to_valid_state_vector(0, 3)
318
317
  with pytest.raises(IndexError, match='-2'):
319
318
  cirq.measure_state_vector(state, [-2])
@@ -321,18 +320,16 @@ def test_measure_state_index_out_of_range(use_np_transpose: bool):
321
320
  cirq.measure_state_vector(state, [3])
322
321
 
323
322
 
324
- @pytest.mark.parametrize('use_np_transpose', [False, True])
323
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
325
324
  def test_measure_state_no_indices(use_np_transpose: bool):
326
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
327
325
  initial_state = cirq.to_valid_state_vector(0, 3)
328
326
  bits, state = cirq.measure_state_vector(initial_state, [])
329
327
  assert [] == bits
330
328
  np.testing.assert_almost_equal(state, initial_state)
331
329
 
332
330
 
333
- @pytest.mark.parametrize('use_np_transpose', [False, True])
331
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
334
332
  def test_measure_state_no_indices_out_is_state(use_np_transpose: bool):
335
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
336
333
  initial_state = cirq.to_valid_state_vector(0, 3)
337
334
  bits, state = cirq.measure_state_vector(initial_state, [], out=initial_state)
338
335
  assert [] == bits
@@ -340,9 +337,8 @@ def test_measure_state_no_indices_out_is_state(use_np_transpose: bool):
340
337
  assert state is initial_state
341
338
 
342
339
 
343
- @pytest.mark.parametrize('use_np_transpose', [False, True])
340
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
344
341
  def test_measure_state_no_indices_out_is_not_state(use_np_transpose: bool):
345
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
346
342
  initial_state = cirq.to_valid_state_vector(0, 3)
347
343
  out = np.zeros_like(initial_state)
348
344
  bits, state = cirq.measure_state_vector(initial_state, [], out=out)
@@ -352,9 +348,8 @@ def test_measure_state_no_indices_out_is_not_state(use_np_transpose: bool):
352
348
  assert out is not initial_state
353
349
 
354
350
 
355
- @pytest.mark.parametrize('use_np_transpose', [False, True])
351
+ @pytest.mark.parametrize('use_np_transpose', [False, True], indirect=True)
356
352
  def test_measure_state_empty_state(use_np_transpose: bool):
357
- linalg.can_numpy_support_shape = lambda s: use_np_transpose
358
353
  initial_state = np.array([1.0])
359
354
  bits, state = cirq.measure_state_vector(initial_state, [])
360
355
  assert [] == bits
cirq/study/__init__.py CHANGED
@@ -15,33 +15,39 @@
15
15
  """Parameterized circuits and results."""
16
16
 
17
17
  from cirq.study.flatten_expressions import (
18
- ExpressionMap,
19
- flatten,
20
- flatten_with_params,
21
- flatten_with_sweep,
18
+ ExpressionMap as ExpressionMap,
19
+ flatten as flatten,
20
+ flatten_with_params as flatten_with_params,
21
+ flatten_with_sweep as flatten_with_sweep,
22
22
  )
23
23
 
24
24
  from cirq.study.resolver import (
25
- ParamDictType,
26
- ParamMappingType,
27
- ParamResolver,
28
- ParamResolverOrSimilarType,
25
+ ParamDictType as ParamDictType,
26
+ ParamMappingType as ParamMappingType,
27
+ ParamResolver as ParamResolver,
28
+ ParamResolverOrSimilarType as ParamResolverOrSimilarType,
29
29
  )
30
30
 
31
- from cirq.study.sweepable import Sweepable, to_resolvers, to_sweep, to_sweeps
31
+ from cirq.study.sweepable import (
32
+ Sweepable as Sweepable,
33
+ to_resolvers as to_resolvers,
34
+ to_sweep as to_sweep,
35
+ to_sweeps as to_sweeps,
36
+ )
32
37
 
33
38
  from cirq.study.sweeps import (
34
- Linspace,
35
- ListSweep,
36
- Points,
37
- Product,
38
- Sweep,
39
- UNIT_SWEEP,
40
- UnitSweep,
41
- Zip,
42
- ZipLongest,
43
- dict_to_product_sweep,
44
- dict_to_zip_sweep,
39
+ Concat as Concat,
40
+ Linspace as Linspace,
41
+ ListSweep as ListSweep,
42
+ Points as Points,
43
+ Product as Product,
44
+ Sweep as Sweep,
45
+ UNIT_SWEEP as UNIT_SWEEP,
46
+ UnitSweep as UnitSweep,
47
+ Zip as Zip,
48
+ ZipLongest as ZipLongest,
49
+ dict_to_product_sweep as dict_to_product_sweep,
50
+ dict_to_zip_sweep as dict_to_zip_sweep,
45
51
  )
46
52
 
47
- from cirq.study.result import ResultDict, Result
53
+ from cirq.study.result import ResultDict as ResultDict, Result as Result
@@ -13,13 +13,13 @@
13
13
  # limitations under the License.
14
14
  """Resolves symbolic expressions to unique symbols."""
15
15
 
16
- from typing import Any, Callable, List, Optional, Tuple, Union, TYPE_CHECKING
17
16
  import numbers
17
+ from typing import Any, Callable, List, Optional, Tuple, TYPE_CHECKING, Union
18
18
 
19
19
  import sympy
20
20
 
21
21
  from cirq import protocols
22
- from cirq.study import resolver, sweeps, sweepable
22
+ from cirq.study import resolver, sweepable, sweeps
23
23
 
24
24
  if TYPE_CHECKING:
25
25
  import cirq
@@ -225,8 +225,7 @@ class _ParamFlattener(resolver.ParamResolver):
225
225
  params = param_dict if param_dict else {}
226
226
  # TODO: Support complex values for typing below.
227
227
  symbol_params: resolver.ParamDictType = {
228
- _ensure_not_str(param): _ensure_not_str(val) # type: ignore[misc]
229
- for param, val in params.items()
228
+ _ensure_not_str(param): _ensure_not_str(val) for param, val in params.items()
230
229
  }
231
230
  super().__init__(symbol_params)
232
231
  if get_param_name is None:
@@ -270,7 +269,7 @@ class _ParamFlattener(resolver.ParamResolver):
270
269
  The unique symbol or value of the parameter as resolved by this
271
270
  resolver.
272
271
  """
273
- if isinstance(value, (int, float, complex, numbers.Complex)):
272
+ if isinstance(value, numbers.Complex):
274
273
  return value
275
274
  if isinstance(value, str):
276
275
  value = sympy.Symbol(value)
@@ -381,7 +380,7 @@ class ExpressionMap(dict):
381
380
 
382
381
 
383
382
  def _ensure_not_str(
384
- param: Union[sympy.Expr, 'cirq.TParamValComplex', str]
383
+ param: Union[sympy.Expr, 'cirq.TParamValComplex', str],
385
384
  ) -> Union[sympy.Expr, 'cirq.TParamValComplex']:
386
385
  if isinstance(param, str):
387
386
  return sympy.Symbol(param)
@@ -13,10 +13,10 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import sympy
16
+
16
17
  import cirq
17
18
  from cirq.study import flatten_expressions
18
19
 
19
-
20
20
  # None of the following tests use expressions of the form
21
21
  # <constant term> - <other term> because the string of expressions containing
22
22
  # exactly two terms, one constant term and one non-constant term with a negative
cirq/study/resolver.py CHANGED
@@ -19,6 +19,7 @@ from typing import Any, cast, Dict, Iterator, Mapping, Optional, TYPE_CHECKING,
19
19
  import numpy as np
20
20
  import sympy
21
21
  from sympy.core import numbers as sympy_numbers
22
+
22
23
  from cirq._compat import proper_repr
23
24
  from cirq._doc import document
24
25
 
@@ -43,10 +44,6 @@ _NOT_FOUND = object()
43
44
  _RECURSION_FLAG = object()
44
45
 
45
46
 
46
- def _is_param_resolver_or_similar_type(obj: Any):
47
- return obj is None or isinstance(obj, (ParamResolver, dict))
48
-
49
-
50
47
  class ParamResolver:
51
48
  """Resolves parameters to actual values.
52
49
 
@@ -139,10 +136,10 @@ class ParamResolver:
139
136
  if isinstance(param_value, str):
140
137
  param_value = sympy.Symbol(param_value)
141
138
  elif not isinstance(param_value, sympy.Basic):
142
- return value # type: ignore[return-value]
139
+ return value
143
140
  if recursive:
144
141
  param_value = self._value_of_recursive(value)
145
- return param_value # type: ignore[return-value]
142
+ return param_value
146
143
 
147
144
  if not isinstance(value, sympy.Basic):
148
145
  # No known way to resolve this variable, return unchanged.
@@ -207,7 +204,7 @@ class ParamResolver:
207
204
 
208
205
  # There isn't a full evaluation for 'value' yet. Until it's ready,
209
206
  # map value to None to identify loops in component evaluation.
210
- self._deep_eval_map[value] = _RECURSION_FLAG # type: ignore
207
+ self._deep_eval_map[value] = _RECURSION_FLAG
211
208
 
212
209
  v = self.value_of(value, recursive=False)
213
210
  if v == value:
@@ -220,10 +217,8 @@ class ParamResolver:
220
217
  new_dict: Dict['cirq.TParamKey', Union[float, str, sympy.Symbol, sympy.Expr]] = {
221
218
  k: k for k in resolver
222
219
  }
223
- new_dict.update({k: self.value_of(k, recursive) for k in self}) # type: ignore[misc]
224
- new_dict.update(
225
- {k: resolver.value_of(v, recursive) for k, v in new_dict.items()} # type: ignore[misc]
226
- )
220
+ new_dict.update({k: self.value_of(k, recursive) for k in self})
221
+ new_dict.update({k: resolver.value_of(v, recursive) for k, v in new_dict.items()})
227
222
  if recursive and self._param_dict:
228
223
  new_resolver = ParamResolver(cast(ParamDictType, new_dict))
229
224
  # Resolve down to single-step mappings.
@@ -246,6 +241,14 @@ class ParamResolver:
246
241
  self._param_hash = hash(frozenset(self._param_dict.items()))
247
242
  return self._param_hash
248
243
 
244
+ def __getstate__(self) -> Dict[str, Any]:
245
+ # clear cached hash value when pickling, see #6674
246
+ state = self.__dict__
247
+ if state["_param_hash"] is not None:
248
+ state = state.copy()
249
+ state["_param_hash"] = None
250
+ return state
251
+
249
252
  def __eq__(self, other):
250
253
  if not isinstance(other, ParamResolver):
251
254
  return NotImplemented
@@ -84,7 +84,7 @@ def _assert_consistent_resolution(v, resolved):
84
84
 
85
85
  # note: super().subs() doesn't resolve based on the param_dict properly
86
86
  # for some reason, that's why a delegate (self.symbol) is used instead
87
- def subs(self, *args, **kwargs):
87
+ def subs(self, *args, **kwargs): # pragma: no cover
88
88
  self.called = True
89
89
  return self.symbol.subs(*args, **kwargs)
90
90
 
@@ -93,6 +93,7 @@ def _assert_consistent_resolution(v, resolved):
93
93
  # symbol based resolution
94
94
  s = SubsAwareSymbol('a')
95
95
  assert r.value_of(s) == resolved, f"expected {resolved}, got {r.value_of(s)}"
96
+ assert r[s] == resolved, f"expected {resolved}, got {r.value_of(s)}"
96
97
  assert not s.called, f"For pass-through type {type(v)} sympy.subs shouldn't have been called."
97
98
  assert isinstance(
98
99
  r.value_of(s), type(resolved)
@@ -183,6 +184,14 @@ def test_recursive_evaluation():
183
184
  assert sympy.Eq(r.value_of(e), 0)
184
185
 
185
186
 
187
+ def test_resolution_of_unknown_formulas():
188
+ a = sympy.Symbol('a')
189
+ b = sympy.Symbol('b')
190
+
191
+ r = cirq.ParamResolver({a: b - 2})
192
+ assert r.value_of(sympy.sin(a), recursive=False) == sympy.sin(b - 2)
193
+
194
+
186
195
  def test_unbound_recursion_halted():
187
196
  a = sympy.Symbol('a')
188
197
  b = sympy.Symbol('b')
cirq/study/result.py CHANGED
@@ -19,22 +19,22 @@ import io
19
19
  from typing import (
20
20
  Any,
21
21
  Callable,
22
+ cast,
22
23
  Dict,
23
24
  Iterable,
24
25
  Mapping,
25
26
  Optional,
26
27
  Sequence,
27
- TYPE_CHECKING,
28
28
  Tuple,
29
+ TYPE_CHECKING,
29
30
  TypeVar,
30
31
  Union,
31
- cast,
32
32
  )
33
33
 
34
34
  import numpy as np
35
35
  import pandas as pd
36
36
 
37
- from cirq import value, ops
37
+ from cirq import ops, value
38
38
  from cirq._compat import proper_repr
39
39
  from cirq.study import resolver
40
40
 
cirq/study/sweepable.py CHANGED
@@ -14,13 +14,14 @@
14
14
 
15
15
  """Defines which types are Sweepable."""
16
16
 
17
- from typing import Iterable, Iterator, List, Sequence, Union, cast
18
17
  import warnings
18
+ from typing import cast, Iterable, Iterator, List, Optional, Sequence, Union
19
+
19
20
  from typing_extensions import Protocol
20
21
 
21
22
  from cirq._doc import document
22
23
  from cirq.study.resolver import ParamResolver, ParamResolverOrSimilarType
23
- from cirq.study.sweeps import ListSweep, Points, Sweep, UnitSweep, Zip, dict_to_product_sweep
24
+ from cirq.study.sweeps import dict_to_product_sweep, ListSweep, Points, Sweep, UnitSweep, Zip
24
25
 
25
26
  SweepLike = Union[ParamResolverOrSimilarType, Sweep]
26
27
  document(SweepLike, """An object similar to an iterable of parameter resolvers.""")
@@ -44,12 +45,12 @@ def to_resolvers(sweepable: Sweepable) -> Iterator[ParamResolver]:
44
45
  yield from sweep
45
46
 
46
47
 
47
- def to_sweeps(sweepable: Sweepable) -> List[Sweep]:
48
+ def to_sweeps(sweepable: Sweepable, metadata: Optional[dict] = None) -> List[Sweep]:
48
49
  """Converts a Sweepable to a list of Sweeps."""
49
50
  if sweepable is None:
50
51
  return [UnitSweep]
51
52
  if isinstance(sweepable, ParamResolver):
52
- return [_resolver_to_sweep(sweepable)]
53
+ return [_resolver_to_sweep(sweepable, metadata)]
53
54
  if isinstance(sweepable, Sweep):
54
55
  return [sweepable]
55
56
  if isinstance(sweepable, dict):
@@ -63,16 +64,16 @@ def to_sweeps(sweepable: Sweepable) -> List[Sweep]:
63
64
  stacklevel=2,
64
65
  )
65
66
  product_sweep = dict_to_product_sweep(sweepable)
66
- return [_resolver_to_sweep(resolver) for resolver in product_sweep]
67
+ return [_resolver_to_sweep(resolver, metadata) for resolver in product_sweep]
67
68
  if isinstance(sweepable, Iterable) and not isinstance(sweepable, str):
68
- return [sweep for item in sweepable for sweep in to_sweeps(item)] # type: ignore[arg-type]
69
+ return [sweep for item in sweepable for sweep in to_sweeps(item, metadata)]
69
70
  raise TypeError(f'Unrecognized sweepable type: {type(sweepable)}.\nsweepable: {sweepable}')
70
71
 
71
72
 
72
73
  def to_sweep(
73
74
  sweep_or_resolver_list: Union[
74
75
  'Sweep', ParamResolverOrSimilarType, Iterable[ParamResolverOrSimilarType]
75
- ]
76
+ ],
76
77
  ) -> 'Sweep':
77
78
  """Converts the argument into a ``cirq.Sweep``.
78
79
 
@@ -98,8 +99,13 @@ def to_sweep(
98
99
  raise TypeError(f'Unexpected sweep-like value: {sweep_or_resolver_list}')
99
100
 
100
101
 
101
- def _resolver_to_sweep(resolver: ParamResolver) -> Sweep:
102
+ def _resolver_to_sweep(resolver: ParamResolver, metadata: Optional[dict]) -> Sweep:
102
103
  params = resolver.param_dict
103
104
  if not params:
104
105
  return UnitSweep
105
- return Zip(*[Points(key, [cast(float, value)]) for key, value in params.items()])
106
+ return Zip(
107
+ *[
108
+ Points(key, [cast(float, value)], metadata=metadata.get(key) if metadata else None)
109
+ for key, value in params.items()
110
+ ]
111
+ )
@@ -147,3 +147,30 @@ def test_to_sweep_resolver_list(r_list_gen):
147
147
  def test_to_sweep_type_error():
148
148
  with pytest.raises(TypeError, match='Unexpected sweep'):
149
149
  cirq.to_sweep(5)
150
+
151
+
152
+ def test_to_sweeps_with_param_dict_appends_metadata():
153
+ params = {'a': 1, 'b': 2, 'c': 3}
154
+ unit_map = {'a': 'ns', 'b': 'ns'}
155
+
156
+ sweep = cirq.to_sweeps(params, unit_map)
157
+
158
+ assert sweep == [
159
+ cirq.Zip(
160
+ cirq.Points('a', [1], metadata='ns'),
161
+ cirq.Points('b', [2], metadata='ns'),
162
+ cirq.Points('c', [3]),
163
+ )
164
+ ]
165
+
166
+
167
+ def test_to_sweeps_with_param_list_appends_metadata():
168
+ resolvers = [cirq.ParamResolver({'a': 2}), cirq.ParamResolver({'a': 1})]
169
+ unit_map = {'a': 'ns'}
170
+
171
+ sweeps = cirq.study.to_sweeps(resolvers, unit_map)
172
+
173
+ assert sweeps == [
174
+ cirq.Zip(cirq.Points('a', [2], metadata='ns')),
175
+ cirq.Zip(cirq.Points('a', [1], metadata='ns')),
176
+ ]
cirq/study/sweeps.py CHANGED
@@ -11,6 +11,9 @@
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
+ import abc
15
+ import collections
16
+ import itertools
14
17
  from typing import (
15
18
  Any,
16
19
  cast,
@@ -21,14 +24,11 @@ from typing import (
21
24
  Optional,
22
25
  overload,
23
26
  Sequence,
24
- TYPE_CHECKING,
25
27
  Tuple,
28
+ TYPE_CHECKING,
26
29
  Union,
27
30
  )
28
31
 
29
- import abc
30
- import collections
31
- import itertools
32
32
  import sympy
33
33
 
34
34
  from cirq import protocols
@@ -216,7 +216,8 @@ class Product(Sweep):
216
216
  If one sweep assigns 'a' to the values 0, 1, 2, and the second sweep
217
217
  assigns 'b' to the values 2, 3, then the product is a sweep that
218
218
  assigns the tuple ('a','b') to all possible combinations of these
219
- assignments: (0, 2), (1, 2), (2, 2), (0, 3), (1, 3), (2, 3).
219
+ assignments: (0, 2), (0, 3), (1, 2), (1, 3), (2, 2), (2, 3).
220
+ That is, the leftmost sweep is the outer loop in a product of sweeps.
220
221
  """
221
222
 
222
223
  def __init__(self, *factors: Sweep) -> None:
@@ -276,6 +277,63 @@ class Product(Sweep):
276
277
  return Product(*factors)
277
278
 
278
279
 
280
+ class Concat(Sweep):
281
+ """Concatenates multiple to a new sweep.
282
+
283
+ All sweeps must share the same descriptors.
284
+
285
+ If one sweep assigns 'a' to the values 0, 1, 2, and another sweep assigns
286
+ 'a' to the values 3, 4, 5, the concatenation produces a sweep assigning
287
+ 'a' to the values 0, 1, 2, 3, 4, 5 in sequence.
288
+ """
289
+
290
+ def __init__(self, *sweeps: Sweep) -> None:
291
+ if not sweeps:
292
+ raise ValueError("Concat requires at least one sweep.")
293
+
294
+ # Validate consistency across sweeps
295
+ first_sweep = sweeps[0]
296
+ for sweep in sweeps[1:]:
297
+ if sweep.keys != first_sweep.keys:
298
+ raise ValueError("All sweeps must have the same descriptors.")
299
+
300
+ self.sweeps = sweeps
301
+
302
+ def __eq__(self, other):
303
+ if not isinstance(other, Concat):
304
+ return NotImplemented
305
+ return self.sweeps == other.sweeps
306
+
307
+ def __hash__(self):
308
+ return hash(tuple(self.sweeps))
309
+
310
+ @property
311
+ def keys(self) -> List['cirq.TParamKey']:
312
+ return self.sweeps[0].keys
313
+
314
+ def __len__(self) -> int:
315
+ return sum(len(sweep) for sweep in self.sweeps)
316
+
317
+ def param_tuples(self) -> Iterator[Params]:
318
+ for sweep in self.sweeps:
319
+ yield from sweep.param_tuples()
320
+
321
+ def __repr__(self) -> str:
322
+ sweeps_repr = ', '.join(repr(sweep) for sweep in self.sweeps)
323
+ return f'cirq.Concat({sweeps_repr})'
324
+
325
+ def __str__(self) -> str:
326
+ sweeps_repr = ', '.join(repr(s) for s in self.sweeps)
327
+ return f'Concat({sweeps_repr})'
328
+
329
+ def _json_dict_(self) -> Dict[str, Any]:
330
+ return protocols.obj_to_dict_helper(self, ['sweeps'])
331
+
332
+ @classmethod
333
+ def _from_json_dict_(cls, sweeps, **kwargs):
334
+ return Concat(*sweeps)
335
+
336
+
279
337
  class Zip(Sweep):
280
338
  """Zip product (direct sum) of one or more sweeps.
281
339
 
@@ -346,7 +404,7 @@ class ZipLongest(Zip):
346
404
  which uses a fixed fill value.
347
405
 
348
406
  Raises:
349
- ValueError if an input sweep if completely empty.
407
+ ValueError if an input sweep is completely empty.
350
408
  """
351
409
 
352
410
  def __init__(self, *sweeps: Sweep) -> None:
@@ -589,10 +647,7 @@ def dict_to_product_sweep(factor_dict: ProductOrZipSweepLike) -> Product:
589
647
  Cartesian product of the sweeps.
590
648
  """
591
649
  return Product(
592
- *(
593
- Points(k, v if isinstance(v, Sequence) else [v]) # type: ignore
594
- for k, v in factor_dict.items()
595
- )
650
+ *(Points(k, v if isinstance(v, Sequence) else [v]) for k, v in factor_dict.items())
596
651
  )
597
652
 
598
653