qiskit 1.1.2__cp38-abi3-macosx_10_9_universal2.whl → 1.2.0rc1__cp38-abi3-macosx_10_9_universal2.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.abi3.so +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
@@ -35,7 +35,7 @@ import logging
35
35
 
36
36
  import numpy as np
37
37
 
38
- from qiskit.circuit import QuantumRegister, QuantumCircuit, Gate
38
+ from qiskit.circuit import QuantumRegister, QuantumCircuit, Gate, CircuitInstruction
39
39
  from qiskit.circuit.library.standard_gates import (
40
40
  CXGate,
41
41
  U3Gate,
@@ -60,7 +60,7 @@ from qiskit.utils.deprecation import deprecate_func
60
60
  from qiskit._accelerate import two_qubit_decompose
61
61
 
62
62
  if TYPE_CHECKING:
63
- from qiskit.dagcircuit.dagcircuit import DAGCircuit
63
+ from qiskit.dagcircuit.dagcircuit import DAGCircuit, DAGOpNode
64
64
 
65
65
  logger = logging.getLogger(__name__)
66
66
 
@@ -116,7 +116,7 @@ def decompose_two_qubit_product_gate(special_unitary_matrix: np.ndarray):
116
116
  if deviation > 1.0e-13:
117
117
  raise QiskitError(
118
118
  "decompose_two_qubit_product_gate: decomposition failed: "
119
- "deviation too large: {}".format(deviation)
119
+ f"deviation too large: {deviation}"
120
120
  )
121
121
 
122
122
  return L, R, phase
@@ -230,13 +230,10 @@ class TwoQubitWeylDecomposition:
230
230
  self, *, euler_basis: str | None = None, simplify: bool = False, atol: float = DEFAULT_ATOL
231
231
  ) -> QuantumCircuit:
232
232
  """Returns Weyl decomposition in circuit form."""
233
- circuit_sequence = self._inner_decomposition.circuit(
233
+ circuit_data = self._inner_decomposition.circuit(
234
234
  euler_basis=euler_basis, simplify=simplify, atol=atol
235
235
  )
236
- circ = QuantumCircuit(2, global_phase=circuit_sequence.global_phase)
237
- for name, params, qubits in circuit_sequence:
238
- getattr(circ, name)(*params, *qubits)
239
- return circ
236
+ return QuantumCircuit._from_circuit_data(circuit_data)
240
237
 
241
238
  def actual_fidelity(self, **kwargs) -> float:
242
239
  """Calculates the actual fidelity of the decomposed circuit to the input unitary."""
@@ -641,47 +638,58 @@ class TwoQubitBasisDecomposer:
641
638
  QiskitError: if ``pulse_optimize`` is True but we don't know how to do it.
642
639
  """
643
640
 
644
- sequence = self._inner_decomposer(
645
- np.asarray(unitary, dtype=complex),
646
- basis_fidelity,
647
- approximate,
648
- _num_basis_uses=_num_basis_uses,
649
- )
650
- q = QuantumRegister(2)
651
641
  if use_dag:
652
- from qiskit.dagcircuit.dagcircuit import DAGCircuit
642
+ from qiskit.dagcircuit.dagcircuit import DAGCircuit, DAGOpNode
643
+
644
+ sequence = self._inner_decomposer(
645
+ np.asarray(unitary, dtype=complex),
646
+ basis_fidelity,
647
+ approximate,
648
+ _num_basis_uses=_num_basis_uses,
649
+ )
650
+ q = QuantumRegister(2)
653
651
 
654
652
  dag = DAGCircuit()
655
653
  dag.global_phase = sequence.global_phase
656
654
  dag.add_qreg(q)
657
- for name, params, qubits in sequence:
658
- if name == "USER_GATE":
655
+ for gate, params, qubits in sequence:
656
+ if gate is None:
659
657
  dag.apply_operation_back(self.gate, tuple(q[x] for x in qubits), check=False)
660
658
  else:
661
- gate = GATE_NAME_MAP[name](*params)
662
- dag.apply_operation_back(gate, tuple(q[x] for x in qubits), check=False)
659
+ op = CircuitInstruction.from_standard(
660
+ gate, qubits=tuple(q[x] for x in qubits), params=params
661
+ )
662
+ node = DAGOpNode.from_instruction(op, dag=dag)
663
+ dag._apply_op_node_back(node)
663
664
  return dag
664
665
  else:
665
- circ = QuantumCircuit(q, global_phase=sequence.global_phase)
666
- for name, params, qubits in sequence:
667
- try:
668
- getattr(circ, name)(*params, *qubits)
669
- except AttributeError as exc:
670
- if name == "USER_GATE":
671
- circ.append(self.gate, qubits)
672
- elif name == "u3":
673
- gate = U3Gate(*params)
674
- circ.append(gate, qubits)
675
- elif name == "u2":
676
- gate = U2Gate(*params)
677
- circ.append(gate, qubits)
678
- elif name == "u1":
679
- gate = U1Gate(*params)
680
- circ.append(gate, qubits)
666
+ if getattr(self.gate, "_standard_gate", None):
667
+ circ_data = self._inner_decomposer.to_circuit(
668
+ np.asarray(unitary, dtype=complex),
669
+ self.gate,
670
+ basis_fidelity,
671
+ approximate,
672
+ _num_basis_uses=_num_basis_uses,
673
+ )
674
+ return QuantumCircuit._from_circuit_data(circ_data)
675
+ else:
676
+ sequence = self._inner_decomposer(
677
+ np.asarray(unitary, dtype=complex),
678
+ basis_fidelity,
679
+ approximate,
680
+ _num_basis_uses=_num_basis_uses,
681
+ )
682
+ q = QuantumRegister(2)
683
+ circ = QuantumCircuit(q, global_phase=sequence.global_phase)
684
+ for gate, params, qubits in sequence:
685
+ if gate is None:
686
+ circ._append(self.gate, qargs=tuple(q[x] for x in qubits))
681
687
  else:
682
- raise QiskitError(f"Unknown gate {name}") from exc
683
-
684
- return circ
688
+ inst = CircuitInstruction.from_standard(
689
+ gate, qubits=tuple(q[x] for x in qubits), params=params
690
+ )
691
+ circ._append(inst)
692
+ return circ
685
693
 
686
694
  def traces(self, target):
687
695
  r"""
@@ -691,98 +699,9 @@ class TwoQubitBasisDecomposer:
691
699
  return self._inner_decomposer.traces(target._inner_decomposition)
692
700
 
693
701
 
694
- class TwoQubitDecomposeUpToDiagonal:
695
- """
696
- Class to decompose two qubit unitaries into the product of a diagonal gate
697
- and another unitary gate which can be represented by two CX gates instead of the
698
- usual three. This can be used when neighboring gates commute with the diagonal to
699
- potentially reduce overall CX count.
700
- """
701
-
702
- def __init__(self):
703
- sy = np.array([[0, -1j], [1j, 0]])
704
- self.sysy = np.kron(sy, sy)
705
-
706
- def _u4_to_su4(self, u4):
707
- phase_factor = np.conj(np.linalg.det(u4) ** (-1 / u4.shape[0]))
708
- su4 = u4 / phase_factor
709
- return su4, cmath.phase(phase_factor)
710
-
711
- def _gamma(self, mat):
712
- """
713
- proposition II.1: this invariant characterizes when two operators in U(4),
714
- say u, v, are equivalent up to single qubit gates:
715
-
716
- u ≡ v -> Det(γ(u)) = Det(±(γ(v)))
717
- """
718
- sumat, _ = self._u4_to_su4(mat)
719
- sysy = self.sysy
720
- return sumat @ sysy @ sumat.T @ sysy
721
-
722
- def _cx0_test(self, mat):
723
- # proposition III.1: zero cx sufficient
724
- gamma = self._gamma(mat)
725
- evals = np.linalg.eigvals(gamma)
726
- return np.all(np.isclose(evals, np.ones(4)))
727
-
728
- def _cx1_test(self, mat):
729
- # proposition III.2: one cx sufficient
730
- gamma = self._gamma(mat)
731
- evals = np.linalg.eigvals(gamma)
732
- uvals, ucnts = np.unique(np.round(evals, 10), return_counts=True)
733
- return (
734
- len(uvals) == 2
735
- and all(ucnts == 2)
736
- and all((np.isclose(x, 1j)) or np.isclose(x, -1j) for x in uvals)
737
- )
738
-
739
- def _cx2_test(self, mat):
740
- # proposition III.3: two cx sufficient
741
- gamma = self._gamma(mat)
742
- return np.isclose(np.trace(gamma).imag, 0)
743
-
744
- def _real_trace_transform(self, mat):
745
- """
746
- Determine diagonal gate such that
747
-
748
- U3 = D U2
749
-
750
- Where U3 is a general two-qubit gate which takes 3 cnots, D is a
751
- diagonal gate, and U2 is a gate which takes 2 cnots.
752
- """
753
- a1 = (
754
- -mat[1, 3] * mat[2, 0]
755
- + mat[1, 2] * mat[2, 1]
756
- + mat[1, 1] * mat[2, 2]
757
- - mat[1, 0] * mat[2, 3]
758
- )
759
- a2 = (
760
- mat[0, 3] * mat[3, 0]
761
- - mat[0, 2] * mat[3, 1]
762
- - mat[0, 1] * mat[3, 2]
763
- + mat[0, 0] * mat[3, 3]
764
- )
765
- theta = 0 # arbitrary
766
- phi = 0 # arbitrary
767
- psi = np.arctan2(a1.imag + a2.imag, a1.real - a2.real) - phi
768
- diag = np.diag(np.exp(-1j * np.array([theta, phi, psi, -(theta + phi + psi)])))
769
- return diag
770
-
771
- def __call__(self, mat):
772
- """do the decomposition"""
773
- su4, phase = self._u4_to_su4(mat)
774
- real_map = self._real_trace_transform(su4)
775
- mapped_su4 = real_map @ su4
776
- if not self._cx2_test(mapped_su4):
777
- warnings.warn("Unitary decomposition up to diagonal may use an additionl CX gate.")
778
- circ = two_qubit_cnot_decompose(mapped_su4)
779
- circ.global_phase += phase
780
- return real_map.conj(), circ
781
-
782
-
783
702
  # This weird duplicated lazy structure is for backwards compatibility; Qiskit has historically
784
703
  # always made ``two_qubit_cnot_decompose`` available publicly immediately on import, but it's quite
785
- # expensive to construct, and we want to defer the obejct's creation until it's actually used. We
704
+ # expensive to construct, and we want to defer the object's creation until it's actually used. We
786
705
  # only need to pass through the public methods that take `self` as a parameter. Using `__getattr__`
787
706
  # doesn't work because it is only called if the normal resolution methods fail. Using
788
707
  # `__getattribute__` is too messy for a simple one-off use object.
@@ -133,7 +133,7 @@ def _get_connectivity(num_qubits: int, connectivity: str) -> dict:
133
133
  links = {i: list(range(num_qubits)) for i in range(num_qubits)}
134
134
 
135
135
  elif connectivity == "line":
136
- # Every qubit is connected to its immediate neighbours only.
136
+ # Every qubit is connected to its immediate neighbors only.
137
137
  links = {i: [i - 1, i, i + 1] for i in range(1, num_qubits - 1)}
138
138
 
139
139
  # first qubit
@@ -30,6 +30,7 @@ from qiskit.circuit.library.standard_gates import CXGate
30
30
  from qiskit.circuit.library.generalized_gates.uc_pauli_rot import UCPauliRotGate, _EPS
31
31
  from qiskit.circuit.library.generalized_gates.ucry import UCRYGate
32
32
  from qiskit.circuit.library.generalized_gates.ucrz import UCRZGate
33
+ from qiskit._accelerate.two_qubit_decompose import two_qubit_decompose_up_to_diagonal
33
34
 
34
35
 
35
36
  def qs_decomposition(
@@ -253,7 +254,7 @@ def _apply_a2(circ):
253
254
  from qiskit.quantum_info import Operator
254
255
  from qiskit.circuit.library.generalized_gates.unitary import UnitaryGate
255
256
 
256
- decomposer = two_qubit_decompose.TwoQubitDecomposeUpToDiagonal()
257
+ decomposer = two_qubit_decompose_up_to_diagonal
257
258
  ccirc = transpile(circ, basis_gates=["u", "cx", "qsd2q"], optimization_level=0)
258
259
  ind2q = []
259
260
  # collect 2q instrs
@@ -269,13 +270,14 @@ def _apply_a2(circ):
269
270
  # rolling over diagonals
270
271
  ind2 = None # lint
271
272
  for ind1, ind2 in zip(ind2q[0:-1:], ind2q[1::]):
272
- # get neigboring 2q gates separated by controls
273
+ # get neighboring 2q gates separated by controls
273
274
  instr1 = ccirc.data[ind1]
274
275
  mat1 = Operator(instr1.operation).data
275
276
  instr2 = ccirc.data[ind2]
276
277
  mat2 = Operator(instr2.operation).data
277
278
  # rollover
278
- dmat, qc2cx = decomposer(mat1)
279
+ dmat, qc2cx_data = decomposer(mat1)
280
+ qc2cx = QuantumCircuit._from_circuit_data(qc2cx_data)
279
281
  ccirc.data[ind1] = instr1.replace(operation=qc2cx.to_gate())
280
282
  mat2 = mat2 @ dmat
281
283
  ccirc.data[ind2] = instr2.replace(UnitaryGate(mat2))
@@ -1277,6 +1277,7 @@ from .basepasses import AnalysisPass, TransformationPass
1277
1277
  from .coupling import CouplingMap
1278
1278
  from .layout import Layout, TranspileLayout
1279
1279
  from .instruction_durations import InstructionDurations
1280
+ from .preset_passmanagers import generate_preset_pass_manager
1280
1281
  from .target import Target
1281
1282
  from .target import InstructionProperties
1282
1283
  from .target import QubitProperties
@@ -87,7 +87,7 @@ class BasePass(GenericPass, metaclass=MetaPass):
87
87
  return hash(self) == hash(other)
88
88
 
89
89
  @abstractmethod
90
- def run(self, dag: DAGCircuit): # pylint: disable=arguments-differ
90
+ def run(self, dag: DAGCircuit): # pylint:disable=arguments-renamed
91
91
  """Run a pass on the DAGCircuit. This is implemented by the pass developer.
92
92
 
93
93
  Args:
@@ -101,7 +101,7 @@ class CouplingMap:
101
101
  raise CouplingError("Physical qubits should be integers.")
102
102
  if physical_qubit in self.physical_qubits:
103
103
  raise CouplingError(
104
- "The physical qubit %s is already in the coupling graph" % physical_qubit
104
+ f"The physical qubit {physical_qubit} is already in the coupling graph"
105
105
  )
106
106
  self.graph.add_node(physical_qubit)
107
107
  self._dist_matrix = None # invalidate
@@ -188,9 +188,9 @@ class CouplingMap:
188
188
  CouplingError: if the qubits do not exist in the CouplingMap
189
189
  """
190
190
  if physical_qubit1 >= self.size():
191
- raise CouplingError("%s not in coupling graph" % physical_qubit1)
191
+ raise CouplingError(f"{physical_qubit1} not in coupling graph")
192
192
  if physical_qubit2 >= self.size():
193
- raise CouplingError("%s not in coupling graph" % physical_qubit2)
193
+ raise CouplingError(f"{physical_qubit2} not in coupling graph")
194
194
  self.compute_distance_matrix()
195
195
  res = self._dist_matrix[physical_qubit1, physical_qubit2]
196
196
  if res == math.inf:
@@ -15,8 +15,7 @@ from __future__ import annotations
15
15
  from typing import Optional, List, Tuple, Union, Iterable
16
16
 
17
17
  import qiskit.circuit
18
- from qiskit.circuit import Barrier, Delay
19
- from qiskit.circuit import Instruction, ParameterExpression
18
+ from qiskit.circuit import Barrier, Delay, Instruction, ParameterExpression
20
19
  from qiskit.circuit.duration import duration_in_dt
21
20
  from qiskit.providers import Backend
22
21
  from qiskit.transpiler.exceptions import TranspilerError
@@ -98,8 +98,8 @@ class Layout:
98
98
  virtual = value1
99
99
  else:
100
100
  raise LayoutError(
101
- "The map (%s -> %s) has to be a (Bit -> integer)"
102
- " or the other way around." % (type(value1), type(value2))
101
+ f"The map ({type(value1)} -> {type(value2)}) has to be a (Bit -> integer)"
102
+ " or the other way around."
103
103
  )
104
104
  return virtual, physical
105
105
 
@@ -137,7 +137,7 @@ class Layout:
137
137
  else:
138
138
  raise LayoutError(
139
139
  "The key to remove should be of the form"
140
- " Qubit or integer) and %s was provided" % (type(key),)
140
+ f" Qubit or integer) and {type(key)} was provided"
141
141
  )
142
142
 
143
143
  def __len__(self):
@@ -91,6 +91,7 @@ Optimizations
91
91
  ElidePermutations
92
92
  NormalizeRXAngle
93
93
  OptimizeAnnotated
94
+ Split2QUnitaries
94
95
 
95
96
  Calibration
96
97
  =============
@@ -244,6 +245,7 @@ from .optimization import OptimizeCliffords
244
245
  from .optimization import ElidePermutations
245
246
  from .optimization import NormalizeRXAngle
246
247
  from .optimization import OptimizeAnnotated
248
+ from .optimization import Split2QUnitaries
247
249
 
248
250
  # circuit analysis
249
251
  from .analysis import ResourceEstimation
@@ -30,11 +30,12 @@ from qiskit.circuit import (
30
30
  QuantumCircuit,
31
31
  ParameterExpression,
32
32
  )
33
- from qiskit.dagcircuit import DAGCircuit
33
+ from qiskit.dagcircuit import DAGCircuit, DAGOpNode
34
34
  from qiskit.converters import circuit_to_dag, dag_to_circuit
35
35
  from qiskit.circuit.equivalence import Key, NodeData
36
36
  from qiskit.transpiler.basepasses import TransformationPass
37
37
  from qiskit.transpiler.exceptions import TranspilerError
38
+ from qiskit.circuit.controlflow import CONTROL_FLOW_OP_NAMES
38
39
 
39
40
  logger = logging.getLogger(__name__)
40
41
 
@@ -207,7 +208,7 @@ class BasisTranslator(TransformationPass):
207
208
  "target basis is not universal or there are additional equivalence rules "
208
209
  "needed in the EquivalenceLibrary being used. For more details on this "
209
210
  "error see: "
210
- "https://docs.quantum.ibm.com/api/qiskit/transpiler_passes."
211
+ "https://docs.quantum.ibm.com/api/qiskit/qiskit.transpiler.passes."
211
212
  "BasisTranslator#translation-errors"
212
213
  )
213
214
 
@@ -225,7 +226,7 @@ class BasisTranslator(TransformationPass):
225
226
  f"basis: {list(target_basis)}. This likely means the target basis is not universal "
226
227
  "or there are additional equivalence rules needed in the EquivalenceLibrary being "
227
228
  "used. For more details on this error see: "
228
- "https://docs.quantum.ibm.com/api/qiskit/transpiler_passes."
229
+ "https://docs.quantum.ibm.com/api/qiskit/qiskit.transpiler.passes."
229
230
  "BasisTranslator#translation-errors"
230
231
  )
231
232
 
@@ -248,72 +249,85 @@ class BasisTranslator(TransformationPass):
248
249
  replace_start_time = time.time()
249
250
 
250
251
  def apply_translation(dag, wire_map):
251
- dag_updated = False
252
- for node in dag.op_nodes():
252
+ is_updated = False
253
+ out_dag = dag.copy_empty_like()
254
+ for node in dag.topological_op_nodes():
253
255
  node_qargs = tuple(wire_map[bit] for bit in node.qargs)
254
256
  qubit_set = frozenset(node_qargs)
255
257
  if node.name in target_basis or len(node.qargs) < self._min_qubits:
256
- if isinstance(node.op, ControlFlowOp):
258
+ if node.name in CONTROL_FLOW_OP_NAMES:
257
259
  flow_blocks = []
258
260
  for block in node.op.blocks:
259
261
  dag_block = circuit_to_dag(block)
260
- dag_updated = apply_translation(
262
+ updated_dag, is_updated = apply_translation(
261
263
  dag_block,
262
264
  {
263
265
  inner: wire_map[outer]
264
266
  for inner, outer in zip(block.qubits, node.qargs)
265
267
  },
266
268
  )
267
- if dag_updated:
268
- flow_circ_block = dag_to_circuit(dag_block)
269
+ if is_updated:
270
+ flow_circ_block = dag_to_circuit(updated_dag)
269
271
  else:
270
272
  flow_circ_block = block
271
273
  flow_blocks.append(flow_circ_block)
272
274
  node.op = node.op.replace_blocks(flow_blocks)
275
+ out_dag.apply_operation_back(node.op, node.qargs, node.cargs, check=False)
273
276
  continue
274
277
  if (
275
278
  node_qargs in self._qargs_with_non_global_operation
276
279
  and node.name in self._qargs_with_non_global_operation[node_qargs]
277
280
  ):
281
+ out_dag.apply_operation_back(node.op, node.qargs, node.cargs, check=False)
278
282
  continue
279
283
 
280
284
  if dag.has_calibration_for(node):
285
+ out_dag.apply_operation_back(node.op, node.qargs, node.cargs, check=False)
281
286
  continue
282
287
  if qubit_set in extra_instr_map:
283
- self._replace_node(dag, node, extra_instr_map[qubit_set])
284
- elif (node.op.name, node.op.num_qubits) in instr_map:
285
- self._replace_node(dag, node, instr_map)
288
+ self._replace_node(out_dag, node, extra_instr_map[qubit_set])
289
+ elif (node.name, node.num_qubits) in instr_map:
290
+ self._replace_node(out_dag, node, instr_map)
286
291
  else:
287
292
  raise TranspilerError(f"BasisTranslator did not map {node.name}.")
288
- dag_updated = True
289
- return dag_updated
293
+ is_updated = True
294
+ return out_dag, is_updated
290
295
 
291
- apply_translation(dag, qarg_indices)
296
+ out_dag, _ = apply_translation(dag, qarg_indices)
292
297
  replace_end_time = time.time()
293
298
  logger.info(
294
299
  "Basis translation instructions replaced in %.3fs.",
295
300
  replace_end_time - replace_start_time,
296
301
  )
297
302
 
298
- return dag
303
+ return out_dag
299
304
 
300
305
  def _replace_node(self, dag, node, instr_map):
301
- target_params, target_dag = instr_map[node.op.name, node.op.num_qubits]
302
- if len(node.op.params) != len(target_params):
306
+ target_params, target_dag = instr_map[node.name, node.num_qubits]
307
+ if len(node.params) != len(target_params):
303
308
  raise TranspilerError(
304
309
  "Translation num_params not equal to op num_params."
305
- "Op: {} {} Translation: {}\n{}".format(
306
- node.op.params, node.op.name, target_params, target_dag
307
- )
310
+ f"Op: {node.params} {node.name} Translation: {target_params}\n{target_dag}"
308
311
  )
309
- if node.op.params:
310
- parameter_map = dict(zip(target_params, node.op.params))
311
- bound_target_dag = target_dag.copy_empty_like()
312
+ if node.params:
313
+ parameter_map = dict(zip(target_params, node.params))
312
314
  for inner_node in target_dag.topological_op_nodes():
313
- if any(isinstance(x, ParameterExpression) for x in inner_node.op.params):
314
- new_op = inner_node.op.copy()
315
+ new_node = DAGOpNode.from_instruction(
316
+ inner_node._to_circuit_instruction(),
317
+ dag=target_dag,
318
+ )
319
+ new_node.qargs = tuple(
320
+ node.qargs[target_dag.find_bit(x).index] for x in inner_node.qargs
321
+ )
322
+ new_node.cargs = tuple(
323
+ node.cargs[target_dag.find_bit(x).index] for x in inner_node.cargs
324
+ )
325
+
326
+ if not new_node.is_standard_gate():
327
+ new_node.op = new_node.op.copy()
328
+ if any(isinstance(x, ParameterExpression) for x in inner_node.params):
315
329
  new_params = []
316
- for param in new_op.params:
330
+ for param in new_node.params:
317
331
  if not isinstance(param, ParameterExpression):
318
332
  new_params.append(param)
319
333
  else:
@@ -327,10 +341,11 @@ class BasisTranslator(TransformationPass):
327
341
  if not new_value.parameters:
328
342
  new_value = new_value.numeric()
329
343
  new_params.append(new_value)
330
- new_op.params = new_params
331
- else:
332
- new_op = inner_node.op
333
- bound_target_dag.apply_operation_back(new_op, inner_node.qargs, inner_node.cargs)
344
+ new_node.params = new_params
345
+ if not new_node.is_standard_gate():
346
+ new_node.op.params = new_params
347
+ dag._apply_op_node_back(new_node)
348
+
334
349
  if isinstance(target_dag.global_phase, ParameterExpression):
335
350
  old_phase = target_dag.global_phase
336
351
  bind_dict = {x: parameter_map[x] for x in old_phase.parameters}
@@ -338,31 +353,37 @@ class BasisTranslator(TransformationPass):
338
353
  new_phase = old_phase
339
354
  for x in bind_dict.items():
340
355
  new_phase = new_phase.assign(*x)
341
-
342
356
  else:
343
357
  new_phase = old_phase.bind(bind_dict)
344
358
  if not new_phase.parameters:
345
359
  new_phase = new_phase.numeric()
346
360
  if isinstance(new_phase, complex):
347
361
  raise TranspilerError(f"Global phase must be real, but got '{new_phase}'")
348
- bound_target_dag.global_phase = new_phase
349
- else:
350
- bound_target_dag = target_dag
351
-
352
- if len(bound_target_dag.op_nodes()) == 1 and len(
353
- bound_target_dag.op_nodes()[0].qargs
354
- ) == len(node.qargs):
355
- dag_op = bound_target_dag.op_nodes()[0].op
356
- # dag_op may be the same instance as other ops in the dag,
357
- # so if there is a condition, need to copy
358
- if getattr(node.op, "condition", None):
359
- dag_op = dag_op.copy()
360
- dag.substitute_node(node, dag_op, inplace=True)
361
-
362
- if bound_target_dag.global_phase:
363
- dag.global_phase += bound_target_dag.global_phase
362
+ dag.global_phase += new_phase
363
+
364
364
  else:
365
- dag.substitute_node_with_dag(node, bound_target_dag)
365
+ for inner_node in target_dag.topological_op_nodes():
366
+ new_node = DAGOpNode.from_instruction(
367
+ inner_node._to_circuit_instruction(),
368
+ dag=target_dag,
369
+ )
370
+ new_node.qargs = tuple(
371
+ node.qargs[target_dag.find_bit(x).index] for x in inner_node.qargs
372
+ )
373
+ new_node.cargs = tuple(
374
+ node.cargs[target_dag.find_bit(x).index] for x in inner_node.cargs
375
+ )
376
+ if not new_node.is_standard_gate:
377
+ new_node.op = new_node.op.copy()
378
+ # dag_op may be the same instance as other ops in the dag,
379
+ # so if there is a condition, need to copy
380
+ if getattr(node.op, "condition", None):
381
+ new_node_op = new_node.op.to_mutable()
382
+ new_node_op.condition = node.op.condition
383
+ new_node.op = new_node_op
384
+ dag._apply_op_node_back(new_node)
385
+ if target_dag.global_phase:
386
+ dag.global_phase += target_dag.global_phase
366
387
 
367
388
  @singledispatchmethod
368
389
  def _extract_basis(self, circuit):
@@ -372,8 +393,8 @@ class BasisTranslator(TransformationPass):
372
393
  def _(self, dag: DAGCircuit):
373
394
  for node in dag.op_nodes():
374
395
  if not dag.has_calibration_for(node) and len(node.qargs) >= self._min_qubits:
375
- yield (node.name, node.op.num_qubits)
376
- if isinstance(node.op, ControlFlowOp):
396
+ yield (node.name, node.num_qubits)
397
+ if node.name in CONTROL_FLOW_OP_NAMES:
377
398
  for block in node.op.blocks:
378
399
  yield from self._extract_basis(block)
379
400
 
@@ -414,10 +435,10 @@ class BasisTranslator(TransformationPass):
414
435
  frozenset(qargs).issuperset(incomplete_qargs)
415
436
  for incomplete_qargs in self._qargs_with_non_global_operation
416
437
  ):
417
- qargs_local_source_basis[frozenset(qargs)].add((node.name, node.op.num_qubits))
438
+ qargs_local_source_basis[frozenset(qargs)].add((node.name, node.num_qubits))
418
439
  else:
419
- source_basis.add((node.name, node.op.num_qubits))
420
- if isinstance(node.op, ControlFlowOp):
440
+ source_basis.add((node.name, node.num_qubits))
441
+ if node.name in CONTROL_FLOW_OP_NAMES:
421
442
  for block in node.op.blocks:
422
443
  block_dag = circuit_to_dag(block)
423
444
  source_basis, qargs_local_source_basis = self._extract_basis_target(
@@ -468,7 +489,7 @@ class BasisSearchVisitor(rustworkx.visit.DijkstraVisitor):
468
489
  score,
469
490
  )
470
491
  self._basis_transforms.append((gate.name, gate.num_qubits, rule.params, rule.circuit))
471
- # we can stop the search if we have found all gates in the original ciruit.
492
+ # we can stop the search if we have found all gates in the original circuit.
472
493
  if not self._source_gates_remain:
473
494
  # if we start from source gates and apply `basis_transforms` in reverse order, we'll end
474
495
  # up with gates in the target basis. Note though that `basis_transforms` may include
@@ -512,7 +533,7 @@ class BasisSearchVisitor(rustworkx.visit.DijkstraVisitor):
512
533
 
513
534
  cost_tot = 0
514
535
  for instruction in edge_data.rule.circuit:
515
- key = Key(name=instruction.operation.name, num_qubits=len(instruction.qubits))
536
+ key = Key(name=instruction.name, num_qubits=len(instruction.qubits))
516
537
  cost_tot += self._opt_cost_map[key]
517
538
 
518
539
  return cost_tot - self._opt_cost_map[edge_data.source]
@@ -550,7 +571,7 @@ def _basis_search(equiv_lib, source_basis, target_basis):
550
571
  if not source_basis:
551
572
  return []
552
573
 
553
- # This is only neccessary since gates in target basis are currently reported by
574
+ # This is only necessary since gates in target basis are currently reported by
554
575
  # their names and we need to have in addition the number of qubits they act on.
555
576
  target_basis_keys = [key for key in equiv_lib.keys() if key.name in target_basis]
556
577
 
@@ -630,7 +651,7 @@ def _compose_transforms(basis_transforms, source_basis, source_dag):
630
651
  doomed_nodes = [
631
652
  node
632
653
  for node in dag.op_nodes()
633
- if (node.op.name, node.op.num_qubits) == (gate_name, gate_num_qubits)
654
+ if (node.name, node.num_qubits) == (gate_name, gate_num_qubits)
634
655
  ]
635
656
 
636
657
  if doomed_nodes and logger.isEnabledFor(logging.DEBUG):
@@ -644,9 +665,7 @@ def _compose_transforms(basis_transforms, source_basis, source_dag):
644
665
 
645
666
  for node in doomed_nodes:
646
667
 
647
- replacement = equiv.assign_parameters(
648
- dict(zip_longest(equiv_params, node.op.params))
649
- )
668
+ replacement = equiv.assign_parameters(dict(zip_longest(equiv_params, node.params)))
650
669
 
651
670
  replacement_dag = circuit_to_dag(replacement)
652
671
 
@@ -668,8 +687,8 @@ def _get_example_gates(source_dag):
668
687
  def recurse(dag, example_gates=None):
669
688
  example_gates = example_gates or {}
670
689
  for node in dag.op_nodes():
671
- example_gates[(node.op.name, node.op.num_qubits)] = node.op
672
- if isinstance(node.op, ControlFlowOp):
690
+ example_gates[(node.name, node.num_qubits)] = node
691
+ if node.name in CONTROL_FLOW_OP_NAMES:
673
692
  for block in node.op.blocks:
674
693
  example_gates = recurse(circuit_to_dag(block), example_gates)
675
694
  return example_gates