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,1849 @@
1
+ # This code is part of Qiskit.
2
+ #
3
+ # (C) Copyright IBM 2017, 2018.
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
+ A module for drawing circuits in ascii art or some other text representation
15
+ """
16
+
17
+ from io import StringIO
18
+ from warnings import warn
19
+ from shutil import get_terminal_size
20
+ import collections
21
+ import sys
22
+
23
+ from qiskit.circuit import Qubit, Clbit, ClassicalRegister, CircuitError
24
+ from qiskit.circuit import ControlledGate, Reset, Measure
25
+ from qiskit.circuit import ControlFlowOp, WhileLoopOp, IfElseOp, ForLoopOp, SwitchCaseOp, BoxOp
26
+ from qiskit.circuit.classical import expr
27
+ from qiskit.circuit.controlflow import node_resources
28
+ from qiskit.circuit.library.standard_gates import IGate, RZZGate, SwapGate, SXGate, SXdgGate
29
+ from qiskit.circuit.annotated_operation import _canonicalize_modifiers, ControlModifier
30
+ from qiskit.circuit.tools.pi_check import pi_check
31
+ from qiskit.qasm3 import ast
32
+ from qiskit.qasm3.printer import BasicPrinter
33
+ from qiskit.qasm3.exporter import _ExprBuilder
34
+
35
+ from ._utils import (
36
+ get_gate_ctrl_text,
37
+ get_param_str,
38
+ get_wire_map,
39
+ get_bit_register,
40
+ get_bit_reg_index,
41
+ get_wire_label,
42
+ get_condition_label_val,
43
+ _get_layered_instructions,
44
+ )
45
+ from ..exceptions import VisualizationError
46
+
47
+ # Indicators for left, middle, and right of control flow gates
48
+ CF_LEFT = 0
49
+ CF_MID = 1
50
+ CF_RIGHT = 2
51
+
52
+
53
+ class TextDrawerEncodingError(VisualizationError):
54
+ """A problem with encoding"""
55
+
56
+ pass
57
+
58
+
59
+ class DrawElement:
60
+ """An element is an operation that needs to be drawn."""
61
+
62
+ def __init__(self, label=None):
63
+ self._width = None
64
+ self.label = self.mid_content = label
65
+ self.top_format = self.mid_format = self.bot_format = "%s"
66
+ self.top_connect = self.bot_connect = " "
67
+ self.top_pad = self._mid_padding = self.bot_pad = " "
68
+ self.mid_bck = self.top_bck = self.bot_bck = " "
69
+ self.bot_connector = {}
70
+ self.top_connector = {}
71
+ self.right_fill = self.left_fill = self.layer_width = 0
72
+ self.wire_label = ""
73
+
74
+ @property
75
+ def top(self):
76
+ """Constructs the top line of the element"""
77
+ if (self.width % 2) == 0 and len(self.top_format) % 2 == 1 and len(self.top_connect) == 1:
78
+ ret = self.top_format % (self.top_pad + self.top_connect).center(
79
+ self.width, self.top_pad
80
+ )
81
+ else:
82
+ ret = self.top_format % self.top_connect.center(self.width, self.top_pad)
83
+ if self.right_fill:
84
+ ret = ret.ljust(self.right_fill, self.top_pad)
85
+ if self.left_fill:
86
+ ret = ret.rjust(self.left_fill, self.top_pad)
87
+ ret = ret.center(self.layer_width, self.top_bck)
88
+ return ret
89
+
90
+ @property
91
+ def mid(self):
92
+ """Constructs the middle line of the element"""
93
+ ret = self.mid_format % self.mid_content.center(self.width, self._mid_padding)
94
+ if self.right_fill:
95
+ ret = ret.ljust(self.right_fill, self._mid_padding)
96
+ if self.left_fill:
97
+ ret = ret.rjust(self.left_fill, self._mid_padding)
98
+ ret = ret.center(self.layer_width, self.mid_bck)
99
+ return ret
100
+
101
+ @property
102
+ def bot(self):
103
+ """Constructs the bottom line of the element"""
104
+ if (self.width % 2) == 0 and len(self.top_format) % 2 == 1:
105
+ ret = self.bot_format % (self.bot_pad + self.bot_connect).center(
106
+ self.width, self.bot_pad
107
+ )
108
+ else:
109
+ ret = self.bot_format % self.bot_connect.center(self.width, self.bot_pad)
110
+ if self.right_fill:
111
+ ret = ret.ljust(self.right_fill, self.bot_pad)
112
+ if self.left_fill:
113
+ ret = ret.rjust(self.left_fill, self.bot_pad)
114
+ ret = ret.center(self.layer_width, self.bot_bck)
115
+ return ret
116
+
117
+ @property
118
+ def length(self):
119
+ """Returns the length of the element, including the box around."""
120
+ return max(len(self.top), len(self.mid), len(self.bot))
121
+
122
+ @property
123
+ def width(self):
124
+ """Returns the width of the label, including padding"""
125
+ if self._width:
126
+ return self._width
127
+ return len(self.mid_content)
128
+
129
+ @width.setter
130
+ def width(self, value):
131
+ self._width = value
132
+
133
+ def connect(self, wire_char, where, label=None):
134
+ """Connects boxes and elements using wire_char and setting proper connectors.
135
+
136
+ Args:
137
+ wire_char (char): For example '║' or '│'.
138
+ where (list["top", "bot"]): Where the connector should be set.
139
+ label (string): Some connectors have a label (see cu1, for example).
140
+ """
141
+
142
+ if "top" in where and self.top_connector:
143
+ self.top_connect = self.top_connector[wire_char]
144
+
145
+ if "bot" in where and self.bot_connector:
146
+ self.bot_connect = self.bot_connector[wire_char]
147
+
148
+ if label:
149
+ self.top_format = self.top_format[:-1] + (label if label else "")
150
+
151
+
152
+ class BoxOnClWire(DrawElement):
153
+ """Draws a box on the classical wire.
154
+
155
+ ::
156
+
157
+ top: ┌───┐ ┌───┐
158
+ mid: ╡ A ╞ ══╡ A ╞══
159
+ bot: └───┘ └───┘
160
+ """
161
+
162
+ def __init__(self, label="", top_connect="─", bot_connect="─"):
163
+ super().__init__(label)
164
+ self.top_format = "┌─%s─┐"
165
+ self.mid_format = "╡ %s ╞"
166
+ self.bot_format = "└─%s─┘"
167
+ self.top_pad = self.bot_pad = "─"
168
+ self.mid_bck = "═"
169
+ self.top_connect = top_connect
170
+ self.bot_connect = bot_connect
171
+ self.mid_content = label
172
+
173
+
174
+ class BoxOnQuWire(DrawElement):
175
+ """Draws a box on the quantum wire.
176
+
177
+ ::
178
+
179
+ top: ┌───┐ ┌───┐
180
+ mid: ┤ A ├ ──┤ A ├──
181
+ bot: └───┘ └───┘
182
+ """
183
+
184
+ def __init__(self, label="", top_connect="─", conditional=False):
185
+ super().__init__(label)
186
+ self.top_format = "┌─%s─┐"
187
+ self.mid_format = "┤ %s ├"
188
+ self.bot_format = "└─%s─┘"
189
+ self.top_pad = self.bot_pad = self.mid_bck = "─"
190
+ self.top_connect = top_connect
191
+ self.bot_connect = "╥" if conditional else "─"
192
+ self.mid_content = label
193
+ self.top_connector = {"│": "┴"}
194
+ self.bot_connector = {"│": "┬"}
195
+
196
+
197
+ class MeasureTo(DrawElement):
198
+ """The element on the classic wire to which the measure is performed.
199
+
200
+ ::
201
+
202
+ top: ║ ║
203
+ mid: ═╩═ ═══╩═══
204
+ bot:
205
+ """
206
+
207
+ def __init__(self, label=""):
208
+ super().__init__()
209
+ self.top_connect = " ║ "
210
+ self.mid_content = "═╩═"
211
+ self.bot_connect = label
212
+ self.mid_bck = "═"
213
+
214
+
215
+ class MeasureFrom(BoxOnQuWire):
216
+ """The element on the quantum wire in which the measure is performed.
217
+
218
+ ::
219
+
220
+ top: ┌─┐ ┌─┐
221
+ mid: ┤M├ ───┤M├───
222
+ bot: └╥┘ └╥┘
223
+ """
224
+
225
+ def __init__(self):
226
+ super().__init__()
227
+ self.top_format = self.mid_format = self.bot_format = "%s"
228
+ self.top_connect = "┌─┐"
229
+ self.mid_content = "┤M├"
230
+ self.bot_connect = "└╥┘"
231
+
232
+ self.top_pad = self.bot_pad = " "
233
+ self._mid_padding = "─"
234
+
235
+
236
+ class MultiBox(DrawElement):
237
+ """Elements that are drawn over multiple wires."""
238
+
239
+ def center_label(self, input_length, order):
240
+ """In multi-bit elements, the label is centered vertically.
241
+
242
+ Args:
243
+ input_length (int): Rhe amount of wires affected.
244
+ order (int): Which middle element is this one?
245
+ """
246
+ if input_length == order == 0:
247
+ self.top_connect = self.label
248
+ return
249
+ location_in_the_box = "*".center(input_length * 2 - 1).index("*") + 1
250
+ top_limit = order * 2 + 2
251
+ bot_limit = top_limit + 2
252
+ if top_limit <= location_in_the_box < bot_limit:
253
+ if location_in_the_box == top_limit:
254
+ self.top_connect = self.label
255
+ elif location_in_the_box == top_limit + 1:
256
+ self.mid_content = self.label
257
+ else:
258
+ self.bot_connect = self.label
259
+
260
+ @property
261
+ def width(self):
262
+ """Returns the width of the label, including padding"""
263
+ if self._width:
264
+ return self._width
265
+ return len(self.label)
266
+
267
+
268
+ class BoxOnQuWireTop(MultiBox, BoxOnQuWire):
269
+ """Draws the top part of a box that affects more than one quantum wire"""
270
+
271
+ def __init__(self, label="", top_connect=None, wire_label=""):
272
+ super().__init__(label)
273
+ self.wire_label = wire_label
274
+ self.bot_connect = self.bot_pad = " "
275
+ self.mid_content = "" # The label will be put by some other part of the box.
276
+ self.left_fill = len(self.wire_label)
277
+ self.top_format = "┌─" + "s".center(self.left_fill + 1, "─") + "─┐"
278
+ self.top_format = self.top_format.replace("s", "%s")
279
+ self.mid_format = f"┤{self.wire_label} %s ├"
280
+ self.bot_format = f"│{self.bot_pad * self.left_fill} %s │"
281
+ self.top_connect = top_connect if top_connect else "─"
282
+
283
+
284
+ class BoxOnWireMid(MultiBox):
285
+ """A generic middle box"""
286
+
287
+ def __init__(self, label, input_length, order, wire_label=""):
288
+ super().__init__(label)
289
+ self.top_pad = self.bot_pad = self.top_connect = self.bot_connect = " "
290
+ self.wire_label = wire_label
291
+ self.left_fill = len(self.wire_label)
292
+ self.top_format = f"│{self.top_pad * self.left_fill} %s │"
293
+ self.bot_format = f"│{self.bot_pad * self.left_fill} %s │"
294
+ self.top_connect = self.bot_connect = self.mid_content = ""
295
+ self.center_label(input_length, order)
296
+
297
+
298
+ class BoxOnQuWireMid(BoxOnWireMid, BoxOnQuWire):
299
+ """Draws the middle part of a box that affects more than one quantum wire"""
300
+
301
+ def __init__(self, label, input_length, order, wire_label="", control_label=None):
302
+ super().__init__(label, input_length, order, wire_label=wire_label)
303
+ if control_label:
304
+ self.mid_format = f"{control_label}{self.wire_label} %s ├"
305
+ else:
306
+ self.mid_format = f"┤{self.wire_label} %s ├"
307
+
308
+
309
+ class BoxOnQuWireBot(MultiBox, BoxOnQuWire):
310
+ """Draws the bottom part of a box that affects more than one quantum wire"""
311
+
312
+ def __init__(self, label, input_length, bot_connect=None, wire_label="", conditional=False):
313
+ super().__init__(label)
314
+ self.wire_label = wire_label
315
+ self.top_pad = " "
316
+ self.left_fill = len(self.wire_label)
317
+ self.top_format = f"│{self.top_pad * self.left_fill} %s │"
318
+ self.mid_format = f"┤{self.wire_label} %s ├"
319
+ self.bot_format = "└─" + "s".center(self.left_fill + 1, "─") + "─┘"
320
+ self.bot_format = self.bot_format.replace("s", "%s")
321
+ bot_connect = bot_connect if bot_connect else "─"
322
+ self.bot_connect = "╥" if conditional else bot_connect
323
+
324
+ self.mid_content = self.top_connect = ""
325
+ if input_length <= 2:
326
+ self.top_connect = label
327
+
328
+
329
+ class FlowOnQuWire(DrawElement):
330
+ """Draws a box for a ControlFlowOp using a single qubit."""
331
+
332
+ def __init__(self, section, label="", top_connect="─", conditional=False):
333
+ super().__init__(label)
334
+ if section == CF_RIGHT:
335
+ self.top_format = " ─%s─┐"
336
+ self.mid_format = " %s ├"
337
+ self.bot_format = " ─%s─┘"
338
+ else:
339
+ self.top_format = "┌─%s─ "
340
+ self.mid_format = "┤ %s "
341
+ self.bot_format = "└─%s─ "
342
+ self.top_pad = self.bot_pad = self.mid_bck = "─"
343
+ self.top_connect = top_connect
344
+ self.bot_connect = "╥" if conditional else "─"
345
+ self.mid_content = label
346
+ self.top_connector = {"│": "┴"}
347
+ self.bot_connector = {"│": "┬"}
348
+
349
+
350
+ class FlowOnQuWireTop(MultiBox, BoxOnQuWire):
351
+ """Draws the top of a box for a ControlFlowOp that uses more than one qubit."""
352
+
353
+ def __init__(self, section, label="", top_connect=None, wire_label=""):
354
+ super().__init__(label)
355
+ self.wire_label = wire_label
356
+ self.bot_connect = self.bot_pad = " "
357
+ self.mid_content = "" # The label will be put by some other part of the box.
358
+ self.left_fill = len(self.wire_label)
359
+ if section == CF_RIGHT:
360
+ self.top_format = "s".center(self.left_fill + 2, "─") + "─┐"
361
+ self.top_format = self.top_format.replace("s", "%s")
362
+ self.mid_format = f" {self.wire_label} %s ├"
363
+ self.bot_format = f" {self.bot_pad * self.left_fill} %s │"
364
+ else:
365
+ self.top_format = "┌─" + "s".center(self.left_fill + 2, "─") + " "
366
+ self.top_format = self.top_format.replace("s", "%s")
367
+ self.mid_format = f"┤{self.wire_label} %s "
368
+ self.bot_format = f"│{self.bot_pad * self.left_fill} %s "
369
+ self.top_connect = top_connect if top_connect else "─"
370
+
371
+
372
+ class FlowOnQuWireMid(MultiBox, BoxOnQuWire):
373
+ """Draws the middle of a box for a ControlFlowOp that uses more than one qubit."""
374
+
375
+ def __init__(self, section, label, input_length, order, wire_label=""):
376
+ super().__init__(label)
377
+ self.top_pad = self.bot_pad = self.top_connect = self.bot_connect = " "
378
+ self.wire_label = wire_label
379
+ self.left_fill = len(self.wire_label)
380
+ if section == CF_RIGHT:
381
+ self.top_format = f" {self.top_pad * self.left_fill} %s │"
382
+ self.bot_format = f" {self.bot_pad * self.left_fill} %s │"
383
+ self.mid_format = f" {self.wire_label} %s ├"
384
+ else:
385
+ self.top_format = f"│{self.top_pad * self.left_fill} %s "
386
+ self.bot_format = f"│{self.bot_pad * self.left_fill} %s "
387
+ self.mid_format = f"┤{self.wire_label} %s "
388
+ self.top_connect = self.bot_connect = self.mid_content = ""
389
+ self.center_label(input_length, order)
390
+
391
+
392
+ class FlowOnQuWireBot(MultiBox, BoxOnQuWire):
393
+ """Draws the bottom of a box for a ControlFlowOp that uses more than one qubit."""
394
+
395
+ def __init__(
396
+ self,
397
+ section,
398
+ label,
399
+ input_length,
400
+ bot_connect=None,
401
+ wire_label="",
402
+ conditional=False,
403
+ ):
404
+ super().__init__(label)
405
+ self.wire_label = wire_label
406
+ self.top_pad = " "
407
+ self.left_fill = len(self.wire_label)
408
+ if section == CF_RIGHT:
409
+ self.top_format = f" {self.top_pad * self.left_fill} %s │"
410
+ self.mid_format = f" {self.wire_label} %s ├"
411
+ self.bot_format = " " + "s".center(self.left_fill + 2, "─") + "─┘"
412
+ self.bot_format = self.bot_format.replace("s", "%s")
413
+ else:
414
+ self.top_format = f"│{self.top_pad * self.left_fill} %s "
415
+ self.mid_format = f"┤{self.wire_label} %s "
416
+ self.bot_format = "└─" + "s".center(self.left_fill + 2, "─") + " "
417
+ self.bot_format = self.bot_format.replace("s", "%s")
418
+ bot_connect = bot_connect if bot_connect else "─"
419
+ self.bot_connect = "╥" if conditional else bot_connect
420
+
421
+ self.mid_content = self.top_connect = ""
422
+ if input_length <= 2:
423
+ self.top_connect = label
424
+
425
+
426
+ class BoxOnClWireTop(MultiBox, BoxOnClWire):
427
+ """Draws the top part of a conditional box that affects more than one classical wire"""
428
+
429
+ def __init__(self, label="", top_connect=None, wire_label=""):
430
+ super().__init__(label)
431
+ self.wire_label = wire_label
432
+ self.mid_content = "" # The label will be put by some other part of the box.
433
+ self.bot_format = "│ %s │"
434
+ self.top_connect = top_connect if top_connect else "─"
435
+ self.bot_connect = self.bot_pad = " "
436
+
437
+
438
+ class BoxOnClWireMid(BoxOnWireMid, BoxOnClWire):
439
+ """Draws the middle part of a conditional box that affects more than one classical wire"""
440
+
441
+ def __init__(self, label, input_length, order, wire_label="", **_):
442
+ super().__init__(label, input_length, order, wire_label=wire_label)
443
+ self.mid_format = f"╡{self.wire_label} %s ╞"
444
+
445
+
446
+ class BoxOnClWireBot(MultiBox, BoxOnClWire):
447
+ """Draws the bottom part of a conditional box that affects more than one classical wire"""
448
+
449
+ def __init__(self, label, input_length, bot_connect="─", wire_label="", **_):
450
+ super().__init__(label)
451
+ self.wire_label = wire_label
452
+ self.left_fill = len(self.wire_label)
453
+ self.top_pad = " "
454
+ self.bot_pad = "─"
455
+ self.top_format = f"│{self.top_pad * self.left_fill} %s │"
456
+ self.mid_format = f"╡{self.wire_label} %s ╞"
457
+ self.bot_format = "└─" + "s".center(self.left_fill + 1, "─") + "─┘"
458
+ self.bot_format = self.bot_format.replace("s", "%s")
459
+ bot_connect = bot_connect if bot_connect else "─"
460
+ self.bot_connect = bot_connect
461
+
462
+ self.mid_content = self.top_connect = ""
463
+ if input_length <= 2:
464
+ self.top_connect = label
465
+
466
+
467
+ class DirectOnQuWire(DrawElement):
468
+ """
469
+ Element to the wire (without the box).
470
+ """
471
+
472
+ def __init__(self, label=""):
473
+ super().__init__(label)
474
+ self.top_format = " %s "
475
+ self.mid_format = "─%s─"
476
+ self.bot_format = " %s "
477
+ self._mid_padding = self.mid_bck = "─"
478
+ self.top_connector = {"│": "│", "║": "║"}
479
+ self.bot_connector = {"│": "│", "║": "║"}
480
+
481
+
482
+ class Barrier(DirectOnQuWire):
483
+ """Draws a barrier with a label at the top if there is one.
484
+
485
+ ::
486
+
487
+ top: ░ label
488
+ mid: ─░─ ───░───
489
+ bot: ░ ░
490
+ """
491
+
492
+ def __init__(self, label=""):
493
+ super().__init__("░")
494
+ self.top_connect = label if label else "░"
495
+ self.bot_connect = "░"
496
+ self.top_connector = {}
497
+ self.bot_connector = {}
498
+
499
+
500
+ class Ex(DirectOnQuWire):
501
+ """Draws an X (usually with a connector). E.g. the top part of a swap gate.
502
+
503
+ ::
504
+
505
+ top:
506
+ mid: ─X─ ───X───
507
+ bot: │ │
508
+ """
509
+
510
+ def __init__(self, bot_connect=" ", top_connect=" ", conditional=False):
511
+ super().__init__("X")
512
+ self.bot_connect = "║" if conditional else bot_connect
513
+ self.top_connect = top_connect
514
+
515
+
516
+ class ResetDisplay(DirectOnQuWire):
517
+ """Draws a reset gate"""
518
+
519
+ def __init__(self, conditional=False):
520
+ super().__init__("|0>")
521
+ if conditional:
522
+ self.bot_connect = "║"
523
+
524
+
525
+ class Bullet(DirectOnQuWire):
526
+ """Draws a bullet (usually with a connector). E.g. the top part of a CX gate.
527
+
528
+ ::
529
+
530
+ top:
531
+ mid: ─■─ ───■───
532
+ bot: │ │
533
+ """
534
+
535
+ def __init__(self, top_connect="", bot_connect="", conditional=False, label=None, bottom=False):
536
+ super().__init__("■")
537
+ self.conditional = conditional
538
+ self.top_connect = top_connect
539
+ self.bot_connect = "║" if conditional else bot_connect
540
+ if label and bottom:
541
+ self.bot_connect = label
542
+ elif label:
543
+ self.top_connect = label
544
+ self.mid_bck = "─"
545
+
546
+
547
+ class OpenBullet(DirectOnQuWire):
548
+ """Draws an open bullet (usually with a connector). E.g. the top part of a CX gate.
549
+
550
+ ::
551
+
552
+ top:
553
+ mid: ─o─ ───o───
554
+ bot: │ │
555
+ """
556
+
557
+ def __init__(self, top_connect="", bot_connect="", conditional=False, label=None, bottom=False):
558
+ super().__init__("o")
559
+ self.conditional = conditional
560
+ self.top_connect = top_connect
561
+ self.bot_connect = "║" if conditional else bot_connect
562
+ if label and bottom:
563
+ self.bot_connect = label
564
+ elif label:
565
+ self.top_connect = label
566
+ self.mid_bck = "─"
567
+
568
+
569
+ class DirectOnClWire(DrawElement):
570
+ """
571
+ Element to the classical wire (without the box).
572
+ """
573
+
574
+ def __init__(self, label=""):
575
+ super().__init__(label)
576
+ self.top_format = " %s "
577
+ self.mid_format = "═%s═"
578
+ self.bot_format = " %s "
579
+ self._mid_padding = self.mid_bck = "═"
580
+ self.top_connector = {"│": "│", "║": "║"}
581
+ self.bot_connector = {"│": "│", "║": "║"}
582
+
583
+
584
+ class ClBullet(DirectOnClWire):
585
+ """Draws a bullet on classical wire (usually with a connector). E.g. the top part of a CX gate.
586
+
587
+ ::
588
+
589
+ top:
590
+ mid: ═■═ ═══■═══
591
+ bot: │ │
592
+ """
593
+
594
+ def __init__(self, top_connect="", bot_connect="", conditional=False, label=None, bottom=False):
595
+ super().__init__("■")
596
+ self.top_connect = top_connect
597
+ self.bot_connect = "║" if conditional else bot_connect
598
+ if label and bottom:
599
+ self.bot_connect = label
600
+ elif label:
601
+ self.top_connect = label
602
+ self.mid_bck = "═"
603
+
604
+
605
+ class ClOpenBullet(DirectOnClWire):
606
+ """Draws an open bullet on classical wire (usually with a connector). E.g. the top part of a CX gate.
607
+
608
+ ::
609
+
610
+ top:
611
+ mid: ═o═ ═══o═══
612
+ bot: │ │
613
+ """
614
+
615
+ def __init__(self, top_connect="", bot_connect="", conditional=False, label=None, bottom=False):
616
+ super().__init__("o")
617
+ self.top_connect = top_connect
618
+ self.bot_connect = "║" if conditional else bot_connect
619
+ if label and bottom:
620
+ self.bot_connect = label
621
+ elif label:
622
+ self.top_connect = label
623
+ self.mid_bck = "═"
624
+
625
+
626
+ class EmptyWire(DrawElement):
627
+ """This element is just the wire, with no operations."""
628
+
629
+ def __init__(self, wire):
630
+ super().__init__(wire)
631
+ self._mid_padding = self.mid_bck = wire
632
+
633
+ @staticmethod
634
+ def fillup_layer(layer, first_clbit):
635
+ """Given a layer, replace the Nones in it with EmptyWire elements.
636
+
637
+ Args:
638
+ layer (list): The layer that contains Nones.
639
+ first_clbit (int): The first wire that is classic.
640
+
641
+ Returns:
642
+ list: The new layer, with no Nones.
643
+ """
644
+ for nones in [i for i, x in enumerate(layer) if x is None]:
645
+ layer[nones] = EmptyWire("═") if nones >= first_clbit else EmptyWire("─")
646
+ return layer
647
+
648
+
649
+ class BreakWire(DrawElement):
650
+ """This element is used to break the drawing in several pages."""
651
+
652
+ def __init__(self, arrow_char):
653
+ super().__init__()
654
+ self.top_format = self.mid_format = self.bot_format = "%s"
655
+ self.top_connect = arrow_char
656
+ self.mid_content = arrow_char
657
+ self.bot_connect = arrow_char
658
+
659
+ @staticmethod
660
+ def fillup_layer(layer_length, arrow_char):
661
+ """Creates a layer with BreakWire elements.
662
+
663
+ Args:
664
+ layer_length (int): The length of the layer to create
665
+ arrow_char (char): The char used to create the BreakWire element.
666
+
667
+ Returns:
668
+ list: The new layer.
669
+ """
670
+ breakwire_layer = []
671
+ for _ in range(layer_length):
672
+ breakwire_layer.append(BreakWire(arrow_char))
673
+ return breakwire_layer
674
+
675
+
676
+ class InputWire(DrawElement):
677
+ """This element is the label and the initial value of a wire."""
678
+
679
+ def __init__(self, label):
680
+ super().__init__(label)
681
+
682
+ @staticmethod
683
+ def fillup_layer(names):
684
+ """Creates a layer with InputWire elements.
685
+
686
+ Args:
687
+ names (list): List of names for the wires.
688
+
689
+ Returns:
690
+ list: The new layer
691
+ """
692
+ longest = max(len(name) for name in names)
693
+ inputs_wires = []
694
+ for name in names:
695
+ inputs_wires.append(InputWire(name.rjust(longest)))
696
+ return inputs_wires
697
+
698
+
699
+ class TextDrawing:
700
+ """The text drawing"""
701
+
702
+ def __init__(
703
+ self,
704
+ qubits,
705
+ clbits,
706
+ nodes,
707
+ circuit,
708
+ reverse_bits=False,
709
+ plotbarriers=True,
710
+ line_length=None,
711
+ vertical_compression="high",
712
+ initial_state=True,
713
+ cregbundle=None,
714
+ encoding=None,
715
+ with_layout=False,
716
+ expr_len=30,
717
+ ):
718
+ self.qubits = qubits
719
+ self.clbits = clbits
720
+ self.nodes = nodes
721
+ self._circuit = circuit
722
+ if with_layout:
723
+ if self._circuit._layout:
724
+ self.layout = self._circuit._layout.initial_layout
725
+ else:
726
+ self.layout = None
727
+ else:
728
+ self.layout = None
729
+
730
+ self.initial_state = initial_state
731
+ self.global_phase = circuit.global_phase
732
+ self.plotbarriers = plotbarriers
733
+ self.reverse_bits = reverse_bits
734
+ self.line_length = line_length
735
+ self.expr_len = expr_len
736
+ if vertical_compression not in ["high", "medium", "low"]:
737
+ raise ValueError("Vertical compression can only be 'high', 'medium', or 'low'")
738
+ self.vertical_compression = vertical_compression
739
+ self._wire_map = {}
740
+ self.cregbundle = cregbundle
741
+
742
+ self.encoding = encoding or sys.stdout.encoding or "utf8"
743
+
744
+ self._nest_depth = 0 # nesting depth for control flow ops
745
+ self._expr_text = "" # expression text to display
746
+
747
+ # Because jupyter calls both __repr__ and __repr_html__ for some backends,
748
+ # the entire drawer can be run twice which can result in different output
749
+ # for different backends. This var caches the output so the drawer only runs once.
750
+ self._single_string = ""
751
+
752
+ def __str__(self):
753
+ return self.single_string()
754
+
755
+ def _repr_html_(self):
756
+ return (
757
+ '<pre style="word-wrap: normal;'
758
+ "white-space: pre;"
759
+ "background: #fff0;"
760
+ "line-height: 1.1;"
761
+ 'font-family: &quot;Courier New&quot;,Courier,monospace">'
762
+ f"{self.single_string()}</pre>"
763
+ )
764
+
765
+ def __repr__(self):
766
+ return self.single_string()
767
+
768
+ def single_string(self):
769
+ """Creates a long string with the ascii art.
770
+ Returns:
771
+ str: The lines joined by a newline (``\\n``)
772
+ """
773
+ # Because jupyter calls both __repr__ and __repr_html__, this prevents the code
774
+ # from running twice.
775
+ if self._single_string:
776
+ return self._single_string
777
+ try:
778
+ self._single_string = (
779
+ "\n".join(self.lines()).encode(self.encoding).decode(self.encoding)
780
+ )
781
+ except (UnicodeEncodeError, UnicodeDecodeError):
782
+ warn(
783
+ f"The encoding {self.encoding} has a limited charset."
784
+ " Consider a different encoding in your "
785
+ "environment. UTF-8 is being used instead",
786
+ RuntimeWarning,
787
+ )
788
+ self.encoding = "utf-8"
789
+ self._single_string = (
790
+ "\n".join(self.lines()).encode(self.encoding).decode(self.encoding)
791
+ )
792
+ return self._single_string
793
+
794
+ def dump(self, filename, encoding=None):
795
+ """Dumps the ascii art in the file.
796
+
797
+ Args:
798
+ filename (str): File to dump the ascii art.
799
+ encoding (str): Optional. Force encoding, instead of self.encoding.
800
+ """
801
+ with open(filename, mode="w", encoding=encoding or self.encoding) as text_file:
802
+ text_file.write(self.single_string())
803
+
804
+ def lines(self, line_length=None):
805
+ """Generates a list with lines. These lines form the text drawing.
806
+
807
+ Args:
808
+ line_length (int): Optional. Breaks the circuit drawing to this length. This is
809
+ useful when the drawing does not fit in the console. If
810
+ None (default), it will try to guess the console width using
811
+ shutil.get_terminal_size(). If you don't want pagination
812
+ at all, set line_length=-1.
813
+
814
+ Returns:
815
+ list: A list of lines with the text drawing.
816
+ """
817
+ if line_length is None:
818
+ line_length = self.line_length
819
+ if not line_length:
820
+ if ("ipykernel" in sys.modules) and ("spyder" not in sys.modules):
821
+ line_length = 80
822
+ else:
823
+ line_length, _ = get_terminal_size()
824
+
825
+ noqubits = len(self.qubits)
826
+
827
+ layers = self.build_layers()
828
+ layer_groups = [[]]
829
+ rest_of_the_line = line_length
830
+ for layerno, layer in enumerate(layers):
831
+ # Replace the Nones with EmptyWire
832
+ layers[layerno] = EmptyWire.fillup_layer(layer, noqubits)
833
+
834
+ TextDrawing.normalize_width(layer)
835
+
836
+ if line_length == -1:
837
+ # Do not use pagination (aka line breaking. aka ignore line_length).
838
+ layer_groups[-1].append(layer)
839
+ continue
840
+
841
+ # chop the layer to the line_length (pager)
842
+ layer_length = layers[layerno][0].length
843
+
844
+ if layer_length < rest_of_the_line:
845
+ layer_groups[-1].append(layer)
846
+ rest_of_the_line -= layer_length
847
+ else:
848
+ layer_groups[-1].append(BreakWire.fillup_layer(len(layer), "»"))
849
+
850
+ # New group
851
+ layer_groups.append([BreakWire.fillup_layer(len(layer), "«")])
852
+ rest_of_the_line = line_length - layer_groups[-1][-1][0].length
853
+
854
+ layer_groups[-1].append(
855
+ InputWire.fillup_layer(self.wire_names(with_initial_state=False))
856
+ )
857
+ rest_of_the_line -= layer_groups[-1][-1][0].length
858
+
859
+ layer_groups[-1].append(layer)
860
+ rest_of_the_line -= layer_groups[-1][-1][0].length
861
+
862
+ lines = []
863
+
864
+ if self.global_phase:
865
+ lines.append(f"global phase: {pi_check(self.global_phase, ndigits=5)}")
866
+
867
+ for layer_group in layer_groups:
868
+ wires = list(zip(*layer_group))
869
+ lines += self.draw_wires(wires)
870
+
871
+ return lines
872
+
873
+ def wire_names(self, with_initial_state=False):
874
+ """Returns a list of names for each wire.
875
+
876
+ Args:
877
+ with_initial_state (bool): Optional (Default: False). If true, adds
878
+ the initial value to the name.
879
+
880
+ Returns:
881
+ List: The list of wire names.
882
+ """
883
+ if with_initial_state:
884
+ initial_qubit_value = "|0>"
885
+ initial_clbit_value = "0 "
886
+ else:
887
+ initial_qubit_value = ""
888
+ initial_clbit_value = ""
889
+
890
+ self._wire_map = get_wire_map(self._circuit, (self.qubits + self.clbits), self.cregbundle)
891
+ wire_labels = []
892
+ for wire, index in self._wire_map.items():
893
+ if isinstance(wire, ClassicalRegister):
894
+ register = wire
895
+ else:
896
+ register, bit_index, reg_index = get_bit_reg_index(self._circuit, wire)
897
+ index = bit_index if register is None else reg_index
898
+
899
+ wire_label = get_wire_label(
900
+ "text", register, index, layout=self.layout, cregbundle=self.cregbundle
901
+ )
902
+ wire_label += " " if self.layout is not None and isinstance(wire, Qubit) else ": "
903
+
904
+ cregb_add = ""
905
+ if isinstance(wire, Qubit):
906
+ initial_bit_value = initial_qubit_value
907
+ else:
908
+ initial_bit_value = initial_clbit_value
909
+ if self.cregbundle and register is not None:
910
+ cregb_add = str(register.size) + "/"
911
+ wire_labels.append(wire_label + initial_bit_value + cregb_add)
912
+
913
+ return wire_labels
914
+
915
+ def should_compress(self, top_line, bot_line):
916
+ """Decides if the top_line and bot_line should be merged,
917
+ based on `self.vertical_compression`."""
918
+ if self.vertical_compression == "high":
919
+ return True
920
+ if self.vertical_compression == "low":
921
+ return False
922
+ for top, bot in zip(top_line, bot_line):
923
+ if top in ["┴", "╨"] and bot in ["┬", "╥"]:
924
+ return False
925
+ if (top.isalnum() and bot != " ") or (bot.isalnum() and top != " "):
926
+ return False
927
+ return True
928
+
929
+ def draw_wires(self, wires):
930
+ """Given a list of wires, creates a list of lines with the text drawing.
931
+
932
+ Args:
933
+ wires (list): A list of wires with nodes.
934
+ Returns:
935
+ list: A list of lines with the text drawing.
936
+ """
937
+ lines = []
938
+ bot_line = None
939
+ for wire in wires:
940
+ # TOP
941
+ top_line = ""
942
+ for node in wire:
943
+ top_line += node.top
944
+
945
+ if bot_line is None:
946
+ lines.append(top_line)
947
+ else:
948
+ if self.should_compress(top_line, bot_line):
949
+ lines.append(TextDrawing.merge_lines(lines.pop(), top_line))
950
+ else:
951
+ lines.append(TextDrawing.merge_lines(lines[-1], top_line, icod="bot"))
952
+
953
+ # MID
954
+ mid_line = ""
955
+ for node in wire:
956
+ mid_line += node.mid
957
+ lines.append(TextDrawing.merge_lines(lines[-1], mid_line, icod="bot"))
958
+
959
+ # BOT
960
+ bot_line = ""
961
+ for node in wire:
962
+ bot_line += node.bot
963
+ lines.append(TextDrawing.merge_lines(lines[-1], bot_line, icod="bot"))
964
+
965
+ return lines
966
+
967
+ @staticmethod
968
+ def special_label(node):
969
+ """Some instructions have special labels"""
970
+ labels = {IGate: "I", SXGate: "√X", SXdgGate: "√Xdg"}
971
+ node_type = getattr(node, "base_class", None)
972
+ return labels.get(node_type, None)
973
+
974
+ @staticmethod
975
+ def merge_lines(top, bot, icod="top"):
976
+ """Merges two lines (top and bot) in a way that the overlapping makes sense.
977
+
978
+ Args:
979
+ top (str): the top line
980
+ bot (str): the bottom line
981
+ icod (top or bot): in case of doubt, which line should have priority? Default: "top".
982
+ Returns:
983
+ str: The merge of both lines.
984
+ """
985
+ ret = ""
986
+ for topc, botc in zip(top, bot):
987
+ if topc == botc:
988
+ ret += topc
989
+ elif topc in "┼╪" and botc == " ":
990
+ ret += "│"
991
+ elif topc == " ":
992
+ ret += botc
993
+ elif topc in "┬╥" and botc in " ║│" and icod == "top":
994
+ ret += topc
995
+ elif topc in "┬" and botc == " " and icod == "bot":
996
+ ret += "│"
997
+ elif topc in "╥" and botc == " " and icod == "bot":
998
+ ret += "║"
999
+ elif topc in "┬│" and botc == "═":
1000
+ ret += "╪"
1001
+ elif topc in "┬│" and botc == "─":
1002
+ ret += "┼"
1003
+ elif topc in "└┘║│░" and botc == " " and icod == "top":
1004
+ ret += topc
1005
+ elif topc in "─═" and botc == " " and icod == "top":
1006
+ ret += topc
1007
+ elif topc in "─═" and botc == " " and icod == "bot":
1008
+ ret += botc
1009
+ elif topc in "║╥" and botc in "═":
1010
+ ret += "╬"
1011
+ elif topc in "║╥" and botc in "─":
1012
+ ret += "╫"
1013
+ elif topc in "║╫╬" and botc in " ":
1014
+ ret += "║"
1015
+ elif topc in "│┼╪" and botc in " ":
1016
+ ret += "│"
1017
+ elif topc == "└" and botc == "┌" and icod == "top":
1018
+ ret += "├"
1019
+ elif topc == "┘" and botc == "┐" and icod == "top":
1020
+ ret += "┤"
1021
+ elif botc in "┐┌" and icod == "top":
1022
+ ret += "┬"
1023
+ elif topc in "┘└" and botc in "─" and icod == "top":
1024
+ ret += "┴"
1025
+ elif botc == " " and icod == "top":
1026
+ ret += topc
1027
+ else:
1028
+ ret += botc
1029
+ return ret
1030
+
1031
+ @staticmethod
1032
+ def normalize_width(layer):
1033
+ """
1034
+ When the elements of the layer have different widths, sets the width to the max elements.
1035
+
1036
+ Args:
1037
+ layer (list): A list of elements.
1038
+ """
1039
+ nodes = list(filter(lambda x: x is not None, layer))
1040
+ longest = max(node.length for node in nodes)
1041
+ for node in nodes:
1042
+ node.layer_width = longest
1043
+
1044
+ @staticmethod
1045
+ def controlled_wires(node, wire_map, ctrl_text, conditional, mod_control):
1046
+ """
1047
+ Analyzes the node in the layer and checks if the controlled arguments are in
1048
+ the box or out of the box.
1049
+
1050
+ Args:
1051
+ node (DAGNode): node to analyse
1052
+ wire_map (dict): map of qubits/clbits to position
1053
+ ctrl_text (str): text for a control label
1054
+ conditional (bool): is this a node with a condition
1055
+ mod_control (ControlModifier): an instance of a modifier for an
1056
+ AnnotatedOperation
1057
+
1058
+ Returns:
1059
+ Tuple(list, list, list):
1060
+ - tuple: controlled arguments on top of the "node box", and its status
1061
+ - tuple: controlled arguments on bottom of the "node box", and its status
1062
+ - tuple: controlled arguments in the "node box", and its status
1063
+ - the rest of the arguments
1064
+ """
1065
+ op = node.op
1066
+ num_ctrl_qubits = mod_control.num_ctrl_qubits if mod_control else op.num_ctrl_qubits
1067
+ ctrl_qubits = node.qargs[:num_ctrl_qubits]
1068
+ args_qubits = node.qargs[num_ctrl_qubits:]
1069
+ ctrl_state = mod_control.ctrl_state if mod_control else op.ctrl_state
1070
+ ctrl_state = f"{ctrl_state:b}".rjust(num_ctrl_qubits, "0")[::-1]
1071
+
1072
+ in_box = []
1073
+ top_box = []
1074
+ bot_box = []
1075
+
1076
+ qubit_indices = sorted(wire_map[x] for x in wire_map if x in args_qubits)
1077
+
1078
+ for ctrl_qubit in zip(ctrl_qubits, ctrl_state):
1079
+ if min(qubit_indices) > wire_map[ctrl_qubit[0]]:
1080
+ top_box.append(ctrl_qubit)
1081
+ elif max(qubit_indices) < wire_map[ctrl_qubit[0]]:
1082
+ bot_box.append(ctrl_qubit)
1083
+ else:
1084
+ in_box.append(ctrl_qubit)
1085
+
1086
+ gates = []
1087
+ for i in range(len(ctrl_qubits)):
1088
+ # For sidetext gate alignment, need to set every Bullet with
1089
+ # conditional on if there's a condition.
1090
+ if getattr(op, "condition", None) is not None:
1091
+ conditional = True
1092
+ if ctrl_state[i] == "1":
1093
+ gates.append(Bullet(conditional=conditional, label=ctrl_text, bottom=bool(bot_box)))
1094
+ else:
1095
+ gates.append(
1096
+ OpenBullet(conditional=conditional, label=ctrl_text, bottom=bool(bot_box))
1097
+ )
1098
+ return (gates, top_box, bot_box, in_box, args_qubits)
1099
+
1100
+ def _node_to_gate(self, node, layer, gate_wire_map):
1101
+ """Convert a dag op node into its corresponding Gate object, and establish
1102
+ any connections it introduces between qubits. gate_wire_map is the flow_wire_map
1103
+ if gate is inside a ControlFlowOp, else it's self._wire_map"""
1104
+ op = node.op
1105
+ current_cons = []
1106
+ current_cons_cond = []
1107
+ connection_label = None
1108
+ conditional = False
1109
+ base_gate = getattr(op, "base_gate", None)
1110
+
1111
+ params = get_param_str(op, "text", ndigits=5)
1112
+ if not isinstance(op, (Measure, SwapGate, Reset)) and not getattr(op, "_directive", False):
1113
+ gate_text, ctrl_text, _ = get_gate_ctrl_text(op, "text")
1114
+ gate_text = TextDrawing.special_label(op) or gate_text
1115
+ gate_text = gate_text + params
1116
+
1117
+ if getattr(op, "condition", None) is not None:
1118
+ # conditional
1119
+ current_cons_cond += layer.set_cl_multibox(op.condition, gate_wire_map, top_connect="╨")
1120
+ conditional = True
1121
+
1122
+ # add in a gate that operates over multiple qubits
1123
+ def add_connected_gate(node, gates, layer, current_cons, gate_wire_map):
1124
+ for i, gate in enumerate(gates):
1125
+ actual_index = gate_wire_map[node.qargs[i]]
1126
+ if actual_index not in [i for i, j in current_cons]:
1127
+ layer.set_qubit(node.qargs[i], gate)
1128
+ current_cons.append((actual_index, gate))
1129
+
1130
+ # AnnotatedOperation with ControlModifier
1131
+ mod_control = None
1132
+ if getattr(op, "modifiers", None):
1133
+ canonical_modifiers = _canonicalize_modifiers(op.modifiers)
1134
+ for modifier in canonical_modifiers:
1135
+ if isinstance(modifier, ControlModifier):
1136
+ mod_control = modifier
1137
+ break
1138
+
1139
+ if isinstance(op, Measure):
1140
+ gate = MeasureFrom()
1141
+ layer.set_qubit(node.qargs[0], gate)
1142
+ register, _, reg_index = get_bit_reg_index(self._circuit, node.cargs[0])
1143
+ if self.cregbundle and register is not None:
1144
+ layer.set_clbit(
1145
+ node.cargs[0],
1146
+ MeasureTo(str(reg_index)),
1147
+ )
1148
+ else:
1149
+ layer.set_clbit(node.cargs[0], MeasureTo())
1150
+
1151
+ elif getattr(op, "_directive", False):
1152
+ # barrier
1153
+ if not self.plotbarriers:
1154
+ return layer, current_cons, current_cons_cond, connection_label
1155
+
1156
+ top_qubit = min(node.qargs, key=lambda q: self._wire_map.get(q, float("inf")))
1157
+ for qubit in node.qargs:
1158
+ if qubit in self.qubits:
1159
+ label = op.label if qubit == top_qubit else ""
1160
+ layer.set_qubit(qubit, Barrier(label))
1161
+
1162
+ elif isinstance(op, SwapGate):
1163
+ # swap
1164
+ gates = [Ex(conditional=conditional) for _ in range(len(node.qargs))]
1165
+ add_connected_gate(node, gates, layer, current_cons, gate_wire_map)
1166
+
1167
+ elif isinstance(op, Reset):
1168
+ # reset
1169
+ layer.set_qubit(node.qargs[0], ResetDisplay(conditional=conditional))
1170
+
1171
+ elif isinstance(op, RZZGate):
1172
+ # rzz
1173
+ connection_label = f"ZZ{params}"
1174
+ gates = [Bullet(conditional=conditional), Bullet(conditional=conditional)]
1175
+ add_connected_gate(node, gates, layer, current_cons, gate_wire_map)
1176
+
1177
+ elif len(node.qargs) == 1 and not node.cargs:
1178
+ # unitary gate
1179
+ layer.set_qubit(node.qargs[0], BoxOnQuWire(gate_text, conditional=conditional))
1180
+
1181
+ elif isinstance(op, ControlledGate) or mod_control:
1182
+ controls_array = TextDrawing.controlled_wires(
1183
+ node, gate_wire_map, ctrl_text, conditional, mod_control
1184
+ )
1185
+ gates, controlled_top, controlled_bot, controlled_edge, rest = controls_array
1186
+ if mod_control:
1187
+ if len(rest) == 1:
1188
+ gates.append(BoxOnQuWire(gate_text, conditional=conditional))
1189
+ else:
1190
+ top_connect = "┴" if controlled_top else None
1191
+ bot_connect = "┬" if controlled_bot else None
1192
+ indexes = layer.set_qu_multibox(
1193
+ rest,
1194
+ gate_text,
1195
+ conditional=conditional,
1196
+ controlled_edge=controlled_edge,
1197
+ top_connect=top_connect,
1198
+ bot_connect=bot_connect,
1199
+ )
1200
+ for index in range(min(indexes), max(indexes) + 1):
1201
+ # Dummy element to connect the multibox with the bullets
1202
+ current_cons.append((index, DrawElement("")))
1203
+ elif base_gate.name == "z":
1204
+ # cz
1205
+ gates.append(Bullet(conditional=conditional))
1206
+ elif base_gate.name in ["u1", "p"]:
1207
+ # cu1
1208
+ connection_label = f"{base_gate.name.upper()}{params}"
1209
+ gates.append(Bullet(conditional=conditional))
1210
+ elif base_gate.name == "swap":
1211
+ # cswap
1212
+ gates += [Ex(conditional=conditional), Ex(conditional=conditional)]
1213
+ add_connected_gate(node, gates, layer, current_cons, gate_wire_map)
1214
+ elif base_gate.name == "rzz":
1215
+ # crzz
1216
+ connection_label = f"ZZ{params}"
1217
+ gates += [Bullet(conditional=conditional), Bullet(conditional=conditional)]
1218
+ elif len(rest) > 1:
1219
+ top_connect = "┴" if controlled_top else None
1220
+ bot_connect = "┬" if controlled_bot else None
1221
+ indexes = layer.set_qu_multibox(
1222
+ rest,
1223
+ gate_text,
1224
+ conditional=conditional,
1225
+ controlled_edge=controlled_edge,
1226
+ top_connect=top_connect,
1227
+ bot_connect=bot_connect,
1228
+ )
1229
+ for index in range(min(indexes), max(indexes) + 1):
1230
+ # Dummy element to connect the multibox with the bullets
1231
+ current_cons.append((index, DrawElement("")))
1232
+ else:
1233
+ gates.append(BoxOnQuWire(gate_text, conditional=conditional))
1234
+
1235
+ add_connected_gate(node, gates, layer, current_cons, gate_wire_map)
1236
+
1237
+ elif len(node.qargs) >= 2 and not node.cargs:
1238
+ layer.set_qu_multibox(node.qargs, gate_text, conditional=conditional)
1239
+
1240
+ elif node.qargs and node.cargs:
1241
+ layer._set_multibox(
1242
+ gate_text,
1243
+ qargs=node.qargs,
1244
+ cargs=node.cargs,
1245
+ conditional=conditional,
1246
+ )
1247
+ else:
1248
+ raise VisualizationError(
1249
+ "Text visualizer does not know how to handle this node: ", op.name
1250
+ )
1251
+
1252
+ # sort into the order they were declared in, to ensure that connected boxes have
1253
+ # lines in the right direction
1254
+ current_cons.sort(key=lambda tup: tup[0])
1255
+ current_cons = [g for q, g in current_cons]
1256
+ current_cons_cond.sort(key=lambda tup: tup[0])
1257
+ current_cons_cond = [g for c, g in current_cons_cond]
1258
+
1259
+ return layer, current_cons, current_cons_cond, connection_label
1260
+
1261
+ def build_layers(self):
1262
+ """
1263
+ Constructs layers.
1264
+ Returns:
1265
+ list: List of DrawElements.
1266
+ Raises:
1267
+ VisualizationError: When the drawing is, for some reason, impossible to be drawn.
1268
+ """
1269
+ wire_names = self.wire_names(with_initial_state=self.initial_state)
1270
+ if not wire_names:
1271
+ return []
1272
+
1273
+ layers = [InputWire.fillup_layer(wire_names)]
1274
+
1275
+ for node_layer in self.nodes:
1276
+ layer = Layer(
1277
+ self.qubits,
1278
+ self.clbits,
1279
+ self.cregbundle,
1280
+ self._circuit,
1281
+ self._wire_map,
1282
+ )
1283
+ for node in node_layer:
1284
+ if isinstance(node.op, ControlFlowOp):
1285
+ self._nest_depth = 0
1286
+ self.add_control_flow(node, layers, self._wire_map)
1287
+ else:
1288
+ layer, current_cons, current_cons_cond, connection_label = self._node_to_gate(
1289
+ node, layer, self._wire_map
1290
+ )
1291
+ layer.connections.append((connection_label, current_cons))
1292
+ layer.connections.append((None, current_cons_cond))
1293
+ layer.connect_with("│")
1294
+ layers.append(layer.full_layer)
1295
+
1296
+ return layers
1297
+
1298
+ def add_control_flow(self, node, layers, wire_map):
1299
+ """Add control flow ops to the circuit drawing."""
1300
+
1301
+ if (isinstance(node.op, SwitchCaseOp) and isinstance(node.op.target, expr.Expr)) or (
1302
+ getattr(node.op, "condition", None) and isinstance(node.op.condition, expr.Expr)
1303
+ ):
1304
+
1305
+ def lookup_var(var):
1306
+ """Look up a classical-expression variable or register/bit in our internal symbol
1307
+ table, and return an OQ3-like identifier."""
1308
+ # We don't attempt to disambiguate anything like register/var naming collisions; we
1309
+ # already don't really show classical variables.
1310
+ if isinstance(var, expr.Var):
1311
+ return ast.Identifier(var.name)
1312
+ if isinstance(var, ClassicalRegister):
1313
+ return ast.Identifier(var.name)
1314
+ # Single clbit. This is not actually the correct way to lookup a bit on the
1315
+ # circuit (it doesn't handle bit bindings fully), but the text drawer doesn't
1316
+ # completely track inner-outer _bit_ bindings, only inner-indices, so we can't fully
1317
+ # recover the information losslessly. Since most control-flow uses the control-flow
1318
+ # builders, we should decay to something usable most of the time.
1319
+ try:
1320
+ register, bit_index, reg_index = get_bit_reg_index(self._circuit, var)
1321
+ except CircuitError:
1322
+ # We failed to find the bit due to binding problems - fall back to something
1323
+ # that's probably wrong, but at least disambiguating.
1324
+ return ast.Identifier(f"_bit{wire_map[var]}")
1325
+ if register is None:
1326
+ return ast.Identifier(f"_bit{bit_index}")
1327
+ return ast.SubscriptedIdentifier(register.name, ast.IntegerLiteral(reg_index))
1328
+
1329
+ condition = node.op.target if isinstance(node.op, SwitchCaseOp) else node.op.condition
1330
+ draw_conditional = bool(node_resources(condition).clbits)
1331
+ stream = StringIO()
1332
+ BasicPrinter(stream, indent=" ").visit(condition.accept(_ExprBuilder(lookup_var)))
1333
+ self._expr_text = stream.getvalue()
1334
+ # Truncate expr_text at 30 chars or user-set expr_len
1335
+ if len(self._expr_text) > self.expr_len:
1336
+ self._expr_text = self._expr_text[: self.expr_len] + "..."
1337
+ else:
1338
+ draw_conditional = isinstance(node.op, (IfElseOp, WhileLoopOp, SwitchCaseOp))
1339
+
1340
+ # # Draw a left box such as If, While, For, and Switch
1341
+ flow_layer = self.draw_flow_box(node, wire_map, CF_LEFT, conditional=draw_conditional)
1342
+ layers.append(flow_layer.full_layer)
1343
+
1344
+ # Get the list of circuits in the ControlFlowOp from the node blocks
1345
+ circuit_list = list(node.op.blocks)
1346
+
1347
+ if isinstance(node.op, SwitchCaseOp):
1348
+ # Create an empty circuit at the head of the circuit_list if a Switch box
1349
+ circuit_list.insert(0, list(node.op.cases_specifier())[0][1].copy_empty_like())
1350
+
1351
+ for circ_num, circuit in enumerate(circuit_list):
1352
+ # Update the wire_map with the qubits and clbits from the inner circuit
1353
+ flow_wire_map = wire_map.copy()
1354
+ flow_wire_map.update(
1355
+ {inner: wire_map[outer] for outer, inner in zip(node.qargs, circuit.qubits)}
1356
+ )
1357
+ for outer, inner in zip(node.cargs, circuit.clbits):
1358
+ if self.cregbundle and (
1359
+ (in_reg := get_bit_register(self._circuit, inner)) is not None
1360
+ ):
1361
+ out_reg = get_bit_register(self._circuit, outer)
1362
+ flow_wire_map.update({in_reg: wire_map[out_reg]})
1363
+ else:
1364
+ flow_wire_map.update({inner: wire_map[outer]})
1365
+
1366
+ if circ_num > 0:
1367
+ # Draw a middle box such as Else and Case
1368
+ flow_layer = self.draw_flow_box(
1369
+ node, flow_wire_map, CF_MID, circ_num - 1, conditional=False
1370
+ )
1371
+ layers.append(flow_layer.full_layer)
1372
+
1373
+ _, _, nodes = _get_layered_instructions(circuit, wire_map=flow_wire_map)
1374
+ for layer_nodes in nodes:
1375
+ # Limit qubits sent to only ones from main circuit, so qubit_layer is correct length
1376
+ flow_layer2 = Layer(
1377
+ self.qubits, self.clbits, self.cregbundle, self._circuit, flow_wire_map
1378
+ )
1379
+ for layer_node in layer_nodes:
1380
+ if isinstance(layer_node.op, ControlFlowOp):
1381
+ # Recurse on this function if nested ControlFlowOps
1382
+ self._nest_depth += 1
1383
+ self.add_control_flow(layer_node, layers, flow_wire_map)
1384
+ self._nest_depth -= 1
1385
+ else:
1386
+ (
1387
+ flow_layer2,
1388
+ current_cons,
1389
+ current_cons_cond,
1390
+ connection_label,
1391
+ ) = self._node_to_gate(layer_node, flow_layer2, flow_wire_map)
1392
+ flow_layer2.connections.append((connection_label, current_cons))
1393
+ flow_layer2.connections.append((None, current_cons_cond))
1394
+
1395
+ flow_layer2.connect_with("│")
1396
+ layers.append(flow_layer2.full_layer)
1397
+
1398
+ # Draw the right box for End
1399
+ flow_layer = self.draw_flow_box(node, wire_map, CF_RIGHT, conditional=False)
1400
+ layers.append(flow_layer.full_layer)
1401
+
1402
+ def draw_flow_box(self, node, flow_wire_map, section, circ_num=0, conditional=False):
1403
+ """Draw the left, middle, or right of a control flow box"""
1404
+
1405
+ op = node.op
1406
+ depth = str(self._nest_depth)
1407
+ if section == CF_LEFT:
1408
+ etext = ""
1409
+ if self._expr_text:
1410
+ etext = " " + self._expr_text
1411
+ if isinstance(op, IfElseOp):
1412
+ label = "If-" + depth + etext
1413
+ elif isinstance(op, WhileLoopOp):
1414
+ label = "While-" + depth + etext
1415
+ elif isinstance(op, ForLoopOp):
1416
+ indexset = op.params[0]
1417
+ # If tuple of values instead of range, cut it off at 4 items
1418
+ if "range" not in str(indexset) and len(indexset) > 4:
1419
+ index_str = str(indexset[:4])
1420
+ index_str = index_str[:-1] + ", ...)"
1421
+ else:
1422
+ index_str = str(indexset)
1423
+ label = "For-" + depth + " " + index_str
1424
+ elif isinstance(op, BoxOp):
1425
+ label = "Box-" + depth + etext
1426
+ elif isinstance(op, SwitchCaseOp):
1427
+ label = "Switch-" + depth + etext
1428
+ else:
1429
+ raise RuntimeError(f"unhandled control-flow operation: {node.name}")
1430
+ elif section == CF_MID:
1431
+ if isinstance(op, IfElseOp):
1432
+ label = "Else-" + depth
1433
+ else:
1434
+ jump_list = []
1435
+ for jump_values, _ in list(op.cases_specifier()):
1436
+ jump_list.append(jump_values)
1437
+
1438
+ if "default" in str(jump_list[circ_num][0]):
1439
+ jump_str = "default"
1440
+ else:
1441
+ jump_str = str(jump_list[circ_num]).replace(",)", ")")
1442
+ label = "Case-" + depth + " " + jump_str
1443
+
1444
+ else:
1445
+ label = "End-" + depth
1446
+
1447
+ flow_layer = Layer(
1448
+ self.qubits,
1449
+ self.clbits,
1450
+ self.cregbundle,
1451
+ self._circuit,
1452
+ flow_wire_map,
1453
+ )
1454
+ # If only 1 qubit, draw basic 1 qubit box
1455
+ if len(node.qargs) == 1:
1456
+ flow_layer.set_qubit(
1457
+ self.qubits[flow_wire_map[node.qargs[0]]],
1458
+ FlowOnQuWire(section, label=label, conditional=conditional),
1459
+ )
1460
+ else:
1461
+ # If multiple qubits, must use wire_map to handle wire_order changes.
1462
+ idx_list = [flow_wire_map[qarg] for qarg in node.qargs]
1463
+ min_idx = min(idx_list)
1464
+ max_idx = max(idx_list)
1465
+ box_height = max_idx - min_idx + 1
1466
+
1467
+ flow_layer.set_qubit(
1468
+ self.qubits[min_idx], FlowOnQuWireTop(section, label=label, wire_label="")
1469
+ )
1470
+ for order, i in enumerate(range(min_idx + 1, max_idx)):
1471
+ flow_layer.set_qubit(
1472
+ self.qubits[i],
1473
+ FlowOnQuWireMid(
1474
+ section,
1475
+ label=label,
1476
+ input_length=box_height,
1477
+ order=order,
1478
+ wire_label="",
1479
+ ),
1480
+ )
1481
+ flow_layer.set_qubit(
1482
+ self.qubits[max_idx],
1483
+ FlowOnQuWireBot(
1484
+ section,
1485
+ label=label,
1486
+ input_length=box_height,
1487
+ conditional=conditional,
1488
+ wire_label="",
1489
+ ),
1490
+ )
1491
+ if conditional:
1492
+ if isinstance(node.op, SwitchCaseOp):
1493
+ if isinstance(node.op.target, expr.Expr):
1494
+ condition = node.op.target
1495
+ elif isinstance(node.op.target, Clbit):
1496
+ condition = (node.op.target, 1)
1497
+ else:
1498
+ condition = (node.op.target, 2 ** (node.op.target.size) - 1)
1499
+ else:
1500
+ condition = node.op.condition
1501
+ _ = flow_layer.set_cl_multibox(condition, flow_wire_map, top_connect="╨")
1502
+
1503
+ return flow_layer
1504
+
1505
+
1506
+ class Layer:
1507
+ """A layer is the "column" of the circuit."""
1508
+
1509
+ def __init__(self, qubits, clbits, cregbundle, circuit, wire_map):
1510
+ self.qubits = qubits
1511
+ self._circuit = circuit
1512
+ if cregbundle:
1513
+ self.clbits = []
1514
+ previous_creg = None
1515
+ for bit in clbits:
1516
+ register = get_bit_register(self._circuit, bit)
1517
+ if previous_creg and previous_creg == register:
1518
+ continue
1519
+ if register is None:
1520
+ self.clbits.append(bit)
1521
+ else:
1522
+ previous_creg = register
1523
+ self.clbits.append(previous_creg)
1524
+ else:
1525
+ self.clbits = clbits
1526
+ self.qubit_layer = [None] * len(qubits)
1527
+ self.connections = []
1528
+ self.clbit_layer = [None] * len(clbits)
1529
+ self.cregbundle = cregbundle
1530
+ self._wire_map = wire_map
1531
+
1532
+ @property
1533
+ def full_layer(self):
1534
+ """
1535
+ Returns the composition of qubits and classic wires.
1536
+ Returns:
1537
+ String: self.qubit_layer + self.clbit_layer
1538
+ """
1539
+ return self.qubit_layer + self.clbit_layer
1540
+
1541
+ def set_qubit(self, qubit, element):
1542
+ """Sets the qubit to the element.
1543
+
1544
+ Args:
1545
+ qubit (qbit): Element of self.qubits.
1546
+ element (DrawElement): Element to set in the qubit
1547
+ """
1548
+ self.qubit_layer[self._wire_map[qubit]] = element
1549
+
1550
+ def set_clbit(self, clbit, element):
1551
+ """Sets the clbit to the element.
1552
+
1553
+ Args:
1554
+ clbit (cbit): Element of self.clbits.
1555
+ element (DrawElement): Element to set in the clbit
1556
+ """
1557
+ register = get_bit_register(self._circuit, clbit)
1558
+ if self.cregbundle and register is not None:
1559
+ self.clbit_layer[self._wire_map[register] - len(self.qubits)] = element
1560
+ else:
1561
+ self.clbit_layer[self._wire_map[clbit] - len(self.qubits)] = element
1562
+
1563
+ def _set_multibox(
1564
+ self,
1565
+ label,
1566
+ qargs=None,
1567
+ cargs=None,
1568
+ top_connect=None,
1569
+ bot_connect=None,
1570
+ conditional=False,
1571
+ controlled_edge=None,
1572
+ ):
1573
+ if qargs is not None and cargs is not None:
1574
+ qarg_indices = sorted(i for i, x in enumerate(self.qubits) if x in qargs)
1575
+ carg_indices = sorted(i for i, x in enumerate(self.clbits) if x in cargs)
1576
+
1577
+ # Further below, indices are used as wire labels. Here, get the length of
1578
+ # the longest label, and pad all labels with spaces to this length.
1579
+ wire_label_len = max(len(str(len(qargs) - 1)), len(str(len(cargs) - 1)))
1580
+ qargs_str = [
1581
+ str(qargs.index(qbit)).ljust(wire_label_len, " ")
1582
+ for qbit in self.qubits
1583
+ if qbit in qargs
1584
+ ]
1585
+ cargs_str = [
1586
+ str(cargs.index(cbit)).ljust(wire_label_len, " ")
1587
+ for cbit in self.clbits
1588
+ if cbit in cargs
1589
+ ]
1590
+
1591
+ qargs = sorted(qargs, key=self.qubits.index)
1592
+ cargs = sorted(cargs, key=self.clbits.index)
1593
+
1594
+ box_height = len(self.qubits) - min(qarg_indices) + max(carg_indices) + 1
1595
+
1596
+ self.set_qubit(qargs.pop(0), BoxOnQuWireTop(label, wire_label=qargs_str.pop(0)))
1597
+ order = 0
1598
+ for order, bit_i in enumerate(range(min(qarg_indices) + 1, len(self.qubits))):
1599
+ if bit_i in qarg_indices:
1600
+ named_bit = qargs.pop(0)
1601
+ wire_label = qargs_str.pop(0)
1602
+ else:
1603
+ named_bit = self.qubits[bit_i]
1604
+ wire_label = " " * wire_label_len
1605
+ self.set_qubit(
1606
+ named_bit, BoxOnQuWireMid(label, box_height, order, wire_label=wire_label)
1607
+ )
1608
+ for order, bit_i in enumerate(range(max(carg_indices)), order + 1):
1609
+ if bit_i in carg_indices:
1610
+ named_bit = cargs.pop(0)
1611
+ wire_label = cargs_str.pop(0)
1612
+ else:
1613
+ named_bit = self.clbits[bit_i]
1614
+ wire_label = " " * wire_label_len
1615
+ self.set_clbit(
1616
+ named_bit, BoxOnClWireMid(label, box_height, order, wire_label=wire_label)
1617
+ )
1618
+ self.set_clbit(
1619
+ cargs.pop(0), BoxOnClWireBot(label, box_height, wire_label=cargs_str.pop(0))
1620
+ )
1621
+ return carg_indices
1622
+
1623
+ if qargs is None and cargs is not None:
1624
+ bits = list(cargs)
1625
+ bit_indices = sorted(i for i, x in enumerate(self.clbits) if x in bits)
1626
+ wire_label_len = len(str(len(bits) - 1))
1627
+ bits.sort(key=self.clbits.index)
1628
+ qargs_str = [""] * len(bits)
1629
+ set_bit = self.set_clbit
1630
+ OnWire = BoxOnClWire
1631
+ OnWireTop = BoxOnClWireTop
1632
+ OnWireMid = BoxOnClWireMid
1633
+ OnWireBot = BoxOnClWireBot
1634
+
1635
+ elif cargs is None and qargs is not None:
1636
+ bits = list(qargs)
1637
+ bit_indices = sorted(i for i, x in enumerate(self.qubits) if x in bits)
1638
+ wire_label_len = len(str(len(bits) - 1))
1639
+ qargs_str = [
1640
+ str(bits.index(qbit)).ljust(wire_label_len, " ")
1641
+ for qbit in self.qubits
1642
+ if qbit in bits
1643
+ ]
1644
+ bits.sort(key=self.qubits.index)
1645
+ set_bit = self.set_qubit
1646
+ OnWire = BoxOnQuWire
1647
+ OnWireTop = BoxOnQuWireTop
1648
+ OnWireMid = BoxOnQuWireMid
1649
+ OnWireBot = BoxOnQuWireBot
1650
+ else:
1651
+ raise VisualizationError("_set_multibox error!.")
1652
+
1653
+ control_index = {}
1654
+ if controlled_edge:
1655
+ for index, qubit in enumerate(self.qubits):
1656
+ for qubit_in_edge, value in controlled_edge:
1657
+ if qubit == qubit_in_edge:
1658
+ control_index[index] = "■" if value == "1" else "o"
1659
+ if len(bit_indices) == 1:
1660
+ set_bit(bits[0], OnWire(label, top_connect=top_connect))
1661
+ else:
1662
+ box_height = max(bit_indices) - min(bit_indices) + 1
1663
+ set_bit(
1664
+ bits.pop(0), OnWireTop(label, top_connect=top_connect, wire_label=qargs_str.pop(0))
1665
+ )
1666
+ for order, bit_i in enumerate(range(min(bit_indices) + 1, max(bit_indices))):
1667
+ if bit_i in bit_indices:
1668
+ named_bit = bits.pop(0)
1669
+ wire_label = qargs_str.pop(0)
1670
+ else:
1671
+ named_bit = (self.qubits + self.clbits)[bit_i]
1672
+ wire_label = " " * wire_label_len
1673
+
1674
+ control_label = control_index.get(bit_i)
1675
+ set_bit(
1676
+ named_bit,
1677
+ OnWireMid(
1678
+ label, box_height, order, wire_label=wire_label, control_label=control_label
1679
+ ),
1680
+ )
1681
+ set_bit(
1682
+ bits.pop(0),
1683
+ OnWireBot(
1684
+ label,
1685
+ box_height,
1686
+ bot_connect=bot_connect,
1687
+ wire_label=qargs_str.pop(0),
1688
+ conditional=conditional,
1689
+ ),
1690
+ )
1691
+ return bit_indices
1692
+
1693
+ def set_cl_multibox(self, condition, wire_map, top_connect="┴"):
1694
+ """Sets the multi clbit box.
1695
+
1696
+ Args:
1697
+ condition (list[Union(Clbit, ClassicalRegister), int]): The condition
1698
+ wire_map (dict): Map of bits to indices
1699
+ top_connect (char): The char to connect the box on the top.
1700
+
1701
+ Returns:
1702
+ List: list of tuples of connections between clbits for multi-bit conditions
1703
+ """
1704
+ if isinstance(condition, expr.Expr):
1705
+ # If fixing this, please update the docstrings of `QuantumCircuit.draw` and
1706
+ # `visualization.circuit_drawer` to remove warnings.
1707
+ label = "[expr]"
1708
+ out = []
1709
+ condition_bits = node_resources(condition).clbits
1710
+ registers = collections.defaultdict(list)
1711
+ for bit in condition_bits:
1712
+ registers[get_bit_register(self._circuit, bit)].append(bit)
1713
+ if registerless := registers.pop(None, ()):
1714
+ out.extend(
1715
+ self.set_cond_bullets(label, ["1"] * len(registerless), registerless, wire_map)
1716
+ )
1717
+ if self.cregbundle:
1718
+ # It's hard to do something properly sensible here without more major rewrites, so
1719
+ # as a minimum to *not crash* we'll just treat a condition that touches part of a
1720
+ # register like it touched the whole register.
1721
+ for register in registers:
1722
+ self.set_clbit(register[0], BoxOnClWire(label=label, top_connect=top_connect))
1723
+ else:
1724
+ for register, bits in registers.items():
1725
+ out.extend(self.set_cond_bullets(label, ["1"] * len(bits), bits, wire_map))
1726
+ return out
1727
+
1728
+ label, val_bits = get_condition_label_val(condition, self._circuit, self.cregbundle)
1729
+ if isinstance(condition[0], ClassicalRegister):
1730
+ cond_reg = condition[0]
1731
+ else:
1732
+ cond_reg = get_bit_register(self._circuit, condition[0])
1733
+ if self.cregbundle:
1734
+ if isinstance(condition[0], Clbit):
1735
+ # if it's a registerless Clbit
1736
+ if cond_reg is None:
1737
+ self.set_cond_bullets(label, val_bits, [condition[0]], wire_map)
1738
+ # if it's a single bit in a register
1739
+ else:
1740
+ self.set_clbit(condition[0], BoxOnClWire(label=label, top_connect=top_connect))
1741
+ # if it's a whole register
1742
+ else:
1743
+ self.set_clbit(condition[0][0], BoxOnClWire(label=label, top_connect=top_connect))
1744
+ return []
1745
+ else:
1746
+ if isinstance(condition[0], Clbit):
1747
+ clbits = [condition[0]]
1748
+ else:
1749
+ clbits = [cond_reg[idx] for idx in range(cond_reg.size)]
1750
+ return self.set_cond_bullets(label, val_bits, clbits, wire_map)
1751
+
1752
+ def set_cond_bullets(self, label, val_bits, clbits, wire_map):
1753
+ """Sets bullets for classical conditioning when cregbundle=False.
1754
+
1755
+ Args:
1756
+ label (str): String to display below the condition
1757
+ val_bits (list(int)): A list of bit values
1758
+ clbits (list[Clbit]): The list of classical bits on
1759
+ which the instruction is conditioned.
1760
+ wire_map (dict): Map of bits to indices
1761
+
1762
+ Returns:
1763
+ List: list of tuples of open or closed bullets for condition bits
1764
+ """
1765
+ current_cons = []
1766
+ wire_max = max(wire_map[bit] for bit in clbits)
1767
+ for i, bit in enumerate(clbits):
1768
+ bot_connect = " "
1769
+ if wire_map[bit] == wire_max:
1770
+ bot_connect = label
1771
+ if val_bits[i] == "1":
1772
+ self.clbit_layer[wire_map[bit] - len(self.qubits)] = ClBullet(
1773
+ top_connect="║", bot_connect=bot_connect
1774
+ )
1775
+ elif val_bits[i] == "0":
1776
+ self.clbit_layer[wire_map[bit] - len(self.qubits)] = ClOpenBullet(
1777
+ top_connect="║", bot_connect=bot_connect
1778
+ )
1779
+ actual_index = wire_map[bit]
1780
+ if actual_index not in [i for i, j in current_cons]:
1781
+ current_cons.append(
1782
+ (actual_index, self.clbit_layer[wire_map[bit] - len(self.qubits)])
1783
+ )
1784
+ return current_cons
1785
+
1786
+ def set_qu_multibox(
1787
+ self,
1788
+ bits,
1789
+ label,
1790
+ top_connect=None,
1791
+ bot_connect=None,
1792
+ conditional=False,
1793
+ controlled_edge=None,
1794
+ ):
1795
+ """Sets the multi qubit box.
1796
+
1797
+ Args:
1798
+ bits (list[int]): A list of affected bits.
1799
+ label (string): The label for the multi qubit box.
1800
+ top_connect (char): None or a char connector on the top
1801
+ bot_connect (char): None or a char connector on the bottom
1802
+ conditional (bool): If the box has a conditional
1803
+ controlled_edge (list): A list of bit that are controlled (to draw them at the edge)
1804
+ Return:
1805
+ List: A list of indexes of the box.
1806
+ """
1807
+ return self._set_multibox(
1808
+ label,
1809
+ qargs=bits,
1810
+ top_connect=top_connect,
1811
+ bot_connect=bot_connect,
1812
+ conditional=conditional,
1813
+ controlled_edge=controlled_edge,
1814
+ )
1815
+
1816
+ def connect_with(self, wire_char):
1817
+ """Connects the elements in the layer using wire_char.
1818
+
1819
+ Args:
1820
+ wire_char (char): For example '║' or '│'.
1821
+ """
1822
+
1823
+ for label, affected_bits in self.connections:
1824
+
1825
+ if not affected_bits:
1826
+ continue
1827
+
1828
+ for index, affected_bit in enumerate(affected_bits):
1829
+ if isinstance(affected_bit, (ClBullet, ClOpenBullet)):
1830
+ wire_char = "║"
1831
+ if index == 0 and len(affected_bits) > 1:
1832
+ affected_bit.connect(wire_char, ["bot"])
1833
+ elif index == len(affected_bits) - 1:
1834
+ affected_bit.connect(wire_char, ["top"])
1835
+ else:
1836
+ affected_bit.connect(wire_char, ["bot", "top"])
1837
+ else:
1838
+ if index == 0:
1839
+ affected_bit.connect(wire_char, ["bot"])
1840
+ elif index == len(affected_bits) - 1:
1841
+ affected_bit.connect(wire_char, ["top"], label)
1842
+ else:
1843
+ affected_bit.connect(wire_char, ["bot", "top"])
1844
+
1845
+ if label:
1846
+ for affected_bit in affected_bits:
1847
+ affected_bit.right_fill = len(label) + len(affected_bit.mid)
1848
+ if isinstance(affected_bit, (Bullet, OpenBullet)) and affected_bit.conditional:
1849
+ affected_bit.left_fill = len(label) + len(affected_bit.mid)