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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. qiskit/VERSION.txt +1 -1
  2. qiskit/__init__.py +27 -24
  3. qiskit/_accelerate.pyd +0 -0
  4. qiskit/_numpy_compat.py +1 -1
  5. qiskit/assembler/assemble_circuits.py +107 -64
  6. qiskit/assembler/assemble_schedules.py +5 -12
  7. qiskit/assembler/disassemble.py +10 -1
  8. qiskit/circuit/__init__.py +1 -1
  9. qiskit/circuit/_classical_resource_map.py +5 -5
  10. qiskit/circuit/_utils.py +0 -13
  11. qiskit/circuit/add_control.py +1 -1
  12. qiskit/circuit/annotated_operation.py +23 -1
  13. qiskit/circuit/classical/expr/expr.py +4 -4
  14. qiskit/circuit/classical/expr/visitors.py +1 -1
  15. qiskit/circuit/classical/types/__init__.py +1 -1
  16. qiskit/circuit/classical/types/types.py +2 -2
  17. qiskit/circuit/classicalfunction/boolean_expression.py +1 -1
  18. qiskit/circuit/classicalfunction/classical_function_visitor.py +5 -5
  19. qiskit/circuit/classicalfunction/utils.py +1 -1
  20. qiskit/circuit/classicalregister.py +1 -1
  21. qiskit/circuit/commutation_checker.py +83 -35
  22. qiskit/circuit/controlflow/_builder_utils.py +1 -1
  23. qiskit/circuit/controlflow/builder.py +10 -6
  24. qiskit/circuit/controlflow/if_else.py +2 -2
  25. qiskit/circuit/controlflow/switch_case.py +1 -1
  26. qiskit/circuit/delay.py +1 -1
  27. qiskit/circuit/duration.py +2 -2
  28. qiskit/circuit/equivalence.py +5 -7
  29. qiskit/circuit/gate.py +11 -8
  30. qiskit/circuit/instruction.py +31 -13
  31. qiskit/circuit/instructionset.py +2 -5
  32. qiskit/circuit/library/__init__.py +2 -1
  33. qiskit/circuit/library/arithmetic/linear_amplitude_function.py +1 -1
  34. qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +1 -1
  35. qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +1 -1
  36. qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +1 -1
  37. qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +3 -3
  38. qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py +1 -1
  39. qiskit/circuit/library/basis_change/__init__.py +1 -1
  40. qiskit/circuit/library/basis_change/qft.py +40 -6
  41. qiskit/circuit/library/blueprintcircuit.py +3 -5
  42. qiskit/circuit/library/data_preparation/__init__.py +9 -2
  43. qiskit/circuit/library/data_preparation/initializer.py +8 -0
  44. qiskit/circuit/library/data_preparation/state_preparation.py +98 -178
  45. qiskit/circuit/library/generalized_gates/isometry.py +8 -8
  46. qiskit/circuit/library/generalized_gates/linear_function.py +3 -2
  47. qiskit/circuit/library/generalized_gates/mcg_up_to_diagonal.py +4 -4
  48. qiskit/circuit/library/generalized_gates/permutation.py +8 -9
  49. qiskit/circuit/library/generalized_gates/uc.py +3 -3
  50. qiskit/circuit/library/generalized_gates/uc_pauli_rot.py +2 -2
  51. qiskit/circuit/library/generalized_gates/unitary.py +13 -11
  52. qiskit/circuit/library/graph_state.py +1 -1
  53. qiskit/circuit/library/hamiltonian_gate.py +1 -2
  54. qiskit/circuit/library/hidden_linear_function.py +1 -1
  55. qiskit/circuit/library/n_local/evolved_operator_ansatz.py +3 -2
  56. qiskit/circuit/library/n_local/n_local.py +4 -5
  57. qiskit/circuit/library/n_local/pauli_two_design.py +1 -1
  58. qiskit/circuit/library/n_local/qaoa_ansatz.py +6 -8
  59. qiskit/circuit/library/n_local/two_local.py +1 -1
  60. qiskit/circuit/library/overlap.py +11 -5
  61. qiskit/circuit/library/pauli_evolution.py +7 -3
  62. qiskit/circuit/library/standard_gates/dcx.py +3 -0
  63. qiskit/circuit/library/standard_gates/ecr.py +3 -0
  64. qiskit/circuit/library/standard_gates/global_phase.py +3 -0
  65. qiskit/circuit/library/standard_gates/h.py +13 -5
  66. qiskit/circuit/library/standard_gates/i.py +3 -0
  67. qiskit/circuit/library/standard_gates/iswap.py +3 -0
  68. qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +19 -10
  69. qiskit/circuit/library/standard_gates/p.py +14 -9
  70. qiskit/circuit/library/standard_gates/r.py +3 -0
  71. qiskit/circuit/library/standard_gates/rx.py +21 -6
  72. qiskit/circuit/library/standard_gates/rxx.py +40 -1
  73. qiskit/circuit/library/standard_gates/ry.py +21 -6
  74. qiskit/circuit/library/standard_gates/ryy.py +40 -1
  75. qiskit/circuit/library/standard_gates/rz.py +22 -6
  76. qiskit/circuit/library/standard_gates/rzx.py +40 -1
  77. qiskit/circuit/library/standard_gates/rzz.py +41 -2
  78. qiskit/circuit/library/standard_gates/s.py +77 -0
  79. qiskit/circuit/library/standard_gates/swap.py +12 -5
  80. qiskit/circuit/library/standard_gates/sx.py +14 -5
  81. qiskit/circuit/library/standard_gates/t.py +5 -0
  82. qiskit/circuit/library/standard_gates/u.py +22 -7
  83. qiskit/circuit/library/standard_gates/u1.py +8 -3
  84. qiskit/circuit/library/standard_gates/u2.py +3 -0
  85. qiskit/circuit/library/standard_gates/u3.py +22 -7
  86. qiskit/circuit/library/standard_gates/x.py +156 -92
  87. qiskit/circuit/library/standard_gates/xx_minus_yy.py +40 -1
  88. qiskit/circuit/library/standard_gates/xx_plus_yy.py +52 -11
  89. qiskit/circuit/library/standard_gates/y.py +6 -1
  90. qiskit/circuit/library/standard_gates/z.py +8 -1
  91. qiskit/circuit/operation.py +1 -1
  92. qiskit/circuit/parameter.py +9 -10
  93. qiskit/circuit/parameterexpression.py +16 -13
  94. qiskit/circuit/parametertable.py +1 -190
  95. qiskit/circuit/parametervector.py +1 -1
  96. qiskit/circuit/quantumcircuit.py +392 -384
  97. qiskit/circuit/quantumcircuitdata.py +3 -5
  98. qiskit/circuit/quantumregister.py +1 -1
  99. qiskit/circuit/random/__init__.py +1 -1
  100. qiskit/circuit/random/utils.py +175 -26
  101. qiskit/circuit/register.py +5 -7
  102. qiskit/circuit/singleton.py +3 -3
  103. qiskit/circuit/tools/pi_check.py +4 -4
  104. qiskit/compiler/assembler.py +95 -24
  105. qiskit/compiler/scheduler.py +2 -2
  106. qiskit/compiler/transpiler.py +41 -127
  107. qiskit/converters/circuit_to_dag.py +4 -6
  108. qiskit/converters/circuit_to_gate.py +4 -8
  109. qiskit/converters/circuit_to_instruction.py +5 -17
  110. qiskit/converters/dag_to_circuit.py +2 -6
  111. qiskit/dagcircuit/collect_blocks.py +2 -2
  112. qiskit/dagcircuit/dagcircuit.py +190 -187
  113. qiskit/dagcircuit/dagdependency.py +4 -4
  114. qiskit/dagcircuit/dagdependency_v2.py +4 -4
  115. qiskit/dagcircuit/dagdepnode.py +1 -1
  116. qiskit/dagcircuit/dagnode.py +66 -157
  117. qiskit/passmanager/flow_controllers.py +1 -1
  118. qiskit/passmanager/passmanager.py +3 -3
  119. qiskit/primitives/__init__.py +1 -5
  120. qiskit/primitives/backend_estimator.py +25 -15
  121. qiskit/primitives/backend_estimator_v2.py +31 -7
  122. qiskit/primitives/backend_sampler.py +21 -12
  123. qiskit/primitives/backend_sampler_v2.py +12 -3
  124. qiskit/primitives/base/base_estimator.py +31 -4
  125. qiskit/primitives/base/base_primitive.py +2 -2
  126. qiskit/primitives/base/base_result.py +2 -2
  127. qiskit/primitives/base/base_sampler.py +26 -2
  128. qiskit/primitives/base/estimator_result.py +2 -2
  129. qiskit/primitives/base/sampler_result.py +2 -2
  130. qiskit/primitives/containers/__init__.py +0 -1
  131. qiskit/primitives/containers/bindings_array.py +2 -2
  132. qiskit/primitives/containers/bit_array.py +108 -10
  133. qiskit/primitives/containers/shape.py +3 -3
  134. qiskit/primitives/estimator.py +9 -2
  135. qiskit/primitives/primitive_job.py +1 -1
  136. qiskit/primitives/sampler.py +10 -3
  137. qiskit/primitives/statevector_estimator.py +5 -3
  138. qiskit/primitives/statevector_sampler.py +11 -5
  139. qiskit/primitives/utils.py +16 -0
  140. qiskit/providers/backend.py +15 -6
  141. qiskit/providers/backend_compat.py +7 -4
  142. qiskit/providers/basic_provider/basic_provider_tools.py +1 -1
  143. qiskit/providers/basic_provider/basic_simulator.py +32 -24
  144. qiskit/providers/fake_provider/fake_backend.py +10 -3
  145. qiskit/providers/fake_provider/fake_openpulse_2q.py +154 -146
  146. qiskit/providers/fake_provider/fake_openpulse_3q.py +226 -217
  147. qiskit/providers/fake_provider/fake_qasm_backend.py +5 -1
  148. qiskit/providers/fake_provider/generic_backend_v2.py +80 -50
  149. qiskit/providers/models/__init__.py +11 -0
  150. qiskit/providers/models/backendconfiguration.py +50 -4
  151. qiskit/providers/models/backendproperties.py +13 -2
  152. qiskit/providers/models/pulsedefaults.py +10 -11
  153. qiskit/providers/options.py +13 -13
  154. qiskit/providers/providerutils.py +3 -1
  155. qiskit/pulse/configuration.py +8 -12
  156. qiskit/pulse/instruction_schedule_map.py +3 -5
  157. qiskit/pulse/instructions/acquire.py +7 -8
  158. qiskit/pulse/instructions/instruction.py +2 -3
  159. qiskit/pulse/library/samplers/decorators.py +5 -9
  160. qiskit/pulse/library/symbolic_pulses.py +4 -7
  161. qiskit/pulse/library/waveform.py +2 -5
  162. qiskit/pulse/macros.py +11 -6
  163. qiskit/pulse/parser.py +8 -10
  164. qiskit/pulse/schedule.py +9 -17
  165. qiskit/pulse/transforms/alignments.py +1 -3
  166. qiskit/pulse/utils.py +1 -2
  167. qiskit/qasm/libs/stdgates.inc +35 -28
  168. qiskit/qasm2/__init__.py +7 -7
  169. qiskit/qasm2/export.py +5 -9
  170. qiskit/qasm2/parse.py +1 -1
  171. qiskit/qasm3/ast.py +9 -25
  172. qiskit/qasm3/exporter.py +578 -481
  173. qiskit/qasm3/printer.py +7 -16
  174. qiskit/qobj/common.py +10 -0
  175. qiskit/qobj/converters/lo_config.py +9 -0
  176. qiskit/qobj/converters/pulse_instruction.py +13 -6
  177. qiskit/qobj/pulse_qobj.py +69 -15
  178. qiskit/qobj/qasm_qobj.py +72 -20
  179. qiskit/qobj/utils.py +9 -0
  180. qiskit/qpy/binary_io/circuits.py +8 -5
  181. qiskit/qpy/binary_io/schedules.py +1 -1
  182. qiskit/qpy/binary_io/value.py +3 -3
  183. qiskit/qpy/interface.py +3 -2
  184. qiskit/qpy/type_keys.py +2 -2
  185. qiskit/quantum_info/operators/channel/quantum_channel.py +3 -6
  186. qiskit/quantum_info/operators/channel/superop.py +2 -2
  187. qiskit/quantum_info/operators/channel/transformations.py +1 -1
  188. qiskit/quantum_info/operators/dihedral/dihedral.py +3 -4
  189. qiskit/quantum_info/operators/dihedral/dihedral_circuits.py +1 -3
  190. qiskit/quantum_info/operators/dihedral/random.py +6 -3
  191. qiskit/quantum_info/operators/measures.py +2 -2
  192. qiskit/quantum_info/operators/op_shape.py +12 -20
  193. qiskit/quantum_info/operators/operator.py +14 -21
  194. qiskit/quantum_info/operators/predicates.py +1 -0
  195. qiskit/quantum_info/operators/symplectic/base_pauli.py +7 -11
  196. qiskit/quantum_info/operators/symplectic/clifford.py +1 -1
  197. qiskit/quantum_info/operators/symplectic/pauli.py +3 -3
  198. qiskit/quantum_info/operators/symplectic/pauli_list.py +9 -10
  199. qiskit/quantum_info/operators/symplectic/random.py +1 -1
  200. qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +14 -16
  201. qiskit/quantum_info/quaternion.py +1 -1
  202. qiskit/quantum_info/states/densitymatrix.py +5 -8
  203. qiskit/quantum_info/states/stabilizerstate.py +128 -37
  204. qiskit/quantum_info/states/statevector.py +4 -8
  205. qiskit/result/counts.py +2 -2
  206. qiskit/result/mitigation/correlated_readout_mitigator.py +2 -2
  207. qiskit/result/mitigation/local_readout_mitigator.py +2 -2
  208. qiskit/result/mitigation/utils.py +1 -3
  209. qiskit/result/models.py +17 -16
  210. qiskit/result/result.py +15 -20
  211. qiskit/scheduler/lowering.py +2 -2
  212. qiskit/synthesis/__init__.py +2 -1
  213. qiskit/synthesis/clifford/__init__.py +1 -1
  214. qiskit/synthesis/clifford/clifford_decompose_ag.py +2 -2
  215. qiskit/synthesis/clifford/clifford_decompose_bm.py +10 -240
  216. qiskit/synthesis/clifford/clifford_decompose_greedy.py +9 -303
  217. qiskit/synthesis/clifford/clifford_decompose_layers.py +25 -23
  218. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_full.py +1 -1
  219. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_general.py +1 -1
  220. qiskit/synthesis/discrete_basis/generate_basis_approximations.py +1 -1
  221. qiskit/synthesis/discrete_basis/solovay_kitaev.py +2 -2
  222. qiskit/synthesis/evolution/evolution_synthesis.py +4 -2
  223. qiskit/synthesis/evolution/lie_trotter.py +46 -19
  224. qiskit/synthesis/evolution/product_formula.py +111 -55
  225. qiskit/synthesis/evolution/qdrift.py +40 -10
  226. qiskit/synthesis/evolution/suzuki_trotter.py +43 -33
  227. qiskit/synthesis/linear/__init__.py +1 -0
  228. qiskit/synthesis/linear/cnot_synth.py +22 -96
  229. qiskit/synthesis/linear/linear_depth_lnn.py +8 -8
  230. qiskit/synthesis/linear/linear_matrix_utils.py +13 -161
  231. qiskit/synthesis/linear_phase/cnot_phase_synth.py +1 -1
  232. qiskit/synthesis/linear_phase/cx_cz_depth_lnn.py +3 -3
  233. qiskit/synthesis/linear_phase/cz_depth_lnn.py +1 -1
  234. qiskit/synthesis/one_qubit/one_qubit_decompose.py +29 -29
  235. qiskit/synthesis/permutation/permutation_full.py +5 -29
  236. qiskit/synthesis/permutation/permutation_lnn.py +2 -24
  237. qiskit/synthesis/permutation/permutation_utils.py +2 -59
  238. qiskit/synthesis/qft/__init__.py +1 -0
  239. qiskit/synthesis/qft/qft_decompose_full.py +79 -0
  240. qiskit/synthesis/qft/qft_decompose_lnn.py +17 -9
  241. qiskit/synthesis/stabilizer/stabilizer_circuit.py +6 -6
  242. qiskit/synthesis/stabilizer/stabilizer_decompose.py +2 -2
  243. qiskit/synthesis/two_qubit/local_invariance.py +8 -38
  244. qiskit/synthesis/two_qubit/two_qubit_decompose.py +48 -129
  245. qiskit/synthesis/unitary/aqc/cnot_structures.py +1 -1
  246. qiskit/synthesis/unitary/qsd.py +5 -3
  247. qiskit/transpiler/__init__.py +1 -0
  248. qiskit/transpiler/basepasses.py +1 -1
  249. qiskit/transpiler/coupling.py +3 -3
  250. qiskit/transpiler/instruction_durations.py +1 -2
  251. qiskit/transpiler/layout.py +3 -3
  252. qiskit/transpiler/passes/__init__.py +2 -0
  253. qiskit/transpiler/passes/basis/basis_translator.py +82 -63
  254. qiskit/transpiler/passes/basis/translate_parameterized.py +3 -5
  255. qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
  256. qiskit/transpiler/passes/basis/unroll_custom_definitions.py +10 -10
  257. qiskit/transpiler/passes/calibration/rx_builder.py +3 -3
  258. qiskit/transpiler/passes/calibration/rzx_builder.py +3 -3
  259. qiskit/transpiler/passes/layout/apply_layout.py +13 -3
  260. qiskit/transpiler/passes/layout/sabre_layout.py +10 -8
  261. qiskit/transpiler/passes/layout/sabre_pre_layout.py +4 -1
  262. qiskit/transpiler/passes/layout/set_layout.py +2 -2
  263. qiskit/transpiler/passes/layout/vf2_layout.py +1 -1
  264. qiskit/transpiler/passes/layout/vf2_utils.py +3 -3
  265. qiskit/transpiler/passes/optimization/__init__.py +1 -0
  266. qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +2 -2
  267. qiskit/transpiler/passes/optimization/commutation_analysis.py +7 -10
  268. qiskit/transpiler/passes/optimization/commutative_cancellation.py +35 -19
  269. qiskit/transpiler/passes/optimization/consolidate_blocks.py +11 -8
  270. qiskit/transpiler/passes/optimization/inverse_cancellation.py +6 -6
  271. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +64 -41
  272. qiskit/transpiler/passes/optimization/optimize_1q_gates.py +1 -1
  273. qiskit/transpiler/passes/optimization/split_2q_unitaries.py +83 -0
  274. qiskit/transpiler/passes/optimization/template_matching/backward_match.py +1 -1
  275. qiskit/transpiler/passes/optimization/template_matching/forward_match.py +2 -2
  276. qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +1 -1
  277. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +3 -2
  278. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +1 -1
  279. qiskit/transpiler/passes/routing/layout_transformation.py +2 -1
  280. qiskit/transpiler/passes/routing/sabre_swap.py +35 -26
  281. qiskit/transpiler/passes/routing/star_prerouting.py +80 -105
  282. qiskit/transpiler/passes/routing/stochastic_swap.py +1 -3
  283. qiskit/transpiler/passes/scheduling/alap.py +1 -2
  284. qiskit/transpiler/passes/scheduling/alignments/__init__.py +2 -2
  285. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
  286. qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +1 -1
  287. qiskit/transpiler/passes/scheduling/alignments/reschedule.py +1 -1
  288. qiskit/transpiler/passes/scheduling/asap.py +1 -2
  289. qiskit/transpiler/passes/scheduling/base_scheduler.py +5 -5
  290. qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +3 -3
  291. qiskit/transpiler/passes/scheduling/padding/base_padding.py +1 -1
  292. qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +11 -11
  293. qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +7 -6
  294. qiskit/transpiler/passes/scheduling/time_unit_conversion.py +4 -3
  295. qiskit/transpiler/passes/synthesis/high_level_synthesis.py +211 -36
  296. qiskit/transpiler/passes/synthesis/plugin.py +2 -2
  297. qiskit/transpiler/passes/synthesis/unitary_synthesis.py +80 -40
  298. qiskit/transpiler/passes/utils/__init__.py +0 -1
  299. qiskit/transpiler/passes/utils/check_gate_direction.py +4 -4
  300. qiskit/transpiler/passes/utils/check_map.py +3 -6
  301. qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +3 -4
  302. qiskit/transpiler/passes/utils/error.py +2 -2
  303. qiskit/transpiler/passes/utils/fixed_point.py +3 -3
  304. qiskit/transpiler/passes/utils/gate_direction.py +1 -1
  305. qiskit/transpiler/passes/utils/gates_basis.py +1 -2
  306. qiskit/transpiler/passmanager.py +7 -6
  307. qiskit/transpiler/preset_passmanagers/__init__.py +4 -228
  308. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +117 -18
  309. qiskit/transpiler/preset_passmanagers/common.py +3 -6
  310. qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +518 -0
  311. qiskit/transpiler/preset_passmanagers/level0.py +1 -1
  312. qiskit/transpiler/target.py +27 -8
  313. qiskit/user_config.py +29 -6
  314. qiskit/utils/classtools.py +3 -3
  315. qiskit/utils/deprecation.py +3 -2
  316. qiskit/utils/lazy_tester.py +2 -2
  317. qiskit/utils/optionals.py +8 -8
  318. qiskit/visualization/bloch.py +19 -67
  319. qiskit/visualization/circuit/_utils.py +34 -10
  320. qiskit/visualization/circuit/circuit_visualization.py +23 -16
  321. qiskit/visualization/circuit/latex.py +29 -27
  322. qiskit/visualization/circuit/matplotlib.py +4 -2
  323. qiskit/visualization/circuit/qcstyle.py +2 -2
  324. qiskit/visualization/circuit/text.py +9 -15
  325. qiskit/visualization/dag_visualization.py +5 -12
  326. qiskit/visualization/pulse_v2/core.py +1 -1
  327. qiskit/visualization/pulse_v2/events.py +1 -1
  328. qiskit/visualization/pulse_v2/generators/frame.py +3 -4
  329. qiskit/visualization/pulse_v2/generators/waveform.py +5 -9
  330. qiskit/visualization/pulse_v2/layouts.py +1 -5
  331. qiskit/visualization/pulse_v2/plotters/matplotlib.py +1 -2
  332. qiskit/visualization/state_visualization.py +5 -6
  333. qiskit/visualization/timeline/plotters/matplotlib.py +1 -2
  334. qiskit/visualization/transition_visualization.py +7 -2
  335. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/METADATA +26 -26
  336. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/RECORD +340 -338
  337. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/WHEEL +1 -1
  338. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/entry_points.txt +3 -0
  339. qiskit/transpiler/passes/utils/block_to_matrix.py +0 -47
  340. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/LICENSE.txt +0 -0
  341. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/top_level.txt +0 -0
@@ -33,6 +33,7 @@ from qiskit.circuit.library.standard_gates import (
33
33
  XGate,
34
34
  )
35
35
  from qiskit.circuit import Qubit
36
+ from qiskit.circuit.quantumcircuitdata import CircuitInstruction
36
37
  from qiskit.dagcircuit.dagcircuit import DAGCircuit
37
38
  from qiskit.dagcircuit.dagnode import DAGOpNode
38
39
 
@@ -110,16 +111,7 @@ class Optimize1qGatesDecomposition(TransformationPass):
110
111
  else:
111
112
  return None
112
113
 
113
- def _resynthesize_run(self, matrix, qubit=None):
114
- """
115
- Re-synthesizes one 2x2 `matrix`, typically extracted via `dag.collect_1q_runs`.
116
-
117
- Returns the newly synthesized circuit in the indicated basis, or None
118
- if no synthesis routine applied.
119
-
120
- When multiple synthesis options are available, it prefers the one with the lowest
121
- error when the circuit is applied to `qubit`.
122
- """
114
+ def _get_decomposer(self, qubit=None):
123
115
  # include path for when target exists but target.num_qubits is None (BasicSimulator)
124
116
  if self._target is not None and self._target.num_qubits is not None:
125
117
  if qubit is not None:
@@ -133,6 +125,19 @@ class Optimize1qGatesDecomposition(TransformationPass):
133
125
  decomposers = _possible_decomposers(available_1q_basis)
134
126
  else:
135
127
  decomposers = self._global_decomposers
128
+ return decomposers
129
+
130
+ def _resynthesize_run(self, matrix, qubit=None):
131
+ """
132
+ Re-synthesizes one 2x2 `matrix`, typically extracted via `dag.collect_1q_runs`.
133
+
134
+ Returns the newly synthesized circuit in the indicated basis, or None
135
+ if no synthesis routine applied.
136
+
137
+ When multiple synthesis options are available, it prefers the one with the lowest
138
+ error when the circuit is applied to `qubit`.
139
+ """
140
+ decomposers = self._get_decomposer(qubit)
136
141
 
137
142
  best_synth_circuit = euler_one_qubit_decomposer.unitary_to_gate_sequence(
138
143
  matrix,
@@ -149,10 +154,13 @@ class Optimize1qGatesDecomposition(TransformationPass):
149
154
  out_dag.global_phase = best_synth_circuit.global_phase
150
155
 
151
156
  for gate_name, angles in best_synth_circuit:
152
- out_dag.apply_operation_back(NAME_MAP[gate_name](*angles), qubits, check=False)
157
+ op = CircuitInstruction.from_standard(gate_name, qubits, angles)
158
+ out_dag.apply_operation_back(op.operation, qubits, check=False)
153
159
  return out_dag
154
160
 
155
- def _substitution_checks(self, dag, old_run, new_circ, basis, qubit):
161
+ def _substitution_checks(
162
+ self, dag, old_run, new_circ, basis, qubit, old_error=None, new_error=None
163
+ ):
156
164
  """
157
165
  Returns `True` when it is recommended to replace `old_run` with `new_circ` over `basis`.
158
166
  """
@@ -176,11 +184,14 @@ class Optimize1qGatesDecomposition(TransformationPass):
176
184
  # if we're outside of the basis set, we're obligated to logically decompose.
177
185
  # if we're outside of the set of gates for which we have physical definitions,
178
186
  # then we _try_ to decompose, using the results if we see improvement.
179
- new_error = 0.0
180
- old_error = 0.0
181
187
  if not uncalibrated_and_not_basis_p:
182
- new_error = self._error(new_circ, qubit)
183
- old_error = self._error(old_run, qubit)
188
+ if new_error is None:
189
+ new_error = self._error(new_circ, qubit)
190
+ if old_error is None:
191
+ old_error = self._error(old_run, qubit)
192
+ else:
193
+ new_error = 0.0
194
+ old_error = 0.0
184
195
 
185
196
  return (
186
197
  uncalibrated_and_not_basis_p
@@ -198,32 +209,47 @@ class Optimize1qGatesDecomposition(TransformationPass):
198
209
  Returns:
199
210
  DAGCircuit: the optimized DAG.
200
211
  """
201
- runs = dag.collect_1q_runs()
202
- for run in runs:
212
+ runs = []
213
+ qubits = []
214
+ bases = []
215
+ for run in dag.collect_1q_runs():
203
216
  qubit = dag.find_bit(run[0].qargs[0]).index
204
- operator = run[0].op.to_matrix()
205
- for node in run[1:]:
206
- operator = node.op.to_matrix().dot(operator)
207
- best_circuit_sequence = self._resynthesize_run(operator, qubit)
208
-
217
+ runs.append(run)
218
+ qubits.append(qubit)
219
+ bases.append(self._get_decomposer(qubit))
220
+ best_sequences = euler_one_qubit_decomposer.optimize_1q_gates_decomposition(
221
+ runs, qubits, bases, simplify=True, error_map=self.error_map
222
+ )
223
+ for index, best_circuit_sequence in enumerate(best_sequences):
224
+ run = runs[index]
225
+ qubit = qubits[index]
209
226
  if self._target is None:
210
227
  basis = self._basis_gates
211
228
  else:
212
229
  basis = self._target.operation_names_for_qargs((qubit,))
213
-
214
- if best_circuit_sequence is not None and self._substitution_checks(
215
- dag, run, best_circuit_sequence, basis, qubit
216
- ):
217
- for gate_name, angles in best_circuit_sequence:
218
- op = NAME_MAP[gate_name](*angles)
219
- node = DAGOpNode(NAME_MAP[gate_name](*angles), run[0].qargs, dag=dag)
220
- node._node_id = dag._multi_graph.add_node(node)
221
- dag._increment_op(op)
222
- dag._multi_graph.insert_node_on_in_edges(node._node_id, run[0]._node_id)
223
- dag.global_phase += best_circuit_sequence.global_phase
224
- # Delete the other nodes in the run
225
- for current_node in run:
226
- dag.remove_op_node(current_node)
230
+ if best_circuit_sequence is not None:
231
+ (old_error, new_error, best_circuit_sequence) = best_circuit_sequence
232
+ if self._substitution_checks(
233
+ dag,
234
+ run,
235
+ best_circuit_sequence,
236
+ basis,
237
+ qubit,
238
+ old_error=old_error,
239
+ new_error=new_error,
240
+ ):
241
+ first_node_id = run[0]._node_id
242
+ qubit = run[0].qargs
243
+ for gate, angles in best_circuit_sequence:
244
+ op = CircuitInstruction.from_standard(gate, qubit, angles)
245
+ node = DAGOpNode.from_instruction(op, dag=dag)
246
+ node._node_id = dag._multi_graph.add_node(node)
247
+ dag._increment_op(gate.name)
248
+ dag._multi_graph.insert_node_on_in_edges(node._node_id, first_node_id)
249
+ dag.global_phase += best_circuit_sequence.global_phase
250
+ # Delete the other nodes in the run
251
+ for current_node in run:
252
+ dag.remove_op_node(current_node)
227
253
 
228
254
  return dag
229
255
 
@@ -241,10 +267,7 @@ class Optimize1qGatesDecomposition(TransformationPass):
241
267
  circuit, qubit, self.error_map
242
268
  )
243
269
  else:
244
- circuit_list = [(x.op.name, []) for x in circuit]
245
- return euler_one_qubit_decomposer.compute_error_list(
246
- circuit_list, qubit, self.error_map
247
- )
270
+ return euler_one_qubit_decomposer.compute_error_list(circuit, qubit, self.error_map)
248
271
 
249
272
 
250
273
  def _possible_decomposers(basis_set):
@@ -308,7 +308,7 @@ class Optimize1qGates(TransformationPass):
308
308
  if "u3" in self.basis:
309
309
  new_op = U3Gate(*right_parameters)
310
310
  else:
311
- raise TranspilerError("It was not possible to use the basis %s" % self.basis)
311
+ raise TranspilerError(f"It was not possible to use the basis {self.basis}")
312
312
 
313
313
  dag.global_phase += right_global_phase
314
314
 
@@ -0,0 +1,83 @@
1
+ # This code is part of Qiskit.
2
+ #
3
+ # (C) Copyright IBM 2017, 2024.
4
+ #
5
+ # This code is licensed under the Apache License, Version 2.0. You may
6
+ # obtain a copy of this license in the LICENSE.txt file in the root directory
7
+ # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8
+ #
9
+ # Any modifications or derivative works of this code must retain this
10
+ # copyright notice, and modified files need to carry a notice indicating
11
+ # that they have been altered from the originals.
12
+ """Splits each two-qubit gate in the `dag` into two single-qubit gates, if possible without error."""
13
+ from typing import Optional
14
+
15
+ from qiskit.transpiler.basepasses import TransformationPass
16
+ from qiskit.circuit.quantumcircuitdata import CircuitInstruction
17
+ from qiskit.dagcircuit.dagcircuit import DAGCircuit, DAGOpNode
18
+ from qiskit.circuit.library.generalized_gates import UnitaryGate
19
+ from qiskit.synthesis.two_qubit.two_qubit_decompose import TwoQubitWeylDecomposition
20
+
21
+
22
+ class Split2QUnitaries(TransformationPass):
23
+ """Attempt to splits two-qubit gates in a :class:`.DAGCircuit` into two single-qubit gates
24
+
25
+ This pass will analyze all the two qubit gates in the circuit and analyze the gate's unitary
26
+ matrix to determine if the gate is actually a product of 2 single qubit gates. In these
27
+ cases the 2q gate can be simplified into two single qubit gates and this pass will
28
+ perform this optimization and will replace the two qubit gate with two single qubit
29
+ :class:`.UnitaryGate`.
30
+ """
31
+
32
+ def __init__(self, fidelity: Optional[float] = 1.0 - 1e-16):
33
+ """Split2QUnitaries initializer.
34
+
35
+ Args:
36
+ fidelity (float): Allowed tolerance for splitting two-qubit unitaries and gate decompositions
37
+ """
38
+ super().__init__()
39
+ self.requested_fidelity = fidelity
40
+
41
+ def run(self, dag: DAGCircuit):
42
+ """Run the Split2QUnitaries pass on `dag`."""
43
+ for node in dag.topological_op_nodes():
44
+ # skip operations without two-qubits and for which we can not determine a potential 1q split
45
+ if (
46
+ len(node.cargs) > 0
47
+ or len(node.qargs) != 2
48
+ or node.matrix is None
49
+ or node.is_parameterized()
50
+ ):
51
+ continue
52
+
53
+ decomp = TwoQubitWeylDecomposition(node.op, fidelity=self.requested_fidelity)
54
+ if (
55
+ decomp._inner_decomposition.specialization
56
+ == TwoQubitWeylDecomposition._specializations.IdEquiv
57
+ ):
58
+ new_dag = DAGCircuit()
59
+ new_dag.add_qubits(node.qargs)
60
+
61
+ ur = decomp.K1r
62
+ ur_node = DAGOpNode.from_instruction(
63
+ CircuitInstruction(UnitaryGate(ur), qubits=(node.qargs[0],)), dag=new_dag
64
+ )
65
+
66
+ ul = decomp.K1l
67
+ ul_node = DAGOpNode.from_instruction(
68
+ CircuitInstruction(UnitaryGate(ul), qubits=(node.qargs[1],)), dag=new_dag
69
+ )
70
+ new_dag._apply_op_node_back(ur_node)
71
+ new_dag._apply_op_node_back(ul_node)
72
+ new_dag.global_phase = decomp.global_phase
73
+ dag.substitute_node_with_dag(node, new_dag)
74
+ elif (
75
+ decomp._inner_decomposition.specialization
76
+ == TwoQubitWeylDecomposition._specializations.SWAPEquiv
77
+ ):
78
+ # TODO maybe also look into swap-gate-like gates? Things to consider:
79
+ # * As the qubit mapping may change, we'll always need to build a new dag in this pass
80
+ # * There may not be many swap-gate-like gates in an arbitrary input circuit
81
+ # * Removing swap gates from a user-routed input circuit here is unexpected
82
+ pass
83
+ return dag
@@ -622,7 +622,7 @@ class BackwardMatch:
622
622
  )
623
623
  self.matching_list.append_scenario(new_matching_scenario)
624
624
 
625
- # Third option: if blocking the succesors breaks a match, we consider
625
+ # Third option: if blocking the successors breaks a match, we consider
626
626
  # also the possibility to block all predecessors (push the gate to the left).
627
627
  if broken_matches and all(global_broken):
628
628
 
@@ -138,8 +138,8 @@ class ForwardMatch:
138
138
  """
139
139
  matches = []
140
140
 
141
- for i in range(0, len(self.match)):
142
- matches.append(self.match[i][0])
141
+ for match in self.match:
142
+ matches.append(match[0])
143
143
 
144
144
  pred = matches.copy()
145
145
  if len(pred) > 1:
@@ -507,7 +507,7 @@ class TemplateSubstitution:
507
507
  to_native_symbolic = lambda x: x
508
508
 
509
509
  circuit_params, template_params = [], []
510
- # Set of all parameter names that are present in the circuits to be optimised.
510
+ # Set of all parameter names that are present in the circuits to be optimized.
511
511
  circuit_params_set = set()
512
512
 
513
513
  template_dag_dep = copy.deepcopy(self.template_dag_dep)
@@ -17,8 +17,9 @@ from collections import defaultdict
17
17
  from qiskit.circuit import Gate, QuantumCircuit, Qubit
18
18
  from qiskit.converters import circuit_to_dag
19
19
  from qiskit.dagcircuit import DAGCircuit, DAGOpNode
20
- from qiskit.transpiler import TransformationPass, Layout, TranspilerError
21
-
20
+ from qiskit.transpiler.basepasses import TransformationPass
21
+ from qiskit.transpiler.exceptions import TranspilerError
22
+ from qiskit.transpiler.layout import Layout
22
23
  from qiskit.transpiler.passes.routing.commuting_2q_gate_routing.swap_strategy import SwapStrategy
23
24
  from qiskit.transpiler.passes.routing.commuting_2q_gate_routing.commuting_2q_block import (
24
25
  Commuting2qBlock,
@@ -17,7 +17,7 @@ import copy
17
17
  import numpy as np
18
18
 
19
19
  from qiskit.exceptions import QiskitError
20
- from qiskit.transpiler import CouplingMap
20
+ from qiskit.transpiler.coupling import CouplingMap
21
21
 
22
22
 
23
23
  class SwapStrategy:
@@ -15,9 +15,10 @@ from __future__ import annotations
15
15
 
16
16
  import numpy as np
17
17
 
18
- from qiskit.transpiler import Layout, CouplingMap
19
18
  from qiskit.transpiler.basepasses import TransformationPass
19
+ from qiskit.transpiler.coupling import CouplingMap
20
20
  from qiskit.transpiler.exceptions import TranspilerError
21
+ from qiskit.transpiler.layout import Layout
21
22
  from qiskit.transpiler.passes.routing.algorithms import ApproximateTokenSwapper
22
23
  from qiskit.transpiler.target import Target
23
24
 
@@ -18,7 +18,7 @@ import time
18
18
 
19
19
  import rustworkx
20
20
 
21
- from qiskit.circuit import SwitchCaseOp, ControlFlowOp, Clbit, ClassicalRegister
21
+ from qiskit.circuit import SwitchCaseOp, Clbit, ClassicalRegister
22
22
  from qiskit.circuit.library.standard_gates import SwapGate
23
23
  from qiskit.circuit.controlflow import condition_resources, node_resources
24
24
  from qiskit.converters import dag_to_circuit
@@ -28,15 +28,10 @@ from qiskit.transpiler.exceptions import TranspilerError
28
28
  from qiskit.transpiler.layout import Layout
29
29
  from qiskit.transpiler.target import Target
30
30
  from qiskit.transpiler.passes.layout import disjoint_utils
31
- from qiskit.dagcircuit import DAGCircuit
31
+ from qiskit.dagcircuit import DAGCircuit, DAGOpNode
32
32
  from qiskit.utils.parallel import CPU_COUNT
33
33
 
34
- from qiskit._accelerate.sabre import (
35
- sabre_routing,
36
- Heuristic,
37
- NeighborTable,
38
- SabreDAG,
39
- )
34
+ from qiskit._accelerate.sabre import sabre_routing, Heuristic, SetScaling, NeighborTable, SabreDAG
40
35
  from qiskit._accelerate.nlayout import NLayout
41
36
 
42
37
  logger = logging.getLogger(__name__)
@@ -211,14 +206,27 @@ class SabreSwap(TransformationPass):
211
206
  " This circuit cannot be routed to this device."
212
207
  )
213
208
 
214
- if self.heuristic == "basic":
215
- heuristic = Heuristic.Basic
209
+ if isinstance(self.heuristic, Heuristic):
210
+ heuristic = self.heuristic
211
+ elif self.heuristic == "basic":
212
+ heuristic = Heuristic(attempt_limit=10 * num_dag_qubits).with_basic(
213
+ 1.0, SetScaling.Size
214
+ )
216
215
  elif self.heuristic == "lookahead":
217
- heuristic = Heuristic.Lookahead
216
+ heuristic = (
217
+ Heuristic(attempt_limit=10 * num_dag_qubits)
218
+ .with_basic(1.0, SetScaling.Size)
219
+ .with_lookahead(0.5, 20, SetScaling.Size)
220
+ )
218
221
  elif self.heuristic == "decay":
219
- heuristic = Heuristic.Decay
222
+ heuristic = (
223
+ Heuristic(attempt_limit=10 * num_dag_qubits)
224
+ .with_basic(1.0, SetScaling.Size)
225
+ .with_lookahead(0.5, 20, SetScaling.Size)
226
+ .with_decay(0.001, 5)
227
+ )
220
228
  else:
221
- raise TranspilerError("Heuristic %s not recognized." % self.heuristic)
229
+ raise TranspilerError(f"Heuristic {self.heuristic} not recognized.")
222
230
  disjoint_utils.require_layout_isolated_to_component(
223
231
  dag, self.coupling_map if self.target is None else self.target
224
232
  )
@@ -289,9 +297,9 @@ def _build_sabre_dag(dag, num_physical_qubits, qubit_indices):
289
297
  node_blocks = {}
290
298
  for node in block_dag.topological_op_nodes():
291
299
  cargs_bits = set(node.cargs)
292
- if node.op.condition is not None:
293
- cargs_bits.update(condition_resources(node.op.condition).clbits)
294
- if isinstance(node.op, SwitchCaseOp):
300
+ if node.condition is not None:
301
+ cargs_bits.update(condition_resources(node.condition).clbits)
302
+ if node.is_control_flow() and isinstance(node.op, SwitchCaseOp):
295
303
  target = node.op.target
296
304
  if isinstance(target, Clbit):
297
305
  cargs_bits.add(target)
@@ -300,7 +308,7 @@ def _build_sabre_dag(dag, num_physical_qubits, qubit_indices):
300
308
  else: # Expr
301
309
  cargs_bits.update(node_resources(target).clbits)
302
310
  cargs = {block_dag.find_bit(x).index for x in cargs_bits}
303
- if isinstance(node.op, ControlFlowOp):
311
+ if node.is_control_flow():
304
312
  node_blocks[node._node_id] = [
305
313
  recurse(
306
314
  block,
@@ -313,7 +321,7 @@ def _build_sabre_dag(dag, num_physical_qubits, qubit_indices):
313
321
  node._node_id,
314
322
  [wire_map[x] for x in node.qargs],
315
323
  cargs,
316
- getattr(node.op, "_directive", False),
324
+ node.is_directive(),
317
325
  )
318
326
  )
319
327
  return SabreDAG(num_physical_qubits, block_dag.num_clbits(), dag_list, node_blocks)
@@ -383,14 +391,15 @@ def _apply_sabre_result(
383
391
  node = source_dag._multi_graph[node_id]
384
392
  if node_id in swap_map:
385
393
  apply_swaps(dest_dag, swap_map[node_id], layout)
386
- if not isinstance(node.op, ControlFlowOp):
387
- dest_dag.apply_operation_back(
388
- node.op,
389
- [
390
- physical_qubits[layout.virtual_to_physical(root_logical_map[q])]
391
- for q in node.qargs
392
- ],
393
- node.cargs,
394
+ if not node.is_control_flow():
395
+ qubits = [
396
+ physical_qubits[layout.virtual_to_physical(root_logical_map[q])]
397
+ for q in node.qargs
398
+ ]
399
+ dest_dag._apply_op_node_back(
400
+ DAGOpNode.from_instruction(
401
+ node._to_circuit_instruction().replace(qubits=qubits)
402
+ ),
394
403
  check=False,
395
404
  )
396
405
  continue
@@ -14,11 +14,15 @@
14
14
  from typing import Iterable, Union, Optional, List, Tuple
15
15
  from math import floor, log10
16
16
 
17
- from qiskit.circuit import Barrier
17
+ from qiskit.circuit import SwitchCaseOp, Clbit, ClassicalRegister, Barrier
18
+ from qiskit.circuit.controlflow import condition_resources, node_resources
18
19
  from qiskit.dagcircuit import DAGOpNode, DAGDepNode, DAGDependency, DAGCircuit
19
- from qiskit.transpiler import Layout
20
20
  from qiskit.transpiler.basepasses import TransformationPass
21
- from qiskit.circuit.library import SwapGate
21
+ from qiskit.transpiler.layout import Layout
22
+ from qiskit.transpiler.passes.routing.sabre_swap import _build_sabre_dag, _apply_sabre_result
23
+
24
+ from qiskit._accelerate import star_prerouting
25
+ from qiskit._accelerate.nlayout import NLayout
22
26
 
23
27
 
24
28
  class StarBlock:
@@ -260,7 +264,7 @@ class StarPreRouting(TransformationPass):
260
264
  # star block by a linear sequence of gates
261
265
  new_dag, qubit_mapping = self.star_preroute(dag, star_blocks, processing_order)
262
266
 
263
- # Fix output permuation -- copied from ElidePermutations
267
+ # Fix output permutation -- copied from ElidePermutations
264
268
  input_qubit_mapping = {qubit: index for index, qubit in enumerate(dag.qubits)}
265
269
  self.property_set["original_layout"] = Layout(input_qubit_mapping)
266
270
  if self.property_set["original_qubit_indices"] is None:
@@ -305,113 +309,84 @@ class StarPreRouting(TransformationPass):
305
309
  new_dag: a dag specifying the pre-routed circuit
306
310
  qubit_mapping: the final qubit mapping after pre-routing
307
311
  """
308
- node_to_block_id = {}
309
- for i, block in enumerate(blocks):
310
- for node in block.get_nodes():
311
- node_to_block_id[node] = i
312
-
313
- new_dag = dag.copy_empty_like()
314
- processed_block_ids = set()
315
- qubit_mapping = list(range(len(dag.qubits)))
316
-
317
- def _apply_mapping(qargs, qubit_mapping, qubits):
318
- return tuple(qubits[qubit_mapping[dag.find_bit(qubit).index]] for qubit in qargs)
319
-
320
- is_first_star = True
321
- last_2q_gate = [
322
- op
323
- for op in reversed(processing_order)
324
- if ((len(op.qargs) > 1) and (op.name != "barrier"))
312
+ # Convert the DAG to a SabreDAG
313
+ num_qubits = len(dag.qubits)
314
+ canonical_register = dag.qregs["q"]
315
+ current_layout = Layout.generate_trivial_layout(canonical_register)
316
+ qubit_indices = {bit: idx for idx, bit in enumerate(canonical_register)}
317
+ layout_mapping = {qubit_indices[k]: v for k, v in current_layout.get_virtual_bits().items()}
318
+ initial_layout = NLayout(layout_mapping, num_qubits, num_qubits)
319
+ sabre_dag, circuit_to_dag_dict = _build_sabre_dag(dag, num_qubits, qubit_indices)
320
+
321
+ # Extract the nodes from the blocks for the Rust representation
322
+ rust_blocks = [
323
+ (block.center is not None, _extract_nodes(block.get_nodes(), dag)) for block in blocks
325
324
  ]
326
- if len(last_2q_gate) > 0:
327
- last_2q_gate = last_2q_gate[0]
328
- else:
329
- last_2q_gate = None
330
325
 
326
+ # Determine the processing order of the nodes in the DAG for the Rust representation
331
327
  int_digits = floor(log10(len(processing_order))) + 1
332
328
  processing_order_index_map = {
333
- node: f"a{str(index).zfill(int(int_digits))}"
334
- for index, node in enumerate(processing_order)
329
+ node: f"a{index:0{int_digits}}" for index, node in enumerate(processing_order)
335
330
  }
336
331
 
337
332
  def tie_breaker_key(node):
338
333
  return processing_order_index_map.get(node, node.sort_key)
339
334
 
340
- for node in dag.topological_op_nodes(key=tie_breaker_key):
341
- block_id = node_to_block_id.get(node, None)
342
- if block_id is not None:
343
- if block_id in processed_block_ids:
344
- continue
345
-
346
- processed_block_ids.add(block_id)
347
-
348
- # process the whole block
349
- block = blocks[block_id]
350
- sequence = block.nodes
351
- center_node = block.center
352
-
353
- if len(sequence) == 2:
354
- for inner_node in sequence:
355
- new_dag.apply_operation_back(
356
- inner_node.op,
357
- _apply_mapping(inner_node.qargs, qubit_mapping, dag.qubits),
358
- inner_node.cargs,
359
- check=False,
360
- )
361
- continue
362
- swap_source = None
363
- prev = None
364
- for inner_node in sequence:
365
- if (len(inner_node.qargs) == 1) or (inner_node.qargs == prev):
366
- new_dag.apply_operation_back(
367
- inner_node.op,
368
- _apply_mapping(inner_node.qargs, qubit_mapping, dag.qubits),
369
- inner_node.cargs,
370
- check=False,
371
- )
372
- continue
373
- if is_first_star and swap_source is None:
374
- swap_source = center_node
375
- new_dag.apply_operation_back(
376
- inner_node.op,
377
- _apply_mapping(inner_node.qargs, qubit_mapping, dag.qubits),
378
- inner_node.cargs,
379
- check=False,
380
- )
381
-
382
- prev = inner_node.qargs
383
- continue
384
- # place 2q-gate and subsequent swap gate
385
- new_dag.apply_operation_back(
386
- inner_node.op,
387
- _apply_mapping(inner_node.qargs, qubit_mapping, dag.qubits),
388
- inner_node.cargs,
389
- check=False,
390
- )
391
-
392
- if not inner_node is last_2q_gate and not isinstance(inner_node.op, Barrier):
393
- new_dag.apply_operation_back(
394
- SwapGate(),
395
- _apply_mapping(inner_node.qargs, qubit_mapping, dag.qubits),
396
- inner_node.cargs,
397
- check=False,
398
- )
399
- # Swap mapping
400
- index_0 = dag.find_bit(inner_node.qargs[0]).index
401
- index_1 = dag.find_bit(inner_node.qargs[1]).index
402
- qubit_mapping[index_1], qubit_mapping[index_0] = (
403
- qubit_mapping[index_0],
404
- qubit_mapping[index_1],
405
- )
406
-
407
- prev = inner_node.qargs
408
- is_first_star = False
409
- else:
410
- # the node is not part of a block
411
- new_dag.apply_operation_back(
412
- node.op,
413
- _apply_mapping(node.qargs, qubit_mapping, dag.qubits),
414
- node.cargs,
415
- check=False,
416
- )
417
- return new_dag, qubit_mapping
335
+ rust_processing_order = _extract_nodes(dag.topological_op_nodes(key=tie_breaker_key), dag)
336
+
337
+ # Run the star prerouting algorithm to obtain the new DAG and qubit mapping
338
+ *sabre_result, qubit_mapping = star_prerouting.star_preroute(
339
+ sabre_dag, rust_blocks, rust_processing_order
340
+ )
341
+
342
+ res_dag = _apply_sabre_result(
343
+ dag.copy_empty_like(),
344
+ dag,
345
+ sabre_result,
346
+ initial_layout,
347
+ dag.qubits,
348
+ circuit_to_dag_dict,
349
+ )
350
+
351
+ return res_dag, qubit_mapping
352
+
353
+
354
+ def _extract_nodes(nodes, dag):
355
+ """Extract and format node information for Rust representation used in SabreDAG.
356
+
357
+ Each node is represented as a tuple containing:
358
+ - Node ID (int): The unique identifier of the node in the DAG.
359
+ - Qubit indices (list of int): Indices of qubits involved in the node's operation.
360
+ - Classical bit indices (set of int): Indices of classical bits involved in the node's operation.
361
+ - Directive flag (bool): Indicates whether the operation is a directive (True) or not (False).
362
+
363
+ Args:
364
+ nodes (list[DAGOpNode]): List of DAGOpNode objects to extract information from.
365
+ dag (DAGCircuit): DAGCircuit object containing the circuit structure.
366
+
367
+ Returns:
368
+ list of tuples: Each tuple contains information about a node in the format described above.
369
+ """
370
+ extracted_node_info = []
371
+ for node in nodes:
372
+ qubit_indices = [dag.find_bit(qubit).index for qubit in node.qargs]
373
+ classical_bit_indices = set()
374
+
375
+ if node.op.condition is not None:
376
+ classical_bit_indices.update(condition_resources(node.op.condition).clbits)
377
+
378
+ if isinstance(node.op, SwitchCaseOp):
379
+ switch_case_target = node.op.target
380
+ if isinstance(switch_case_target, Clbit):
381
+ classical_bit_indices.add(switch_case_target)
382
+ elif isinstance(switch_case_target, ClassicalRegister):
383
+ classical_bit_indices.update(switch_case_target)
384
+ else: # Assume target is an expression involving classical bits
385
+ classical_bit_indices.update(node_resources(switch_case_target).clbits)
386
+
387
+ is_directive = getattr(node.op, "_directive", False)
388
+ extracted_node_info.append(
389
+ (node._node_id, qubit_indices, classical_bit_indices, is_directive)
390
+ )
391
+
392
+ return extracted_node_info