qiskit 1.4.1__cp39-abi3-win_amd64.whl → 2.0.0__cp39-abi3-win_amd64.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 (462) hide show
  1. qiskit/VERSION.txt +1 -1
  2. qiskit/__init__.py +3 -9
  3. qiskit/_accelerate.pyd +0 -0
  4. qiskit/circuit/__init__.py +35 -10
  5. qiskit/circuit/{add_control.py → _add_control.py} +32 -12
  6. qiskit/circuit/_classical_resource_map.py +5 -3
  7. qiskit/circuit/barrier.py +3 -7
  8. qiskit/circuit/classical/expr/__init__.py +31 -3
  9. qiskit/circuit/classical/expr/constructors.py +236 -28
  10. qiskit/circuit/classical/expr/expr.py +104 -3
  11. qiskit/circuit/classical/expr/visitors.py +75 -0
  12. qiskit/circuit/classical/types/__init__.py +12 -8
  13. qiskit/circuit/classical/types/ordering.py +14 -7
  14. qiskit/circuit/classical/types/types.py +36 -0
  15. qiskit/circuit/commutation_checker.py +34 -7
  16. qiskit/circuit/controlflow/__init__.py +32 -1
  17. qiskit/circuit/controlflow/_builder_utils.py +9 -5
  18. qiskit/circuit/controlflow/box.py +163 -0
  19. qiskit/circuit/controlflow/break_loop.py +1 -1
  20. qiskit/circuit/controlflow/builder.py +139 -39
  21. qiskit/circuit/controlflow/continue_loop.py +1 -3
  22. qiskit/circuit/controlflow/control_flow.py +10 -0
  23. qiskit/circuit/controlflow/for_loop.py +2 -1
  24. qiskit/circuit/controlflow/if_else.py +3 -16
  25. qiskit/circuit/controlflow/switch_case.py +2 -8
  26. qiskit/circuit/controlflow/while_loop.py +2 -7
  27. qiskit/circuit/controlledgate.py +2 -4
  28. qiskit/circuit/delay.py +40 -11
  29. qiskit/circuit/duration.py +0 -15
  30. qiskit/circuit/gate.py +2 -4
  31. qiskit/circuit/instruction.py +2 -141
  32. qiskit/circuit/instructionset.py +7 -54
  33. qiskit/circuit/library/__init__.py +469 -154
  34. qiskit/circuit/library/arithmetic/__init__.py +16 -10
  35. qiskit/circuit/library/arithmetic/adders/cdkm_ripple_carry_adder.py +1 -1
  36. qiskit/circuit/library/arithmetic/adders/draper_qft_adder.py +2 -2
  37. qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py +1 -1
  38. qiskit/circuit/library/arithmetic/exact_reciprocal.py +64 -21
  39. qiskit/circuit/library/arithmetic/integer_comparator.py +37 -80
  40. qiskit/circuit/library/arithmetic/linear_amplitude_function.py +169 -2
  41. qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +59 -5
  42. qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +154 -6
  43. qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +114 -4
  44. qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +191 -15
  45. qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py +93 -39
  46. qiskit/circuit/library/arithmetic/quadratic_form.py +168 -2
  47. qiskit/circuit/library/arithmetic/weighted_adder.py +73 -1
  48. qiskit/circuit/library/bit_flip_oracle.py +130 -0
  49. qiskit/circuit/library/blueprintcircuit.py +52 -16
  50. qiskit/circuit/library/data_preparation/initializer.py +1 -1
  51. qiskit/circuit/library/data_preparation/pauli_feature_map.py +4 -4
  52. qiskit/circuit/library/data_preparation/state_preparation.py +1 -1
  53. qiskit/circuit/library/generalized_gates/gms.py +1 -1
  54. qiskit/circuit/library/generalized_gates/isometry.py +1 -1
  55. qiskit/circuit/library/generalized_gates/pauli.py +1 -2
  56. qiskit/circuit/library/generalized_gates/uc.py +97 -7
  57. qiskit/circuit/library/generalized_gates/uc_pauli_rot.py +1 -1
  58. qiskit/circuit/library/generalized_gates/unitary.py +4 -2
  59. qiskit/circuit/library/graph_state.py +1 -0
  60. qiskit/circuit/library/hamiltonian_gate.py +1 -1
  61. qiskit/circuit/library/n_local/evolved_operator_ansatz.py +1 -1
  62. qiskit/circuit/library/n_local/n_local.py +1 -1
  63. qiskit/circuit/library/n_local/qaoa_ansatz.py +1 -1
  64. qiskit/circuit/library/overlap.py +2 -2
  65. qiskit/circuit/library/pauli_evolution.py +39 -24
  66. qiskit/circuit/library/phase_oracle.py +130 -51
  67. qiskit/circuit/library/standard_gates/__init__.py +0 -1
  68. qiskit/circuit/library/standard_gates/dcx.py +3 -4
  69. qiskit/circuit/library/standard_gates/ecr.py +3 -4
  70. qiskit/circuit/library/standard_gates/global_phase.py +5 -6
  71. qiskit/circuit/library/standard_gates/h.py +4 -9
  72. qiskit/circuit/library/standard_gates/i.py +2 -2
  73. qiskit/circuit/library/standard_gates/iswap.py +3 -4
  74. qiskit/circuit/library/standard_gates/p.py +15 -34
  75. qiskit/circuit/library/standard_gates/r.py +7 -10
  76. qiskit/circuit/library/standard_gates/rx.py +5 -15
  77. qiskit/circuit/library/standard_gates/rxx.py +3 -6
  78. qiskit/circuit/library/standard_gates/ry.py +5 -17
  79. qiskit/circuit/library/standard_gates/ryy.py +3 -6
  80. qiskit/circuit/library/standard_gates/rz.py +5 -17
  81. qiskit/circuit/library/standard_gates/rzx.py +3 -6
  82. qiskit/circuit/library/standard_gates/rzz.py +3 -6
  83. qiskit/circuit/library/standard_gates/s.py +6 -15
  84. qiskit/circuit/library/standard_gates/swap.py +4 -11
  85. qiskit/circuit/library/standard_gates/sx.py +7 -12
  86. qiskit/circuit/library/standard_gates/t.py +6 -7
  87. qiskit/circuit/library/standard_gates/u.py +2 -10
  88. qiskit/circuit/library/standard_gates/u1.py +5 -16
  89. qiskit/circuit/library/standard_gates/u2.py +2 -6
  90. qiskit/circuit/library/standard_gates/u3.py +3 -11
  91. qiskit/circuit/library/standard_gates/x.py +14 -62
  92. qiskit/circuit/library/standard_gates/xx_minus_yy.py +2 -5
  93. qiskit/circuit/library/standard_gates/xx_plus_yy.py +2 -5
  94. qiskit/circuit/library/standard_gates/y.py +4 -9
  95. qiskit/circuit/library/standard_gates/z.py +5 -15
  96. qiskit/circuit/measure.py +11 -2
  97. qiskit/circuit/parameterexpression.py +11 -0
  98. qiskit/circuit/quantumcircuit.py +890 -564
  99. qiskit/circuit/random/utils.py +12 -6
  100. qiskit/circuit/reset.py +5 -2
  101. qiskit/circuit/singleton.py +5 -11
  102. qiskit/circuit/store.py +0 -8
  103. qiskit/circuit/tools/pi_check.py +3 -0
  104. qiskit/compiler/__init__.py +1 -7
  105. qiskit/compiler/transpiler.py +38 -196
  106. qiskit/converters/circuit_to_dag.py +6 -4
  107. qiskit/converters/circuit_to_dagdependency.py +0 -2
  108. qiskit/converters/circuit_to_dagdependency_v2.py +0 -1
  109. qiskit/converters/circuit_to_gate.py +1 -1
  110. qiskit/converters/circuit_to_instruction.py +16 -29
  111. qiskit/converters/dag_to_circuit.py +7 -8
  112. qiskit/converters/dag_to_dagdependency.py +0 -1
  113. qiskit/converters/dag_to_dagdependency_v2.py +0 -1
  114. qiskit/converters/dagdependency_to_circuit.py +0 -6
  115. qiskit/converters/dagdependency_to_dag.py +0 -6
  116. qiskit/dagcircuit/collect_blocks.py +32 -20
  117. qiskit/dagcircuit/dagdependency.py +3 -37
  118. qiskit/dagcircuit/dagdependency_v2.py +5 -82
  119. qiskit/dagcircuit/dagnode.py +14 -2
  120. qiskit/passmanager/__init__.py +24 -6
  121. qiskit/passmanager/passmanager.py +26 -24
  122. qiskit/primitives/__init__.py +44 -35
  123. qiskit/primitives/backend_estimator_v2.py +102 -23
  124. qiskit/primitives/backend_sampler_v2.py +5 -20
  125. qiskit/primitives/base/__init__.py +4 -4
  126. qiskit/primitives/base/base_estimator.py +77 -82
  127. qiskit/primitives/base/base_primitive_job.py +2 -2
  128. qiskit/primitives/base/{base_primitive.py → base_primitive_v1.py} +1 -1
  129. qiskit/primitives/base/{base_result.py → base_result_v1.py} +1 -1
  130. qiskit/primitives/base/base_sampler.py +52 -60
  131. qiskit/primitives/base/{estimator_result.py → estimator_result_v1.py} +2 -2
  132. qiskit/primitives/base/{sampler_result.py → sampler_result_v1.py} +2 -2
  133. qiskit/primitives/base/{validation.py → validation_v1.py} +34 -15
  134. qiskit/primitives/containers/bindings_array.py +3 -1
  135. qiskit/primitives/containers/bit_array.py +23 -0
  136. qiskit/primitives/containers/data_bin.py +3 -1
  137. qiskit/primitives/containers/observables_array.py +19 -2
  138. qiskit/primitives/statevector_sampler.py +6 -8
  139. qiskit/primitives/utils.py +14 -189
  140. qiskit/providers/__init__.py +4 -130
  141. qiskit/providers/backend.py +11 -314
  142. qiskit/providers/basic_provider/__init__.py +3 -1
  143. qiskit/providers/basic_provider/basic_provider.py +29 -9
  144. qiskit/providers/basic_provider/basic_simulator.py +158 -298
  145. qiskit/providers/exceptions.py +0 -33
  146. qiskit/providers/fake_provider/__init__.py +0 -37
  147. qiskit/providers/fake_provider/generic_backend_v2.py +32 -693
  148. qiskit/qasm2/__init__.py +21 -6
  149. qiskit/qasm2/export.py +2 -10
  150. qiskit/qasm2/parse.py +11 -25
  151. qiskit/qasm3/__init__.py +5 -1
  152. qiskit/qasm3/ast.py +44 -0
  153. qiskit/qasm3/exporter.py +65 -27
  154. qiskit/qasm3/printer.py +35 -4
  155. qiskit/qpy/__init__.py +162 -19
  156. qiskit/qpy/binary_io/__init__.py +0 -1
  157. qiskit/qpy/binary_io/circuits.py +96 -116
  158. qiskit/qpy/binary_io/parse_sympy_repr.py +121 -0
  159. qiskit/qpy/binary_io/schedules.py +61 -388
  160. qiskit/qpy/binary_io/value.py +159 -33
  161. qiskit/qpy/common.py +10 -7
  162. qiskit/qpy/formats.py +41 -0
  163. qiskit/qpy/interface.py +29 -62
  164. qiskit/qpy/type_keys.py +58 -221
  165. qiskit/quantum_info/analysis/distance.py +3 -1
  166. qiskit/quantum_info/operators/dihedral/dihedral.py +3 -1
  167. qiskit/quantum_info/operators/operator.py +6 -2
  168. qiskit/quantum_info/operators/symplectic/clifford.py +3 -1
  169. qiskit/quantum_info/operators/symplectic/pauli.py +4 -2
  170. qiskit/quantum_info/operators/symplectic/pauli_list.py +17 -5
  171. qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +40 -6
  172. qiskit/quantum_info/states/densitymatrix.py +16 -6
  173. qiskit/quantum_info/states/stabilizerstate.py +35 -4
  174. qiskit/quantum_info/states/statevector.py +16 -6
  175. qiskit/result/__init__.py +5 -17
  176. qiskit/result/models.py +18 -11
  177. qiskit/result/result.py +38 -134
  178. qiskit/result/sampled_expval.py +1 -2
  179. qiskit/result/utils.py +3 -4
  180. qiskit/synthesis/__init__.py +21 -1
  181. qiskit/synthesis/arithmetic/__init__.py +3 -1
  182. qiskit/synthesis/arithmetic/adders/cdkm_ripple_carry_adder.py +1 -1
  183. qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +1 -1
  184. qiskit/synthesis/arithmetic/adders/vbe_ripple_carry_adder.py +2 -2
  185. qiskit/{providers/fake_provider/backends_v1/fake_20q → synthesis/arithmetic/comparators}/__init__.py +4 -6
  186. qiskit/synthesis/arithmetic/comparators/compare_2s.py +112 -0
  187. qiskit/synthesis/arithmetic/comparators/compare_greedy.py +66 -0
  188. qiskit/synthesis/arithmetic/multipliers/hrs_cumulative_multiplier.py +1 -1
  189. qiskit/synthesis/arithmetic/multipliers/rg_qft_multiplier.py +1 -1
  190. qiskit/synthesis/arithmetic/weighted_sum.py +155 -0
  191. qiskit/{result/mitigation → synthesis/boolean}/__init__.py +2 -2
  192. qiskit/synthesis/boolean/boolean_expression.py +231 -0
  193. qiskit/synthesis/boolean/boolean_expression_synth.py +124 -0
  194. qiskit/synthesis/boolean/boolean_expression_visitor.py +96 -0
  195. qiskit/synthesis/discrete_basis/generate_basis_approximations.py +2 -0
  196. qiskit/synthesis/evolution/lie_trotter.py +10 -7
  197. qiskit/synthesis/evolution/product_formula.py +44 -35
  198. qiskit/synthesis/evolution/qdrift.py +17 -24
  199. qiskit/synthesis/evolution/suzuki_trotter.py +20 -27
  200. qiskit/synthesis/linear/linear_depth_lnn.py +6 -221
  201. qiskit/synthesis/linear_phase/cx_cz_depth_lnn.py +4 -205
  202. qiskit/synthesis/multi_controlled/__init__.py +1 -0
  203. qiskit/synthesis/multi_controlled/mcx_synthesis.py +5 -2
  204. qiskit/synthesis/multi_controlled/multi_control_rotation_gates.py +206 -0
  205. qiskit/synthesis/one_qubit/one_qubit_decompose.py +1 -1
  206. qiskit/synthesis/two_qubit/__init__.py +1 -0
  207. qiskit/synthesis/two_qubit/two_qubit_decompose.py +28 -145
  208. qiskit/transpiler/__init__.py +32 -232
  209. qiskit/transpiler/basepasses.py +20 -51
  210. qiskit/transpiler/layout.py +1 -1
  211. qiskit/transpiler/passes/__init__.py +4 -40
  212. qiskit/transpiler/passes/basis/basis_translator.py +5 -4
  213. qiskit/transpiler/passes/basis/decompose.py +1 -15
  214. qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -5
  215. qiskit/transpiler/passes/basis/unroll_custom_definitions.py +3 -2
  216. qiskit/transpiler/passes/layout/apply_layout.py +4 -0
  217. qiskit/transpiler/passes/layout/dense_layout.py +2 -39
  218. qiskit/transpiler/passes/layout/full_ancilla_allocation.py +3 -4
  219. qiskit/transpiler/passes/layout/sabre_layout.py +7 -3
  220. qiskit/transpiler/passes/layout/vf2_layout.py +2 -20
  221. qiskit/transpiler/passes/layout/vf2_post_layout.py +60 -125
  222. qiskit/transpiler/passes/layout/vf2_utils.py +2 -26
  223. qiskit/transpiler/passes/optimization/__init__.py +2 -3
  224. qiskit/transpiler/passes/optimization/collect_and_collapse.py +2 -0
  225. qiskit/transpiler/passes/optimization/collect_cliffords.py +5 -0
  226. qiskit/transpiler/passes/optimization/collect_linear_functions.py +5 -0
  227. qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +16 -1
  228. qiskit/transpiler/passes/optimization/commutation_analysis.py +3 -3
  229. qiskit/transpiler/passes/optimization/consolidate_blocks.py +41 -19
  230. qiskit/transpiler/passes/optimization/contract_idle_wires_in_control_flow.py +104 -0
  231. qiskit/transpiler/passes/optimization/light_cone.py +135 -0
  232. qiskit/transpiler/passes/optimization/optimize_1q_commutation.py +0 -1
  233. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +18 -22
  234. qiskit/transpiler/passes/optimization/optimize_annotated.py +3 -2
  235. qiskit/transpiler/passes/optimization/remove_identity_equiv.py +6 -4
  236. qiskit/transpiler/passes/optimization/reset_after_measure_simplification.py +5 -2
  237. qiskit/transpiler/passes/optimization/split_2q_unitaries.py +26 -3
  238. qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +3 -2
  239. qiskit/transpiler/passes/routing/__init__.py +0 -1
  240. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +3 -1
  241. qiskit/transpiler/passes/routing/sabre_swap.py +14 -6
  242. qiskit/transpiler/passes/routing/star_prerouting.py +1 -1
  243. qiskit/transpiler/passes/scheduling/__init__.py +1 -7
  244. qiskit/transpiler/passes/scheduling/alignments/__init__.py +2 -4
  245. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -9
  246. qiskit/transpiler/passes/scheduling/alignments/reschedule.py +17 -16
  247. qiskit/transpiler/passes/scheduling/padding/base_padding.py +32 -4
  248. qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +25 -63
  249. qiskit/transpiler/passes/scheduling/padding/pad_delay.py +12 -4
  250. qiskit/transpiler/passes/scheduling/scheduling/alap.py +5 -39
  251. qiskit/transpiler/passes/scheduling/scheduling/asap.py +4 -35
  252. qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +10 -16
  253. qiskit/transpiler/passes/scheduling/time_unit_conversion.py +134 -62
  254. qiskit/transpiler/passes/synthesis/default_unitary_synth_plugin.py +653 -0
  255. qiskit/transpiler/passes/synthesis/high_level_synthesis.py +176 -601
  256. qiskit/transpiler/passes/synthesis/hls_plugins.py +294 -1
  257. qiskit/transpiler/passes/synthesis/plugin.py +4 -0
  258. qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +16 -10
  259. qiskit/transpiler/passes/synthesis/unitary_synthesis.py +34 -697
  260. qiskit/transpiler/passes/utils/__init__.py +0 -1
  261. qiskit/transpiler/passes/utils/check_gate_direction.py +13 -5
  262. qiskit/transpiler/passes/utils/control_flow.py +2 -6
  263. qiskit/transpiler/passes/utils/gate_direction.py +7 -0
  264. qiskit/transpiler/passes/utils/remove_final_measurements.py +40 -33
  265. qiskit/transpiler/passmanager.py +13 -0
  266. qiskit/transpiler/passmanager_config.py +5 -81
  267. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +225 -344
  268. qiskit/transpiler/preset_passmanagers/common.py +140 -167
  269. qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +107 -322
  270. qiskit/transpiler/preset_passmanagers/level0.py +2 -11
  271. qiskit/transpiler/preset_passmanagers/level1.py +2 -14
  272. qiskit/transpiler/preset_passmanagers/level2.py +2 -12
  273. qiskit/transpiler/preset_passmanagers/level3.py +2 -11
  274. qiskit/transpiler/preset_passmanagers/plugin.py +5 -3
  275. qiskit/transpiler/target.py +78 -524
  276. qiskit/user_config.py +8 -4
  277. qiskit/utils/__init__.py +13 -12
  278. qiskit/utils/deprecation.py +4 -112
  279. qiskit/utils/optionals.py +11 -4
  280. qiskit/utils/parallel.py +214 -87
  281. qiskit/utils/units.py +4 -1
  282. qiskit/visualization/__init__.py +3 -7
  283. qiskit/visualization/array.py +4 -1
  284. qiskit/visualization/bloch.py +1 -1
  285. qiskit/visualization/circuit/_utils.py +19 -19
  286. qiskit/visualization/circuit/circuit_visualization.py +11 -4
  287. qiskit/visualization/circuit/matplotlib.py +13 -23
  288. qiskit/visualization/circuit/text.py +7 -3
  289. qiskit/visualization/counts_visualization.py +4 -0
  290. qiskit/visualization/dag_visualization.py +2 -1
  291. qiskit/visualization/gate_map.py +39 -154
  292. qiskit/visualization/library.py +4 -1
  293. qiskit/visualization/pass_manager_visualization.py +6 -2
  294. qiskit/visualization/state_visualization.py +19 -2
  295. qiskit/visualization/timeline/core.py +19 -13
  296. qiskit/visualization/timeline/interface.py +19 -18
  297. qiskit/visualization/timeline/plotters/matplotlib.py +4 -1
  298. {qiskit-1.4.1.dist-info → qiskit-2.0.0.dist-info}/METADATA +4 -3
  299. {qiskit-1.4.1.dist-info → qiskit-2.0.0.dist-info}/RECORD +303 -449
  300. {qiskit-1.4.1.dist-info → qiskit-2.0.0.dist-info}/WHEEL +1 -1
  301. {qiskit-1.4.1.dist-info → qiskit-2.0.0.dist-info}/entry_points.txt +8 -2
  302. qiskit/assembler/__init__.py +0 -42
  303. qiskit/assembler/assemble_circuits.py +0 -451
  304. qiskit/assembler/assemble_schedules.py +0 -367
  305. qiskit/assembler/disassemble.py +0 -310
  306. qiskit/assembler/run_config.py +0 -77
  307. qiskit/circuit/bit.py +0 -106
  308. qiskit/circuit/classicalfunction/__init__.py +0 -152
  309. qiskit/circuit/classicalfunction/boolean_expression.py +0 -138
  310. qiskit/circuit/classicalfunction/classical_element.py +0 -54
  311. qiskit/circuit/classicalfunction/classical_function_visitor.py +0 -155
  312. qiskit/circuit/classicalfunction/classicalfunction.py +0 -182
  313. qiskit/circuit/classicalfunction/exceptions.py +0 -41
  314. qiskit/circuit/classicalfunction/types.py +0 -18
  315. qiskit/circuit/classicalfunction/utils.py +0 -91
  316. qiskit/circuit/classicalregister.py +0 -57
  317. qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +0 -405
  318. qiskit/circuit/quantumregister.py +0 -75
  319. qiskit/circuit/register.py +0 -246
  320. qiskit/compiler/assembler.py +0 -689
  321. qiskit/compiler/scheduler.py +0 -109
  322. qiskit/compiler/sequencer.py +0 -71
  323. qiskit/primitives/backend_estimator.py +0 -486
  324. qiskit/primitives/backend_sampler.py +0 -222
  325. qiskit/primitives/estimator.py +0 -172
  326. qiskit/primitives/sampler.py +0 -162
  327. qiskit/providers/backend_compat.py +0 -507
  328. qiskit/providers/fake_provider/backends_v1/__init__.py +0 -22
  329. qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/__init__.py +0 -18
  330. qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/conf_washington.json +0 -1
  331. qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/defs_washington.json +0 -1
  332. qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/fake_127q_pulse_v1.py +0 -37
  333. qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/props_washington.json +0 -1
  334. qiskit/providers/fake_provider/backends_v1/fake_20q/conf_singapore.json +0 -1
  335. qiskit/providers/fake_provider/backends_v1/fake_20q/fake_20q.py +0 -43
  336. qiskit/providers/fake_provider/backends_v1/fake_20q/props_singapore.json +0 -1
  337. qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/__init__.py +0 -18
  338. qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/conf_hanoi.json +0 -1
  339. qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/defs_hanoi.json +0 -1
  340. qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/fake_27q_pulse_v1.py +0 -50
  341. qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/props_hanoi.json +0 -1
  342. qiskit/providers/fake_provider/backends_v1/fake_5q/__init__.py +0 -18
  343. qiskit/providers/fake_provider/backends_v1/fake_5q/conf_yorktown.json +0 -1
  344. qiskit/providers/fake_provider/backends_v1/fake_5q/fake_5q_v1.py +0 -41
  345. qiskit/providers/fake_provider/backends_v1/fake_5q/props_yorktown.json +0 -1
  346. qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/__init__.py +0 -18
  347. qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/conf_nairobi.json +0 -1
  348. qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/defs_nairobi.json +0 -1
  349. qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/fake_7q_pulse_v1.py +0 -44
  350. qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/props_nairobi.json +0 -1
  351. qiskit/providers/fake_provider/fake_1q.py +0 -91
  352. qiskit/providers/fake_provider/fake_backend.py +0 -165
  353. qiskit/providers/fake_provider/fake_openpulse_2q.py +0 -391
  354. qiskit/providers/fake_provider/fake_openpulse_3q.py +0 -340
  355. qiskit/providers/fake_provider/fake_pulse_backend.py +0 -49
  356. qiskit/providers/fake_provider/fake_qasm_backend.py +0 -77
  357. qiskit/providers/fake_provider/utils/backend_converter.py +0 -150
  358. qiskit/providers/fake_provider/utils/json_decoder.py +0 -109
  359. qiskit/providers/models/__init__.py +0 -89
  360. qiskit/providers/models/backendconfiguration.py +0 -1040
  361. qiskit/providers/models/backendproperties.py +0 -535
  362. qiskit/providers/models/backendstatus.py +0 -104
  363. qiskit/providers/models/jobstatus.py +0 -77
  364. qiskit/providers/models/pulsedefaults.py +0 -305
  365. qiskit/providers/provider.py +0 -95
  366. qiskit/pulse/__init__.py +0 -158
  367. qiskit/pulse/builder.py +0 -2262
  368. qiskit/pulse/calibration_entries.py +0 -381
  369. qiskit/pulse/channels.py +0 -227
  370. qiskit/pulse/configuration.py +0 -245
  371. qiskit/pulse/exceptions.py +0 -45
  372. qiskit/pulse/filters.py +0 -309
  373. qiskit/pulse/instruction_schedule_map.py +0 -424
  374. qiskit/pulse/instructions/__init__.py +0 -67
  375. qiskit/pulse/instructions/acquire.py +0 -150
  376. qiskit/pulse/instructions/delay.py +0 -71
  377. qiskit/pulse/instructions/directives.py +0 -154
  378. qiskit/pulse/instructions/frequency.py +0 -135
  379. qiskit/pulse/instructions/instruction.py +0 -270
  380. qiskit/pulse/instructions/phase.py +0 -152
  381. qiskit/pulse/instructions/play.py +0 -99
  382. qiskit/pulse/instructions/reference.py +0 -100
  383. qiskit/pulse/instructions/snapshot.py +0 -82
  384. qiskit/pulse/library/__init__.py +0 -97
  385. qiskit/pulse/library/continuous.py +0 -430
  386. qiskit/pulse/library/pulse.py +0 -148
  387. qiskit/pulse/library/samplers/__init__.py +0 -15
  388. qiskit/pulse/library/samplers/decorators.py +0 -295
  389. qiskit/pulse/library/samplers/strategies.py +0 -71
  390. qiskit/pulse/library/symbolic_pulses.py +0 -1989
  391. qiskit/pulse/library/waveform.py +0 -136
  392. qiskit/pulse/macros.py +0 -262
  393. qiskit/pulse/parameter_manager.py +0 -445
  394. qiskit/pulse/parser.py +0 -314
  395. qiskit/pulse/reference_manager.py +0 -58
  396. qiskit/pulse/schedule.py +0 -1854
  397. qiskit/pulse/transforms/__init__.py +0 -106
  398. qiskit/pulse/transforms/alignments.py +0 -406
  399. qiskit/pulse/transforms/base_transforms.py +0 -71
  400. qiskit/pulse/transforms/canonicalization.py +0 -498
  401. qiskit/pulse/transforms/dag.py +0 -122
  402. qiskit/pulse/utils.py +0 -149
  403. qiskit/qobj/__init__.py +0 -75
  404. qiskit/qobj/common.py +0 -81
  405. qiskit/qobj/converters/__init__.py +0 -18
  406. qiskit/qobj/converters/lo_config.py +0 -177
  407. qiskit/qobj/converters/pulse_instruction.py +0 -897
  408. qiskit/qobj/pulse_qobj.py +0 -709
  409. qiskit/qobj/qasm_qobj.py +0 -708
  410. qiskit/qobj/utils.py +0 -46
  411. qiskit/result/mitigation/base_readout_mitigator.py +0 -79
  412. qiskit/result/mitigation/correlated_readout_mitigator.py +0 -277
  413. qiskit/result/mitigation/local_readout_mitigator.py +0 -328
  414. qiskit/result/mitigation/utils.py +0 -217
  415. qiskit/scheduler/__init__.py +0 -40
  416. qiskit/scheduler/config.py +0 -37
  417. qiskit/scheduler/lowering.py +0 -187
  418. qiskit/scheduler/methods/__init__.py +0 -15
  419. qiskit/scheduler/methods/basic.py +0 -140
  420. qiskit/scheduler/schedule_circuit.py +0 -69
  421. qiskit/scheduler/sequence.py +0 -104
  422. qiskit/transpiler/passes/calibration/__init__.py +0 -17
  423. qiskit/transpiler/passes/calibration/base_builder.py +0 -79
  424. qiskit/transpiler/passes/calibration/builders.py +0 -20
  425. qiskit/transpiler/passes/calibration/exceptions.py +0 -22
  426. qiskit/transpiler/passes/calibration/pulse_gate.py +0 -100
  427. qiskit/transpiler/passes/calibration/rx_builder.py +0 -164
  428. qiskit/transpiler/passes/calibration/rzx_builder.py +0 -411
  429. qiskit/transpiler/passes/calibration/rzx_templates.py +0 -58
  430. qiskit/transpiler/passes/optimization/cx_cancellation.py +0 -65
  431. qiskit/transpiler/passes/optimization/echo_rzx_weyl_decomposition.py +0 -162
  432. qiskit/transpiler/passes/optimization/normalize_rx_angle.py +0 -157
  433. qiskit/transpiler/passes/routing/stochastic_swap.py +0 -532
  434. qiskit/transpiler/passes/scheduling/alap.py +0 -153
  435. qiskit/transpiler/passes/scheduling/alignments/align_measures.py +0 -255
  436. qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +0 -107
  437. qiskit/transpiler/passes/scheduling/asap.py +0 -175
  438. qiskit/transpiler/passes/scheduling/base_scheduler.py +0 -310
  439. qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +0 -313
  440. qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +0 -93
  441. qiskit/utils/deprecate_pulse.py +0 -119
  442. qiskit/utils/multiprocessing.py +0 -56
  443. qiskit/visualization/pulse_v2/__init__.py +0 -21
  444. qiskit/visualization/pulse_v2/core.py +0 -901
  445. qiskit/visualization/pulse_v2/device_info.py +0 -173
  446. qiskit/visualization/pulse_v2/drawings.py +0 -253
  447. qiskit/visualization/pulse_v2/events.py +0 -254
  448. qiskit/visualization/pulse_v2/generators/__init__.py +0 -40
  449. qiskit/visualization/pulse_v2/generators/barrier.py +0 -76
  450. qiskit/visualization/pulse_v2/generators/chart.py +0 -208
  451. qiskit/visualization/pulse_v2/generators/frame.py +0 -436
  452. qiskit/visualization/pulse_v2/generators/snapshot.py +0 -133
  453. qiskit/visualization/pulse_v2/generators/waveform.py +0 -645
  454. qiskit/visualization/pulse_v2/interface.py +0 -459
  455. qiskit/visualization/pulse_v2/layouts.py +0 -387
  456. qiskit/visualization/pulse_v2/plotters/__init__.py +0 -17
  457. qiskit/visualization/pulse_v2/plotters/base_plotter.py +0 -53
  458. qiskit/visualization/pulse_v2/plotters/matplotlib.py +0 -201
  459. qiskit/visualization/pulse_v2/stylesheet.py +0 -312
  460. qiskit/visualization/pulse_v2/types.py +0 -242
  461. {qiskit-1.4.1.dist-info → qiskit-2.0.0.dist-info/licenses}/LICENSE.txt +0 -0
  462. {qiskit-1.4.1.dist-info → qiskit-2.0.0.dist-info}/top_level.txt +0 -0
@@ -17,32 +17,25 @@ High-level-synthesis transpiler pass.
17
17
  from __future__ import annotations
18
18
 
19
19
  import typing
20
- from functools import partial
21
20
  from collections.abc import Callable
22
21
 
23
22
  import numpy as np
24
23
 
25
- from qiskit.circuit.annotated_operation import Modifier
26
24
  from qiskit.circuit.operation import Operation
27
- from qiskit.circuit.instruction import Instruction
28
- from qiskit.converters import circuit_to_dag, dag_to_circuit
29
25
  from qiskit.transpiler.basepasses import TransformationPass
30
26
  from qiskit.circuit.quantumcircuit import QuantumCircuit
31
- from qiskit.circuit import ControlledGate, EquivalenceLibrary, equivalence, Qubit
32
- from qiskit.transpiler.passes.utils import control_flow
27
+ from qiskit.circuit import EquivalenceLibrary
33
28
  from qiskit.transpiler.target import Target
34
29
  from qiskit.transpiler.coupling import CouplingMap
35
30
  from qiskit.dagcircuit.dagcircuit import DAGCircuit
36
31
  from qiskit.transpiler.exceptions import TranspilerError
37
32
 
38
- from qiskit.circuit.annotated_operation import (
39
- AnnotatedOperation,
40
- InverseModifier,
41
- ControlModifier,
42
- PowerModifier,
33
+ from qiskit._accelerate.high_level_synthesis import (
34
+ QubitTracker,
35
+ HighLevelSynthesisData,
36
+ run_on_dag,
43
37
  )
44
38
 
45
- from qiskit._accelerate.high_level_synthesis import QubitTracker, QubitContext
46
39
  from .plugin import HighLevelSynthesisPluginManager
47
40
 
48
41
  if typing.TYPE_CHECKING:
@@ -230,32 +223,43 @@ class HighLevelSynthesis(TransformationPass):
230
223
  """
231
224
  super().__init__()
232
225
 
233
- if hls_config is not None:
234
- self.hls_config = hls_config
235
- else:
236
- # When the config file is not provided, we will use the "default" method
237
- # to synthesize Operations (when available).
238
- self.hls_config = HLSConfig(True)
239
-
240
- self.hls_plugin_manager = HighLevelSynthesisPluginManager()
241
- self._coupling_map = coupling_map
242
- self._target = target
243
- self._use_qubit_indices = use_qubit_indices
244
- self.qubits_initially_zero = qubits_initially_zero
226
+ # When the config file is not provided, we will use the "default" method
227
+ # to synthesize Operations (when available).
228
+ hls_config = hls_config or HLSConfig(True)
229
+ hls_plugin_manager = HighLevelSynthesisPluginManager()
230
+ hls_op_names = set(hls_plugin_manager.plugins_by_op.keys()).union(
231
+ set(hls_config.methods.keys())
232
+ )
233
+
245
234
  if target is not None:
246
- self._coupling_map = self._target.build_coupling_map()
247
- self._equiv_lib = equivalence_library
248
- self._basis_gates = basis_gates
249
- self._min_qubits = min_qubits
235
+ coupling_map = target.build_coupling_map()
250
236
 
251
- self._top_level_only = self._basis_gates is None and self._target is None
237
+ unroll_definitions = not (
238
+ (basis_gates is None or len(basis_gates) == 0)
239
+ and (target is None or len(target.operation_names) == 0)
240
+ )
252
241
 
253
242
  # include path for when target exists but target.num_qubits is None (BasicSimulator)
254
- if not self._top_level_only and (self._target is None or self._target.num_qubits is None):
243
+ if unroll_definitions and (target is None or target.num_qubits is None):
255
244
  basic_insts = {"measure", "reset", "barrier", "snapshot", "delay", "store"}
256
- self._device_insts = basic_insts | set(self._basis_gates)
245
+ device_insts = basic_insts | set(basis_gates)
257
246
  else:
258
- self._device_insts = set()
247
+ device_insts = set()
248
+
249
+ self.qubits_initially_zero = qubits_initially_zero
250
+
251
+ self.data = HighLevelSynthesisData(
252
+ hls_config=hls_config,
253
+ hls_plugin_manager=hls_plugin_manager,
254
+ coupling_map=coupling_map,
255
+ target=target,
256
+ equivalence_library=equivalence_library,
257
+ hls_op_names=hls_op_names,
258
+ device_insts=device_insts,
259
+ use_physical_indices=use_qubit_indices,
260
+ min_qubits=min_qubits,
261
+ unroll_definitions=unroll_definitions,
262
+ )
259
263
 
260
264
  def run(self, dag: DAGCircuit) -> DAGCircuit:
261
265
  """Run the HighLevelSynthesis pass on `dag`.
@@ -270,585 +274,156 @@ class HighLevelSynthesis(TransformationPass):
270
274
  TranspilerError: when the transpiler is unable to synthesize the given DAG
271
275
  (for instance, when the specified synthesis method is not available).
272
276
  """
273
- qubits = tuple(dag.find_bit(q).index for q in dag.qubits)
274
- context = QubitContext(list(range(len(dag.qubits))))
275
- tracker = QubitTracker(num_qubits=dag.num_qubits())
276
- if self.qubits_initially_zero:
277
- tracker.set_clean(context.to_globals(qubits))
278
-
279
- out_dag = self._run(dag, tracker, context, use_ancillas=True, top_level=True)
280
- return out_dag
281
-
282
- def _run(
283
- self,
284
- dag: DAGCircuit,
285
- tracker: QubitTracker,
286
- context: QubitContext,
287
- use_ancillas: bool,
288
- top_level: bool,
289
- ) -> DAGCircuit:
290
- """
291
- The main recursive function that synthesizes a DAGCircuit.
292
-
293
- Input:
294
- dag: the DAG to be synthesized.
295
- tracker: the global tracker, tracking the state of original qubits.
296
- context: the correspondence between the dag's qubits and the global qubits.
297
- use_ancillas: if True, synthesis algorithms are allowed to use ancillas.
298
- top_level: specifies if this is the top-level of the recursion.
299
-
300
- The function returns the synthesized DAG.
301
-
302
- Note that by using the auxiliary qubits to synthesize operations present in the input DAG,
303
- the synthesized DAG may be defined over more qubits than the input DAG. In this case,
304
- the function update in-place the global qubits tracker and extends the local-to-global
305
- context.
306
- """
307
-
308
- if dag.num_qubits() != context.num_qubits():
309
- raise TranspilerError("HighLevelSynthesis internal error.")
310
-
311
- # STEP 1: Check if HighLevelSynthesis can be skipped altogether. This is only
312
- # done at the top-level since this does not update the global qubits tracker.
313
- if top_level:
314
- for node in dag.op_nodes():
315
- qubits = tuple(dag.find_bit(q).index for q in node.qargs)
316
- if not self._definitely_skip_node(node, qubits, dag):
317
- break
318
- else:
319
- # The for-loop terminates without reaching the break statement
320
- if dag.num_qubits() != context.num_qubits():
321
- raise TranspilerError("HighLevelSynthesis internal error.")
322
- return dag
323
-
324
- # STEP 2: Analyze the nodes in the DAG. For each node in the DAG that needs
325
- # to be synthesized, we recursively synthesize it and store the result. For
326
- # instance, the result of synthesizing a custom gate is a DAGCircuit corresponding
327
- # to the (recursively synthesized) gate's definition. When the result is a
328
- # DAG, we also store its context (the mapping of its qubits to global qubits).
329
- # In addition, we keep track of the qubit states using the (global) qubits tracker.
330
- #
331
- # Note: This is a first version of a potentially more elaborate approach to find
332
- # good operation/ancilla allocations. The current approach is greedy and just gives
333
- # all available ancilla qubits to the current operation ("the-first-takes-all" approach).
334
- # It does not distribute ancilla qubits between different operations present in the DAG.
335
- synthesized_nodes = {}
336
-
337
- for node in dag.topological_op_nodes():
338
- qubits = tuple(dag.find_bit(q).index for q in node.qargs)
339
- processed = False
340
- synthesized = None
341
- synthesized_context = None
342
-
343
- # Start by handling special operations. Other cases can also be
344
- # considered: swaps, automatically simplifying control gate (e.g. if
345
- # a control is 0).
346
- if node.op.name in ["id", "delay", "barrier"]:
347
- # tracker not updated, these are no-ops
348
- processed = True
349
-
350
- elif node.op.name == "reset":
351
- # reset qubits to 0
352
- tracker.set_clean(context.to_globals(qubits))
353
- processed = True
354
-
355
- # check if synthesis for the operation can be skipped
356
- elif self._definitely_skip_node(node, qubits, dag):
357
- tracker.set_dirty(context.to_globals(qubits))
358
-
359
- # next check control flow
360
- elif node.is_control_flow():
361
- inner_context = context.restrict(qubits)
362
- synthesized = control_flow.map_blocks(
363
- partial(
364
- self._run,
365
- tracker=tracker,
366
- context=inner_context,
367
- use_ancillas=False,
368
- top_level=False,
369
- ),
370
- node.op,
371
- )
372
-
373
- # now we are free to synthesize
374
- else:
375
- # This returns the synthesized operation and its context (when the result is
376
- # a DAG, it's the correspondence between its qubits and the global qubits).
377
- # Also note that the DAG may use auxiliary qubits. The qubits tracker and the
378
- # current DAG's context are updated in-place.
379
- synthesized, synthesized_context = self._synthesize_operation(
380
- node.op, qubits, tracker, context, use_ancillas=use_ancillas
381
- )
382
-
383
- # If the synthesis changed the operation (i.e. it is not None), store the result.
384
- if synthesized is not None:
385
- synthesized_nodes[node._node_id] = (synthesized, synthesized_context)
386
-
387
- # If the synthesis did not change anything, just update the qubit tracker.
388
- elif not processed:
389
- tracker.set_dirty(context.to_globals(qubits))
390
-
391
- # We did not change anything just return the input.
392
- if len(synthesized_nodes) == 0:
393
- if dag.num_qubits() != context.num_qubits():
394
- raise TranspilerError("HighLevelSynthesis internal error.")
395
- return dag
396
-
397
- # STEP 3. We rebuild the DAG with new operations. Note that we could also
398
- # check if no operation changed in size and substitute in-place, but rebuilding is
399
- # generally as fast or faster, unless very few operations are changed.
400
- out = dag.copy_empty_like()
401
- num_additional_qubits = context.num_qubits() - out.num_qubits()
402
-
403
- if num_additional_qubits > 0:
404
- out.add_qubits([Qubit() for _ in range(num_additional_qubits)])
405
-
406
- index_to_qubit = dict(enumerate(out.qubits))
407
- outer_to_local = context.to_local_mapping()
408
-
409
- for node in dag.topological_op_nodes():
410
-
411
- if op_tuple := synthesized_nodes.get(node._node_id, None):
412
- op, op_context = op_tuple
413
-
414
- if isinstance(op, Operation):
415
- out.apply_operation_back(op, node.qargs, node.cargs)
416
- continue
417
-
418
- if isinstance(op, QuantumCircuit):
419
- op = circuit_to_dag(op, copy_operations=False)
420
-
421
- inner_to_global = op_context.to_global_mapping()
422
- if isinstance(op, DAGCircuit):
423
- qubit_map = {
424
- q: index_to_qubit[outer_to_local[inner_to_global[i]]]
425
- for (i, q) in enumerate(op.qubits)
426
- }
427
- clbit_map = dict(zip(op.clbits, node.cargs))
428
-
429
- for sub_node in op.op_nodes():
430
- out.apply_operation_back(
431
- sub_node.op,
432
- tuple(qubit_map[qarg] for qarg in sub_node.qargs),
433
- tuple(clbit_map[carg] for carg in sub_node.cargs),
434
- )
435
- out.global_phase += op.global_phase
436
-
437
- else:
438
- raise TranspilerError(f"Unexpected synthesized type: {type(op)}")
439
- else:
440
- out.apply_operation_back(node.op, node.qargs, node.cargs, check=False)
277
+ res = run_on_dag(dag, self.data, self.qubits_initially_zero)
278
+ return res if res is not None else dag
279
+
280
+
281
+ def _methods_to_try(data: HighLevelSynthesisData, name: str):
282
+ """Get a sequence of methods to try for a given op name."""
283
+ if (methods := data.hls_config.methods.get(name)) is not None:
284
+ # the operation's name appears in the user-provided config,
285
+ # we use the list of methods provided by the user
286
+ return methods
287
+ if (
288
+ data.hls_config.use_default_on_unspecified
289
+ and "default" in data.hls_plugin_manager.method_names(name)
290
+ ):
291
+ # the operation's name does not appear in the user-specified config,
292
+ # we use the "default" method when instructed to do so and the "default"
293
+ # method is available
294
+ return ["default"]
295
+ return []
296
+
297
+
298
+ def _synthesize_op_using_plugins(
299
+ operation: Operation,
300
+ input_qubits: tuple[int],
301
+ data: HighLevelSynthesisData,
302
+ tracker: QubitTracker,
303
+ ) -> tuple[QuantumCircuit, tuple[int], QubitTracker] | None:
304
+ """
305
+ Attempts to synthesize an operation using plugin mechanism.
441
306
 
442
- if out.num_qubits() != context.num_qubits():
443
- raise TranspilerError("HighLevelSynthesis internal error.")
307
+ Input:
308
+ operation: the operation to be synthesized.
309
+ input_qubits: a list of global qubits (qubits in the original circuit) over
310
+ which the operation is defined.
311
+ data: high-level-synthesis data and options.
312
+ tracker: the global tracker, tracking the state of global qubits.
313
+ hls_methods: the list of synthesis methods to try.
444
314
 
445
- return out
315
+ The function is called from within Rust code.
446
316
 
447
- def _synthesize_operation(
448
- self,
449
- operation: Operation,
450
- qubits: tuple[int],
451
- tracker: QubitTracker,
452
- context: QubitContext,
453
- use_ancillas: bool,
454
- ) -> tuple[QuantumCircuit | Operation | DAGCircuit | None, QubitContext | None]:
455
- """
456
- Synthesizes an operation. The function receives the qubits on which the operation
457
- is defined in the current DAG, the correspondence between the qubits of the current
458
- DAG and the global qubits and the global qubits tracker. The function returns the
459
- result of synthesizing the operation. The value of `None` means that the operation
460
- should remain as it is. When it's a circuit, we also return the context, i.e. the
461
- correspondence of its local qubits and the global qubits. The function changes
462
- in-place the tracker (state of the global qubits), the qubits (when the synthesized
463
- operation is defined over additional ancilla qubits), and the context (to keep track
464
- of where these ancilla qubits maps to).
465
- """
466
-
467
- synthesized_context = None
468
-
469
- # Try to synthesize the operation. We'll go through the following options:
470
- # (1) Annotations: if the operator is annotated, synthesize the base operation
471
- # and then apply the modifiers. Returns a circuit (e.g. applying a power)
472
- # or operation (e.g adding control on an X gate).
473
- # (2) High-level objects: try running the battery of high-level synthesis plugins (e.g.
474
- # if the operation is a Clifford). Returns a circuit.
475
- # (3) Unrolling custom definitions: try defining the operation if it is not yet
476
- # in the set of supported instructions. Returns a circuit.
477
- #
478
- # If any of the above were triggered, we will recurse and go again through these steps
479
- # until no further change occurred. At this point, we convert circuits to DAGs (the final
480
- # possible return type). If there was no change, we just return ``None``.
481
- num_original_qubits = len(qubits)
482
- qubits = list(qubits)
483
-
484
- synthesized = None
485
-
486
- # Try synthesizing via AnnotatedOperation. This is faster than an isinstance check
487
- # but a bit less safe since someone could create operations with a ``modifiers`` attribute.
488
- if len(modifiers := getattr(operation, "modifiers", [])) > 0:
489
- # Note: the base operation must be synthesized without using potential control qubits
490
- # used in the modifiers.
491
- num_ctrl = sum(
492
- mod.num_ctrl_qubits for mod in modifiers if isinstance(mod, ControlModifier)
493
- )
494
- baseop_qubits = qubits[num_ctrl:] # reminder: control qubits are the first ones
495
-
496
- # get qubits of base operation
497
- control_qubits = qubits[0:num_ctrl]
498
-
499
- # Do not allow access to control qubits
500
- tracker.disable(context.to_globals(control_qubits))
501
- synthesized_base_op, _ = self._synthesize_operation(
502
- operation.base_op,
503
- baseop_qubits,
504
- tracker,
505
- context,
506
- use_ancillas=use_ancillas,
507
- )
508
-
509
- if synthesized_base_op is None:
510
- synthesized_base_op = operation.base_op
511
- elif isinstance(synthesized_base_op, DAGCircuit):
512
- synthesized_base_op = dag_to_circuit(synthesized_base_op)
513
-
514
- # Handle the case that synthesizing the base operation introduced
515
- # additional qubits (e.g. the base operation is a circuit that includes
516
- # an MCX gate).
517
- if synthesized_base_op.num_qubits > len(baseop_qubits):
518
- global_aux_qubits = tracker.borrow(
519
- synthesized_base_op.num_qubits - len(baseop_qubits),
520
- context.to_globals(baseop_qubits),
521
- )
522
- global_to_local = context.to_local_mapping()
523
- for aq in global_aux_qubits:
524
- if aq in global_to_local:
525
- qubits.append(global_to_local[aq])
526
- else:
527
- new_local_qubit = context.add_qubit(aq)
528
- qubits.append(new_local_qubit)
529
- # Restore access to control qubits.
530
- tracker.enable(context.to_globals(control_qubits))
531
-
532
- # This step currently does not introduce ancilla qubits.
533
- synthesized = self._apply_annotations(synthesized_base_op, operation.modifiers)
534
-
535
- # If it was no AnnotatedOperation, try synthesizing via HLS or by unrolling.
317
+ Returns either the synthesized circuit or ``None`` (which may occur
318
+ when no synthesis methods is available or specified, or when there is
319
+ an insufficient number of auxiliary qubits).
320
+ """
321
+ hls_methods = _methods_to_try(data, operation.name)
322
+ if len(hls_methods) == 0:
323
+ return None
324
+
325
+ hls_plugin_manager = data.hls_plugin_manager
326
+ num_clean_ancillas = tracker.num_clean(input_qubits)
327
+ num_dirty_ancillas = tracker.num_dirty(input_qubits)
328
+
329
+ best_decomposition = None
330
+ best_score = np.inf
331
+
332
+ for method in hls_methods:
333
+ # There are two ways to specify a synthesis method. The more explicit
334
+ # way is to specify it as a tuple consisting of a synthesis algorithm and a
335
+ # list of additional arguments, e.g.,
336
+ # ("kms", {"all_mats": 1, "max_paths": 100, "orig_circuit": 0}), or
337
+ # ("pmh", {}).
338
+ # When the list of additional arguments is empty, one can also specify
339
+ # just the synthesis algorithm, e.g.,
340
+ # "pmh".
341
+ if isinstance(method, tuple):
342
+ plugin_specifier, plugin_args = method
536
343
  else:
537
- # Try synthesis via HLS -- which will return ``None`` if unsuccessful.
538
- indices = qubits if self._use_qubit_indices else None
539
- if len(hls_methods := self._methods_to_try(operation.name)) > 0:
540
- if use_ancillas:
541
- num_clean_available = tracker.num_clean(context.to_globals(qubits))
542
- num_dirty_available = tracker.num_dirty(context.to_globals(qubits))
543
- else:
544
- num_clean_available = 0
545
- num_dirty_available = 0
546
- synthesized = self._synthesize_op_using_plugins(
547
- hls_methods,
548
- operation,
549
- indices,
550
- num_clean_available,
551
- num_dirty_available,
552
- )
553
-
554
- # It may happen that the plugin synthesis method uses clean/dirty ancilla qubits
555
- if (synthesized is not None) and (synthesized.num_qubits > len(qubits)):
556
- # need to borrow more qubits from tracker
557
- global_aux_qubits = tracker.borrow(
558
- synthesized.num_qubits - len(qubits), context.to_globals(qubits)
559
- )
560
- global_to_local = context.to_local_mapping()
561
-
562
- for aq in global_aux_qubits:
563
- if aq in global_to_local:
564
- qubits.append(global_to_local[aq])
565
- else:
566
- new_local_qubit = context.add_qubit(aq)
567
- qubits.append(new_local_qubit)
568
-
569
- # If HLS did not apply, or was unsuccessful, try unrolling custom definitions.
570
- if synthesized is None and not self._top_level_only:
571
- synthesized = self._get_custom_definition(operation, indices)
572
-
573
- if synthesized is None:
574
- # if we didn't synthesize, there was nothing to unroll
575
- # updating the tracker will be handled upstream
576
- pass
577
-
578
- # if it has been synthesized, recurse and finally store the decomposition
579
- elif isinstance(synthesized, Operation):
580
- resynthesized, resynthesized_context = self._synthesize_operation(
581
- synthesized, qubits, tracker, context, use_ancillas=use_ancillas
582
- )
583
-
584
- if resynthesized is not None:
585
- synthesized = resynthesized
586
- else:
587
- tracker.set_dirty(context.to_globals(qubits))
588
- if isinstance(resynthesized, DAGCircuit):
589
- synthesized_context = resynthesized_context
590
-
591
- elif isinstance(synthesized, QuantumCircuit):
592
- # Synthesized is a quantum circuit which we want to process recursively.
593
- # For example, it's the definition circuit of a custom gate
594
- # or a circuit obtained by calling a synthesis method on a high-level-object.
595
- # In the second case, synthesized may have more qubits than the original node.
596
-
597
- as_dag = circuit_to_dag(synthesized, copy_operations=False)
598
- inner_context = context.restrict(qubits)
599
-
600
- if as_dag.num_qubits() != inner_context.num_qubits():
601
- raise TranspilerError("HighLevelSynthesis internal error.")
602
-
603
- # We save the current state of the tracker to be able to return the ancilla
604
- # qubits to the current positions. Note that at this point we do not know
605
- # which ancilla qubits will be allocated.
606
- saved_tracker = tracker.copy()
607
- synthesized = self._run(
608
- as_dag, tracker, inner_context, use_ancillas=use_ancillas, top_level=False
609
- )
610
- synthesized_context = inner_context
611
-
612
- if (synthesized is not None) and (synthesized.num_qubits() > len(qubits)):
613
- # need to borrow more qubits from tracker
614
- global_aux_qubits = tracker.borrow(
615
- synthesized.num_qubits() - len(qubits), context.to_globals(qubits)
616
- )
617
- global_to_local = context.to_local_mapping()
618
-
619
- for aq in global_aux_qubits:
620
- if aq in global_to_local:
621
- qubits.append(global_to_local[aq])
622
- else:
623
- new_local_qubit = context.add_qubit(aq)
624
- qubits.append(new_local_qubit)
625
-
626
- if len(qubits) > num_original_qubits:
627
- tracker.replace_state(
628
- saved_tracker, context.to_globals(qubits[num_original_qubits:])
344
+ plugin_specifier = method
345
+ plugin_args = {}
346
+
347
+ # There are two ways to specify a synthesis algorithm being run,
348
+ # either by name, e.g. "kms" (which then should be specified in entry_points),
349
+ # or directly as a class inherited from HighLevelSynthesisPlugin (which then
350
+ # does not need to be specified in entry_points).
351
+ if isinstance(plugin_specifier, str):
352
+ if plugin_specifier not in hls_plugin_manager.method_names(operation.name):
353
+ raise TranspilerError(
354
+ f"Specified method: {plugin_specifier} not found in available "
355
+ f"plugins for {operation.name}"
629
356
  )
630
-
357
+ plugin_method = hls_plugin_manager.method(operation.name, plugin_specifier)
631
358
  else:
632
- raise TranspilerError(f"Unexpected synthesized type: {type(synthesized)}")
633
-
634
- if isinstance(synthesized, DAGCircuit) and synthesized_context is None:
635
- raise TranspilerError("HighLevelSynthesis internal error.")
636
-
637
- return synthesized, synthesized_context
638
-
639
- def _get_custom_definition(
640
- self, inst: Instruction, qubits: list[int] | None
641
- ) -> QuantumCircuit | None:
642
- # check if the operation is already supported natively
643
- if not (isinstance(inst, ControlledGate) and inst._open_ctrl):
644
- # include path for when target exists but target.num_qubits is None (BasicSimulator)
645
- inst_supported = self._instruction_supported(inst.name, qubits)
646
- if inst_supported or (self._equiv_lib is not None and self._equiv_lib.has_entry(inst)):
647
- return None # we support this operation already
648
-
649
- # if not, try to get the definition
650
- try:
651
- definition = inst.definition
652
- except (TypeError, AttributeError) as err:
653
- raise TranspilerError(f"HighLevelSynthesis was unable to define {inst.name}.") from err
654
-
655
- if definition is None:
656
- raise TranspilerError(f"HighLevelSynthesis was unable to synthesize {inst}.")
657
-
658
- return definition
659
-
660
- def _methods_to_try(self, name: str):
661
- """Get a sequence of methods to try for a given op name."""
662
- if (methods := self.hls_config.methods.get(name)) is not None:
663
- # the operation's name appears in the user-provided config,
664
- # we use the list of methods provided by the user
665
- return methods
666
- if (
667
- self.hls_config.use_default_on_unspecified
668
- and "default" in self.hls_plugin_manager.method_names(name)
669
- ):
670
- # the operation's name does not appear in the user-specified config,
671
- # we use the "default" method when instructed to do so and the "default"
672
- # method is available
673
- return ["default"]
674
- return []
675
-
676
- def _synthesize_op_using_plugins(
677
- self,
678
- hls_methods: list,
679
- op: Operation,
680
- qubits: list[int] | None,
681
- num_clean_ancillas: int = 0,
682
- num_dirty_ancillas: int = 0,
683
- ) -> QuantumCircuit | None:
684
- """
685
- Attempts to synthesize op using plugin mechanism.
359
+ plugin_method = plugin_specifier
686
360
 
687
- The arguments ``num_clean_ancillas`` and ``num_dirty_ancillas`` specify
688
- the number of clean and dirty qubits available to synthesize the given
689
- operation. A synthesis method does not need to use these additional qubits.
361
+ # The additional arguments we pass to every plugin include the list of global
362
+ # qubits over which the operation is defined, high-level-synthesis data and options,
363
+ # and the tracker that tracks the state for global qubits.
364
+ #
365
+ # Note: the difference between the argument "qubits" passed explicitly to "run"
366
+ # and "input_qubits" passed via "plugin_args" is that for backwards compatibility
367
+ # the former should be None if the synthesis is done before layout/routing.
368
+ # However, plugins may need access to the global qubits over which the operation
369
+ # is defined, as well as their state, in particular the plugin for AnnotatedOperations
370
+ # requires these arguments to be able to process the base operation recursively.
371
+ #
372
+ # We may want to refactor the inputs and the outputs for the plugins' "run" method,
373
+ # however this needs to be backwards-compatible.
374
+ plugin_args["input_qubits"] = input_qubits
375
+ plugin_args["hls_data"] = data
376
+ plugin_args["qubit_tracker"] = tracker
377
+ plugin_args["num_clean_ancillas"] = num_clean_ancillas
378
+ plugin_args["num_dirty_ancillas"] = num_dirty_ancillas
379
+
380
+ qubits = input_qubits if data.use_physical_indices else None
381
+
382
+ decomposition = plugin_method.run(
383
+ operation,
384
+ coupling_map=data.coupling_map,
385
+ target=data.target,
386
+ qubits=qubits,
387
+ **plugin_args,
388
+ )
690
389
 
691
- Returns either the synthesized circuit or None (which may occur
692
- when no synthesis methods is available or specified, or when there is
693
- an insufficient number of auxiliary qubits).
694
- """
695
- hls_plugin_manager = self.hls_plugin_manager
696
-
697
- best_decomposition = None
698
- best_score = np.inf
699
-
700
- for method in hls_methods:
701
- # There are two ways to specify a synthesis method. The more explicit
702
- # way is to specify it as a tuple consisting of a synthesis algorithm and a
703
- # list of additional arguments, e.g.,
704
- # ("kms", {"all_mats": 1, "max_paths": 100, "orig_circuit": 0}), or
705
- # ("pmh", {}).
706
- # When the list of additional arguments is empty, one can also specify
707
- # just the synthesis algorithm, e.g.,
708
- # "pmh".
709
- if isinstance(method, tuple):
710
- plugin_specifier, plugin_args = method
711
- else:
712
- plugin_specifier = method
713
- plugin_args = {}
714
-
715
- # There are two ways to specify a synthesis algorithm being run,
716
- # either by name, e.g. "kms" (which then should be specified in entry_points),
717
- # or directly as a class inherited from HighLevelSynthesisPlugin (which then
718
- # does not need to be specified in entry_points).
719
- if isinstance(plugin_specifier, str):
720
- if plugin_specifier not in hls_plugin_manager.method_names(op.name):
721
- raise TranspilerError(
722
- f"Specified method: {plugin_specifier} not found in available "
723
- f"plugins for {op.name}"
724
- )
725
- plugin_method = hls_plugin_manager.method(op.name, plugin_specifier)
726
- else:
727
- plugin_method = plugin_specifier
728
-
729
- # Set the number of available clean and dirty auxiliary qubits via plugin args.
730
- plugin_args["num_clean_ancillas"] = num_clean_ancillas
731
- plugin_args["num_dirty_ancillas"] = num_dirty_ancillas
732
-
733
- decomposition = plugin_method.run(
734
- op,
735
- coupling_map=self._coupling_map,
736
- target=self._target,
737
- qubits=qubits,
738
- **plugin_args,
390
+ # The synthesis methods that are not suited for the given higher-level-object
391
+ # will return None.
392
+ if decomposition is not None:
393
+ if data.hls_config.plugin_selection == "sequential":
394
+ # In the "sequential" mode the first successful decomposition is
395
+ # returned.
396
+ best_decomposition = decomposition
397
+ break
398
+
399
+ # In the "run everything" mode we update the best decomposition
400
+ # discovered
401
+ current_score = data.hls_config.plugin_evaluation_fn(decomposition)
402
+ if current_score < best_score:
403
+ best_decomposition = decomposition
404
+ best_score = current_score
405
+
406
+ # A synthesis method may have potentially used available ancilla qubits.
407
+ # The following greedily grabs global qubits available. In the additional
408
+ # refactoring mentioned previously, we want each plugin to actually return
409
+ # the global qubits used, especially when the synthesis is done on the physical
410
+ # circuit, and the choice of which ancilla qubits to use really matters.
411
+ output_qubits = input_qubits
412
+ if best_decomposition is not None:
413
+ if best_decomposition.num_qubits > len(input_qubits):
414
+ global_aux_qubits = tracker.borrow(
415
+ best_decomposition.num_qubits - len(input_qubits), input_qubits
739
416
  )
417
+ output_qubits = output_qubits + global_aux_qubits
740
418
 
741
- # The synthesis methods that are not suited for the given higher-level-object
742
- # will return None.
743
- if decomposition is not None:
744
- if self.hls_config.plugin_selection == "sequential":
745
- # In the "sequential" mode the first successful decomposition is
746
- # returned.
747
- best_decomposition = decomposition
748
- break
749
-
750
- # In the "run everything" mode we update the best decomposition
751
- # discovered
752
- current_score = self.hls_config.plugin_evaluation_fn(decomposition)
753
- if current_score < best_score:
754
- best_decomposition = decomposition
755
- best_score = current_score
756
-
757
- return best_decomposition
758
-
759
- def _apply_annotations(
760
- self, synthesized: Operation | QuantumCircuit, modifiers: list[Modifier]
761
- ) -> QuantumCircuit:
762
- """
763
- Recursively synthesizes annotated operations.
764
- Returns either the synthesized operation or None (which occurs when the operation
765
- is not an annotated operation).
766
- """
767
- for modifier in modifiers:
768
- if isinstance(modifier, InverseModifier):
769
- # Both QuantumCircuit and Gate have inverse method
770
- synthesized = synthesized.inverse()
771
-
772
- elif isinstance(modifier, ControlModifier):
773
- # Both QuantumCircuit and Gate have control method, however for circuits
774
- # it is more efficient to avoid constructing the controlled quantum circuit.
775
- if isinstance(synthesized, QuantumCircuit):
776
- synthesized = synthesized.to_gate()
777
-
778
- synthesized = synthesized.control(
779
- num_ctrl_qubits=modifier.num_ctrl_qubits,
780
- label=None,
781
- ctrl_state=modifier.ctrl_state,
782
- annotated=False,
783
- )
784
-
785
- if isinstance(synthesized, AnnotatedOperation):
786
- raise TranspilerError(
787
- "HighLevelSynthesis failed to synthesize the control modifier."
788
- )
789
-
790
- elif isinstance(modifier, PowerModifier):
791
- # QuantumCircuit has power method, and Gate needs to be converted
792
- # to a quantum circuit.
793
- if not isinstance(synthesized, QuantumCircuit):
794
- synthesized = _instruction_to_circuit(synthesized)
795
-
796
- synthesized = synthesized.power(modifier.power)
797
-
798
- else:
799
- raise TranspilerError(f"Unknown modifier {modifier}.")
800
-
801
- return synthesized
802
-
803
- def _definitely_skip_node(
804
- self, node: DAGOpNode, qubits: tuple[int] | None, dag: DAGCircuit
805
- ) -> bool:
806
- """Fast-path determination of whether a node can certainly be skipped (i.e. nothing will
807
- attempt to synthesise it) without accessing its Python-space `Operation`.
808
-
809
- This is tightly coupled to `_recursively_handle_op`; it exists as a temporary measure to
810
- avoid Python-space `Operation` creation from a `DAGOpNode` if we wouldn't do anything to the
811
- node (which is _most_ nodes)."""
812
-
813
- if (
814
- dag._has_calibration_for(node)
815
- or len(node.qargs) < self._min_qubits
816
- or node.is_directive()
817
- or (self._instruction_supported(node.name, qubits) and not node.is_control_flow())
818
- ):
819
- return True
820
-
821
- return (
822
- # The fast path is just for Rust-space standard gates (which excludes
823
- # `AnnotatedOperation`).
824
- node.is_standard_gate()
825
- # We don't have the fast-path for controlled gates over 3 or more qubits.
826
- # However, we most probably want the fast-path for controlled 2-qubit gates
827
- # (such as CX, CZ, CY, CH, CRX, and so on), so "_definitely_skip_node" should
828
- # not immediately return False when encountering a controlled gate over 2 qubits.
829
- and not (node.is_controlled_gate() and node.num_qubits >= 3)
830
- # If there are plugins to try, they need to be tried.
831
- and not self._methods_to_try(node.name)
832
- # If all the above constraints hold, and it's already supported or the basis translator
833
- # can handle it, we'll leave it be.
834
- and (
835
- # This uses unfortunately private details of `EquivalenceLibrary`, but so does the
836
- # `BasisTranslator`, and this is supposed to just be temporary til this is moved
837
- # into Rust space.
838
- self._equiv_lib is not None
839
- and equivalence.Key(name=node.name, num_qubits=node.num_qubits)
840
- in self._equiv_lib.keys()
419
+ # This checks (in particular) that there is indeed a sufficient number
420
+ # of ancilla qubits to borrow from the tracker.
421
+ if best_decomposition.num_qubits != len(output_qubits):
422
+ raise TranspilerError(
423
+ "HighLevelSynthesis: the result from 'synthesize_op_using_plugin' is incorrect."
841
424
  )
842
- )
843
-
844
- def _instruction_supported(self, name: str, qubits: tuple[int] | None) -> bool:
845
- # include path for when target exists but target.num_qubits is None (BasicSimulator)
846
- if self._target is None or self._target.num_qubits is None:
847
- return name in self._device_insts
848
- return self._target.instruction_supported(operation_name=name, qargs=qubits)
849
425
 
426
+ if best_decomposition is None:
427
+ return None
850
428
 
851
- def _instruction_to_circuit(inst: Instruction) -> QuantumCircuit:
852
- circuit = QuantumCircuit(inst.num_qubits, inst.num_clbits)
853
- circuit.append(inst, circuit.qubits, circuit.clbits)
854
- return circuit
429
+ return (best_decomposition, output_qubits)