qiskit 1.1.2__cp38-abi3-win32.whl → 1.2.0rc1__cp38-abi3-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. qiskit/VERSION.txt +1 -1
  2. qiskit/__init__.py +27 -24
  3. qiskit/_accelerate.pyd +0 -0
  4. qiskit/_numpy_compat.py +1 -1
  5. qiskit/assembler/assemble_circuits.py +107 -64
  6. qiskit/assembler/assemble_schedules.py +5 -12
  7. qiskit/assembler/disassemble.py +10 -1
  8. qiskit/circuit/__init__.py +1 -1
  9. qiskit/circuit/_classical_resource_map.py +5 -5
  10. qiskit/circuit/_utils.py +0 -13
  11. qiskit/circuit/add_control.py +1 -1
  12. qiskit/circuit/annotated_operation.py +23 -1
  13. qiskit/circuit/classical/expr/expr.py +4 -4
  14. qiskit/circuit/classical/expr/visitors.py +1 -1
  15. qiskit/circuit/classical/types/__init__.py +1 -1
  16. qiskit/circuit/classical/types/types.py +2 -2
  17. qiskit/circuit/classicalfunction/boolean_expression.py +1 -1
  18. qiskit/circuit/classicalfunction/classical_function_visitor.py +5 -5
  19. qiskit/circuit/classicalfunction/utils.py +1 -1
  20. qiskit/circuit/classicalregister.py +1 -1
  21. qiskit/circuit/commutation_checker.py +83 -35
  22. qiskit/circuit/controlflow/_builder_utils.py +1 -1
  23. qiskit/circuit/controlflow/builder.py +10 -6
  24. qiskit/circuit/controlflow/if_else.py +2 -2
  25. qiskit/circuit/controlflow/switch_case.py +1 -1
  26. qiskit/circuit/delay.py +1 -1
  27. qiskit/circuit/duration.py +2 -2
  28. qiskit/circuit/equivalence.py +5 -7
  29. qiskit/circuit/gate.py +11 -8
  30. qiskit/circuit/instruction.py +31 -13
  31. qiskit/circuit/instructionset.py +2 -5
  32. qiskit/circuit/library/__init__.py +2 -1
  33. qiskit/circuit/library/arithmetic/linear_amplitude_function.py +1 -1
  34. qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +1 -1
  35. qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +1 -1
  36. qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +1 -1
  37. qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +3 -3
  38. qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py +1 -1
  39. qiskit/circuit/library/basis_change/__init__.py +1 -1
  40. qiskit/circuit/library/basis_change/qft.py +40 -6
  41. qiskit/circuit/library/blueprintcircuit.py +3 -5
  42. qiskit/circuit/library/data_preparation/__init__.py +9 -2
  43. qiskit/circuit/library/data_preparation/initializer.py +8 -0
  44. qiskit/circuit/library/data_preparation/state_preparation.py +98 -178
  45. qiskit/circuit/library/generalized_gates/isometry.py +8 -8
  46. qiskit/circuit/library/generalized_gates/linear_function.py +3 -2
  47. qiskit/circuit/library/generalized_gates/mcg_up_to_diagonal.py +4 -4
  48. qiskit/circuit/library/generalized_gates/permutation.py +8 -9
  49. qiskit/circuit/library/generalized_gates/uc.py +3 -3
  50. qiskit/circuit/library/generalized_gates/uc_pauli_rot.py +2 -2
  51. qiskit/circuit/library/generalized_gates/unitary.py +13 -11
  52. qiskit/circuit/library/graph_state.py +1 -1
  53. qiskit/circuit/library/hamiltonian_gate.py +1 -2
  54. qiskit/circuit/library/hidden_linear_function.py +1 -1
  55. qiskit/circuit/library/n_local/evolved_operator_ansatz.py +3 -2
  56. qiskit/circuit/library/n_local/n_local.py +4 -5
  57. qiskit/circuit/library/n_local/pauli_two_design.py +1 -1
  58. qiskit/circuit/library/n_local/qaoa_ansatz.py +6 -8
  59. qiskit/circuit/library/n_local/two_local.py +1 -1
  60. qiskit/circuit/library/overlap.py +11 -5
  61. qiskit/circuit/library/pauli_evolution.py +7 -3
  62. qiskit/circuit/library/standard_gates/dcx.py +3 -0
  63. qiskit/circuit/library/standard_gates/ecr.py +3 -0
  64. qiskit/circuit/library/standard_gates/global_phase.py +3 -0
  65. qiskit/circuit/library/standard_gates/h.py +13 -5
  66. qiskit/circuit/library/standard_gates/i.py +3 -0
  67. qiskit/circuit/library/standard_gates/iswap.py +3 -0
  68. qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +19 -10
  69. qiskit/circuit/library/standard_gates/p.py +14 -9
  70. qiskit/circuit/library/standard_gates/r.py +3 -0
  71. qiskit/circuit/library/standard_gates/rx.py +21 -6
  72. qiskit/circuit/library/standard_gates/rxx.py +40 -1
  73. qiskit/circuit/library/standard_gates/ry.py +21 -6
  74. qiskit/circuit/library/standard_gates/ryy.py +40 -1
  75. qiskit/circuit/library/standard_gates/rz.py +22 -6
  76. qiskit/circuit/library/standard_gates/rzx.py +40 -1
  77. qiskit/circuit/library/standard_gates/rzz.py +41 -2
  78. qiskit/circuit/library/standard_gates/s.py +77 -0
  79. qiskit/circuit/library/standard_gates/swap.py +12 -5
  80. qiskit/circuit/library/standard_gates/sx.py +14 -5
  81. qiskit/circuit/library/standard_gates/t.py +5 -0
  82. qiskit/circuit/library/standard_gates/u.py +22 -7
  83. qiskit/circuit/library/standard_gates/u1.py +8 -3
  84. qiskit/circuit/library/standard_gates/u2.py +3 -0
  85. qiskit/circuit/library/standard_gates/u3.py +22 -7
  86. qiskit/circuit/library/standard_gates/x.py +156 -92
  87. qiskit/circuit/library/standard_gates/xx_minus_yy.py +40 -1
  88. qiskit/circuit/library/standard_gates/xx_plus_yy.py +52 -11
  89. qiskit/circuit/library/standard_gates/y.py +6 -1
  90. qiskit/circuit/library/standard_gates/z.py +8 -1
  91. qiskit/circuit/operation.py +1 -1
  92. qiskit/circuit/parameter.py +9 -10
  93. qiskit/circuit/parameterexpression.py +16 -13
  94. qiskit/circuit/parametertable.py +1 -190
  95. qiskit/circuit/parametervector.py +1 -1
  96. qiskit/circuit/quantumcircuit.py +392 -384
  97. qiskit/circuit/quantumcircuitdata.py +3 -5
  98. qiskit/circuit/quantumregister.py +1 -1
  99. qiskit/circuit/random/__init__.py +1 -1
  100. qiskit/circuit/random/utils.py +175 -26
  101. qiskit/circuit/register.py +5 -7
  102. qiskit/circuit/singleton.py +3 -3
  103. qiskit/circuit/tools/pi_check.py +4 -4
  104. qiskit/compiler/assembler.py +95 -24
  105. qiskit/compiler/scheduler.py +2 -2
  106. qiskit/compiler/transpiler.py +41 -127
  107. qiskit/converters/circuit_to_dag.py +4 -6
  108. qiskit/converters/circuit_to_gate.py +4 -8
  109. qiskit/converters/circuit_to_instruction.py +5 -17
  110. qiskit/converters/dag_to_circuit.py +2 -6
  111. qiskit/dagcircuit/collect_blocks.py +2 -2
  112. qiskit/dagcircuit/dagcircuit.py +190 -187
  113. qiskit/dagcircuit/dagdependency.py +4 -4
  114. qiskit/dagcircuit/dagdependency_v2.py +4 -4
  115. qiskit/dagcircuit/dagdepnode.py +1 -1
  116. qiskit/dagcircuit/dagnode.py +66 -157
  117. qiskit/passmanager/flow_controllers.py +1 -1
  118. qiskit/passmanager/passmanager.py +3 -3
  119. qiskit/primitives/__init__.py +1 -5
  120. qiskit/primitives/backend_estimator.py +25 -15
  121. qiskit/primitives/backend_estimator_v2.py +31 -7
  122. qiskit/primitives/backend_sampler.py +21 -12
  123. qiskit/primitives/backend_sampler_v2.py +12 -3
  124. qiskit/primitives/base/base_estimator.py +31 -4
  125. qiskit/primitives/base/base_primitive.py +2 -2
  126. qiskit/primitives/base/base_result.py +2 -2
  127. qiskit/primitives/base/base_sampler.py +26 -2
  128. qiskit/primitives/base/estimator_result.py +2 -2
  129. qiskit/primitives/base/sampler_result.py +2 -2
  130. qiskit/primitives/containers/__init__.py +0 -1
  131. qiskit/primitives/containers/bindings_array.py +2 -2
  132. qiskit/primitives/containers/bit_array.py +108 -10
  133. qiskit/primitives/containers/shape.py +3 -3
  134. qiskit/primitives/estimator.py +9 -2
  135. qiskit/primitives/primitive_job.py +1 -1
  136. qiskit/primitives/sampler.py +10 -3
  137. qiskit/primitives/statevector_estimator.py +5 -3
  138. qiskit/primitives/statevector_sampler.py +11 -5
  139. qiskit/primitives/utils.py +16 -0
  140. qiskit/providers/backend.py +15 -6
  141. qiskit/providers/backend_compat.py +7 -4
  142. qiskit/providers/basic_provider/basic_provider_tools.py +1 -1
  143. qiskit/providers/basic_provider/basic_simulator.py +32 -24
  144. qiskit/providers/fake_provider/fake_backend.py +10 -3
  145. qiskit/providers/fake_provider/fake_openpulse_2q.py +154 -146
  146. qiskit/providers/fake_provider/fake_openpulse_3q.py +226 -217
  147. qiskit/providers/fake_provider/fake_qasm_backend.py +5 -1
  148. qiskit/providers/fake_provider/generic_backend_v2.py +80 -50
  149. qiskit/providers/models/__init__.py +11 -0
  150. qiskit/providers/models/backendconfiguration.py +50 -4
  151. qiskit/providers/models/backendproperties.py +13 -2
  152. qiskit/providers/models/pulsedefaults.py +10 -11
  153. qiskit/providers/options.py +13 -13
  154. qiskit/providers/providerutils.py +3 -1
  155. qiskit/pulse/configuration.py +8 -12
  156. qiskit/pulse/instruction_schedule_map.py +3 -5
  157. qiskit/pulse/instructions/acquire.py +7 -8
  158. qiskit/pulse/instructions/instruction.py +2 -3
  159. qiskit/pulse/library/samplers/decorators.py +5 -9
  160. qiskit/pulse/library/symbolic_pulses.py +4 -7
  161. qiskit/pulse/library/waveform.py +2 -5
  162. qiskit/pulse/macros.py +11 -6
  163. qiskit/pulse/parser.py +8 -10
  164. qiskit/pulse/schedule.py +9 -17
  165. qiskit/pulse/transforms/alignments.py +1 -3
  166. qiskit/pulse/utils.py +1 -2
  167. qiskit/qasm/libs/stdgates.inc +35 -28
  168. qiskit/qasm2/__init__.py +7 -7
  169. qiskit/qasm2/export.py +5 -9
  170. qiskit/qasm2/parse.py +1 -1
  171. qiskit/qasm3/ast.py +9 -25
  172. qiskit/qasm3/exporter.py +578 -481
  173. qiskit/qasm3/printer.py +7 -16
  174. qiskit/qobj/common.py +10 -0
  175. qiskit/qobj/converters/lo_config.py +9 -0
  176. qiskit/qobj/converters/pulse_instruction.py +13 -6
  177. qiskit/qobj/pulse_qobj.py +69 -15
  178. qiskit/qobj/qasm_qobj.py +72 -20
  179. qiskit/qobj/utils.py +9 -0
  180. qiskit/qpy/binary_io/circuits.py +8 -5
  181. qiskit/qpy/binary_io/schedules.py +1 -1
  182. qiskit/qpy/binary_io/value.py +3 -3
  183. qiskit/qpy/interface.py +3 -2
  184. qiskit/qpy/type_keys.py +2 -2
  185. qiskit/quantum_info/operators/channel/quantum_channel.py +3 -6
  186. qiskit/quantum_info/operators/channel/superop.py +2 -2
  187. qiskit/quantum_info/operators/channel/transformations.py +1 -1
  188. qiskit/quantum_info/operators/dihedral/dihedral.py +3 -4
  189. qiskit/quantum_info/operators/dihedral/dihedral_circuits.py +1 -3
  190. qiskit/quantum_info/operators/dihedral/random.py +6 -3
  191. qiskit/quantum_info/operators/measures.py +2 -2
  192. qiskit/quantum_info/operators/op_shape.py +12 -20
  193. qiskit/quantum_info/operators/operator.py +14 -21
  194. qiskit/quantum_info/operators/predicates.py +1 -0
  195. qiskit/quantum_info/operators/symplectic/base_pauli.py +7 -11
  196. qiskit/quantum_info/operators/symplectic/clifford.py +1 -1
  197. qiskit/quantum_info/operators/symplectic/pauli.py +3 -3
  198. qiskit/quantum_info/operators/symplectic/pauli_list.py +9 -10
  199. qiskit/quantum_info/operators/symplectic/random.py +1 -1
  200. qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +14 -16
  201. qiskit/quantum_info/quaternion.py +1 -1
  202. qiskit/quantum_info/states/densitymatrix.py +5 -8
  203. qiskit/quantum_info/states/stabilizerstate.py +128 -37
  204. qiskit/quantum_info/states/statevector.py +4 -8
  205. qiskit/result/counts.py +2 -2
  206. qiskit/result/mitigation/correlated_readout_mitigator.py +2 -2
  207. qiskit/result/mitigation/local_readout_mitigator.py +2 -2
  208. qiskit/result/mitigation/utils.py +1 -3
  209. qiskit/result/models.py +17 -16
  210. qiskit/result/result.py +15 -20
  211. qiskit/scheduler/lowering.py +2 -2
  212. qiskit/synthesis/__init__.py +2 -1
  213. qiskit/synthesis/clifford/__init__.py +1 -1
  214. qiskit/synthesis/clifford/clifford_decompose_ag.py +2 -2
  215. qiskit/synthesis/clifford/clifford_decompose_bm.py +10 -240
  216. qiskit/synthesis/clifford/clifford_decompose_greedy.py +9 -303
  217. qiskit/synthesis/clifford/clifford_decompose_layers.py +25 -23
  218. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_full.py +1 -1
  219. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_general.py +1 -1
  220. qiskit/synthesis/discrete_basis/generate_basis_approximations.py +1 -1
  221. qiskit/synthesis/discrete_basis/solovay_kitaev.py +2 -2
  222. qiskit/synthesis/evolution/evolution_synthesis.py +4 -2
  223. qiskit/synthesis/evolution/lie_trotter.py +46 -19
  224. qiskit/synthesis/evolution/product_formula.py +111 -55
  225. qiskit/synthesis/evolution/qdrift.py +40 -10
  226. qiskit/synthesis/evolution/suzuki_trotter.py +43 -33
  227. qiskit/synthesis/linear/__init__.py +1 -0
  228. qiskit/synthesis/linear/cnot_synth.py +22 -96
  229. qiskit/synthesis/linear/linear_depth_lnn.py +8 -8
  230. qiskit/synthesis/linear/linear_matrix_utils.py +13 -161
  231. qiskit/synthesis/linear_phase/cnot_phase_synth.py +1 -1
  232. qiskit/synthesis/linear_phase/cx_cz_depth_lnn.py +3 -3
  233. qiskit/synthesis/linear_phase/cz_depth_lnn.py +1 -1
  234. qiskit/synthesis/one_qubit/one_qubit_decompose.py +29 -29
  235. qiskit/synthesis/permutation/permutation_full.py +5 -29
  236. qiskit/synthesis/permutation/permutation_lnn.py +2 -24
  237. qiskit/synthesis/permutation/permutation_utils.py +2 -59
  238. qiskit/synthesis/qft/__init__.py +1 -0
  239. qiskit/synthesis/qft/qft_decompose_full.py +79 -0
  240. qiskit/synthesis/qft/qft_decompose_lnn.py +17 -9
  241. qiskit/synthesis/stabilizer/stabilizer_circuit.py +6 -6
  242. qiskit/synthesis/stabilizer/stabilizer_decompose.py +2 -2
  243. qiskit/synthesis/two_qubit/local_invariance.py +8 -38
  244. qiskit/synthesis/two_qubit/two_qubit_decompose.py +48 -129
  245. qiskit/synthesis/unitary/aqc/cnot_structures.py +1 -1
  246. qiskit/synthesis/unitary/qsd.py +5 -3
  247. qiskit/transpiler/__init__.py +1 -0
  248. qiskit/transpiler/basepasses.py +1 -1
  249. qiskit/transpiler/coupling.py +3 -3
  250. qiskit/transpiler/instruction_durations.py +1 -2
  251. qiskit/transpiler/layout.py +3 -3
  252. qiskit/transpiler/passes/__init__.py +2 -0
  253. qiskit/transpiler/passes/basis/basis_translator.py +82 -63
  254. qiskit/transpiler/passes/basis/translate_parameterized.py +3 -5
  255. qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
  256. qiskit/transpiler/passes/basis/unroll_custom_definitions.py +10 -10
  257. qiskit/transpiler/passes/calibration/rx_builder.py +3 -3
  258. qiskit/transpiler/passes/calibration/rzx_builder.py +3 -3
  259. qiskit/transpiler/passes/layout/apply_layout.py +13 -3
  260. qiskit/transpiler/passes/layout/sabre_layout.py +10 -8
  261. qiskit/transpiler/passes/layout/sabre_pre_layout.py +4 -1
  262. qiskit/transpiler/passes/layout/set_layout.py +2 -2
  263. qiskit/transpiler/passes/layout/vf2_layout.py +1 -1
  264. qiskit/transpiler/passes/layout/vf2_utils.py +3 -3
  265. qiskit/transpiler/passes/optimization/__init__.py +1 -0
  266. qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +2 -2
  267. qiskit/transpiler/passes/optimization/commutation_analysis.py +7 -10
  268. qiskit/transpiler/passes/optimization/commutative_cancellation.py +35 -19
  269. qiskit/transpiler/passes/optimization/consolidate_blocks.py +11 -8
  270. qiskit/transpiler/passes/optimization/inverse_cancellation.py +6 -6
  271. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +64 -41
  272. qiskit/transpiler/passes/optimization/optimize_1q_gates.py +1 -1
  273. qiskit/transpiler/passes/optimization/split_2q_unitaries.py +83 -0
  274. qiskit/transpiler/passes/optimization/template_matching/backward_match.py +1 -1
  275. qiskit/transpiler/passes/optimization/template_matching/forward_match.py +2 -2
  276. qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +1 -1
  277. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +3 -2
  278. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +1 -1
  279. qiskit/transpiler/passes/routing/layout_transformation.py +2 -1
  280. qiskit/transpiler/passes/routing/sabre_swap.py +35 -26
  281. qiskit/transpiler/passes/routing/star_prerouting.py +80 -105
  282. qiskit/transpiler/passes/routing/stochastic_swap.py +1 -3
  283. qiskit/transpiler/passes/scheduling/alap.py +1 -2
  284. qiskit/transpiler/passes/scheduling/alignments/__init__.py +2 -2
  285. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
  286. qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +1 -1
  287. qiskit/transpiler/passes/scheduling/alignments/reschedule.py +1 -1
  288. qiskit/transpiler/passes/scheduling/asap.py +1 -2
  289. qiskit/transpiler/passes/scheduling/base_scheduler.py +5 -5
  290. qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +3 -3
  291. qiskit/transpiler/passes/scheduling/padding/base_padding.py +1 -1
  292. qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +11 -11
  293. qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +7 -6
  294. qiskit/transpiler/passes/scheduling/time_unit_conversion.py +4 -3
  295. qiskit/transpiler/passes/synthesis/high_level_synthesis.py +211 -36
  296. qiskit/transpiler/passes/synthesis/plugin.py +2 -2
  297. qiskit/transpiler/passes/synthesis/unitary_synthesis.py +80 -40
  298. qiskit/transpiler/passes/utils/__init__.py +0 -1
  299. qiskit/transpiler/passes/utils/check_gate_direction.py +4 -4
  300. qiskit/transpiler/passes/utils/check_map.py +3 -6
  301. qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +3 -4
  302. qiskit/transpiler/passes/utils/error.py +2 -2
  303. qiskit/transpiler/passes/utils/fixed_point.py +3 -3
  304. qiskit/transpiler/passes/utils/gate_direction.py +1 -1
  305. qiskit/transpiler/passes/utils/gates_basis.py +1 -2
  306. qiskit/transpiler/passmanager.py +7 -6
  307. qiskit/transpiler/preset_passmanagers/__init__.py +4 -228
  308. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +117 -18
  309. qiskit/transpiler/preset_passmanagers/common.py +3 -6
  310. qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +518 -0
  311. qiskit/transpiler/preset_passmanagers/level0.py +1 -1
  312. qiskit/transpiler/target.py +27 -8
  313. qiskit/user_config.py +29 -6
  314. qiskit/utils/classtools.py +3 -3
  315. qiskit/utils/deprecation.py +3 -2
  316. qiskit/utils/lazy_tester.py +2 -2
  317. qiskit/utils/optionals.py +8 -8
  318. qiskit/visualization/bloch.py +19 -67
  319. qiskit/visualization/circuit/_utils.py +34 -10
  320. qiskit/visualization/circuit/circuit_visualization.py +23 -16
  321. qiskit/visualization/circuit/latex.py +29 -27
  322. qiskit/visualization/circuit/matplotlib.py +4 -2
  323. qiskit/visualization/circuit/qcstyle.py +2 -2
  324. qiskit/visualization/circuit/text.py +9 -15
  325. qiskit/visualization/dag_visualization.py +5 -12
  326. qiskit/visualization/pulse_v2/core.py +1 -1
  327. qiskit/visualization/pulse_v2/events.py +1 -1
  328. qiskit/visualization/pulse_v2/generators/frame.py +3 -4
  329. qiskit/visualization/pulse_v2/generators/waveform.py +5 -9
  330. qiskit/visualization/pulse_v2/layouts.py +1 -5
  331. qiskit/visualization/pulse_v2/plotters/matplotlib.py +1 -2
  332. qiskit/visualization/state_visualization.py +5 -6
  333. qiskit/visualization/timeline/plotters/matplotlib.py +1 -2
  334. qiskit/visualization/transition_visualization.py +7 -2
  335. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/METADATA +26 -26
  336. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/RECORD +340 -338
  337. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/WHEEL +1 -1
  338. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/entry_points.txt +3 -0
  339. qiskit/transpiler/passes/utils/block_to_matrix.py +0 -47
  340. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/LICENSE.txt +0 -0
  341. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/top_level.txt +0 -0
@@ -33,9 +33,10 @@ from qiskit.synthesis.linear import (
33
33
  from qiskit.synthesis.linear_phase import synth_cz_depth_line_mr, synth_cx_cz_depth_line_my
34
34
  from qiskit.synthesis.linear.linear_matrix_utils import (
35
35
  calc_inverse_matrix,
36
- _compute_rank,
37
- _gauss_elimination,
38
- _gauss_elimination_with_perm,
36
+ compute_rank,
37
+ gauss_elimination,
38
+ gauss_elimination_with_perm,
39
+ binary_matmul,
39
40
  )
40
41
 
41
42
 
@@ -137,32 +138,32 @@ def synth_clifford_layers(
137
138
  cz_func_reverse_qubits=cz_func_reverse_qubits,
138
139
  )
139
140
 
140
- layeredCircuit.append(S2_circ, qubit_list)
141
+ layeredCircuit.append(S2_circ, qubit_list, copy=False)
141
142
 
142
143
  if cx_cz_synth_func is None:
143
- layeredCircuit.append(CZ2_circ, qubit_list)
144
+ layeredCircuit.append(CZ2_circ, qubit_list, copy=False)
144
145
 
145
146
  CXinv = CX_circ.copy().inverse()
146
- layeredCircuit.append(CXinv, qubit_list)
147
+ layeredCircuit.append(CXinv, qubit_list, copy=False)
147
148
 
148
149
  else:
149
150
  # note that CZ2_circ is None and built into the CX_circ when
150
151
  # cx_cz_synth_func is not None
151
- layeredCircuit.append(CX_circ, qubit_list)
152
+ layeredCircuit.append(CX_circ, qubit_list, copy=False)
152
153
 
153
- layeredCircuit.append(H2_circ, qubit_list)
154
- layeredCircuit.append(S1_circ, qubit_list)
155
- layeredCircuit.append(CZ1_circ, qubit_list)
154
+ layeredCircuit.append(H2_circ, qubit_list, copy=False)
155
+ layeredCircuit.append(S1_circ, qubit_list, copy=False)
156
+ layeredCircuit.append(CZ1_circ, qubit_list, copy=False)
156
157
 
157
158
  if cz_func_reverse_qubits:
158
159
  H1_circ = H1_circ.reverse_bits()
159
- layeredCircuit.append(H1_circ, qubit_list)
160
+ layeredCircuit.append(H1_circ, qubit_list, copy=False)
160
161
 
161
162
  # Add Pauli layer to fix the Clifford phase signs
162
163
 
163
164
  clifford_target = Clifford(layeredCircuit)
164
165
  pauli_circ = _calc_pauli_diff(cliff, clifford_target)
165
- layeredCircuit.append(pauli_circ, qubit_list)
166
+ layeredCircuit.append(pauli_circ, qubit_list, copy=False)
166
167
 
167
168
  return layeredCircuit
168
169
 
@@ -203,24 +204,25 @@ def _create_graph_state(cliff, validate=False):
203
204
  """
204
205
 
205
206
  num_qubits = cliff.num_qubits
206
- rank = _compute_rank(cliff.stab_x)
207
+ rank = compute_rank(np.asarray(cliff.stab_x, dtype=bool))
207
208
  H1_circ = QuantumCircuit(num_qubits, name="H1")
208
209
  cliffh = cliff.copy()
209
210
 
210
211
  if rank < num_qubits:
211
212
  stab = cliff.stab[:, :-1]
212
- stab = _gauss_elimination(stab, num_qubits)
213
+ stab = stab.astype(bool, copy=True)
214
+ gauss_elimination(stab, num_qubits)
213
215
 
214
216
  Cmat = stab[rank:num_qubits, num_qubits:]
215
217
  Cmat = np.transpose(Cmat)
216
- Cmat, perm = _gauss_elimination_with_perm(Cmat)
218
+ perm = gauss_elimination_with_perm(Cmat)
217
219
  perm = perm[0 : num_qubits - rank]
218
220
 
219
221
  # validate that the output matrix has the same rank
220
222
  if validate:
221
- if _compute_rank(Cmat) != num_qubits - rank:
223
+ if compute_rank(Cmat) != num_qubits - rank:
222
224
  raise QiskitError("The matrix Cmat after Gauss elimination has wrong rank.")
223
- if _compute_rank(stab[:, 0:num_qubits]) != rank:
225
+ if compute_rank(stab[:, 0:num_qubits]) != rank:
224
226
  raise QiskitError("The matrix after Gauss elimination has wrong rank.")
225
227
  # validate that we have a num_qubits - rank zero rows
226
228
  for i in range(rank, num_qubits):
@@ -236,8 +238,8 @@ def _create_graph_state(cliff, validate=False):
236
238
 
237
239
  # validate that a layer of Hadamard gates and then appending cliff, provides a graph state.
238
240
  if validate:
239
- stabh = cliffh.stab_x
240
- if _compute_rank(stabh) != num_qubits:
241
+ stabh = (cliffh.stab_x).astype(bool, copy=False)
242
+ if compute_rank(stabh) != num_qubits:
241
243
  raise QiskitError("The state is not a graph state.")
242
244
 
243
245
  return H1_circ, cliffh
@@ -267,7 +269,7 @@ def _decompose_graph_state(cliff, validate, cz_synth_func):
267
269
  """
268
270
 
269
271
  num_qubits = cliff.num_qubits
270
- rank = _compute_rank(cliff.stab_x)
272
+ rank = compute_rank(np.asarray(cliff.stab_x, dtype=bool))
271
273
  cliff_cpy = cliff.copy()
272
274
  if rank < num_qubits:
273
275
  raise QiskitError("The stabilizer state is not a graph state.")
@@ -278,7 +280,7 @@ def _decompose_graph_state(cliff, validate, cz_synth_func):
278
280
  stabx = cliff.stab_x
279
281
  stabz = cliff.stab_z
280
282
  stabx_inv = calc_inverse_matrix(stabx, validate)
281
- stabz_update = np.matmul(stabx_inv, stabz) % 2
283
+ stabz_update = binary_matmul(stabx_inv, stabz)
282
284
 
283
285
  # Assert that stabz_update is a symmetric matrix.
284
286
  if validate:
@@ -340,7 +342,7 @@ def _decompose_hadamard_free(
340
342
  if not (stabx == np.zeros((num_qubits, num_qubits))).all():
341
343
  raise QiskitError("The given Clifford is not Hadamard-free.")
342
344
 
343
- destabz_update = np.matmul(calc_inverse_matrix(destabx), destabz) % 2
345
+ destabz_update = binary_matmul(calc_inverse_matrix(destabx), destabz)
344
346
  # Assert that destabz_update is a symmetric matrix.
345
347
  if validate:
346
348
  if (destabz_update != destabz_update.T).any():
@@ -412,7 +414,7 @@ def _calc_pauli_diff(cliff, cliff_target):
412
414
 
413
415
 
414
416
  def synth_clifford_depth_lnn(cliff):
415
- """Synthesis of a :class:`.Clifford` into layers for linear-nearest neighbour connectivity.
417
+ """Synthesis of a :class:`.Clifford` into layers for linear-nearest neighbor connectivity.
416
418
 
417
419
  The depth of the synthesized n-qubit circuit is bounded by :math:`7n+2`, which is not optimal.
418
420
  It should be replaced by a better algorithm that provides depth bounded by :math:`7n-4` [3].
@@ -40,7 +40,7 @@ def synth_cnotdihedral_full(elem: CNOTDihedral) -> QuantumCircuit:
40
40
  with optimal number of two qubit gates*, `Quantum 4(369), 2020
41
41
  <https://quantum-journal.org/papers/q-2020-12-07-369/>`_
42
42
  2. Andrew W. Cross, Easwar Magesan, Lev S. Bishop, John A. Smolin and Jay M. Gambetta,
43
- *Scalable randomised benchmarking of non-Clifford gates*,
43
+ *Scalable randomized benchmarking of non-Clifford gates*,
44
44
  npj Quantum Inf 2, 16012 (2016).
45
45
  """
46
46
 
@@ -38,7 +38,7 @@ def synth_cnotdihedral_general(elem: CNOTDihedral) -> QuantumCircuit:
38
38
 
39
39
  References:
40
40
  1. Andrew W. Cross, Easwar Magesan, Lev S. Bishop, John A. Smolin and Jay M. Gambetta,
41
- *Scalable randomised benchmarking of non-Clifford gates*,
41
+ *Scalable randomized benchmarking of non-Clifford gates*,
42
42
  npj Quantum Inf 2, 16012 (2016).
43
43
  """
44
44
 
@@ -137,7 +137,7 @@ def generate_basic_approximations(
137
137
  basis = []
138
138
  for gate in basis_gates:
139
139
  if isinstance(gate, str):
140
- if gate not in _1q_gates.keys():
140
+ if gate not in _1q_gates:
141
141
  raise ValueError(f"Invalid gate identifier: {gate}")
142
142
  basis.append(gate)
143
143
  else: # gate is a qiskit.circuit.Gate
@@ -119,7 +119,7 @@ class SolovayKitaevDecomposition:
119
119
  gate_matrix_su2 = GateSequence.from_matrix(z * gate_matrix)
120
120
  global_phase = np.arctan2(np.imag(z), np.real(z))
121
121
 
122
- # get the decompositon as GateSequence type
122
+ # get the decomposition as GateSequence type
123
123
  decomposition = self._recurse(gate_matrix_su2, recursion_degree, check_input=check_input)
124
124
 
125
125
  # simplify
@@ -190,7 +190,7 @@ def _remove_inverse_follows_gate(sequence):
190
190
  while index < len(sequence.gates) - 1:
191
191
  curr_gate = sequence.gates[index]
192
192
  next_gate = sequence.gates[index + 1]
193
- if curr_gate.name in _1q_inverses.keys():
193
+ if curr_gate.name in _1q_inverses:
194
194
  remove = _1q_inverses[curr_gate.name] == next_gate.name
195
195
  else:
196
196
  remove = curr_gate.inverse() == next_gate
@@ -12,8 +12,10 @@
12
12
 
13
13
  """Evolution synthesis."""
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  from abc import ABC, abstractmethod
16
- from typing import Any, Dict
18
+ from typing import Any
17
19
 
18
20
 
19
21
  class EvolutionSynthesis(ABC):
@@ -32,7 +34,7 @@ class EvolutionSynthesis(ABC):
32
34
  raise NotImplementedError
33
35
 
34
36
  @property
35
- def settings(self) -> Dict[str, Any]:
37
+ def settings(self) -> dict[str, Any]:
36
38
  """Return the settings in a dictionary, which can be used to reconstruct the object.
37
39
 
38
40
  Returns:
@@ -12,10 +12,15 @@
12
12
 
13
13
  """The Lie-Trotter product formula."""
14
14
 
15
- from typing import Callable, Optional, Union, Dict, Any
15
+ from __future__ import annotations
16
+
17
+ import inspect
18
+ from collections.abc import Callable
19
+ from typing import Any
16
20
  import numpy as np
17
21
  from qiskit.circuit.quantumcircuit import QuantumCircuit
18
22
  from qiskit.quantum_info.operators import SparsePauliOp, Pauli
23
+ from qiskit.utils.deprecation import deprecate_arg
19
24
 
20
25
  from .product_formula import ProductFormula
21
26
 
@@ -47,14 +52,32 @@ class LieTrotter(ProductFormula):
47
52
  `arXiv:math-ph/0506007 <https://arxiv.org/pdf/math-ph/0506007.pdf>`_
48
53
  """
49
54
 
55
+ @deprecate_arg(
56
+ name="atomic_evolution",
57
+ since="1.2",
58
+ predicate=lambda callable: callable is not None
59
+ and len(inspect.signature(callable).parameters) == 2,
60
+ deprecation_description=(
61
+ "The 'Callable[[Pauli | SparsePauliOp, float], QuantumCircuit]' signature of the "
62
+ "'atomic_evolution' argument"
63
+ ),
64
+ additional_msg=(
65
+ "Instead you should update your 'atomic_evolution' function to be of the following "
66
+ "type: 'Callable[[QuantumCircuit, Pauli | SparsePauliOp, float], None]'."
67
+ ),
68
+ pending=True,
69
+ )
50
70
  def __init__(
51
71
  self,
52
72
  reps: int = 1,
53
73
  insert_barriers: bool = False,
54
74
  cx_structure: str = "chain",
55
- atomic_evolution: Optional[
56
- Callable[[Union[Pauli, SparsePauliOp], float], QuantumCircuit]
57
- ] = None,
75
+ atomic_evolution: (
76
+ Callable[[Pauli | SparsePauliOp, float], QuantumCircuit]
77
+ | Callable[[QuantumCircuit, Pauli | SparsePauliOp, float], None]
78
+ | None
79
+ ) = None,
80
+ wrap: bool = False,
58
81
  ) -> None:
59
82
  """
60
83
  Args:
@@ -62,12 +85,20 @@ class LieTrotter(ProductFormula):
62
85
  insert_barriers: Whether to insert barriers between the atomic evolutions.
63
86
  cx_structure: How to arrange the CX gates for the Pauli evolutions, can be
64
87
  ``"chain"``, where next neighbor connections are used, or ``"fountain"``,
65
- where all qubits are connected to one.
66
- atomic_evolution: A function to construct the circuit for the evolution of single
67
- Pauli string. Per default, a single Pauli evolution is decomposed in a CX chain
68
- and a single qubit Z rotation.
88
+ where all qubits are connected to one. This only takes effect when
89
+ ``atomic_evolution is None``.
90
+ atomic_evolution: A function to apply the evolution of a single :class:`.Pauli`, or
91
+ :class:`.SparsePauliOp` of only commuting terms, to a circuit. The function takes in
92
+ three arguments: the circuit to append the evolution to, the Pauli operator to
93
+ evolve, and the evolution time. By default, a single Pauli evolution is decomposed
94
+ into a chain of ``CX`` gates and a single ``RZ`` gate.
95
+ Alternatively, the function can also take Pauli operator and evolution time as
96
+ inputs and returns the circuit that will be appended to the overall circuit being
97
+ built.
98
+ wrap: Whether to wrap the atomic evolutions into custom gate objects. This only takes
99
+ effect when ``atomic_evolution is None``.
69
100
  """
70
- super().__init__(1, reps, insert_barriers, cx_structure, atomic_evolution)
101
+ super().__init__(1, reps, insert_barriers, cx_structure, atomic_evolution, wrap)
71
102
 
72
103
  def synthesize(self, evolution):
73
104
  # get operators and time to evolve
@@ -75,27 +106,22 @@ class LieTrotter(ProductFormula):
75
106
  time = evolution.time
76
107
 
77
108
  # construct the evolution circuit
78
- evolution_circuit = QuantumCircuit(operators[0].num_qubits)
109
+ single_rep = QuantumCircuit(operators[0].num_qubits)
79
110
 
80
111
  if not isinstance(operators, list):
81
112
  pauli_list = [(Pauli(op), np.real(coeff)) for op, coeff in operators.to_list()]
82
113
  else:
83
114
  pauli_list = [(op, 1) for op in operators]
84
115
 
85
- # if we only evolve a single Pauli we don't need to additionally wrap it
86
- wrap = not (len(pauli_list) == 1 and self.reps == 1)
87
-
88
116
  for i, (op, coeff) in enumerate(pauli_list):
89
- evolution_circuit.compose(
90
- self.atomic_evolution(op, coeff * time / self.reps), wrap=wrap, inplace=True
91
- )
117
+ self.atomic_evolution(single_rep, op, coeff * time / self.reps)
92
118
  if self.insert_barriers and i != len(pauli_list) - 1:
93
- evolution_circuit.barrier()
119
+ single_rep.barrier()
94
120
 
95
- return evolution_circuit.repeat(self.reps).decompose()
121
+ return single_rep.repeat(self.reps, insert_barriers=self.insert_barriers).decompose()
96
122
 
97
123
  @property
98
- def settings(self) -> Dict[str, Any]:
124
+ def settings(self) -> dict[str, Any]:
99
125
  """Return the settings in a dictionary, which can be used to reconstruct the object.
100
126
 
101
127
  Returns:
@@ -113,4 +139,5 @@ class LieTrotter(ProductFormula):
113
139
  "reps": self.reps,
114
140
  "insert_barriers": self.insert_barriers,
115
141
  "cx_structure": self._cx_structure,
142
+ "wrap": self._wrap,
116
143
  }
@@ -12,12 +12,17 @@
12
12
 
13
13
  """A product formula base for decomposing non-commuting operator exponentials."""
14
14
 
15
- from typing import Callable, Optional, Union, Any, Dict
15
+ from __future__ import annotations
16
+
17
+ import inspect
18
+ from collections.abc import Callable
19
+ from typing import Any
16
20
  from functools import partial
17
21
  import numpy as np
18
22
  from qiskit.circuit.parameterexpression import ParameterExpression
19
23
  from qiskit.circuit.quantumcircuit import QuantumCircuit
20
24
  from qiskit.quantum_info import SparsePauliOp, Pauli
25
+ from qiskit.utils.deprecation import deprecate_arg
21
26
 
22
27
  from .evolution_synthesis import EvolutionSynthesis
23
28
 
@@ -28,15 +33,33 @@ class ProductFormula(EvolutionSynthesis):
28
33
  :obj:`.LieTrotter` and :obj:`.SuzukiTrotter` inherit from this class.
29
34
  """
30
35
 
36
+ @deprecate_arg(
37
+ name="atomic_evolution",
38
+ since="1.2",
39
+ predicate=lambda callable: callable is not None
40
+ and len(inspect.signature(callable).parameters) == 2,
41
+ deprecation_description=(
42
+ "The 'Callable[[Pauli | SparsePauliOp, float], QuantumCircuit]' signature of the "
43
+ "'atomic_evolution' argument"
44
+ ),
45
+ additional_msg=(
46
+ "Instead you should update your 'atomic_evolution' function to be of the following "
47
+ "type: 'Callable[[QuantumCircuit, Pauli | SparsePauliOp, float], None]'."
48
+ ),
49
+ pending=True,
50
+ )
31
51
  def __init__(
32
52
  self,
33
53
  order: int,
34
54
  reps: int = 1,
35
55
  insert_barriers: bool = False,
36
56
  cx_structure: str = "chain",
37
- atomic_evolution: Optional[
38
- Callable[[Union[Pauli, SparsePauliOp], float], QuantumCircuit]
39
- ] = None,
57
+ atomic_evolution: (
58
+ Callable[[Pauli | SparsePauliOp, float], QuantumCircuit]
59
+ | Callable[[QuantumCircuit, Pauli | SparsePauliOp, float], None]
60
+ | None
61
+ ) = None,
62
+ wrap: bool = False,
40
63
  ) -> None:
41
64
  """
42
65
  Args:
@@ -45,10 +68,18 @@ class ProductFormula(EvolutionSynthesis):
45
68
  insert_barriers: Whether to insert barriers between the atomic evolutions.
46
69
  cx_structure: How to arrange the CX gates for the Pauli evolutions, can be
47
70
  ``"chain"``, where next neighbor connections are used, or ``"fountain"``,
48
- where all qubits are connected to one.
49
- atomic_evolution: A function to construct the circuit for the evolution of single
50
- Pauli string. Per default, a single Pauli evolution is decomposed in a CX chain
51
- and a single qubit Z rotation.
71
+ where all qubits are connected to one. This only takes effect when
72
+ ``atomic_evolution is None``.
73
+ atomic_evolution: A function to apply the evolution of a single :class:`.Pauli`, or
74
+ :class:`.SparsePauliOp` of only commuting terms, to a circuit. The function takes in
75
+ three arguments: the circuit to append the evolution to, the Pauli operator to
76
+ evolve, and the evolution time. By default, a single Pauli evolution is decomposed
77
+ into a chain of ``CX`` gates and a single ``RZ`` gate.
78
+ Alternatively, the function can also take Pauli operator and evolution time as
79
+ inputs and returns the circuit that will be appended to the overall circuit being
80
+ built.
81
+ wrap: Whether to wrap the atomic evolutions into custom gate objects. This only takes
82
+ effect when ``atomic_evolution is None``.
52
83
  """
53
84
  super().__init__()
54
85
  self.order = order
@@ -58,15 +89,27 @@ class ProductFormula(EvolutionSynthesis):
58
89
  # user-provided atomic evolution, stored for serialization
59
90
  self._atomic_evolution = atomic_evolution
60
91
  self._cx_structure = cx_structure
92
+ self._wrap = wrap
61
93
 
62
94
  # if atomic evolution is not provided, set a default
63
95
  if atomic_evolution is None:
64
- atomic_evolution = partial(_default_atomic_evolution, cx_structure=cx_structure)
96
+ self.atomic_evolution = partial(
97
+ _default_atomic_evolution, cx_structure=cx_structure, wrap=wrap
98
+ )
99
+
100
+ elif len(inspect.signature(atomic_evolution).parameters) == 2:
101
+
102
+ def wrap_atomic_evolution(output, operator, time):
103
+ definition = atomic_evolution(operator, time)
104
+ output.compose(definition, wrap=wrap, inplace=True)
105
+
106
+ self.atomic_evolution = wrap_atomic_evolution
65
107
 
66
- self.atomic_evolution = atomic_evolution
108
+ else:
109
+ self.atomic_evolution = atomic_evolution
67
110
 
68
111
  @property
69
- def settings(self) -> Dict[str, Any]:
112
+ def settings(self) -> dict[str, Any]:
70
113
  """Return the settings in a dictionary, which can be used to reconstruct the object.
71
114
 
72
115
  Returns:
@@ -85,15 +128,18 @@ class ProductFormula(EvolutionSynthesis):
85
128
  "reps": self.reps,
86
129
  "insert_barriers": self.insert_barriers,
87
130
  "cx_structure": self._cx_structure,
131
+ "wrap": self._wrap,
88
132
  }
89
133
 
90
134
 
91
135
  def evolve_pauli(
136
+ output: QuantumCircuit,
92
137
  pauli: Pauli,
93
- time: Union[float, ParameterExpression] = 1.0,
138
+ time: float | ParameterExpression = 1.0,
94
139
  cx_structure: str = "chain",
95
- label: Optional[str] = None,
96
- ) -> QuantumCircuit:
140
+ wrap: bool = False,
141
+ label: str | None = None,
142
+ ) -> None:
97
143
  r"""Construct a circuit implementing the time evolution of a single Pauli string.
98
144
 
99
145
  For a Pauli string :math:`P = \{I, X, Y, Z\}^{\otimes n}` on :math:`n` qubits and an
@@ -106,79 +152,91 @@ def evolve_pauli(
106
152
  Since only a single Pauli string is evolved the circuit decomposition is exact.
107
153
 
108
154
  Args:
155
+ output: The circuit object to which to append the evolved Pauli.
109
156
  pauli: The Pauli to evolve.
110
157
  time: The evolution time.
111
158
  cx_structure: Determine the structure of CX gates, can be either ``"chain"`` for
112
159
  next-neighbor connections or ``"fountain"`` to connect directly to the top qubit.
160
+ wrap: Whether to wrap the single Pauli evolutions into custom gate objects.
113
161
  label: A label for the gate.
114
-
115
- Returns:
116
- A quantum circuit implementing the time evolution of the Pauli.
117
162
  """
118
163
  num_non_identity = len([label for label in pauli.to_label() if label != "I"])
119
164
 
120
165
  # first check, if the Pauli is only the identity, in which case the evolution only
121
166
  # adds a global phase
122
167
  if num_non_identity == 0:
123
- definition = QuantumCircuit(pauli.num_qubits, global_phase=-time)
168
+ output.global_phase -= time
124
169
  # if we evolve on a single qubit, if yes use the corresponding qubit rotation
125
170
  elif num_non_identity == 1:
126
- definition = _single_qubit_evolution(pauli, time)
171
+ _single_qubit_evolution(output, pauli, time, wrap)
127
172
  # same for two qubits, use Qiskit's native rotations
128
173
  elif num_non_identity == 2:
129
- definition = _two_qubit_evolution(pauli, time, cx_structure)
174
+ _two_qubit_evolution(output, pauli, time, cx_structure, wrap)
130
175
  # otherwise do basis transformation and CX chains
131
176
  else:
132
- definition = _multi_qubit_evolution(pauli, time, cx_structure)
133
-
134
- definition.name = f"exp(it {pauli.to_label()})"
177
+ _multi_qubit_evolution(output, pauli, time, cx_structure, wrap)
135
178
 
136
- return definition
137
179
 
138
-
139
- def _single_qubit_evolution(pauli, time):
140
- definition = QuantumCircuit(pauli.num_qubits)
180
+ def _single_qubit_evolution(output, pauli, time, wrap):
181
+ dest = QuantumCircuit(1) if wrap else output
141
182
  # Note that all phases are removed from the pauli label and are only in the coefficients.
142
183
  # That's because the operators we evolved have all been translated to a SparsePauliOp.
184
+ qubits = []
185
+ label = ""
143
186
  for i, pauli_i in enumerate(reversed(pauli.to_label())):
187
+ idx = 0 if wrap else i
144
188
  if pauli_i == "X":
145
- definition.rx(2 * time, i)
189
+ dest.rx(2 * time, idx)
190
+ qubits.append(i)
191
+ label += "X"
146
192
  elif pauli_i == "Y":
147
- definition.ry(2 * time, i)
193
+ dest.ry(2 * time, idx)
194
+ qubits.append(i)
195
+ label += "Y"
148
196
  elif pauli_i == "Z":
149
- definition.rz(2 * time, i)
197
+ dest.rz(2 * time, idx)
198
+ qubits.append(i)
199
+ label += "Z"
150
200
 
151
- return definition
201
+ if wrap:
202
+ gate = dest.to_gate(label=f"exp(it {label})")
203
+ qubits = [output.qubits[q] for q in qubits]
204
+ output.append(gate, qargs=qubits, copy=False)
152
205
 
153
206
 
154
- def _two_qubit_evolution(pauli, time, cx_structure):
207
+ def _two_qubit_evolution(output, pauli, time, cx_structure, wrap):
155
208
  # Get the Paulis and the qubits they act on.
156
209
  # Note that all phases are removed from the pauli label and are only in the coefficients.
157
210
  # That's because the operators we evolved have all been translated to a SparsePauliOp.
158
211
  labels_as_array = np.array(list(reversed(pauli.to_label())))
159
212
  qubits = np.where(labels_as_array != "I")[0]
213
+ indices = [0, 1] if wrap else qubits
160
214
  labels = np.array([labels_as_array[idx] for idx in qubits])
161
215
 
162
- definition = QuantumCircuit(pauli.num_qubits)
216
+ dest = QuantumCircuit(2) if wrap else output
163
217
 
164
218
  # go through all cases we have implemented in Qiskit
165
219
  if all(labels == "X"): # RXX
166
- definition.rxx(2 * time, qubits[0], qubits[1])
220
+ dest.rxx(2 * time, indices[0], indices[1])
167
221
  elif all(labels == "Y"): # RYY
168
- definition.ryy(2 * time, qubits[0], qubits[1])
222
+ dest.ryy(2 * time, indices[0], indices[1])
169
223
  elif all(labels == "Z"): # RZZ
170
- definition.rzz(2 * time, qubits[0], qubits[1])
224
+ dest.rzz(2 * time, indices[0], indices[1])
171
225
  elif labels[0] == "Z" and labels[1] == "X": # RZX
172
- definition.rzx(2 * time, qubits[0], qubits[1])
226
+ dest.rzx(2 * time, indices[0], indices[1])
173
227
  elif labels[0] == "X" and labels[1] == "Z": # RXZ
174
- definition.rzx(2 * time, qubits[1], qubits[0])
228
+ dest.rzx(2 * time, indices[1], indices[0])
175
229
  else: # all the others are not native in Qiskit, so use default the decomposition
176
- definition = _multi_qubit_evolution(pauli, time, cx_structure)
230
+ _multi_qubit_evolution(output, pauli, time, cx_structure, wrap)
231
+ return
177
232
 
178
- return definition
233
+ if wrap:
234
+ gate = dest.to_gate(label=f"exp(it {''.join(labels)})")
235
+ qubits = [output.qubits[q] for q in qubits]
236
+ output.append(gate, qargs=qubits, copy=False)
179
237
 
180
238
 
181
- def _multi_qubit_evolution(pauli, time, cx_structure):
239
+ def _multi_qubit_evolution(output, pauli, time, cx_structure, wrap):
182
240
  # get diagonalizing clifford
183
241
  cliff = diagonalizing_clifford(pauli)
184
242
 
@@ -198,14 +256,16 @@ def _multi_qubit_evolution(pauli, time, cx_structure):
198
256
  break
199
257
 
200
258
  # build the evolution as: diagonalization, reduction, 1q evolution, followed by inverses
201
- definition = QuantumCircuit(pauli.num_qubits)
202
- definition.compose(cliff, inplace=True)
203
- definition.compose(chain, inplace=True)
204
- definition.rz(2 * time, target)
205
- definition.compose(chain.inverse(), inplace=True)
206
- definition.compose(cliff.inverse(), inplace=True)
259
+ dest = QuantumCircuit(pauli.num_qubits) if wrap else output
260
+ dest.compose(cliff, inplace=True)
261
+ dest.compose(chain, inplace=True)
262
+ dest.rz(2 * time, target)
263
+ dest.compose(chain.inverse(), inplace=True)
264
+ dest.compose(cliff.inverse(), inplace=True)
207
265
 
208
- return definition
266
+ if wrap:
267
+ gate = dest.to_gate(label=f"exp(it {pauli.to_label()})")
268
+ output.append(gate, qargs=output.qubits, copy=False)
209
269
 
210
270
 
211
271
  def diagonalizing_clifford(pauli: Pauli) -> QuantumCircuit:
@@ -313,16 +373,12 @@ def cnot_fountain(pauli: Pauli) -> QuantumCircuit:
313
373
  return chain
314
374
 
315
375
 
316
- def _default_atomic_evolution(operator, time, cx_structure):
376
+ def _default_atomic_evolution(output, operator, time, cx_structure, wrap):
317
377
  if isinstance(operator, Pauli):
318
378
  # single Pauli operator: just exponentiate it
319
- evolution_circuit = evolve_pauli(operator, time, cx_structure)
379
+ evolve_pauli(output, operator, time, cx_structure, wrap)
320
380
  else:
321
381
  # sum of Pauli operators: exponentiate each term (this assumes they commute)
322
382
  pauli_list = [(Pauli(op), np.real(coeff)) for op, coeff in operator.to_list()]
323
- name = f"exp(it {[pauli.to_label() for pauli, _ in pauli_list]})"
324
- evolution_circuit = QuantumCircuit(operator.num_qubits, name=name)
325
383
  for pauli, coeff in pauli_list:
326
- evolution_circuit.compose(evolve_pauli(pauli, coeff * time, cx_structure), inplace=True)
327
-
328
- return evolution_circuit
384
+ evolve_pauli(output, pauli, coeff * time, cx_structure, wrap)