qiskit 1.3.0b1__cp39-abi3-macosx_10_9_x86_64.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 (825) hide show
  1. qiskit/VERSION.txt +1 -0
  2. qiskit/__init__.py +127 -0
  3. qiskit/_accelerate.abi3.so +0 -0
  4. qiskit/_numpy_compat.py +73 -0
  5. qiskit/assembler/__init__.py +42 -0
  6. qiskit/assembler/assemble_circuits.py +451 -0
  7. qiskit/assembler/assemble_schedules.py +365 -0
  8. qiskit/assembler/disassemble.py +310 -0
  9. qiskit/assembler/run_config.py +77 -0
  10. qiskit/circuit/__init__.py +1270 -0
  11. qiskit/circuit/_classical_resource_map.py +148 -0
  12. qiskit/circuit/_standard_gates_commutations.py +3264 -0
  13. qiskit/circuit/_utils.py +167 -0
  14. qiskit/circuit/add_control.py +274 -0
  15. qiskit/circuit/annotated_operation.py +279 -0
  16. qiskit/circuit/barrier.py +48 -0
  17. qiskit/circuit/bit.py +94 -0
  18. qiskit/circuit/classical/__init__.py +41 -0
  19. qiskit/circuit/classical/expr/__init__.py +238 -0
  20. qiskit/circuit/classical/expr/constructors.py +556 -0
  21. qiskit/circuit/classical/expr/expr.py +397 -0
  22. qiskit/circuit/classical/expr/visitors.py +300 -0
  23. qiskit/circuit/classical/types/__init__.py +109 -0
  24. qiskit/circuit/classical/types/ordering.py +222 -0
  25. qiskit/circuit/classical/types/types.py +117 -0
  26. qiskit/circuit/classicalfunction/__init__.py +140 -0
  27. qiskit/circuit/classicalfunction/boolean_expression.py +129 -0
  28. qiskit/circuit/classicalfunction/classical_element.py +54 -0
  29. qiskit/circuit/classicalfunction/classical_function_visitor.py +155 -0
  30. qiskit/circuit/classicalfunction/classicalfunction.py +173 -0
  31. qiskit/circuit/classicalfunction/exceptions.py +35 -0
  32. qiskit/circuit/classicalfunction/types.py +18 -0
  33. qiskit/circuit/classicalfunction/utils.py +91 -0
  34. qiskit/circuit/classicalregister.py +57 -0
  35. qiskit/circuit/commutation_checker.py +106 -0
  36. qiskit/circuit/commutation_library.py +20 -0
  37. qiskit/circuit/controlflow/__init__.py +28 -0
  38. qiskit/circuit/controlflow/_builder_utils.py +207 -0
  39. qiskit/circuit/controlflow/break_loop.py +56 -0
  40. qiskit/circuit/controlflow/builder.py +691 -0
  41. qiskit/circuit/controlflow/continue_loop.py +58 -0
  42. qiskit/circuit/controlflow/control_flow.py +84 -0
  43. qiskit/circuit/controlflow/for_loop.py +217 -0
  44. qiskit/circuit/controlflow/if_else.py +503 -0
  45. qiskit/circuit/controlflow/switch_case.py +417 -0
  46. qiskit/circuit/controlflow/while_loop.py +163 -0
  47. qiskit/circuit/controlledgate.py +274 -0
  48. qiskit/circuit/delay.py +106 -0
  49. qiskit/circuit/duration.py +95 -0
  50. qiskit/circuit/equivalence.py +295 -0
  51. qiskit/circuit/equivalence_library.py +18 -0
  52. qiskit/circuit/exceptions.py +19 -0
  53. qiskit/circuit/gate.py +261 -0
  54. qiskit/circuit/instruction.py +676 -0
  55. qiskit/circuit/instructionset.py +177 -0
  56. qiskit/circuit/library/__init__.py +572 -0
  57. qiskit/circuit/library/arithmetic/__init__.py +27 -0
  58. qiskit/circuit/library/arithmetic/adders/__init__.py +17 -0
  59. qiskit/circuit/library/arithmetic/adders/adder.py +58 -0
  60. qiskit/circuit/library/arithmetic/adders/cdkm_ripple_carry_adder.py +159 -0
  61. qiskit/circuit/library/arithmetic/adders/draper_qft_adder.py +116 -0
  62. qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py +165 -0
  63. qiskit/circuit/library/arithmetic/exact_reciprocal.py +88 -0
  64. qiskit/circuit/library/arithmetic/functional_pauli_rotations.py +114 -0
  65. qiskit/circuit/library/arithmetic/integer_comparator.py +243 -0
  66. qiskit/circuit/library/arithmetic/linear_amplitude_function.py +196 -0
  67. qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +189 -0
  68. qiskit/circuit/library/arithmetic/multipliers/__init__.py +16 -0
  69. qiskit/circuit/library/arithmetic/multipliers/hrs_cumulative_multiplier.py +138 -0
  70. qiskit/circuit/library/arithmetic/multipliers/multiplier.py +101 -0
  71. qiskit/circuit/library/arithmetic/multipliers/rg_qft_multiplier.py +101 -0
  72. qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +353 -0
  73. qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +277 -0
  74. qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +317 -0
  75. qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py +335 -0
  76. qiskit/circuit/library/arithmetic/quadratic_form.py +198 -0
  77. qiskit/circuit/library/arithmetic/weighted_adder.py +337 -0
  78. qiskit/circuit/library/basis_change/__init__.py +15 -0
  79. qiskit/circuit/library/basis_change/qft.py +331 -0
  80. qiskit/circuit/library/blueprintcircuit.py +216 -0
  81. qiskit/circuit/library/boolean_logic/__init__.py +18 -0
  82. qiskit/circuit/library/boolean_logic/inner_product.py +78 -0
  83. qiskit/circuit/library/boolean_logic/quantum_and.py +97 -0
  84. qiskit/circuit/library/boolean_logic/quantum_or.py +98 -0
  85. qiskit/circuit/library/boolean_logic/quantum_xor.py +71 -0
  86. qiskit/circuit/library/data_preparation/__init__.py +54 -0
  87. qiskit/circuit/library/data_preparation/initializer.py +107 -0
  88. qiskit/circuit/library/data_preparation/pauli_feature_map.py +343 -0
  89. qiskit/circuit/library/data_preparation/state_preparation.py +336 -0
  90. qiskit/circuit/library/data_preparation/z_feature_map.py +104 -0
  91. qiskit/circuit/library/data_preparation/zz_feature_map.py +118 -0
  92. qiskit/circuit/library/fourier_checking.py +97 -0
  93. qiskit/circuit/library/generalized_gates/__init__.py +30 -0
  94. qiskit/circuit/library/generalized_gates/diagonal.py +165 -0
  95. qiskit/circuit/library/generalized_gates/gms.py +121 -0
  96. qiskit/circuit/library/generalized_gates/gr.py +215 -0
  97. qiskit/circuit/library/generalized_gates/isometry.py +370 -0
  98. qiskit/circuit/library/generalized_gates/linear_function.py +312 -0
  99. qiskit/circuit/library/generalized_gates/mcg_up_to_diagonal.py +143 -0
  100. qiskit/circuit/library/generalized_gates/mcmt.py +256 -0
  101. qiskit/circuit/library/generalized_gates/pauli.py +85 -0
  102. qiskit/circuit/library/generalized_gates/permutation.py +192 -0
  103. qiskit/circuit/library/generalized_gates/rv.py +97 -0
  104. qiskit/circuit/library/generalized_gates/uc.py +213 -0
  105. qiskit/circuit/library/generalized_gates/uc_pauli_rot.py +164 -0
  106. qiskit/circuit/library/generalized_gates/ucrx.py +32 -0
  107. qiskit/circuit/library/generalized_gates/ucry.py +32 -0
  108. qiskit/circuit/library/generalized_gates/ucrz.py +32 -0
  109. qiskit/circuit/library/generalized_gates/unitary.py +215 -0
  110. qiskit/circuit/library/graph_state.py +86 -0
  111. qiskit/circuit/library/grover_operator.py +311 -0
  112. qiskit/circuit/library/hamiltonian_gate.py +142 -0
  113. qiskit/circuit/library/hidden_linear_function.py +98 -0
  114. qiskit/circuit/library/iqp.py +96 -0
  115. qiskit/circuit/library/n_local/__init__.py +33 -0
  116. qiskit/circuit/library/n_local/efficient_su2.py +164 -0
  117. qiskit/circuit/library/n_local/evolved_operator_ansatz.py +256 -0
  118. qiskit/circuit/library/n_local/excitation_preserving.py +173 -0
  119. qiskit/circuit/library/n_local/n_local.py +1071 -0
  120. qiskit/circuit/library/n_local/pauli_two_design.py +141 -0
  121. qiskit/circuit/library/n_local/qaoa_ansatz.py +287 -0
  122. qiskit/circuit/library/n_local/real_amplitudes.py +186 -0
  123. qiskit/circuit/library/n_local/two_local.py +282 -0
  124. qiskit/circuit/library/overlap.py +117 -0
  125. qiskit/circuit/library/pauli_evolution.py +184 -0
  126. qiskit/circuit/library/phase_estimation.py +99 -0
  127. qiskit/circuit/library/phase_oracle.py +153 -0
  128. qiskit/circuit/library/quantum_volume.py +115 -0
  129. qiskit/circuit/library/standard_gates/__init__.py +123 -0
  130. qiskit/circuit/library/standard_gates/dcx.py +77 -0
  131. qiskit/circuit/library/standard_gates/ecr.py +130 -0
  132. qiskit/circuit/library/standard_gates/equivalence_library.py +1800 -0
  133. qiskit/circuit/library/standard_gates/global_phase.py +85 -0
  134. qiskit/circuit/library/standard_gates/h.py +257 -0
  135. qiskit/circuit/library/standard_gates/i.py +75 -0
  136. qiskit/circuit/library/standard_gates/iswap.py +134 -0
  137. qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +405 -0
  138. qiskit/circuit/library/standard_gates/p.py +433 -0
  139. qiskit/circuit/library/standard_gates/r.py +117 -0
  140. qiskit/circuit/library/standard_gates/rx.py +302 -0
  141. qiskit/circuit/library/standard_gates/rxx.py +183 -0
  142. qiskit/circuit/library/standard_gates/ry.py +297 -0
  143. qiskit/circuit/library/standard_gates/ryy.py +183 -0
  144. qiskit/circuit/library/standard_gates/rz.py +318 -0
  145. qiskit/circuit/library/standard_gates/rzx.py +229 -0
  146. qiskit/circuit/library/standard_gates/rzz.py +196 -0
  147. qiskit/circuit/library/standard_gates/s.py +428 -0
  148. qiskit/circuit/library/standard_gates/swap.py +288 -0
  149. qiskit/circuit/library/standard_gates/sx.py +314 -0
  150. qiskit/circuit/library/standard_gates/t.py +179 -0
  151. qiskit/circuit/library/standard_gates/u.py +395 -0
  152. qiskit/circuit/library/standard_gates/u1.py +451 -0
  153. qiskit/circuit/library/standard_gates/u2.py +146 -0
  154. qiskit/circuit/library/standard_gates/u3.py +408 -0
  155. qiskit/circuit/library/standard_gates/x.py +1527 -0
  156. qiskit/circuit/library/standard_gates/xx_minus_yy.py +235 -0
  157. qiskit/circuit/library/standard_gates/xx_plus_yy.py +239 -0
  158. qiskit/circuit/library/standard_gates/y.py +261 -0
  159. qiskit/circuit/library/standard_gates/z.py +348 -0
  160. qiskit/circuit/library/templates/__init__.py +92 -0
  161. qiskit/circuit/library/templates/clifford/__init__.py +33 -0
  162. qiskit/circuit/library/templates/clifford/clifford_2_1.py +33 -0
  163. qiskit/circuit/library/templates/clifford/clifford_2_2.py +34 -0
  164. qiskit/circuit/library/templates/clifford/clifford_2_3.py +32 -0
  165. qiskit/circuit/library/templates/clifford/clifford_2_4.py +33 -0
  166. qiskit/circuit/library/templates/clifford/clifford_3_1.py +34 -0
  167. qiskit/circuit/library/templates/clifford/clifford_4_1.py +37 -0
  168. qiskit/circuit/library/templates/clifford/clifford_4_2.py +36 -0
  169. qiskit/circuit/library/templates/clifford/clifford_4_3.py +37 -0
  170. qiskit/circuit/library/templates/clifford/clifford_4_4.py +36 -0
  171. qiskit/circuit/library/templates/clifford/clifford_5_1.py +39 -0
  172. qiskit/circuit/library/templates/clifford/clifford_6_1.py +39 -0
  173. qiskit/circuit/library/templates/clifford/clifford_6_2.py +39 -0
  174. qiskit/circuit/library/templates/clifford/clifford_6_3.py +39 -0
  175. qiskit/circuit/library/templates/clifford/clifford_6_4.py +37 -0
  176. qiskit/circuit/library/templates/clifford/clifford_6_5.py +39 -0
  177. qiskit/circuit/library/templates/clifford/clifford_8_1.py +41 -0
  178. qiskit/circuit/library/templates/clifford/clifford_8_2.py +41 -0
  179. qiskit/circuit/library/templates/clifford/clifford_8_3.py +40 -0
  180. qiskit/circuit/library/templates/nct/__init__.py +67 -0
  181. qiskit/circuit/library/templates/nct/template_nct_2a_1.py +32 -0
  182. qiskit/circuit/library/templates/nct/template_nct_2a_2.py +33 -0
  183. qiskit/circuit/library/templates/nct/template_nct_2a_3.py +35 -0
  184. qiskit/circuit/library/templates/nct/template_nct_4a_1.py +41 -0
  185. qiskit/circuit/library/templates/nct/template_nct_4a_2.py +39 -0
  186. qiskit/circuit/library/templates/nct/template_nct_4a_3.py +37 -0
  187. qiskit/circuit/library/templates/nct/template_nct_4b_1.py +39 -0
  188. qiskit/circuit/library/templates/nct/template_nct_4b_2.py +37 -0
  189. qiskit/circuit/library/templates/nct/template_nct_5a_1.py +38 -0
  190. qiskit/circuit/library/templates/nct/template_nct_5a_2.py +38 -0
  191. qiskit/circuit/library/templates/nct/template_nct_5a_3.py +38 -0
  192. qiskit/circuit/library/templates/nct/template_nct_5a_4.py +37 -0
  193. qiskit/circuit/library/templates/nct/template_nct_6a_1.py +38 -0
  194. qiskit/circuit/library/templates/nct/template_nct_6a_2.py +39 -0
  195. qiskit/circuit/library/templates/nct/template_nct_6a_3.py +39 -0
  196. qiskit/circuit/library/templates/nct/template_nct_6a_4.py +39 -0
  197. qiskit/circuit/library/templates/nct/template_nct_6b_1.py +39 -0
  198. qiskit/circuit/library/templates/nct/template_nct_6b_2.py +39 -0
  199. qiskit/circuit/library/templates/nct/template_nct_6c_1.py +39 -0
  200. qiskit/circuit/library/templates/nct/template_nct_7a_1.py +41 -0
  201. qiskit/circuit/library/templates/nct/template_nct_7b_1.py +41 -0
  202. qiskit/circuit/library/templates/nct/template_nct_7c_1.py +41 -0
  203. qiskit/circuit/library/templates/nct/template_nct_7d_1.py +41 -0
  204. qiskit/circuit/library/templates/nct/template_nct_7e_1.py +41 -0
  205. qiskit/circuit/library/templates/nct/template_nct_9a_1.py +43 -0
  206. qiskit/circuit/library/templates/nct/template_nct_9c_1.py +41 -0
  207. qiskit/circuit/library/templates/nct/template_nct_9c_10.py +42 -0
  208. qiskit/circuit/library/templates/nct/template_nct_9c_11.py +42 -0
  209. qiskit/circuit/library/templates/nct/template_nct_9c_12.py +42 -0
  210. qiskit/circuit/library/templates/nct/template_nct_9c_2.py +42 -0
  211. qiskit/circuit/library/templates/nct/template_nct_9c_3.py +42 -0
  212. qiskit/circuit/library/templates/nct/template_nct_9c_4.py +42 -0
  213. qiskit/circuit/library/templates/nct/template_nct_9c_5.py +42 -0
  214. qiskit/circuit/library/templates/nct/template_nct_9c_6.py +42 -0
  215. qiskit/circuit/library/templates/nct/template_nct_9c_7.py +42 -0
  216. qiskit/circuit/library/templates/nct/template_nct_9c_8.py +42 -0
  217. qiskit/circuit/library/templates/nct/template_nct_9c_9.py +42 -0
  218. qiskit/circuit/library/templates/nct/template_nct_9d_1.py +41 -0
  219. qiskit/circuit/library/templates/nct/template_nct_9d_10.py +42 -0
  220. qiskit/circuit/library/templates/nct/template_nct_9d_2.py +42 -0
  221. qiskit/circuit/library/templates/nct/template_nct_9d_3.py +42 -0
  222. qiskit/circuit/library/templates/nct/template_nct_9d_4.py +42 -0
  223. qiskit/circuit/library/templates/nct/template_nct_9d_5.py +42 -0
  224. qiskit/circuit/library/templates/nct/template_nct_9d_6.py +42 -0
  225. qiskit/circuit/library/templates/nct/template_nct_9d_7.py +42 -0
  226. qiskit/circuit/library/templates/nct/template_nct_9d_8.py +42 -0
  227. qiskit/circuit/library/templates/nct/template_nct_9d_9.py +42 -0
  228. qiskit/circuit/library/templates/rzx/__init__.py +25 -0
  229. qiskit/circuit/library/templates/rzx/rzx_cy.py +46 -0
  230. qiskit/circuit/library/templates/rzx/rzx_xz.py +53 -0
  231. qiskit/circuit/library/templates/rzx/rzx_yz.py +43 -0
  232. qiskit/circuit/library/templates/rzx/rzx_zz1.py +67 -0
  233. qiskit/circuit/library/templates/rzx/rzx_zz2.py +58 -0
  234. qiskit/circuit/library/templates/rzx/rzx_zz3.py +57 -0
  235. qiskit/circuit/measure.py +44 -0
  236. qiskit/circuit/operation.py +67 -0
  237. qiskit/circuit/parameter.py +174 -0
  238. qiskit/circuit/parameterexpression.py +559 -0
  239. qiskit/circuit/parametertable.py +119 -0
  240. qiskit/circuit/parametervector.py +120 -0
  241. qiskit/circuit/quantumcircuit.py +6793 -0
  242. qiskit/circuit/quantumcircuitdata.py +136 -0
  243. qiskit/circuit/quantumregister.py +75 -0
  244. qiskit/circuit/random/__init__.py +15 -0
  245. qiskit/circuit/random/utils.py +358 -0
  246. qiskit/circuit/register.py +233 -0
  247. qiskit/circuit/reset.py +34 -0
  248. qiskit/circuit/singleton.py +604 -0
  249. qiskit/circuit/store.py +95 -0
  250. qiskit/circuit/tools/__init__.py +16 -0
  251. qiskit/circuit/tools/pi_check.py +190 -0
  252. qiskit/compiler/__init__.py +33 -0
  253. qiskit/compiler/assembler.py +668 -0
  254. qiskit/compiler/scheduler.py +107 -0
  255. qiskit/compiler/sequencer.py +69 -0
  256. qiskit/compiler/transpiler.py +478 -0
  257. qiskit/converters/__init__.py +74 -0
  258. qiskit/converters/circuit_to_dag.py +78 -0
  259. qiskit/converters/circuit_to_dagdependency.py +51 -0
  260. qiskit/converters/circuit_to_dagdependency_v2.py +47 -0
  261. qiskit/converters/circuit_to_gate.py +107 -0
  262. qiskit/converters/circuit_to_instruction.py +155 -0
  263. qiskit/converters/dag_to_circuit.py +77 -0
  264. qiskit/converters/dag_to_dagdependency.py +55 -0
  265. qiskit/converters/dag_to_dagdependency_v2.py +44 -0
  266. qiskit/converters/dagdependency_to_circuit.py +42 -0
  267. qiskit/converters/dagdependency_to_dag.py +49 -0
  268. qiskit/dagcircuit/__init__.py +44 -0
  269. qiskit/dagcircuit/collect_blocks.py +391 -0
  270. qiskit/dagcircuit/dagcircuit.py +24 -0
  271. qiskit/dagcircuit/dagdependency.py +633 -0
  272. qiskit/dagcircuit/dagdependency_v2.py +641 -0
  273. qiskit/dagcircuit/dagdepnode.py +160 -0
  274. qiskit/dagcircuit/dagnode.py +176 -0
  275. qiskit/dagcircuit/exceptions.py +42 -0
  276. qiskit/exceptions.py +153 -0
  277. qiskit/passmanager/__init__.py +240 -0
  278. qiskit/passmanager/base_tasks.py +230 -0
  279. qiskit/passmanager/compilation_status.py +74 -0
  280. qiskit/passmanager/exceptions.py +19 -0
  281. qiskit/passmanager/flow_controllers.py +116 -0
  282. qiskit/passmanager/passmanager.py +333 -0
  283. qiskit/primitives/__init__.py +481 -0
  284. qiskit/primitives/backend_estimator.py +483 -0
  285. qiskit/primitives/backend_estimator_v2.py +434 -0
  286. qiskit/primitives/backend_sampler.py +222 -0
  287. qiskit/primitives/backend_sampler_v2.py +296 -0
  288. qiskit/primitives/base/__init__.py +20 -0
  289. qiskit/primitives/base/base_estimator.py +252 -0
  290. qiskit/primitives/base/base_primitive.py +45 -0
  291. qiskit/primitives/base/base_primitive_job.py +78 -0
  292. qiskit/primitives/base/base_result.py +65 -0
  293. qiskit/primitives/base/base_sampler.py +204 -0
  294. qiskit/primitives/base/estimator_result.py +46 -0
  295. qiskit/primitives/base/sampler_result.py +45 -0
  296. qiskit/primitives/base/validation.py +231 -0
  297. qiskit/primitives/containers/__init__.py +26 -0
  298. qiskit/primitives/containers/bindings_array.py +389 -0
  299. qiskit/primitives/containers/bit_array.py +741 -0
  300. qiskit/primitives/containers/data_bin.py +165 -0
  301. qiskit/primitives/containers/estimator_pub.py +222 -0
  302. qiskit/primitives/containers/object_array.py +94 -0
  303. qiskit/primitives/containers/observables_array.py +279 -0
  304. qiskit/primitives/containers/primitive_result.py +53 -0
  305. qiskit/primitives/containers/pub_result.py +51 -0
  306. qiskit/primitives/containers/sampler_pub.py +193 -0
  307. qiskit/primitives/containers/sampler_pub_result.py +74 -0
  308. qiskit/primitives/containers/shape.py +129 -0
  309. qiskit/primitives/estimator.py +172 -0
  310. qiskit/primitives/primitive_job.py +81 -0
  311. qiskit/primitives/sampler.py +162 -0
  312. qiskit/primitives/statevector_estimator.py +174 -0
  313. qiskit/primitives/statevector_sampler.py +292 -0
  314. qiskit/primitives/utils.py +247 -0
  315. qiskit/providers/__init__.py +803 -0
  316. qiskit/providers/backend.py +656 -0
  317. qiskit/providers/backend_compat.py +452 -0
  318. qiskit/providers/basic_provider/__init__.py +45 -0
  319. qiskit/providers/basic_provider/basic_provider.py +101 -0
  320. qiskit/providers/basic_provider/basic_provider_job.py +65 -0
  321. qiskit/providers/basic_provider/basic_provider_tools.py +218 -0
  322. qiskit/providers/basic_provider/basic_simulator.py +811 -0
  323. qiskit/providers/basic_provider/exceptions.py +30 -0
  324. qiskit/providers/exceptions.py +45 -0
  325. qiskit/providers/fake_provider/__init__.py +105 -0
  326. qiskit/providers/fake_provider/backends_v1/__init__.py +22 -0
  327. qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/__init__.py +18 -0
  328. qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/conf_washington.json +1 -0
  329. qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/defs_washington.json +1 -0
  330. qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/fake_127q_pulse_v1.py +37 -0
  331. qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/props_washington.json +1 -0
  332. qiskit/providers/fake_provider/backends_v1/fake_20q/__init__.py +18 -0
  333. qiskit/providers/fake_provider/backends_v1/fake_20q/conf_singapore.json +1 -0
  334. qiskit/providers/fake_provider/backends_v1/fake_20q/fake_20q.py +43 -0
  335. qiskit/providers/fake_provider/backends_v1/fake_20q/props_singapore.json +1 -0
  336. qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/__init__.py +18 -0
  337. qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/conf_hanoi.json +1 -0
  338. qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/defs_hanoi.json +1 -0
  339. qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/fake_27q_pulse_v1.py +50 -0
  340. qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/props_hanoi.json +1 -0
  341. qiskit/providers/fake_provider/backends_v1/fake_5q/__init__.py +18 -0
  342. qiskit/providers/fake_provider/backends_v1/fake_5q/conf_yorktown.json +1 -0
  343. qiskit/providers/fake_provider/backends_v1/fake_5q/fake_5q_v1.py +41 -0
  344. qiskit/providers/fake_provider/backends_v1/fake_5q/props_yorktown.json +1 -0
  345. qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/__init__.py +18 -0
  346. qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/conf_nairobi.json +1 -0
  347. qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/defs_nairobi.json +1 -0
  348. qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/fake_7q_pulse_v1.py +44 -0
  349. qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/props_nairobi.json +1 -0
  350. qiskit/providers/fake_provider/fake_1q.py +91 -0
  351. qiskit/providers/fake_provider/fake_backend.py +165 -0
  352. qiskit/providers/fake_provider/fake_openpulse_2q.py +391 -0
  353. qiskit/providers/fake_provider/fake_openpulse_3q.py +340 -0
  354. qiskit/providers/fake_provider/fake_pulse_backend.py +44 -0
  355. qiskit/providers/fake_provider/fake_qasm_backend.py +77 -0
  356. qiskit/providers/fake_provider/generic_backend_v2.py +1019 -0
  357. qiskit/providers/fake_provider/utils/__init__.py +15 -0
  358. qiskit/providers/fake_provider/utils/backend_converter.py +150 -0
  359. qiskit/providers/fake_provider/utils/json_decoder.py +109 -0
  360. qiskit/providers/job.py +147 -0
  361. qiskit/providers/jobstatus.py +30 -0
  362. qiskit/providers/models/__init__.py +89 -0
  363. qiskit/providers/models/backendconfiguration.py +1040 -0
  364. qiskit/providers/models/backendproperties.py +517 -0
  365. qiskit/providers/models/backendstatus.py +94 -0
  366. qiskit/providers/models/jobstatus.py +66 -0
  367. qiskit/providers/models/pulsedefaults.py +303 -0
  368. qiskit/providers/options.py +273 -0
  369. qiskit/providers/provider.py +95 -0
  370. qiskit/providers/providerutils.py +110 -0
  371. qiskit/pulse/__init__.py +158 -0
  372. qiskit/pulse/builder.py +2213 -0
  373. qiskit/pulse/calibration_entries.py +378 -0
  374. qiskit/pulse/channels.py +225 -0
  375. qiskit/pulse/configuration.py +245 -0
  376. qiskit/pulse/exceptions.py +43 -0
  377. qiskit/pulse/filters.py +309 -0
  378. qiskit/pulse/instruction_schedule_map.py +409 -0
  379. qiskit/pulse/instructions/__init__.py +67 -0
  380. qiskit/pulse/instructions/acquire.py +148 -0
  381. qiskit/pulse/instructions/delay.py +69 -0
  382. qiskit/pulse/instructions/directives.py +146 -0
  383. qiskit/pulse/instructions/frequency.py +132 -0
  384. qiskit/pulse/instructions/instruction.py +268 -0
  385. qiskit/pulse/instructions/phase.py +149 -0
  386. qiskit/pulse/instructions/play.py +97 -0
  387. qiskit/pulse/instructions/reference.py +98 -0
  388. qiskit/pulse/instructions/snapshot.py +80 -0
  389. qiskit/pulse/library/__init__.py +97 -0
  390. qiskit/pulse/library/continuous.py +430 -0
  391. qiskit/pulse/library/pulse.py +146 -0
  392. qiskit/pulse/library/samplers/__init__.py +15 -0
  393. qiskit/pulse/library/samplers/decorators.py +295 -0
  394. qiskit/pulse/library/samplers/strategies.py +71 -0
  395. qiskit/pulse/library/symbolic_pulses.py +1960 -0
  396. qiskit/pulse/library/waveform.py +134 -0
  397. qiskit/pulse/macros.py +262 -0
  398. qiskit/pulse/parameter_manager.py +445 -0
  399. qiskit/pulse/parser.py +314 -0
  400. qiskit/pulse/reference_manager.py +58 -0
  401. qiskit/pulse/schedule.py +1855 -0
  402. qiskit/pulse/transforms/__init__.py +106 -0
  403. qiskit/pulse/transforms/alignments.py +404 -0
  404. qiskit/pulse/transforms/base_transforms.py +71 -0
  405. qiskit/pulse/transforms/canonicalization.py +498 -0
  406. qiskit/pulse/transforms/dag.py +115 -0
  407. qiskit/pulse/utils.py +149 -0
  408. qiskit/qasm/libs/dummy/stdgates.inc +75 -0
  409. qiskit/qasm/libs/qelib1.inc +266 -0
  410. qiskit/qasm/libs/stdgates.inc +82 -0
  411. qiskit/qasm2/__init__.py +654 -0
  412. qiskit/qasm2/exceptions.py +27 -0
  413. qiskit/qasm2/export.py +370 -0
  414. qiskit/qasm2/parse.py +408 -0
  415. qiskit/qasm3/__init__.py +366 -0
  416. qiskit/qasm3/ast.py +630 -0
  417. qiskit/qasm3/exceptions.py +27 -0
  418. qiskit/qasm3/experimental.py +70 -0
  419. qiskit/qasm3/exporter.py +1273 -0
  420. qiskit/qasm3/printer.py +577 -0
  421. qiskit/qobj/__init__.py +75 -0
  422. qiskit/qobj/common.py +81 -0
  423. qiskit/qobj/converters/__init__.py +18 -0
  424. qiskit/qobj/converters/lo_config.py +177 -0
  425. qiskit/qobj/converters/pulse_instruction.py +895 -0
  426. qiskit/qobj/pulse_qobj.py +709 -0
  427. qiskit/qobj/qasm_qobj.py +708 -0
  428. qiskit/qobj/utils.py +46 -0
  429. qiskit/qpy/__init__.py +1641 -0
  430. qiskit/qpy/binary_io/__init__.py +36 -0
  431. qiskit/qpy/binary_io/circuits.py +1460 -0
  432. qiskit/qpy/binary_io/schedules.py +636 -0
  433. qiskit/qpy/binary_io/value.py +728 -0
  434. qiskit/qpy/common.py +306 -0
  435. qiskit/qpy/exceptions.py +53 -0
  436. qiskit/qpy/formats.py +394 -0
  437. qiskit/qpy/interface.py +341 -0
  438. qiskit/qpy/type_keys.py +572 -0
  439. qiskit/quantum_info/__init__.py +158 -0
  440. qiskit/quantum_info/analysis/__init__.py +17 -0
  441. qiskit/quantum_info/analysis/average.py +47 -0
  442. qiskit/quantum_info/analysis/distance.py +102 -0
  443. qiskit/quantum_info/analysis/make_observable.py +44 -0
  444. qiskit/quantum_info/analysis/z2_symmetries.py +484 -0
  445. qiskit/quantum_info/operators/__init__.py +28 -0
  446. qiskit/quantum_info/operators/base_operator.py +145 -0
  447. qiskit/quantum_info/operators/channel/__init__.py +29 -0
  448. qiskit/quantum_info/operators/channel/chi.py +191 -0
  449. qiskit/quantum_info/operators/channel/choi.py +218 -0
  450. qiskit/quantum_info/operators/channel/kraus.py +337 -0
  451. qiskit/quantum_info/operators/channel/ptm.py +204 -0
  452. qiskit/quantum_info/operators/channel/quantum_channel.py +348 -0
  453. qiskit/quantum_info/operators/channel/stinespring.py +296 -0
  454. qiskit/quantum_info/operators/channel/superop.py +377 -0
  455. qiskit/quantum_info/operators/channel/transformations.py +468 -0
  456. qiskit/quantum_info/operators/custom_iterator.py +48 -0
  457. qiskit/quantum_info/operators/dihedral/__init__.py +18 -0
  458. qiskit/quantum_info/operators/dihedral/dihedral.py +509 -0
  459. qiskit/quantum_info/operators/dihedral/dihedral_circuits.py +216 -0
  460. qiskit/quantum_info/operators/dihedral/polynomial.py +313 -0
  461. qiskit/quantum_info/operators/dihedral/random.py +64 -0
  462. qiskit/quantum_info/operators/linear_op.py +25 -0
  463. qiskit/quantum_info/operators/measures.py +418 -0
  464. qiskit/quantum_info/operators/mixins/__init__.py +52 -0
  465. qiskit/quantum_info/operators/mixins/adjoint.py +52 -0
  466. qiskit/quantum_info/operators/mixins/group.py +171 -0
  467. qiskit/quantum_info/operators/mixins/linear.py +84 -0
  468. qiskit/quantum_info/operators/mixins/multiply.py +62 -0
  469. qiskit/quantum_info/operators/mixins/tolerances.py +72 -0
  470. qiskit/quantum_info/operators/op_shape.py +525 -0
  471. qiskit/quantum_info/operators/operator.py +819 -0
  472. qiskit/quantum_info/operators/operator_utils.py +76 -0
  473. qiskit/quantum_info/operators/predicates.py +183 -0
  474. qiskit/quantum_info/operators/random.py +154 -0
  475. qiskit/quantum_info/operators/scalar_op.py +254 -0
  476. qiskit/quantum_info/operators/symplectic/__init__.py +23 -0
  477. qiskit/quantum_info/operators/symplectic/base_pauli.py +727 -0
  478. qiskit/quantum_info/operators/symplectic/clifford.py +1030 -0
  479. qiskit/quantum_info/operators/symplectic/clifford_circuits.py +558 -0
  480. qiskit/quantum_info/operators/symplectic/pauli.py +751 -0
  481. qiskit/quantum_info/operators/symplectic/pauli_list.py +1230 -0
  482. qiskit/quantum_info/operators/symplectic/pauli_utils.py +40 -0
  483. qiskit/quantum_info/operators/symplectic/random.py +117 -0
  484. qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +1175 -0
  485. qiskit/quantum_info/operators/utils/__init__.py +20 -0
  486. qiskit/quantum_info/operators/utils/anti_commutator.py +36 -0
  487. qiskit/quantum_info/operators/utils/commutator.py +36 -0
  488. qiskit/quantum_info/operators/utils/double_commutator.py +76 -0
  489. qiskit/quantum_info/quaternion.py +156 -0
  490. qiskit/quantum_info/random.py +26 -0
  491. qiskit/quantum_info/states/__init__.py +28 -0
  492. qiskit/quantum_info/states/densitymatrix.py +845 -0
  493. qiskit/quantum_info/states/measures.py +288 -0
  494. qiskit/quantum_info/states/quantum_state.py +503 -0
  495. qiskit/quantum_info/states/random.py +157 -0
  496. qiskit/quantum_info/states/stabilizerstate.py +773 -0
  497. qiskit/quantum_info/states/statevector.py +958 -0
  498. qiskit/quantum_info/states/utils.py +247 -0
  499. qiskit/result/__init__.py +73 -0
  500. qiskit/result/counts.py +189 -0
  501. qiskit/result/distributions/__init__.py +17 -0
  502. qiskit/result/distributions/probability.py +100 -0
  503. qiskit/result/distributions/quasi.py +154 -0
  504. qiskit/result/exceptions.py +40 -0
  505. qiskit/result/mitigation/__init__.py +13 -0
  506. qiskit/result/mitigation/base_readout_mitigator.py +79 -0
  507. qiskit/result/mitigation/correlated_readout_mitigator.py +269 -0
  508. qiskit/result/mitigation/local_readout_mitigator.py +320 -0
  509. qiskit/result/mitigation/utils.py +160 -0
  510. qiskit/result/models.py +234 -0
  511. qiskit/result/postprocess.py +239 -0
  512. qiskit/result/result.py +392 -0
  513. qiskit/result/sampled_expval.py +75 -0
  514. qiskit/result/utils.py +295 -0
  515. qiskit/scheduler/__init__.py +40 -0
  516. qiskit/scheduler/config.py +35 -0
  517. qiskit/scheduler/lowering.py +187 -0
  518. qiskit/scheduler/methods/__init__.py +15 -0
  519. qiskit/scheduler/methods/basic.py +137 -0
  520. qiskit/scheduler/schedule_circuit.py +67 -0
  521. qiskit/scheduler/sequence.py +102 -0
  522. qiskit/synthesis/__init__.py +195 -0
  523. qiskit/synthesis/clifford/__init__.py +19 -0
  524. qiskit/synthesis/clifford/clifford_decompose_ag.py +178 -0
  525. qiskit/synthesis/clifford/clifford_decompose_bm.py +47 -0
  526. qiskit/synthesis/clifford/clifford_decompose_full.py +64 -0
  527. qiskit/synthesis/clifford/clifford_decompose_greedy.py +57 -0
  528. qiskit/synthesis/clifford/clifford_decompose_layers.py +446 -0
  529. qiskit/synthesis/cnotdihedral/__init__.py +17 -0
  530. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_full.py +52 -0
  531. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_general.py +141 -0
  532. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_two_qubits.py +266 -0
  533. qiskit/synthesis/discrete_basis/__init__.py +16 -0
  534. qiskit/synthesis/discrete_basis/commutator_decompose.py +241 -0
  535. qiskit/synthesis/discrete_basis/gate_sequence.py +415 -0
  536. qiskit/synthesis/discrete_basis/generate_basis_approximations.py +163 -0
  537. qiskit/synthesis/discrete_basis/solovay_kitaev.py +217 -0
  538. qiskit/synthesis/evolution/__init__.py +20 -0
  539. qiskit/synthesis/evolution/evolution_synthesis.py +48 -0
  540. qiskit/synthesis/evolution/lie_trotter.py +143 -0
  541. qiskit/synthesis/evolution/matrix_synthesis.py +47 -0
  542. qiskit/synthesis/evolution/product_formula.py +384 -0
  543. qiskit/synthesis/evolution/qdrift.py +131 -0
  544. qiskit/synthesis/evolution/suzuki_trotter.py +155 -0
  545. qiskit/synthesis/linear/__init__.py +26 -0
  546. qiskit/synthesis/linear/cnot_synth.py +69 -0
  547. qiskit/synthesis/linear/linear_circuits_utils.py +128 -0
  548. qiskit/synthesis/linear/linear_depth_lnn.py +276 -0
  549. qiskit/synthesis/linear/linear_matrix_utils.py +27 -0
  550. qiskit/synthesis/linear_phase/__init__.py +17 -0
  551. qiskit/synthesis/linear_phase/cnot_phase_synth.py +206 -0
  552. qiskit/synthesis/linear_phase/cx_cz_depth_lnn.py +262 -0
  553. qiskit/synthesis/linear_phase/cz_depth_lnn.py +58 -0
  554. qiskit/synthesis/multi_controlled/__init__.py +23 -0
  555. qiskit/synthesis/multi_controlled/mcx_synthesis.py +356 -0
  556. qiskit/synthesis/one_qubit/__init__.py +15 -0
  557. qiskit/synthesis/one_qubit/one_qubit_decompose.py +288 -0
  558. qiskit/synthesis/permutation/__init__.py +18 -0
  559. qiskit/synthesis/permutation/permutation_full.py +78 -0
  560. qiskit/synthesis/permutation/permutation_lnn.py +54 -0
  561. qiskit/synthesis/permutation/permutation_reverse_lnn.py +93 -0
  562. qiskit/synthesis/permutation/permutation_utils.py +16 -0
  563. qiskit/synthesis/qft/__init__.py +16 -0
  564. qiskit/synthesis/qft/qft_decompose_full.py +79 -0
  565. qiskit/synthesis/qft/qft_decompose_lnn.py +78 -0
  566. qiskit/synthesis/stabilizer/__init__.py +16 -0
  567. qiskit/synthesis/stabilizer/stabilizer_circuit.py +149 -0
  568. qiskit/synthesis/stabilizer/stabilizer_decompose.py +193 -0
  569. qiskit/synthesis/two_qubit/__init__.py +19 -0
  570. qiskit/synthesis/two_qubit/local_invariance.py +63 -0
  571. qiskit/synthesis/two_qubit/two_qubit_decompose.py +759 -0
  572. qiskit/synthesis/two_qubit/weyl.py +97 -0
  573. qiskit/synthesis/two_qubit/xx_decompose/__init__.py +19 -0
  574. qiskit/synthesis/two_qubit/xx_decompose/circuits.py +300 -0
  575. qiskit/synthesis/two_qubit/xx_decompose/decomposer.py +324 -0
  576. qiskit/synthesis/two_qubit/xx_decompose/embodiments.py +163 -0
  577. qiskit/synthesis/two_qubit/xx_decompose/paths.py +412 -0
  578. qiskit/synthesis/two_qubit/xx_decompose/polytopes.py +262 -0
  579. qiskit/synthesis/two_qubit/xx_decompose/utilities.py +40 -0
  580. qiskit/synthesis/two_qubit/xx_decompose/weyl.py +133 -0
  581. qiskit/synthesis/unitary/__init__.py +13 -0
  582. qiskit/synthesis/unitary/aqc/__init__.py +177 -0
  583. qiskit/synthesis/unitary/aqc/approximate.py +116 -0
  584. qiskit/synthesis/unitary/aqc/aqc.py +175 -0
  585. qiskit/synthesis/unitary/aqc/cnot_structures.py +300 -0
  586. qiskit/synthesis/unitary/aqc/cnot_unit_circuit.py +103 -0
  587. qiskit/synthesis/unitary/aqc/cnot_unit_objective.py +299 -0
  588. qiskit/synthesis/unitary/aqc/elementary_operations.py +108 -0
  589. qiskit/synthesis/unitary/aqc/fast_gradient/__init__.py +164 -0
  590. qiskit/synthesis/unitary/aqc/fast_gradient/fast_grad_utils.py +237 -0
  591. qiskit/synthesis/unitary/aqc/fast_gradient/fast_gradient.py +226 -0
  592. qiskit/synthesis/unitary/aqc/fast_gradient/layer.py +370 -0
  593. qiskit/synthesis/unitary/aqc/fast_gradient/pmatrix.py +312 -0
  594. qiskit/synthesis/unitary/qsd.py +288 -0
  595. qiskit/transpiler/__init__.py +1283 -0
  596. qiskit/transpiler/basepasses.py +221 -0
  597. qiskit/transpiler/coupling.py +500 -0
  598. qiskit/transpiler/exceptions.py +59 -0
  599. qiskit/transpiler/instruction_durations.py +281 -0
  600. qiskit/transpiler/layout.py +737 -0
  601. qiskit/transpiler/passes/__init__.py +310 -0
  602. qiskit/transpiler/passes/analysis/__init__.py +23 -0
  603. qiskit/transpiler/passes/analysis/count_ops.py +30 -0
  604. qiskit/transpiler/passes/analysis/count_ops_longest_path.py +26 -0
  605. qiskit/transpiler/passes/analysis/dag_longest_path.py +24 -0
  606. qiskit/transpiler/passes/analysis/depth.py +33 -0
  607. qiskit/transpiler/passes/analysis/num_qubits.py +26 -0
  608. qiskit/transpiler/passes/analysis/num_tensor_factors.py +26 -0
  609. qiskit/transpiler/passes/analysis/resource_estimation.py +41 -0
  610. qiskit/transpiler/passes/analysis/size.py +36 -0
  611. qiskit/transpiler/passes/analysis/width.py +27 -0
  612. qiskit/transpiler/passes/basis/__init__.py +19 -0
  613. qiskit/transpiler/passes/basis/basis_translator.py +693 -0
  614. qiskit/transpiler/passes/basis/decompose.py +98 -0
  615. qiskit/transpiler/passes/basis/translate_parameterized.py +175 -0
  616. qiskit/transpiler/passes/basis/unroll_3q_or_more.py +88 -0
  617. qiskit/transpiler/passes/basis/unroll_custom_definitions.py +109 -0
  618. qiskit/transpiler/passes/calibration/__init__.py +17 -0
  619. qiskit/transpiler/passes/calibration/base_builder.py +79 -0
  620. qiskit/transpiler/passes/calibration/builders.py +20 -0
  621. qiskit/transpiler/passes/calibration/exceptions.py +22 -0
  622. qiskit/transpiler/passes/calibration/pulse_gate.py +98 -0
  623. qiskit/transpiler/passes/calibration/rx_builder.py +160 -0
  624. qiskit/transpiler/passes/calibration/rzx_builder.py +395 -0
  625. qiskit/transpiler/passes/calibration/rzx_templates.py +51 -0
  626. qiskit/transpiler/passes/layout/__init__.py +26 -0
  627. qiskit/transpiler/passes/layout/_csp_custom_solver.py +65 -0
  628. qiskit/transpiler/passes/layout/apply_layout.py +123 -0
  629. qiskit/transpiler/passes/layout/csp_layout.py +132 -0
  630. qiskit/transpiler/passes/layout/dense_layout.py +202 -0
  631. qiskit/transpiler/passes/layout/disjoint_utils.py +217 -0
  632. qiskit/transpiler/passes/layout/enlarge_with_ancilla.py +49 -0
  633. qiskit/transpiler/passes/layout/full_ancilla_allocation.py +117 -0
  634. qiskit/transpiler/passes/layout/layout_2q_distance.py +77 -0
  635. qiskit/transpiler/passes/layout/sabre_layout.py +482 -0
  636. qiskit/transpiler/passes/layout/sabre_pre_layout.py +220 -0
  637. qiskit/transpiler/passes/layout/set_layout.py +69 -0
  638. qiskit/transpiler/passes/layout/trivial_layout.py +66 -0
  639. qiskit/transpiler/passes/layout/vf2_layout.py +263 -0
  640. qiskit/transpiler/passes/layout/vf2_post_layout.py +419 -0
  641. qiskit/transpiler/passes/layout/vf2_utils.py +260 -0
  642. qiskit/transpiler/passes/optimization/__init__.py +42 -0
  643. qiskit/transpiler/passes/optimization/_gate_extension.py +80 -0
  644. qiskit/transpiler/passes/optimization/collect_1q_runs.py +31 -0
  645. qiskit/transpiler/passes/optimization/collect_2q_blocks.py +35 -0
  646. qiskit/transpiler/passes/optimization/collect_and_collapse.py +115 -0
  647. qiskit/transpiler/passes/optimization/collect_cliffords.py +88 -0
  648. qiskit/transpiler/passes/optimization/collect_linear_functions.py +80 -0
  649. qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +227 -0
  650. qiskit/transpiler/passes/optimization/commutation_analysis.py +44 -0
  651. qiskit/transpiler/passes/optimization/commutative_cancellation.py +82 -0
  652. qiskit/transpiler/passes/optimization/commutative_inverse_cancellation.py +140 -0
  653. qiskit/transpiler/passes/optimization/consolidate_blocks.py +232 -0
  654. qiskit/transpiler/passes/optimization/cx_cancellation.py +65 -0
  655. qiskit/transpiler/passes/optimization/echo_rzx_weyl_decomposition.py +160 -0
  656. qiskit/transpiler/passes/optimization/elide_permutations.py +114 -0
  657. qiskit/transpiler/passes/optimization/hoare_opt.py +420 -0
  658. qiskit/transpiler/passes/optimization/inverse_cancellation.py +93 -0
  659. qiskit/transpiler/passes/optimization/normalize_rx_angle.py +149 -0
  660. qiskit/transpiler/passes/optimization/optimize_1q_commutation.py +268 -0
  661. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +260 -0
  662. qiskit/transpiler/passes/optimization/optimize_1q_gates.py +384 -0
  663. qiskit/transpiler/passes/optimization/optimize_annotated.py +448 -0
  664. qiskit/transpiler/passes/optimization/optimize_cliffords.py +89 -0
  665. qiskit/transpiler/passes/optimization/optimize_swap_before_measure.py +71 -0
  666. qiskit/transpiler/passes/optimization/remove_diagonal_gates_before_measure.py +41 -0
  667. qiskit/transpiler/passes/optimization/remove_final_reset.py +37 -0
  668. qiskit/transpiler/passes/optimization/remove_reset_in_zero_state.py +37 -0
  669. qiskit/transpiler/passes/optimization/reset_after_measure_simplification.py +47 -0
  670. qiskit/transpiler/passes/optimization/split_2q_unitaries.py +40 -0
  671. qiskit/transpiler/passes/optimization/template_matching/__init__.py +19 -0
  672. qiskit/transpiler/passes/optimization/template_matching/backward_match.py +749 -0
  673. qiskit/transpiler/passes/optimization/template_matching/forward_match.py +452 -0
  674. qiskit/transpiler/passes/optimization/template_matching/maximal_matches.py +77 -0
  675. qiskit/transpiler/passes/optimization/template_matching/template_matching.py +370 -0
  676. qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +638 -0
  677. qiskit/transpiler/passes/optimization/template_optimization.py +158 -0
  678. qiskit/transpiler/passes/routing/__init__.py +22 -0
  679. qiskit/transpiler/passes/routing/algorithms/__init__.py +33 -0
  680. qiskit/transpiler/passes/routing/algorithms/token_swapper.py +105 -0
  681. qiskit/transpiler/passes/routing/algorithms/types.py +46 -0
  682. qiskit/transpiler/passes/routing/algorithms/util.py +103 -0
  683. qiskit/transpiler/passes/routing/basic_swap.py +166 -0
  684. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/__init__.py +25 -0
  685. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_block.py +60 -0
  686. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +395 -0
  687. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/pauli_2q_evolution_commutation.py +145 -0
  688. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +306 -0
  689. qiskit/transpiler/passes/routing/layout_transformation.py +119 -0
  690. qiskit/transpiler/passes/routing/lookahead_swap.py +390 -0
  691. qiskit/transpiler/passes/routing/sabre_swap.py +443 -0
  692. qiskit/transpiler/passes/routing/star_prerouting.py +392 -0
  693. qiskit/transpiler/passes/routing/stochastic_swap.py +532 -0
  694. qiskit/transpiler/passes/routing/utils.py +35 -0
  695. qiskit/transpiler/passes/scheduling/__init__.py +27 -0
  696. qiskit/transpiler/passes/scheduling/alap.py +153 -0
  697. qiskit/transpiler/passes/scheduling/alignments/__init__.py +81 -0
  698. qiskit/transpiler/passes/scheduling/alignments/align_measures.py +255 -0
  699. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +78 -0
  700. qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +105 -0
  701. qiskit/transpiler/passes/scheduling/alignments/reschedule.py +250 -0
  702. qiskit/transpiler/passes/scheduling/asap.py +175 -0
  703. qiskit/transpiler/passes/scheduling/base_scheduler.py +308 -0
  704. qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +307 -0
  705. qiskit/transpiler/passes/scheduling/padding/__init__.py +16 -0
  706. qiskit/transpiler/passes/scheduling/padding/base_padding.py +256 -0
  707. qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +441 -0
  708. qiskit/transpiler/passes/scheduling/padding/pad_delay.py +79 -0
  709. qiskit/transpiler/passes/scheduling/scheduling/__init__.py +17 -0
  710. qiskit/transpiler/passes/scheduling/scheduling/alap.py +127 -0
  711. qiskit/transpiler/passes/scheduling/scheduling/asap.py +131 -0
  712. qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +90 -0
  713. qiskit/transpiler/passes/scheduling/scheduling/set_io_latency.py +64 -0
  714. qiskit/transpiler/passes/scheduling/time_unit_conversion.py +160 -0
  715. qiskit/transpiler/passes/synthesis/__init__.py +20 -0
  716. qiskit/transpiler/passes/synthesis/aqc_plugin.py +153 -0
  717. qiskit/transpiler/passes/synthesis/high_level_synthesis.py +691 -0
  718. qiskit/transpiler/passes/synthesis/hls_plugins.py +928 -0
  719. qiskit/transpiler/passes/synthesis/linear_functions_synthesis.py +41 -0
  720. qiskit/transpiler/passes/synthesis/plugin.py +734 -0
  721. qiskit/transpiler/passes/synthesis/qubit_tracker.py +132 -0
  722. qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +297 -0
  723. qiskit/transpiler/passes/synthesis/unitary_synthesis.py +1055 -0
  724. qiskit/transpiler/passes/utils/__init__.py +33 -0
  725. qiskit/transpiler/passes/utils/barrier_before_final_measurements.py +95 -0
  726. qiskit/transpiler/passes/utils/check_gate_direction.py +52 -0
  727. qiskit/transpiler/passes/utils/check_map.py +78 -0
  728. qiskit/transpiler/passes/utils/contains_instruction.py +45 -0
  729. qiskit/transpiler/passes/utils/control_flow.py +65 -0
  730. qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +88 -0
  731. qiskit/transpiler/passes/utils/dag_fixed_point.py +36 -0
  732. qiskit/transpiler/passes/utils/error.py +69 -0
  733. qiskit/transpiler/passes/utils/filter_op_nodes.py +65 -0
  734. qiskit/transpiler/passes/utils/fixed_point.py +48 -0
  735. qiskit/transpiler/passes/utils/gate_direction.py +349 -0
  736. qiskit/transpiler/passes/utils/gates_basis.py +74 -0
  737. qiskit/transpiler/passes/utils/merge_adjacent_barriers.py +162 -0
  738. qiskit/transpiler/passes/utils/minimum_point.py +118 -0
  739. qiskit/transpiler/passes/utils/remove_barriers.py +49 -0
  740. qiskit/transpiler/passes/utils/remove_final_measurements.py +114 -0
  741. qiskit/transpiler/passes/utils/unroll_forloops.py +81 -0
  742. qiskit/transpiler/passmanager.py +490 -0
  743. qiskit/transpiler/passmanager_config.py +198 -0
  744. qiskit/transpiler/preset_passmanagers/__init__.py +73 -0
  745. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +1019 -0
  746. qiskit/transpiler/preset_passmanagers/common.py +647 -0
  747. qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +543 -0
  748. qiskit/transpiler/preset_passmanagers/level0.py +113 -0
  749. qiskit/transpiler/preset_passmanagers/level1.py +120 -0
  750. qiskit/transpiler/preset_passmanagers/level2.py +119 -0
  751. qiskit/transpiler/preset_passmanagers/level3.py +119 -0
  752. qiskit/transpiler/preset_passmanagers/plugin.py +353 -0
  753. qiskit/transpiler/target.py +1261 -0
  754. qiskit/transpiler/timing_constraints.py +59 -0
  755. qiskit/user_config.py +262 -0
  756. qiskit/utils/__init__.py +89 -0
  757. qiskit/utils/classtools.py +146 -0
  758. qiskit/utils/deprecation.py +490 -0
  759. qiskit/utils/lazy_tester.py +363 -0
  760. qiskit/utils/multiprocessing.py +56 -0
  761. qiskit/utils/optionals.py +347 -0
  762. qiskit/utils/parallel.py +191 -0
  763. qiskit/utils/units.py +143 -0
  764. qiskit/version.py +84 -0
  765. qiskit/visualization/__init__.py +288 -0
  766. qiskit/visualization/array.py +204 -0
  767. qiskit/visualization/bloch.py +778 -0
  768. qiskit/visualization/circuit/__init__.py +15 -0
  769. qiskit/visualization/circuit/_utils.py +675 -0
  770. qiskit/visualization/circuit/circuit_visualization.py +726 -0
  771. qiskit/visualization/circuit/latex.py +661 -0
  772. qiskit/visualization/circuit/matplotlib.py +2029 -0
  773. qiskit/visualization/circuit/qcstyle.py +278 -0
  774. qiskit/visualization/circuit/styles/__init__.py +13 -0
  775. qiskit/visualization/circuit/styles/bw.json +202 -0
  776. qiskit/visualization/circuit/styles/clifford.json +202 -0
  777. qiskit/visualization/circuit/styles/iqp-dark.json +214 -0
  778. qiskit/visualization/circuit/styles/iqp.json +214 -0
  779. qiskit/visualization/circuit/styles/textbook.json +202 -0
  780. qiskit/visualization/circuit/text.py +1844 -0
  781. qiskit/visualization/circuit_visualization.py +19 -0
  782. qiskit/visualization/counts_visualization.py +481 -0
  783. qiskit/visualization/dag_visualization.py +316 -0
  784. qiskit/visualization/exceptions.py +21 -0
  785. qiskit/visualization/gate_map.py +1485 -0
  786. qiskit/visualization/library.py +37 -0
  787. qiskit/visualization/pass_manager_visualization.py +319 -0
  788. qiskit/visualization/pulse_v2/__init__.py +21 -0
  789. qiskit/visualization/pulse_v2/core.py +901 -0
  790. qiskit/visualization/pulse_v2/device_info.py +173 -0
  791. qiskit/visualization/pulse_v2/drawings.py +253 -0
  792. qiskit/visualization/pulse_v2/events.py +254 -0
  793. qiskit/visualization/pulse_v2/generators/__init__.py +40 -0
  794. qiskit/visualization/pulse_v2/generators/barrier.py +76 -0
  795. qiskit/visualization/pulse_v2/generators/chart.py +208 -0
  796. qiskit/visualization/pulse_v2/generators/frame.py +436 -0
  797. qiskit/visualization/pulse_v2/generators/snapshot.py +133 -0
  798. qiskit/visualization/pulse_v2/generators/waveform.py +645 -0
  799. qiskit/visualization/pulse_v2/interface.py +456 -0
  800. qiskit/visualization/pulse_v2/layouts.py +387 -0
  801. qiskit/visualization/pulse_v2/plotters/__init__.py +17 -0
  802. qiskit/visualization/pulse_v2/plotters/base_plotter.py +53 -0
  803. qiskit/visualization/pulse_v2/plotters/matplotlib.py +201 -0
  804. qiskit/visualization/pulse_v2/stylesheet.py +312 -0
  805. qiskit/visualization/pulse_v2/types.py +242 -0
  806. qiskit/visualization/state_visualization.py +1518 -0
  807. qiskit/visualization/timeline/__init__.py +21 -0
  808. qiskit/visualization/timeline/core.py +457 -0
  809. qiskit/visualization/timeline/drawings.py +260 -0
  810. qiskit/visualization/timeline/generators.py +506 -0
  811. qiskit/visualization/timeline/interface.py +424 -0
  812. qiskit/visualization/timeline/layouts.py +115 -0
  813. qiskit/visualization/timeline/plotters/__init__.py +16 -0
  814. qiskit/visualization/timeline/plotters/base_plotter.py +58 -0
  815. qiskit/visualization/timeline/plotters/matplotlib.py +192 -0
  816. qiskit/visualization/timeline/stylesheet.py +301 -0
  817. qiskit/visualization/timeline/types.py +148 -0
  818. qiskit/visualization/transition_visualization.py +369 -0
  819. qiskit/visualization/utils.py +49 -0
  820. qiskit-1.3.0b1.dist-info/LICENSE.txt +203 -0
  821. qiskit-1.3.0b1.dist-info/METADATA +221 -0
  822. qiskit-1.3.0b1.dist-info/RECORD +825 -0
  823. qiskit-1.3.0b1.dist-info/WHEEL +5 -0
  824. qiskit-1.3.0b1.dist-info/entry_points.txt +57 -0
  825. qiskit-1.3.0b1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1855 @@
1
+ # This code is part of Qiskit.
2
+ #
3
+ # (C) Copyright IBM 2019.
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
+ # pylint: disable=cyclic-import
14
+
15
+ """
16
+ =========
17
+ Schedules
18
+ =========
19
+
20
+ .. currentmodule:: qiskit.pulse
21
+
22
+ Schedules are Pulse programs. They describe instruction sequences for the control hardware.
23
+ The Schedule is one of the most fundamental objects to this pulse-level programming module.
24
+ A ``Schedule`` is a representation of a *program* in Pulse. Each schedule tracks the time of each
25
+ instruction occuring in parallel over multiple signal *channels*.
26
+
27
+ .. autosummary::
28
+ :toctree: ../stubs/
29
+
30
+ Schedule
31
+ ScheduleBlock
32
+ """
33
+ from __future__ import annotations
34
+ import abc
35
+ import copy
36
+ import functools
37
+ import itertools
38
+ import multiprocessing as mp
39
+ import sys
40
+ import warnings
41
+ from collections.abc import Callable, Iterable
42
+ from typing import List, Tuple, Union, Dict, Any, Sequence
43
+
44
+ import numpy as np
45
+ import rustworkx as rx
46
+
47
+ from qiskit.circuit import ParameterVector
48
+ from qiskit.circuit.parameter import Parameter
49
+ from qiskit.circuit.parameterexpression import ParameterExpression, ParameterValueType
50
+ from qiskit.pulse.channels import Channel
51
+ from qiskit.pulse.exceptions import PulseError, UnassignedReferenceError
52
+ from qiskit.pulse.instructions import Instruction, Reference
53
+ from qiskit.pulse.utils import instruction_duration_validation
54
+ from qiskit.pulse.reference_manager import ReferenceManager
55
+ from qiskit.utils.multiprocessing import is_main_process
56
+ from qiskit.utils import deprecate_arg
57
+
58
+
59
+ Interval = Tuple[int, int]
60
+ """An interval type is a tuple of a start time (inclusive) and an end time (exclusive)."""
61
+
62
+ TimeSlots = Dict[Channel, List[Interval]]
63
+ """List of timeslots occupied by instructions for each channel."""
64
+
65
+
66
+ class Schedule:
67
+ """A quantum program *schedule* with exact time constraints for its instructions, operating
68
+ over all input signal *channels* and supporting special syntaxes for building.
69
+
70
+ Pulse program representation for the original Qiskit Pulse model [1].
71
+ Instructions are not allowed to overlap in time
72
+ on the same channel. This overlap constraint is immediately
73
+ evaluated when a new instruction is added to the ``Schedule`` object.
74
+
75
+ It is necessary to specify the absolute start time and duration
76
+ for each instruction so as to deterministically fix its execution time.
77
+
78
+ The ``Schedule`` program supports some syntax sugar for easier programming.
79
+
80
+ - Appending an instruction to the end of a channel
81
+
82
+ .. code-block:: python
83
+
84
+ sched = Schedule()
85
+ sched += Play(Gaussian(160, 0.1, 40), DriveChannel(0))
86
+
87
+ - Appending an instruction shifted in time by a given amount
88
+
89
+ .. code-block:: python
90
+
91
+ sched = Schedule()
92
+ sched += Play(Gaussian(160, 0.1, 40), DriveChannel(0)) << 30
93
+
94
+ - Merge two schedules
95
+
96
+ .. code-block:: python
97
+
98
+ sched1 = Schedule()
99
+ sched1 += Play(Gaussian(160, 0.1, 40), DriveChannel(0))
100
+
101
+ sched2 = Schedule()
102
+ sched2 += Play(Gaussian(160, 0.1, 40), DriveChannel(1))
103
+ sched2 = sched1 | sched2
104
+
105
+ A :obj:`.PulseError` is immediately raised when the overlap constraint is violated.
106
+
107
+ In the schedule representation, we cannot parametrize the duration of instructions.
108
+ Thus, we need to create a new schedule object for each duration.
109
+ To parametrize an instruction's duration, the :class:`~qiskit.pulse.ScheduleBlock`
110
+ representation may be used instead.
111
+
112
+ References:
113
+ [1]: https://arxiv.org/abs/2004.06755
114
+
115
+ """
116
+
117
+ # Prefix to use for auto naming.
118
+ prefix = "sched"
119
+
120
+ # Counter to count instance number.
121
+ instances_counter = itertools.count()
122
+
123
+ def __init__(
124
+ self,
125
+ *schedules: "ScheduleComponent" | tuple[int, "ScheduleComponent"],
126
+ name: str | None = None,
127
+ metadata: dict | None = None,
128
+ ):
129
+ """Create an empty schedule.
130
+
131
+ Args:
132
+ *schedules: Child Schedules of this parent Schedule. May either be passed as
133
+ the list of schedules, or a list of ``(start_time, schedule)`` pairs.
134
+ name: Name of this schedule. Defaults to an autogenerated string if not provided.
135
+ metadata: Arbitrary key value metadata to associate with the schedule. This gets
136
+ stored as free-form data in a dict in the
137
+ :attr:`~qiskit.pulse.Schedule.metadata` attribute. It will not be directly
138
+ used in the schedule.
139
+ Raises:
140
+ TypeError: if metadata is not a dict.
141
+ """
142
+ from qiskit.pulse.parameter_manager import ParameterManager
143
+
144
+ if name is None:
145
+ name = self.prefix + str(next(self.instances_counter))
146
+ if sys.platform != "win32" and not is_main_process():
147
+ name += f"-{mp.current_process().pid}"
148
+
149
+ self._name = name
150
+ self._parameter_manager = ParameterManager()
151
+
152
+ if not isinstance(metadata, dict) and metadata is not None:
153
+ raise TypeError("Only a dictionary or None is accepted for schedule metadata")
154
+ self._metadata = metadata or {}
155
+
156
+ self._duration = 0
157
+
158
+ # These attributes are populated by ``_mutable_insert``
159
+ self._timeslots: TimeSlots = {}
160
+ self._children: list[tuple[int, "ScheduleComponent"]] = []
161
+ for sched_pair in schedules:
162
+ try:
163
+ time, sched = sched_pair
164
+ except TypeError:
165
+ # recreate as sequence starting at 0.
166
+ time, sched = 0, sched_pair
167
+ self._mutable_insert(time, sched)
168
+
169
+ @classmethod
170
+ def initialize_from(cls, other_program: Any, name: str | None = None) -> "Schedule":
171
+ """Create new schedule object with metadata of another schedule object.
172
+
173
+ Args:
174
+ other_program: Qiskit program that provides metadata to new object.
175
+ name: Name of new schedule. Name of ``schedule`` is used by default.
176
+
177
+ Returns:
178
+ New schedule object with name and metadata.
179
+
180
+ Raises:
181
+ PulseError: When `other_program` does not provide necessary information.
182
+ """
183
+ try:
184
+ name = name or other_program.name
185
+
186
+ if other_program.metadata:
187
+ metadata = other_program.metadata.copy()
188
+ else:
189
+ metadata = None
190
+
191
+ return cls(name=name, metadata=metadata)
192
+ except AttributeError as ex:
193
+ raise PulseError(
194
+ f"{cls.__name__} cannot be initialized from the program data "
195
+ f"{other_program.__class__.__name__}."
196
+ ) from ex
197
+
198
+ @property
199
+ def name(self) -> str:
200
+ """Name of this Schedule"""
201
+ return self._name
202
+
203
+ @property
204
+ def metadata(self) -> dict[str, Any]:
205
+ """The user provided metadata associated with the schedule.
206
+
207
+ User provided ``dict`` of metadata for the schedule.
208
+ The metadata contents do not affect the semantics of the program
209
+ but are used to influence the execution of the schedule. It is expected
210
+ to be passed between all transforms of the schedule and that providers
211
+ will associate any schedule metadata with the results it returns from the
212
+ execution of that schedule.
213
+ """
214
+ return self._metadata
215
+
216
+ @metadata.setter
217
+ def metadata(self, metadata):
218
+ """Update the schedule metadata"""
219
+ if not isinstance(metadata, dict) and metadata is not None:
220
+ raise TypeError("Only a dictionary or None is accepted for schedule metadata")
221
+ self._metadata = metadata or {}
222
+
223
+ @property
224
+ def timeslots(self) -> TimeSlots:
225
+ """Time keeping attribute."""
226
+ return self._timeslots
227
+
228
+ @property
229
+ def duration(self) -> int:
230
+ """Duration of this schedule."""
231
+ return self._duration
232
+
233
+ @property
234
+ def start_time(self) -> int:
235
+ """Starting time of this schedule."""
236
+ return self.ch_start_time(*self.channels)
237
+
238
+ @property
239
+ def stop_time(self) -> int:
240
+ """Stopping time of this schedule."""
241
+ return self.duration
242
+
243
+ @property
244
+ def channels(self) -> tuple[Channel, ...]:
245
+ """Returns channels that this schedule uses."""
246
+ return tuple(self._timeslots.keys())
247
+
248
+ @property
249
+ def children(self) -> tuple[tuple[int, "ScheduleComponent"], ...]:
250
+ """Return the child schedule components of this ``Schedule`` in the
251
+ order they were added to the schedule.
252
+
253
+ Notes:
254
+ Nested schedules are returned as-is. If you want to collect only instructions,
255
+ use :py:meth:`~Schedule.instructions` instead.
256
+
257
+ Returns:
258
+ A tuple, where each element is a two-tuple containing the initial
259
+ scheduled time of each ``NamedValue`` and the component
260
+ itself.
261
+ """
262
+ return tuple(self._children)
263
+
264
+ @property
265
+ def instructions(self) -> tuple[tuple[int, Instruction], ...]:
266
+ """Get the time-ordered instructions from self."""
267
+
268
+ def key(time_inst_pair):
269
+ inst = time_inst_pair[1]
270
+ return time_inst_pair[0], inst.duration, sorted(chan.name for chan in inst.channels)
271
+
272
+ return tuple(sorted(self._instructions(), key=key))
273
+
274
+ @property
275
+ def parameters(self) -> set[Parameter]:
276
+ """Parameters which determine the schedule behavior."""
277
+ return self._parameter_manager.parameters
278
+
279
+ def ch_duration(self, *channels: Channel) -> int:
280
+ """Return the time of the end of the last instruction over the supplied channels.
281
+
282
+ Args:
283
+ *channels: Channels within ``self`` to include.
284
+ """
285
+ return self.ch_stop_time(*channels)
286
+
287
+ def ch_start_time(self, *channels: Channel) -> int:
288
+ """Return the time of the start of the first instruction over the supplied channels.
289
+
290
+ Args:
291
+ *channels: Channels within ``self`` to include.
292
+ """
293
+ try:
294
+ chan_intervals = (self._timeslots[chan] for chan in channels if chan in self._timeslots)
295
+ return min(intervals[0][0] for intervals in chan_intervals)
296
+ except ValueError:
297
+ # If there are no instructions over channels
298
+ return 0
299
+
300
+ def ch_stop_time(self, *channels: Channel) -> int:
301
+ """Return maximum start time over supplied channels.
302
+
303
+ Args:
304
+ *channels: Channels within ``self`` to include.
305
+ """
306
+ try:
307
+ chan_intervals = (self._timeslots[chan] for chan in channels if chan in self._timeslots)
308
+ return max(intervals[-1][1] for intervals in chan_intervals)
309
+ except ValueError:
310
+ # If there are no instructions over channels
311
+ return 0
312
+
313
+ def _instructions(self, time: int = 0):
314
+ """Iterable for flattening Schedule tree.
315
+
316
+ Args:
317
+ time: Shifted time due to parent.
318
+
319
+ Yields:
320
+ Iterable[Tuple[int, Instruction]]: Tuple containing the time each
321
+ :class:`~qiskit.pulse.Instruction`
322
+ starts at and the flattened :class:`~qiskit.pulse.Instruction` s.
323
+ """
324
+ for insert_time, child_sched in self.children:
325
+ yield from child_sched._instructions(time + insert_time)
326
+
327
+ def shift(self, time: int, name: str | None = None, inplace: bool = False) -> "Schedule":
328
+ """Return a schedule shifted forward by ``time``.
329
+
330
+ Args:
331
+ time: Time to shift by.
332
+ name: Name of the new schedule. Defaults to the name of self.
333
+ inplace: Perform operation inplace on this schedule. Otherwise
334
+ return a new ``Schedule``.
335
+ """
336
+ if inplace:
337
+ return self._mutable_shift(time)
338
+ return self._immutable_shift(time, name=name)
339
+
340
+ def _immutable_shift(self, time: int, name: str | None = None) -> "Schedule":
341
+ """Return a new schedule shifted forward by `time`.
342
+
343
+ Args:
344
+ time: Time to shift by
345
+ name: Name of the new schedule if call was mutable. Defaults to name of self
346
+ """
347
+ shift_sched = Schedule.initialize_from(self, name)
348
+ shift_sched.insert(time, self, inplace=True)
349
+
350
+ return shift_sched
351
+
352
+ def _mutable_shift(self, time: int) -> "Schedule":
353
+ """Return this schedule shifted forward by `time`.
354
+
355
+ Args:
356
+ time: Time to shift by
357
+
358
+ Raises:
359
+ PulseError: if ``time`` is not an integer.
360
+ """
361
+ if not isinstance(time, int):
362
+ raise PulseError("Schedule start time must be an integer.")
363
+
364
+ timeslots = {}
365
+ for chan, ch_timeslots in self._timeslots.items():
366
+ timeslots[chan] = [(ts[0] + time, ts[1] + time) for ts in ch_timeslots]
367
+
368
+ _check_nonnegative_timeslot(timeslots)
369
+
370
+ self._duration = self._duration + time
371
+ self._timeslots = timeslots
372
+ self._children = [(orig_time + time, child) for orig_time, child in self.children]
373
+ return self
374
+
375
+ def insert(
376
+ self,
377
+ start_time: int,
378
+ schedule: "ScheduleComponent",
379
+ name: str | None = None,
380
+ inplace: bool = False,
381
+ ) -> "Schedule":
382
+ """Return a new schedule with ``schedule`` inserted into ``self`` at ``start_time``.
383
+
384
+ Args:
385
+ start_time: Time to insert the schedule.
386
+ schedule: Schedule to insert.
387
+ name: Name of the new schedule. Defaults to the name of self.
388
+ inplace: Perform operation inplace on this schedule. Otherwise
389
+ return a new ``Schedule``.
390
+ """
391
+ if inplace:
392
+ return self._mutable_insert(start_time, schedule)
393
+ return self._immutable_insert(start_time, schedule, name=name)
394
+
395
+ def _mutable_insert(self, start_time: int, schedule: "ScheduleComponent") -> "Schedule":
396
+ """Mutably insert `schedule` into `self` at `start_time`.
397
+
398
+ Args:
399
+ start_time: Time to insert the second schedule.
400
+ schedule: Schedule to mutably insert.
401
+ """
402
+ self._add_timeslots(start_time, schedule)
403
+ self._children.append((start_time, schedule))
404
+ self._parameter_manager.update_parameter_table(schedule)
405
+ return self
406
+
407
+ def _immutable_insert(
408
+ self,
409
+ start_time: int,
410
+ schedule: "ScheduleComponent",
411
+ name: str | None = None,
412
+ ) -> "Schedule":
413
+ """Return a new schedule with ``schedule`` inserted into ``self`` at ``start_time``.
414
+ Args:
415
+ start_time: Time to insert the schedule.
416
+ schedule: Schedule to insert.
417
+ name: Name of the new ``Schedule``. Defaults to name of ``self``.
418
+ """
419
+ new_sched = Schedule.initialize_from(self, name)
420
+ new_sched._mutable_insert(0, self)
421
+ new_sched._mutable_insert(start_time, schedule)
422
+ return new_sched
423
+
424
+ def append(
425
+ self, schedule: "ScheduleComponent", name: str | None = None, inplace: bool = False
426
+ ) -> "Schedule":
427
+ r"""Return a new schedule with ``schedule`` inserted at the maximum time over
428
+ all channels shared between ``self`` and ``schedule``.
429
+
430
+ .. math::
431
+
432
+ t = \textrm{max}(\texttt{x.stop_time} |\texttt{x} \in
433
+ \texttt{self.channels} \cap \texttt{schedule.channels})
434
+
435
+ Args:
436
+ schedule: Schedule to be appended.
437
+ name: Name of the new ``Schedule``. Defaults to name of ``self``.
438
+ inplace: Perform operation inplace on this schedule. Otherwise
439
+ return a new ``Schedule``.
440
+ """
441
+ common_channels = set(self.channels) & set(schedule.channels)
442
+ time = self.ch_stop_time(*common_channels)
443
+ return self.insert(time, schedule, name=name, inplace=inplace)
444
+
445
+ def filter(
446
+ self,
447
+ *filter_funcs: Callable,
448
+ channels: Iterable[Channel] | None = None,
449
+ instruction_types: Iterable[abc.ABCMeta] | abc.ABCMeta = None,
450
+ time_ranges: Iterable[tuple[int, int]] | None = None,
451
+ intervals: Iterable[Interval] | None = None,
452
+ check_subroutine: bool = True,
453
+ ) -> "Schedule":
454
+ """Return a new ``Schedule`` with only the instructions from this ``Schedule`` which pass
455
+ though the provided filters; i.e. an instruction will be retained iff every function in
456
+ ``filter_funcs`` returns ``True``, the instruction occurs on a channel type contained in
457
+ ``channels``, the instruction type is contained in ``instruction_types``, and the period
458
+ over which the instruction operates is *fully* contained in one specified in
459
+ ``time_ranges`` or ``intervals``.
460
+
461
+ If no arguments are provided, ``self`` is returned.
462
+
463
+ Args:
464
+ filter_funcs: A list of Callables which take a (int, Union['Schedule', Instruction])
465
+ tuple and return a bool.
466
+ channels: For example, ``[DriveChannel(0), AcquireChannel(0)]``.
467
+ instruction_types: For example, ``[PulseInstruction, AcquireInstruction]``.
468
+ time_ranges: For example, ``[(0, 5), (6, 10)]``.
469
+ intervals: For example, ``[(0, 5), (6, 10)]``.
470
+ check_subroutine: Set `True` to individually filter instructions inside of a subroutine
471
+ defined by the :py:class:`~qiskit.pulse.instructions.Call` instruction.
472
+ """
473
+ from qiskit.pulse.filters import composite_filter, filter_instructions
474
+
475
+ filters = composite_filter(channels, instruction_types, time_ranges, intervals)
476
+ filters.extend(filter_funcs)
477
+
478
+ return filter_instructions(
479
+ self, filters=filters, negate=False, recurse_subroutines=check_subroutine
480
+ )
481
+
482
+ def exclude(
483
+ self,
484
+ *filter_funcs: Callable,
485
+ channels: Iterable[Channel] | None = None,
486
+ instruction_types: Iterable[abc.ABCMeta] | abc.ABCMeta = None,
487
+ time_ranges: Iterable[tuple[int, int]] | None = None,
488
+ intervals: Iterable[Interval] | None = None,
489
+ check_subroutine: bool = True,
490
+ ) -> "Schedule":
491
+ """Return a ``Schedule`` with only the instructions from this Schedule *failing*
492
+ at least one of the provided filters.
493
+ This method is the complement of :py:meth:`~Schedule.filter`, so that::
494
+
495
+ self.filter(args) | self.exclude(args) == self
496
+
497
+ Args:
498
+ filter_funcs: A list of Callables which take a (int, Union['Schedule', Instruction])
499
+ tuple and return a bool.
500
+ channels: For example, ``[DriveChannel(0), AcquireChannel(0)]``.
501
+ instruction_types: For example, ``[PulseInstruction, AcquireInstruction]``.
502
+ time_ranges: For example, ``[(0, 5), (6, 10)]``.
503
+ intervals: For example, ``[(0, 5), (6, 10)]``.
504
+ check_subroutine: Set `True` to individually filter instructions inside of a subroutine
505
+ defined by the :py:class:`~qiskit.pulse.instructions.Call` instruction.
506
+ """
507
+ from qiskit.pulse.filters import composite_filter, filter_instructions
508
+
509
+ filters = composite_filter(channels, instruction_types, time_ranges, intervals)
510
+ filters.extend(filter_funcs)
511
+
512
+ return filter_instructions(
513
+ self, filters=filters, negate=True, recurse_subroutines=check_subroutine
514
+ )
515
+
516
+ def _add_timeslots(self, time: int, schedule: "ScheduleComponent") -> None:
517
+ """Update all time tracking within this schedule based on the given schedule.
518
+
519
+ Args:
520
+ time: The time to insert the schedule into self.
521
+ schedule: The schedule to insert into self.
522
+
523
+ Raises:
524
+ PulseError: If timeslots overlap or an invalid start time is provided.
525
+ """
526
+ if not np.issubdtype(type(time), np.integer):
527
+ raise PulseError("Schedule start time must be an integer.")
528
+
529
+ other_timeslots = _get_timeslots(schedule)
530
+ self._duration = max(self._duration, time + schedule.duration)
531
+
532
+ for channel in schedule.channels:
533
+ if channel not in self._timeslots:
534
+ if time == 0:
535
+ self._timeslots[channel] = copy.copy(other_timeslots[channel])
536
+ else:
537
+ self._timeslots[channel] = [
538
+ (i[0] + time, i[1] + time) for i in other_timeslots[channel]
539
+ ]
540
+ continue
541
+
542
+ for idx, interval in enumerate(other_timeslots[channel]):
543
+ if interval[0] + time >= self._timeslots[channel][-1][1]:
544
+ # Can append the remaining intervals
545
+ self._timeslots[channel].extend(
546
+ [(i[0] + time, i[1] + time) for i in other_timeslots[channel][idx:]]
547
+ )
548
+ break
549
+
550
+ try:
551
+ interval = (interval[0] + time, interval[1] + time)
552
+ index = _find_insertion_index(self._timeslots[channel], interval)
553
+ self._timeslots[channel].insert(index, interval)
554
+ except PulseError as ex:
555
+ raise PulseError(
556
+ f"Schedule(name='{schedule.name or ''}') cannot be inserted into "
557
+ f"Schedule(name='{self.name or ''}') at "
558
+ f"time {time} because its instruction on channel {channel} scheduled from time "
559
+ f"{interval[0]} to {interval[1]} overlaps with an existing instruction."
560
+ ) from ex
561
+
562
+ _check_nonnegative_timeslot(self._timeslots)
563
+
564
+ def _remove_timeslots(self, time: int, schedule: "ScheduleComponent"):
565
+ """Delete the timeslots if present for the respective schedule component.
566
+
567
+ Args:
568
+ time: The time to remove the timeslots for the ``schedule`` component.
569
+ schedule: The schedule to insert into self.
570
+
571
+ Raises:
572
+ PulseError: If timeslots overlap or an invalid start time is provided.
573
+ """
574
+ if not isinstance(time, int):
575
+ raise PulseError("Schedule start time must be an integer.")
576
+
577
+ for channel in schedule.channels:
578
+
579
+ if channel not in self._timeslots:
580
+ raise PulseError(f"The channel {channel} is not present in the schedule")
581
+
582
+ channel_timeslots = self._timeslots[channel]
583
+ other_timeslots = _get_timeslots(schedule)
584
+
585
+ for interval in other_timeslots[channel]:
586
+ if channel_timeslots:
587
+ interval = (interval[0] + time, interval[1] + time)
588
+ index = _interval_index(channel_timeslots, interval)
589
+ if channel_timeslots[index] == interval:
590
+ channel_timeslots.pop(index)
591
+ continue
592
+
593
+ raise PulseError(
594
+ f"Cannot find interval ({interval[0]}, {interval[1]}) to remove from "
595
+ f"channel {channel} in Schedule(name='{schedule.name}')."
596
+ )
597
+
598
+ if not channel_timeslots:
599
+ self._timeslots.pop(channel)
600
+
601
+ def _replace_timeslots(self, time: int, old: "ScheduleComponent", new: "ScheduleComponent"):
602
+ """Replace the timeslots of ``old`` if present with the timeslots of ``new``.
603
+
604
+ Args:
605
+ time: The time to remove the timeslots for the ``schedule`` component.
606
+ old: Instruction to replace.
607
+ new: Instruction to replace with.
608
+ """
609
+ self._remove_timeslots(time, old)
610
+ self._add_timeslots(time, new)
611
+
612
+ def _renew_timeslots(self):
613
+ """Regenerate timeslots based on current instructions."""
614
+ self._timeslots.clear()
615
+ for t0, inst in self.instructions:
616
+ self._add_timeslots(t0, inst)
617
+
618
+ def replace(
619
+ self,
620
+ old: "ScheduleComponent",
621
+ new: "ScheduleComponent",
622
+ inplace: bool = False,
623
+ ) -> "Schedule":
624
+ """Return a ``Schedule`` with the ``old`` instruction replaced with a ``new``
625
+ instruction.
626
+
627
+ The replacement matching is based on an instruction equality check.
628
+
629
+ .. code-block::
630
+
631
+ from qiskit import pulse
632
+
633
+ d0 = pulse.DriveChannel(0)
634
+
635
+ sched = pulse.Schedule()
636
+
637
+ old = pulse.Play(pulse.Constant(100, 1.0), d0)
638
+ new = pulse.Play(pulse.Constant(100, 0.1), d0)
639
+
640
+ sched += old
641
+
642
+ sched = sched.replace(old, new)
643
+
644
+ assert sched == pulse.Schedule(new)
645
+
646
+ Only matches at the top-level of the schedule tree. If you wish to
647
+ perform this replacement over all instructions in the schedule tree.
648
+ Flatten the schedule prior to running::
649
+
650
+ .. code-block::
651
+
652
+ sched = pulse.Schedule()
653
+
654
+ sched += pulse.Schedule(old)
655
+
656
+ sched = sched.flatten()
657
+
658
+ sched = sched.replace(old, new)
659
+
660
+ assert sched == pulse.Schedule(new)
661
+
662
+ Args:
663
+ old: Instruction to replace.
664
+ new: Instruction to replace with.
665
+ inplace: Replace instruction by mutably modifying this ``Schedule``.
666
+
667
+ Returns:
668
+ The modified schedule with ``old`` replaced by ``new``.
669
+
670
+ Raises:
671
+ PulseError: If the ``Schedule`` after replacements will has a timing overlap.
672
+ """
673
+ from qiskit.pulse.parameter_manager import ParameterManager
674
+
675
+ new_children = []
676
+ new_parameters = ParameterManager()
677
+
678
+ for time, child in self.children:
679
+ if child == old:
680
+ new_children.append((time, new))
681
+ new_parameters.update_parameter_table(new)
682
+ else:
683
+ new_children.append((time, child))
684
+ new_parameters.update_parameter_table(child)
685
+
686
+ if inplace:
687
+ self._children = new_children
688
+ self._parameter_manager = new_parameters
689
+ self._renew_timeslots()
690
+ return self
691
+ else:
692
+ try:
693
+ new_sched = Schedule.initialize_from(self)
694
+ for time, inst in new_children:
695
+ new_sched.insert(time, inst, inplace=True)
696
+ return new_sched
697
+ except PulseError as err:
698
+ raise PulseError(
699
+ f"Replacement of {old} with {new} results in overlapping instructions."
700
+ ) from err
701
+
702
+ def is_parameterized(self) -> bool:
703
+ """Return True iff the instruction is parameterized."""
704
+ return self._parameter_manager.is_parameterized()
705
+
706
+ def assign_parameters(
707
+ self,
708
+ value_dict: dict[
709
+ ParameterExpression | ParameterVector | str,
710
+ ParameterValueType | Sequence[ParameterValueType],
711
+ ],
712
+ inplace: bool = True,
713
+ ) -> "Schedule":
714
+ """Assign the parameters in this schedule according to the input.
715
+
716
+ Args:
717
+ value_dict: A mapping from parameters or parameter names (parameter vector
718
+ or parameter vector name) to either numeric values (list of numeric values)
719
+ or another parameter expression (list of parameter expressions).
720
+ inplace: Set ``True`` to override this instance with new parameter.
721
+
722
+ Returns:
723
+ Schedule with updated parameters.
724
+ """
725
+ if not inplace:
726
+ new_schedule = copy.deepcopy(self)
727
+ return new_schedule.assign_parameters(value_dict, inplace=True)
728
+
729
+ return self._parameter_manager.assign_parameters(pulse_program=self, value_dict=value_dict)
730
+
731
+ def get_parameters(self, parameter_name: str) -> list[Parameter]:
732
+ """Get parameter object bound to this schedule by string name.
733
+
734
+ Because different ``Parameter`` objects can have the same name,
735
+ this method returns a list of ``Parameter`` s for the provided name.
736
+
737
+ Args:
738
+ parameter_name: Name of parameter.
739
+
740
+ Returns:
741
+ Parameter objects that have corresponding name.
742
+ """
743
+ return self._parameter_manager.get_parameters(parameter_name)
744
+
745
+ def __len__(self) -> int:
746
+ """Return number of instructions in the schedule."""
747
+ return len(self.instructions)
748
+
749
+ def __add__(self, other: "ScheduleComponent") -> "Schedule":
750
+ """Return a new schedule with ``other`` inserted within ``self`` at ``start_time``."""
751
+ return self.append(other)
752
+
753
+ def __or__(self, other: "ScheduleComponent") -> "Schedule":
754
+ """Return a new schedule which is the union of `self` and `other`."""
755
+ return self.insert(0, other)
756
+
757
+ def __lshift__(self, time: int) -> "Schedule":
758
+ """Return a new schedule which is shifted forward by ``time``."""
759
+ return self.shift(time)
760
+
761
+ def __eq__(self, other: object) -> bool:
762
+ """Test if two Schedule are equal.
763
+
764
+ Equality is checked by verifying there is an equal instruction at every time
765
+ in ``other`` for every instruction in this ``Schedule``.
766
+
767
+ .. warning::
768
+
769
+ This does not check for logical equivalency. Ie.,
770
+
771
+ ```python
772
+ >>> Delay(10, DriveChannel(0)) + Delay(10, DriveChannel(0))
773
+ == Delay(20, DriveChannel(0))
774
+ False
775
+ ```
776
+ """
777
+ # 0. type check, we consider Instruction is a subtype of schedule
778
+ if not isinstance(other, (type(self), Instruction)):
779
+ return False
780
+
781
+ # 1. channel check
782
+ if set(self.channels) != set(other.channels):
783
+ return False
784
+
785
+ # 2. size check
786
+ if len(self.instructions) != len(other.instructions):
787
+ return False
788
+
789
+ # 3. instruction check
790
+ return all(
791
+ self_inst == other_inst
792
+ for self_inst, other_inst in zip(self.instructions, other.instructions)
793
+ )
794
+
795
+ def __repr__(self) -> str:
796
+ name = format(self._name) if self._name else ""
797
+ instructions = ", ".join([repr(instr) for instr in self.instructions[:50]])
798
+ if len(self.instructions) > 25:
799
+ instructions += ", ..."
800
+ return f'{self.__class__.__name__}({instructions}, name="{name}")'
801
+
802
+
803
+ def _require_schedule_conversion(function: Callable) -> Callable:
804
+ """A method decorator to convert schedule block to pulse schedule.
805
+
806
+ This conversation is performed for backward compatibility only if all durations are assigned.
807
+ """
808
+
809
+ @functools.wraps(function)
810
+ def wrapper(self, *args, **kwargs):
811
+ from qiskit.pulse.transforms import block_to_schedule
812
+
813
+ return function(block_to_schedule(self), *args, **kwargs)
814
+
815
+ return wrapper
816
+
817
+
818
+ class ScheduleBlock:
819
+ """Time-ordered sequence of instructions with alignment context.
820
+
821
+ :class:`.ScheduleBlock` supports lazy scheduling of context instructions,
822
+ i.e. their timeslots is always generated at runtime.
823
+ This indicates we can parametrize instruction durations as well as
824
+ other parameters. In contrast to :class:`.Schedule` being somewhat static,
825
+ :class:`.ScheduleBlock` is a dynamic representation of a pulse program.
826
+
827
+ .. rubric:: Pulse Builder
828
+
829
+ The Qiskit pulse builder is a domain specific language that is developed on top of
830
+ the schedule block. Use of the builder syntax will improve the workflow of
831
+ pulse programming. See :ref:`pulse_builder` for a user guide.
832
+
833
+ .. rubric:: Alignment contexts
834
+
835
+ A schedule block is always relatively scheduled.
836
+ Instead of taking individual instructions with absolute execution time ``t0``,
837
+ the schedule block defines a context of scheduling and instructions
838
+ under the same context are scheduled in the same manner (alignment).
839
+ Several contexts are available in :ref:`pulse_alignments`.
840
+ A schedule block is instantiated with one of these alignment contexts.
841
+ The default context is :class:`AlignLeft`, for which all instructions are left-justified,
842
+ in other words, meaning they use as-soon-as-possible scheduling.
843
+
844
+ If you need an absolute-time interval in between instructions, you can explicitly
845
+ insert :class:`~qiskit.pulse.instructions.Delay` instructions.
846
+
847
+ .. rubric:: Nested blocks
848
+
849
+ A schedule block can contain other nested blocks with different alignment contexts.
850
+ This enables advanced scheduling, where a subset of instructions is
851
+ locally scheduled in a different manner.
852
+ Note that a :class:`.Schedule` instance cannot be directly added to a schedule block.
853
+ To add a :class:`.Schedule` instance, wrap it in a :class:`.Call` instruction.
854
+ This is implicitly performed when a schedule is added through the :ref:`pulse_builder`.
855
+
856
+ .. rubric:: Unsupported operations
857
+
858
+ Because the schedule block representation lacks timeslots, it cannot
859
+ perform particular :class:`.Schedule` operations such as :meth:`insert` or :meth:`shift` that
860
+ require instruction start time ``t0``.
861
+ In addition, :meth:`exclude` and :meth:`filter` methods are not supported
862
+ because these operations may identify the target instruction with ``t0``.
863
+ Except for these operations, :class:`.ScheduleBlock` provides full compatibility
864
+ with :class:`.Schedule`.
865
+
866
+ .. rubric:: Subroutine
867
+
868
+ The timeslots-free representation offers much greater flexibility for writing pulse programs.
869
+ Because :class:`.ScheduleBlock` only cares about the ordering of the child blocks
870
+ we can add an undefined pulse sequence as a subroutine of the main program.
871
+ If your program contains the same sequence multiple times, this representation may
872
+ reduce the memory footprint required by the program construction.
873
+ Such a subroutine is realized by the special compiler directive
874
+ :class:`~qiskit.pulse.instructions.Reference` that is defined by
875
+ a unique set of reference key strings to the subroutine.
876
+ The (executable) subroutine is separately stored in the main program.
877
+ Appended reference directives are resolved when the main program is executed.
878
+ Subroutines must be assigned through :meth:`assign_references` before execution.
879
+
880
+ One way to reference a subroutine in a schedule is to use the pulse
881
+ builder's :func:`~qiskit.pulse.builder.reference` function to declare an
882
+ unassigned reference. In this example, the program is called with the
883
+ reference key "grand_child". You can call a subroutine without specifying
884
+ a substantial program.
885
+
886
+ .. code-block::
887
+
888
+ from qiskit import pulse
889
+ from qiskit.circuit.parameter import Parameter
890
+
891
+ amp1 = Parameter("amp1")
892
+ amp2 = Parameter("amp2")
893
+
894
+ with pulse.build() as sched_inner:
895
+ pulse.play(pulse.Constant(100, amp1), pulse.DriveChannel(0))
896
+
897
+ with pulse.build() as sched_outer:
898
+ with pulse.align_right():
899
+ pulse.reference("grand_child")
900
+ pulse.play(pulse.Constant(200, amp2), pulse.DriveChannel(0))
901
+
902
+ Now you assign the inner pulse program to this reference.
903
+
904
+ .. code-block::
905
+
906
+ sched_outer.assign_references({("grand_child", ): sched_inner})
907
+ print(sched_outer.parameters)
908
+
909
+ .. parsed-literal::
910
+
911
+ {Parameter(amp1), Parameter(amp2)}
912
+
913
+ The outer program now has the parameter ``amp2`` from the inner program,
914
+ indicating that the inner program's data has been made available to the
915
+ outer program.
916
+ The program calling the "grand_child" has a reference program description
917
+ which is accessed through :attr:`ScheduleBlock.references`.
918
+
919
+ .. code-block::
920
+
921
+ print(sched_outer.references)
922
+
923
+ .. parsed-literal::
924
+
925
+ ReferenceManager:
926
+ - ('grand_child',): ScheduleBlock(Play(Constant(duration=100, amp=amp1,...
927
+
928
+ Finally, you may want to call this program from another program.
929
+ Here we try a different approach to define subroutine. Namely, we call
930
+ a subroutine from the root program with the actual program ``sched2``.
931
+
932
+ .. code-block::
933
+
934
+ amp3 = Parameter("amp3")
935
+
936
+ with pulse.build() as main:
937
+ pulse.play(pulse.Constant(300, amp3), pulse.DriveChannel(0))
938
+ pulse.call(sched_outer, name="child")
939
+
940
+ print(main.parameters)
941
+
942
+ .. parsed-literal::
943
+
944
+ {Parameter(amp1), Parameter(amp2), Parameter(amp3}
945
+
946
+ This implicitly creates a reference named "child" within
947
+ the root program and assigns ``sched_outer`` to it.
948
+
949
+ Note that the root program is only aware of its direct references.
950
+
951
+ .. code-block::
952
+
953
+ print(main.references)
954
+
955
+ .. parsed-literal::
956
+
957
+ ReferenceManager:
958
+ - ('child',): ScheduleBlock(ScheduleBlock(ScheduleBlock(Play(Con...
959
+
960
+ As you can see the main program cannot directly assign a subroutine to the "grand_child" because
961
+ this subroutine is not called within the root program, i.e. it is indirectly called by "child".
962
+ However, the returned :class:`.ReferenceManager` is a dict-like object, and you can still
963
+ reach to "grand_child" via the "child" program with the following chained dict access.
964
+
965
+ .. code-block::
966
+
967
+ main.references[("child", )].references[("grand_child", )]
968
+
969
+ Note that :attr:`ScheduleBlock.parameters` still collects all parameters
970
+ also from the subroutine once it's assigned.
971
+ """
972
+
973
+ __slots__ = (
974
+ "_parent",
975
+ "_name",
976
+ "_reference_manager",
977
+ "_parameter_manager",
978
+ "_alignment_context",
979
+ "_blocks",
980
+ "_metadata",
981
+ )
982
+
983
+ # Prefix to use for auto naming.
984
+ prefix = "block"
985
+
986
+ # Counter to count instance number.
987
+ instances_counter = itertools.count()
988
+
989
+ def __init__(
990
+ self, name: str | None = None, metadata: dict | None = None, alignment_context=None
991
+ ):
992
+ """Create an empty schedule block.
993
+
994
+ Args:
995
+ name: Name of this schedule. Defaults to an autogenerated string if not provided.
996
+ metadata: Arbitrary key value metadata to associate with the schedule. This gets
997
+ stored as free-form data in a dict in the
998
+ :attr:`~qiskit.pulse.ScheduleBlock.metadata` attribute. It will not be directly
999
+ used in the schedule.
1000
+ alignment_context (AlignmentKind): ``AlignmentKind`` instance that manages
1001
+ scheduling of instructions in this block.
1002
+
1003
+ Raises:
1004
+ TypeError: if metadata is not a dict.
1005
+ """
1006
+ from qiskit.pulse.parameter_manager import ParameterManager
1007
+ from qiskit.pulse.transforms import AlignLeft
1008
+
1009
+ if name is None:
1010
+ name = self.prefix + str(next(self.instances_counter))
1011
+ if sys.platform != "win32" and not is_main_process():
1012
+ name += f"-{mp.current_process().pid}"
1013
+
1014
+ # This points to the parent schedule object in the current scope.
1015
+ # Note that schedule block can be nested without referencing, e.g. .append(child_block),
1016
+ # and parent=None indicates the root program of the current scope.
1017
+ # The nested schedule block objects should not have _reference_manager and
1018
+ # should refer to the one of the root program.
1019
+ # This also means referenced program should be assigned to the root program, not to child.
1020
+ self._parent: ScheduleBlock | None = None
1021
+
1022
+ self._name = name
1023
+ self._parameter_manager = ParameterManager()
1024
+ self._reference_manager = ReferenceManager()
1025
+ self._alignment_context = alignment_context or AlignLeft()
1026
+ self._blocks: list["BlockComponent"] = []
1027
+
1028
+ # get parameters from context
1029
+ self._parameter_manager.update_parameter_table(self._alignment_context)
1030
+
1031
+ if not isinstance(metadata, dict) and metadata is not None:
1032
+ raise TypeError("Only a dictionary or None is accepted for schedule metadata")
1033
+ self._metadata = metadata or {}
1034
+
1035
+ @classmethod
1036
+ def initialize_from(cls, other_program: Any, name: str | None = None) -> "ScheduleBlock":
1037
+ """Create new schedule object with metadata of another schedule object.
1038
+
1039
+ Args:
1040
+ other_program: Qiskit program that provides metadata to new object.
1041
+ name: Name of new schedule. Name of ``block`` is used by default.
1042
+
1043
+ Returns:
1044
+ New block object with name and metadata.
1045
+
1046
+ Raises:
1047
+ PulseError: When ``other_program`` does not provide necessary information.
1048
+ """
1049
+ try:
1050
+ name = name or other_program.name
1051
+
1052
+ if other_program.metadata:
1053
+ metadata = other_program.metadata.copy()
1054
+ else:
1055
+ metadata = None
1056
+
1057
+ try:
1058
+ alignment_context = other_program.alignment_context
1059
+ except AttributeError:
1060
+ alignment_context = None
1061
+
1062
+ return cls(name=name, metadata=metadata, alignment_context=alignment_context)
1063
+ except AttributeError as ex:
1064
+ raise PulseError(
1065
+ f"{cls.__name__} cannot be initialized from the program data "
1066
+ f"{other_program.__class__.__name__}."
1067
+ ) from ex
1068
+
1069
+ @property
1070
+ def name(self) -> str:
1071
+ """Return name of this schedule"""
1072
+ return self._name
1073
+
1074
+ @property
1075
+ def metadata(self) -> dict[str, Any]:
1076
+ """The user provided metadata associated with the schedule.
1077
+
1078
+ User provided ``dict`` of metadata for the schedule.
1079
+ The metadata contents do not affect the semantics of the program
1080
+ but are used to influence the execution of the schedule. It is expected
1081
+ to be passed between all transforms of the schedule and that providers
1082
+ will associate any schedule metadata with the results it returns from the
1083
+ execution of that schedule.
1084
+ """
1085
+ return self._metadata
1086
+
1087
+ @metadata.setter
1088
+ def metadata(self, metadata):
1089
+ """Update the schedule metadata"""
1090
+ if not isinstance(metadata, dict) and metadata is not None:
1091
+ raise TypeError("Only a dictionary or None is accepted for schedule metadata")
1092
+ self._metadata = metadata or {}
1093
+
1094
+ @property
1095
+ def alignment_context(self):
1096
+ """Return alignment instance that allocates block component to generate schedule."""
1097
+ return self._alignment_context
1098
+
1099
+ def is_schedulable(self) -> bool:
1100
+ """Return ``True`` if all durations are assigned."""
1101
+ # check context assignment
1102
+ for context_param in self._alignment_context._context_params:
1103
+ if isinstance(context_param, ParameterExpression):
1104
+ return False
1105
+
1106
+ # check duration assignment
1107
+ for elm in self.blocks:
1108
+ if isinstance(elm, ScheduleBlock):
1109
+ if not elm.is_schedulable():
1110
+ return False
1111
+ else:
1112
+ try:
1113
+ if not isinstance(elm.duration, int):
1114
+ return False
1115
+ except UnassignedReferenceError:
1116
+ return False
1117
+ return True
1118
+
1119
+ @property
1120
+ @_require_schedule_conversion
1121
+ def duration(self) -> int:
1122
+ """Duration of this schedule block."""
1123
+ return self.duration
1124
+
1125
+ @property
1126
+ def channels(self) -> tuple[Channel, ...]:
1127
+ """Returns channels that this schedule block uses."""
1128
+ chans: set[Channel] = set()
1129
+ for elm in self.blocks:
1130
+ if isinstance(elm, Reference):
1131
+ raise UnassignedReferenceError(
1132
+ f"This schedule contains unassigned reference {elm.ref_keys} "
1133
+ "and channels are ambiguous. Please assign the subroutine first."
1134
+ )
1135
+ chans = chans | set(elm.channels)
1136
+ return tuple(chans)
1137
+
1138
+ @property
1139
+ @_require_schedule_conversion
1140
+ def instructions(self) -> tuple[tuple[int, Instruction]]:
1141
+ """Get the time-ordered instructions from self."""
1142
+ return self.instructions
1143
+
1144
+ @property
1145
+ def blocks(self) -> tuple["BlockComponent", ...]:
1146
+ """Get the block elements added to self.
1147
+
1148
+ .. note::
1149
+
1150
+ The sequence of elements is returned in order of addition. Because the first element is
1151
+ schedule first, e.g. FIFO, the returned sequence is roughly time-ordered.
1152
+ However, in the parallel alignment context, especially in
1153
+ the as-late-as-possible scheduling, or :class:`.AlignRight` context,
1154
+ the actual timing of when the instructions are issued is unknown until
1155
+ the :class:`.ScheduleBlock` is scheduled and converted into a :class:`.Schedule`.
1156
+ """
1157
+ blocks = []
1158
+ for elm in self._blocks:
1159
+ if isinstance(elm, Reference):
1160
+ elm = self.references.get(elm.ref_keys, None) or elm
1161
+ blocks.append(elm)
1162
+ return tuple(blocks)
1163
+
1164
+ @property
1165
+ def parameters(self) -> set[Parameter]:
1166
+ """Return unassigned parameters with raw names."""
1167
+ # Need new object not to mutate parameter_manager.parameters
1168
+ out_params = set()
1169
+
1170
+ out_params |= self._parameter_manager.parameters
1171
+ for subroutine in self.references.values():
1172
+ if subroutine is None:
1173
+ continue
1174
+ out_params |= subroutine.parameters
1175
+
1176
+ return out_params
1177
+
1178
+ @property
1179
+ def references(self) -> ReferenceManager:
1180
+ """Return a reference manager of the current scope."""
1181
+ if self._parent is not None:
1182
+ return self._parent.references
1183
+ return self._reference_manager
1184
+
1185
+ @_require_schedule_conversion
1186
+ def ch_duration(self, *channels: Channel) -> int:
1187
+ """Return the time of the end of the last instruction over the supplied channels.
1188
+
1189
+ Args:
1190
+ *channels: Channels within ``self`` to include.
1191
+ """
1192
+ return self.ch_duration(*channels)
1193
+
1194
+ def append(
1195
+ self, block: "BlockComponent", name: str | None = None, inplace: bool = True
1196
+ ) -> "ScheduleBlock":
1197
+ """Return a new schedule block with ``block`` appended to the context block.
1198
+ The execution time is automatically assigned when the block is converted into schedule.
1199
+
1200
+ Args:
1201
+ block: ScheduleBlock to be appended.
1202
+ name: Name of the new ``Schedule``. Defaults to name of ``self``.
1203
+ inplace: Perform operation inplace on this schedule. Otherwise,
1204
+ return a new ``Schedule``.
1205
+
1206
+ Returns:
1207
+ Schedule block with appended schedule.
1208
+
1209
+ Raises:
1210
+ PulseError: When invalid schedule type is specified.
1211
+ """
1212
+ if not isinstance(block, (ScheduleBlock, Instruction)):
1213
+ raise PulseError(
1214
+ f"Appended `schedule` {block.__class__.__name__} is invalid type. "
1215
+ "Only `Instruction` and `ScheduleBlock` can be accepted."
1216
+ )
1217
+
1218
+ if not inplace:
1219
+ schedule = copy.deepcopy(self)
1220
+ schedule._name = name or self.name
1221
+ schedule.append(block, inplace=True)
1222
+ return schedule
1223
+
1224
+ if isinstance(block, Reference) and block.ref_keys not in self.references:
1225
+ self.references[block.ref_keys] = None
1226
+
1227
+ elif isinstance(block, ScheduleBlock):
1228
+ block = copy.deepcopy(block)
1229
+ # Expose subroutines to the current main scope.
1230
+ # Note that this 'block' is not called.
1231
+ # The block is just directly appended to the current scope.
1232
+ if block.is_referenced():
1233
+ if block._parent is not None:
1234
+ # This is an edge case:
1235
+ # If this is not a parent, block.references points to the parent's reference
1236
+ # where subroutine not referred within the 'block' may exist.
1237
+ # Move only references existing in the 'block'.
1238
+ # See 'test.python.pulse.test_reference.TestReference.test_appending_child_block'
1239
+ for ref in _get_references(block._blocks):
1240
+ self.references[ref.ref_keys] = block.references[ref.ref_keys]
1241
+ else:
1242
+ # Avoid using dict.update and explicitly call __set_item__ for validation.
1243
+ # Reference manager of appended block is cleared because of data reduction.
1244
+ for ref_keys, ref in block._reference_manager.items():
1245
+ self.references[ref_keys] = ref
1246
+ block._reference_manager.clear()
1247
+ # Now switch the parent because block is appended to self.
1248
+ block._parent = self
1249
+
1250
+ self._blocks.append(block)
1251
+ self._parameter_manager.update_parameter_table(block)
1252
+
1253
+ return self
1254
+
1255
+ def filter(
1256
+ self,
1257
+ *filter_funcs: Callable[..., bool],
1258
+ channels: Iterable[Channel] | None = None,
1259
+ instruction_types: Iterable[abc.ABCMeta] | abc.ABCMeta = None,
1260
+ check_subroutine: bool = True,
1261
+ ):
1262
+ """Return a new ``ScheduleBlock`` with only the instructions from this ``ScheduleBlock``
1263
+ which pass though the provided filters; i.e. an instruction will be retained if
1264
+ every function in ``filter_funcs`` returns ``True``, the instruction occurs on
1265
+ a channel type contained in ``channels``, and the instruction type is contained
1266
+ in ``instruction_types``.
1267
+
1268
+ .. warning::
1269
+ Because ``ScheduleBlock`` is not aware of the execution time of
1270
+ the context instructions, filtering out some instructions may
1271
+ change the execution time of the remaining instructions.
1272
+
1273
+ If no arguments are provided, ``self`` is returned.
1274
+
1275
+ Args:
1276
+ filter_funcs: A list of Callables which take a ``Instruction`` and return a bool.
1277
+ channels: For example, ``[DriveChannel(0), AcquireChannel(0)]``.
1278
+ instruction_types: For example, ``[PulseInstruction, AcquireInstruction]``.
1279
+ check_subroutine: Set `True` to individually filter instructions inside a subroutine
1280
+ defined by the :py:class:`~qiskit.pulse.instructions.Call` instruction.
1281
+
1282
+ Returns:
1283
+ ``ScheduleBlock`` consisting of instructions that matches with filtering condition.
1284
+ """
1285
+ from qiskit.pulse.filters import composite_filter, filter_instructions
1286
+
1287
+ filters = composite_filter(channels, instruction_types)
1288
+ filters.extend(filter_funcs)
1289
+
1290
+ return filter_instructions(
1291
+ self, filters=filters, negate=False, recurse_subroutines=check_subroutine
1292
+ )
1293
+
1294
+ def exclude(
1295
+ self,
1296
+ *filter_funcs: Callable[..., bool],
1297
+ channels: Iterable[Channel] | None = None,
1298
+ instruction_types: Iterable[abc.ABCMeta] | abc.ABCMeta = None,
1299
+ check_subroutine: bool = True,
1300
+ ):
1301
+ """Return a new ``ScheduleBlock`` with only the instructions from this ``ScheduleBlock``
1302
+ *failing* at least one of the provided filters.
1303
+ This method is the complement of :py:meth:`~ScheduleBlock.filter`, so that::
1304
+
1305
+ self.filter(args) + self.exclude(args) == self in terms of instructions included.
1306
+
1307
+ .. warning::
1308
+ Because ``ScheduleBlock`` is not aware of the execution time of
1309
+ the context instructions, excluding some instructions may
1310
+ change the execution time of the remaining instructions.
1311
+
1312
+ Args:
1313
+ filter_funcs: A list of Callables which take a ``Instruction`` and return a bool.
1314
+ channels: For example, ``[DriveChannel(0), AcquireChannel(0)]``.
1315
+ instruction_types: For example, ``[PulseInstruction, AcquireInstruction]``.
1316
+ check_subroutine: Set `True` to individually filter instructions inside of a subroutine
1317
+ defined by the :py:class:`~qiskit.pulse.instructions.Call` instruction.
1318
+
1319
+ Returns:
1320
+ ``ScheduleBlock`` consisting of instructions that do not match with
1321
+ at least one of filtering conditions.
1322
+ """
1323
+ from qiskit.pulse.filters import composite_filter, filter_instructions
1324
+
1325
+ filters = composite_filter(channels, instruction_types)
1326
+ filters.extend(filter_funcs)
1327
+
1328
+ return filter_instructions(
1329
+ self, filters=filters, negate=True, recurse_subroutines=check_subroutine
1330
+ )
1331
+
1332
+ def replace(
1333
+ self,
1334
+ old: "BlockComponent",
1335
+ new: "BlockComponent",
1336
+ inplace: bool = True,
1337
+ ) -> "ScheduleBlock":
1338
+ """Return a ``ScheduleBlock`` with the ``old`` component replaced with a ``new``
1339
+ component.
1340
+
1341
+ Args:
1342
+ old: Schedule block component to replace.
1343
+ new: Schedule block component to replace with.
1344
+ inplace: Replace instruction by mutably modifying this ``ScheduleBlock``.
1345
+
1346
+ Returns:
1347
+ The modified schedule block with ``old`` replaced by ``new``.
1348
+ """
1349
+ if not inplace:
1350
+ schedule = copy.deepcopy(self)
1351
+ return schedule.replace(old, new, inplace=True)
1352
+
1353
+ if old not in self._blocks:
1354
+ # Avoid unnecessary update of reference and parameter manager
1355
+ return self
1356
+
1357
+ # Temporarily copies references
1358
+ all_references = ReferenceManager()
1359
+ if isinstance(new, ScheduleBlock):
1360
+ new = copy.deepcopy(new)
1361
+ all_references.update(new.references)
1362
+ new._reference_manager.clear()
1363
+ new._parent = self
1364
+ for ref_key, subroutine in self.references.items():
1365
+ if ref_key in all_references:
1366
+ warnings.warn(
1367
+ f"Reference {ref_key} conflicts with substituted program {new.name}. "
1368
+ "Existing reference has been replaced with new reference.",
1369
+ UserWarning,
1370
+ )
1371
+ continue
1372
+ all_references[ref_key] = subroutine
1373
+
1374
+ # Regenerate parameter table by regenerating elements.
1375
+ # Note that removal of parameters in old is not sufficient,
1376
+ # because corresponding parameters might be also used in another block element.
1377
+ self._parameter_manager.clear()
1378
+ self._parameter_manager.update_parameter_table(self._alignment_context)
1379
+
1380
+ new_elms = []
1381
+ for elm in self._blocks:
1382
+ if elm == old:
1383
+ elm = new
1384
+ self._parameter_manager.update_parameter_table(elm)
1385
+ new_elms.append(elm)
1386
+ self._blocks = new_elms
1387
+
1388
+ # Regenerate reference table
1389
+ # Note that reference is attached to the outer schedule if nested.
1390
+ # Thus, this investigates all references within the scope.
1391
+ self.references.clear()
1392
+ root = self
1393
+ while root._parent is not None:
1394
+ root = root._parent
1395
+ for ref in _get_references(root._blocks):
1396
+ self.references[ref.ref_keys] = all_references[ref.ref_keys]
1397
+
1398
+ return self
1399
+
1400
+ def is_parameterized(self) -> bool:
1401
+ """Return True iff the instruction is parameterized."""
1402
+ return any(self.parameters)
1403
+
1404
+ def is_referenced(self) -> bool:
1405
+ """Return True iff the current schedule block contains reference to subroutine."""
1406
+ return len(self.references) > 0
1407
+
1408
+ def assign_parameters(
1409
+ self,
1410
+ value_dict: dict[
1411
+ ParameterExpression | ParameterVector | str,
1412
+ ParameterValueType | Sequence[ParameterValueType],
1413
+ ],
1414
+ inplace: bool = True,
1415
+ ) -> "ScheduleBlock":
1416
+ """Assign the parameters in this schedule according to the input.
1417
+
1418
+ Args:
1419
+ value_dict: A mapping from parameters or parameter names (parameter vector
1420
+ or parameter vector name) to either numeric values (list of numeric values)
1421
+ or another parameter expression (list of parameter expressions).
1422
+ inplace: Set ``True`` to override this instance with new parameter.
1423
+
1424
+ Returns:
1425
+ Schedule with updated parameters.
1426
+
1427
+ Raises:
1428
+ PulseError: When the block is nested into another block.
1429
+ """
1430
+ if not inplace:
1431
+ new_schedule = copy.deepcopy(self)
1432
+ return new_schedule.assign_parameters(value_dict, inplace=True)
1433
+
1434
+ # Update parameters in the current scope
1435
+ self._parameter_manager.assign_parameters(pulse_program=self, value_dict=value_dict)
1436
+
1437
+ for subroutine in self._reference_manager.values():
1438
+ # Also assigning parameters to the references associated with self.
1439
+ # Note that references are always stored in the root program.
1440
+ # So calling assign_parameters from nested block doesn't update references.
1441
+ if subroutine is None:
1442
+ continue
1443
+ subroutine.assign_parameters(value_dict=value_dict, inplace=True)
1444
+
1445
+ return self
1446
+
1447
+ def assign_references(
1448
+ self,
1449
+ subroutine_dict: dict[str | tuple[str, ...], "ScheduleBlock"],
1450
+ inplace: bool = True,
1451
+ ) -> "ScheduleBlock":
1452
+ """Assign schedules to references.
1453
+
1454
+ It is only capable of assigning a schedule block to immediate references
1455
+ which are directly referred within the current scope.
1456
+ Let's see following example:
1457
+
1458
+ .. code-block:: python
1459
+
1460
+ from qiskit import pulse
1461
+
1462
+ with pulse.build() as subroutine:
1463
+ pulse.delay(10, pulse.DriveChannel(0))
1464
+
1465
+ with pulse.build() as sub_prog:
1466
+ pulse.reference("A")
1467
+
1468
+ with pulse.build() as main_prog:
1469
+ pulse.reference("B")
1470
+
1471
+ In above example, the ``main_prog`` can refer to the subroutine "root::B" and the
1472
+ reference of "B" to program "A", i.e., "B::A", is not defined in the root namespace.
1473
+ This prevents breaking the reference "root::B::A" by the assignment of "root::B".
1474
+ For example, if a user could indirectly assign "root::B::A" from the root program,
1475
+ one can later assign another program to "root::B" that doesn't contain "A" within it.
1476
+ In this situation, a reference "root::B::A" would still live in
1477
+ the reference manager of the root.
1478
+ However, the subroutine "root::B::A" would no longer be used in the actual pulse program.
1479
+ To assign subroutine "A" to ``nested_prog`` as a nested subprogram of ``main_prog``,
1480
+ you must first assign "A" of the ``sub_prog``,
1481
+ and then assign the ``sub_prog`` to the ``main_prog``.
1482
+
1483
+ .. code-block:: python
1484
+
1485
+ sub_prog.assign_references({("A", ): nested_prog}, inplace=True)
1486
+ main_prog.assign_references({("B", ): sub_prog}, inplace=True)
1487
+
1488
+ Alternatively, you can also write
1489
+
1490
+ .. code-block:: python
1491
+
1492
+ main_prog.assign_references({("B", ): sub_prog}, inplace=True)
1493
+ main_prog.references[("B", )].assign_references({"A": nested_prog}, inplace=True)
1494
+
1495
+ Here :attr:`.references` returns a dict-like object, and you can
1496
+ mutably update the nested reference of the particular subroutine.
1497
+
1498
+ .. note::
1499
+
1500
+ Assigned programs are deep-copied to prevent an unexpected update.
1501
+
1502
+ Args:
1503
+ subroutine_dict: A mapping from reference key to schedule block of the subroutine.
1504
+ inplace: Set ``True`` to override this instance with new subroutine.
1505
+
1506
+ Returns:
1507
+ Schedule block with assigned subroutine.
1508
+
1509
+ Raises:
1510
+ PulseError: When reference key is not defined in the current scope.
1511
+ """
1512
+ if not inplace:
1513
+ new_schedule = copy.deepcopy(self)
1514
+ return new_schedule.assign_references(subroutine_dict, inplace=True)
1515
+
1516
+ for key, subroutine in subroutine_dict.items():
1517
+ if key not in self.references:
1518
+ unassigned_keys = ", ".join(map(repr, self.references.unassigned()))
1519
+ raise PulseError(
1520
+ f"Reference instruction with {key} doesn't exist "
1521
+ f"in the current scope: {unassigned_keys}"
1522
+ )
1523
+ self.references[key] = copy.deepcopy(subroutine)
1524
+
1525
+ return self
1526
+
1527
+ def get_parameters(self, parameter_name: str) -> list[Parameter]:
1528
+ """Get parameter object bound to this schedule by string name.
1529
+
1530
+ Note that we can define different parameter objects with the same name,
1531
+ because these different objects are identified by their unique uuid.
1532
+ For example,
1533
+
1534
+ .. code-block:: python
1535
+
1536
+ from qiskit import pulse, circuit
1537
+
1538
+ amp1 = circuit.Parameter("amp")
1539
+ amp2 = circuit.Parameter("amp")
1540
+
1541
+ with pulse.build() as sub_prog:
1542
+ pulse.play(pulse.Constant(100, amp1), pulse.DriveChannel(0))
1543
+
1544
+ with pulse.build() as main_prog:
1545
+ pulse.call(sub_prog, name="sub")
1546
+ pulse.play(pulse.Constant(100, amp2), pulse.DriveChannel(0))
1547
+
1548
+ main_prog.get_parameters("amp")
1549
+
1550
+ This returns a list of two parameters ``amp1`` and ``amp2``.
1551
+
1552
+ Args:
1553
+ parameter_name: Name of parameter.
1554
+
1555
+ Returns:
1556
+ Parameter objects that have corresponding name.
1557
+ """
1558
+ matched = [p for p in self.parameters if p.name == parameter_name]
1559
+ return matched
1560
+
1561
+ def __len__(self) -> int:
1562
+ """Return number of instructions in the schedule."""
1563
+ return len(self.blocks)
1564
+
1565
+ def __eq__(self, other: object) -> bool:
1566
+ """Test if two ScheduleBlocks are equal.
1567
+
1568
+ Equality is checked by verifying there is an equal instruction at every time
1569
+ in ``other`` for every instruction in this ``ScheduleBlock``. This check is
1570
+ performed by converting the instruction representation into directed acyclic graph,
1571
+ in which execution order of every instruction is evaluated correctly across all channels.
1572
+ Also ``self`` and ``other`` should have the same alignment context.
1573
+
1574
+ .. warning::
1575
+
1576
+ This does not check for logical equivalency. Ie.,
1577
+
1578
+ ```python
1579
+ >>> Delay(10, DriveChannel(0)) + Delay(10, DriveChannel(0))
1580
+ == Delay(20, DriveChannel(0))
1581
+ False
1582
+ ```
1583
+ """
1584
+ # 0. type check
1585
+ if not isinstance(other, type(self)):
1586
+ return False
1587
+
1588
+ # 1. transformation check
1589
+ if self.alignment_context != other.alignment_context:
1590
+ return False
1591
+
1592
+ # 2. size check
1593
+ if len(self) != len(other):
1594
+ return False
1595
+
1596
+ # 3. instruction check with alignment
1597
+ from qiskit.pulse.transforms.dag import block_to_dag as dag
1598
+
1599
+ if not rx.is_isomorphic_node_match(dag(self), dag(other), lambda x, y: x == y):
1600
+ return False
1601
+
1602
+ return True
1603
+
1604
+ def __repr__(self) -> str:
1605
+ name = format(self._name) if self._name else ""
1606
+ blocks = ", ".join([repr(instr) for instr in self.blocks[:50]])
1607
+ if len(self.blocks) > 25:
1608
+ blocks += ", ..."
1609
+ return (
1610
+ f'{self.__class__.__name__}({blocks}, name="{name}",'
1611
+ f" transform={repr(self.alignment_context)})"
1612
+ )
1613
+
1614
+ def __add__(self, other: "BlockComponent") -> "ScheduleBlock":
1615
+ """Return a new schedule with ``other`` inserted within ``self`` at ``start_time``."""
1616
+ return self.append(other)
1617
+
1618
+
1619
+ def _common_method(*classes):
1620
+ """A function decorator to attach the function to specified classes as a method.
1621
+
1622
+ .. note:: For developer: A method attached through this decorator may hurt readability
1623
+ of the codebase, because the method may not be detected by a code editor.
1624
+ Thus, this decorator should be used to a limited extent, i.e. huge helper method.
1625
+ By using this decorator wisely, we can reduce code maintenance overhead without
1626
+ losing readability of the codebase.
1627
+ """
1628
+
1629
+ def decorator(method):
1630
+ @functools.wraps(method)
1631
+ def wrapper(*args, **kwargs):
1632
+ return method(*args, **kwargs)
1633
+
1634
+ for cls in classes:
1635
+ setattr(cls, method.__name__, wrapper)
1636
+ return method
1637
+
1638
+ return decorator
1639
+
1640
+
1641
+ @deprecate_arg("show_barriers", new_alias="plot_barriers", since="1.1.0", pending=True)
1642
+ @_common_method(Schedule, ScheduleBlock)
1643
+ def draw(
1644
+ self,
1645
+ style: dict[str, Any] | None = None,
1646
+ backend=None, # importing backend causes cyclic import
1647
+ time_range: tuple[int, int] | None = None,
1648
+ time_unit: str = "dt",
1649
+ disable_channels: list[Channel] | None = None,
1650
+ show_snapshot: bool = True,
1651
+ show_framechange: bool = True,
1652
+ show_waveform_info: bool = True,
1653
+ plot_barrier: bool = True,
1654
+ plotter: str = "mpl2d",
1655
+ axis: Any | None = None,
1656
+ show_barrier: bool = True,
1657
+ ):
1658
+ """Plot the schedule.
1659
+
1660
+ Args:
1661
+ style: Stylesheet options. This can be dictionary or preset stylesheet classes. See
1662
+ :py:class:`~qiskit.visualization.pulse_v2.stylesheets.IQXStandard`,
1663
+ :py:class:`~qiskit.visualization.pulse_v2.stylesheets.IQXSimple`, and
1664
+ :py:class:`~qiskit.visualization.pulse_v2.stylesheets.IQXDebugging` for details of
1665
+ preset stylesheets.
1666
+ backend (Optional[BaseBackend]): Backend object to play the input pulse program.
1667
+ If provided, the plotter may use to make the visualization hardware aware.
1668
+ time_range: Set horizontal axis limit. Tuple ``(tmin, tmax)``.
1669
+ time_unit: The unit of specified time range either ``dt`` or ``ns``.
1670
+ The unit of `ns` is available only when ``backend`` object is provided.
1671
+ disable_channels: A control property to show specific pulse channel.
1672
+ Pulse channel instances provided as a list are not shown in the output image.
1673
+ show_snapshot: Show snapshot instructions.
1674
+ show_framechange: Show frame change instructions. The frame change represents
1675
+ instructions that modulate phase or frequency of pulse channels.
1676
+ show_waveform_info: Show additional information about waveforms such as their name.
1677
+ plot_barrier: Show barrier lines.
1678
+ plotter: Name of plotter API to generate an output image.
1679
+ One of following APIs should be specified::
1680
+
1681
+ mpl2d: Matplotlib API for 2D image generation.
1682
+ Matplotlib API to generate 2D image. Charts are placed along y axis with
1683
+ vertical offset. This API takes matplotlib.axes.Axes as ``axis`` input.
1684
+
1685
+ ``axis`` and ``style`` kwargs may depend on the plotter.
1686
+ axis: Arbitrary object passed to the plotter. If this object is provided,
1687
+ the plotters use a given ``axis`` instead of internally initializing
1688
+ a figure object. This object format depends on the plotter.
1689
+ See plotter argument for details.
1690
+ show_barrier: DEPRECATED. Show barrier lines.
1691
+
1692
+ Returns:
1693
+ Visualization output data.
1694
+ The returned data type depends on the ``plotter``.
1695
+ If matplotlib family is specified, this will be a ``matplotlib.pyplot.Figure`` data.
1696
+ """
1697
+ # pylint: disable=cyclic-import
1698
+ from qiskit.visualization import pulse_drawer
1699
+
1700
+ del show_barrier
1701
+ return pulse_drawer(
1702
+ program=self,
1703
+ style=style,
1704
+ backend=backend,
1705
+ time_range=time_range,
1706
+ time_unit=time_unit,
1707
+ disable_channels=disable_channels,
1708
+ show_snapshot=show_snapshot,
1709
+ show_framechange=show_framechange,
1710
+ show_waveform_info=show_waveform_info,
1711
+ plot_barrier=plot_barrier,
1712
+ plotter=plotter,
1713
+ axis=axis,
1714
+ )
1715
+
1716
+
1717
+ def _interval_index(intervals: list[Interval], interval: Interval) -> int:
1718
+ """Find the index of an interval.
1719
+
1720
+ Args:
1721
+ intervals: A sorted list of non-overlapping Intervals.
1722
+ interval: The interval for which the index into intervals will be found.
1723
+
1724
+ Returns:
1725
+ The index of the interval.
1726
+
1727
+ Raises:
1728
+ PulseError: If the interval does not exist.
1729
+ """
1730
+ index = _locate_interval_index(intervals, interval)
1731
+ found_interval = intervals[index]
1732
+ if found_interval != interval:
1733
+ raise PulseError(f"The interval: {interval} does not exist in intervals: {intervals}")
1734
+ return index
1735
+
1736
+
1737
+ def _locate_interval_index(intervals: list[Interval], interval: Interval, index: int = 0) -> int:
1738
+ """Using binary search on start times, find an interval.
1739
+
1740
+ Args:
1741
+ intervals: A sorted list of non-overlapping Intervals.
1742
+ interval: The interval for which the index into intervals will be found.
1743
+ index: A running tally of the index, for recursion. The user should not pass a value.
1744
+
1745
+ Returns:
1746
+ The index into intervals that new_interval would be inserted to maintain
1747
+ a sorted list of intervals.
1748
+ """
1749
+ if not intervals or len(intervals) == 1:
1750
+ return index
1751
+
1752
+ mid_idx = len(intervals) // 2
1753
+ mid = intervals[mid_idx]
1754
+ if interval[1] <= mid[0] and (interval != mid):
1755
+ return _locate_interval_index(intervals[:mid_idx], interval, index=index)
1756
+ else:
1757
+ return _locate_interval_index(intervals[mid_idx:], interval, index=index + mid_idx)
1758
+
1759
+
1760
+ def _find_insertion_index(intervals: list[Interval], new_interval: Interval) -> int:
1761
+ """Using binary search on start times, return the index into `intervals` where the new interval
1762
+ belongs, or raise an error if the new interval overlaps with any existing ones.
1763
+ Args:
1764
+ intervals: A sorted list of non-overlapping Intervals.
1765
+ new_interval: The interval for which the index into intervals will be found.
1766
+ Returns:
1767
+ The index into intervals that new_interval should be inserted to maintain a sorted list
1768
+ of intervals.
1769
+ Raises:
1770
+ PulseError: If new_interval overlaps with the given intervals.
1771
+ """
1772
+ index = _locate_interval_index(intervals, new_interval)
1773
+ if index < len(intervals):
1774
+ if _overlaps(intervals[index], new_interval):
1775
+ raise PulseError("New interval overlaps with existing.")
1776
+ return index if new_interval[1] <= intervals[index][0] else index + 1
1777
+ return index
1778
+
1779
+
1780
+ def _overlaps(first: Interval, second: Interval) -> bool:
1781
+ """Return True iff first and second overlap.
1782
+ Note: first.stop may equal second.start, since Interval stop times are exclusive.
1783
+ """
1784
+ if first[0] == second[0] == second[1]:
1785
+ # They fail to overlap if one of the intervals has duration 0
1786
+ return False
1787
+ if first[0] > second[0]:
1788
+ first, second = second, first
1789
+ return second[0] < first[1]
1790
+
1791
+
1792
+ def _check_nonnegative_timeslot(timeslots: TimeSlots):
1793
+ """Test that a channel has no negative timeslots.
1794
+
1795
+ Raises:
1796
+ PulseError: If a channel timeslot is negative.
1797
+ """
1798
+ for chan, chan_timeslots in timeslots.items():
1799
+ if chan_timeslots:
1800
+ if chan_timeslots[0][0] < 0:
1801
+ raise PulseError(f"An instruction on {chan} has a negative starting time.")
1802
+
1803
+
1804
+ def _get_timeslots(schedule: "ScheduleComponent") -> TimeSlots:
1805
+ """Generate timeslots from given schedule component.
1806
+
1807
+ Args:
1808
+ schedule: Input schedule component.
1809
+
1810
+ Raises:
1811
+ PulseError: When invalid schedule type is specified.
1812
+ """
1813
+ if isinstance(schedule, Instruction):
1814
+ duration = schedule.duration
1815
+ instruction_duration_validation(duration)
1816
+ timeslots = {channel: [(0, duration)] for channel in schedule.channels}
1817
+ elif isinstance(schedule, Schedule):
1818
+ timeslots = schedule.timeslots
1819
+ else:
1820
+ raise PulseError(f"Invalid schedule type {type(schedule)} is specified.")
1821
+
1822
+ return timeslots
1823
+
1824
+
1825
+ def _get_references(block_elms: list["BlockComponent"]) -> set[Reference]:
1826
+ """Recursively get reference instructions in the current scope.
1827
+
1828
+ Args:
1829
+ block_elms: List of schedule block elements to investigate.
1830
+
1831
+ Returns:
1832
+ A set of unique reference instructions.
1833
+ """
1834
+ references = set()
1835
+ for elm in block_elms:
1836
+ if isinstance(elm, ScheduleBlock):
1837
+ references |= _get_references(elm._blocks)
1838
+ elif isinstance(elm, Reference):
1839
+ references.add(elm)
1840
+ return references
1841
+
1842
+
1843
+ # These type aliases are defined at the bottom of the file, because as of 2022-01-18 they are
1844
+ # imported into other parts of Terra. Previously, the aliases were at the top of the file and used
1845
+ # forwards references within themselves. This was fine within the same file, but causes scoping
1846
+ # issues when the aliases are imported into different scopes, in which the `ForwardRef` instances
1847
+ # would no longer resolve. Instead, we only use forward references in the annotations of _this_
1848
+ # file to reference the aliases, which are guaranteed to resolve in scope, so the aliases can all be
1849
+ # concrete.
1850
+
1851
+ ScheduleComponent = Union[Schedule, Instruction]
1852
+ """An element that composes a pulse schedule."""
1853
+
1854
+ BlockComponent = Union[ScheduleBlock, Instruction]
1855
+ """An element that composes a pulse schedule block."""