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
@@ -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, Qubit
31
+ from qiskit.circuit import ControlledGate, EquivalenceLibrary, equivalence
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
46
45
  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,161 +271,96 @@ 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())
276
274
  if self.qubits_initially_zero:
277
- tracker.set_clean(context.to_globals(qubits))
278
-
279
- out_dag = self._run(dag, tracker, context, use_ancillas=True, top_level=True)
280
- return out_dag
281
-
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.
275
+ clean, dirty = set(qubits), set()
276
+ else:
277
+ clean, dirty = set(), set(qubits)
301
278
 
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
- """
279
+ tracker = QubitTracker(qubits=qubits, clean=clean, dirty=dirty)
280
+ return self._run(dag, tracker)
307
281
 
308
- if dag.num_qubits() != context.num_qubits():
309
- raise TranspilerError("HighLevelSynthesis internal error.")
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
310
291
 
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.
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).
335
297
  synthesized_nodes = {}
336
298
 
337
299
  for node in dag.topological_op_nodes():
338
300
  qubits = tuple(dag.find_bit(q).index for q in node.qargs)
339
- processed = False
340
301
  synthesized = 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
302
+ used_qubits = None
354
303
 
355
304
  # check if synthesis for the operation can be skipped
356
- elif self._definitely_skip_node(node, qubits, dag):
357
- tracker.set_dirty(context.to_globals(qubits))
305
+ if self._definitely_skip_node(node, qubits, dag):
306
+ pass
358
307
 
359
308
  # next check control flow
360
309
  elif node.is_control_flow():
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,
310
+ dag.substitute_node(
311
+ node,
312
+ control_flow.map_blocks(partial(self._run, tracker=tracker.copy()), node.op),
313
+ propagate_condition=False,
371
314
  )
372
315
 
373
316
  # now we are free to synthesize
374
317
  else:
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
- )
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)
382
321
 
383
- # If the synthesis changed the operation (i.e. it is not None), store the result.
322
+ # if the synthesis changed the operation (i.e. it is not None), store the result
323
+ # and mark the operation qubits as used
384
324
  if synthesized is not None:
385
- synthesized_nodes[node._node_id] = (synthesized, synthesized_context)
325
+ synthesized_nodes[node] = (synthesized, used_qubits)
326
+ tracker.used(qubits) # assumes that auxiliary are returned in the same state
386
327
 
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))
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
390
337
 
391
- # We did not change anything just return the input.
338
+ # we did not change anything just return the input
392
339
  if len(synthesized_nodes) == 0:
393
- if dag.num_qubits() != context.num_qubits():
394
- raise TranspilerError("HighLevelSynthesis internal error.")
395
340
  return dag
396
341
 
397
- # STEP 3. We rebuild the DAG with new operations. Note that we could also
342
+ # Otherwise, we will rebuild with the new operations. Note that we could also
398
343
  # check if no operation changed in size and substitute in-place, but rebuilding is
399
344
  # generally as fast or faster, unless very few operations are changed.
400
345
  out = dag.copy_empty_like()
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()
346
+ index_to_qubit = dict(enumerate(dag.qubits))
408
347
 
409
348
  for node in dag.topological_op_nodes():
410
-
411
- if op_tuple := synthesized_nodes.get(node._node_id, None):
412
- op, op_context = op_tuple
413
-
349
+ if node in synthesized_nodes:
350
+ op, qubits = synthesized_nodes[node]
351
+ qargs = tuple(index_to_qubit[index] for index in qubits)
414
352
  if isinstance(op, Operation):
415
- out.apply_operation_back(op, node.qargs, node.cargs)
353
+ out.apply_operation_back(op, qargs, cargs=[])
416
354
  continue
417
355
 
418
356
  if isinstance(op, QuantumCircuit):
419
357
  op = circuit_to_dag(op, copy_operations=False)
420
358
 
421
- inner_to_global = op_context.to_global_mapping()
422
359
  if isinstance(op, DAGCircuit):
423
360
  qubit_map = {
424
- q: index_to_qubit[outer_to_local[inner_to_global[i]]]
425
- for (i, q) in enumerate(op.qubits)
361
+ qubit: index_to_qubit[index] for index, qubit in zip(qubits, op.qubits)
426
362
  }
427
363
  clbit_map = dict(zip(op.clbits, node.cargs))
428
-
429
364
  for sub_node in op.op_nodes():
430
365
  out.apply_operation_back(
431
366
  sub_node.op,
@@ -433,15 +368,11 @@ class HighLevelSynthesis(TransformationPass):
433
368
  tuple(clbit_map[carg] for carg in sub_node.cargs),
434
369
  )
435
370
  out.global_phase += op.global_phase
436
-
437
371
  else:
438
- raise TranspilerError(f"Unexpected synthesized type: {type(op)}")
372
+ raise RuntimeError(f"Unexpected synthesized type: {type(op)}")
439
373
  else:
440
374
  out.apply_operation_back(node.op, node.qargs, node.cargs, check=False)
441
375
 
442
- if out.num_qubits() != context.num_qubits():
443
- raise TranspilerError("HighLevelSynthesis internal error.")
444
-
445
376
  return out
446
377
 
447
378
  def _synthesize_operation(
@@ -449,23 +380,7 @@ class HighLevelSynthesis(TransformationPass):
449
380
  operation: Operation,
450
381
  qubits: tuple[int],
451
382
  tracker: QubitTracker,
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
-
383
+ ) -> tuple[QuantumCircuit | Operation | DAGCircuit | None, list[int] | None]:
469
384
  # Try to synthesize the operation. We'll go through the following options:
470
385
  # (1) Annotations: if the operator is annotated, synthesize the base operation
471
386
  # and then apply the modifiers. Returns a circuit (e.g. applying a power)
@@ -474,62 +389,31 @@ class HighLevelSynthesis(TransformationPass):
474
389
  # if the operation is a Clifford). Returns a circuit.
475
390
  # (3) Unrolling custom definitions: try defining the operation if it is not yet
476
391
  # in the set of supported instructions. Returns a circuit.
477
- #
478
392
  # If any of the above were triggered, we will recurse and go again through these steps
479
393
  # until no further change occurred. At this point, we convert circuits to DAGs (the final
480
394
  # possible return type). If there was no change, we just return ``None``.
481
- num_original_qubits = len(qubits)
482
- qubits = list(qubits)
483
-
484
395
  synthesized = None
485
396
 
486
397
  # Try synthesizing via AnnotatedOperation. This is faster than an isinstance check
487
398
  # but a bit less safe since someone could create operations with a ``modifiers`` attribute.
488
399
  if len(modifiers := getattr(operation, "modifiers", [])) > 0:
489
- # Note: the base operation must be synthesized without using potential control qubits
400
+ # The base operation must be synthesized without using potential control qubits
490
401
  # used in the modifiers.
491
402
  num_ctrl = sum(
492
403
  mod.num_ctrl_qubits for mod in modifiers if isinstance(mod, ControlModifier)
493
404
  )
494
405
  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
495
407
 
496
408
  # 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))
501
409
  synthesized_base_op, _ = self._synthesize_operation(
502
- operation.base_op,
503
- baseop_qubits,
504
- tracker,
505
- context,
506
- use_ancillas=use_ancillas,
410
+ operation.base_op, baseop_qubits, baseop_tracker
507
411
  )
508
-
509
412
  if synthesized_base_op is None:
510
413
  synthesized_base_op = operation.base_op
511
414
  elif isinstance(synthesized_base_op, DAGCircuit):
512
415
  synthesized_base_op = dag_to_circuit(synthesized_base_op)
513
416
 
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.
533
417
  synthesized = self._apply_annotations(synthesized_base_op, operation.modifiers)
534
418
 
535
419
  # If it was no AnnotatedOperation, try synthesizing via HLS or by unrolling.
@@ -537,106 +421,57 @@ class HighLevelSynthesis(TransformationPass):
537
421
  # Try synthesis via HLS -- which will return ``None`` if unsuccessful.
538
422
  indices = qubits if self._use_qubit_indices else None
539
423
  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
546
424
  synthesized = self._synthesize_op_using_plugins(
547
425
  hls_methods,
548
426
  operation,
549
427
  indices,
550
- num_clean_available,
551
- num_dirty_available,
428
+ tracker.num_clean(qubits),
429
+ tracker.num_dirty(qubits),
552
430
  )
553
431
 
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
-
569
432
  # If HLS did not apply, or was unsuccessful, try unrolling custom definitions.
570
433
  if synthesized is None and not self._top_level_only:
571
- synthesized = self._get_custom_definition(operation, indices)
434
+ synthesized = self._unroll_custom_definition(operation, indices)
572
435
 
573
436
  if synthesized is None:
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
- )
583
-
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
437
+ # if we didn't synthesize, there was nothing to unroll, so just set the used qubits
438
+ used_qubits = qubits
611
439
 
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:])
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()
629
445
  )
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
+ )
630
465
 
631
- else:
632
- raise TranspilerError(f"Unexpected synthesized type: {type(synthesized)}")
466
+ else:
467
+ raise RuntimeError(f"Unexpected synthesized type: {type(synthesized)}")
633
468
 
634
- if isinstance(synthesized, DAGCircuit) and synthesized_context is None:
635
- raise TranspilerError("HighLevelSynthesis internal error.")
469
+ if synthesized is not None and used_qubits is None:
470
+ raise RuntimeError("Failed to find qubit indices on", synthesized)
636
471
 
637
- return synthesized, synthesized_context
472
+ return synthesized, used_qubits
638
473
 
639
- def _get_custom_definition(
474
+ def _unroll_custom_definition(
640
475
  self, inst: Instruction, qubits: list[int] | None
641
476
  ) -> QuantumCircuit | None:
642
477
  # check if the operation is already supported natively
@@ -811,10 +646,9 @@ class HighLevelSynthesis(TransformationPass):
811
646
  node (which is _most_ nodes)."""
812
647
 
813
648
  if (
814
- dag._has_calibration_for(node)
649
+ dag.has_calibration_for(node)
815
650
  or len(node.qargs) < self._min_qubits
816
651
  or node.is_directive()
817
- or (self._instruction_supported(node.name, qubits) and not node.is_control_flow())
818
652
  ):
819
653
  return True
820
654
 
@@ -832,12 +666,15 @@ class HighLevelSynthesis(TransformationPass):
832
666
  # If all the above constraints hold, and it's already supported or the basis translator
833
667
  # can handle it, we'll leave it be.
834
668
  and (
669
+ self._instruction_supported(node.name, qubits)
835
670
  # This uses unfortunately private details of `EquivalenceLibrary`, but so does the
836
671
  # `BasisTranslator`, and this is supposed to just be temporary til this is moved
837
672
  # into Rust space.
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()
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
+ )
841
678
  )
842
679
  )
843
680