qiskit 2.1.0rc1__cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.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 (699) hide show
  1. qiskit/VERSION.txt +1 -0
  2. qiskit/__init__.py +159 -0
  3. qiskit/_accelerate.abi3.so +0 -0
  4. qiskit/_numpy_compat.py +73 -0
  5. qiskit/circuit/__init__.py +1335 -0
  6. qiskit/circuit/_add_control.py +338 -0
  7. qiskit/circuit/_classical_resource_map.py +154 -0
  8. qiskit/circuit/_standard_gates_commutations.py +3849 -0
  9. qiskit/circuit/_utils.py +167 -0
  10. qiskit/circuit/annotated_operation.py +279 -0
  11. qiskit/circuit/annotation.py +404 -0
  12. qiskit/circuit/barrier.py +46 -0
  13. qiskit/circuit/classical/__init__.py +41 -0
  14. qiskit/circuit/classical/expr/__init__.py +266 -0
  15. qiskit/circuit/classical/expr/constructors.py +764 -0
  16. qiskit/circuit/classical/expr/expr.py +156 -0
  17. qiskit/circuit/classical/expr/visitors.py +381 -0
  18. qiskit/circuit/classical/types/__init__.py +113 -0
  19. qiskit/circuit/classical/types/ordering.py +229 -0
  20. qiskit/circuit/classical/types/types.py +30 -0
  21. qiskit/circuit/commutation_checker.py +133 -0
  22. qiskit/circuit/commutation_library.py +20 -0
  23. qiskit/circuit/controlflow/__init__.py +59 -0
  24. qiskit/circuit/controlflow/_builder_utils.py +211 -0
  25. qiskit/circuit/controlflow/box.py +188 -0
  26. qiskit/circuit/controlflow/break_loop.py +56 -0
  27. qiskit/circuit/controlflow/builder.py +791 -0
  28. qiskit/circuit/controlflow/continue_loop.py +56 -0
  29. qiskit/circuit/controlflow/control_flow.py +94 -0
  30. qiskit/circuit/controlflow/for_loop.py +218 -0
  31. qiskit/circuit/controlflow/if_else.py +498 -0
  32. qiskit/circuit/controlflow/switch_case.py +411 -0
  33. qiskit/circuit/controlflow/while_loop.py +166 -0
  34. qiskit/circuit/controlledgate.py +274 -0
  35. qiskit/circuit/delay.py +159 -0
  36. qiskit/circuit/duration.py +80 -0
  37. qiskit/circuit/equivalence.py +94 -0
  38. qiskit/circuit/equivalence_library.py +18 -0
  39. qiskit/circuit/exceptions.py +19 -0
  40. qiskit/circuit/gate.py +261 -0
  41. qiskit/circuit/instruction.py +564 -0
  42. qiskit/circuit/instructionset.py +132 -0
  43. qiskit/circuit/library/__init__.py +984 -0
  44. qiskit/circuit/library/arithmetic/__init__.py +40 -0
  45. qiskit/circuit/library/arithmetic/adders/__init__.py +18 -0
  46. qiskit/circuit/library/arithmetic/adders/adder.py +235 -0
  47. qiskit/circuit/library/arithmetic/adders/cdkm_ripple_carry_adder.py +123 -0
  48. qiskit/circuit/library/arithmetic/adders/draper_qft_adder.py +129 -0
  49. qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py +95 -0
  50. qiskit/circuit/library/arithmetic/exact_reciprocal.py +131 -0
  51. qiskit/circuit/library/arithmetic/functional_pauli_rotations.py +114 -0
  52. qiskit/circuit/library/arithmetic/integer_comparator.py +200 -0
  53. qiskit/circuit/library/arithmetic/linear_amplitude_function.py +363 -0
  54. qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +243 -0
  55. qiskit/circuit/library/arithmetic/multipliers/__init__.py +17 -0
  56. qiskit/circuit/library/arithmetic/multipliers/hrs_cumulative_multiplier.py +145 -0
  57. qiskit/circuit/library/arithmetic/multipliers/multiplier.py +201 -0
  58. qiskit/circuit/library/arithmetic/multipliers/rg_qft_multiplier.py +108 -0
  59. qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +506 -0
  60. qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +395 -0
  61. qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +501 -0
  62. qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py +389 -0
  63. qiskit/circuit/library/arithmetic/quadratic_form.py +370 -0
  64. qiskit/circuit/library/arithmetic/weighted_adder.py +428 -0
  65. qiskit/circuit/library/basis_change/__init__.py +15 -0
  66. qiskit/circuit/library/basis_change/qft.py +316 -0
  67. qiskit/circuit/library/bit_flip_oracle.py +130 -0
  68. qiskit/circuit/library/blueprintcircuit.py +322 -0
  69. qiskit/circuit/library/boolean_logic/__init__.py +18 -0
  70. qiskit/circuit/library/boolean_logic/inner_product.py +157 -0
  71. qiskit/circuit/library/boolean_logic/quantum_and.py +204 -0
  72. qiskit/circuit/library/boolean_logic/quantum_or.py +206 -0
  73. qiskit/circuit/library/boolean_logic/quantum_xor.py +167 -0
  74. qiskit/circuit/library/data_preparation/__init__.py +57 -0
  75. qiskit/circuit/library/data_preparation/_z_feature_map.py +115 -0
  76. qiskit/circuit/library/data_preparation/_zz_feature_map.py +150 -0
  77. qiskit/circuit/library/data_preparation/initializer.py +107 -0
  78. qiskit/circuit/library/data_preparation/pauli_feature_map.py +656 -0
  79. qiskit/circuit/library/data_preparation/state_preparation.py +336 -0
  80. qiskit/circuit/library/fourier_checking.py +160 -0
  81. qiskit/circuit/library/generalized_gates/__init__.py +30 -0
  82. qiskit/circuit/library/generalized_gates/diagonal.py +163 -0
  83. qiskit/circuit/library/generalized_gates/gms.py +179 -0
  84. qiskit/circuit/library/generalized_gates/gr.py +219 -0
  85. qiskit/circuit/library/generalized_gates/isometry.py +370 -0
  86. qiskit/circuit/library/generalized_gates/linear_function.py +318 -0
  87. qiskit/circuit/library/generalized_gates/mcg_up_to_diagonal.py +143 -0
  88. qiskit/circuit/library/generalized_gates/mcmt.py +316 -0
  89. qiskit/circuit/library/generalized_gates/pauli.py +84 -0
  90. qiskit/circuit/library/generalized_gates/permutation.py +202 -0
  91. qiskit/circuit/library/generalized_gates/rv.py +96 -0
  92. qiskit/circuit/library/generalized_gates/uc.py +303 -0
  93. qiskit/circuit/library/generalized_gates/uc_pauli_rot.py +164 -0
  94. qiskit/circuit/library/generalized_gates/ucrx.py +32 -0
  95. qiskit/circuit/library/generalized_gates/ucry.py +32 -0
  96. qiskit/circuit/library/generalized_gates/ucrz.py +32 -0
  97. qiskit/circuit/library/generalized_gates/unitary.py +236 -0
  98. qiskit/circuit/library/graph_state.py +172 -0
  99. qiskit/circuit/library/grover_operator.py +583 -0
  100. qiskit/circuit/library/hamiltonian_gate.py +142 -0
  101. qiskit/circuit/library/hidden_linear_function.py +163 -0
  102. qiskit/circuit/library/iqp.py +180 -0
  103. qiskit/circuit/library/n_local/__init__.py +45 -0
  104. qiskit/circuit/library/n_local/efficient_su2.py +282 -0
  105. qiskit/circuit/library/n_local/evolved_operator_ansatz.py +520 -0
  106. qiskit/circuit/library/n_local/excitation_preserving.py +301 -0
  107. qiskit/circuit/library/n_local/n_local.py +1478 -0
  108. qiskit/circuit/library/n_local/pauli_two_design.py +246 -0
  109. qiskit/circuit/library/n_local/qaoa_ansatz.py +367 -0
  110. qiskit/circuit/library/n_local/real_amplitudes.py +312 -0
  111. qiskit/circuit/library/n_local/two_local.py +289 -0
  112. qiskit/circuit/library/overlap.py +183 -0
  113. qiskit/circuit/library/pauli_evolution.py +202 -0
  114. qiskit/circuit/library/phase_estimation.py +177 -0
  115. qiskit/circuit/library/phase_oracle.py +239 -0
  116. qiskit/circuit/library/quantum_volume.py +179 -0
  117. qiskit/circuit/library/standard_gates/__init__.py +141 -0
  118. qiskit/circuit/library/standard_gates/dcx.py +76 -0
  119. qiskit/circuit/library/standard_gates/ecr.py +126 -0
  120. qiskit/circuit/library/standard_gates/equivalence_library.py +1936 -0
  121. qiskit/circuit/library/standard_gates/global_phase.py +83 -0
  122. qiskit/circuit/library/standard_gates/h.py +230 -0
  123. qiskit/circuit/library/standard_gates/i.py +76 -0
  124. qiskit/circuit/library/standard_gates/iswap.py +115 -0
  125. qiskit/circuit/library/standard_gates/p.py +415 -0
  126. qiskit/circuit/library/standard_gates/r.py +108 -0
  127. qiskit/circuit/library/standard_gates/rx.py +269 -0
  128. qiskit/circuit/library/standard_gates/rxx.py +165 -0
  129. qiskit/circuit/library/standard_gates/ry.py +268 -0
  130. qiskit/circuit/library/standard_gates/ryy.py +165 -0
  131. qiskit/circuit/library/standard_gates/rz.py +290 -0
  132. qiskit/circuit/library/standard_gates/rzx.py +211 -0
  133. qiskit/circuit/library/standard_gates/rzz.py +181 -0
  134. qiskit/circuit/library/standard_gates/s.py +424 -0
  135. qiskit/circuit/library/standard_gates/swap.py +268 -0
  136. qiskit/circuit/library/standard_gates/sx.py +303 -0
  137. qiskit/circuit/library/standard_gates/t.py +169 -0
  138. qiskit/circuit/library/standard_gates/u.py +379 -0
  139. qiskit/circuit/library/standard_gates/u1.py +466 -0
  140. qiskit/circuit/library/standard_gates/u2.py +145 -0
  141. qiskit/circuit/library/standard_gates/u3.py +412 -0
  142. qiskit/circuit/library/standard_gates/x.py +1335 -0
  143. qiskit/circuit/library/standard_gates/xx_minus_yy.py +164 -0
  144. qiskit/circuit/library/standard_gates/xx_plus_yy.py +197 -0
  145. qiskit/circuit/library/standard_gates/y.py +253 -0
  146. qiskit/circuit/library/standard_gates/z.py +331 -0
  147. qiskit/circuit/library/templates/__init__.py +92 -0
  148. qiskit/circuit/library/templates/clifford/__init__.py +33 -0
  149. qiskit/circuit/library/templates/clifford/clifford_2_1.py +34 -0
  150. qiskit/circuit/library/templates/clifford/clifford_2_2.py +35 -0
  151. qiskit/circuit/library/templates/clifford/clifford_2_3.py +34 -0
  152. qiskit/circuit/library/templates/clifford/clifford_2_4.py +34 -0
  153. qiskit/circuit/library/templates/clifford/clifford_3_1.py +35 -0
  154. qiskit/circuit/library/templates/clifford/clifford_4_1.py +38 -0
  155. qiskit/circuit/library/templates/clifford/clifford_4_2.py +37 -0
  156. qiskit/circuit/library/templates/clifford/clifford_4_3.py +38 -0
  157. qiskit/circuit/library/templates/clifford/clifford_4_4.py +37 -0
  158. qiskit/circuit/library/templates/clifford/clifford_5_1.py +40 -0
  159. qiskit/circuit/library/templates/clifford/clifford_6_1.py +40 -0
  160. qiskit/circuit/library/templates/clifford/clifford_6_2.py +40 -0
  161. qiskit/circuit/library/templates/clifford/clifford_6_3.py +40 -0
  162. qiskit/circuit/library/templates/clifford/clifford_6_4.py +38 -0
  163. qiskit/circuit/library/templates/clifford/clifford_6_5.py +40 -0
  164. qiskit/circuit/library/templates/clifford/clifford_8_1.py +42 -0
  165. qiskit/circuit/library/templates/clifford/clifford_8_2.py +42 -0
  166. qiskit/circuit/library/templates/clifford/clifford_8_3.py +41 -0
  167. qiskit/circuit/library/templates/nct/__init__.py +67 -0
  168. qiskit/circuit/library/templates/nct/template_nct_2a_1.py +34 -0
  169. qiskit/circuit/library/templates/nct/template_nct_2a_2.py +35 -0
  170. qiskit/circuit/library/templates/nct/template_nct_2a_3.py +37 -0
  171. qiskit/circuit/library/templates/nct/template_nct_4a_1.py +43 -0
  172. qiskit/circuit/library/templates/nct/template_nct_4a_2.py +41 -0
  173. qiskit/circuit/library/templates/nct/template_nct_4a_3.py +39 -0
  174. qiskit/circuit/library/templates/nct/template_nct_4b_1.py +41 -0
  175. qiskit/circuit/library/templates/nct/template_nct_4b_2.py +39 -0
  176. qiskit/circuit/library/templates/nct/template_nct_5a_1.py +40 -0
  177. qiskit/circuit/library/templates/nct/template_nct_5a_2.py +40 -0
  178. qiskit/circuit/library/templates/nct/template_nct_5a_3.py +40 -0
  179. qiskit/circuit/library/templates/nct/template_nct_5a_4.py +39 -0
  180. qiskit/circuit/library/templates/nct/template_nct_6a_1.py +40 -0
  181. qiskit/circuit/library/templates/nct/template_nct_6a_2.py +41 -0
  182. qiskit/circuit/library/templates/nct/template_nct_6a_3.py +41 -0
  183. qiskit/circuit/library/templates/nct/template_nct_6a_4.py +41 -0
  184. qiskit/circuit/library/templates/nct/template_nct_6b_1.py +41 -0
  185. qiskit/circuit/library/templates/nct/template_nct_6b_2.py +41 -0
  186. qiskit/circuit/library/templates/nct/template_nct_6c_1.py +41 -0
  187. qiskit/circuit/library/templates/nct/template_nct_7a_1.py +43 -0
  188. qiskit/circuit/library/templates/nct/template_nct_7b_1.py +43 -0
  189. qiskit/circuit/library/templates/nct/template_nct_7c_1.py +43 -0
  190. qiskit/circuit/library/templates/nct/template_nct_7d_1.py +43 -0
  191. qiskit/circuit/library/templates/nct/template_nct_7e_1.py +43 -0
  192. qiskit/circuit/library/templates/nct/template_nct_9a_1.py +45 -0
  193. qiskit/circuit/library/templates/nct/template_nct_9c_1.py +43 -0
  194. qiskit/circuit/library/templates/nct/template_nct_9c_10.py +44 -0
  195. qiskit/circuit/library/templates/nct/template_nct_9c_11.py +44 -0
  196. qiskit/circuit/library/templates/nct/template_nct_9c_12.py +44 -0
  197. qiskit/circuit/library/templates/nct/template_nct_9c_2.py +44 -0
  198. qiskit/circuit/library/templates/nct/template_nct_9c_3.py +44 -0
  199. qiskit/circuit/library/templates/nct/template_nct_9c_4.py +44 -0
  200. qiskit/circuit/library/templates/nct/template_nct_9c_5.py +44 -0
  201. qiskit/circuit/library/templates/nct/template_nct_9c_6.py +44 -0
  202. qiskit/circuit/library/templates/nct/template_nct_9c_7.py +44 -0
  203. qiskit/circuit/library/templates/nct/template_nct_9c_8.py +44 -0
  204. qiskit/circuit/library/templates/nct/template_nct_9c_9.py +44 -0
  205. qiskit/circuit/library/templates/nct/template_nct_9d_1.py +43 -0
  206. qiskit/circuit/library/templates/nct/template_nct_9d_10.py +44 -0
  207. qiskit/circuit/library/templates/nct/template_nct_9d_2.py +44 -0
  208. qiskit/circuit/library/templates/nct/template_nct_9d_3.py +44 -0
  209. qiskit/circuit/library/templates/nct/template_nct_9d_4.py +44 -0
  210. qiskit/circuit/library/templates/nct/template_nct_9d_5.py +44 -0
  211. qiskit/circuit/library/templates/nct/template_nct_9d_6.py +44 -0
  212. qiskit/circuit/library/templates/nct/template_nct_9d_7.py +44 -0
  213. qiskit/circuit/library/templates/nct/template_nct_9d_8.py +44 -0
  214. qiskit/circuit/library/templates/nct/template_nct_9d_9.py +44 -0
  215. qiskit/circuit/library/templates/rzx/__init__.py +25 -0
  216. qiskit/circuit/library/templates/rzx/rzx_cy.py +47 -0
  217. qiskit/circuit/library/templates/rzx/rzx_xz.py +54 -0
  218. qiskit/circuit/library/templates/rzx/rzx_yz.py +45 -0
  219. qiskit/circuit/library/templates/rzx/rzx_zz1.py +69 -0
  220. qiskit/circuit/library/templates/rzx/rzx_zz2.py +59 -0
  221. qiskit/circuit/library/templates/rzx/rzx_zz3.py +59 -0
  222. qiskit/circuit/measure.py +53 -0
  223. qiskit/circuit/operation.py +68 -0
  224. qiskit/circuit/parameter.py +188 -0
  225. qiskit/circuit/parameterexpression.py +737 -0
  226. qiskit/circuit/parametertable.py +119 -0
  227. qiskit/circuit/parametervector.py +140 -0
  228. qiskit/circuit/quantumcircuit.py +7610 -0
  229. qiskit/circuit/quantumcircuitdata.py +137 -0
  230. qiskit/circuit/random/__init__.py +50 -0
  231. qiskit/circuit/random/utils.py +755 -0
  232. qiskit/circuit/reset.py +37 -0
  233. qiskit/circuit/singleton.py +600 -0
  234. qiskit/circuit/store.py +89 -0
  235. qiskit/circuit/tools/__init__.py +16 -0
  236. qiskit/circuit/tools/pi_check.py +185 -0
  237. qiskit/circuit/twirling.py +145 -0
  238. qiskit/compiler/__init__.py +27 -0
  239. qiskit/compiler/transpiler.py +375 -0
  240. qiskit/converters/__init__.py +74 -0
  241. qiskit/converters/circuit_to_dag.py +80 -0
  242. qiskit/converters/circuit_to_dagdependency.py +49 -0
  243. qiskit/converters/circuit_to_dagdependency_v2.py +46 -0
  244. qiskit/converters/circuit_to_gate.py +107 -0
  245. qiskit/converters/circuit_to_instruction.py +142 -0
  246. qiskit/converters/dag_to_circuit.py +79 -0
  247. qiskit/converters/dag_to_dagdependency.py +54 -0
  248. qiskit/converters/dag_to_dagdependency_v2.py +43 -0
  249. qiskit/converters/dagdependency_to_circuit.py +40 -0
  250. qiskit/converters/dagdependency_to_dag.py +48 -0
  251. qiskit/dagcircuit/__init__.py +44 -0
  252. qiskit/dagcircuit/collect_blocks.py +403 -0
  253. qiskit/dagcircuit/dagcircuit.py +24 -0
  254. qiskit/dagcircuit/dagdependency.py +612 -0
  255. qiskit/dagcircuit/dagdependency_v2.py +566 -0
  256. qiskit/dagcircuit/dagdepnode.py +160 -0
  257. qiskit/dagcircuit/dagnode.py +193 -0
  258. qiskit/dagcircuit/exceptions.py +42 -0
  259. qiskit/exceptions.py +153 -0
  260. qiskit/passmanager/__init__.py +258 -0
  261. qiskit/passmanager/base_tasks.py +230 -0
  262. qiskit/passmanager/compilation_status.py +74 -0
  263. qiskit/passmanager/exceptions.py +19 -0
  264. qiskit/passmanager/flow_controllers.py +116 -0
  265. qiskit/passmanager/passmanager.py +353 -0
  266. qiskit/primitives/__init__.py +490 -0
  267. qiskit/primitives/backend_estimator_v2.py +530 -0
  268. qiskit/primitives/backend_sampler_v2.py +339 -0
  269. qiskit/primitives/base/__init__.py +20 -0
  270. qiskit/primitives/base/base_estimator.py +247 -0
  271. qiskit/primitives/base/base_primitive_job.py +78 -0
  272. qiskit/primitives/base/base_primitive_v1.py +45 -0
  273. qiskit/primitives/base/base_result_v1.py +65 -0
  274. qiskit/primitives/base/base_sampler.py +196 -0
  275. qiskit/primitives/base/estimator_result_v1.py +46 -0
  276. qiskit/primitives/base/sampler_result_v1.py +45 -0
  277. qiskit/primitives/base/validation_v1.py +250 -0
  278. qiskit/primitives/containers/__init__.py +26 -0
  279. qiskit/primitives/containers/bindings_array.py +391 -0
  280. qiskit/primitives/containers/bit_array.py +764 -0
  281. qiskit/primitives/containers/data_bin.py +172 -0
  282. qiskit/primitives/containers/estimator_pub.py +222 -0
  283. qiskit/primitives/containers/object_array.py +94 -0
  284. qiskit/primitives/containers/observables_array.py +380 -0
  285. qiskit/primitives/containers/primitive_result.py +53 -0
  286. qiskit/primitives/containers/pub_result.py +51 -0
  287. qiskit/primitives/containers/sampler_pub.py +193 -0
  288. qiskit/primitives/containers/sampler_pub_result.py +74 -0
  289. qiskit/primitives/containers/shape.py +129 -0
  290. qiskit/primitives/primitive_job.py +100 -0
  291. qiskit/primitives/statevector_estimator.py +175 -0
  292. qiskit/primitives/statevector_sampler.py +290 -0
  293. qiskit/primitives/utils.py +72 -0
  294. qiskit/providers/__init__.py +677 -0
  295. qiskit/providers/backend.py +364 -0
  296. qiskit/providers/basic_provider/__init__.py +47 -0
  297. qiskit/providers/basic_provider/basic_provider.py +121 -0
  298. qiskit/providers/basic_provider/basic_provider_job.py +65 -0
  299. qiskit/providers/basic_provider/basic_provider_tools.py +218 -0
  300. qiskit/providers/basic_provider/basic_simulator.py +693 -0
  301. qiskit/providers/basic_provider/exceptions.py +30 -0
  302. qiskit/providers/exceptions.py +33 -0
  303. qiskit/providers/fake_provider/__init__.py +69 -0
  304. qiskit/providers/fake_provider/generic_backend_v2.py +376 -0
  305. qiskit/providers/fake_provider/utils/__init__.py +15 -0
  306. qiskit/providers/job.py +147 -0
  307. qiskit/providers/jobstatus.py +30 -0
  308. qiskit/providers/options.py +273 -0
  309. qiskit/providers/providerutils.py +110 -0
  310. qiskit/qasm/libs/dummy/stdgates.inc +75 -0
  311. qiskit/qasm/libs/qelib1.inc +266 -0
  312. qiskit/qasm/libs/stdgates.inc +82 -0
  313. qiskit/qasm2/__init__.py +669 -0
  314. qiskit/qasm2/exceptions.py +27 -0
  315. qiskit/qasm2/export.py +364 -0
  316. qiskit/qasm2/parse.py +438 -0
  317. qiskit/qasm3/__init__.py +466 -0
  318. qiskit/qasm3/ast.py +796 -0
  319. qiskit/qasm3/exceptions.py +27 -0
  320. qiskit/qasm3/experimental.py +70 -0
  321. qiskit/qasm3/exporter.py +1363 -0
  322. qiskit/qasm3/printer.py +620 -0
  323. qiskit/qpy/__init__.py +2141 -0
  324. qiskit/qpy/binary_io/__init__.py +35 -0
  325. qiskit/qpy/binary_io/circuits.py +1687 -0
  326. qiskit/qpy/binary_io/parse_sympy_repr.py +126 -0
  327. qiskit/qpy/binary_io/schedules.py +288 -0
  328. qiskit/qpy/binary_io/value.py +1183 -0
  329. qiskit/qpy/common.py +361 -0
  330. qiskit/qpy/exceptions.py +53 -0
  331. qiskit/qpy/formats.py +458 -0
  332. qiskit/qpy/interface.py +384 -0
  333. qiskit/qpy/type_keys.py +415 -0
  334. qiskit/quantum_info/__init__.py +172 -0
  335. qiskit/quantum_info/analysis/__init__.py +17 -0
  336. qiskit/quantum_info/analysis/average.py +47 -0
  337. qiskit/quantum_info/analysis/distance.py +104 -0
  338. qiskit/quantum_info/analysis/make_observable.py +44 -0
  339. qiskit/quantum_info/analysis/z2_symmetries.py +484 -0
  340. qiskit/quantum_info/operators/__init__.py +29 -0
  341. qiskit/quantum_info/operators/base_operator.py +145 -0
  342. qiskit/quantum_info/operators/channel/__init__.py +29 -0
  343. qiskit/quantum_info/operators/channel/chi.py +191 -0
  344. qiskit/quantum_info/operators/channel/choi.py +218 -0
  345. qiskit/quantum_info/operators/channel/kraus.py +337 -0
  346. qiskit/quantum_info/operators/channel/ptm.py +204 -0
  347. qiskit/quantum_info/operators/channel/quantum_channel.py +348 -0
  348. qiskit/quantum_info/operators/channel/stinespring.py +296 -0
  349. qiskit/quantum_info/operators/channel/superop.py +373 -0
  350. qiskit/quantum_info/operators/channel/transformations.py +490 -0
  351. qiskit/quantum_info/operators/custom_iterator.py +48 -0
  352. qiskit/quantum_info/operators/dihedral/__init__.py +18 -0
  353. qiskit/quantum_info/operators/dihedral/dihedral.py +511 -0
  354. qiskit/quantum_info/operators/dihedral/dihedral_circuits.py +216 -0
  355. qiskit/quantum_info/operators/dihedral/polynomial.py +313 -0
  356. qiskit/quantum_info/operators/dihedral/random.py +64 -0
  357. qiskit/quantum_info/operators/linear_op.py +25 -0
  358. qiskit/quantum_info/operators/measures.py +418 -0
  359. qiskit/quantum_info/operators/mixins/__init__.py +52 -0
  360. qiskit/quantum_info/operators/mixins/adjoint.py +52 -0
  361. qiskit/quantum_info/operators/mixins/group.py +171 -0
  362. qiskit/quantum_info/operators/mixins/linear.py +84 -0
  363. qiskit/quantum_info/operators/mixins/multiply.py +62 -0
  364. qiskit/quantum_info/operators/mixins/tolerances.py +72 -0
  365. qiskit/quantum_info/operators/op_shape.py +525 -0
  366. qiskit/quantum_info/operators/operator.py +869 -0
  367. qiskit/quantum_info/operators/operator_utils.py +76 -0
  368. qiskit/quantum_info/operators/predicates.py +183 -0
  369. qiskit/quantum_info/operators/random.py +154 -0
  370. qiskit/quantum_info/operators/scalar_op.py +254 -0
  371. qiskit/quantum_info/operators/symplectic/__init__.py +24 -0
  372. qiskit/quantum_info/operators/symplectic/base_pauli.py +719 -0
  373. qiskit/quantum_info/operators/symplectic/clifford.py +1032 -0
  374. qiskit/quantum_info/operators/symplectic/clifford_circuits.py +584 -0
  375. qiskit/quantum_info/operators/symplectic/pauli.py +755 -0
  376. qiskit/quantum_info/operators/symplectic/pauli_list.py +1242 -0
  377. qiskit/quantum_info/operators/symplectic/pauli_utils.py +40 -0
  378. qiskit/quantum_info/operators/symplectic/random.py +117 -0
  379. qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +1239 -0
  380. qiskit/quantum_info/operators/utils/__init__.py +20 -0
  381. qiskit/quantum_info/operators/utils/anti_commutator.py +36 -0
  382. qiskit/quantum_info/operators/utils/commutator.py +36 -0
  383. qiskit/quantum_info/operators/utils/double_commutator.py +76 -0
  384. qiskit/quantum_info/quaternion.py +156 -0
  385. qiskit/quantum_info/random.py +26 -0
  386. qiskit/quantum_info/states/__init__.py +28 -0
  387. qiskit/quantum_info/states/densitymatrix.py +857 -0
  388. qiskit/quantum_info/states/measures.py +288 -0
  389. qiskit/quantum_info/states/quantum_state.py +503 -0
  390. qiskit/quantum_info/states/random.py +157 -0
  391. qiskit/quantum_info/states/stabilizerstate.py +805 -0
  392. qiskit/quantum_info/states/statevector.py +977 -0
  393. qiskit/quantum_info/states/utils.py +247 -0
  394. qiskit/result/__init__.py +61 -0
  395. qiskit/result/counts.py +189 -0
  396. qiskit/result/distributions/__init__.py +17 -0
  397. qiskit/result/distributions/probability.py +100 -0
  398. qiskit/result/distributions/quasi.py +154 -0
  399. qiskit/result/exceptions.py +40 -0
  400. qiskit/result/models.py +241 -0
  401. qiskit/result/postprocess.py +239 -0
  402. qiskit/result/result.py +385 -0
  403. qiskit/result/sampled_expval.py +76 -0
  404. qiskit/result/utils.py +294 -0
  405. qiskit/synthesis/__init__.py +250 -0
  406. qiskit/synthesis/arithmetic/__init__.py +18 -0
  407. qiskit/synthesis/arithmetic/adders/__init__.py +18 -0
  408. qiskit/synthesis/arithmetic/adders/cdkm_ripple_carry_adder.py +154 -0
  409. qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +107 -0
  410. qiskit/synthesis/arithmetic/adders/rv_ripple_carry_adder.py +156 -0
  411. qiskit/synthesis/arithmetic/adders/vbe_ripple_carry_adder.py +161 -0
  412. qiskit/synthesis/arithmetic/comparators/__init__.py +16 -0
  413. qiskit/synthesis/arithmetic/comparators/compare_2s.py +112 -0
  414. qiskit/synthesis/arithmetic/comparators/compare_greedy.py +66 -0
  415. qiskit/synthesis/arithmetic/multipliers/__init__.py +16 -0
  416. qiskit/synthesis/arithmetic/multipliers/hrs_cumulative_multiplier.py +103 -0
  417. qiskit/synthesis/arithmetic/multipliers/rg_qft_multiplier.py +100 -0
  418. qiskit/synthesis/arithmetic/weighted_sum.py +155 -0
  419. qiskit/synthesis/boolean/__init__.py +13 -0
  420. qiskit/synthesis/boolean/boolean_expression.py +231 -0
  421. qiskit/synthesis/boolean/boolean_expression_synth.py +124 -0
  422. qiskit/synthesis/boolean/boolean_expression_visitor.py +96 -0
  423. qiskit/synthesis/clifford/__init__.py +19 -0
  424. qiskit/synthesis/clifford/clifford_decompose_ag.py +178 -0
  425. qiskit/synthesis/clifford/clifford_decompose_bm.py +46 -0
  426. qiskit/synthesis/clifford/clifford_decompose_full.py +64 -0
  427. qiskit/synthesis/clifford/clifford_decompose_greedy.py +58 -0
  428. qiskit/synthesis/clifford/clifford_decompose_layers.py +447 -0
  429. qiskit/synthesis/cnotdihedral/__init__.py +17 -0
  430. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_full.py +52 -0
  431. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_general.py +141 -0
  432. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_two_qubits.py +266 -0
  433. qiskit/synthesis/discrete_basis/__init__.py +16 -0
  434. qiskit/synthesis/discrete_basis/generate_basis_approximations.py +53 -0
  435. qiskit/synthesis/discrete_basis/solovay_kitaev.py +280 -0
  436. qiskit/synthesis/evolution/__init__.py +21 -0
  437. qiskit/synthesis/evolution/evolution_synthesis.py +48 -0
  438. qiskit/synthesis/evolution/lie_trotter.py +123 -0
  439. qiskit/synthesis/evolution/matrix_synthesis.py +47 -0
  440. qiskit/synthesis/evolution/pauli_network.py +80 -0
  441. qiskit/synthesis/evolution/product_formula.py +316 -0
  442. qiskit/synthesis/evolution/qdrift.py +133 -0
  443. qiskit/synthesis/evolution/suzuki_trotter.py +227 -0
  444. qiskit/synthesis/linear/__init__.py +26 -0
  445. qiskit/synthesis/linear/cnot_synth.py +69 -0
  446. qiskit/synthesis/linear/linear_circuits_utils.py +128 -0
  447. qiskit/synthesis/linear/linear_depth_lnn.py +61 -0
  448. qiskit/synthesis/linear/linear_matrix_utils.py +27 -0
  449. qiskit/synthesis/linear_phase/__init__.py +17 -0
  450. qiskit/synthesis/linear_phase/cnot_phase_synth.py +206 -0
  451. qiskit/synthesis/linear_phase/cx_cz_depth_lnn.py +61 -0
  452. qiskit/synthesis/linear_phase/cz_depth_lnn.py +58 -0
  453. qiskit/synthesis/multi_controlled/__init__.py +29 -0
  454. qiskit/synthesis/multi_controlled/mcmt_vchain.py +52 -0
  455. qiskit/synthesis/multi_controlled/mcx_synthesis.py +583 -0
  456. qiskit/synthesis/multi_controlled/multi_control_rotation_gates.py +205 -0
  457. qiskit/synthesis/one_qubit/__init__.py +15 -0
  458. qiskit/synthesis/one_qubit/one_qubit_decompose.py +288 -0
  459. qiskit/synthesis/permutation/__init__.py +18 -0
  460. qiskit/synthesis/permutation/permutation_full.py +78 -0
  461. qiskit/synthesis/permutation/permutation_lnn.py +54 -0
  462. qiskit/synthesis/permutation/permutation_reverse_lnn.py +93 -0
  463. qiskit/synthesis/permutation/permutation_utils.py +16 -0
  464. qiskit/synthesis/qft/__init__.py +16 -0
  465. qiskit/synthesis/qft/qft_decompose_full.py +97 -0
  466. qiskit/synthesis/qft/qft_decompose_lnn.py +61 -0
  467. qiskit/synthesis/stabilizer/__init__.py +16 -0
  468. qiskit/synthesis/stabilizer/stabilizer_circuit.py +149 -0
  469. qiskit/synthesis/stabilizer/stabilizer_decompose.py +194 -0
  470. qiskit/synthesis/two_qubit/__init__.py +20 -0
  471. qiskit/synthesis/two_qubit/local_invariance.py +63 -0
  472. qiskit/synthesis/two_qubit/two_qubit_decompose.py +583 -0
  473. qiskit/synthesis/two_qubit/xx_decompose/__init__.py +19 -0
  474. qiskit/synthesis/two_qubit/xx_decompose/circuits.py +300 -0
  475. qiskit/synthesis/two_qubit/xx_decompose/decomposer.py +324 -0
  476. qiskit/synthesis/two_qubit/xx_decompose/embodiments.py +163 -0
  477. qiskit/synthesis/two_qubit/xx_decompose/paths.py +412 -0
  478. qiskit/synthesis/two_qubit/xx_decompose/polytopes.py +262 -0
  479. qiskit/synthesis/two_qubit/xx_decompose/utilities.py +40 -0
  480. qiskit/synthesis/two_qubit/xx_decompose/weyl.py +133 -0
  481. qiskit/synthesis/unitary/__init__.py +13 -0
  482. qiskit/synthesis/unitary/aqc/__init__.py +177 -0
  483. qiskit/synthesis/unitary/aqc/approximate.py +116 -0
  484. qiskit/synthesis/unitary/aqc/aqc.py +175 -0
  485. qiskit/synthesis/unitary/aqc/cnot_structures.py +300 -0
  486. qiskit/synthesis/unitary/aqc/cnot_unit_circuit.py +103 -0
  487. qiskit/synthesis/unitary/aqc/cnot_unit_objective.py +299 -0
  488. qiskit/synthesis/unitary/aqc/elementary_operations.py +108 -0
  489. qiskit/synthesis/unitary/aqc/fast_gradient/__init__.py +164 -0
  490. qiskit/synthesis/unitary/aqc/fast_gradient/fast_grad_utils.py +237 -0
  491. qiskit/synthesis/unitary/aqc/fast_gradient/fast_gradient.py +226 -0
  492. qiskit/synthesis/unitary/aqc/fast_gradient/layer.py +370 -0
  493. qiskit/synthesis/unitary/aqc/fast_gradient/pmatrix.py +312 -0
  494. qiskit/synthesis/unitary/qsd.py +359 -0
  495. qiskit/transpiler/__init__.py +1352 -0
  496. qiskit/transpiler/basepasses.py +190 -0
  497. qiskit/transpiler/coupling.py +500 -0
  498. qiskit/transpiler/exceptions.py +59 -0
  499. qiskit/transpiler/instruction_durations.py +263 -0
  500. qiskit/transpiler/layout.py +740 -0
  501. qiskit/transpiler/passes/__init__.py +278 -0
  502. qiskit/transpiler/passes/analysis/__init__.py +23 -0
  503. qiskit/transpiler/passes/analysis/count_ops.py +30 -0
  504. qiskit/transpiler/passes/analysis/count_ops_longest_path.py +26 -0
  505. qiskit/transpiler/passes/analysis/dag_longest_path.py +24 -0
  506. qiskit/transpiler/passes/analysis/depth.py +33 -0
  507. qiskit/transpiler/passes/analysis/num_qubits.py +26 -0
  508. qiskit/transpiler/passes/analysis/num_tensor_factors.py +26 -0
  509. qiskit/transpiler/passes/analysis/resource_estimation.py +41 -0
  510. qiskit/transpiler/passes/analysis/size.py +36 -0
  511. qiskit/transpiler/passes/analysis/width.py +27 -0
  512. qiskit/transpiler/passes/basis/__init__.py +19 -0
  513. qiskit/transpiler/passes/basis/basis_translator.py +138 -0
  514. qiskit/transpiler/passes/basis/decompose.py +137 -0
  515. qiskit/transpiler/passes/basis/translate_parameterized.py +175 -0
  516. qiskit/transpiler/passes/basis/unroll_3q_or_more.py +84 -0
  517. qiskit/transpiler/passes/basis/unroll_custom_definitions.py +110 -0
  518. qiskit/transpiler/passes/layout/__init__.py +26 -0
  519. qiskit/transpiler/passes/layout/_csp_custom_solver.py +65 -0
  520. qiskit/transpiler/passes/layout/apply_layout.py +128 -0
  521. qiskit/transpiler/passes/layout/csp_layout.py +132 -0
  522. qiskit/transpiler/passes/layout/dense_layout.py +197 -0
  523. qiskit/transpiler/passes/layout/disjoint_utils.py +54 -0
  524. qiskit/transpiler/passes/layout/enlarge_with_ancilla.py +49 -0
  525. qiskit/transpiler/passes/layout/full_ancilla_allocation.py +116 -0
  526. qiskit/transpiler/passes/layout/layout_2q_distance.py +77 -0
  527. qiskit/transpiler/passes/layout/sabre_layout.py +525 -0
  528. qiskit/transpiler/passes/layout/sabre_pre_layout.py +225 -0
  529. qiskit/transpiler/passes/layout/set_layout.py +69 -0
  530. qiskit/transpiler/passes/layout/trivial_layout.py +66 -0
  531. qiskit/transpiler/passes/layout/vf2_layout.py +292 -0
  532. qiskit/transpiler/passes/layout/vf2_post_layout.py +376 -0
  533. qiskit/transpiler/passes/layout/vf2_utils.py +245 -0
  534. qiskit/transpiler/passes/optimization/__init__.py +42 -0
  535. qiskit/transpiler/passes/optimization/_gate_extension.py +80 -0
  536. qiskit/transpiler/passes/optimization/collect_1q_runs.py +31 -0
  537. qiskit/transpiler/passes/optimization/collect_2q_blocks.py +35 -0
  538. qiskit/transpiler/passes/optimization/collect_and_collapse.py +117 -0
  539. qiskit/transpiler/passes/optimization/collect_cliffords.py +109 -0
  540. qiskit/transpiler/passes/optimization/collect_linear_functions.py +85 -0
  541. qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +242 -0
  542. qiskit/transpiler/passes/optimization/commutation_analysis.py +44 -0
  543. qiskit/transpiler/passes/optimization/commutative_cancellation.py +82 -0
  544. qiskit/transpiler/passes/optimization/commutative_inverse_cancellation.py +140 -0
  545. qiskit/transpiler/passes/optimization/consolidate_blocks.py +176 -0
  546. qiskit/transpiler/passes/optimization/contract_idle_wires_in_control_flow.py +104 -0
  547. qiskit/transpiler/passes/optimization/elide_permutations.py +91 -0
  548. qiskit/transpiler/passes/optimization/hoare_opt.py +420 -0
  549. qiskit/transpiler/passes/optimization/inverse_cancellation.py +95 -0
  550. qiskit/transpiler/passes/optimization/light_cone.py +135 -0
  551. qiskit/transpiler/passes/optimization/optimize_1q_commutation.py +267 -0
  552. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +251 -0
  553. qiskit/transpiler/passes/optimization/optimize_1q_gates.py +384 -0
  554. qiskit/transpiler/passes/optimization/optimize_annotated.py +449 -0
  555. qiskit/transpiler/passes/optimization/optimize_clifford_t.py +68 -0
  556. qiskit/transpiler/passes/optimization/optimize_cliffords.py +89 -0
  557. qiskit/transpiler/passes/optimization/optimize_swap_before_measure.py +71 -0
  558. qiskit/transpiler/passes/optimization/remove_diagonal_gates_before_measure.py +41 -0
  559. qiskit/transpiler/passes/optimization/remove_final_reset.py +37 -0
  560. qiskit/transpiler/passes/optimization/remove_identity_equiv.py +70 -0
  561. qiskit/transpiler/passes/optimization/remove_reset_in_zero_state.py +37 -0
  562. qiskit/transpiler/passes/optimization/reset_after_measure_simplification.py +50 -0
  563. qiskit/transpiler/passes/optimization/split_2q_unitaries.py +63 -0
  564. qiskit/transpiler/passes/optimization/template_matching/__init__.py +19 -0
  565. qiskit/transpiler/passes/optimization/template_matching/backward_match.py +749 -0
  566. qiskit/transpiler/passes/optimization/template_matching/forward_match.py +452 -0
  567. qiskit/transpiler/passes/optimization/template_matching/maximal_matches.py +77 -0
  568. qiskit/transpiler/passes/optimization/template_matching/template_matching.py +370 -0
  569. qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +633 -0
  570. qiskit/transpiler/passes/optimization/template_optimization.py +158 -0
  571. qiskit/transpiler/passes/routing/__init__.py +21 -0
  572. qiskit/transpiler/passes/routing/algorithms/__init__.py +33 -0
  573. qiskit/transpiler/passes/routing/algorithms/token_swapper.py +105 -0
  574. qiskit/transpiler/passes/routing/algorithms/types.py +46 -0
  575. qiskit/transpiler/passes/routing/algorithms/util.py +103 -0
  576. qiskit/transpiler/passes/routing/basic_swap.py +166 -0
  577. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/__init__.py +25 -0
  578. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_block.py +60 -0
  579. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +397 -0
  580. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/pauli_2q_evolution_commutation.py +145 -0
  581. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +306 -0
  582. qiskit/transpiler/passes/routing/layout_transformation.py +119 -0
  583. qiskit/transpiler/passes/routing/lookahead_swap.py +390 -0
  584. qiskit/transpiler/passes/routing/sabre_swap.py +465 -0
  585. qiskit/transpiler/passes/routing/star_prerouting.py +433 -0
  586. qiskit/transpiler/passes/routing/utils.py +35 -0
  587. qiskit/transpiler/passes/scheduling/__init__.py +21 -0
  588. qiskit/transpiler/passes/scheduling/alignments/__init__.py +79 -0
  589. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +70 -0
  590. qiskit/transpiler/passes/scheduling/alignments/reschedule.py +251 -0
  591. qiskit/transpiler/passes/scheduling/padding/__init__.py +17 -0
  592. qiskit/transpiler/passes/scheduling/padding/base_padding.py +284 -0
  593. qiskit/transpiler/passes/scheduling/padding/context_aware_dynamical_decoupling.py +876 -0
  594. qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +415 -0
  595. qiskit/transpiler/passes/scheduling/padding/pad_delay.py +90 -0
  596. qiskit/transpiler/passes/scheduling/scheduling/__init__.py +17 -0
  597. qiskit/transpiler/passes/scheduling/scheduling/alap.py +93 -0
  598. qiskit/transpiler/passes/scheduling/scheduling/asap.py +100 -0
  599. qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +88 -0
  600. qiskit/transpiler/passes/scheduling/scheduling/set_io_latency.py +64 -0
  601. qiskit/transpiler/passes/scheduling/time_unit_conversion.py +237 -0
  602. qiskit/transpiler/passes/synthesis/__init__.py +21 -0
  603. qiskit/transpiler/passes/synthesis/aqc_plugin.py +153 -0
  604. qiskit/transpiler/passes/synthesis/clifford_unitary_synth_plugin.py +123 -0
  605. qiskit/transpiler/passes/synthesis/default_unitary_synth_plugin.py +653 -0
  606. qiskit/transpiler/passes/synthesis/high_level_synthesis.py +429 -0
  607. qiskit/transpiler/passes/synthesis/hls_plugins.py +2338 -0
  608. qiskit/transpiler/passes/synthesis/linear_functions_synthesis.py +41 -0
  609. qiskit/transpiler/passes/synthesis/plugin.py +738 -0
  610. qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +318 -0
  611. qiskit/transpiler/passes/synthesis/unitary_synthesis.py +425 -0
  612. qiskit/transpiler/passes/utils/__init__.py +32 -0
  613. qiskit/transpiler/passes/utils/barrier_before_final_measurements.py +41 -0
  614. qiskit/transpiler/passes/utils/check_gate_direction.py +60 -0
  615. qiskit/transpiler/passes/utils/check_map.py +78 -0
  616. qiskit/transpiler/passes/utils/contains_instruction.py +45 -0
  617. qiskit/transpiler/passes/utils/control_flow.py +61 -0
  618. qiskit/transpiler/passes/utils/dag_fixed_point.py +36 -0
  619. qiskit/transpiler/passes/utils/error.py +69 -0
  620. qiskit/transpiler/passes/utils/filter_op_nodes.py +66 -0
  621. qiskit/transpiler/passes/utils/fixed_point.py +48 -0
  622. qiskit/transpiler/passes/utils/gate_direction.py +93 -0
  623. qiskit/transpiler/passes/utils/gates_basis.py +51 -0
  624. qiskit/transpiler/passes/utils/merge_adjacent_barriers.py +163 -0
  625. qiskit/transpiler/passes/utils/minimum_point.py +118 -0
  626. qiskit/transpiler/passes/utils/remove_barriers.py +50 -0
  627. qiskit/transpiler/passes/utils/remove_final_measurements.py +121 -0
  628. qiskit/transpiler/passes/utils/unroll_forloops.py +81 -0
  629. qiskit/transpiler/passmanager.py +503 -0
  630. qiskit/transpiler/passmanager_config.py +154 -0
  631. qiskit/transpiler/preset_passmanagers/__init__.py +93 -0
  632. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +1114 -0
  633. qiskit/transpiler/preset_passmanagers/common.py +773 -0
  634. qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +443 -0
  635. qiskit/transpiler/preset_passmanagers/level0.py +104 -0
  636. qiskit/transpiler/preset_passmanagers/level1.py +108 -0
  637. qiskit/transpiler/preset_passmanagers/level2.py +109 -0
  638. qiskit/transpiler/preset_passmanagers/level3.py +110 -0
  639. qiskit/transpiler/preset_passmanagers/plugin.py +346 -0
  640. qiskit/transpiler/target.py +905 -0
  641. qiskit/transpiler/timing_constraints.py +59 -0
  642. qiskit/user_config.py +266 -0
  643. qiskit/utils/__init__.py +90 -0
  644. qiskit/utils/classtools.py +146 -0
  645. qiskit/utils/deprecation.py +382 -0
  646. qiskit/utils/lazy_tester.py +363 -0
  647. qiskit/utils/optionals.py +355 -0
  648. qiskit/utils/parallel.py +318 -0
  649. qiskit/utils/units.py +146 -0
  650. qiskit/version.py +84 -0
  651. qiskit/visualization/__init__.py +290 -0
  652. qiskit/visualization/array.py +207 -0
  653. qiskit/visualization/bloch.py +778 -0
  654. qiskit/visualization/circuit/__init__.py +15 -0
  655. qiskit/visualization/circuit/_utils.py +677 -0
  656. qiskit/visualization/circuit/circuit_visualization.py +735 -0
  657. qiskit/visualization/circuit/latex.py +668 -0
  658. qiskit/visualization/circuit/matplotlib.py +2041 -0
  659. qiskit/visualization/circuit/qcstyle.py +130 -0
  660. qiskit/visualization/circuit/styles/__init__.py +13 -0
  661. qiskit/visualization/circuit/styles/bw.json +202 -0
  662. qiskit/visualization/circuit/styles/clifford.json +202 -0
  663. qiskit/visualization/circuit/styles/iqp-dark.json +214 -0
  664. qiskit/visualization/circuit/styles/iqp.json +214 -0
  665. qiskit/visualization/circuit/styles/textbook.json +202 -0
  666. qiskit/visualization/circuit/text.py +1849 -0
  667. qiskit/visualization/circuit_visualization.py +19 -0
  668. qiskit/visualization/counts_visualization.py +487 -0
  669. qiskit/visualization/dag/__init__.py +13 -0
  670. qiskit/visualization/dag/dagstyle.py +103 -0
  671. qiskit/visualization/dag/styles/__init__.py +13 -0
  672. qiskit/visualization/dag/styles/color.json +10 -0
  673. qiskit/visualization/dag/styles/plain.json +5 -0
  674. qiskit/visualization/dag_visualization.py +389 -0
  675. qiskit/visualization/exceptions.py +21 -0
  676. qiskit/visualization/gate_map.py +1424 -0
  677. qiskit/visualization/library.py +40 -0
  678. qiskit/visualization/pass_manager_visualization.py +312 -0
  679. qiskit/visualization/state_visualization.py +1546 -0
  680. qiskit/visualization/style.py +223 -0
  681. qiskit/visualization/timeline/__init__.py +21 -0
  682. qiskit/visualization/timeline/core.py +495 -0
  683. qiskit/visualization/timeline/drawings.py +260 -0
  684. qiskit/visualization/timeline/generators.py +506 -0
  685. qiskit/visualization/timeline/interface.py +444 -0
  686. qiskit/visualization/timeline/layouts.py +115 -0
  687. qiskit/visualization/timeline/plotters/__init__.py +16 -0
  688. qiskit/visualization/timeline/plotters/base_plotter.py +58 -0
  689. qiskit/visualization/timeline/plotters/matplotlib.py +195 -0
  690. qiskit/visualization/timeline/stylesheet.py +301 -0
  691. qiskit/visualization/timeline/types.py +148 -0
  692. qiskit/visualization/transition_visualization.py +369 -0
  693. qiskit/visualization/utils.py +49 -0
  694. qiskit-2.1.0rc1.dist-info/METADATA +221 -0
  695. qiskit-2.1.0rc1.dist-info/RECORD +699 -0
  696. qiskit-2.1.0rc1.dist-info/WHEEL +6 -0
  697. qiskit-2.1.0rc1.dist-info/entry_points.txt +88 -0
  698. qiskit-2.1.0rc1.dist-info/licenses/LICENSE.txt +203 -0
  699. qiskit-2.1.0rc1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,2338 @@
1
+ # This code is part of Qiskit.
2
+ #
3
+ # (C) Copyright IBM 2022, 2023.
4
+ #
5
+ # This code is licensed under the Apache License, Version 2.0. You may
6
+ # obtain a copy of this license in the LICENSE.txt file in the root directory
7
+ # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8
+ #
9
+ # Any modifications or derivative works of this code must retain this
10
+ # copyright notice, and modified files need to carry a notice indicating
11
+ # that they have been altered from the originals.
12
+
13
+
14
+ """
15
+
16
+ High Level Synthesis Plugins
17
+ -----------------------------
18
+
19
+ Clifford Synthesis
20
+ ''''''''''''''''''
21
+
22
+ .. list-table:: Plugins for :class:`qiskit.quantum_info.Clifford` (key = ``"clifford"``)
23
+ :header-rows: 1
24
+
25
+ * - Plugin name
26
+ - Plugin class
27
+ - Targeted connectivity
28
+ - Description
29
+ * - ``"ag"``
30
+ - :class:`~.AGSynthesisClifford`
31
+ - all-to-all
32
+ - greedily optimizes CX-count
33
+ * - ``"bm"``
34
+ - :class:`~.BMSynthesisClifford`
35
+ - all-to-all
36
+ - optimal count for `n=2,3`; used in ``"default"`` for `n=2,3`
37
+ * - ``"greedy"``
38
+ - :class:`~.GreedySynthesisClifford`
39
+ - all-to-all
40
+ - greedily optimizes CX-count; used in ``"default"`` for `n>=4`
41
+ * - ``"layers"``
42
+ - :class:`~.LayerSynthesisClifford`
43
+ - all-to-all
44
+ -
45
+ * - ``"lnn"``
46
+ - :class:`~.LayerLnnSynthesisClifford`
47
+ - linear
48
+ - many CX-gates but guarantees CX-depth of at most `7*n+2`
49
+ * - ``"default"``
50
+ - :class:`~.DefaultSynthesisClifford`
51
+ - all-to-all
52
+ - usually best for optimizing CX-count (and optimal CX-count for `n=2,3`)
53
+
54
+ .. autosummary::
55
+ :toctree: ../stubs/
56
+
57
+ AGSynthesisClifford
58
+ BMSynthesisClifford
59
+ GreedySynthesisClifford
60
+ LayerSynthesisClifford
61
+ LayerLnnSynthesisClifford
62
+ DefaultSynthesisClifford
63
+
64
+
65
+ Linear Function Synthesis
66
+ '''''''''''''''''''''''''
67
+
68
+ .. list-table:: Plugins for :class:`.LinearFunction` (key = ``"linear"``)
69
+ :header-rows: 1
70
+
71
+ * - Plugin name
72
+ - Plugin class
73
+ - Targeted connectivity
74
+ - Description
75
+ * - ``"kms"``
76
+ - :class:`~.KMSSynthesisLinearFunction`
77
+ - linear
78
+ - many CX-gates but guarantees CX-depth of at most `5*n`
79
+ * - ``"pmh"``
80
+ - :class:`~.PMHSynthesisLinearFunction`
81
+ - all-to-all
82
+ - greedily optimizes CX-count; used in ``"default"``
83
+ * - ``"default"``
84
+ - :class:`~.DefaultSynthesisLinearFunction`
85
+ - all-to-all
86
+ - best for optimizing CX-count
87
+
88
+ .. autosummary::
89
+ :toctree: ../stubs/
90
+
91
+ KMSSynthesisLinearFunction
92
+ PMHSynthesisLinearFunction
93
+ DefaultSynthesisLinearFunction
94
+
95
+
96
+ Permutation Synthesis
97
+ '''''''''''''''''''''
98
+
99
+ .. list-table:: Plugins for :class:`.PermutationGate` (key = ``"permutation"``)
100
+ :header-rows: 1
101
+
102
+ * - Plugin name
103
+ - Plugin class
104
+ - Targeted connectivity
105
+ - Description
106
+ * - ``"basic"``
107
+ - :class:`~.BasicSynthesisPermutation`
108
+ - all-to-all
109
+ - optimal SWAP-count; used in ``"default"``
110
+ * - ``"acg"``
111
+ - :class:`~.ACGSynthesisPermutation`
112
+ - all-to-all
113
+ - guarantees SWAP-depth of at most `2`
114
+ * - ``"kms"``
115
+ - :class:`~.KMSSynthesisPermutation`
116
+ - linear
117
+ - many SWAP-gates, but guarantees SWAP-depth of at most `n`
118
+ * - ``"token_swapper"``
119
+ - :class:`~.TokenSwapperSynthesisPermutation`
120
+ - any
121
+ - greedily optimizes SWAP-count for arbitrary connectivity
122
+ * - ``"default"``
123
+ - :class:`~.BasicSynthesisPermutation`
124
+ - all-to-all
125
+ - best for optimizing SWAP-count
126
+
127
+ .. autosummary::
128
+ :toctree: ../stubs/
129
+
130
+ BasicSynthesisPermutation
131
+ ACGSynthesisPermutation
132
+ KMSSynthesisPermutation
133
+ TokenSwapperSynthesisPermutation
134
+
135
+
136
+ QFT Synthesis
137
+ '''''''''''''
138
+
139
+ .. list-table:: Plugins for :class:`.QFTGate` (key = ``"qft"``)
140
+ :header-rows: 1
141
+
142
+ * - Plugin name
143
+ - Plugin class
144
+ - Targeted connectivity
145
+ * - ``"full"``
146
+ - :class:`~.QFTSynthesisFull`
147
+ - all-to-all
148
+ * - ``"line"``
149
+ - :class:`~.QFTSynthesisLine`
150
+ - linear
151
+ * - ``"default"``
152
+ - :class:`~.QFTSynthesisFull`
153
+ - all-to-all
154
+
155
+ .. autosummary::
156
+ :toctree: ../stubs/
157
+
158
+ QFTSynthesisFull
159
+ QFTSynthesisLine
160
+
161
+
162
+ MCX Synthesis
163
+ '''''''''''''
164
+
165
+ The following table lists synthesis plugins available for an :class:`.MCXGate` gate
166
+ with `k` control qubits. If the available number of clean/dirty auxiliary qubits is
167
+ not sufficient, the corresponding synthesis method will return `None`.
168
+
169
+ .. list-table:: Plugins for :class:`.MCXGate` (key = ``"mcx"``)
170
+ :header-rows: 1
171
+
172
+ * - Plugin name
173
+ - Plugin class
174
+ - Number of clean ancillas
175
+ - Number of dirty ancillas
176
+ - Description
177
+ * - ``"gray_code"``
178
+ - :class:`~.MCXSynthesisGrayCode`
179
+ - `0`
180
+ - `0`
181
+ - exponentially many CX gates; use only for small values of `k`
182
+ * - ``"noaux_v24"``
183
+ - :class:`~.MCXSynthesisNoAuxV24`
184
+ - `0`
185
+ - `0`
186
+ - quadratic number of CX gates; use instead of ``"gray_code"`` for large values of `k`
187
+ * - ``"n_clean_m15"``
188
+ - :class:`~.MCXSynthesisNCleanM15`
189
+ - `k-2`
190
+ - `0`
191
+ - at most `6*k-6` CX gates
192
+ * - ``"n_dirty_i15"``
193
+ - :class:`~.MCXSynthesisNDirtyI15`
194
+ - `0`
195
+ - `k-2`
196
+ - at most `8*k-6` CX gates
197
+ * - ``"2_clean_kg24"``
198
+ - :class:`~.MCXSynthesis2CleanKG24`
199
+ - `2`
200
+ - `0`
201
+ - at most `12*k-18` CX gates
202
+ * - ``"2_dirty_kg24"``
203
+ - :class:`~.MCXSynthesis2DirtyKG24`
204
+ - `0`
205
+ - `2`
206
+ - at most `24*k-48` CX gates
207
+ * - ``"1_clean_kg24"``
208
+ - :class:`~.MCXSynthesis1CleanKG24`
209
+ - `1`
210
+ - `0`
211
+ - at most `12*k-18` CX gates
212
+ * - ``"1_dirty_kg24"``
213
+ - :class:`~.MCXSynthesis1DirtyKG24`
214
+ - `0`
215
+ - `1`
216
+ - at most `24*k-48` CX gates
217
+ * - ``"1_clean_b95"``
218
+ - :class:`~.MCXSynthesis1CleanB95`
219
+ - `1`
220
+ - `0`
221
+ - at most `16*k-8` CX gates
222
+ * - ``"default"``
223
+ - :class:`~.MCXSynthesisDefault`
224
+ - any
225
+ - any
226
+ - chooses the best algorithm based on the ancillas available
227
+
228
+ .. autosummary::
229
+ :toctree: ../stubs/
230
+
231
+ MCXSynthesisGrayCode
232
+ MCXSynthesisNoAuxV24
233
+ MCXSynthesisNCleanM15
234
+ MCXSynthesisNDirtyI15
235
+ MCXSynthesis2CleanKG24
236
+ MCXSynthesis2DirtyKG24
237
+ MCXSynthesis1CleanKG24
238
+ MCXSynthesis1DirtyKG24
239
+ MCXSynthesis1CleanB95
240
+ MCXSynthesisDefault
241
+
242
+
243
+ MCMT Synthesis
244
+ ''''''''''''''
245
+
246
+ .. list-table:: Plugins for :class:`.MCMTGate` (key = ``"mcmt"``)
247
+ :header-rows: 1
248
+
249
+ * - Plugin name
250
+ - Plugin class
251
+ - Number of clean ancillas
252
+ - Number of dirty ancillas
253
+ - Description
254
+ * - ``"vchain"``
255
+ - :class:`.MCMTSynthesisVChain`
256
+ - `k-1`
257
+ - `0`
258
+ - uses a linear number of Toffoli gates
259
+ * - ``"noaux"``
260
+ - :class:`~.MCMTSynthesisNoAux`
261
+ - `0`
262
+ - `0`
263
+ - uses Qiskit's standard control mechanism
264
+ * - ``"default"``
265
+ - :class:`~.MCMTSynthesisDefault`
266
+ - any
267
+ - any
268
+ - chooses the best algorithm based on the ancillas available
269
+
270
+ .. autosummary::
271
+ :toctree: ../stubs/
272
+
273
+ MCMTSynthesisVChain
274
+ MCMTSynthesisNoAux
275
+ MCMTSynthesisDefault
276
+
277
+
278
+ Integer comparators
279
+ '''''''''''''''''''
280
+
281
+ .. list-table:: Plugins for :class:`.IntegerComparatorGate` (key = ``"IntComp"``)
282
+ :header-rows: 1
283
+
284
+ * - Plugin name
285
+ - Plugin class
286
+ - Description
287
+ - Auxiliary qubits
288
+ * - ``"twos"``
289
+ - :class:`~.IntComparatorSynthesis2s`
290
+ - use addition with two's complement
291
+ - ``n - 1`` clean
292
+ * - ``"noaux"``
293
+ - :class:`~.IntComparatorSynthesisNoAux`
294
+ - flip the target controlled on all :math:`O(2^l)` allowed integer values
295
+ - none
296
+ * - ``"default"``
297
+ - :class:`~.IntComparatorSynthesisDefault`
298
+ - use the best algorithm depending on the available auxiliary qubits
299
+ - any
300
+
301
+ .. autosummary::
302
+ :toctree: ../stubs/
303
+
304
+ IntComparatorSynthesis2s
305
+ IntComparatorSynthesisNoAux
306
+ IntComparatorSynthesisDefault
307
+
308
+
309
+ Sums
310
+ ''''
311
+
312
+ .. list-table:: Plugins for :class:`.WeightedSumGate` (key = ``"WeightedSum"``)
313
+ :header-rows: 1
314
+
315
+ * - Plugin name
316
+ - Plugin class
317
+ - Description
318
+ - Auxiliary qubits
319
+ * - ``"default"``
320
+ - :class:`.WeightedSumSynthesisDefault`
321
+ - use a V-chain based synthesis
322
+ - given ``s`` sum qubits, used ``s - 1 + int(s > 2)`` clean auxiliary qubits
323
+
324
+ .. autosummary::
325
+ :toctree: ../stubs/
326
+
327
+ WeightedSumSynthesisDefault
328
+
329
+
330
+ Pauli Evolution Synthesis
331
+ '''''''''''''''''''''''''
332
+
333
+ .. list-table:: Plugins for :class:`.PauliEvolutionGate` (key = ``"PauliEvolution"``)
334
+ :header-rows: 1
335
+
336
+ * - Plugin name
337
+ - Plugin class
338
+ - Description
339
+ - Targeted connectivity
340
+ * - ``"rustiq"``
341
+ - :class:`~.PauliEvolutionSynthesisRustiq`
342
+ - use the synthesis method from `Rustiq circuit synthesis library
343
+ <https://github.com/smartiel/rustiq-core>`_
344
+ - all-to-all
345
+ * - ``"default"``
346
+ - :class:`~.PauliEvolutionSynthesisDefault`
347
+ - use a diagonalizing Clifford per Pauli term
348
+ - all-to-all
349
+
350
+ .. autosummary::
351
+ :toctree: ../stubs/
352
+
353
+ PauliEvolutionSynthesisDefault
354
+ PauliEvolutionSynthesisRustiq
355
+
356
+
357
+ Modular Adder Synthesis
358
+ '''''''''''''''''''''''
359
+
360
+ .. list-table:: Plugins for :class:`.ModularAdderGate` (key = ``"ModularAdder"``)
361
+ :header-rows: 1
362
+
363
+ * - Plugin name
364
+ - Plugin class
365
+ - Number of clean ancillas
366
+ - Description
367
+ * - ``"ripple_cdkm"``
368
+ - :class:`.ModularAdderSynthesisC04`
369
+ - 1
370
+ - a ripple-carry adder
371
+ * - ``"ripple_vbe"``
372
+ - :class:`.ModularAdderSynthesisV95`
373
+ - :math:`n-1`, for :math:`n`-bit numbers
374
+ - a ripple-carry adder
375
+ * - ``"qft"``
376
+ - :class:`.ModularAdderSynthesisD00`
377
+ - 0
378
+ - a QFT-based adder
379
+ * - ``"default"``
380
+ - :class:`~.ModularAdderSynthesisDefault`
381
+ - any
382
+ - chooses the best algorithm based on the ancillas available
383
+
384
+ .. autosummary::
385
+ :toctree: ../stubs/
386
+
387
+ ModularAdderSynthesisC04
388
+ ModularAdderSynthesisD00
389
+ ModularAdderSynthesisV95
390
+ ModularAdderSynthesisDefault
391
+
392
+ Half Adder Synthesis
393
+ ''''''''''''''''''''
394
+
395
+ .. list-table:: Plugins for :class:`.HalfAdderGate` (key = ``"HalfAdder"``)
396
+ :header-rows: 1
397
+
398
+ * - Plugin name
399
+ - Plugin class
400
+ - Number of clean ancillas
401
+ - Description
402
+ * - ``"ripple_cdkm"``
403
+ - :class:`.HalfAdderSynthesisC04`
404
+ - 1
405
+ - a ripple-carry adder
406
+ * - ``"ripple_r25"``
407
+ - :class:`.HalfAdderSynthesisR25`
408
+ - 0
409
+ - a ripple-carry adder with no ancillas
410
+ * - ``"ripple_vbe"``
411
+ - :class:`.HalfAdderSynthesisV95`
412
+ - :math:`n-1`, for :math:`n`-bit numbers
413
+ - a ripple-carry adder
414
+ * - ``"qft"``
415
+ - :class:`.HalfAdderSynthesisD00`
416
+ - 0
417
+ - a QFT-based adder
418
+ * - ``"default"``
419
+ - :class:`~.HalfAdderSynthesisDefault`
420
+ - any
421
+ - chooses the best algorithm based on the ancillas available
422
+
423
+ .. autosummary::
424
+ :toctree: ../stubs/
425
+
426
+ HalfAdderSynthesisC04
427
+ HalfAdderSynthesisD00
428
+ HalfAdderSynthesisV95
429
+ HalfAdderSynthesisR25
430
+ HalfAdderSynthesisDefault
431
+
432
+ Full Adder Synthesis
433
+ ''''''''''''''''''''
434
+
435
+ .. list-table:: Plugins for :class:`.FullAdderGate` (key = ``"FullAdder"``)
436
+ :header-rows: 1
437
+
438
+ * - Plugin name
439
+ - Plugin class
440
+ - Number of clean ancillas
441
+ - Description
442
+ * - ``"ripple_cdkm"``
443
+ - :class:`.FullAdderSynthesisC04`
444
+ - 0
445
+ - a ripple-carry adder
446
+ * - ``"ripple_vbe"``
447
+ - :class:`.FullAdderSynthesisV95`
448
+ - :math:`n-1`, for :math:`n`-bit numbers
449
+ - a ripple-carry adder
450
+ * - ``"default"``
451
+ - :class:`~.FullAdderSynthesisDefault`
452
+ - any
453
+ - chooses the best algorithm based on the ancillas available
454
+
455
+ .. autosummary::
456
+ :toctree: ../stubs/
457
+
458
+ FullAdderSynthesisC04
459
+ FullAdderSynthesisV95
460
+ FullAdderSynthesisDefault
461
+
462
+
463
+ Multiplier Synthesis
464
+ ''''''''''''''''''''
465
+
466
+ .. list-table:: Plugins for :class:`.MultiplierGate` (key = ``"Multiplier"``)
467
+ :header-rows: 1
468
+
469
+ * - Plugin name
470
+ - Plugin class
471
+ - Number of clean ancillas
472
+ - Description
473
+ * - ``"cumulative"``
474
+ - :class:`.MultiplierSynthesisH18`
475
+ - depending on the :class:`.AdderGate` used
476
+ - a cumulative adder based on controlled adders
477
+ * - ``"qft"``
478
+ - :class:`.MultiplierSynthesisR17`
479
+ - 0
480
+ - a QFT-based multiplier
481
+
482
+ .. autosummary::
483
+ :toctree: ../stubs/
484
+
485
+ MultiplierSynthesisH18
486
+ MultiplierSynthesisR17
487
+
488
+ """
489
+
490
+ from __future__ import annotations
491
+
492
+ import warnings
493
+ import numpy as np
494
+ import rustworkx as rx
495
+
496
+ from qiskit.circuit.quantumcircuit import QuantumCircuit
497
+ from qiskit.circuit.operation import Operation
498
+ from qiskit.circuit.library import (
499
+ LinearFunction,
500
+ QFTGate,
501
+ MCXGate,
502
+ C3XGate,
503
+ C4XGate,
504
+ PauliEvolutionGate,
505
+ PermutationGate,
506
+ MCMTGate,
507
+ ModularAdderGate,
508
+ HalfAdderGate,
509
+ FullAdderGate,
510
+ MultiplierGate,
511
+ WeightedSumGate,
512
+ GlobalPhaseGate,
513
+ )
514
+ from qiskit.circuit.annotated_operation import (
515
+ AnnotatedOperation,
516
+ Modifier,
517
+ ControlModifier,
518
+ InverseModifier,
519
+ PowerModifier,
520
+ _canonicalize_modifiers,
521
+ )
522
+ from qiskit.transpiler.coupling import CouplingMap
523
+
524
+ from qiskit.synthesis.arithmetic import (
525
+ synth_integer_comparator_2s,
526
+ synth_integer_comparator_greedy,
527
+ synth_weighted_sum_carry,
528
+ )
529
+ from qiskit.synthesis.clifford import (
530
+ synth_clifford_full,
531
+ synth_clifford_layers,
532
+ synth_clifford_depth_lnn,
533
+ synth_clifford_greedy,
534
+ synth_clifford_ag,
535
+ synth_clifford_bm,
536
+ )
537
+ from qiskit.synthesis.linear import (
538
+ synth_cnot_count_full_pmh,
539
+ synth_cnot_depth_line_kms,
540
+ calc_inverse_matrix,
541
+ )
542
+ from qiskit.synthesis.linear.linear_circuits_utils import transpose_cx_circ
543
+ from qiskit.synthesis.permutation import (
544
+ synth_permutation_basic,
545
+ synth_permutation_acg,
546
+ synth_permutation_depth_lnn_kms,
547
+ )
548
+ from qiskit.synthesis.qft import (
549
+ synth_qft_full,
550
+ synth_qft_line,
551
+ )
552
+ from qiskit.synthesis.multi_controlled import (
553
+ synth_mcx_n_dirty_i15,
554
+ synth_mcx_2_dirty_kg24,
555
+ synth_mcx_1_dirty_kg24,
556
+ synth_mcx_n_clean_m15,
557
+ synth_mcx_2_clean_kg24,
558
+ synth_mcx_1_clean_kg24,
559
+ synth_mcx_1_clean_b95,
560
+ synth_mcx_gray_code,
561
+ synth_mcx_noaux_v24,
562
+ synth_mcmt_vchain,
563
+ )
564
+ from qiskit.synthesis.evolution import ProductFormula, synth_pauli_network_rustiq
565
+ from qiskit.synthesis.arithmetic import (
566
+ adder_ripple_c04,
567
+ adder_qft_d00,
568
+ adder_ripple_v95,
569
+ adder_ripple_r25,
570
+ multiplier_qft_r17,
571
+ multiplier_cumulative_h18,
572
+ )
573
+ from qiskit.quantum_info.operators import Clifford
574
+ from qiskit.transpiler.passes.routing.algorithms import ApproximateTokenSwapper
575
+ from qiskit.transpiler.exceptions import TranspilerError
576
+ from qiskit.circuit._add_control import EFFICIENTLY_CONTROLLED_GATES
577
+
578
+ from qiskit._accelerate.high_level_synthesis import synthesize_operation, HighLevelSynthesisData
579
+ from .plugin import HighLevelSynthesisPlugin
580
+
581
+
582
+ class DefaultSynthesisClifford(HighLevelSynthesisPlugin):
583
+ """The default clifford synthesis plugin.
584
+
585
+ For N <= 3 qubits this is the optimal CX cost decomposition by Bravyi, Maslov.
586
+ For N > 3 qubits this is done using the general non-optimal greedy compilation
587
+ routine from reference by Bravyi, Hu, Maslov, Shaydulin.
588
+
589
+ This plugin name is :``clifford.default`` which can be used as the key on
590
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
591
+ """
592
+
593
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
594
+ """Run synthesis for the given Clifford."""
595
+ if not isinstance(high_level_object, Clifford):
596
+ return None
597
+
598
+ decomposition = synth_clifford_full(high_level_object)
599
+ return decomposition
600
+
601
+
602
+ class AGSynthesisClifford(HighLevelSynthesisPlugin):
603
+ """Clifford synthesis plugin based on the Aaronson-Gottesman method.
604
+
605
+ This plugin name is :``clifford.ag`` which can be used as the key on
606
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
607
+ """
608
+
609
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
610
+ """Run synthesis for the given Clifford."""
611
+ if not isinstance(high_level_object, Clifford):
612
+ return None
613
+
614
+ decomposition = synth_clifford_ag(high_level_object)
615
+ return decomposition
616
+
617
+
618
+ class BMSynthesisClifford(HighLevelSynthesisPlugin):
619
+ """Clifford synthesis plugin based on the Bravyi-Maslov method.
620
+
621
+ The method only works on Cliffords with at most 3 qubits, for which it
622
+ constructs the optimal CX cost decomposition.
623
+
624
+ This plugin name is :``clifford.bm`` which can be used as the key on
625
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
626
+ """
627
+
628
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
629
+ """Run synthesis for the given Clifford."""
630
+ if not isinstance(high_level_object, Clifford):
631
+ return None
632
+
633
+ if high_level_object.num_qubits <= 3:
634
+ decomposition = synth_clifford_bm(high_level_object)
635
+ else:
636
+ decomposition = None
637
+
638
+ return decomposition
639
+
640
+
641
+ class GreedySynthesisClifford(HighLevelSynthesisPlugin):
642
+ """Clifford synthesis plugin based on the greedy synthesis
643
+ Bravyi-Hu-Maslov-Shaydulin method.
644
+
645
+ This plugin name is :``clifford.greedy`` which can be used as the key on
646
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
647
+ """
648
+
649
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
650
+ """Run synthesis for the given Clifford."""
651
+ if not isinstance(high_level_object, Clifford):
652
+ return None
653
+
654
+ decomposition = synth_clifford_greedy(high_level_object)
655
+ return decomposition
656
+
657
+
658
+ class LayerSynthesisClifford(HighLevelSynthesisPlugin):
659
+ """Clifford synthesis plugin based on the Bravyi-Maslov method
660
+ to synthesize Cliffords into layers.
661
+
662
+ This plugin name is :``clifford.layers`` which can be used as the key on
663
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
664
+ """
665
+
666
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
667
+ """Run synthesis for the given Clifford."""
668
+ if not isinstance(high_level_object, Clifford):
669
+ return None
670
+
671
+ decomposition = synth_clifford_layers(high_level_object)
672
+ return decomposition
673
+
674
+
675
+ class LayerLnnSynthesisClifford(HighLevelSynthesisPlugin):
676
+ """Clifford synthesis plugin based on the Bravyi-Maslov method
677
+ to synthesize Cliffords into layers, with each layer synthesized
678
+ adhering to LNN connectivity.
679
+
680
+ This plugin name is :``clifford.lnn`` which can be used as the key on
681
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
682
+ """
683
+
684
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
685
+ """Run synthesis for the given Clifford."""
686
+ if not isinstance(high_level_object, Clifford):
687
+ return None
688
+
689
+ decomposition = synth_clifford_depth_lnn(high_level_object)
690
+ return decomposition
691
+
692
+
693
+ class DefaultSynthesisLinearFunction(HighLevelSynthesisPlugin):
694
+ """The default linear function synthesis plugin.
695
+
696
+ This plugin name is :``linear_function.default`` which can be used as the key on
697
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
698
+ """
699
+
700
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
701
+ """Run synthesis for the given LinearFunction."""
702
+ if not isinstance(high_level_object, LinearFunction):
703
+ return None
704
+
705
+ decomposition = synth_cnot_count_full_pmh(high_level_object.linear)
706
+ return decomposition
707
+
708
+
709
+ class KMSSynthesisLinearFunction(HighLevelSynthesisPlugin):
710
+ """Linear function synthesis plugin based on the Kutin-Moulton-Smithline method.
711
+
712
+ This plugin name is :``linear_function.kms`` which can be used as the key on
713
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
714
+
715
+ The plugin supports the following plugin-specific options:
716
+
717
+ * use_inverted: Indicates whether to run the algorithm on the inverse matrix
718
+ and to invert the synthesized circuit.
719
+ In certain cases this provides a better decomposition than the direct approach.
720
+ * use_transposed: Indicates whether to run the algorithm on the transposed matrix
721
+ and to invert the order of CX gates in the synthesized circuit.
722
+ In certain cases this provides a better decomposition than the direct approach.
723
+
724
+ """
725
+
726
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
727
+ """Run synthesis for the given LinearFunction."""
728
+ if not isinstance(high_level_object, LinearFunction):
729
+ return None
730
+
731
+ use_inverted = options.get("use_inverted", False)
732
+ use_transposed = options.get("use_transposed", False)
733
+
734
+ mat = high_level_object.linear.astype(bool, copy=False)
735
+
736
+ if use_transposed:
737
+ mat = np.transpose(mat)
738
+ if use_inverted:
739
+ mat = calc_inverse_matrix(mat)
740
+
741
+ decomposition = synth_cnot_depth_line_kms(mat)
742
+
743
+ if use_transposed:
744
+ decomposition = transpose_cx_circ(decomposition)
745
+ if use_inverted:
746
+ decomposition = decomposition.inverse()
747
+
748
+ return decomposition
749
+
750
+
751
+ class PMHSynthesisLinearFunction(HighLevelSynthesisPlugin):
752
+ """Linear function synthesis plugin based on the Patel-Markov-Hayes method.
753
+
754
+ This plugin name is :``linear_function.pmh`` which can be used as the key on
755
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
756
+
757
+ The plugin supports the following plugin-specific options:
758
+
759
+ * section size: The size of each section used in the Patel–Markov–Hayes algorithm [1].
760
+ * use_inverted: Indicates whether to run the algorithm on the inverse matrix
761
+ and to invert the synthesized circuit.
762
+ In certain cases this provides a better decomposition than the direct approach.
763
+ * use_transposed: Indicates whether to run the algorithm on the transposed matrix
764
+ and to invert the order of CX gates in the synthesized circuit.
765
+ In certain cases this provides a better decomposition than the direct approach.
766
+
767
+ References:
768
+ 1. Patel, Ketan N., Igor L. Markov, and John P. Hayes,
769
+ *Optimal synthesis of linear reversible circuits*,
770
+ Quantum Information & Computation 8.3 (2008): 282-294.
771
+ `arXiv:quant-ph/0302002 [quant-ph] <https://arxiv.org/abs/quant-ph/0302002>`_
772
+ """
773
+
774
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
775
+ """Run synthesis for the given LinearFunction."""
776
+ if not isinstance(high_level_object, LinearFunction):
777
+ return None
778
+
779
+ section_size = options.get("section_size", 2)
780
+ use_inverted = options.get("use_inverted", False)
781
+ use_transposed = options.get("use_transposed", False)
782
+
783
+ mat = high_level_object.linear.astype(bool, copy=False)
784
+
785
+ if use_transposed:
786
+ mat = np.transpose(mat)
787
+ if use_inverted:
788
+ mat = calc_inverse_matrix(mat)
789
+
790
+ decomposition = synth_cnot_count_full_pmh(mat, section_size=section_size)
791
+
792
+ if use_transposed:
793
+ decomposition = transpose_cx_circ(decomposition)
794
+ if use_inverted:
795
+ decomposition = decomposition.inverse()
796
+
797
+ return decomposition
798
+
799
+
800
+ class KMSSynthesisPermutation(HighLevelSynthesisPlugin):
801
+ """The permutation synthesis plugin based on the Kutin, Moulton, Smithline method.
802
+
803
+ This plugin name is :``permutation.kms`` which can be used as the key on
804
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
805
+ """
806
+
807
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
808
+ """Run synthesis for the given Permutation."""
809
+ if not isinstance(high_level_object, PermutationGate):
810
+ return None
811
+
812
+ decomposition = synth_permutation_depth_lnn_kms(high_level_object.pattern)
813
+ return decomposition
814
+
815
+
816
+ class BasicSynthesisPermutation(HighLevelSynthesisPlugin):
817
+ """The permutation synthesis plugin based on sorting.
818
+
819
+ This plugin name is :``permutation.basic`` which can be used as the key on
820
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
821
+ """
822
+
823
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
824
+ """Run synthesis for the given Permutation."""
825
+ if not isinstance(high_level_object, PermutationGate):
826
+ return None
827
+
828
+ decomposition = synth_permutation_basic(high_level_object.pattern)
829
+ return decomposition
830
+
831
+
832
+ class ACGSynthesisPermutation(HighLevelSynthesisPlugin):
833
+ """The permutation synthesis plugin based on the Alon, Chung, Graham method.
834
+
835
+ This plugin name is :``permutation.acg`` which can be used as the key on
836
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
837
+ """
838
+
839
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
840
+ """Run synthesis for the given Permutation."""
841
+ if not isinstance(high_level_object, PermutationGate):
842
+ return None
843
+
844
+ decomposition = synth_permutation_acg(high_level_object.pattern)
845
+ return decomposition
846
+
847
+
848
+ class QFTSynthesisFull(HighLevelSynthesisPlugin):
849
+ """Synthesis plugin for QFT gates using all-to-all connectivity.
850
+
851
+ This plugin name is :``qft.full`` which can be used as the key on
852
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
853
+
854
+ Note that the plugin mechanism is not applied if the gate is called ``qft`` but
855
+ is not an instance of ``QFTGate``. This allows users to create custom gates with
856
+ name ``qft``.
857
+
858
+ The plugin supports the following additional options:
859
+
860
+ * reverse_qubits (bool): Whether to synthesize the "QFT" operation (if ``False``,
861
+ which is the default) or the "QFT-with-reversal" operation (if ``True``).
862
+ Some implementation of the ``QFTGate`` include a layer of swap gates at the end
863
+ of the synthesized circuit, which can in principle be dropped if the ``QFTGate``
864
+ itself is the last gate in the circuit.
865
+ * approximation_degree (int): The degree of approximation (0 for no approximation).
866
+ It is possible to implement the QFT approximately by ignoring
867
+ controlled-phase rotations with the angle beneath a threshold. This is discussed
868
+ in more detail in [1] or [2].
869
+ * insert_barriers (bool): If True, barriers are inserted as visualization improvement.
870
+ * inverse (bool): If True, the inverse Fourier transform is constructed.
871
+ * name (str): The name of the circuit.
872
+
873
+ References:
874
+ 1. Adriano Barenco, Artur Ekert, Kalle-Antti Suominen, and Päivi Törmä,
875
+ *Approximate Quantum Fourier Transform and Decoherence*,
876
+ Physical Review A (1996).
877
+ `arXiv:quant-ph/9601018 [quant-ph] <https://arxiv.org/abs/quant-ph/9601018>`_
878
+ 2. Donny Cheung,
879
+ *Improved Bounds for the Approximate QFT* (2004),
880
+ `arXiv:quant-ph/0403071 [quant-ph] <https://https://arxiv.org/abs/quant-ph/0403071>`_
881
+ """
882
+
883
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
884
+ """Run synthesis for the given QFTGate."""
885
+
886
+ # Even though the gate is called "qft", it's not a QFTGate,
887
+ # and we should not synthesize it using the plugin.
888
+ if not isinstance(high_level_object, QFTGate):
889
+ return None
890
+
891
+ reverse_qubits = options.get("reverse_qubits", False)
892
+ approximation_degree = options.get("approximation_degree", 0)
893
+ insert_barriers = options.get("insert_barriers", False)
894
+ inverse = options.get("inverse", False)
895
+ name = options.get("name", None)
896
+
897
+ decomposition = synth_qft_full(
898
+ num_qubits=high_level_object.num_qubits,
899
+ do_swaps=not reverse_qubits,
900
+ approximation_degree=approximation_degree,
901
+ insert_barriers=insert_barriers,
902
+ inverse=inverse,
903
+ name=name,
904
+ )
905
+ return decomposition
906
+
907
+
908
+ class QFTSynthesisLine(HighLevelSynthesisPlugin):
909
+ """Synthesis plugin for QFT gates using linear connectivity.
910
+
911
+ This plugin name is :``qft.line`` which can be used as the key on
912
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
913
+
914
+ Note that the plugin mechanism is not applied if the gate is called ``qft`` but
915
+ is not an instance of ``QFTGate``. This allows users to create custom gates with
916
+ name ``qft``.
917
+
918
+ The plugin supports the following additional options:
919
+
920
+ * reverse_qubits (bool): Whether to synthesize the "QFT" operation (if ``False``,
921
+ which is the default) or the "QFT-with-reversal" operation (if ``True``).
922
+ Some implementation of the ``QFTGate`` include a layer of swap gates at the end
923
+ of the synthesized circuit, which can in principle be dropped if the ``QFTGate``
924
+ itself is the last gate in the circuit.
925
+ * approximation_degree (int): the degree of approximation (0 for no approximation).
926
+ It is possible to implement the QFT approximately by ignoring
927
+ controlled-phase rotations with the angle beneath a threshold. This is discussed
928
+ in more detail in [1] or [2].
929
+
930
+ References:
931
+ 1. Adriano Barenco, Artur Ekert, Kalle-Antti Suominen, and Päivi Törmä,
932
+ *Approximate Quantum Fourier Transform and Decoherence*,
933
+ Physical Review A (1996).
934
+ `arXiv:quant-ph/9601018 [quant-ph] <https://arxiv.org/abs/quant-ph/9601018>`_
935
+ 2. Donny Cheung,
936
+ *Improved Bounds for the Approximate QFT* (2004),
937
+ `arXiv:quant-ph/0403071 [quant-ph] <https://https://arxiv.org/abs/quant-ph/0403071>`_
938
+ """
939
+
940
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
941
+ """Run synthesis for the given QFTGate."""
942
+
943
+ # Even though the gate is called "qft", it's not a QFTGate,
944
+ # and we should not synthesize it using the plugin.
945
+ if not isinstance(high_level_object, QFTGate):
946
+ return None
947
+
948
+ reverse_qubits = options.get("reverse_qubits", False)
949
+ approximation_degree = options.get("approximation_degree", 0)
950
+
951
+ decomposition = synth_qft_line(
952
+ num_qubits=high_level_object.num_qubits,
953
+ do_swaps=not reverse_qubits,
954
+ approximation_degree=approximation_degree,
955
+ )
956
+ return decomposition
957
+
958
+
959
+ class TokenSwapperSynthesisPermutation(HighLevelSynthesisPlugin):
960
+ """The permutation synthesis plugin based on the token swapper algorithm.
961
+
962
+ This plugin name is :``permutation.token_swapper`` which can be used as the key on
963
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
964
+
965
+ In more detail, this plugin is used to synthesize objects of type `PermutationGate`.
966
+ When synthesis succeeds, the plugin outputs a quantum circuit consisting only of swap
967
+ gates. When synthesis does not succeed, the plugin outputs `None`.
968
+
969
+ If either `coupling_map` or `qubits` is None, then the synthesized circuit
970
+ is not required to adhere to connectivity constraints, as is the case
971
+ when the synthesis is done before layout/routing.
972
+
973
+ On the other hand, if both `coupling_map` and `qubits` are specified, the synthesized
974
+ circuit is supposed to adhere to connectivity constraints. At the moment, the
975
+ plugin only creates swap gates between qubits in `qubits`, i.e. it does not use
976
+ any other qubits in the coupling map (if such synthesis is not possible, the
977
+ plugin outputs `None`).
978
+
979
+ The plugin supports the following plugin-specific options:
980
+
981
+ * trials: The number of trials for the token swapper to perform the mapping. The
982
+ circuit with the smallest number of SWAPs is returned.
983
+ * seed: The argument to the token swapper specifying the seed for random trials.
984
+ * parallel_threshold: The argument to the token swapper specifying the number of nodes
985
+ in the graph beyond which the algorithm will use parallel processing.
986
+
987
+ For more details on the token swapper algorithm, see to the paper:
988
+ `arXiv:1902.09102 <https://arxiv.org/abs/1902.09102>`__.
989
+ """
990
+
991
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
992
+ """Run synthesis for the given Permutation."""
993
+
994
+ if not isinstance(high_level_object, PermutationGate):
995
+ return None
996
+
997
+ trials = options.get("trials", 5)
998
+ seed = options.get("seed", 0)
999
+ parallel_threshold = options.get("parallel_threshold", 50)
1000
+
1001
+ pattern = high_level_object.pattern
1002
+ pattern_as_dict = {j: i for i, j in enumerate(pattern)}
1003
+
1004
+ # When the plugin is called from the HighLevelSynthesis transpiler pass,
1005
+ # the coupling map already takes target into account.
1006
+ if coupling_map is None or qubits is None:
1007
+ # The abstract synthesis uses a fully connected coupling map, allowing
1008
+ # arbitrary connections between qubits.
1009
+ used_coupling_map = CouplingMap.from_full(len(pattern))
1010
+ else:
1011
+ # The concrete synthesis uses the coupling map restricted to the set of
1012
+ # qubits over which the permutation gate is defined. If we allow using other
1013
+ # qubits in the coupling map, replacing the node in the DAGCircuit that
1014
+ # defines this PermutationGate by the DAG corresponding to the constructed
1015
+ # decomposition becomes problematic. Note that we allow the reduced
1016
+ # coupling map to be disconnected.
1017
+ used_coupling_map = coupling_map.reduce(qubits, check_if_connected=False)
1018
+
1019
+ graph = used_coupling_map.graph.to_undirected()
1020
+ swapper = ApproximateTokenSwapper(graph, seed=seed)
1021
+
1022
+ try:
1023
+ swapper_result = swapper.map(
1024
+ pattern_as_dict, trials, parallel_threshold=parallel_threshold
1025
+ )
1026
+ except rx.InvalidMapping:
1027
+ swapper_result = None
1028
+
1029
+ if swapper_result is not None:
1030
+ decomposition = QuantumCircuit(len(graph.node_indices()))
1031
+ for swap in swapper_result:
1032
+ decomposition.swap(*swap)
1033
+ return decomposition
1034
+
1035
+ return None
1036
+
1037
+
1038
+ class MCXSynthesisNDirtyI15(HighLevelSynthesisPlugin):
1039
+ r"""Synthesis plugin for a multi-controlled X gate based on the paper
1040
+ by Iten et al. (2016).
1041
+
1042
+ See [1] for details.
1043
+
1044
+ This plugin name is :``mcx.n_dirty_i15`` which can be used as the key on
1045
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1046
+
1047
+ For a multi-controlled X gate with :math:`k\ge 4` control qubits this synthesis
1048
+ method requires :math:`k - 2` additional dirty auxiliary qubits. The synthesized
1049
+ circuit consists of :math:`2 * k - 1` qubits and at most :math:`8 * k - 6` CX gates.
1050
+ For :math:`k\le 3` explicit efficient circuits are used instead.
1051
+
1052
+ The plugin supports the following plugin-specific options:
1053
+
1054
+ * num_clean_ancillas: The number of clean auxiliary qubits available.
1055
+ * num_dirty_ancillas: The number of dirty auxiliary qubits available.
1056
+ * relative_phase: When set to ``True``, the method applies the optimized multi-controlled
1057
+ X gate up to a relative phase, in a way that, by lemma 8 of [1], the relative
1058
+ phases of the ``action part`` cancel out with the phases of the ``reset part``.
1059
+ * action_only: when set to ``True``, the method applies only the ``action part``
1060
+ of lemma 8 of [1].
1061
+
1062
+ References:
1063
+ 1. Iten et. al., *Quantum Circuits for Isometries*, Phys. Rev. A 93, 032318 (2016),
1064
+ `arXiv:1501.06911 <http://arxiv.org/abs/1501.06911>`_
1065
+ """
1066
+
1067
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1068
+ """Run synthesis for the given MCX gate."""
1069
+
1070
+ if not isinstance(high_level_object, (MCXGate, C3XGate, C4XGate)):
1071
+ # Unfortunately we occasionally have custom instructions called "mcx"
1072
+ # which get wrongly caught by the plugin interface. A simple solution is
1073
+ # to return None in this case, since HLS would proceed to examine
1074
+ # their definition as it should.
1075
+ return None
1076
+
1077
+ num_ctrl_qubits = high_level_object.num_ctrl_qubits
1078
+ num_clean_ancillas = options.get("num_clean_ancillas", 0)
1079
+ num_dirty_ancillas = options.get("num_dirty_ancillas", 0)
1080
+ relative_phase = options.get("relative_phase", False)
1081
+ action_only = options.get("actions_only", False)
1082
+
1083
+ if num_ctrl_qubits >= 3 and num_dirty_ancillas + num_clean_ancillas < num_ctrl_qubits - 2:
1084
+ # This synthesis method is not applicable as there are not enough ancilla qubits
1085
+ return None
1086
+
1087
+ decomposition = synth_mcx_n_dirty_i15(num_ctrl_qubits, relative_phase, action_only)
1088
+ return decomposition
1089
+
1090
+
1091
+ class MCXSynthesisNCleanM15(HighLevelSynthesisPlugin):
1092
+ r"""Synthesis plugin for a multi-controlled X gate based on the paper by
1093
+ Maslov (2016).
1094
+
1095
+ See [1] for details.
1096
+
1097
+ This plugin name is :``mcx.n_clean_m15`` which can be used as the key on
1098
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1099
+
1100
+ For a multi-controlled X gate with :math:`k\ge 3` control qubits this synthesis
1101
+ method requires :math:`k - 2` additional clean auxiliary qubits. The synthesized
1102
+ circuit consists of :math:`2 * k - 1` qubits and at most :math:`6 * k - 6` CX gates.
1103
+
1104
+ The plugin supports the following plugin-specific options:
1105
+
1106
+ * num_clean_ancillas: The number of clean auxiliary qubits available.
1107
+
1108
+ References:
1109
+ 1. Maslov., Phys. Rev. A 93, 022311 (2016),
1110
+ `arXiv:1508.03273 <https://arxiv.org/pdf/1508.03273>`_
1111
+ """
1112
+
1113
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1114
+ """Run synthesis for the given MCX gate."""
1115
+
1116
+ if not isinstance(high_level_object, (MCXGate, C3XGate, C4XGate)):
1117
+ # Unfortunately we occasionally have custom instructions called "mcx"
1118
+ # which get wrongly caught by the plugin interface. A simple solution is
1119
+ # to return None in this case, since HLS would proceed to examine
1120
+ # their definition as it should.
1121
+ return None
1122
+
1123
+ num_ctrl_qubits = high_level_object.num_ctrl_qubits
1124
+ num_clean_ancillas = options.get("num_clean_ancillas", 0)
1125
+
1126
+ if num_ctrl_qubits >= 3 and num_clean_ancillas < num_ctrl_qubits - 2:
1127
+ # This synthesis method is not applicable as there are not enough ancilla qubits
1128
+ return None
1129
+
1130
+ decomposition = synth_mcx_n_clean_m15(num_ctrl_qubits)
1131
+ return decomposition
1132
+
1133
+
1134
+ class MCXSynthesis1CleanB95(HighLevelSynthesisPlugin):
1135
+ r"""Synthesis plugin for a multi-controlled X gate based on the paper by
1136
+ Barenco et al. (1995).
1137
+
1138
+ See [1] for details.
1139
+
1140
+ This plugin name is :``mcx.1_clean_b95`` which can be used as the key on
1141
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1142
+
1143
+ For a multi-controlled X gate with :math:`k\ge 5` control qubits this synthesis
1144
+ method requires a single additional clean auxiliary qubit. The synthesized
1145
+ circuit consists of :math:`k + 2` qubits and at most :math:`16 * k - 24` CX gates.
1146
+
1147
+ The plugin supports the following plugin-specific options:
1148
+
1149
+ * num_clean_ancillas: The number of clean auxiliary qubits available.
1150
+
1151
+ References:
1152
+ 1. Barenco et. al., *Elementary gates for quantum computation*, Phys.Rev. A52 3457 (1995),
1153
+ `arXiv:quant-ph/9503016 <https://arxiv.org/abs/quant-ph/9503016>`_
1154
+ """
1155
+
1156
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1157
+ """Run synthesis for the given MCX gate."""
1158
+
1159
+ if not isinstance(high_level_object, (MCXGate, C3XGate, C4XGate)):
1160
+ # Unfortunately we occasionally have custom instructions called "mcx"
1161
+ # which get wrongly caught by the plugin interface. A simple solution is
1162
+ # to return None in this case, since HLS would proceed to examine
1163
+ # their definition as it should.
1164
+ return None
1165
+
1166
+ num_ctrl_qubits = high_level_object.num_ctrl_qubits
1167
+
1168
+ if num_ctrl_qubits <= 2:
1169
+ # The method requires at least 3 control qubits
1170
+ return None
1171
+
1172
+ num_clean_ancillas = options.get("num_clean_ancillas", 0)
1173
+
1174
+ if num_ctrl_qubits >= 5 and num_clean_ancillas == 0:
1175
+ # This synthesis method is not applicable as there are not enough ancilla qubits
1176
+ return None
1177
+
1178
+ decomposition = synth_mcx_1_clean_b95(num_ctrl_qubits)
1179
+ return decomposition
1180
+
1181
+
1182
+ class MCXSynthesis2CleanKG24(HighLevelSynthesisPlugin):
1183
+ r"""Synthesis plugin for a multi-controlled X gate based on the paper by Khattar and
1184
+ Gidney (2024).
1185
+
1186
+ See [1] for details.
1187
+
1188
+ The plugin name is :``mcx.2_clean_kg24`` which can be used as the key on an :class:`~.HLSConfig`
1189
+ object to use this method with :class:`~.HighLevelSynthesis`.
1190
+
1191
+ For a multi-controlled X gate with :math:`k\ge 3` control qubits this synthesis method requires
1192
+ :math:`2` additional clean ancillary qubits. The synthesized circuit consists of :math:`k + 2`
1193
+ qubits and at most :math:`12 * k - 18` CX gates.
1194
+
1195
+ The plugin supports the following plugin-specific options:
1196
+
1197
+ * num_clean_ancillas: The number of clean ancillary qubits available.
1198
+
1199
+ References:
1200
+ 1. Khattar and Gidney, Rise of conditionally clean ancillae for optimizing quantum circuits
1201
+ `arXiv:2407.17966 <https://arxiv.org/abs/2407.17966>`__
1202
+ """
1203
+
1204
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1205
+ """Run synthesis for the given MCX gate."""
1206
+
1207
+ if not isinstance(high_level_object, (MCXGate, C3XGate, C4XGate)):
1208
+ # Unfortunately we occasionally have custom instructions called "mcx"
1209
+ # which get wrongly caught by the plugin interface. A simple solution is
1210
+ # to return None in this case, since HLS would proceed to examine
1211
+ # their definition as it should.
1212
+ return None
1213
+
1214
+ num_ctrl_qubits = high_level_object.num_ctrl_qubits
1215
+ num_clean_ancillas = options.get("num_clean_ancillas", 0)
1216
+
1217
+ if num_clean_ancillas < 2:
1218
+ return None
1219
+
1220
+ decomposition = synth_mcx_2_clean_kg24(num_ctrl_qubits)
1221
+ return decomposition
1222
+
1223
+
1224
+ class MCXSynthesis2DirtyKG24(HighLevelSynthesisPlugin):
1225
+ r"""Synthesis plugin for a multi-controlled X gate based on the paper by Khattar and
1226
+ Gidney (2024).
1227
+
1228
+ See [1] for details.
1229
+
1230
+ The plugin name is :``mcx.2_dirty_kg24`` which can be used as the key on an :class:`~.HLSConfig`
1231
+ object to use this method with :class:`~.HighLevelSynthesis`.
1232
+
1233
+ For a multi-controlled X gate with :math:`k\ge 3` control qubits this synthesis method requires
1234
+ :math:`2` additional dirty ancillary qubits. The synthesized circuit consists of :math:`k + 2`
1235
+ qubits and at most :math:`24 * k - 48` CX gates.
1236
+
1237
+ The plugin supports the following plugin-specific options:
1238
+
1239
+ * num_clean_ancillas: The number of clean ancillary qubits available.
1240
+
1241
+ References:
1242
+ 1. Khattar and Gidney, Rise of conditionally clean ancillae for optimizing quantum circuits
1243
+ `arXiv:2407.17966 <https://arxiv.org/abs/2407.17966>`__
1244
+ """
1245
+
1246
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1247
+ """Run synthesis for the given MCX gate."""
1248
+
1249
+ if not isinstance(high_level_object, (MCXGate, C3XGate, C4XGate)):
1250
+ # Unfortunately we occasionally have custom instructions called "mcx"
1251
+ # which get wrongly caught by the plugin interface. A simple solution is
1252
+ # to return None in this case, since HLS would proceed to examine
1253
+ # their definition as it should.
1254
+ return None
1255
+
1256
+ num_ctrl_qubits = high_level_object.num_ctrl_qubits
1257
+ num_dirty_ancillas = options.get("num_dirty_ancillas", 0)
1258
+
1259
+ if num_dirty_ancillas < 2:
1260
+ return None
1261
+
1262
+ decomposition = synth_mcx_2_dirty_kg24(num_ctrl_qubits)
1263
+ return decomposition
1264
+
1265
+
1266
+ class MCXSynthesis1CleanKG24(HighLevelSynthesisPlugin):
1267
+ r"""Synthesis plugin for a multi-controlled X gate based on the paper by Khattar and
1268
+ Gidney (2024).
1269
+
1270
+ See [1] for details.
1271
+
1272
+ The plugin name is :``mcx.1_clean_kg24`` which can be used as the key on an :class:`~.HLSConfig`
1273
+ object to use this method with :class:`~.HighLevelSynthesis`.
1274
+
1275
+ For a multi-controlled X gate with :math:`k\ge 3` control qubits this synthesis method requires
1276
+ :math:`1` additional clean ancillary qubit. The synthesized circuit consists of :math:`k + 2`
1277
+ qubits and at most :math:`12 * k - 18` CX gates.
1278
+
1279
+ The plugin supports the following plugin-specific options:
1280
+
1281
+ * num_clean_ancillas: The number of clean ancillary qubits available.
1282
+
1283
+ References:
1284
+ 1. Khattar and Gidney, Rise of conditionally clean ancillae for optimizing quantum circuits
1285
+ `arXiv:2407.17966 <https://arxiv.org/abs/2407.17966>`__
1286
+ """
1287
+
1288
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1289
+ """Run synthesis for the given MCX gate."""
1290
+
1291
+ if not isinstance(high_level_object, (MCXGate, C3XGate, C4XGate)):
1292
+ # Unfortunately we occasionally have custom instructions called "mcx"
1293
+ # which get wrongly caught by the plugin interface. A simple solution is
1294
+ # to return None in this case, since HLS would proceed to examine
1295
+ # their definition as it should.
1296
+ return None
1297
+
1298
+ num_ctrl_qubits = high_level_object.num_ctrl_qubits
1299
+ num_clean_ancillas = options.get("num_clean_ancillas", 0)
1300
+
1301
+ if num_clean_ancillas < 1:
1302
+ return None
1303
+
1304
+ decomposition = synth_mcx_1_clean_kg24(num_ctrl_qubits)
1305
+ return decomposition
1306
+
1307
+
1308
+ class MCXSynthesis1DirtyKG24(HighLevelSynthesisPlugin):
1309
+ r"""Synthesis plugin for a multi-controlled X gate based on the paper by Khattar and
1310
+ Gidney (2024).
1311
+
1312
+ See [1] for details.
1313
+
1314
+ The plugin name is :``mcx.1_dirty_kg24`` which can be used as the key on an :class:`~.HLSConfig`
1315
+ object to use this method with :class:`~.HighLevelSynthesis`.
1316
+
1317
+ For a multi-controlled X gate with :math:`k\ge 3` control qubits this synthesis method requires
1318
+ :math:`1` additional dirty ancillary qubit. The synthesized circuit consists of :math:`k + 2`
1319
+ qubits and at most :math:`24 * k - 48` CX gates.
1320
+
1321
+ The plugin supports the following plugin-specific options:
1322
+
1323
+ * num_clean_ancillas: The number of clean ancillary qubits available.
1324
+
1325
+ References:
1326
+ 1. Khattar and Gidney, Rise of conditionally clean ancillae for optimizing quantum circuits
1327
+ `arXiv:2407.17966 <https://arxiv.org/abs/2407.17966>`__
1328
+ """
1329
+
1330
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1331
+ """Run synthesis for the given MCX gate."""
1332
+
1333
+ if not isinstance(high_level_object, (MCXGate, C3XGate, C4XGate)):
1334
+ # Unfortunately we occasionally have custom instructions called "mcx"
1335
+ # which get wrongly caught by the plugin interface. A simple solution is
1336
+ # to return None in this case, since HLS would proceed to examine
1337
+ # their definition as it should.
1338
+ return None
1339
+
1340
+ num_ctrl_qubits = high_level_object.num_ctrl_qubits
1341
+ num_dirty_ancillas = options.get("num_dirty_ancillas", 0)
1342
+
1343
+ if num_dirty_ancillas < 1:
1344
+ return None
1345
+
1346
+ decomposition = synth_mcx_1_dirty_kg24(num_ctrl_qubits)
1347
+ return decomposition
1348
+
1349
+
1350
+ class MCXSynthesisGrayCode(HighLevelSynthesisPlugin):
1351
+ r"""Synthesis plugin for a multi-controlled X gate based on the Gray code.
1352
+
1353
+ This plugin name is :``mcx.gray_code`` which can be used as the key on
1354
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1355
+
1356
+ For a multi-controlled X gate with :math:`k` control qubits this synthesis
1357
+ method requires no additional clean auxiliary qubits. The synthesized
1358
+ circuit consists of :math:`k + 1` qubits.
1359
+
1360
+ It is not recommended to use this method for large values of :math:`k + 1`
1361
+ as it produces exponentially many gates.
1362
+ """
1363
+
1364
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1365
+ """Run synthesis for the given MCX gate."""
1366
+
1367
+ if not isinstance(high_level_object, (MCXGate, C3XGate, C4XGate)):
1368
+ # Unfortunately we occasionally have custom instructions called "mcx"
1369
+ # which get wrongly caught by the plugin interface. A simple solution is
1370
+ # to return None in this case, since HLS would proceed to examine
1371
+ # their definition as it should.
1372
+ return None
1373
+
1374
+ num_ctrl_qubits = high_level_object.num_ctrl_qubits
1375
+ decomposition = synth_mcx_gray_code(num_ctrl_qubits)
1376
+ return decomposition
1377
+
1378
+
1379
+ class MCXSynthesisNoAuxV24(HighLevelSynthesisPlugin):
1380
+ r"""Synthesis plugin for a multi-controlled X gate based on the
1381
+ implementation for MCPhaseGate, which is in turn based on the
1382
+ paper by Vale et al. (2024).
1383
+
1384
+ See [1] for details.
1385
+
1386
+ This plugin name is :``mcx.noaux_v24`` which can be used as the key on
1387
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1388
+
1389
+ For a multi-controlled X gate with :math:`k` control qubits this synthesis
1390
+ method requires no additional clean auxiliary qubits. The synthesized
1391
+ circuit consists of :math:`k + 1` qubits.
1392
+
1393
+ References:
1394
+ 1. Vale et. al., *Circuit Decomposition of Multicontrolled Special Unitary
1395
+ Single-Qubit Gates*, IEEE TCAD 43(3) (2024),
1396
+ `arXiv:2302.06377 <https://arxiv.org/abs/2302.06377>`_
1397
+ """
1398
+
1399
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1400
+ """Run synthesis for the given MCX gate."""
1401
+
1402
+ if not isinstance(high_level_object, (MCXGate, C3XGate, C4XGate)):
1403
+ # Unfortunately we occasionally have custom instructions called "mcx"
1404
+ # which get wrongly caught by the plugin interface. A simple solution is
1405
+ # to return None in this case, since HLS would proceed to examine
1406
+ # their definition as it should.
1407
+ return None
1408
+
1409
+ num_ctrl_qubits = high_level_object.num_ctrl_qubits
1410
+ decomposition = synth_mcx_noaux_v24(num_ctrl_qubits)
1411
+ return decomposition
1412
+
1413
+
1414
+ class MCXSynthesisDefault(HighLevelSynthesisPlugin):
1415
+ r"""The default synthesis plugin for a multi-controlled X gate.
1416
+
1417
+ This plugin name is :``mcx.default`` which can be used as the key on
1418
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1419
+ """
1420
+
1421
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1422
+ """Run synthesis for the given MCX gate."""
1423
+
1424
+ if not isinstance(high_level_object, (MCXGate, C3XGate, C4XGate)):
1425
+ # Unfortunately we occasionally have custom instructions called "mcx"
1426
+ # which get wrongly caught by the plugin interface. A simple solution is
1427
+ # to return None in this case, since HLS would proceed to examine
1428
+ # their definition as it should.
1429
+ return None
1430
+
1431
+ # Iteratively run other synthesis methods available
1432
+
1433
+ for synthesis_method in [
1434
+ MCXSynthesis2CleanKG24,
1435
+ MCXSynthesis1CleanKG24,
1436
+ MCXSynthesisNCleanM15,
1437
+ MCXSynthesisNDirtyI15,
1438
+ MCXSynthesis2DirtyKG24,
1439
+ MCXSynthesis1DirtyKG24,
1440
+ MCXSynthesis1CleanB95,
1441
+ ]:
1442
+ if (
1443
+ decomposition := synthesis_method().run(
1444
+ high_level_object, coupling_map, target, qubits, **options
1445
+ )
1446
+ ) is not None:
1447
+ return decomposition
1448
+
1449
+ # If no synthesis method was successful, fall back to the default
1450
+ return MCXSynthesisNoAuxV24().run(
1451
+ high_level_object, coupling_map, target, qubits, **options
1452
+ )
1453
+
1454
+
1455
+ class MCMTSynthesisDefault(HighLevelSynthesisPlugin):
1456
+ """A default decomposition for MCMT gates."""
1457
+
1458
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1459
+ # first try to use the V-chain synthesis if enough auxiliary qubits are available
1460
+ if not isinstance(high_level_object, MCMTGate):
1461
+ return None
1462
+
1463
+ if (
1464
+ decomposition := MCMTSynthesisVChain().run(
1465
+ high_level_object, coupling_map, target, qubits, **options
1466
+ )
1467
+ ) is not None:
1468
+ return decomposition
1469
+
1470
+ return MCMTSynthesisNoAux().run(high_level_object, coupling_map, target, qubits, **options)
1471
+
1472
+
1473
+ class MCMTSynthesisNoAux(HighLevelSynthesisPlugin):
1474
+ """A V-chain based synthesis for ``MCMTGate``."""
1475
+
1476
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1477
+ if not isinstance(high_level_object, MCMTGate):
1478
+ return None
1479
+
1480
+ base_gate = high_level_object.base_gate
1481
+ ctrl_state = options.get("ctrl_state", None)
1482
+
1483
+ if high_level_object.num_target_qubits == 1:
1484
+ # no broadcasting needed (makes for better circuit diagrams)
1485
+ circuit = QuantumCircuit(high_level_object.num_qubits)
1486
+ circuit.append(
1487
+ base_gate.control(high_level_object.num_ctrl_qubits, ctrl_state=ctrl_state),
1488
+ circuit.qubits,
1489
+ )
1490
+
1491
+ else:
1492
+ base = QuantumCircuit(high_level_object.num_target_qubits, name=high_level_object.label)
1493
+ for i in range(high_level_object.num_target_qubits):
1494
+ base.append(base_gate, [i], [])
1495
+
1496
+ circuit = base.control(high_level_object.num_ctrl_qubits, ctrl_state=ctrl_state)
1497
+
1498
+ return circuit.decompose()
1499
+
1500
+
1501
+ class MCMTSynthesisVChain(HighLevelSynthesisPlugin):
1502
+ """A V-chain based synthesis for ``MCMTGate``."""
1503
+
1504
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1505
+ if not isinstance(high_level_object, MCMTGate):
1506
+ return None
1507
+
1508
+ if options.get("num_clean_ancillas", 0) < high_level_object.num_ctrl_qubits - 1:
1509
+ return None # insufficient number of auxiliary qubits
1510
+
1511
+ ctrl_state = options.get("ctrl_state", None)
1512
+
1513
+ return synth_mcmt_vchain(
1514
+ high_level_object.base_gate,
1515
+ high_level_object.num_ctrl_qubits,
1516
+ high_level_object.num_target_qubits,
1517
+ ctrl_state,
1518
+ )
1519
+
1520
+
1521
+ class IntComparatorSynthesisDefault(HighLevelSynthesisPlugin):
1522
+ """The default synthesis for ``IntegerComparatorGate``.
1523
+
1524
+ Currently this is only supporting an ancilla-based decomposition.
1525
+ """
1526
+
1527
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1528
+ num_state_qubits = high_level_object.num_qubits - 1
1529
+ num_aux = num_state_qubits - 1
1530
+ if options.get("num_clean_ancillas", 0) < num_aux:
1531
+ return synth_integer_comparator_greedy(
1532
+ num_state_qubits, high_level_object.value, high_level_object.geq
1533
+ )
1534
+
1535
+ return synth_integer_comparator_2s(
1536
+ num_state_qubits, high_level_object.value, high_level_object.geq
1537
+ )
1538
+
1539
+
1540
+ class IntComparatorSynthesisNoAux(HighLevelSynthesisPlugin):
1541
+ """A potentially exponentially expensive comparison w/o auxiliary qubits."""
1542
+
1543
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1544
+ return synth_integer_comparator_greedy(
1545
+ high_level_object.num_state_qubits, high_level_object.value, high_level_object.geq
1546
+ )
1547
+
1548
+
1549
+ class IntComparatorSynthesis2s(HighLevelSynthesisPlugin):
1550
+ """An integer comparison based on 2s complement."""
1551
+
1552
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1553
+ num_aux = high_level_object.num_state_qubits - 1
1554
+ if options.get("num_clean_ancillas", 0) < num_aux:
1555
+ return None
1556
+
1557
+ return synth_integer_comparator_2s(
1558
+ high_level_object.num_state_qubits, high_level_object.value, high_level_object.geq
1559
+ )
1560
+
1561
+
1562
+ class ModularAdderSynthesisDefault(HighLevelSynthesisPlugin):
1563
+ """The default modular adder (no carry in, no carry out qubit) synthesis.
1564
+
1565
+ This plugin name is:``ModularAdder.default`` which can be used as the key on
1566
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1567
+
1568
+ If at least one clean auxiliary qubit is available, the :class:`ModularAdderSynthesisC04`
1569
+ is used, otherwise :class:`ModularAdderSynthesisD00`.
1570
+
1571
+ The plugin supports the following plugin-specific options:
1572
+
1573
+ * ``num_clean_ancillas``: The number of clean auxiliary qubits available.
1574
+
1575
+ """
1576
+
1577
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1578
+ if not isinstance(high_level_object, ModularAdderGate):
1579
+ return None
1580
+
1581
+ # For up to 5 qubits, the QFT-based adder is best
1582
+ if high_level_object.num_state_qubits <= 5:
1583
+ decomposition = ModularAdderSynthesisD00().run(
1584
+ high_level_object, coupling_map, target, qubits, **options
1585
+ )
1586
+ if decomposition is not None:
1587
+ return decomposition
1588
+
1589
+ # Otherwise, the following decomposition is best (if there are enough ancillas)
1590
+ if (
1591
+ decomposition := ModularAdderSynthesisC04().run(
1592
+ high_level_object, coupling_map, target, qubits, **options
1593
+ )
1594
+ ) is not None:
1595
+ return decomposition
1596
+
1597
+ # Otherwise, use the QFT-adder again
1598
+ return ModularAdderSynthesisD00().run(
1599
+ high_level_object, coupling_map, target, qubits, **options
1600
+ )
1601
+
1602
+
1603
+ class ModularAdderSynthesisC04(HighLevelSynthesisPlugin):
1604
+ r"""A ripple-carry adder, modulo :math:`2^n`.
1605
+
1606
+ This plugin name is:``ModularAdder.ripple_c04`` which can be used as the key on
1607
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1608
+
1609
+ This plugin requires at least one clean auxiliary qubit.
1610
+
1611
+ The plugin supports the following plugin-specific options:
1612
+
1613
+ * ``num_clean_ancillas``: The number of clean auxiliary qubits available.
1614
+
1615
+ """
1616
+
1617
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1618
+ if not isinstance(high_level_object, ModularAdderGate):
1619
+ return None
1620
+
1621
+ # unless we implement the full adder, this implementation needs an ancilla qubit
1622
+ if options.get("num_clean_ancillas", 0) < 1:
1623
+ return None
1624
+
1625
+ return adder_ripple_c04(high_level_object.num_state_qubits, kind="fixed")
1626
+
1627
+
1628
+ class ModularAdderSynthesisV95(HighLevelSynthesisPlugin):
1629
+ r"""A ripple-carry adder, modulo :math:`2^n`.
1630
+
1631
+ This plugin name is:``ModularAdder.ripple_v95`` which can be used as the key on
1632
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1633
+
1634
+ For an adder on 2 registers with :math:`n` qubits each, this plugin requires at
1635
+ least :math:`n-1` clean auxiliary qubit.
1636
+
1637
+ The plugin supports the following plugin-specific options:
1638
+
1639
+ * ``num_clean_ancillas``: The number of clean auxiliary qubits available.
1640
+
1641
+ """
1642
+
1643
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1644
+ if not isinstance(high_level_object, ModularAdderGate):
1645
+ return None
1646
+
1647
+ num_state_qubits = high_level_object.num_state_qubits
1648
+
1649
+ # The synthesis method needs n-1 clean ancilla qubits
1650
+ if num_state_qubits - 1 > options.get("num_clean_ancillas", 0):
1651
+ return None
1652
+
1653
+ return adder_ripple_v95(num_state_qubits, kind="fixed")
1654
+
1655
+
1656
+ class ModularAdderSynthesisD00(HighLevelSynthesisPlugin):
1657
+ r"""A QFT-based adder, modulo :math:`2^n`.
1658
+
1659
+ This plugin name is:``ModularAdder.qft_d00`` which can be used as the key on
1660
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1661
+ """
1662
+
1663
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1664
+ if not isinstance(high_level_object, ModularAdderGate):
1665
+ return None
1666
+
1667
+ return adder_qft_d00(high_level_object.num_state_qubits, kind="fixed", annotated=True)
1668
+
1669
+
1670
+ class HalfAdderSynthesisDefault(HighLevelSynthesisPlugin):
1671
+ r"""The default half-adder (no carry in, but a carry out qubit) synthesis.
1672
+
1673
+ If we have an auxiliary qubit available, the Cuccaro ripple-carry adder uses
1674
+ :math:`O(n)` CX gates and 1 auxiliary qubit, whereas the Vedral ripple-carry uses more CX
1675
+ and :math:`n-1` auxiliary qubits. The QFT-based adder uses no auxiliary qubits, but
1676
+ :math:`O(n^2)`, hence it is only used if no auxiliary qubits are available.
1677
+
1678
+ This plugin name is:``HalfAdder.default`` which can be used as the key on
1679
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1680
+
1681
+ If at least one clean auxiliary qubit is available, the :class:`HalfAdderSynthesisC04`
1682
+ is used, otherwise :class:`HalfAdderSynthesisD00`.
1683
+
1684
+ The plugin supports the following plugin-specific options:
1685
+
1686
+ * ``num_clean_ancillas``: The number of clean auxiliary qubits available.
1687
+
1688
+ """
1689
+
1690
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1691
+ if not isinstance(high_level_object, HalfAdderGate):
1692
+ return None
1693
+
1694
+ # For up to 3 qubits, ripple_r25 is better
1695
+ if (
1696
+ high_level_object.num_state_qubits <= 3
1697
+ and (
1698
+ decomposition := HalfAdderSynthesisR25().run(
1699
+ high_level_object, coupling_map, target, qubits, **options
1700
+ )
1701
+ )
1702
+ is not None
1703
+ ):
1704
+ return decomposition
1705
+
1706
+ # The next best option is to use ripple_c04 (if there are enough ancilla qubits)
1707
+ if (
1708
+ decomposition := HalfAdderSynthesisC04().run(
1709
+ high_level_object, coupling_map, target, qubits, **options
1710
+ )
1711
+ ) is not None:
1712
+ return decomposition
1713
+
1714
+ # The ripple_rv_25 adder does not require ancilla qubits and should always succeed
1715
+ return HalfAdderSynthesisR25().run(
1716
+ high_level_object, coupling_map, target, qubits, **options
1717
+ )
1718
+
1719
+
1720
+ class HalfAdderSynthesisC04(HighLevelSynthesisPlugin):
1721
+ """A ripple-carry adder with a carry-out bit.
1722
+
1723
+ This plugin name is:``HalfAdder.ripple_c04`` which can be used as the key on
1724
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1725
+
1726
+ This plugin requires at least one clean auxiliary qubit.
1727
+
1728
+ The plugin supports the following plugin-specific options:
1729
+
1730
+ * ``num_clean_ancillas``: The number of clean auxiliary qubits available.
1731
+
1732
+ """
1733
+
1734
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1735
+ if not isinstance(high_level_object, HalfAdderGate):
1736
+ return None
1737
+
1738
+ # unless we implement the full adder, this implementation needs an ancilla qubit
1739
+ if options.get("num_clean_ancillas", 0) < 1:
1740
+ return None
1741
+
1742
+ return adder_ripple_c04(high_level_object.num_state_qubits, kind="half")
1743
+
1744
+
1745
+ class HalfAdderSynthesisV95(HighLevelSynthesisPlugin):
1746
+ """A ripple-carry adder with a carry-out bit.
1747
+
1748
+ This plugin name is:``HalfAdder.ripple_v95`` which can be used as the key on
1749
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1750
+
1751
+ For an adder on 2 registers with :math:`n` qubits each, this plugin requires at
1752
+ least :math:`n-1` clean auxiliary qubit.
1753
+
1754
+ The plugin supports the following plugin-specific options:
1755
+
1756
+ * ``num_clean_ancillas``: The number of clean auxiliary qubits available.
1757
+ """
1758
+
1759
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1760
+ if not isinstance(high_level_object, HalfAdderGate):
1761
+ return None
1762
+
1763
+ num_state_qubits = high_level_object.num_state_qubits
1764
+
1765
+ # The synthesis method needs n-1 clean ancilla qubits
1766
+ if num_state_qubits - 1 > options.get("num_clean_ancillas", 0):
1767
+ return None
1768
+
1769
+ return adder_ripple_v95(num_state_qubits, kind="half")
1770
+
1771
+
1772
+ class HalfAdderSynthesisR25(HighLevelSynthesisPlugin):
1773
+ """A ripple-carry adder with a carry-out bit with no ancillary qubits.
1774
+
1775
+ This plugin name is:``HalfAdder.ripple_r25`` which can be used as the key on an
1776
+ :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1777
+
1778
+ """
1779
+
1780
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1781
+ if not isinstance(high_level_object, HalfAdderGate):
1782
+ return None
1783
+
1784
+ num_state_qubits = high_level_object.num_state_qubits
1785
+ return adder_ripple_r25(num_state_qubits)
1786
+
1787
+
1788
+ class HalfAdderSynthesisD00(HighLevelSynthesisPlugin):
1789
+ """A QFT-based adder with a carry-in and a carry-out bit.
1790
+
1791
+ This plugin name is:``HalfAdder.qft_d00`` which can be used as the key on
1792
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1793
+ """
1794
+
1795
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1796
+ if not isinstance(high_level_object, HalfAdderGate):
1797
+ return None
1798
+
1799
+ return adder_qft_d00(high_level_object.num_state_qubits, kind="half", annotated=True)
1800
+
1801
+
1802
+ class FullAdderSynthesisDefault(HighLevelSynthesisPlugin):
1803
+ """A ripple-carry adder with a carry-in and a carry-out bit.
1804
+
1805
+ This plugin name is:``FullAdder.default`` which can be used as the key on
1806
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1807
+ """
1808
+
1809
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1810
+ if not isinstance(high_level_object, FullAdderGate):
1811
+ return None
1812
+
1813
+ # FullAdderSynthesisC04 requires no ancilla qubits and returns better results
1814
+ # than FullAdderSynthesisV95 in all cases except for n=1.
1815
+ if high_level_object.num_state_qubits == 1:
1816
+ decomposition = FullAdderSynthesisV95().run(
1817
+ high_level_object, coupling_map, target, qubits, **options
1818
+ )
1819
+ if decomposition is not None:
1820
+ return decomposition
1821
+
1822
+ return FullAdderSynthesisC04().run(
1823
+ high_level_object, coupling_map, target, qubits, **options
1824
+ )
1825
+
1826
+
1827
+ class FullAdderSynthesisC04(HighLevelSynthesisPlugin):
1828
+ """A ripple-carry adder with a carry-in and a carry-out bit.
1829
+
1830
+ This plugin name is:``FullAdder.ripple_c04`` which can be used as the key on
1831
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1832
+
1833
+ This plugin requires no auxiliary qubits.
1834
+ """
1835
+
1836
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1837
+ if not isinstance(high_level_object, FullAdderGate):
1838
+ return None
1839
+
1840
+ return adder_ripple_c04(high_level_object.num_state_qubits, kind="full")
1841
+
1842
+
1843
+ class FullAdderSynthesisV95(HighLevelSynthesisPlugin):
1844
+ """A ripple-carry adder with a carry-in and a carry-out bit.
1845
+
1846
+ This plugin name is:``FullAdder.ripple_v95`` which can be used as the key on
1847
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1848
+
1849
+ For an adder on 2 registers with :math:`n` qubits each, this plugin requires at
1850
+ least :math:`n-1` clean auxiliary qubits.
1851
+
1852
+ The plugin supports the following plugin-specific options:
1853
+
1854
+ * ``num_clean_ancillas``: The number of clean auxiliary qubits available.
1855
+ """
1856
+
1857
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1858
+ if not isinstance(high_level_object, FullAdderGate):
1859
+ return None
1860
+
1861
+ num_state_qubits = high_level_object.num_state_qubits
1862
+
1863
+ # The synthesis method needs n-1 clean ancilla qubits
1864
+ if num_state_qubits - 1 > options.get("num_clean_ancillas", 0):
1865
+ return None
1866
+
1867
+ return adder_ripple_v95(num_state_qubits, kind="full")
1868
+
1869
+
1870
+ class MultiplierSynthesisH18(HighLevelSynthesisPlugin):
1871
+ """A cumulative multiplier based on controlled adders.
1872
+
1873
+ This plugin name is:``Multiplier.cumulative_h18`` which can be used as the key on
1874
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1875
+ """
1876
+
1877
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1878
+ if not isinstance(high_level_object, MultiplierGate):
1879
+ return None
1880
+
1881
+ return multiplier_cumulative_h18(
1882
+ high_level_object.num_state_qubits, high_level_object.num_result_qubits
1883
+ )
1884
+
1885
+
1886
+ class MultiplierSynthesisR17(HighLevelSynthesisPlugin):
1887
+ """A QFT-based multiplier.
1888
+
1889
+ This plugin name is:``Multiplier.qft_r17`` which can be used as the key on
1890
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1891
+ """
1892
+
1893
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1894
+ if not isinstance(high_level_object, MultiplierGate):
1895
+ return None
1896
+
1897
+ return multiplier_qft_r17(
1898
+ high_level_object.num_state_qubits, high_level_object.num_result_qubits
1899
+ )
1900
+
1901
+
1902
+ class PauliEvolutionSynthesisDefault(HighLevelSynthesisPlugin):
1903
+ """Synthesize a :class:`.PauliEvolutionGate` using the default synthesis algorithm.
1904
+
1905
+ This plugin name is:``PauliEvolution.default`` which can be used as the key on
1906
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1907
+
1908
+ The following plugin option can be set:
1909
+
1910
+ * preserve_order: If ``False``, allow re-ordering the Pauli terms in the Hamiltonian to
1911
+ reduce the circuit depth of the decomposition.
1912
+
1913
+ """
1914
+
1915
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1916
+ if not isinstance(high_level_object, PauliEvolutionGate):
1917
+ # Don't do anything if a gate is called "evolution" but is not an
1918
+ # actual PauliEvolutionGate
1919
+ return None
1920
+ algo = high_level_object.synthesis
1921
+
1922
+ original_preserve_order = algo.preserve_order
1923
+ if "preserve_order" in options and isinstance(algo, ProductFormula):
1924
+ algo.preserve_order = options["preserve_order"]
1925
+
1926
+ synth_object = algo.synthesize(high_level_object)
1927
+ algo.preserve_order = original_preserve_order
1928
+ return synth_object
1929
+
1930
+
1931
+ class PauliEvolutionSynthesisRustiq(HighLevelSynthesisPlugin):
1932
+ """Synthesize a :class:`.PauliEvolutionGate` using Rustiq.
1933
+
1934
+ This plugin name is :``PauliEvolution.rustiq`` which can be used as the key on
1935
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
1936
+
1937
+ The Rustiq synthesis algorithm is described in [1], and is implemented in
1938
+ Rust-based quantum circuit synthesis library available at
1939
+ https://github.com/smartiel/rustiq-core.
1940
+
1941
+ On large circuits the plugin may take a significant runtime.
1942
+
1943
+ The plugin supports the following additional options:
1944
+
1945
+ * optimize_count (bool): if `True` the synthesis algorithm will try to optimize
1946
+ the 2-qubit gate count; and if `False` then the 2-qubit depth.
1947
+ * preserve_order (bool): whether the order of paulis should be preserved, up to
1948
+ commutativity.
1949
+ * upto_clifford (bool): if `True`, the final Clifford operator is not synthesized.
1950
+ * upto_phase (bool): if `True`, the global phase of the returned circuit may
1951
+ differ from the global phase of the given pauli network.
1952
+ * resynth_clifford_method (int): describes the strategy to synthesize the final
1953
+ Clifford operator. Allowed values are `0` (naive approach), `1` (qiskit
1954
+ greedy synthesis), `2` (rustiq isometry synthesis).
1955
+
1956
+ References:
1957
+ 1. Timothée Goubault de Brugière and Simon Martiel,
1958
+ *Faster and shorter synthesis of Hamiltonian simulation circuits*,
1959
+ `arXiv:2404.03280 [quant-ph] <https://arxiv.org/abs/2404.03280>`_
1960
+
1961
+ """
1962
+
1963
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
1964
+ if not isinstance(high_level_object, PauliEvolutionGate):
1965
+ # Don't do anything if a gate is called "evolution" but is not an
1966
+ # actual PauliEvolutionGate
1967
+ return None
1968
+
1969
+ algo = high_level_object.synthesis
1970
+
1971
+ if not isinstance(algo, ProductFormula):
1972
+ warnings.warn(
1973
+ "Cannot apply Rustiq if the evolution synthesis does not implement ``expand``. ",
1974
+ stacklevel=2,
1975
+ category=RuntimeWarning,
1976
+ )
1977
+ return None
1978
+
1979
+ original_preserve_order = algo.preserve_order
1980
+ if "preserve_order" in options:
1981
+ algo.preserve_order = options["preserve_order"]
1982
+
1983
+ num_qubits = high_level_object.num_qubits
1984
+ pauli_network = algo.expand(high_level_object)
1985
+
1986
+ optimize_count = options.get("optimize_count", True)
1987
+ preserve_order = options.get("preserve_order", True)
1988
+ upto_clifford = options.get("upto_clifford", False)
1989
+ upto_phase = options.get("upto_phase", False)
1990
+ resynth_clifford_method = options.get("resynth_clifford_method", 1)
1991
+
1992
+ synth_object = synth_pauli_network_rustiq(
1993
+ num_qubits=num_qubits,
1994
+ pauli_network=pauli_network,
1995
+ optimize_count=optimize_count,
1996
+ preserve_order=preserve_order,
1997
+ upto_clifford=upto_clifford,
1998
+ upto_phase=upto_phase,
1999
+ resynth_clifford_method=resynth_clifford_method,
2000
+ )
2001
+ algo.preserve_order = original_preserve_order
2002
+ return synth_object
2003
+
2004
+
2005
+ class AnnotatedSynthesisDefault(HighLevelSynthesisPlugin):
2006
+ """Synthesize an :class:`.AnnotatedOperation` using the default synthesis algorithm.
2007
+
2008
+ This plugin name is:``annotated.default`` which can be used as the key on
2009
+ an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
2010
+ """
2011
+
2012
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
2013
+ # The plugin is triggered based on the name (i.e. for operations called "annotated").
2014
+ # However, we should only do something when the operation is truthfully an AnnotatedOperation.
2015
+ if not isinstance(high_level_object, AnnotatedOperation):
2016
+ return None
2017
+
2018
+ # Combine the modifiers. If there were no modifiers, or the modifiers magically canceled out,
2019
+ # return the quantum circuit containing the base operation.
2020
+ high_level_object = self._canonicalize_op(high_level_object)
2021
+ if not isinstance(high_level_object, AnnotatedOperation):
2022
+ return self._instruction_to_circuit(high_level_object)
2023
+
2024
+ operation = high_level_object
2025
+ modifiers = high_level_object.modifiers
2026
+
2027
+ # The plugin needs additional information that is not yet passed via the run's method
2028
+ # arguments: namely high-level-synthesis data and options, the global qubits over which
2029
+ # the operation is defined, and the initial state of each global qubit.
2030
+ tracker = options.get("qubit_tracker", None)
2031
+ data = options.get("hls_data", None)
2032
+ input_qubits = options.get("input_qubits", None)
2033
+
2034
+ if data is None or input_qubits is None:
2035
+ raise TranspilerError(
2036
+ "The AnnotatedSynthesisDefault plugin should receive data and input_qubits via options."
2037
+ )
2038
+
2039
+ # The synthesis consists of two steps:
2040
+ # - First, we synthesize the base operation.
2041
+ # - Second, we apply modifiers to this circuit.
2042
+ #
2043
+ # An important optimization (similar to the code in ``add_control.py``) is to synthesize
2044
+ # the base operation with respect to a larger set of "basis" gates, to which the control
2045
+ # logic can be added more efficiently. In addition, we add annotated operations to be
2046
+ # in this larger set, exploiting the fact that adding control to annotated operations
2047
+ # returns a new annotated operation with an extended list of modifiers.
2048
+ #
2049
+ # Note that it is fine for this function to return a circuit with high-level objects
2050
+ # (including annotated operations) as the HighLevelSynthesis transpiler pass will
2051
+ # recursively re-synthesize this circuit, However, we should always guarantee that some
2052
+ # progress is made.
2053
+ basis = set(EFFICIENTLY_CONTROLLED_GATES + ["annotated", "mcx", "qft"])
2054
+
2055
+ base_synthesis_data = HighLevelSynthesisData(
2056
+ hls_config=data.hls_config,
2057
+ hls_plugin_manager=data.hls_plugin_manager,
2058
+ coupling_map=None,
2059
+ target=None,
2060
+ equivalence_library=data.equivalence_library,
2061
+ hls_op_names=data.hls_op_names,
2062
+ device_insts=basis,
2063
+ use_physical_indices=data.use_physical_indices,
2064
+ min_qubits=0,
2065
+ unroll_definitions=data.unroll_definitions,
2066
+ )
2067
+
2068
+ num_ctrl = sum(mod.num_ctrl_qubits for mod in modifiers if isinstance(mod, ControlModifier))
2069
+ power = sum(mod.power for mod in modifiers if isinstance(mod, PowerModifier))
2070
+ is_inverted = sum(1 for mod in modifiers if isinstance(mod, InverseModifier)) % 2
2071
+
2072
+ # First, synthesize the base operation of this annotated operation.
2073
+ # As this step cannot use any control qubits as auxiliary qubits, we use a dedicated
2074
+ # tracker (annotated_tracker).
2075
+ # The logic is as follows:
2076
+ # - annotated_tracker.disable control qubits
2077
+ # - if have power or inverse modifiers, annotated_tracker.set_dirty(base_qubits)
2078
+ # - synthesize the base operation using annotated tracker
2079
+ # - main_tracker.set_dirty(base_qubits)
2080
+ #
2081
+ # Note that we need to set the base_qubits to dirty if we have power or inverse
2082
+ # modifiers. For power: even if the power is a positive integer (that is, we need
2083
+ # to repeat the same circuit multiple times), even if the target is initially at |0>,
2084
+ # it will generally not be at |0> after one iteration. For inverse: as we
2085
+ # flip the order of operations, we cannot exploit which qubits are at |0> as "viewed from
2086
+ # the back of the circuit". If we just have control modifiers, we can use the state
2087
+ # of base qubits when synthesizing the controlled operation.
2088
+ #
2089
+ # In addition, all of the other global qubits that are not a part of the annotated
2090
+ # operation can be used as they are in all cases, since we are assuming that all of
2091
+ # the synthesis methods preserve the states of ancilla qubits.
2092
+ annotated_tracker = tracker.copy()
2093
+ control_qubits = input_qubits[:num_ctrl]
2094
+ base_qubits = input_qubits[num_ctrl:]
2095
+ annotated_tracker.disable(control_qubits) # do not access control qubits
2096
+ if power != 0 or is_inverted:
2097
+ annotated_tracker.set_dirty(base_qubits)
2098
+
2099
+ # Note that synthesize_operation also returns the output qubits on which the
2100
+ # operation is defined, however currently the plugin mechanism has no way
2101
+ # to return these (and instead the upstream code greedily grabs some ancilla
2102
+ # qubits from the circuit). We should refactor the plugin "run" iterface to
2103
+ # return the actual ancilla qubits used.
2104
+ synthesized_base_op_result = synthesize_operation(
2105
+ operation.base_op, base_qubits, base_synthesis_data, annotated_tracker
2106
+ )
2107
+
2108
+ # The base operation does not need to be synthesized.
2109
+ # For simplicity, we wrap the instruction into a circuit. Note that
2110
+ # this should not deteriorate the quality of the result.
2111
+ if synthesized_base_op_result is None:
2112
+ synthesized_base_op = self._instruction_to_circuit(operation.base_op)
2113
+ else:
2114
+ synthesized_base_op = QuantumCircuit._from_circuit_data(synthesized_base_op_result[0])
2115
+ tracker.set_dirty(base_qubits)
2116
+
2117
+ # As one simple optimization, we apply conjugate decomposition to the circuit obtained
2118
+ # while synthesizing the base operator.
2119
+ conjugate_decomp = self._conjugate_decomposition(synthesized_base_op)
2120
+
2121
+ if conjugate_decomp is None:
2122
+ # Apply annotations to the whole circuit.
2123
+ # This step currently does not introduce ancilla qubits. However it makes
2124
+ # a lot of sense to allow this in the future.
2125
+ synthesized = self._apply_annotations(synthesized_base_op, operation.modifiers)
2126
+ else:
2127
+ # Apply annotations only to the middle part of the circuit.
2128
+ (front, middle, back) = conjugate_decomp
2129
+ synthesized = QuantumCircuit(operation.num_qubits)
2130
+ synthesized.compose(
2131
+ front, synthesized.qubits[num_ctrl : operation.num_qubits], inplace=True
2132
+ )
2133
+ synthesized.compose(
2134
+ self._apply_annotations(middle, operation.modifiers),
2135
+ synthesized.qubits,
2136
+ inplace=True,
2137
+ )
2138
+ synthesized.compose(
2139
+ back, synthesized.qubits[num_ctrl : operation.num_qubits], inplace=True
2140
+ )
2141
+
2142
+ return synthesized
2143
+
2144
+ @staticmethod
2145
+ def _apply_annotations(circuit: QuantumCircuit, modifiers: list[Modifier]) -> QuantumCircuit:
2146
+ """
2147
+ Applies modifiers to a quantum circuit.
2148
+ """
2149
+ for modifier in modifiers:
2150
+ if isinstance(modifier, InverseModifier):
2151
+ circuit = circuit.inverse()
2152
+
2153
+ elif isinstance(modifier, ControlModifier):
2154
+ if circuit.num_clbits > 0:
2155
+ raise TranspilerError(
2156
+ "AnnotatedSynthesisDefault: cannot control a circuit with classical bits."
2157
+ )
2158
+
2159
+ # Apply the control modifier to each gate in the circuit.
2160
+ controlled_circuit = QuantumCircuit(modifier.num_ctrl_qubits + circuit.num_qubits)
2161
+ if circuit.global_phase != 0:
2162
+ controlled_op = GlobalPhaseGate(circuit.global_phase).control(
2163
+ num_ctrl_qubits=modifier.num_ctrl_qubits,
2164
+ label=None,
2165
+ ctrl_state=modifier.ctrl_state,
2166
+ annotated=False,
2167
+ )
2168
+ controlled_qubits = list(range(0, modifier.num_ctrl_qubits))
2169
+ controlled_circuit.append(controlled_op, controlled_qubits)
2170
+ for inst in circuit:
2171
+ inst_op = inst.operation
2172
+ inst_qubits = inst.qubits
2173
+ controlled_op = inst_op.control(
2174
+ num_ctrl_qubits=modifier.num_ctrl_qubits,
2175
+ label=None,
2176
+ ctrl_state=modifier.ctrl_state,
2177
+ annotated=False,
2178
+ )
2179
+ controlled_qubits = list(range(0, modifier.num_ctrl_qubits)) + [
2180
+ modifier.num_ctrl_qubits + circuit.find_bit(q).index for q in inst_qubits
2181
+ ]
2182
+ controlled_circuit.append(controlled_op, controlled_qubits)
2183
+
2184
+ circuit = controlled_circuit
2185
+
2186
+ if isinstance(circuit, AnnotatedOperation):
2187
+ raise TranspilerError(
2188
+ "AnnotatedSynthesisDefault: failed to synthesize the control modifier."
2189
+ )
2190
+
2191
+ elif isinstance(modifier, PowerModifier):
2192
+ circuit = circuit.power(modifier.power)
2193
+
2194
+ else:
2195
+ raise TranspilerError(f"AnnotatedSynthesisDefault: Unknown modifier {modifier}.")
2196
+
2197
+ return circuit
2198
+
2199
+ @staticmethod
2200
+ def _instruction_to_circuit(op: Operation) -> QuantumCircuit:
2201
+ """Wraps a single operation into a quantum circuit."""
2202
+ circuit = QuantumCircuit(op.num_qubits, op.num_clbits)
2203
+ circuit.append(op, circuit.qubits, circuit.clbits)
2204
+ return circuit
2205
+
2206
+ @staticmethod
2207
+ def _instruction_to_circuit(op: Operation) -> QuantumCircuit:
2208
+ """Wraps a single operation into a quantum circuit."""
2209
+ circuit = QuantumCircuit(op.num_qubits, op.num_clbits)
2210
+ circuit.append(op, circuit.qubits, circuit.clbits)
2211
+ return circuit
2212
+
2213
+ @staticmethod
2214
+ def _canonicalize_op(op: Operation) -> Operation:
2215
+ """
2216
+ Combines recursive annotated operations and canonicalizes modifiers.
2217
+ """
2218
+ cur = op
2219
+ all_modifiers = []
2220
+
2221
+ while isinstance(cur, AnnotatedOperation):
2222
+ all_modifiers.append(cur.modifiers)
2223
+ cur = cur.base_op
2224
+
2225
+ new_modifiers = []
2226
+ for modifiers in all_modifiers[::-1]:
2227
+ new_modifiers.extend(modifiers)
2228
+
2229
+ canonical_modifiers = _canonicalize_modifiers(new_modifiers)
2230
+
2231
+ if not canonical_modifiers:
2232
+ return cur
2233
+
2234
+ return AnnotatedOperation(cur, canonical_modifiers)
2235
+
2236
+ @staticmethod
2237
+ def _are_inverse_ops(inst1: "CircuitInstruction", inst2: "CircuitInstruction"):
2238
+ """A very naive function that checks whether two circuit instructions are inverse of
2239
+ each other. The main use-case covered is a ``QFTGate`` and its inverse, represented as
2240
+ an ``AnnotatedOperation`` with a single ``InverseModifier``.
2241
+ """
2242
+ res = False
2243
+
2244
+ if (
2245
+ inst1.qubits != inst2.qubits
2246
+ or inst1.clbits != inst2.clbits
2247
+ or len(inst1.params) != len(inst2.params)
2248
+ ):
2249
+ return False
2250
+
2251
+ op1 = inst1.operation
2252
+ op2 = inst2.operation
2253
+
2254
+ ann1 = isinstance(op1, AnnotatedOperation)
2255
+ ann2 = isinstance(op2, AnnotatedOperation)
2256
+
2257
+ if not ann1 and not ann2:
2258
+ res = op1 == op2.inverse()
2259
+ elif not ann1 and ann2 and op2.modifiers == [InverseModifier()]:
2260
+ res = op1 == op2.base_op
2261
+ elif not ann2 and ann1 and op1.modifiers == [InverseModifier()]:
2262
+ res = op1.base_op == op2
2263
+
2264
+ return res
2265
+
2266
+ @staticmethod
2267
+ def _conjugate_decomposition(
2268
+ circuit: QuantumCircuit,
2269
+ ) -> tuple[QuantumCircuit, QuantumCircuit, QuantumCircuit] | None:
2270
+ """
2271
+ Decomposes a circuit ``A`` into 3 sub-circuits ``P``, ``Q``, ``R`` such that
2272
+ ``A = P -- Q -- R`` and ``R = P^{-1}``.
2273
+
2274
+ This is accomplished by iteratively finding inverse nodes at the front and at the back of the
2275
+ circuit.
2276
+
2277
+ The function returns ``None`` when ``P`` and ``R`` are empty.
2278
+ """
2279
+ num_gates = circuit.size()
2280
+
2281
+ idx = 0
2282
+ ridx = num_gates - 1
2283
+
2284
+ while True:
2285
+ if idx >= ridx:
2286
+ break
2287
+ if AnnotatedSynthesisDefault._are_inverse_ops(circuit[idx], circuit[ridx]):
2288
+ idx += 1
2289
+ ridx -= 1
2290
+ else:
2291
+ break
2292
+
2293
+ if idx == 0:
2294
+ return None
2295
+
2296
+ front_circuit = circuit.copy_empty_like()
2297
+ front_circuit.global_phase = 0
2298
+ for i in range(0, idx):
2299
+ front_circuit.append(circuit[i])
2300
+ middle_circuit = circuit.copy_empty_like() # inherits the global phase
2301
+ for i in range(idx, ridx + 1):
2302
+ middle_circuit.append(circuit[i])
2303
+ back_circuit = circuit.copy_empty_like()
2304
+ back_circuit.global_phase = 0
2305
+ for i in range(ridx + 1, num_gates):
2306
+ back_circuit.append(circuit[i])
2307
+ return (front_circuit, middle_circuit, back_circuit)
2308
+
2309
+
2310
+ class WeightedSumSynthesisDefault(HighLevelSynthesisPlugin):
2311
+ """Synthesize a :class:`.WeightedSumGate` using the default synthesis algorithm.
2312
+
2313
+ This plugin name is:``WeightedSum.default`` which can be used as the key on
2314
+ an :class:`.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
2315
+
2316
+ .. note::
2317
+
2318
+ This default plugin requires auxiliary qubits. There is currently no implementation
2319
+ available without auxiliary qubits.
2320
+
2321
+ """
2322
+
2323
+ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
2324
+ if not isinstance(high_level_object, WeightedSumGate):
2325
+ return None
2326
+
2327
+ required_auxiliaries = (
2328
+ high_level_object.num_sum_qubits - 1 + int(high_level_object.num_sum_qubits > 2)
2329
+ )
2330
+ if (num_clean := options.get("num_clean_ancillas", 0)) < required_auxiliaries:
2331
+ warnings.warn(
2332
+ f"Cannot synthesize a WeightedSumGate on {high_level_object.num_state_qubits} state "
2333
+ f"qubits with less than {required_auxiliaries} clean auxiliary qubits. Only "
2334
+ f"{num_clean} are available. This will likely lead to a error in HighLevelSynthesis."
2335
+ )
2336
+ return None
2337
+
2338
+ return synth_weighted_sum_carry(high_level_object)