qiskit 1.3.0b1__cp39-abi3-win32.whl → 1.3.0rc2__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 (360) hide show
  1. qiskit/VERSION.txt +1 -1
  2. qiskit/__init__.py +20 -1
  3. qiskit/_accelerate.pyd +0 -0
  4. qiskit/assembler/assemble_schedules.py +2 -0
  5. qiskit/circuit/__init__.py +44 -1
  6. qiskit/circuit/_standard_gates_commutations.py +585 -0
  7. qiskit/circuit/barrier.py +2 -0
  8. qiskit/circuit/controlflow/builder.py +3 -3
  9. qiskit/circuit/controlflow/if_else.py +13 -5
  10. qiskit/circuit/controlflow/while_loop.py +10 -2
  11. qiskit/circuit/delay.py +20 -3
  12. qiskit/circuit/equivalence.py +13 -214
  13. qiskit/circuit/gate.py +3 -1
  14. qiskit/circuit/instruction.py +32 -11
  15. qiskit/circuit/instructionset.py +2 -0
  16. qiskit/circuit/library/__init__.py +110 -14
  17. qiskit/circuit/library/arithmetic/__init__.py +9 -2
  18. qiskit/circuit/library/arithmetic/adders/__init__.py +1 -0
  19. qiskit/circuit/library/arithmetic/adders/adder.py +154 -2
  20. qiskit/circuit/library/arithmetic/adders/cdkm_ripple_carry_adder.py +20 -56
  21. qiskit/circuit/library/arithmetic/adders/draper_qft_adder.py +14 -1
  22. qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py +21 -91
  23. qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +1 -1
  24. qiskit/circuit/library/arithmetic/multipliers/__init__.py +1 -0
  25. qiskit/circuit/library/arithmetic/multipliers/hrs_cumulative_multiplier.py +8 -1
  26. qiskit/circuit/library/arithmetic/multipliers/multiplier.py +94 -3
  27. qiskit/circuit/library/arithmetic/multipliers/rg_qft_multiplier.py +8 -1
  28. qiskit/circuit/library/arithmetic/weighted_adder.py +1 -1
  29. qiskit/circuit/library/basis_change/qft.py +20 -38
  30. qiskit/circuit/library/blueprintcircuit.py +64 -0
  31. qiskit/circuit/library/boolean_logic/__init__.py +4 -4
  32. qiskit/circuit/library/boolean_logic/inner_product.py +81 -4
  33. qiskit/circuit/library/boolean_logic/quantum_and.py +107 -4
  34. qiskit/circuit/library/boolean_logic/quantum_or.py +107 -3
  35. qiskit/circuit/library/boolean_logic/quantum_xor.py +97 -3
  36. qiskit/circuit/library/data_preparation/__init__.py +6 -3
  37. qiskit/circuit/library/data_preparation/{z_feature_map.py → _z_feature_map.py} +45 -34
  38. qiskit/circuit/library/data_preparation/_zz_feature_map.py +150 -0
  39. qiskit/circuit/library/data_preparation/pauli_feature_map.py +342 -29
  40. qiskit/circuit/library/fourier_checking.py +72 -11
  41. qiskit/circuit/library/generalized_gates/__init__.py +1 -1
  42. qiskit/circuit/library/generalized_gates/diagonal.py +45 -51
  43. qiskit/circuit/library/generalized_gates/gms.py +67 -14
  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 +12 -6
  47. qiskit/circuit/library/generalized_gates/mcmt.py +167 -107
  48. qiskit/circuit/library/generalized_gates/permutation.py +8 -6
  49. qiskit/circuit/library/generalized_gates/rv.py +8 -9
  50. qiskit/circuit/library/graph_state.py +93 -10
  51. qiskit/circuit/library/grover_operator.py +270 -2
  52. qiskit/circuit/library/hidden_linear_function.py +83 -20
  53. qiskit/circuit/library/iqp.py +99 -20
  54. qiskit/circuit/library/n_local/__init__.py +19 -7
  55. qiskit/circuit/library/n_local/efficient_su2.py +118 -5
  56. qiskit/circuit/library/n_local/evolved_operator_ansatz.py +259 -0
  57. qiskit/circuit/library/n_local/excitation_preserving.py +130 -6
  58. qiskit/circuit/library/n_local/n_local.py +406 -5
  59. qiskit/circuit/library/n_local/pauli_two_design.py +106 -4
  60. qiskit/circuit/library/n_local/qaoa_ansatz.py +80 -1
  61. qiskit/circuit/library/n_local/real_amplitudes.py +127 -7
  62. qiskit/circuit/library/n_local/two_local.py +14 -7
  63. qiskit/circuit/library/overlap.py +91 -26
  64. qiskit/circuit/library/pauli_evolution.py +17 -15
  65. qiskit/circuit/library/phase_estimation.py +80 -4
  66. qiskit/circuit/library/quantum_volume.py +72 -20
  67. qiskit/circuit/library/standard_gates/__init__.py +20 -1
  68. qiskit/circuit/library/standard_gates/dcx.py +2 -1
  69. qiskit/circuit/library/standard_gates/ecr.py +2 -2
  70. qiskit/circuit/library/standard_gates/h.py +4 -3
  71. qiskit/circuit/library/standard_gates/i.py +2 -1
  72. qiskit/circuit/library/standard_gates/iswap.py +2 -2
  73. qiskit/circuit/library/standard_gates/p.py +20 -12
  74. qiskit/circuit/library/standard_gates/r.py +1 -1
  75. qiskit/circuit/library/standard_gates/rx.py +4 -3
  76. qiskit/circuit/library/standard_gates/rxx.py +2 -2
  77. qiskit/circuit/library/standard_gates/ry.py +4 -3
  78. qiskit/circuit/library/standard_gates/ryy.py +2 -2
  79. qiskit/circuit/library/standard_gates/rz.py +13 -12
  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 +4 -3
  85. qiskit/circuit/library/standard_gates/t.py +2 -2
  86. qiskit/circuit/library/standard_gates/u.py +11 -3
  87. qiskit/circuit/library/standard_gates/u1.py +65 -15
  88. qiskit/circuit/library/standard_gates/u2.py +4 -1
  89. qiskit/circuit/library/standard_gates/u3.py +31 -3
  90. qiskit/circuit/library/standard_gates/x.py +7 -5
  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 +4 -3
  94. qiskit/circuit/library/standard_gates/z.py +3 -3
  95. qiskit/circuit/library/templates/clifford/clifford_2_1.py +9 -8
  96. qiskit/circuit/library/templates/clifford/clifford_2_2.py +10 -9
  97. qiskit/circuit/library/templates/clifford/clifford_2_3.py +9 -7
  98. qiskit/circuit/library/templates/clifford/clifford_2_4.py +9 -8
  99. qiskit/circuit/library/templates/clifford/clifford_3_1.py +9 -8
  100. qiskit/circuit/library/templates/clifford/clifford_4_1.py +10 -9
  101. qiskit/circuit/library/templates/clifford/clifford_4_2.py +10 -9
  102. qiskit/circuit/library/templates/clifford/clifford_4_3.py +10 -9
  103. qiskit/circuit/library/templates/clifford/clifford_4_4.py +10 -9
  104. qiskit/circuit/library/templates/clifford/clifford_5_1.py +10 -9
  105. qiskit/circuit/library/templates/clifford/clifford_6_1.py +10 -9
  106. qiskit/circuit/library/templates/clifford/clifford_6_2.py +10 -9
  107. qiskit/circuit/library/templates/clifford/clifford_6_3.py +10 -9
  108. qiskit/circuit/library/templates/clifford/clifford_6_4.py +9 -8
  109. qiskit/circuit/library/templates/clifford/clifford_6_5.py +10 -9
  110. qiskit/circuit/library/templates/clifford/clifford_8_1.py +10 -9
  111. qiskit/circuit/library/templates/clifford/clifford_8_2.py +10 -9
  112. qiskit/circuit/library/templates/clifford/clifford_8_3.py +10 -9
  113. qiskit/circuit/library/templates/nct/template_nct_2a_1.py +9 -7
  114. qiskit/circuit/library/templates/nct/template_nct_2a_2.py +10 -8
  115. qiskit/circuit/library/templates/nct/template_nct_2a_3.py +12 -10
  116. qiskit/circuit/library/templates/nct/template_nct_4a_1.py +16 -14
  117. qiskit/circuit/library/templates/nct/template_nct_4a_2.py +14 -12
  118. qiskit/circuit/library/templates/nct/template_nct_4a_3.py +12 -10
  119. qiskit/circuit/library/templates/nct/template_nct_4b_1.py +14 -12
  120. qiskit/circuit/library/templates/nct/template_nct_4b_2.py +12 -10
  121. qiskit/circuit/library/templates/nct/template_nct_5a_1.py +12 -10
  122. qiskit/circuit/library/templates/nct/template_nct_5a_2.py +12 -10
  123. qiskit/circuit/library/templates/nct/template_nct_5a_3.py +12 -10
  124. qiskit/circuit/library/templates/nct/template_nct_5a_4.py +11 -9
  125. qiskit/circuit/library/templates/nct/template_nct_6a_1.py +11 -9
  126. qiskit/circuit/library/templates/nct/template_nct_6a_2.py +12 -10
  127. qiskit/circuit/library/templates/nct/template_nct_6a_3.py +12 -10
  128. qiskit/circuit/library/templates/nct/template_nct_6a_4.py +12 -10
  129. qiskit/circuit/library/templates/nct/template_nct_6b_1.py +12 -10
  130. qiskit/circuit/library/templates/nct/template_nct_6b_2.py +12 -10
  131. qiskit/circuit/library/templates/nct/template_nct_6c_1.py +12 -10
  132. qiskit/circuit/library/templates/nct/template_nct_7a_1.py +13 -11
  133. qiskit/circuit/library/templates/nct/template_nct_7b_1.py +13 -11
  134. qiskit/circuit/library/templates/nct/template_nct_7c_1.py +13 -11
  135. qiskit/circuit/library/templates/nct/template_nct_7d_1.py +13 -11
  136. qiskit/circuit/library/templates/nct/template_nct_7e_1.py +13 -11
  137. qiskit/circuit/library/templates/nct/template_nct_9a_1.py +13 -11
  138. qiskit/circuit/library/templates/nct/template_nct_9c_1.py +11 -9
  139. qiskit/circuit/library/templates/nct/template_nct_9c_10.py +12 -10
  140. qiskit/circuit/library/templates/nct/template_nct_9c_11.py +12 -10
  141. qiskit/circuit/library/templates/nct/template_nct_9c_12.py +12 -10
  142. qiskit/circuit/library/templates/nct/template_nct_9c_2.py +12 -10
  143. qiskit/circuit/library/templates/nct/template_nct_9c_3.py +12 -10
  144. qiskit/circuit/library/templates/nct/template_nct_9c_4.py +12 -10
  145. qiskit/circuit/library/templates/nct/template_nct_9c_5.py +12 -10
  146. qiskit/circuit/library/templates/nct/template_nct_9c_6.py +12 -10
  147. qiskit/circuit/library/templates/nct/template_nct_9c_7.py +12 -10
  148. qiskit/circuit/library/templates/nct/template_nct_9c_8.py +12 -10
  149. qiskit/circuit/library/templates/nct/template_nct_9c_9.py +12 -10
  150. qiskit/circuit/library/templates/nct/template_nct_9d_1.py +11 -9
  151. qiskit/circuit/library/templates/nct/template_nct_9d_10.py +12 -10
  152. qiskit/circuit/library/templates/nct/template_nct_9d_2.py +12 -10
  153. qiskit/circuit/library/templates/nct/template_nct_9d_3.py +12 -10
  154. qiskit/circuit/library/templates/nct/template_nct_9d_4.py +12 -10
  155. qiskit/circuit/library/templates/nct/template_nct_9d_5.py +12 -10
  156. qiskit/circuit/library/templates/nct/template_nct_9d_6.py +12 -10
  157. qiskit/circuit/library/templates/nct/template_nct_9d_7.py +12 -10
  158. qiskit/circuit/library/templates/nct/template_nct_9d_8.py +12 -10
  159. qiskit/circuit/library/templates/nct/template_nct_9d_9.py +12 -10
  160. qiskit/circuit/library/templates/rzx/rzx_cy.py +11 -10
  161. qiskit/circuit/library/templates/rzx/rzx_xz.py +16 -15
  162. qiskit/circuit/library/templates/rzx/rzx_yz.py +12 -10
  163. qiskit/circuit/library/templates/rzx/rzx_zz1.py +22 -20
  164. qiskit/circuit/library/templates/rzx/rzx_zz2.py +16 -15
  165. qiskit/circuit/library/templates/rzx/rzx_zz3.py +17 -15
  166. qiskit/circuit/parameter.py +4 -0
  167. qiskit/circuit/parameterexpression.py +167 -34
  168. qiskit/circuit/quantumcircuit.py +162 -126
  169. qiskit/circuit/singleton.py +2 -0
  170. qiskit/circuit/store.py +2 -0
  171. qiskit/circuit/twirling.py +145 -0
  172. qiskit/compiler/assembler.py +17 -4
  173. qiskit/compiler/scheduler.py +2 -0
  174. qiskit/compiler/sequencer.py +2 -0
  175. qiskit/compiler/transpiler.py +81 -26
  176. qiskit/converters/circuit_to_dag.py +2 -2
  177. qiskit/converters/circuit_to_dagdependency.py +1 -1
  178. qiskit/converters/circuit_to_dagdependency_v2.py +1 -1
  179. qiskit/converters/circuit_to_instruction.py +1 -1
  180. qiskit/converters/dag_to_circuit.py +7 -5
  181. qiskit/converters/dag_to_dagdependency.py +1 -1
  182. qiskit/converters/dag_to_dagdependency_v2.py +1 -1
  183. qiskit/converters/dagdependency_to_circuit.py +5 -1
  184. qiskit/converters/dagdependency_to_dag.py +6 -1
  185. qiskit/dagcircuit/collect_blocks.py +3 -3
  186. qiskit/dagcircuit/dagdependency.py +18 -5
  187. qiskit/dagcircuit/dagdependency_v2.py +1 -1
  188. qiskit/dagcircuit/dagnode.py +2 -2
  189. qiskit/passmanager/__init__.py +2 -2
  190. qiskit/primitives/backend_estimator.py +5 -2
  191. qiskit/primitives/backend_sampler_v2.py +61 -18
  192. qiskit/primitives/base/base_estimator.py +2 -2
  193. qiskit/primitives/containers/data_bin.py +9 -1
  194. qiskit/primitives/statevector_sampler.py +1 -1
  195. qiskit/primitives/utils.py +1 -1
  196. qiskit/providers/__init__.py +3 -3
  197. qiskit/providers/backend.py +12 -1
  198. qiskit/providers/backend_compat.py +23 -3
  199. qiskit/providers/basic_provider/basic_simulator.py +12 -2
  200. qiskit/providers/fake_provider/fake_pulse_backend.py +6 -1
  201. qiskit/providers/fake_provider/generic_backend_v2.py +46 -30
  202. qiskit/providers/models/pulsedefaults.py +2 -0
  203. qiskit/pulse/builder.py +59 -18
  204. qiskit/pulse/calibration_entries.py +4 -1
  205. qiskit/pulse/channels.py +2 -0
  206. qiskit/pulse/exceptions.py +2 -0
  207. qiskit/pulse/instruction_schedule_map.py +21 -6
  208. qiskit/pulse/instructions/acquire.py +2 -0
  209. qiskit/pulse/instructions/delay.py +2 -0
  210. qiskit/pulse/instructions/directives.py +8 -0
  211. qiskit/pulse/instructions/frequency.py +3 -0
  212. qiskit/pulse/instructions/instruction.py +2 -0
  213. qiskit/pulse/instructions/phase.py +3 -0
  214. qiskit/pulse/instructions/play.py +2 -0
  215. qiskit/pulse/instructions/reference.py +2 -0
  216. qiskit/pulse/instructions/snapshot.py +2 -0
  217. qiskit/pulse/library/pulse.py +2 -0
  218. qiskit/pulse/library/symbolic_pulses.py +28 -0
  219. qiskit/pulse/library/waveform.py +2 -0
  220. qiskit/pulse/macros.py +1 -1
  221. qiskit/pulse/schedule.py +12 -13
  222. qiskit/pulse/transforms/alignments.py +5 -3
  223. qiskit/pulse/transforms/dag.py +7 -0
  224. qiskit/qasm2/export.py +5 -3
  225. qiskit/qasm2/parse.py +46 -2
  226. qiskit/qasm3/__init__.py +1 -0
  227. qiskit/qasm3/ast.py +123 -15
  228. qiskit/qasm3/exporter.py +103 -77
  229. qiskit/qobj/converters/pulse_instruction.py +6 -4
  230. qiskit/qpy/__init__.py +181 -0
  231. qiskit/qpy/binary_io/circuits.py +20 -5
  232. qiskit/qpy/binary_io/schedules.py +3 -4
  233. qiskit/qpy/binary_io/value.py +310 -13
  234. qiskit/qpy/common.py +46 -2
  235. qiskit/qpy/formats.py +7 -0
  236. qiskit/qpy/interface.py +40 -4
  237. qiskit/quantum_info/__init__.py +4 -0
  238. qiskit/quantum_info/operators/channel/transformations.py +28 -21
  239. qiskit/quantum_info/operators/dihedral/dihedral.py +1 -1
  240. qiskit/quantum_info/operators/operator.py +54 -8
  241. qiskit/quantum_info/operators/symplectic/base_pauli.py +11 -19
  242. qiskit/quantum_info/operators/symplectic/clifford.py +1 -1
  243. qiskit/quantum_info/operators/symplectic/clifford_circuits.py +1 -1
  244. qiskit/quantum_info/operators/symplectic/pauli.py +2 -0
  245. qiskit/quantum_info/operators/symplectic/pauli_list.py +4 -4
  246. qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +23 -2
  247. qiskit/quantum_info/states/densitymatrix.py +5 -5
  248. qiskit/quantum_info/states/stabilizerstate.py +1 -1
  249. qiskit/quantum_info/states/statevector.py +6 -6
  250. qiskit/result/mitigation/base_readout_mitigator.py +1 -1
  251. qiskit/result/mitigation/correlated_readout_mitigator.py +9 -1
  252. qiskit/result/mitigation/local_readout_mitigator.py +9 -1
  253. qiskit/result/mitigation/utils.py +57 -0
  254. qiskit/scheduler/config.py +2 -0
  255. qiskit/scheduler/methods/basic.py +3 -0
  256. qiskit/scheduler/schedule_circuit.py +2 -0
  257. qiskit/scheduler/sequence.py +2 -0
  258. qiskit/synthesis/__init__.py +25 -0
  259. qiskit/synthesis/arithmetic/__init__.py +16 -0
  260. qiskit/synthesis/arithmetic/adders/__init__.py +17 -0
  261. qiskit/synthesis/arithmetic/adders/cdkm_ripple_carry_adder.py +154 -0
  262. qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +103 -0
  263. qiskit/synthesis/arithmetic/adders/vbe_ripple_carry_adder.py +161 -0
  264. qiskit/synthesis/arithmetic/multipliers/__init__.py +16 -0
  265. qiskit/synthesis/arithmetic/multipliers/hrs_cumulative_multiplier.py +102 -0
  266. qiskit/synthesis/arithmetic/multipliers/rg_qft_multiplier.py +99 -0
  267. qiskit/synthesis/clifford/clifford_decompose_bm.py +1 -2
  268. qiskit/synthesis/clifford/clifford_decompose_greedy.py +3 -2
  269. qiskit/synthesis/clifford/clifford_decompose_layers.py +2 -1
  270. qiskit/synthesis/evolution/__init__.py +1 -0
  271. qiskit/synthesis/evolution/lie_trotter.py +16 -42
  272. qiskit/synthesis/evolution/pauli_network.py +80 -0
  273. qiskit/synthesis/evolution/product_formula.py +165 -238
  274. qiskit/synthesis/evolution/qdrift.py +36 -29
  275. qiskit/synthesis/evolution/suzuki_trotter.py +87 -27
  276. qiskit/synthesis/multi_controlled/__init__.py +1 -0
  277. qiskit/synthesis/multi_controlled/mcmt_vchain.py +52 -0
  278. qiskit/synthesis/qft/qft_decompose_full.py +19 -1
  279. qiskit/synthesis/qft/qft_decompose_lnn.py +2 -1
  280. qiskit/synthesis/stabilizer/stabilizer_decompose.py +2 -1
  281. qiskit/synthesis/two_qubit/two_qubit_decompose.py +4 -63
  282. qiskit/synthesis/unitary/qsd.py +5 -5
  283. qiskit/transpiler/__init__.py +21 -14
  284. qiskit/transpiler/basepasses.py +1 -1
  285. qiskit/transpiler/passes/__init__.py +2 -0
  286. qiskit/transpiler/passes/basis/basis_translator.py +9 -565
  287. qiskit/transpiler/passes/basis/decompose.py +45 -12
  288. qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
  289. qiskit/transpiler/passes/basis/unroll_custom_definitions.py +1 -1
  290. qiskit/transpiler/passes/calibration/pulse_gate.py +4 -2
  291. qiskit/transpiler/passes/calibration/rx_builder.py +11 -7
  292. qiskit/transpiler/passes/calibration/rzx_builder.py +46 -30
  293. qiskit/transpiler/passes/layout/disjoint_utils.py +15 -13
  294. qiskit/transpiler/passes/layout/sabre_layout.py +7 -2
  295. qiskit/transpiler/passes/layout/sabre_pre_layout.py +5 -0
  296. qiskit/transpiler/passes/optimization/__init__.py +1 -0
  297. qiskit/transpiler/passes/optimization/collect_cliffords.py +19 -3
  298. qiskit/transpiler/passes/optimization/collect_linear_functions.py +1 -1
  299. qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +2 -2
  300. qiskit/transpiler/passes/optimization/commutative_inverse_cancellation.py +1 -1
  301. qiskit/transpiler/passes/optimization/consolidate_blocks.py +48 -131
  302. qiskit/transpiler/passes/optimization/echo_rzx_weyl_decomposition.py +4 -2
  303. qiskit/transpiler/passes/optimization/elide_permutations.py +9 -32
  304. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +5 -11
  305. qiskit/transpiler/passes/optimization/optimize_1q_gates.py +1 -1
  306. qiskit/transpiler/passes/optimization/optimize_swap_before_measure.py +1 -1
  307. qiskit/transpiler/passes/optimization/remove_identity_equiv.py +69 -0
  308. qiskit/transpiler/passes/optimization/template_matching/backward_match.py +5 -5
  309. qiskit/transpiler/passes/optimization/template_matching/forward_match.py +4 -4
  310. qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +2 -2
  311. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +1 -1
  312. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +1 -1
  313. qiskit/transpiler/passes/routing/sabre_swap.py +7 -3
  314. qiskit/transpiler/passes/routing/star_prerouting.py +2 -2
  315. qiskit/transpiler/passes/scheduling/alap.py +1 -1
  316. qiskit/transpiler/passes/scheduling/alignments/align_measures.py +2 -2
  317. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
  318. qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +2 -0
  319. qiskit/transpiler/passes/scheduling/alignments/reschedule.py +2 -2
  320. qiskit/transpiler/passes/scheduling/asap.py +1 -1
  321. qiskit/transpiler/passes/scheduling/base_scheduler.py +14 -12
  322. qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +9 -4
  323. qiskit/transpiler/passes/scheduling/padding/base_padding.py +1 -1
  324. qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +16 -5
  325. qiskit/transpiler/passes/scheduling/padding/pad_delay.py +4 -1
  326. qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +6 -2
  327. qiskit/transpiler/passes/scheduling/time_unit_conversion.py +9 -4
  328. qiskit/transpiler/passes/synthesis/high_level_synthesis.py +262 -99
  329. qiskit/transpiler/passes/synthesis/hls_plugins.py +637 -7
  330. qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +3 -3
  331. qiskit/transpiler/passes/synthesis/unitary_synthesis.py +55 -34
  332. qiskit/transpiler/passes/utils/barrier_before_final_measurements.py +2 -56
  333. qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +5 -0
  334. qiskit/transpiler/passes/utils/gate_direction.py +12 -275
  335. qiskit/transpiler/passes/utils/gates_basis.py +7 -30
  336. qiskit/transpiler/passes/utils/merge_adjacent_barriers.py +2 -1
  337. qiskit/transpiler/passmanager_config.py +22 -4
  338. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +40 -14
  339. qiskit/transpiler/preset_passmanagers/common.py +5 -3
  340. qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +125 -42
  341. qiskit/transpiler/preset_passmanagers/plugin.py +1 -1
  342. qiskit/transpiler/target.py +74 -16
  343. qiskit/utils/deprecate_pulse.py +119 -0
  344. qiskit/visualization/circuit/_utils.py +2 -2
  345. qiskit/visualization/circuit/circuit_visualization.py +3 -2
  346. qiskit/visualization/circuit/matplotlib.py +1 -1
  347. qiskit/visualization/dag_visualization.py +1 -1
  348. qiskit/visualization/pass_manager_visualization.py +3 -14
  349. qiskit/visualization/pulse_v2/interface.py +3 -1
  350. qiskit/visualization/timeline/core.py +25 -2
  351. qiskit/visualization/timeline/interface.py +12 -0
  352. {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/METADATA +9 -8
  353. {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/RECORD +357 -346
  354. {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/WHEEL +1 -1
  355. {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/entry_points.txt +19 -0
  356. qiskit/circuit/library/data_preparation/zz_feature_map.py +0 -118
  357. qiskit/synthesis/two_qubit/weyl.py +0 -97
  358. qiskit/transpiler/passes/synthesis/qubit_tracker.py +0 -132
  359. {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/LICENSE.txt +0 -0
  360. {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/top_level.txt +0 -0
@@ -64,10 +64,14 @@ class BaseScheduler(AnalysisPass):
64
64
  """A helper method to get duration from node or calibration."""
65
65
  indices = [dag.find_bit(qarg).index for qarg in node.qargs]
66
66
 
67
- if dag.has_calibration_for(node):
67
+ if dag._has_calibration_for(node):
68
68
  # If node has calibration, this value should be the highest priority
69
69
  cal_key = tuple(indices), tuple(float(p) for p in node.op.params)
70
- duration = dag.calibrations[node.op.name][cal_key].duration
70
+ with warnings.catch_warnings():
71
+ warnings.simplefilter(action="ignore", category=DeprecationWarning)
72
+ # `schedule.duration` emits pulse deprecation warnings which we don't want
73
+ # to see here
74
+ duration = dag._calibrations_prop[node.op.name][cal_key].duration
71
75
 
72
76
  # Note that node duration is updated (but this is analysis pass)
73
77
  op = node.op.to_mutable()
@@ -12,6 +12,7 @@
12
12
 
13
13
  """Unify time unit in circuit for scheduling and following passes."""
14
14
  from typing import Set
15
+ import warnings
15
16
 
16
17
  from qiskit.circuit import Delay
17
18
  from qiskit.dagcircuit import DAGCircuit
@@ -121,11 +122,15 @@ class TimeUnitConversion(TransformationPass):
121
122
  """
122
123
  circ_durations = InstructionDurations()
123
124
 
124
- if dag.calibrations:
125
+ if dag._calibrations_prop:
125
126
  cal_durations = []
126
- for gate, gate_cals in dag.calibrations.items():
127
- for (qubits, parameters), schedule in gate_cals.items():
128
- cal_durations.append((gate, qubits, parameters, schedule.duration))
127
+ with warnings.catch_warnings():
128
+ warnings.simplefilter(action="ignore", category=DeprecationWarning)
129
+ # `schedule.duration` emits pulse deprecation warnings which we don't want
130
+ # to see here
131
+ for gate, gate_cals in dag._calibrations_prop.items():
132
+ for (qubits, parameters), schedule in gate_cals.items():
133
+ cal_durations.append((gate, qubits, parameters, schedule.duration))
129
134
  circ_durations.update(cal_durations, circ_durations.dt)
130
135
 
131
136
  if self._durations_provided:
@@ -28,7 +28,7 @@ from qiskit.circuit.instruction import Instruction
28
28
  from qiskit.converters import circuit_to_dag, dag_to_circuit
29
29
  from qiskit.transpiler.basepasses import TransformationPass
30
30
  from qiskit.circuit.quantumcircuit import QuantumCircuit
31
- from qiskit.circuit import ControlledGate, EquivalenceLibrary, equivalence
31
+ from qiskit.circuit import ControlledGate, EquivalenceLibrary, equivalence, Qubit
32
32
  from qiskit.transpiler.passes.utils import control_flow
33
33
  from qiskit.transpiler.target import Target
34
34
  from qiskit.transpiler.coupling import CouplingMap
@@ -42,8 +42,8 @@ from qiskit.circuit.annotated_operation import (
42
42
  PowerModifier,
43
43
  )
44
44
 
45
+ from qiskit._accelerate.high_level_synthesis import QubitTracker, QubitContext
45
46
  from .plugin import HighLevelSynthesisPluginManager
46
- from .qubit_tracker import QubitTracker
47
47
 
48
48
  if typing.TYPE_CHECKING:
49
49
  from qiskit.dagcircuit import DAGOpNode
@@ -271,96 +271,161 @@ class HighLevelSynthesis(TransformationPass):
271
271
  (for instance, when the specified synthesis method is not available).
272
272
  """
273
273
  qubits = tuple(dag.find_bit(q).index for q in dag.qubits)
274
+ context = QubitContext(list(range(len(dag.qubits))))
275
+ tracker = QubitTracker(num_qubits=dag.num_qubits())
274
276
  if self.qubits_initially_zero:
275
- clean, dirty = set(qubits), set()
276
- else:
277
- clean, dirty = set(), set(qubits)
277
+ tracker.set_clean(context.to_globals(qubits))
278
278
 
279
- tracker = QubitTracker(qubits=qubits, clean=clean, dirty=dirty)
280
- return self._run(dag, tracker)
279
+ out_dag = self._run(dag, tracker, context, use_ancillas=True, top_level=True)
280
+ return out_dag
281
281
 
282
- def _run(self, dag: DAGCircuit, tracker: QubitTracker) -> DAGCircuit:
283
- # Check if HighLevelSynthesis can be skipped.
284
- for node in dag.op_nodes():
285
- qubits = tuple(dag.find_bit(q).index for q in node.qargs)
286
- if not self._definitely_skip_node(node, qubits, dag):
287
- break
288
- else:
289
- # The for-loop terminates without reaching the break statement
290
- return dag
282
+ def _run(
283
+ self,
284
+ dag: DAGCircuit,
285
+ tracker: QubitTracker,
286
+ context: QubitContext,
287
+ use_ancillas: bool,
288
+ top_level: bool,
289
+ ) -> DAGCircuit:
290
+ """
291
+ The main recursive function that synthesizes a DAGCircuit.
292
+
293
+ Input:
294
+ dag: the DAG to be synthesized.
295
+ tracker: the global tracker, tracking the state of original qubits.
296
+ context: the correspondence between the dag's qubits and the global qubits.
297
+ use_ancillas: if True, synthesis algorithms are allowed to use ancillas.
298
+ top_level: specifies if this is the top-level of the recursion.
299
+
300
+ The function returns the synthesized DAG.
301
+
302
+ Note that by using the auxiliary qubits to synthesize operations present in the input DAG,
303
+ the synthesized DAG may be defined over more qubits than the input DAG. In this case,
304
+ the function update in-place the global qubits tracker and extends the local-to-global
305
+ context.
306
+ """
307
+
308
+ if dag.num_qubits() != context.num_qubits():
309
+ raise TranspilerError("HighLevelSynthesis internal error.")
291
310
 
292
- # Start by analyzing the nodes in the DAG. This for-loop is a first version of a potentially
293
- # more elaborate approach to find good operation/ancilla allocations. It greedily iterates
294
- # over the nodes, checking whether we can synthesize them, while keeping track of the
295
- # qubit states. It does not trade-off allocations and just gives all available qubits
296
- # to the current operation (a "the-first-takes-all" approach).
311
+ # STEP 1: Check if HighLevelSynthesis can be skipped altogether. This is only
312
+ # done at the top-level since this does not update the global qubits tracker.
313
+ if top_level:
314
+ for node in dag.op_nodes():
315
+ qubits = tuple(dag.find_bit(q).index for q in node.qargs)
316
+ if not self._definitely_skip_node(node, qubits, dag):
317
+ break
318
+ else:
319
+ # The for-loop terminates without reaching the break statement
320
+ if dag.num_qubits() != context.num_qubits():
321
+ raise TranspilerError("HighLevelSynthesis internal error.")
322
+ return dag
323
+
324
+ # STEP 2: Analyze the nodes in the DAG. For each node in the DAG that needs
325
+ # to be synthesized, we recursively synthesize it and store the result. For
326
+ # instance, the result of synthesizing a custom gate is a DAGCircuit corresponding
327
+ # to the (recursively synthesized) gate's definition. When the result is a
328
+ # DAG, we also store its context (the mapping of its qubits to global qubits).
329
+ # In addition, we keep track of the qubit states using the (global) qubits tracker.
330
+ #
331
+ # Note: This is a first version of a potentially more elaborate approach to find
332
+ # good operation/ancilla allocations. The current approach is greedy and just gives
333
+ # all available ancilla qubits to the current operation ("the-first-takes-all" approach).
334
+ # It does not distribute ancilla qubits between different operations present in the DAG.
297
335
  synthesized_nodes = {}
298
336
 
299
337
  for node in dag.topological_op_nodes():
300
338
  qubits = tuple(dag.find_bit(q).index for q in node.qargs)
339
+ processed = False
301
340
  synthesized = None
302
- used_qubits = None
341
+ synthesized_context = None
342
+
343
+ # Start by handling special operations. Other cases can also be
344
+ # considered: swaps, automatically simplifying control gate (e.g. if
345
+ # a control is 0).
346
+ if node.op.name in ["id", "delay", "barrier"]:
347
+ # tracker not updated, these are no-ops
348
+ processed = True
349
+
350
+ elif node.op.name == "reset":
351
+ # reset qubits to 0
352
+ tracker.set_clean(context.to_globals(qubits))
353
+ processed = True
303
354
 
304
355
  # check if synthesis for the operation can be skipped
305
- if self._definitely_skip_node(node, qubits, dag):
306
- pass
356
+ elif self._definitely_skip_node(node, qubits, dag):
357
+ tracker.set_dirty(context.to_globals(qubits))
307
358
 
308
359
  # next check control flow
309
360
  elif node.is_control_flow():
310
- dag.substitute_node(
311
- node,
312
- control_flow.map_blocks(partial(self._run, tracker=tracker.copy()), node.op),
313
- propagate_condition=False,
361
+ inner_context = context.restrict(qubits)
362
+ synthesized = control_flow.map_blocks(
363
+ partial(
364
+ self._run,
365
+ tracker=tracker,
366
+ context=inner_context,
367
+ use_ancillas=False,
368
+ top_level=False,
369
+ ),
370
+ node.op,
314
371
  )
315
372
 
316
373
  # now we are free to synthesize
317
374
  else:
318
- # this returns the synthesized operation and the qubits it acts on -- note that this
319
- # may be different from the original qubits, since we may use auxiliary qubits
320
- synthesized, used_qubits = self._synthesize_operation(node.op, qubits, tracker)
375
+ # This returns the synthesized operation and its context (when the result is
376
+ # a DAG, it's the correspondence between its qubits and the global qubits).
377
+ # Also note that the DAG may use auxiliary qubits. The qubits tracker and the
378
+ # current DAG's context are updated in-place.
379
+ synthesized, synthesized_context = self._synthesize_operation(
380
+ node.op, qubits, tracker, context, use_ancillas=use_ancillas
381
+ )
321
382
 
322
- # if the synthesis changed the operation (i.e. it is not None), store the result
323
- # and mark the operation qubits as used
383
+ # If the synthesis changed the operation (i.e. it is not None), store the result.
324
384
  if synthesized is not None:
325
- synthesized_nodes[node] = (synthesized, used_qubits)
326
- tracker.used(qubits) # assumes that auxiliary are returned in the same state
385
+ synthesized_nodes[node._node_id] = (synthesized, synthesized_context)
327
386
 
328
- # if the synthesis did not change anything, just update the qubit tracker
329
- # other cases can be added: swaps, controlled gates (e.g. if control is 0), ...
330
- else:
331
- if node.op.name in ["id", "delay", "barrier"]:
332
- pass # tracker not updated, these are no-ops
333
- elif node.op.name == "reset":
334
- tracker.reset(qubits) # reset qubits to 0
335
- else:
336
- tracker.used(qubits) # any other op used the clean state up
387
+ # If the synthesis did not change anything, just update the qubit tracker.
388
+ elif not processed:
389
+ tracker.set_dirty(context.to_globals(qubits))
337
390
 
338
- # we did not change anything just return the input
391
+ # We did not change anything just return the input.
339
392
  if len(synthesized_nodes) == 0:
393
+ if dag.num_qubits() != context.num_qubits():
394
+ raise TranspilerError("HighLevelSynthesis internal error.")
340
395
  return dag
341
396
 
342
- # Otherwise, we will rebuild with the new operations. Note that we could also
397
+ # STEP 3. We rebuild the DAG with new operations. Note that we could also
343
398
  # check if no operation changed in size and substitute in-place, but rebuilding is
344
399
  # generally as fast or faster, unless very few operations are changed.
345
400
  out = dag.copy_empty_like()
346
- index_to_qubit = dict(enumerate(dag.qubits))
401
+ num_additional_qubits = context.num_qubits() - out.num_qubits()
402
+
403
+ if num_additional_qubits > 0:
404
+ out.add_qubits([Qubit() for _ in range(num_additional_qubits)])
405
+
406
+ index_to_qubit = dict(enumerate(out.qubits))
407
+ outer_to_local = context.to_local_mapping()
347
408
 
348
409
  for node in dag.topological_op_nodes():
349
- if node in synthesized_nodes:
350
- op, qubits = synthesized_nodes[node]
351
- qargs = tuple(index_to_qubit[index] for index in qubits)
410
+
411
+ if op_tuple := synthesized_nodes.get(node._node_id, None):
412
+ op, op_context = op_tuple
413
+
352
414
  if isinstance(op, Operation):
353
- out.apply_operation_back(op, qargs, cargs=[])
415
+ out.apply_operation_back(op, node.qargs, node.cargs)
354
416
  continue
355
417
 
356
418
  if isinstance(op, QuantumCircuit):
357
419
  op = circuit_to_dag(op, copy_operations=False)
358
420
 
421
+ inner_to_global = op_context.to_global_mapping()
359
422
  if isinstance(op, DAGCircuit):
360
423
  qubit_map = {
361
- qubit: index_to_qubit[index] for index, qubit in zip(qubits, op.qubits)
424
+ q: index_to_qubit[outer_to_local[inner_to_global[i]]]
425
+ for (i, q) in enumerate(op.qubits)
362
426
  }
363
427
  clbit_map = dict(zip(op.clbits, node.cargs))
428
+
364
429
  for sub_node in op.op_nodes():
365
430
  out.apply_operation_back(
366
431
  sub_node.op,
@@ -368,11 +433,15 @@ class HighLevelSynthesis(TransformationPass):
368
433
  tuple(clbit_map[carg] for carg in sub_node.cargs),
369
434
  )
370
435
  out.global_phase += op.global_phase
436
+
371
437
  else:
372
- raise RuntimeError(f"Unexpected synthesized type: {type(op)}")
438
+ raise TranspilerError(f"Unexpected synthesized type: {type(op)}")
373
439
  else:
374
440
  out.apply_operation_back(node.op, node.qargs, node.cargs, check=False)
375
441
 
442
+ if out.num_qubits() != context.num_qubits():
443
+ raise TranspilerError("HighLevelSynthesis internal error.")
444
+
376
445
  return out
377
446
 
378
447
  def _synthesize_operation(
@@ -380,7 +449,23 @@ class HighLevelSynthesis(TransformationPass):
380
449
  operation: Operation,
381
450
  qubits: tuple[int],
382
451
  tracker: QubitTracker,
383
- ) -> tuple[QuantumCircuit | Operation | DAGCircuit | None, list[int] | None]:
452
+ context: QubitContext,
453
+ use_ancillas: bool,
454
+ ) -> tuple[QuantumCircuit | Operation | DAGCircuit | None, QubitContext | None]:
455
+ """
456
+ Synthesizes an operation. The function receives the qubits on which the operation
457
+ is defined in the current DAG, the correspondence between the qubits of the current
458
+ DAG and the global qubits and the global qubits tracker. The function returns the
459
+ result of synthesizing the operation. The value of `None` means that the operation
460
+ should remain as it is. When it's a circuit, we also return the context, i.e. the
461
+ correspondence of its local qubits and the global qubits. The function changes
462
+ in-place the tracker (state of the global qubits), the qubits (when the synthesized
463
+ operation is defined over additional ancilla qubits), and the context (to keep track
464
+ of where these ancilla qubits maps to).
465
+ """
466
+
467
+ synthesized_context = None
468
+
384
469
  # Try to synthesize the operation. We'll go through the following options:
385
470
  # (1) Annotations: if the operator is annotated, synthesize the base operation
386
471
  # and then apply the modifiers. Returns a circuit (e.g. applying a power)
@@ -389,31 +474,62 @@ class HighLevelSynthesis(TransformationPass):
389
474
  # if the operation is a Clifford). Returns a circuit.
390
475
  # (3) Unrolling custom definitions: try defining the operation if it is not yet
391
476
  # in the set of supported instructions. Returns a circuit.
477
+ #
392
478
  # If any of the above were triggered, we will recurse and go again through these steps
393
479
  # until no further change occurred. At this point, we convert circuits to DAGs (the final
394
480
  # possible return type). If there was no change, we just return ``None``.
481
+ num_original_qubits = len(qubits)
482
+ qubits = list(qubits)
483
+
395
484
  synthesized = None
396
485
 
397
486
  # Try synthesizing via AnnotatedOperation. This is faster than an isinstance check
398
487
  # but a bit less safe since someone could create operations with a ``modifiers`` attribute.
399
488
  if len(modifiers := getattr(operation, "modifiers", [])) > 0:
400
- # The base operation must be synthesized without using potential control qubits
489
+ # Note: the base operation must be synthesized without using potential control qubits
401
490
  # used in the modifiers.
402
491
  num_ctrl = sum(
403
492
  mod.num_ctrl_qubits for mod in modifiers if isinstance(mod, ControlModifier)
404
493
  )
405
494
  baseop_qubits = qubits[num_ctrl:] # reminder: control qubits are the first ones
406
- baseop_tracker = tracker.copy(drop=qubits[:num_ctrl]) # no access to control qubits
407
495
 
408
496
  # get qubits of base operation
497
+ control_qubits = qubits[0:num_ctrl]
498
+
499
+ # Do not allow access to control qubits
500
+ tracker.disable(context.to_globals(control_qubits))
409
501
  synthesized_base_op, _ = self._synthesize_operation(
410
- operation.base_op, baseop_qubits, baseop_tracker
502
+ operation.base_op,
503
+ baseop_qubits,
504
+ tracker,
505
+ context,
506
+ use_ancillas=use_ancillas,
411
507
  )
508
+
412
509
  if synthesized_base_op is None:
413
510
  synthesized_base_op = operation.base_op
414
511
  elif isinstance(synthesized_base_op, DAGCircuit):
415
512
  synthesized_base_op = dag_to_circuit(synthesized_base_op)
416
513
 
514
+ # Handle the case that synthesizing the base operation introduced
515
+ # additional qubits (e.g. the base operation is a circuit that includes
516
+ # an MCX gate).
517
+ if synthesized_base_op.num_qubits > len(baseop_qubits):
518
+ global_aux_qubits = tracker.borrow(
519
+ synthesized_base_op.num_qubits - len(baseop_qubits),
520
+ context.to_globals(baseop_qubits),
521
+ )
522
+ global_to_local = context.to_local_mapping()
523
+ for aq in global_aux_qubits:
524
+ if aq in global_to_local:
525
+ qubits.append(global_to_local[aq])
526
+ else:
527
+ new_local_qubit = context.add_qubit(aq)
528
+ qubits.append(new_local_qubit)
529
+ # Restore access to control qubits.
530
+ tracker.enable(context.to_globals(control_qubits))
531
+
532
+ # This step currently does not introduce ancilla qubits.
417
533
  synthesized = self._apply_annotations(synthesized_base_op, operation.modifiers)
418
534
 
419
535
  # If it was no AnnotatedOperation, try synthesizing via HLS or by unrolling.
@@ -421,57 +537,106 @@ class HighLevelSynthesis(TransformationPass):
421
537
  # Try synthesis via HLS -- which will return ``None`` if unsuccessful.
422
538
  indices = qubits if self._use_qubit_indices else None
423
539
  if len(hls_methods := self._methods_to_try(operation.name)) > 0:
540
+ if use_ancillas:
541
+ num_clean_available = tracker.num_clean(context.to_globals(qubits))
542
+ num_dirty_available = tracker.num_dirty(context.to_globals(qubits))
543
+ else:
544
+ num_clean_available = 0
545
+ num_dirty_available = 0
424
546
  synthesized = self._synthesize_op_using_plugins(
425
547
  hls_methods,
426
548
  operation,
427
549
  indices,
428
- tracker.num_clean(qubits),
429
- tracker.num_dirty(qubits),
550
+ num_clean_available,
551
+ num_dirty_available,
430
552
  )
431
553
 
554
+ # It may happen that the plugin synthesis method uses clean/dirty ancilla qubits
555
+ if (synthesized is not None) and (synthesized.num_qubits > len(qubits)):
556
+ # need to borrow more qubits from tracker
557
+ global_aux_qubits = tracker.borrow(
558
+ synthesized.num_qubits - len(qubits), context.to_globals(qubits)
559
+ )
560
+ global_to_local = context.to_local_mapping()
561
+
562
+ for aq in global_aux_qubits:
563
+ if aq in global_to_local:
564
+ qubits.append(global_to_local[aq])
565
+ else:
566
+ new_local_qubit = context.add_qubit(aq)
567
+ qubits.append(new_local_qubit)
568
+
432
569
  # If HLS did not apply, or was unsuccessful, try unrolling custom definitions.
433
570
  if synthesized is None and not self._top_level_only:
434
- synthesized = self._unroll_custom_definition(operation, indices)
571
+ synthesized = self._get_custom_definition(operation, indices)
435
572
 
436
573
  if synthesized is None:
437
- # if we didn't synthesize, there was nothing to unroll, so just set the used qubits
438
- used_qubits = qubits
574
+ # if we didn't synthesize, there was nothing to unroll
575
+ # updating the tracker will be handled upstream
576
+ pass
577
+
578
+ # if it has been synthesized, recurse and finally store the decomposition
579
+ elif isinstance(synthesized, Operation):
580
+ resynthesized, resynthesized_context = self._synthesize_operation(
581
+ synthesized, qubits, tracker, context, use_ancillas=use_ancillas
582
+ )
439
583
 
440
- else:
441
- # if it has been synthesized, recurse and finally store the decomposition
442
- if isinstance(synthesized, Operation):
443
- re_synthesized, qubits = self._synthesize_operation(
444
- synthesized, qubits, tracker.copy()
584
+ if resynthesized is not None:
585
+ synthesized = resynthesized
586
+ else:
587
+ tracker.set_dirty(context.to_globals(qubits))
588
+ if isinstance(resynthesized, DAGCircuit):
589
+ synthesized_context = resynthesized_context
590
+
591
+ elif isinstance(synthesized, QuantumCircuit):
592
+ # Synthesized is a quantum circuit which we want to process recursively.
593
+ # For example, it's the definition circuit of a custom gate
594
+ # or a circuit obtained by calling a synthesis method on a high-level-object.
595
+ # In the second case, synthesized may have more qubits than the original node.
596
+
597
+ as_dag = circuit_to_dag(synthesized, copy_operations=False)
598
+ inner_context = context.restrict(qubits)
599
+
600
+ if as_dag.num_qubits() != inner_context.num_qubits():
601
+ raise TranspilerError("HighLevelSynthesis internal error.")
602
+
603
+ # We save the current state of the tracker to be able to return the ancilla
604
+ # qubits to the current positions. Note that at this point we do not know
605
+ # which ancilla qubits will be allocated.
606
+ saved_tracker = tracker.copy()
607
+ synthesized = self._run(
608
+ as_dag, tracker, inner_context, use_ancillas=use_ancillas, top_level=False
609
+ )
610
+ synthesized_context = inner_context
611
+
612
+ if (synthesized is not None) and (synthesized.num_qubits() > len(qubits)):
613
+ # need to borrow more qubits from tracker
614
+ global_aux_qubits = tracker.borrow(
615
+ synthesized.num_qubits() - len(qubits), context.to_globals(qubits)
616
+ )
617
+ global_to_local = context.to_local_mapping()
618
+
619
+ for aq in global_aux_qubits:
620
+ if aq in global_to_local:
621
+ qubits.append(global_to_local[aq])
622
+ else:
623
+ new_local_qubit = context.add_qubit(aq)
624
+ qubits.append(new_local_qubit)
625
+
626
+ if len(qubits) > num_original_qubits:
627
+ tracker.replace_state(
628
+ saved_tracker, context.to_globals(qubits[num_original_qubits:])
445
629
  )
446
- if re_synthesized is not None:
447
- synthesized = re_synthesized
448
- used_qubits = qubits
449
-
450
- elif isinstance(synthesized, QuantumCircuit):
451
- aux_qubits = tracker.borrow(synthesized.num_qubits - len(qubits), qubits)
452
- used_qubits = qubits + tuple(aux_qubits)
453
- as_dag = circuit_to_dag(synthesized, copy_operations=False)
454
-
455
- # map used qubits to subcircuit
456
- new_qubits = [as_dag.find_bit(q).index for q in as_dag.qubits]
457
- qubit_map = dict(zip(used_qubits, new_qubits))
458
-
459
- synthesized = self._run(as_dag, tracker.copy(qubit_map))
460
- if synthesized.num_qubits() != len(used_qubits):
461
- raise RuntimeError(
462
- f"Mismatching number of qubits, using {synthesized.num_qubits()} "
463
- f"but have {len(used_qubits)}."
464
- )
465
630
 
466
- else:
467
- raise RuntimeError(f"Unexpected synthesized type: {type(synthesized)}")
631
+ else:
632
+ raise TranspilerError(f"Unexpected synthesized type: {type(synthesized)}")
468
633
 
469
- if synthesized is not None and used_qubits is None:
470
- raise RuntimeError("Failed to find qubit indices on", synthesized)
634
+ if isinstance(synthesized, DAGCircuit) and synthesized_context is None:
635
+ raise TranspilerError("HighLevelSynthesis internal error.")
471
636
 
472
- return synthesized, used_qubits
637
+ return synthesized, synthesized_context
473
638
 
474
- def _unroll_custom_definition(
639
+ def _get_custom_definition(
475
640
  self, inst: Instruction, qubits: list[int] | None
476
641
  ) -> QuantumCircuit | None:
477
642
  # check if the operation is already supported natively
@@ -646,9 +811,10 @@ class HighLevelSynthesis(TransformationPass):
646
811
  node (which is _most_ nodes)."""
647
812
 
648
813
  if (
649
- dag.has_calibration_for(node)
814
+ dag._has_calibration_for(node)
650
815
  or len(node.qargs) < self._min_qubits
651
816
  or node.is_directive()
817
+ or (self._instruction_supported(node.name, qubits) and not node.is_control_flow())
652
818
  ):
653
819
  return True
654
820
 
@@ -666,15 +832,12 @@ class HighLevelSynthesis(TransformationPass):
666
832
  # If all the above constraints hold, and it's already supported or the basis translator
667
833
  # can handle it, we'll leave it be.
668
834
  and (
669
- self._instruction_supported(node.name, qubits)
670
835
  # This uses unfortunately private details of `EquivalenceLibrary`, but so does the
671
836
  # `BasisTranslator`, and this is supposed to just be temporary til this is moved
672
837
  # into Rust space.
673
- or (
674
- self._equiv_lib is not None
675
- and equivalence.Key(name=node.name, num_qubits=node.num_qubits)
676
- in self._equiv_lib._key_to_node_index
677
- )
838
+ self._equiv_lib is not None
839
+ and equivalence.Key(name=node.name, num_qubits=node.num_qubits)
840
+ in self._equiv_lib.keys()
678
841
  )
679
842
  )
680
843