qiskit 1.3.0__cp39-abi3-win32.whl → 1.3.0b1__cp39-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 (361) hide show
  1. qiskit/VERSION.txt +1 -1
  2. qiskit/__init__.py +1 -20
  3. qiskit/_accelerate.pyd +0 -0
  4. qiskit/assembler/assemble_schedules.py +0 -2
  5. qiskit/circuit/__init__.py +1 -44
  6. qiskit/circuit/_standard_gates_commutations.py +0 -585
  7. qiskit/circuit/barrier.py +0 -2
  8. qiskit/circuit/controlflow/builder.py +3 -3
  9. qiskit/circuit/controlflow/if_else.py +5 -13
  10. qiskit/circuit/controlflow/while_loop.py +2 -10
  11. qiskit/circuit/delay.py +3 -20
  12. qiskit/circuit/equivalence.py +214 -13
  13. qiskit/circuit/gate.py +1 -3
  14. qiskit/circuit/instruction.py +11 -32
  15. qiskit/circuit/instructionset.py +0 -2
  16. qiskit/circuit/library/__init__.py +14 -110
  17. qiskit/circuit/library/arithmetic/__init__.py +2 -9
  18. qiskit/circuit/library/arithmetic/adders/__init__.py +0 -1
  19. qiskit/circuit/library/arithmetic/adders/adder.py +2 -154
  20. qiskit/circuit/library/arithmetic/adders/cdkm_ripple_carry_adder.py +56 -20
  21. qiskit/circuit/library/arithmetic/adders/draper_qft_adder.py +1 -14
  22. qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py +91 -21
  23. qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +1 -1
  24. qiskit/circuit/library/arithmetic/multipliers/__init__.py +0 -1
  25. qiskit/circuit/library/arithmetic/multipliers/hrs_cumulative_multiplier.py +1 -8
  26. qiskit/circuit/library/arithmetic/multipliers/multiplier.py +3 -94
  27. qiskit/circuit/library/arithmetic/multipliers/rg_qft_multiplier.py +1 -8
  28. qiskit/circuit/library/arithmetic/weighted_adder.py +1 -1
  29. qiskit/circuit/library/basis_change/qft.py +38 -20
  30. qiskit/circuit/library/blueprintcircuit.py +0 -64
  31. qiskit/circuit/library/boolean_logic/__init__.py +4 -4
  32. qiskit/circuit/library/boolean_logic/inner_product.py +4 -81
  33. qiskit/circuit/library/boolean_logic/quantum_and.py +4 -107
  34. qiskit/circuit/library/boolean_logic/quantum_or.py +3 -107
  35. qiskit/circuit/library/boolean_logic/quantum_xor.py +3 -97
  36. qiskit/circuit/library/data_preparation/__init__.py +3 -6
  37. qiskit/circuit/library/data_preparation/pauli_feature_map.py +29 -342
  38. qiskit/circuit/library/data_preparation/{_z_feature_map.py → z_feature_map.py} +34 -45
  39. qiskit/circuit/library/data_preparation/zz_feature_map.py +118 -0
  40. qiskit/circuit/library/fourier_checking.py +11 -72
  41. qiskit/circuit/library/generalized_gates/__init__.py +1 -1
  42. qiskit/circuit/library/generalized_gates/diagonal.py +51 -45
  43. qiskit/circuit/library/generalized_gates/gms.py +14 -67
  44. qiskit/circuit/library/generalized_gates/gr.py +4 -4
  45. qiskit/circuit/library/generalized_gates/isometry.py +2 -2
  46. qiskit/circuit/library/generalized_gates/linear_function.py +6 -12
  47. qiskit/circuit/library/generalized_gates/mcmt.py +107 -167
  48. qiskit/circuit/library/generalized_gates/permutation.py +6 -8
  49. qiskit/circuit/library/generalized_gates/rv.py +9 -8
  50. qiskit/circuit/library/graph_state.py +10 -93
  51. qiskit/circuit/library/grover_operator.py +2 -270
  52. qiskit/circuit/library/hidden_linear_function.py +20 -83
  53. qiskit/circuit/library/iqp.py +20 -99
  54. qiskit/circuit/library/n_local/__init__.py +7 -19
  55. qiskit/circuit/library/n_local/efficient_su2.py +5 -118
  56. qiskit/circuit/library/n_local/evolved_operator_ansatz.py +0 -259
  57. qiskit/circuit/library/n_local/excitation_preserving.py +6 -130
  58. qiskit/circuit/library/n_local/n_local.py +5 -406
  59. qiskit/circuit/library/n_local/pauli_two_design.py +4 -106
  60. qiskit/circuit/library/n_local/qaoa_ansatz.py +1 -80
  61. qiskit/circuit/library/n_local/real_amplitudes.py +7 -127
  62. qiskit/circuit/library/n_local/two_local.py +7 -14
  63. qiskit/circuit/library/overlap.py +26 -91
  64. qiskit/circuit/library/pauli_evolution.py +15 -17
  65. qiskit/circuit/library/phase_estimation.py +4 -80
  66. qiskit/circuit/library/quantum_volume.py +20 -72
  67. qiskit/circuit/library/standard_gates/__init__.py +1 -20
  68. qiskit/circuit/library/standard_gates/dcx.py +1 -2
  69. qiskit/circuit/library/standard_gates/ecr.py +2 -2
  70. qiskit/circuit/library/standard_gates/h.py +3 -4
  71. qiskit/circuit/library/standard_gates/i.py +1 -2
  72. qiskit/circuit/library/standard_gates/iswap.py +2 -2
  73. qiskit/circuit/library/standard_gates/p.py +12 -20
  74. qiskit/circuit/library/standard_gates/r.py +1 -1
  75. qiskit/circuit/library/standard_gates/rx.py +3 -4
  76. qiskit/circuit/library/standard_gates/rxx.py +2 -2
  77. qiskit/circuit/library/standard_gates/ry.py +3 -4
  78. qiskit/circuit/library/standard_gates/ryy.py +2 -2
  79. qiskit/circuit/library/standard_gates/rz.py +12 -13
  80. qiskit/circuit/library/standard_gates/rzx.py +6 -6
  81. qiskit/circuit/library/standard_gates/rzz.py +1 -1
  82. qiskit/circuit/library/standard_gates/s.py +4 -4
  83. qiskit/circuit/library/standard_gates/swap.py +3 -3
  84. qiskit/circuit/library/standard_gates/sx.py +3 -4
  85. qiskit/circuit/library/standard_gates/t.py +2 -2
  86. qiskit/circuit/library/standard_gates/u.py +3 -11
  87. qiskit/circuit/library/standard_gates/u1.py +15 -65
  88. qiskit/circuit/library/standard_gates/u2.py +1 -4
  89. qiskit/circuit/library/standard_gates/u3.py +3 -31
  90. qiskit/circuit/library/standard_gates/x.py +5 -7
  91. qiskit/circuit/library/standard_gates/xx_minus_yy.py +2 -2
  92. qiskit/circuit/library/standard_gates/xx_plus_yy.py +2 -2
  93. qiskit/circuit/library/standard_gates/y.py +3 -4
  94. qiskit/circuit/library/standard_gates/z.py +3 -3
  95. qiskit/circuit/library/templates/clifford/clifford_2_1.py +8 -9
  96. qiskit/circuit/library/templates/clifford/clifford_2_2.py +9 -10
  97. qiskit/circuit/library/templates/clifford/clifford_2_3.py +7 -9
  98. qiskit/circuit/library/templates/clifford/clifford_2_4.py +8 -9
  99. qiskit/circuit/library/templates/clifford/clifford_3_1.py +8 -9
  100. qiskit/circuit/library/templates/clifford/clifford_4_1.py +9 -10
  101. qiskit/circuit/library/templates/clifford/clifford_4_2.py +9 -10
  102. qiskit/circuit/library/templates/clifford/clifford_4_3.py +9 -10
  103. qiskit/circuit/library/templates/clifford/clifford_4_4.py +9 -10
  104. qiskit/circuit/library/templates/clifford/clifford_5_1.py +9 -10
  105. qiskit/circuit/library/templates/clifford/clifford_6_1.py +9 -10
  106. qiskit/circuit/library/templates/clifford/clifford_6_2.py +9 -10
  107. qiskit/circuit/library/templates/clifford/clifford_6_3.py +9 -10
  108. qiskit/circuit/library/templates/clifford/clifford_6_4.py +8 -9
  109. qiskit/circuit/library/templates/clifford/clifford_6_5.py +9 -10
  110. qiskit/circuit/library/templates/clifford/clifford_8_1.py +9 -10
  111. qiskit/circuit/library/templates/clifford/clifford_8_2.py +9 -10
  112. qiskit/circuit/library/templates/clifford/clifford_8_3.py +9 -10
  113. qiskit/circuit/library/templates/nct/template_nct_2a_1.py +7 -9
  114. qiskit/circuit/library/templates/nct/template_nct_2a_2.py +8 -10
  115. qiskit/circuit/library/templates/nct/template_nct_2a_3.py +10 -12
  116. qiskit/circuit/library/templates/nct/template_nct_4a_1.py +14 -16
  117. qiskit/circuit/library/templates/nct/template_nct_4a_2.py +12 -14
  118. qiskit/circuit/library/templates/nct/template_nct_4a_3.py +10 -12
  119. qiskit/circuit/library/templates/nct/template_nct_4b_1.py +12 -14
  120. qiskit/circuit/library/templates/nct/template_nct_4b_2.py +10 -12
  121. qiskit/circuit/library/templates/nct/template_nct_5a_1.py +10 -12
  122. qiskit/circuit/library/templates/nct/template_nct_5a_2.py +10 -12
  123. qiskit/circuit/library/templates/nct/template_nct_5a_3.py +10 -12
  124. qiskit/circuit/library/templates/nct/template_nct_5a_4.py +9 -11
  125. qiskit/circuit/library/templates/nct/template_nct_6a_1.py +9 -11
  126. qiskit/circuit/library/templates/nct/template_nct_6a_2.py +10 -12
  127. qiskit/circuit/library/templates/nct/template_nct_6a_3.py +10 -12
  128. qiskit/circuit/library/templates/nct/template_nct_6a_4.py +10 -12
  129. qiskit/circuit/library/templates/nct/template_nct_6b_1.py +10 -12
  130. qiskit/circuit/library/templates/nct/template_nct_6b_2.py +10 -12
  131. qiskit/circuit/library/templates/nct/template_nct_6c_1.py +10 -12
  132. qiskit/circuit/library/templates/nct/template_nct_7a_1.py +11 -13
  133. qiskit/circuit/library/templates/nct/template_nct_7b_1.py +11 -13
  134. qiskit/circuit/library/templates/nct/template_nct_7c_1.py +11 -13
  135. qiskit/circuit/library/templates/nct/template_nct_7d_1.py +11 -13
  136. qiskit/circuit/library/templates/nct/template_nct_7e_1.py +11 -13
  137. qiskit/circuit/library/templates/nct/template_nct_9a_1.py +11 -13
  138. qiskit/circuit/library/templates/nct/template_nct_9c_1.py +9 -11
  139. qiskit/circuit/library/templates/nct/template_nct_9c_10.py +10 -12
  140. qiskit/circuit/library/templates/nct/template_nct_9c_11.py +10 -12
  141. qiskit/circuit/library/templates/nct/template_nct_9c_12.py +10 -12
  142. qiskit/circuit/library/templates/nct/template_nct_9c_2.py +10 -12
  143. qiskit/circuit/library/templates/nct/template_nct_9c_3.py +10 -12
  144. qiskit/circuit/library/templates/nct/template_nct_9c_4.py +10 -12
  145. qiskit/circuit/library/templates/nct/template_nct_9c_5.py +10 -12
  146. qiskit/circuit/library/templates/nct/template_nct_9c_6.py +10 -12
  147. qiskit/circuit/library/templates/nct/template_nct_9c_7.py +10 -12
  148. qiskit/circuit/library/templates/nct/template_nct_9c_8.py +10 -12
  149. qiskit/circuit/library/templates/nct/template_nct_9c_9.py +10 -12
  150. qiskit/circuit/library/templates/nct/template_nct_9d_1.py +9 -11
  151. qiskit/circuit/library/templates/nct/template_nct_9d_10.py +10 -12
  152. qiskit/circuit/library/templates/nct/template_nct_9d_2.py +10 -12
  153. qiskit/circuit/library/templates/nct/template_nct_9d_3.py +10 -12
  154. qiskit/circuit/library/templates/nct/template_nct_9d_4.py +10 -12
  155. qiskit/circuit/library/templates/nct/template_nct_9d_5.py +10 -12
  156. qiskit/circuit/library/templates/nct/template_nct_9d_6.py +10 -12
  157. qiskit/circuit/library/templates/nct/template_nct_9d_7.py +10 -12
  158. qiskit/circuit/library/templates/nct/template_nct_9d_8.py +10 -12
  159. qiskit/circuit/library/templates/nct/template_nct_9d_9.py +10 -12
  160. qiskit/circuit/library/templates/rzx/rzx_cy.py +10 -11
  161. qiskit/circuit/library/templates/rzx/rzx_xz.py +15 -16
  162. qiskit/circuit/library/templates/rzx/rzx_yz.py +10 -12
  163. qiskit/circuit/library/templates/rzx/rzx_zz1.py +20 -22
  164. qiskit/circuit/library/templates/rzx/rzx_zz2.py +15 -16
  165. qiskit/circuit/library/templates/rzx/rzx_zz3.py +15 -17
  166. qiskit/circuit/parameter.py +0 -4
  167. qiskit/circuit/parameterexpression.py +34 -167
  168. qiskit/circuit/quantumcircuit.py +126 -162
  169. qiskit/circuit/singleton.py +0 -2
  170. qiskit/circuit/store.py +0 -2
  171. qiskit/compiler/assembler.py +4 -17
  172. qiskit/compiler/scheduler.py +0 -2
  173. qiskit/compiler/sequencer.py +0 -2
  174. qiskit/compiler/transpiler.py +26 -81
  175. qiskit/converters/circuit_to_dag.py +2 -2
  176. qiskit/converters/circuit_to_dagdependency.py +1 -1
  177. qiskit/converters/circuit_to_dagdependency_v2.py +1 -1
  178. qiskit/converters/circuit_to_instruction.py +1 -1
  179. qiskit/converters/dag_to_circuit.py +5 -7
  180. qiskit/converters/dag_to_dagdependency.py +1 -1
  181. qiskit/converters/dag_to_dagdependency_v2.py +1 -1
  182. qiskit/converters/dagdependency_to_circuit.py +1 -5
  183. qiskit/converters/dagdependency_to_dag.py +1 -6
  184. qiskit/dagcircuit/collect_blocks.py +3 -3
  185. qiskit/dagcircuit/dagdependency.py +5 -18
  186. qiskit/dagcircuit/dagdependency_v2.py +1 -1
  187. qiskit/dagcircuit/dagnode.py +2 -2
  188. qiskit/passmanager/__init__.py +2 -2
  189. qiskit/primitives/backend_estimator.py +2 -5
  190. qiskit/primitives/backend_sampler_v2.py +18 -61
  191. qiskit/primitives/base/base_estimator.py +2 -2
  192. qiskit/primitives/containers/data_bin.py +1 -9
  193. qiskit/primitives/statevector_sampler.py +1 -1
  194. qiskit/primitives/utils.py +1 -1
  195. qiskit/providers/__init__.py +3 -3
  196. qiskit/providers/backend.py +1 -12
  197. qiskit/providers/backend_compat.py +3 -23
  198. qiskit/providers/basic_provider/basic_simulator.py +2 -12
  199. qiskit/providers/fake_provider/fake_pulse_backend.py +1 -6
  200. qiskit/providers/fake_provider/generic_backend_v2.py +30 -46
  201. qiskit/providers/models/pulsedefaults.py +0 -2
  202. qiskit/pulse/builder.py +18 -59
  203. qiskit/pulse/calibration_entries.py +1 -4
  204. qiskit/pulse/channels.py +0 -2
  205. qiskit/pulse/exceptions.py +0 -2
  206. qiskit/pulse/instruction_schedule_map.py +6 -21
  207. qiskit/pulse/instructions/acquire.py +0 -2
  208. qiskit/pulse/instructions/delay.py +0 -2
  209. qiskit/pulse/instructions/directives.py +0 -8
  210. qiskit/pulse/instructions/frequency.py +0 -3
  211. qiskit/pulse/instructions/instruction.py +0 -2
  212. qiskit/pulse/instructions/phase.py +0 -3
  213. qiskit/pulse/instructions/play.py +0 -2
  214. qiskit/pulse/instructions/reference.py +0 -2
  215. qiskit/pulse/instructions/snapshot.py +0 -2
  216. qiskit/pulse/library/pulse.py +0 -2
  217. qiskit/pulse/library/symbolic_pulses.py +0 -28
  218. qiskit/pulse/library/waveform.py +0 -2
  219. qiskit/pulse/macros.py +1 -1
  220. qiskit/pulse/schedule.py +13 -12
  221. qiskit/pulse/transforms/alignments.py +3 -5
  222. qiskit/pulse/transforms/dag.py +0 -7
  223. qiskit/qasm2/export.py +3 -5
  224. qiskit/qasm2/parse.py +2 -46
  225. qiskit/qasm3/__init__.py +0 -1
  226. qiskit/qasm3/ast.py +15 -123
  227. qiskit/qasm3/exporter.py +77 -103
  228. qiskit/qobj/converters/pulse_instruction.py +4 -6
  229. qiskit/qpy/__init__.py +0 -181
  230. qiskit/qpy/binary_io/circuits.py +5 -20
  231. qiskit/qpy/binary_io/schedules.py +4 -3
  232. qiskit/qpy/binary_io/value.py +13 -310
  233. qiskit/qpy/common.py +2 -46
  234. qiskit/qpy/formats.py +0 -7
  235. qiskit/qpy/interface.py +4 -40
  236. qiskit/quantum_info/__init__.py +0 -4
  237. qiskit/quantum_info/operators/channel/transformations.py +21 -28
  238. qiskit/quantum_info/operators/dihedral/dihedral.py +1 -1
  239. qiskit/quantum_info/operators/operator.py +8 -54
  240. qiskit/quantum_info/operators/symplectic/base_pauli.py +19 -11
  241. qiskit/quantum_info/operators/symplectic/clifford.py +1 -1
  242. qiskit/quantum_info/operators/symplectic/clifford_circuits.py +1 -1
  243. qiskit/quantum_info/operators/symplectic/pauli.py +0 -2
  244. qiskit/quantum_info/operators/symplectic/pauli_list.py +4 -4
  245. qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +2 -23
  246. qiskit/quantum_info/states/densitymatrix.py +5 -5
  247. qiskit/quantum_info/states/stabilizerstate.py +1 -1
  248. qiskit/quantum_info/states/statevector.py +6 -6
  249. qiskit/result/mitigation/base_readout_mitigator.py +1 -1
  250. qiskit/result/mitigation/correlated_readout_mitigator.py +1 -9
  251. qiskit/result/mitigation/local_readout_mitigator.py +1 -9
  252. qiskit/result/mitigation/utils.py +0 -57
  253. qiskit/scheduler/config.py +0 -2
  254. qiskit/scheduler/methods/basic.py +0 -3
  255. qiskit/scheduler/schedule_circuit.py +0 -2
  256. qiskit/scheduler/sequence.py +0 -2
  257. qiskit/synthesis/__init__.py +0 -25
  258. qiskit/synthesis/clifford/clifford_decompose_bm.py +2 -1
  259. qiskit/synthesis/clifford/clifford_decompose_greedy.py +2 -3
  260. qiskit/synthesis/clifford/clifford_decompose_layers.py +1 -2
  261. qiskit/synthesis/evolution/__init__.py +0 -1
  262. qiskit/synthesis/evolution/lie_trotter.py +42 -16
  263. qiskit/synthesis/evolution/product_formula.py +238 -165
  264. qiskit/synthesis/evolution/qdrift.py +29 -36
  265. qiskit/synthesis/evolution/suzuki_trotter.py +27 -87
  266. qiskit/synthesis/multi_controlled/__init__.py +0 -1
  267. qiskit/synthesis/qft/qft_decompose_full.py +1 -19
  268. qiskit/synthesis/qft/qft_decompose_lnn.py +1 -2
  269. qiskit/synthesis/stabilizer/stabilizer_decompose.py +1 -2
  270. qiskit/synthesis/two_qubit/two_qubit_decompose.py +63 -4
  271. qiskit/synthesis/two_qubit/weyl.py +97 -0
  272. qiskit/synthesis/unitary/qsd.py +5 -5
  273. qiskit/transpiler/__init__.py +14 -21
  274. qiskit/transpiler/basepasses.py +1 -1
  275. qiskit/transpiler/passes/__init__.py +0 -2
  276. qiskit/transpiler/passes/basis/basis_translator.py +565 -9
  277. qiskit/transpiler/passes/basis/decompose.py +12 -45
  278. qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
  279. qiskit/transpiler/passes/basis/unroll_custom_definitions.py +1 -1
  280. qiskit/transpiler/passes/calibration/pulse_gate.py +2 -4
  281. qiskit/transpiler/passes/calibration/rx_builder.py +7 -11
  282. qiskit/transpiler/passes/calibration/rzx_builder.py +30 -46
  283. qiskit/transpiler/passes/layout/disjoint_utils.py +13 -15
  284. qiskit/transpiler/passes/layout/sabre_layout.py +2 -7
  285. qiskit/transpiler/passes/layout/sabre_pre_layout.py +0 -5
  286. qiskit/transpiler/passes/optimization/__init__.py +0 -1
  287. qiskit/transpiler/passes/optimization/collect_cliffords.py +3 -19
  288. qiskit/transpiler/passes/optimization/collect_linear_functions.py +1 -1
  289. qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +2 -2
  290. qiskit/transpiler/passes/optimization/commutative_inverse_cancellation.py +1 -1
  291. qiskit/transpiler/passes/optimization/consolidate_blocks.py +131 -48
  292. qiskit/transpiler/passes/optimization/echo_rzx_weyl_decomposition.py +2 -4
  293. qiskit/transpiler/passes/optimization/elide_permutations.py +32 -9
  294. qiskit/transpiler/passes/optimization/inverse_cancellation.py +0 -2
  295. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +11 -5
  296. qiskit/transpiler/passes/optimization/optimize_1q_gates.py +1 -1
  297. qiskit/transpiler/passes/optimization/optimize_swap_before_measure.py +1 -1
  298. qiskit/transpiler/passes/optimization/template_matching/backward_match.py +5 -5
  299. qiskit/transpiler/passes/optimization/template_matching/forward_match.py +4 -4
  300. qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +2 -2
  301. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +1 -1
  302. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +1 -1
  303. qiskit/transpiler/passes/routing/sabre_swap.py +3 -7
  304. qiskit/transpiler/passes/routing/star_prerouting.py +2 -2
  305. qiskit/transpiler/passes/scheduling/alap.py +1 -1
  306. qiskit/transpiler/passes/scheduling/alignments/align_measures.py +2 -2
  307. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
  308. qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +0 -2
  309. qiskit/transpiler/passes/scheduling/alignments/reschedule.py +2 -2
  310. qiskit/transpiler/passes/scheduling/asap.py +1 -1
  311. qiskit/transpiler/passes/scheduling/base_scheduler.py +12 -14
  312. qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +4 -9
  313. qiskit/transpiler/passes/scheduling/padding/base_padding.py +1 -1
  314. qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +5 -16
  315. qiskit/transpiler/passes/scheduling/padding/pad_delay.py +1 -4
  316. qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +2 -6
  317. qiskit/transpiler/passes/scheduling/time_unit_conversion.py +4 -9
  318. qiskit/transpiler/passes/synthesis/high_level_synthesis.py +99 -262
  319. qiskit/transpiler/passes/synthesis/hls_plugins.py +7 -638
  320. qiskit/transpiler/passes/synthesis/qubit_tracker.py +132 -0
  321. qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +3 -3
  322. qiskit/transpiler/passes/synthesis/unitary_synthesis.py +34 -55
  323. qiskit/transpiler/passes/utils/barrier_before_final_measurements.py +56 -2
  324. qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +0 -5
  325. qiskit/transpiler/passes/utils/gate_direction.py +275 -12
  326. qiskit/transpiler/passes/utils/gates_basis.py +30 -7
  327. qiskit/transpiler/passes/utils/merge_adjacent_barriers.py +1 -2
  328. qiskit/transpiler/passmanager_config.py +4 -22
  329. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +14 -40
  330. qiskit/transpiler/preset_passmanagers/common.py +3 -5
  331. qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +42 -125
  332. qiskit/transpiler/preset_passmanagers/plugin.py +1 -1
  333. qiskit/transpiler/target.py +16 -74
  334. qiskit/visualization/circuit/_utils.py +2 -2
  335. qiskit/visualization/circuit/circuit_visualization.py +2 -3
  336. qiskit/visualization/circuit/matplotlib.py +1 -1
  337. qiskit/visualization/dag_visualization.py +1 -1
  338. qiskit/visualization/pass_manager_visualization.py +14 -3
  339. qiskit/visualization/pulse_v2/interface.py +1 -3
  340. qiskit/visualization/timeline/core.py +2 -25
  341. qiskit/visualization/timeline/interface.py +0 -12
  342. {qiskit-1.3.0.dist-info → qiskit-1.3.0b1.dist-info}/METADATA +19 -20
  343. {qiskit-1.3.0.dist-info → qiskit-1.3.0b1.dist-info}/RECORD +347 -358
  344. {qiskit-1.3.0.dist-info → qiskit-1.3.0b1.dist-info}/WHEEL +1 -1
  345. {qiskit-1.3.0.dist-info → qiskit-1.3.0b1.dist-info}/entry_points.txt +0 -19
  346. qiskit/circuit/library/data_preparation/_zz_feature_map.py +0 -150
  347. qiskit/circuit/twirling.py +0 -145
  348. qiskit/synthesis/arithmetic/__init__.py +0 -16
  349. qiskit/synthesis/arithmetic/adders/__init__.py +0 -17
  350. qiskit/synthesis/arithmetic/adders/cdkm_ripple_carry_adder.py +0 -154
  351. qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +0 -103
  352. qiskit/synthesis/arithmetic/adders/vbe_ripple_carry_adder.py +0 -161
  353. qiskit/synthesis/arithmetic/multipliers/__init__.py +0 -16
  354. qiskit/synthesis/arithmetic/multipliers/hrs_cumulative_multiplier.py +0 -102
  355. qiskit/synthesis/arithmetic/multipliers/rg_qft_multiplier.py +0 -99
  356. qiskit/synthesis/evolution/pauli_network.py +0 -80
  357. qiskit/synthesis/multi_controlled/mcmt_vchain.py +0 -52
  358. qiskit/transpiler/passes/optimization/remove_identity_equiv.py +0 -69
  359. qiskit/utils/deprecate_pulse.py +0 -119
  360. {qiskit-1.3.0.dist-info → qiskit-1.3.0b1.dist-info}/LICENSE.txt +0 -0
  361. {qiskit-1.3.0.dist-info → qiskit-1.3.0b1.dist-info}/top_level.txt +0 -0
@@ -125,7 +125,6 @@ Two-Qubit Synthesis
125
125
  Multi Controlled Synthesis
126
126
  ==========================
127
127
 
128
- .. autofunction:: synth_mcmt_vchain
129
128
  .. autofunction:: synth_mcx_n_dirty_i15
130
129
  .. autofunction:: synth_mcx_n_clean_m15
131
130
  .. autofunction:: synth_mcx_1_clean_b95
@@ -134,22 +133,6 @@ Multi Controlled Synthesis
134
133
  .. autofunction:: synth_c3x
135
134
  .. autofunction:: synth_c4x
136
135
 
137
- Binary Arithmetic Synthesis
138
- ===========================
139
-
140
- Adders
141
- ------
142
-
143
- .. autofunction:: adder_qft_d00
144
- .. autofunction:: adder_ripple_c04
145
- .. autofunction:: adder_ripple_v95
146
-
147
- Multipliers
148
- -----------
149
-
150
- .. autofunction:: multiplier_cumulative_h18
151
- .. autofunction:: multiplier_qft_r17
152
-
153
136
  """
154
137
 
155
138
  from .evolution import (
@@ -202,7 +185,6 @@ from .two_qubit.two_qubit_decompose import (
202
185
  TwoQubitWeylDecomposition,
203
186
  )
204
187
  from .multi_controlled import (
205
- synth_mcmt_vchain,
206
188
  synth_mcx_n_dirty_i15,
207
189
  synth_mcx_n_clean_m15,
208
190
  synth_mcx_1_clean_b95,
@@ -211,10 +193,3 @@ from .multi_controlled import (
211
193
  synth_c3x,
212
194
  synth_c4x,
213
195
  )
214
- from .arithmetic import (
215
- adder_qft_d00,
216
- adder_ripple_c04,
217
- adder_ripple_v95,
218
- multiplier_cumulative_h18,
219
- multiplier_qft_r17,
220
- )
@@ -41,6 +41,7 @@ def synth_clifford_bm(clifford: Clifford) -> QuantumCircuit:
41
41
  `arXiv:2003.09412 [quant-ph] <https://arxiv.org/abs/2003.09412>`_
42
42
  """
43
43
  circuit = QuantumCircuit._from_circuit_data(
44
- synth_clifford_bm_inner(clifford.tableau.astype(bool)), add_regs=True, name=str(clifford)
44
+ synth_clifford_bm_inner(clifford.tableau.astype(bool)), add_regs=True
45
45
  )
46
+ circuit.name = str(clifford)
46
47
  return circuit
@@ -51,8 +51,7 @@ def synth_clifford_greedy(clifford: Clifford) -> QuantumCircuit:
51
51
  `arXiv:2105.02291 [quant-ph] <https://arxiv.org/abs/2105.02291>`_
52
52
  """
53
53
  circuit = QuantumCircuit._from_circuit_data(
54
- synth_clifford_greedy_inner(clifford.tableau.astype(bool)),
55
- add_regs=True,
56
- name=str(clifford),
54
+ synth_clifford_greedy_inner(clifford.tableau.astype(bool)), add_regs=True
57
55
  )
56
+ circuit.name = str(clifford)
58
57
  return circuit
@@ -77,8 +77,7 @@ def synth_clifford_layers(
77
77
 
78
78
  For example, a 5-qubit Clifford circuit is decomposed into the following layers:
79
79
 
80
- .. code-block:: text
81
-
80
+ .. parsed-literal::
82
81
  ┌─────┐┌─────┐┌────────┐┌─────┐┌─────┐┌─────┐┌─────┐┌────────┐
83
82
  q_0: ┤0 ├┤0 ├┤0 ├┤0 ├┤0 ├┤0 ├┤0 ├┤0 ├
84
83
  │ ││ ││ ││ ││ ││ ││ ││ │
@@ -18,4 +18,3 @@ from .product_formula import ProductFormula
18
18
  from .lie_trotter import LieTrotter
19
19
  from .suzuki_trotter import SuzukiTrotter
20
20
  from .qdrift import QDrift
21
- from .pauli_network import synth_pauli_network_rustiq
@@ -14,15 +14,18 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
+ import inspect
17
18
  from collections.abc import Callable
18
19
  from typing import Any
20
+ import numpy as np
19
21
  from qiskit.circuit.quantumcircuit import QuantumCircuit
20
22
  from qiskit.quantum_info.operators import SparsePauliOp, Pauli
23
+ from qiskit.utils.deprecation import deprecate_arg
21
24
 
22
- from .suzuki_trotter import SuzukiTrotter
25
+ from .product_formula import ProductFormula
23
26
 
24
27
 
25
- class LieTrotter(SuzukiTrotter):
28
+ class LieTrotter(ProductFormula):
26
29
  r"""The Lie-Trotter product formula.
27
30
 
28
31
  The Lie-Trotter formula approximates the exponential of two non-commuting operators
@@ -37,7 +40,7 @@ class LieTrotter(SuzukiTrotter):
37
40
 
38
41
  .. math::
39
42
 
40
- e^{-it(XI + ZZ)} = e^{-it XI}e^{-it ZZ} + \mathcal{O}(t^2).
43
+ e^{-it(XX + ZZ)} = e^{-it XX}e^{-it ZZ} + \mathcal{O}(t^2).
41
44
 
42
45
  References:
43
46
 
@@ -49,6 +52,21 @@ class LieTrotter(SuzukiTrotter):
49
52
  `arXiv:math-ph/0506007 <https://arxiv.org/pdf/math-ph/0506007.pdf>`_
50
53
  """
51
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
+ )
52
70
  def __init__(
53
71
  self,
54
72
  reps: int = 1,
@@ -60,7 +78,6 @@ class LieTrotter(SuzukiTrotter):
60
78
  | None
61
79
  ) = None,
62
80
  wrap: bool = False,
63
- preserve_order: bool = True,
64
81
  ) -> None:
65
82
  """
66
83
  Args:
@@ -80,19 +97,28 @@ class LieTrotter(SuzukiTrotter):
80
97
  built.
81
98
  wrap: Whether to wrap the atomic evolutions into custom gate objects. This only takes
82
99
  effect when ``atomic_evolution is None``.
83
- preserve_order: If ``False``, allows reordering the terms of the operator to
84
- potentially yield a shallower evolution circuit. Not relevant
85
- when synthesizing operator with a single term.
86
100
  """
87
- super().__init__(
88
- 1,
89
- reps,
90
- insert_barriers,
91
- cx_structure,
92
- atomic_evolution,
93
- wrap,
94
- preserve_order=preserve_order,
95
- )
101
+ super().__init__(1, reps, insert_barriers, cx_structure, atomic_evolution, wrap)
102
+
103
+ def synthesize(self, evolution):
104
+ # get operators and time to evolve
105
+ operators = evolution.operator
106
+ time = evolution.time
107
+
108
+ # construct the evolution circuit
109
+ single_rep = QuantumCircuit(operators[0].num_qubits)
110
+
111
+ if not isinstance(operators, list):
112
+ pauli_list = [(Pauli(op), np.real(coeff)) for op, coeff in operators.to_list()]
113
+ else:
114
+ pauli_list = [(op, 1) for op in operators]
115
+
116
+ for i, (op, coeff) in enumerate(pauli_list):
117
+ self.atomic_evolution(single_rep, op, coeff * time / self.reps)
118
+ if self.insert_barriers and i != len(pauli_list) - 1:
119
+ single_rep.barrier()
120
+
121
+ return single_rep.repeat(self.reps, insert_barriers=self.insert_barriers).decompose()
96
122
 
97
123
  @property
98
124
  def settings(self) -> dict[str, Any]:
@@ -15,26 +15,17 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import inspect
18
- import itertools
19
- from collections.abc import Callable, Sequence
20
- from collections import defaultdict
21
- from itertools import combinations
22
- import typing
18
+ from collections.abc import Callable
19
+ from typing import Any
20
+ from functools import partial
23
21
  import numpy as np
24
- import rustworkx as rx
25
22
  from qiskit.circuit.parameterexpression import ParameterExpression
26
- from qiskit.circuit.quantumcircuit import QuantumCircuit, ParameterValueType
23
+ from qiskit.circuit.quantumcircuit import QuantumCircuit
27
24
  from qiskit.quantum_info import SparsePauliOp, Pauli
28
25
  from qiskit.utils.deprecation import deprecate_arg
29
- from qiskit._accelerate.circuit_library import pauli_evolution
30
26
 
31
27
  from .evolution_synthesis import EvolutionSynthesis
32
28
 
33
- if typing.TYPE_CHECKING:
34
- from qiskit.circuit.library import PauliEvolutionGate
35
-
36
- SparsePauliLabel = typing.Tuple[str, list[int], ParameterValueType]
37
-
38
29
 
39
30
  class ProductFormula(EvolutionSynthesis):
40
31
  """Product formula base class for the decomposition of non-commuting operator exponentials.
@@ -69,7 +60,6 @@ class ProductFormula(EvolutionSynthesis):
69
60
  | None
70
61
  ) = None,
71
62
  wrap: bool = False,
72
- preserve_order: bool = True,
73
63
  ) -> None:
74
64
  """
75
65
  Args:
@@ -88,31 +78,24 @@ class ProductFormula(EvolutionSynthesis):
88
78
  Alternatively, the function can also take Pauli operator and evolution time as
89
79
  inputs and returns the circuit that will be appended to the overall circuit being
90
80
  built.
91
- wrap: Whether to wrap the atomic evolutions into custom gate objects. Note that setting
92
- this to ``True`` is slower than ``False``. This only takes effect when
93
- ``atomic_evolution is None``.
94
- preserve_order: If ``False``, allows reordering the terms of the operator to
95
- potentially yield a shallower evolution circuit. Not relevant
96
- when synthesizing operator with a single term.
81
+ wrap: Whether to wrap the atomic evolutions into custom gate objects. This only takes
82
+ effect when ``atomic_evolution is None``.
97
83
  """
98
84
  super().__init__()
99
85
  self.order = order
100
86
  self.reps = reps
101
87
  self.insert_barriers = insert_barriers
102
- self.preserve_order = preserve_order
103
88
 
104
89
  # user-provided atomic evolution, stored for serialization
105
90
  self._atomic_evolution = atomic_evolution
106
-
107
- if cx_structure not in ["chain", "fountain"]:
108
- raise ValueError(f"Unsupported CX structure: {cx_structure}")
109
-
110
91
  self._cx_structure = cx_structure
111
92
  self._wrap = wrap
112
93
 
113
94
  # if atomic evolution is not provided, set a default
114
95
  if atomic_evolution is None:
115
- self.atomic_evolution = None
96
+ self.atomic_evolution = partial(
97
+ _default_atomic_evolution, cx_structure=cx_structure, wrap=wrap
98
+ )
116
99
 
117
100
  elif len(inspect.signature(atomic_evolution).parameters) == 2:
118
101
 
@@ -125,50 +108,8 @@ class ProductFormula(EvolutionSynthesis):
125
108
  else:
126
109
  self.atomic_evolution = atomic_evolution
127
110
 
128
- def expand(
129
- self, evolution: PauliEvolutionGate
130
- ) -> list[tuple[str, tuple[int], ParameterValueType]]:
131
- """Apply the product formula to expand the Hamiltonian in the evolution gate.
132
-
133
- Args:
134
- evolution: The :class:`.PauliEvolutionGate`, whose Hamiltonian we expand.
135
-
136
- Returns:
137
- A list of Pauli rotations in a sparse format, where each element is
138
- ``(paulistring, qubits, coefficient)``. For example, the Lie-Trotter expansion
139
- of ``H = XI + ZZ`` would return ``[("X", [1], 1), ("ZZ", [0, 1], 1)]``.
140
- """
141
- raise NotImplementedError(
142
- f"The method ``expand`` is not implemented for {self.__class__}. Implement it to "
143
- f"automatically enable the call to {self.__class__}.synthesize."
144
- )
145
-
146
- def synthesize(self, evolution: PauliEvolutionGate) -> QuantumCircuit:
147
- """Synthesize a :class:`.PauliEvolutionGate`.
148
-
149
- Args:
150
- evolution: The evolution gate to synthesize.
151
-
152
- Returns:
153
- QuantumCircuit: A circuit implementing the evolution.
154
- """
155
- pauli_rotations = self.expand(evolution)
156
- num_qubits = evolution.num_qubits
157
-
158
- if self._wrap or self._atomic_evolution is not None:
159
- # this is the slow path, where each Pauli evolution is constructed in Rust
160
- # separately and then wrapped into a gate object
161
- circuit = self._custom_evolution(num_qubits, pauli_rotations)
162
- else:
163
- # this is the fast path, where the whole evolution is constructed Rust-side
164
- cx_fountain = self._cx_structure == "fountain"
165
- data = pauli_evolution(num_qubits, pauli_rotations, self.insert_barriers, cx_fountain)
166
- circuit = QuantumCircuit._from_circuit_data(data, add_regs=True)
167
-
168
- return circuit
169
-
170
111
  @property
171
- def settings(self) -> dict[str, typing.Any]:
112
+ def settings(self) -> dict[str, Any]:
172
113
  """Return the settings in a dictionary, which can be used to reconstruct the object.
173
114
 
174
115
  Returns:
@@ -188,124 +129,256 @@ class ProductFormula(EvolutionSynthesis):
188
129
  "insert_barriers": self.insert_barriers,
189
130
  "cx_structure": self._cx_structure,
190
131
  "wrap": self._wrap,
191
- "preserve_order": self.preserve_order,
192
132
  }
193
133
 
194
- def _normalize_coefficients(
195
- self, paulis: list[str | list[int], float | complex | ParameterExpression]
196
- ) -> list[str | list[int] | ParameterValueType]:
197
- """Ensure the coefficients are real (or parameter expressions)."""
198
- return [[(op, qubits, real_or_fail(coeff)) for op, qubits, coeff in ops] for ops in paulis]
199
134
 
200
- def _custom_evolution(self, num_qubits, pauli_rotations):
201
- """Implement the evolution for the non-standard path.
135
+ def evolve_pauli(
136
+ output: QuantumCircuit,
137
+ pauli: Pauli,
138
+ time: float | ParameterExpression = 1.0,
139
+ cx_structure: str = "chain",
140
+ wrap: bool = False,
141
+ label: str | None = None,
142
+ ) -> None:
143
+ r"""Construct a circuit implementing the time evolution of a single Pauli string.
202
144
 
203
- This is either because a user-defined atomic evolution is given, or because the evolution
204
- of individual Paulis needs to be wrapped in gates.
205
- """
206
- circuit = QuantumCircuit(num_qubits)
207
- cx_fountain = self._cx_structure == "fountain"
145
+ For a Pauli string :math:`P = \{I, X, Y, Z\}^{\otimes n}` on :math:`n` qubits and an
146
+ evolution time :math:`t`, the returned circuit implements the unitary operation
147
+
148
+ .. math::
149
+
150
+ U(t) = e^{-itP}.
151
+
152
+ Since only a single Pauli string is evolved the circuit decomposition is exact.
153
+
154
+ Args:
155
+ output: The circuit object to which to append the evolved Pauli.
156
+ pauli: The Pauli to evolve.
157
+ time: The evolution time.
158
+ cx_structure: Determine the structure of CX gates, can be either ``"chain"`` for
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.
161
+ label: A label for the gate.
162
+ """
163
+ num_non_identity = len([label for label in pauli.to_label() if label != "I"])
164
+
165
+ # first check, if the Pauli is only the identity, in which case the evolution only
166
+ # adds a global phase
167
+ if num_non_identity == 0:
168
+ output.global_phase -= time
169
+ # if we evolve on a single qubit, if yes use the corresponding qubit rotation
170
+ elif num_non_identity == 1:
171
+ _single_qubit_evolution(output, pauli, time, wrap)
172
+ # same for two qubits, use Qiskit's native rotations
173
+ elif num_non_identity == 2:
174
+ _two_qubit_evolution(output, pauli, time, cx_structure, wrap)
175
+ # otherwise do basis transformation and CX chains
176
+ else:
177
+ _multi_qubit_evolution(output, pauli, time, cx_structure, wrap)
178
+
179
+
180
+ def _single_qubit_evolution(output, pauli, time, wrap):
181
+ dest = QuantumCircuit(1) if wrap else output
182
+ # Note that all phases are removed from the pauli label and are only in the coefficients.
183
+ # That's because the operators we evolved have all been translated to a SparsePauliOp.
184
+ qubits = []
185
+ label = ""
186
+ for i, pauli_i in enumerate(reversed(pauli.to_label())):
187
+ idx = 0 if wrap else i
188
+ if pauli_i == "X":
189
+ dest.rx(2 * time, idx)
190
+ qubits.append(i)
191
+ label += "X"
192
+ elif pauli_i == "Y":
193
+ dest.ry(2 * time, idx)
194
+ qubits.append(i)
195
+ label += "Y"
196
+ elif pauli_i == "Z":
197
+ dest.rz(2 * time, idx)
198
+ qubits.append(i)
199
+ label += "Z"
200
+
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)
205
+
206
+
207
+ def _two_qubit_evolution(output, pauli, time, cx_structure, wrap):
208
+ # Get the Paulis and the qubits they act on.
209
+ # Note that all phases are removed from the pauli label and are only in the coefficients.
210
+ # That's because the operators we evolved have all been translated to a SparsePauliOp.
211
+ labels_as_array = np.array(list(reversed(pauli.to_label())))
212
+ qubits = np.where(labels_as_array != "I")[0]
213
+ indices = [0, 1] if wrap else qubits
214
+ labels = np.array([labels_as_array[idx] for idx in qubits])
215
+
216
+ dest = QuantumCircuit(2) if wrap else output
217
+
218
+ # go through all cases we have implemented in Qiskit
219
+ if all(labels == "X"): # RXX
220
+ dest.rxx(2 * time, indices[0], indices[1])
221
+ elif all(labels == "Y"): # RYY
222
+ dest.ryy(2 * time, indices[0], indices[1])
223
+ elif all(labels == "Z"): # RZZ
224
+ dest.rzz(2 * time, indices[0], indices[1])
225
+ elif labels[0] == "Z" and labels[1] == "X": # RZX
226
+ dest.rzx(2 * time, indices[0], indices[1])
227
+ elif labels[0] == "X" and labels[1] == "Z": # RXZ
228
+ dest.rzx(2 * time, indices[1], indices[0])
229
+ else: # all the others are not native in Qiskit, so use default the decomposition
230
+ _multi_qubit_evolution(output, pauli, time, cx_structure, wrap)
231
+ return
232
+
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)
237
+
238
+
239
+ def _multi_qubit_evolution(output, pauli, time, cx_structure, wrap):
240
+ # get diagonalizing clifford
241
+ cliff = diagonalizing_clifford(pauli)
242
+
243
+ # get CX chain to reduce the evolution to the top qubit
244
+ if cx_structure == "chain":
245
+ chain = cnot_chain(pauli)
246
+ else:
247
+ chain = cnot_fountain(pauli)
248
+
249
+ # determine qubit to do the rotation on
250
+ target = None
251
+ # Note that all phases are removed from the pauli label and are only in the coefficients.
252
+ # That's because the operators we evolved have all been translated to a SparsePauliOp.
253
+ for i, pauli_i in enumerate(reversed(pauli.to_label())):
254
+ if pauli_i != "I":
255
+ target = i
256
+ break
257
+
258
+ # build the evolution as: diagonalization, reduction, 1q evolution, followed by inverses
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)
265
+
266
+ if wrap:
267
+ gate = dest.to_gate(label=f"exp(it {pauli.to_label()})")
268
+ output.append(gate, qargs=output.qubits, copy=False)
269
+
270
+
271
+ def diagonalizing_clifford(pauli: Pauli) -> QuantumCircuit:
272
+ """Get the clifford circuit to diagonalize the Pauli operator.
208
273
 
209
- num_paulis = len(pauli_rotations)
210
- for i, pauli_rotation in enumerate(pauli_rotations):
211
- if self._atomic_evolution is not None:
212
- # use the user-provided evolution with a global operator
213
- operator = SparsePauliOp.from_sparse_list([pauli_rotation], num_qubits)
214
- self.atomic_evolution(circuit, operator, time=1) # time is inside the Pauli coeff
274
+ Args:
275
+ pauli: The Pauli to diagonalize.
215
276
 
216
- else: # this means self._wrap is True
217
- # we create a local sparse Pauli representation such that the operator
218
- # does not span over all qubits of the circuit
219
- pauli_string, qubits, coeff = pauli_rotation
220
- local_pauli = (pauli_string, list(range(len(qubits))), coeff)
277
+ Returns:
278
+ A circuit to diagonalize.
279
+ """
280
+ cliff = QuantumCircuit(pauli.num_qubits)
281
+ for i, pauli_i in enumerate(reversed(pauli.to_label())):
282
+ if pauli_i == "Y":
283
+ cliff.sdg(i)
284
+ if pauli_i in ["X", "Y"]:
285
+ cliff.h(i)
221
286
 
222
- # build the circuit Rust-side
223
- data = pauli_evolution(
224
- len(qubits),
225
- [local_pauli],
226
- False,
227
- cx_fountain,
228
- )
229
- evo = QuantumCircuit._from_circuit_data(data)
287
+ return cliff
230
288
 
231
- # and append it to the circuit with the correct label
232
- gate = evo.to_gate(label=f"exp(it {pauli_string})")
233
- circuit.append(gate, qubits)
234
289
 
235
- if self.insert_barriers and i < num_paulis - 1:
236
- circuit.barrier()
290
+ def cnot_chain(pauli: Pauli) -> QuantumCircuit:
291
+ """CX chain.
237
292
 
238
- return circuit
293
+ For example, for the Pauli with the label 'XYZIX'.
239
294
 
295
+ .. parsed-literal::
240
296
 
241
- def real_or_fail(value, tol=100):
242
- """Return real if close, otherwise fail. Unbound parameters are left unchanged.
297
+ ┌───┐
298
+ q_0: ──────────┤ X
299
+ └─┬─┘
300
+ q_1: ────────────┼──
301
+ ┌───┐ │
302
+ q_2: ─────┤ X ├──■──
303
+ ┌───┐└─┬─┘
304
+ q_3: ┤ X ├──■───────
305
+ └─┬─┘
306
+ q_4: ──■────────────
307
+
308
+ Args:
309
+ pauli: The Pauli for which to construct the CX chain.
243
310
 
244
- Based on NumPy's ``real_if_close``, i.e. ``tol`` is in terms of machine precision for float.
311
+ Returns:
312
+ A circuit implementing the CX chain.
245
313
  """
246
- if isinstance(value, ParameterExpression):
247
- return value
248
314
 
249
- abstol = tol * np.finfo(float).eps
250
- if abs(np.imag(value)) < abstol:
251
- return np.real(value)
315
+ chain = QuantumCircuit(pauli.num_qubits)
316
+ control, target = None, None
252
317
 
253
- raise ValueError(f"Encountered complex value {value}, but expected real.")
318
+ # iterate over the Pauli's and add CNOTs
319
+ for i, pauli_i in enumerate(pauli.to_label()):
320
+ i = pauli.num_qubits - i - 1
321
+ if pauli_i != "I":
322
+ if control is None:
323
+ control = i
324
+ else:
325
+ target = i
254
326
 
327
+ if control is not None and target is not None:
328
+ chain.cx(control, target)
329
+ control = i
330
+ target = None
255
331
 
256
- def reorder_paulis(
257
- paulis: Sequence[SparsePauliLabel],
258
- strategy: rx.ColoringStrategy = rx.ColoringStrategy.Saturation,
259
- ) -> list[SparsePauliLabel]:
260
- r"""
261
- Creates an equivalent operator by reordering terms in order to yield a
262
- shallower circuit after evolution synthesis. The original operator remains
263
- unchanged.
332
+ return chain
264
333
 
265
- This method works in three steps. First, a graph is constructed, where the
266
- nodes are the terms of the operator and where two nodes are connected if
267
- their terms act on the same qubit (for example, the terms :math:`IXX` and
268
- :math:`IYI` would be connected, but not :math:`IXX` and :math:`YII`). Then,
269
- the graph is colored. Two terms with the same color thus do not act on the
270
- same qubit, and in particular, their evolution subcircuits can be run in
271
- parallel in the greater evolution circuit of ``paulis``.
272
334
 
273
- This method is deterministic and invariant under permutation of the Pauli
274
- term in ``paulis``.
335
+ def cnot_fountain(pauli: Pauli) -> QuantumCircuit:
336
+ """CX chain in the fountain shape.
275
337
 
276
- Args:
277
- paulis: The operator whose terms to reorder.
278
- strategy: The coloring heuristic to use, see ``ColoringStrategy`` [#].
279
- Default is ``ColoringStrategy.Saturation``.
338
+ For example, for the Pauli with the label 'XYZIX'.
339
+
340
+ .. parsed-literal::
280
341
 
281
- .. [#] https://www.rustworkx.org/apiref/rustworkx.ColoringStrategy.html#coloringstrategy
342
+ ┌───┐┌───┐┌───┐
343
+ q_0: ┤ X ├┤ X ├┤ X ├
344
+ └─┬─┘└─┬─┘└─┬─┘
345
+ q_1: ──┼────┼────┼──
346
+ │ │ │
347
+ q_2: ──■────┼────┼──
348
+ │ │
349
+ q_3: ───────■────┼──
350
+
351
+ q_4: ────────────■──
352
+
353
+ Args:
354
+ pauli: The Pauli for which to construct the CX chain.
282
355
 
356
+ Returns:
357
+ A circuit implementing the CX chain.
283
358
  """
284
359
 
285
- def _term_sort_key(term: SparsePauliLabel) -> typing.Any:
286
- # sort by index, then by pauli
287
- return (term[1], term[0])
288
-
289
- # Do nothing in trivial cases
290
- if len(paulis) <= 1:
291
- return paulis
292
-
293
- terms = sorted(paulis, key=_term_sort_key)
294
- graph = rx.PyGraph()
295
- graph.add_nodes_from(terms)
296
- indexed_nodes = list(enumerate(graph.nodes()))
297
- for (idx1, (_, ind1, _)), (idx2, (_, ind2, _)) in combinations(indexed_nodes, 2):
298
- # Add an edge between two terms if they touch the same qubit
299
- if len(set(ind1).intersection(ind2)) > 0:
300
- graph.add_edge(idx1, idx2, None)
301
-
302
- # rx.graph_greedy_color is supposed to be deterministic
303
- coloring = rx.graph_greedy_color(graph, strategy=strategy)
304
- terms_by_color = defaultdict(list)
305
-
306
- for term_idx, color in sorted(coloring.items()):
307
- term = graph.nodes()[term_idx]
308
- terms_by_color[color].append(term)
309
-
310
- terms = list(itertools.chain(*terms_by_color.values()))
311
- return terms
360
+ chain = QuantumCircuit(pauli.num_qubits)
361
+ control, target = None, None
362
+ for i, pauli_i in enumerate(reversed(pauli.to_label())):
363
+ if pauli_i != "I":
364
+ if target is None:
365
+ target = i
366
+ else:
367
+ control = i
368
+
369
+ if control is not None and target is not None:
370
+ chain.cx(control, target)
371
+ control = None
372
+
373
+ return chain
374
+
375
+
376
+ def _default_atomic_evolution(output, operator, time, cx_structure, wrap):
377
+ if isinstance(operator, Pauli):
378
+ # single Pauli operator: just exponentiate it
379
+ evolve_pauli(output, operator, time, cx_structure, wrap)
380
+ else:
381
+ # sum of Pauli operators: exponentiate each term (this assumes they commute)
382
+ pauli_list = [(Pauli(op), np.real(coeff)) for op, coeff in operator.to_list()]
383
+ for pauli, coeff in pauli_list:
384
+ evolve_pauli(output, pauli, coeff * time, cx_structure, wrap)