qiskit 1.3.0b1__cp39-abi3-win32.whl → 1.3.0rc2__cp39-abi3-win32.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 (360) hide show
  1. qiskit/VERSION.txt +1 -1
  2. qiskit/__init__.py +20 -1
  3. qiskit/_accelerate.pyd +0 -0
  4. qiskit/assembler/assemble_schedules.py +2 -0
  5. qiskit/circuit/__init__.py +44 -1
  6. qiskit/circuit/_standard_gates_commutations.py +585 -0
  7. qiskit/circuit/barrier.py +2 -0
  8. qiskit/circuit/controlflow/builder.py +3 -3
  9. qiskit/circuit/controlflow/if_else.py +13 -5
  10. qiskit/circuit/controlflow/while_loop.py +10 -2
  11. qiskit/circuit/delay.py +20 -3
  12. qiskit/circuit/equivalence.py +13 -214
  13. qiskit/circuit/gate.py +3 -1
  14. qiskit/circuit/instruction.py +32 -11
  15. qiskit/circuit/instructionset.py +2 -0
  16. qiskit/circuit/library/__init__.py +110 -14
  17. qiskit/circuit/library/arithmetic/__init__.py +9 -2
  18. qiskit/circuit/library/arithmetic/adders/__init__.py +1 -0
  19. qiskit/circuit/library/arithmetic/adders/adder.py +154 -2
  20. qiskit/circuit/library/arithmetic/adders/cdkm_ripple_carry_adder.py +20 -56
  21. qiskit/circuit/library/arithmetic/adders/draper_qft_adder.py +14 -1
  22. qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py +21 -91
  23. qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +1 -1
  24. qiskit/circuit/library/arithmetic/multipliers/__init__.py +1 -0
  25. qiskit/circuit/library/arithmetic/multipliers/hrs_cumulative_multiplier.py +8 -1
  26. qiskit/circuit/library/arithmetic/multipliers/multiplier.py +94 -3
  27. qiskit/circuit/library/arithmetic/multipliers/rg_qft_multiplier.py +8 -1
  28. qiskit/circuit/library/arithmetic/weighted_adder.py +1 -1
  29. qiskit/circuit/library/basis_change/qft.py +20 -38
  30. qiskit/circuit/library/blueprintcircuit.py +64 -0
  31. qiskit/circuit/library/boolean_logic/__init__.py +4 -4
  32. qiskit/circuit/library/boolean_logic/inner_product.py +81 -4
  33. qiskit/circuit/library/boolean_logic/quantum_and.py +107 -4
  34. qiskit/circuit/library/boolean_logic/quantum_or.py +107 -3
  35. qiskit/circuit/library/boolean_logic/quantum_xor.py +97 -3
  36. qiskit/circuit/library/data_preparation/__init__.py +6 -3
  37. qiskit/circuit/library/data_preparation/{z_feature_map.py → _z_feature_map.py} +45 -34
  38. qiskit/circuit/library/data_preparation/_zz_feature_map.py +150 -0
  39. qiskit/circuit/library/data_preparation/pauli_feature_map.py +342 -29
  40. qiskit/circuit/library/fourier_checking.py +72 -11
  41. qiskit/circuit/library/generalized_gates/__init__.py +1 -1
  42. qiskit/circuit/library/generalized_gates/diagonal.py +45 -51
  43. qiskit/circuit/library/generalized_gates/gms.py +67 -14
  44. qiskit/circuit/library/generalized_gates/gr.py +4 -4
  45. qiskit/circuit/library/generalized_gates/isometry.py +2 -2
  46. qiskit/circuit/library/generalized_gates/linear_function.py +12 -6
  47. qiskit/circuit/library/generalized_gates/mcmt.py +167 -107
  48. qiskit/circuit/library/generalized_gates/permutation.py +8 -6
  49. qiskit/circuit/library/generalized_gates/rv.py +8 -9
  50. qiskit/circuit/library/graph_state.py +93 -10
  51. qiskit/circuit/library/grover_operator.py +270 -2
  52. qiskit/circuit/library/hidden_linear_function.py +83 -20
  53. qiskit/circuit/library/iqp.py +99 -20
  54. qiskit/circuit/library/n_local/__init__.py +19 -7
  55. qiskit/circuit/library/n_local/efficient_su2.py +118 -5
  56. qiskit/circuit/library/n_local/evolved_operator_ansatz.py +259 -0
  57. qiskit/circuit/library/n_local/excitation_preserving.py +130 -6
  58. qiskit/circuit/library/n_local/n_local.py +406 -5
  59. qiskit/circuit/library/n_local/pauli_two_design.py +106 -4
  60. qiskit/circuit/library/n_local/qaoa_ansatz.py +80 -1
  61. qiskit/circuit/library/n_local/real_amplitudes.py +127 -7
  62. qiskit/circuit/library/n_local/two_local.py +14 -7
  63. qiskit/circuit/library/overlap.py +91 -26
  64. qiskit/circuit/library/pauli_evolution.py +17 -15
  65. qiskit/circuit/library/phase_estimation.py +80 -4
  66. qiskit/circuit/library/quantum_volume.py +72 -20
  67. qiskit/circuit/library/standard_gates/__init__.py +20 -1
  68. qiskit/circuit/library/standard_gates/dcx.py +2 -1
  69. qiskit/circuit/library/standard_gates/ecr.py +2 -2
  70. qiskit/circuit/library/standard_gates/h.py +4 -3
  71. qiskit/circuit/library/standard_gates/i.py +2 -1
  72. qiskit/circuit/library/standard_gates/iswap.py +2 -2
  73. qiskit/circuit/library/standard_gates/p.py +20 -12
  74. qiskit/circuit/library/standard_gates/r.py +1 -1
  75. qiskit/circuit/library/standard_gates/rx.py +4 -3
  76. qiskit/circuit/library/standard_gates/rxx.py +2 -2
  77. qiskit/circuit/library/standard_gates/ry.py +4 -3
  78. qiskit/circuit/library/standard_gates/ryy.py +2 -2
  79. qiskit/circuit/library/standard_gates/rz.py +13 -12
  80. qiskit/circuit/library/standard_gates/rzx.py +6 -6
  81. qiskit/circuit/library/standard_gates/rzz.py +1 -1
  82. qiskit/circuit/library/standard_gates/s.py +4 -4
  83. qiskit/circuit/library/standard_gates/swap.py +3 -3
  84. qiskit/circuit/library/standard_gates/sx.py +4 -3
  85. qiskit/circuit/library/standard_gates/t.py +2 -2
  86. qiskit/circuit/library/standard_gates/u.py +11 -3
  87. qiskit/circuit/library/standard_gates/u1.py +65 -15
  88. qiskit/circuit/library/standard_gates/u2.py +4 -1
  89. qiskit/circuit/library/standard_gates/u3.py +31 -3
  90. qiskit/circuit/library/standard_gates/x.py +7 -5
  91. qiskit/circuit/library/standard_gates/xx_minus_yy.py +2 -2
  92. qiskit/circuit/library/standard_gates/xx_plus_yy.py +2 -2
  93. qiskit/circuit/library/standard_gates/y.py +4 -3
  94. qiskit/circuit/library/standard_gates/z.py +3 -3
  95. qiskit/circuit/library/templates/clifford/clifford_2_1.py +9 -8
  96. qiskit/circuit/library/templates/clifford/clifford_2_2.py +10 -9
  97. qiskit/circuit/library/templates/clifford/clifford_2_3.py +9 -7
  98. qiskit/circuit/library/templates/clifford/clifford_2_4.py +9 -8
  99. qiskit/circuit/library/templates/clifford/clifford_3_1.py +9 -8
  100. qiskit/circuit/library/templates/clifford/clifford_4_1.py +10 -9
  101. qiskit/circuit/library/templates/clifford/clifford_4_2.py +10 -9
  102. qiskit/circuit/library/templates/clifford/clifford_4_3.py +10 -9
  103. qiskit/circuit/library/templates/clifford/clifford_4_4.py +10 -9
  104. qiskit/circuit/library/templates/clifford/clifford_5_1.py +10 -9
  105. qiskit/circuit/library/templates/clifford/clifford_6_1.py +10 -9
  106. qiskit/circuit/library/templates/clifford/clifford_6_2.py +10 -9
  107. qiskit/circuit/library/templates/clifford/clifford_6_3.py +10 -9
  108. qiskit/circuit/library/templates/clifford/clifford_6_4.py +9 -8
  109. qiskit/circuit/library/templates/clifford/clifford_6_5.py +10 -9
  110. qiskit/circuit/library/templates/clifford/clifford_8_1.py +10 -9
  111. qiskit/circuit/library/templates/clifford/clifford_8_2.py +10 -9
  112. qiskit/circuit/library/templates/clifford/clifford_8_3.py +10 -9
  113. qiskit/circuit/library/templates/nct/template_nct_2a_1.py +9 -7
  114. qiskit/circuit/library/templates/nct/template_nct_2a_2.py +10 -8
  115. qiskit/circuit/library/templates/nct/template_nct_2a_3.py +12 -10
  116. qiskit/circuit/library/templates/nct/template_nct_4a_1.py +16 -14
  117. qiskit/circuit/library/templates/nct/template_nct_4a_2.py +14 -12
  118. qiskit/circuit/library/templates/nct/template_nct_4a_3.py +12 -10
  119. qiskit/circuit/library/templates/nct/template_nct_4b_1.py +14 -12
  120. qiskit/circuit/library/templates/nct/template_nct_4b_2.py +12 -10
  121. qiskit/circuit/library/templates/nct/template_nct_5a_1.py +12 -10
  122. qiskit/circuit/library/templates/nct/template_nct_5a_2.py +12 -10
  123. qiskit/circuit/library/templates/nct/template_nct_5a_3.py +12 -10
  124. qiskit/circuit/library/templates/nct/template_nct_5a_4.py +11 -9
  125. qiskit/circuit/library/templates/nct/template_nct_6a_1.py +11 -9
  126. qiskit/circuit/library/templates/nct/template_nct_6a_2.py +12 -10
  127. qiskit/circuit/library/templates/nct/template_nct_6a_3.py +12 -10
  128. qiskit/circuit/library/templates/nct/template_nct_6a_4.py +12 -10
  129. qiskit/circuit/library/templates/nct/template_nct_6b_1.py +12 -10
  130. qiskit/circuit/library/templates/nct/template_nct_6b_2.py +12 -10
  131. qiskit/circuit/library/templates/nct/template_nct_6c_1.py +12 -10
  132. qiskit/circuit/library/templates/nct/template_nct_7a_1.py +13 -11
  133. qiskit/circuit/library/templates/nct/template_nct_7b_1.py +13 -11
  134. qiskit/circuit/library/templates/nct/template_nct_7c_1.py +13 -11
  135. qiskit/circuit/library/templates/nct/template_nct_7d_1.py +13 -11
  136. qiskit/circuit/library/templates/nct/template_nct_7e_1.py +13 -11
  137. qiskit/circuit/library/templates/nct/template_nct_9a_1.py +13 -11
  138. qiskit/circuit/library/templates/nct/template_nct_9c_1.py +11 -9
  139. qiskit/circuit/library/templates/nct/template_nct_9c_10.py +12 -10
  140. qiskit/circuit/library/templates/nct/template_nct_9c_11.py +12 -10
  141. qiskit/circuit/library/templates/nct/template_nct_9c_12.py +12 -10
  142. qiskit/circuit/library/templates/nct/template_nct_9c_2.py +12 -10
  143. qiskit/circuit/library/templates/nct/template_nct_9c_3.py +12 -10
  144. qiskit/circuit/library/templates/nct/template_nct_9c_4.py +12 -10
  145. qiskit/circuit/library/templates/nct/template_nct_9c_5.py +12 -10
  146. qiskit/circuit/library/templates/nct/template_nct_9c_6.py +12 -10
  147. qiskit/circuit/library/templates/nct/template_nct_9c_7.py +12 -10
  148. qiskit/circuit/library/templates/nct/template_nct_9c_8.py +12 -10
  149. qiskit/circuit/library/templates/nct/template_nct_9c_9.py +12 -10
  150. qiskit/circuit/library/templates/nct/template_nct_9d_1.py +11 -9
  151. qiskit/circuit/library/templates/nct/template_nct_9d_10.py +12 -10
  152. qiskit/circuit/library/templates/nct/template_nct_9d_2.py +12 -10
  153. qiskit/circuit/library/templates/nct/template_nct_9d_3.py +12 -10
  154. qiskit/circuit/library/templates/nct/template_nct_9d_4.py +12 -10
  155. qiskit/circuit/library/templates/nct/template_nct_9d_5.py +12 -10
  156. qiskit/circuit/library/templates/nct/template_nct_9d_6.py +12 -10
  157. qiskit/circuit/library/templates/nct/template_nct_9d_7.py +12 -10
  158. qiskit/circuit/library/templates/nct/template_nct_9d_8.py +12 -10
  159. qiskit/circuit/library/templates/nct/template_nct_9d_9.py +12 -10
  160. qiskit/circuit/library/templates/rzx/rzx_cy.py +11 -10
  161. qiskit/circuit/library/templates/rzx/rzx_xz.py +16 -15
  162. qiskit/circuit/library/templates/rzx/rzx_yz.py +12 -10
  163. qiskit/circuit/library/templates/rzx/rzx_zz1.py +22 -20
  164. qiskit/circuit/library/templates/rzx/rzx_zz2.py +16 -15
  165. qiskit/circuit/library/templates/rzx/rzx_zz3.py +17 -15
  166. qiskit/circuit/parameter.py +4 -0
  167. qiskit/circuit/parameterexpression.py +167 -34
  168. qiskit/circuit/quantumcircuit.py +162 -126
  169. qiskit/circuit/singleton.py +2 -0
  170. qiskit/circuit/store.py +2 -0
  171. qiskit/circuit/twirling.py +145 -0
  172. qiskit/compiler/assembler.py +17 -4
  173. qiskit/compiler/scheduler.py +2 -0
  174. qiskit/compiler/sequencer.py +2 -0
  175. qiskit/compiler/transpiler.py +81 -26
  176. qiskit/converters/circuit_to_dag.py +2 -2
  177. qiskit/converters/circuit_to_dagdependency.py +1 -1
  178. qiskit/converters/circuit_to_dagdependency_v2.py +1 -1
  179. qiskit/converters/circuit_to_instruction.py +1 -1
  180. qiskit/converters/dag_to_circuit.py +7 -5
  181. qiskit/converters/dag_to_dagdependency.py +1 -1
  182. qiskit/converters/dag_to_dagdependency_v2.py +1 -1
  183. qiskit/converters/dagdependency_to_circuit.py +5 -1
  184. qiskit/converters/dagdependency_to_dag.py +6 -1
  185. qiskit/dagcircuit/collect_blocks.py +3 -3
  186. qiskit/dagcircuit/dagdependency.py +18 -5
  187. qiskit/dagcircuit/dagdependency_v2.py +1 -1
  188. qiskit/dagcircuit/dagnode.py +2 -2
  189. qiskit/passmanager/__init__.py +2 -2
  190. qiskit/primitives/backend_estimator.py +5 -2
  191. qiskit/primitives/backend_sampler_v2.py +61 -18
  192. qiskit/primitives/base/base_estimator.py +2 -2
  193. qiskit/primitives/containers/data_bin.py +9 -1
  194. qiskit/primitives/statevector_sampler.py +1 -1
  195. qiskit/primitives/utils.py +1 -1
  196. qiskit/providers/__init__.py +3 -3
  197. qiskit/providers/backend.py +12 -1
  198. qiskit/providers/backend_compat.py +23 -3
  199. qiskit/providers/basic_provider/basic_simulator.py +12 -2
  200. qiskit/providers/fake_provider/fake_pulse_backend.py +6 -1
  201. qiskit/providers/fake_provider/generic_backend_v2.py +46 -30
  202. qiskit/providers/models/pulsedefaults.py +2 -0
  203. qiskit/pulse/builder.py +59 -18
  204. qiskit/pulse/calibration_entries.py +4 -1
  205. qiskit/pulse/channels.py +2 -0
  206. qiskit/pulse/exceptions.py +2 -0
  207. qiskit/pulse/instruction_schedule_map.py +21 -6
  208. qiskit/pulse/instructions/acquire.py +2 -0
  209. qiskit/pulse/instructions/delay.py +2 -0
  210. qiskit/pulse/instructions/directives.py +8 -0
  211. qiskit/pulse/instructions/frequency.py +3 -0
  212. qiskit/pulse/instructions/instruction.py +2 -0
  213. qiskit/pulse/instructions/phase.py +3 -0
  214. qiskit/pulse/instructions/play.py +2 -0
  215. qiskit/pulse/instructions/reference.py +2 -0
  216. qiskit/pulse/instructions/snapshot.py +2 -0
  217. qiskit/pulse/library/pulse.py +2 -0
  218. qiskit/pulse/library/symbolic_pulses.py +28 -0
  219. qiskit/pulse/library/waveform.py +2 -0
  220. qiskit/pulse/macros.py +1 -1
  221. qiskit/pulse/schedule.py +12 -13
  222. qiskit/pulse/transforms/alignments.py +5 -3
  223. qiskit/pulse/transforms/dag.py +7 -0
  224. qiskit/qasm2/export.py +5 -3
  225. qiskit/qasm2/parse.py +46 -2
  226. qiskit/qasm3/__init__.py +1 -0
  227. qiskit/qasm3/ast.py +123 -15
  228. qiskit/qasm3/exporter.py +103 -77
  229. qiskit/qobj/converters/pulse_instruction.py +6 -4
  230. qiskit/qpy/__init__.py +181 -0
  231. qiskit/qpy/binary_io/circuits.py +20 -5
  232. qiskit/qpy/binary_io/schedules.py +3 -4
  233. qiskit/qpy/binary_io/value.py +310 -13
  234. qiskit/qpy/common.py +46 -2
  235. qiskit/qpy/formats.py +7 -0
  236. qiskit/qpy/interface.py +40 -4
  237. qiskit/quantum_info/__init__.py +4 -0
  238. qiskit/quantum_info/operators/channel/transformations.py +28 -21
  239. qiskit/quantum_info/operators/dihedral/dihedral.py +1 -1
  240. qiskit/quantum_info/operators/operator.py +54 -8
  241. qiskit/quantum_info/operators/symplectic/base_pauli.py +11 -19
  242. qiskit/quantum_info/operators/symplectic/clifford.py +1 -1
  243. qiskit/quantum_info/operators/symplectic/clifford_circuits.py +1 -1
  244. qiskit/quantum_info/operators/symplectic/pauli.py +2 -0
  245. qiskit/quantum_info/operators/symplectic/pauli_list.py +4 -4
  246. qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +23 -2
  247. qiskit/quantum_info/states/densitymatrix.py +5 -5
  248. qiskit/quantum_info/states/stabilizerstate.py +1 -1
  249. qiskit/quantum_info/states/statevector.py +6 -6
  250. qiskit/result/mitigation/base_readout_mitigator.py +1 -1
  251. qiskit/result/mitigation/correlated_readout_mitigator.py +9 -1
  252. qiskit/result/mitigation/local_readout_mitigator.py +9 -1
  253. qiskit/result/mitigation/utils.py +57 -0
  254. qiskit/scheduler/config.py +2 -0
  255. qiskit/scheduler/methods/basic.py +3 -0
  256. qiskit/scheduler/schedule_circuit.py +2 -0
  257. qiskit/scheduler/sequence.py +2 -0
  258. qiskit/synthesis/__init__.py +25 -0
  259. qiskit/synthesis/arithmetic/__init__.py +16 -0
  260. qiskit/synthesis/arithmetic/adders/__init__.py +17 -0
  261. qiskit/synthesis/arithmetic/adders/cdkm_ripple_carry_adder.py +154 -0
  262. qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +103 -0
  263. qiskit/synthesis/arithmetic/adders/vbe_ripple_carry_adder.py +161 -0
  264. qiskit/synthesis/arithmetic/multipliers/__init__.py +16 -0
  265. qiskit/synthesis/arithmetic/multipliers/hrs_cumulative_multiplier.py +102 -0
  266. qiskit/synthesis/arithmetic/multipliers/rg_qft_multiplier.py +99 -0
  267. qiskit/synthesis/clifford/clifford_decompose_bm.py +1 -2
  268. qiskit/synthesis/clifford/clifford_decompose_greedy.py +3 -2
  269. qiskit/synthesis/clifford/clifford_decompose_layers.py +2 -1
  270. qiskit/synthesis/evolution/__init__.py +1 -0
  271. qiskit/synthesis/evolution/lie_trotter.py +16 -42
  272. qiskit/synthesis/evolution/pauli_network.py +80 -0
  273. qiskit/synthesis/evolution/product_formula.py +165 -238
  274. qiskit/synthesis/evolution/qdrift.py +36 -29
  275. qiskit/synthesis/evolution/suzuki_trotter.py +87 -27
  276. qiskit/synthesis/multi_controlled/__init__.py +1 -0
  277. qiskit/synthesis/multi_controlled/mcmt_vchain.py +52 -0
  278. qiskit/synthesis/qft/qft_decompose_full.py +19 -1
  279. qiskit/synthesis/qft/qft_decompose_lnn.py +2 -1
  280. qiskit/synthesis/stabilizer/stabilizer_decompose.py +2 -1
  281. qiskit/synthesis/two_qubit/two_qubit_decompose.py +4 -63
  282. qiskit/synthesis/unitary/qsd.py +5 -5
  283. qiskit/transpiler/__init__.py +21 -14
  284. qiskit/transpiler/basepasses.py +1 -1
  285. qiskit/transpiler/passes/__init__.py +2 -0
  286. qiskit/transpiler/passes/basis/basis_translator.py +9 -565
  287. qiskit/transpiler/passes/basis/decompose.py +45 -12
  288. qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
  289. qiskit/transpiler/passes/basis/unroll_custom_definitions.py +1 -1
  290. qiskit/transpiler/passes/calibration/pulse_gate.py +4 -2
  291. qiskit/transpiler/passes/calibration/rx_builder.py +11 -7
  292. qiskit/transpiler/passes/calibration/rzx_builder.py +46 -30
  293. qiskit/transpiler/passes/layout/disjoint_utils.py +15 -13
  294. qiskit/transpiler/passes/layout/sabre_layout.py +7 -2
  295. qiskit/transpiler/passes/layout/sabre_pre_layout.py +5 -0
  296. qiskit/transpiler/passes/optimization/__init__.py +1 -0
  297. qiskit/transpiler/passes/optimization/collect_cliffords.py +19 -3
  298. qiskit/transpiler/passes/optimization/collect_linear_functions.py +1 -1
  299. qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +2 -2
  300. qiskit/transpiler/passes/optimization/commutative_inverse_cancellation.py +1 -1
  301. qiskit/transpiler/passes/optimization/consolidate_blocks.py +48 -131
  302. qiskit/transpiler/passes/optimization/echo_rzx_weyl_decomposition.py +4 -2
  303. qiskit/transpiler/passes/optimization/elide_permutations.py +9 -32
  304. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +5 -11
  305. qiskit/transpiler/passes/optimization/optimize_1q_gates.py +1 -1
  306. qiskit/transpiler/passes/optimization/optimize_swap_before_measure.py +1 -1
  307. qiskit/transpiler/passes/optimization/remove_identity_equiv.py +69 -0
  308. qiskit/transpiler/passes/optimization/template_matching/backward_match.py +5 -5
  309. qiskit/transpiler/passes/optimization/template_matching/forward_match.py +4 -4
  310. qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +2 -2
  311. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +1 -1
  312. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +1 -1
  313. qiskit/transpiler/passes/routing/sabre_swap.py +7 -3
  314. qiskit/transpiler/passes/routing/star_prerouting.py +2 -2
  315. qiskit/transpiler/passes/scheduling/alap.py +1 -1
  316. qiskit/transpiler/passes/scheduling/alignments/align_measures.py +2 -2
  317. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
  318. qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +2 -0
  319. qiskit/transpiler/passes/scheduling/alignments/reschedule.py +2 -2
  320. qiskit/transpiler/passes/scheduling/asap.py +1 -1
  321. qiskit/transpiler/passes/scheduling/base_scheduler.py +14 -12
  322. qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +9 -4
  323. qiskit/transpiler/passes/scheduling/padding/base_padding.py +1 -1
  324. qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +16 -5
  325. qiskit/transpiler/passes/scheduling/padding/pad_delay.py +4 -1
  326. qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +6 -2
  327. qiskit/transpiler/passes/scheduling/time_unit_conversion.py +9 -4
  328. qiskit/transpiler/passes/synthesis/high_level_synthesis.py +262 -99
  329. qiskit/transpiler/passes/synthesis/hls_plugins.py +637 -7
  330. qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +3 -3
  331. qiskit/transpiler/passes/synthesis/unitary_synthesis.py +55 -34
  332. qiskit/transpiler/passes/utils/barrier_before_final_measurements.py +2 -56
  333. qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +5 -0
  334. qiskit/transpiler/passes/utils/gate_direction.py +12 -275
  335. qiskit/transpiler/passes/utils/gates_basis.py +7 -30
  336. qiskit/transpiler/passes/utils/merge_adjacent_barriers.py +2 -1
  337. qiskit/transpiler/passmanager_config.py +22 -4
  338. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +40 -14
  339. qiskit/transpiler/preset_passmanagers/common.py +5 -3
  340. qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +125 -42
  341. qiskit/transpiler/preset_passmanagers/plugin.py +1 -1
  342. qiskit/transpiler/target.py +74 -16
  343. qiskit/utils/deprecate_pulse.py +119 -0
  344. qiskit/visualization/circuit/_utils.py +2 -2
  345. qiskit/visualization/circuit/circuit_visualization.py +3 -2
  346. qiskit/visualization/circuit/matplotlib.py +1 -1
  347. qiskit/visualization/dag_visualization.py +1 -1
  348. qiskit/visualization/pass_manager_visualization.py +3 -14
  349. qiskit/visualization/pulse_v2/interface.py +3 -1
  350. qiskit/visualization/timeline/core.py +25 -2
  351. qiskit/visualization/timeline/interface.py +12 -0
  352. {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/METADATA +9 -8
  353. {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/RECORD +357 -346
  354. {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/WHEEL +1 -1
  355. {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/entry_points.txt +19 -0
  356. qiskit/circuit/library/data_preparation/zz_feature_map.py +0 -118
  357. qiskit/synthesis/two_qubit/weyl.py +0 -97
  358. qiskit/transpiler/passes/synthesis/qubit_tracker.py +0 -132
  359. {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/LICENSE.txt +0 -0
  360. {qiskit-1.3.0b1.dist-info → qiskit-1.3.0rc2.dist-info}/top_level.txt +0 -0
@@ -14,14 +14,14 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
+ import warnings
17
18
  from collections.abc import Callable
18
19
 
19
20
  from qiskit import circuit
20
- from qiskit.circuit import ControlledGate, Gate, QuantumRegister, QuantumCircuit
21
- from qiskit.exceptions import QiskitError
22
-
23
- # pylint: disable=cyclic-import
24
- from ..standard_gates import XGate, YGate, ZGate, HGate, TGate, TdgGate, SGate, SdgGate
21
+ from qiskit.circuit import ControlledGate, Gate, QuantumCircuit
22
+ from qiskit.circuit._utils import _ctrl_state_to_int
23
+ from qiskit.utils.deprecation import deprecate_func
24
+ from ..standard_gates import get_standard_gate_name_mapping
25
25
 
26
26
 
27
27
  class MCMT(QuantumCircuit):
@@ -29,7 +29,7 @@ class MCMT(QuantumCircuit):
29
29
 
30
30
  For example, the H gate controlled on 3 qubits and acting on 2 target qubit is represented as:
31
31
 
32
- .. parsed-literal::
32
+ .. code-block:: text
33
33
 
34
34
  ───■────
35
35
 
@@ -49,6 +49,7 @@ class MCMT(QuantumCircuit):
49
49
  :class:`~qiskit.circuit.library.MCMTVChain`.
50
50
  """
51
51
 
52
+ @deprecate_func(since="1.3", additional_msg="Use MCMTGate instead.", pending=True)
52
53
  def __init__(
53
54
  self,
54
55
  gate: Gate | Callable[[QuantumCircuit, circuit.Qubit, circuit.Qubit], circuit.Instruction],
@@ -71,77 +72,41 @@ class MCMT(QuantumCircuit):
71
72
  if num_ctrl_qubits == 0 or num_target_qubits == 0:
72
73
  raise AttributeError("Need at least one control and one target qubit.")
73
74
 
74
- # set the internal properties and determine the number of qubits
75
- self.gate = self._identify_gate(gate)
75
+ if callable(gate):
76
+ warnings.warn(
77
+ "Passing a callable to MCMT is pending deprecation since Qiskit 1.3. Pass a "
78
+ "gate instance or the gate name instead, e.g. pass 'h' instead of QuantumCircuit.h.",
79
+ category=PendingDeprecationWarning,
80
+ stacklevel=2,
81
+ )
82
+ gate = gate.__name__
83
+ elif isinstance(gate, QuantumCircuit):
84
+ warnings.warn(
85
+ "Passing a QuantumCircuit is pending deprecation since Qiskit 1.3. Pass a gate "
86
+ "or turn the circuit into a gate using the ``to_gate`` method, instead.",
87
+ category=PendingDeprecationWarning,
88
+ stacklevel=2,
89
+ )
90
+ gate = gate.to_gate()
91
+
92
+ self.gate = MCMTGate._identify_base_gate(gate)
76
93
  self.num_ctrl_qubits = num_ctrl_qubits
77
94
  self.num_target_qubits = num_target_qubits
78
- num_qubits = num_ctrl_qubits + num_target_qubits + self.num_ancilla_qubits
79
95
 
80
96
  # initialize the circuit object
97
+ num_qubits = num_ctrl_qubits + num_target_qubits + self.num_ancilla_qubits
81
98
  super().__init__(num_qubits, name="mcmt")
82
- self._label = f"{num_target_qubits}-{self.gate.name.capitalize()}"
83
-
84
- # build the circuit
85
99
  self._build()
86
100
 
87
101
  def _build(self):
88
- """Define the MCMT gate without ancillas."""
89
- if self.num_target_qubits == 1:
90
- # no broadcasting needed (makes for better circuit diagrams)
91
- broadcasted_gate = self.gate
92
- else:
93
- broadcasted = QuantumCircuit(self.num_target_qubits, name=self._label)
94
- for target in list(range(self.num_target_qubits)):
95
- broadcasted.append(self.gate, [target], [])
96
- broadcasted_gate = broadcasted.to_gate()
97
-
98
- mcmt_gate = broadcasted_gate.control(self.num_ctrl_qubits)
99
- self.append(mcmt_gate, self.qubits, [])
102
+ gate = MCMTGate(self.gate, self.num_ctrl_qubits, self.num_target_qubits)
103
+ self.append(gate, self.qubits)
100
104
 
101
105
  @property
102
106
  def num_ancilla_qubits(self):
103
107
  """Return the number of ancillas."""
104
108
  return 0
105
109
 
106
- def _identify_gate(self, gate):
107
- """Case the gate input to a gate."""
108
- valid_gates = {
109
- "ch": HGate(),
110
- "cx": XGate(),
111
- "cy": YGate(),
112
- "cz": ZGate(),
113
- "h": HGate(),
114
- "s": SGate(),
115
- "sdg": SdgGate(),
116
- "x": XGate(),
117
- "y": YGate(),
118
- "z": ZGate(),
119
- "t": TGate(),
120
- "tdg": TdgGate(),
121
- }
122
- if isinstance(gate, ControlledGate):
123
- base_gate = gate.base_gate
124
- elif isinstance(gate, Gate):
125
- if gate.num_qubits != 1:
126
- raise AttributeError("Base gate must act on one qubit only.")
127
- base_gate = gate
128
- elif isinstance(gate, QuantumCircuit):
129
- if gate.num_qubits != 1:
130
- raise AttributeError(
131
- "The circuit you specified as control gate can only have one qubit!"
132
- )
133
- base_gate = gate.to_gate() # raises error if circuit contains non-unitary instructions
134
- else:
135
- if callable(gate): # identify via name of the passed function
136
- name = gate.__name__
137
- elif isinstance(gate, str):
138
- name = gate
139
- else:
140
- raise AttributeError(f"Invalid gate specified: {gate}")
141
- base_gate = valid_gates[name]
142
-
143
- return base_gate
144
-
145
110
  def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None, annotated=False):
146
111
  """Return the controlled version of the MCMT circuit."""
147
112
  if not annotated and ctrl_state is None:
@@ -191,66 +156,161 @@ class MCMTVChain(MCMT):
191
156
  └───┘ └───┘
192
157
  """
193
158
 
159
+ @deprecate_func(
160
+ since="1.3",
161
+ additional_msg="Use MCMTGate with the V-chain synthesis plugin instead.",
162
+ pending=True,
163
+ )
164
+ def __init__(
165
+ self,
166
+ gate: Gate | Callable[[QuantumCircuit, circuit.Qubit, circuit.Qubit], circuit.Instruction],
167
+ num_ctrl_qubits: int,
168
+ num_target_qubits: int,
169
+ ) -> None:
170
+ super().__init__(gate, num_ctrl_qubits, num_target_qubits)
171
+
194
172
  def _build(self):
195
- """Define the MCMT gate."""
196
- control_qubits = self.qubits[: self.num_ctrl_qubits]
197
- target_qubits = self.qubits[
198
- self.num_ctrl_qubits : self.num_ctrl_qubits + self.num_target_qubits
199
- ]
200
- ancilla_qubits = self.qubits[self.num_ctrl_qubits + self.num_target_qubits :]
201
-
202
- if len(ancilla_qubits) > 0:
203
- master_control = ancilla_qubits[-1]
204
- else:
205
- master_control = control_qubits[0]
173
+ # pylint: disable=cyclic-import
174
+ from qiskit.synthesis.multi_controlled import synth_mcmt_vchain
206
175
 
207
- self._ccx_v_chain_rule(control_qubits, ancilla_qubits, reverse=False)
208
- for qubit in target_qubits:
209
- self.append(self.gate.control(), [master_control, qubit], [])
210
- self._ccx_v_chain_rule(control_qubits, ancilla_qubits, reverse=True)
176
+ synthesized = synth_mcmt_vchain(self.gate, self.num_ctrl_qubits, self.num_target_qubits)
177
+ self.compose(synthesized, inplace=True, copy=False)
211
178
 
212
179
  @property
213
180
  def num_ancilla_qubits(self):
214
181
  """Return the number of ancilla qubits required."""
215
182
  return max(0, self.num_ctrl_qubits - 1)
216
183
 
217
- def _ccx_v_chain_rule(
184
+ def inverse(self, annotated: bool = False):
185
+ return MCMTVChain(self.gate, self.num_ctrl_qubits, self.num_target_qubits)
186
+
187
+
188
+ class MCMTGate(ControlledGate):
189
+ """The multi-controlled multi-target gate, for an arbitrary singly controlled target gate.
190
+
191
+ For example, the H gate controlled on 3 qubits and acting on 2 target qubit is represented as:
192
+
193
+ .. parsed-literal::
194
+
195
+ ───■────
196
+
197
+ ───■────
198
+
199
+ ───■────
200
+ ┌──┴───┐
201
+ ┤0 ├
202
+ │ 2-H │
203
+ ┤1 ├
204
+ └──────┘
205
+
206
+ Depending on the number of available auxiliary qubits, this operation can be synthesized
207
+ using different methods. For example, if :math:`n - 1` clean auxiliary qubits are available
208
+ (where :math:`n` is the number of control qubits), a V-chain decomposition can be used whose
209
+ depth is linear in :math:`n`. See also :func:`.synth_mcmt_chain`.
210
+ """
211
+
212
+ def __init__(
218
213
  self,
219
- control_qubits: QuantumRegister | list[circuit.Qubit],
220
- ancilla_qubits: QuantumRegister | list[circuit.Qubit],
221
- reverse: bool = False,
214
+ gate: Gate,
215
+ num_ctrl_qubits: int,
216
+ num_target_qubits: int,
217
+ ctrl_state: int | str | None = None,
218
+ label: str | None = None,
222
219
  ) -> None:
223
- """Get the rule for the CCX V-chain.
220
+ """
221
+ Args:
222
+ gate: The base gate to apply on multiple target qubits, controlled by other qubits.
223
+ This must be a single-qubit gate or a controlled single-qubit gate.
224
+ num_ctrl_qubits: The number of control qubits.
225
+ num_target_qubits: The number of target qubits.
226
+ ctrl_state: The control state of the control qubits. Defaults to all closed controls.
227
+ label: The gate label.
228
+ """
229
+ if num_target_qubits < 1:
230
+ raise ValueError("Need at least one target qubit.")
224
231
 
225
- The CCX V-chain progressively computes the CCX of the control qubits and puts the final
226
- result in the last ancillary qubit.
232
+ if num_ctrl_qubits < 1:
233
+ raise ValueError("Need at least one control qubit.")
227
234
 
228
- Args:
229
- control_qubits: The control qubits.
230
- ancilla_qubits: The ancilla qubits.
231
- reverse: If True, compute the chain down to the qubit. If False, compute upwards.
235
+ self.num_target_qubits = num_target_qubits
232
236
 
233
- Returns:
234
- The rule for the (reversed) CCX V-chain.
237
+ base_gate = self._identify_base_gate(gate)
238
+ num_qubits = num_ctrl_qubits + num_target_qubits
239
+
240
+ if label is None:
241
+ label = f"{num_target_qubits}-{gate.name.capitalize()}"
242
+
243
+ super().__init__(
244
+ "mcmt",
245
+ base_gate=base_gate,
246
+ num_qubits=num_qubits,
247
+ params=gate.params,
248
+ num_ctrl_qubits=num_ctrl_qubits,
249
+ ctrl_state=ctrl_state,
250
+ label=label,
251
+ )
252
+
253
+ def _define(self):
254
+ """Default definition relying on gate.control. Control state is handled by superclass."""
255
+ # pylint: disable=cyclic-import
256
+ from qiskit.transpiler.passes.synthesis.hls_plugins import MCMTSynthesisDefault
257
+
258
+ self.definition = MCMTSynthesisDefault().run(self)
259
+
260
+ @staticmethod
261
+ def _identify_base_gate(gate):
262
+ """Get the control base gate. Note this must be a single qubit gate."""
263
+
264
+ # try getting the standard name from the string
265
+ if isinstance(gate, str):
266
+ standard_gates = get_standard_gate_name_mapping()
267
+ if gate in standard_gates:
268
+ gate = standard_gates[gate]
269
+ else:
270
+ raise AttributeError(
271
+ f"Unknown gate {gate}. Available: {list(get_standard_gate_name_mapping.keys())}"
272
+ )
235
273
 
236
- Raises:
237
- QiskitError: If an insufficient number of ancilla qubits was provided.
238
- """
239
- if len(ancilla_qubits) == 0:
240
- return
274
+ # extract the base gate
275
+ if isinstance(gate, ControlledGate):
276
+ warnings.warn(
277
+ "Passing a controlled gate to MCMT is pending deprecation since Qiskit 1.3. Pass a "
278
+ "single-qubit gate instance or the gate name instead, e.g. pass 'h' instead of 'ch'.",
279
+ category=PendingDeprecationWarning,
280
+ stacklevel=2,
281
+ )
282
+ base_gate = gate.base_gate
283
+ elif isinstance(gate, Gate):
284
+ base_gate = gate
285
+ else:
286
+ raise TypeError(f"Invalid gate type {type(gate)}.")
287
+
288
+ if base_gate.num_qubits != 1:
289
+ raise ValueError(
290
+ f"MCMTGate requires a base gate with a single qubit, but got {base_gate.num_qubits}."
291
+ )
241
292
 
242
- if len(ancilla_qubits) < len(control_qubits) - 1:
243
- raise QiskitError("Insufficient number of ancilla qubits.")
293
+ return base_gate
244
294
 
245
- iterations = list(enumerate(range(2, len(control_qubits))))
246
- if not reverse:
247
- self.ccx(control_qubits[0], control_qubits[1], ancilla_qubits[0])
248
- for i, j in iterations:
249
- self.ccx(control_qubits[j], ancilla_qubits[i], ancilla_qubits[i + 1])
295
+ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None, annotated=False):
296
+ """Return the controlled version of the MCMT circuit."""
297
+ if not annotated:
298
+ ctrl_state = _ctrl_state_to_int(ctrl_state, num_ctrl_qubits)
299
+ new_ctrl_state = (self.ctrl_state << num_ctrl_qubits) | ctrl_state
300
+
301
+ gate = MCMTGate(
302
+ self.base_gate,
303
+ self.num_ctrl_qubits + num_ctrl_qubits,
304
+ self.num_target_qubits,
305
+ ctrl_state=new_ctrl_state,
306
+ )
250
307
  else:
251
- for i, j in reversed(iterations):
252
- self.ccx(control_qubits[j], ancilla_qubits[i], ancilla_qubits[i + 1])
253
- self.ccx(control_qubits[0], control_qubits[1], ancilla_qubits[0])
308
+ gate = super().control(num_ctrl_qubits, label, ctrl_state, annotated=annotated)
309
+
310
+ return gate
254
311
 
255
312
  def inverse(self, annotated: bool = False):
256
- return MCMTVChain(self.gate, self.num_ctrl_qubits, self.num_target_qubits)
313
+ """Return the inverse MCMT circuit."""
314
+ return MCMTGate(
315
+ self.base_gate.inverse(), self.num_ctrl_qubits, self.num_target_qubits, self.ctrl_state
316
+ )
@@ -22,11 +22,13 @@ import numpy as np
22
22
  from qiskit.circuit.quantumcircuit import QuantumCircuit
23
23
  from qiskit.circuit.quantumcircuit import Gate
24
24
  from qiskit.circuit.exceptions import CircuitError
25
+ from qiskit.utils.deprecation import deprecate_func
25
26
 
26
27
 
27
28
  class Permutation(QuantumCircuit):
28
29
  """An n_qubit circuit that permutes qubits."""
29
30
 
31
+ @deprecate_func(since="1.3", pending=True, additional_msg="Use PermutationGate instead.")
30
32
  def __init__(
31
33
  self,
32
34
  num_qubits: int,
@@ -117,11 +119,11 @@ class PermutationGate(Gate):
117
119
 
118
120
  from qiskit.circuit.quantumcircuit import QuantumCircuit
119
121
  from qiskit.circuit.library import PermutationGate
120
- A = [2,4,3,0,1]
122
+ A = [2, 4, 3, 0, 1]
121
123
  permutation = PermutationGate(A)
122
124
  circuit = QuantumCircuit(5)
123
125
  circuit.append(permutation, [0, 1, 2, 3, 4])
124
- circuit.draw('mpl')
126
+ circuit.draw("mpl")
125
127
 
126
128
  Expanded Circuit:
127
129
  .. plot::
@@ -129,7 +131,7 @@ class PermutationGate(Gate):
129
131
  from qiskit.circuit.quantumcircuit import QuantumCircuit
130
132
  from qiskit.circuit.library import PermutationGate
131
133
  from qiskit.visualization.library import _generate_circuit_library_visualization
132
- A = [2,4,3,0,1]
134
+ A = [2, 4, 3, 0, 1]
133
135
  permutation = PermutationGate(A)
134
136
  circuit = QuantumCircuit(5)
135
137
  circuit.append(permutation, [0, 1, 2, 3, 4])
@@ -141,7 +143,7 @@ class PermutationGate(Gate):
141
143
  raise CircuitError(
142
144
  "Permutation pattern must be some ordering of 0..num_qubits-1 in a list."
143
145
  )
144
- pattern = np.array(pattern)
146
+ pattern = np.array(pattern, dtype=np.int32)
145
147
 
146
148
  super().__init__(name="permutation", num_qubits=num_qubits, params=[pattern])
147
149
 
@@ -168,11 +170,11 @@ class PermutationGate(Gate):
168
170
  return parameter
169
171
 
170
172
  @property
171
- def pattern(self):
173
+ def pattern(self) -> np.ndarray[bool]:
172
174
  """Returns the permutation pattern defining this permutation."""
173
175
  return self.params[0]
174
176
 
175
- def inverse(self, annotated: bool = False):
177
+ def inverse(self, annotated: bool = False) -> PermutationGate:
176
178
  """Returns the inverse of the permutation."""
177
179
 
178
180
  # pylint: disable=cyclic-import
@@ -27,7 +27,7 @@ class RVGate(Gate):
27
27
 
28
28
  **Circuit symbol:**
29
29
 
30
- .. parsed-literal::
30
+ .. code-block:: text
31
31
 
32
32
  ┌─────────────────┐
33
33
  q_0: ┤ RV(v_x,v_y,v_z) ├
@@ -51,14 +51,13 @@ class RVGate(Gate):
51
51
  \end{pmatrix}
52
52
  """
53
53
 
54
- def __init__(self, v_x, v_y, v_z, basis="U"):
55
- """Create new rv single-qubit gate.
56
-
54
+ def __init__(self, v_x: float, v_y: float, v_z: float, basis: str = "U"):
55
+ """
57
56
  Args:
58
- v_x (float): x-component
59
- v_y (float): y-component
60
- v_z (float): z-component
61
- basis (str, optional): basis (see
57
+ v_x: x-component
58
+ v_y: y-component
59
+ v_z: z-component
60
+ basis: basis (see
62
61
  :class:`~qiskit.synthesis.one_qubit.one_qubit_decompose.OneQubitEulerDecomposer`)
63
62
  """
64
63
  # pylint: disable=cyclic-import
@@ -80,7 +79,7 @@ class RVGate(Gate):
80
79
  vx, vy, vz = self.params
81
80
  return RVGate(-vx, -vy, -vz)
82
81
 
83
- def to_matrix(self):
82
+ def to_matrix(self) -> numpy.ndarray:
84
83
  """Return a numpy.array for the R(v) gate."""
85
84
  v = numpy.asarray(self.params, dtype=float)
86
85
  angle = math.sqrt(v.dot(v))
@@ -1,6 +1,6 @@
1
1
  # This code is part of Qiskit.
2
2
  #
3
- # (C) Copyright IBM 2017, 2020.
3
+ # (C) Copyright IBM 2017, 2024.
4
4
  #
5
5
  # This code is licensed under the Apache License, Version 2.0. You may
6
6
  # obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -10,13 +10,14 @@
10
10
  # copyright notice, and modified files need to carry a notice indicating
11
11
  # that they have been altered from the originals.
12
12
 
13
- """Graph State circuit."""
13
+ """Graph State circuit and gate."""
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
17
  import numpy as np
18
- from qiskit.circuit.quantumcircuit import QuantumCircuit
18
+ from qiskit.circuit.quantumcircuit import QuantumCircuit, Gate
19
19
  from qiskit.circuit.exceptions import CircuitError
20
+ from qiskit.utils.deprecation import deprecate_func
20
21
 
21
22
 
22
23
  class GraphState(QuantumCircuit):
@@ -56,6 +57,11 @@ class GraphState(QuantumCircuit):
56
57
  `arXiv:1512.07892 <https://arxiv.org/pdf/1512.07892.pdf>`_
57
58
  """
58
59
 
60
+ @deprecate_func(
61
+ since="1.3",
62
+ additional_msg="Use qiskit.circuit.library.GraphStateGate instead.",
63
+ pending=True,
64
+ )
59
65
  def __init__(self, adjacency_matrix: list | np.ndarray) -> None:
60
66
  """Create graph state preparation circuit.
61
67
 
@@ -73,14 +79,91 @@ class GraphState(QuantumCircuit):
73
79
  if not np.allclose(adjacency_matrix, adjacency_matrix.transpose()):
74
80
  raise CircuitError("The adjacency matrix must be symmetric.")
75
81
 
82
+ graph_state_gate = GraphStateGate(adjacency_matrix)
83
+ super().__init__(graph_state_gate.num_qubits, name=f"graph: {adjacency_matrix}")
84
+ self.compose(graph_state_gate, qubits=self.qubits, inplace=True)
85
+
86
+
87
+ class GraphStateGate(Gate):
88
+ r"""A gate representing a graph state.
89
+
90
+ Given a graph G = (V, E), with the set of vertices V and the set of edges E,
91
+ the corresponding graph state is defined as
92
+
93
+ .. math::
94
+
95
+ |G\rangle = \prod_{(a,b) \in E} CZ_{(a,b)} {|+\rangle}^{\otimes V}
96
+
97
+ Such a state can be prepared by first preparing all qubits in the :math:`+`
98
+ state, then applying a :math:`CZ` gate for each corresponding graph edge.
99
+
100
+ Graph state preparation circuits are Clifford circuits, and thus
101
+ easy to simulate classically. However, by adding a layer of measurements
102
+ in a product basis at the end, there is evidence that the circuit becomes
103
+ hard to simulate [2].
104
+
105
+ **Reference Circuit:**
106
+
107
+ .. plot::
108
+ :include-source:
109
+
110
+ from qiskit.circuit import QuantumCircuit
111
+ from qiskit.circuit.library import GraphStateGate
112
+ import rustworkx as rx
113
+
114
+ G = rx.generators.cycle_graph(5)
115
+ circuit = QuantumCircuit(5)
116
+ circuit.append(GraphStateGate(rx.adjacency_matrix(G)), [0, 1, 2, 3, 4])
117
+ circuit.decompose().draw('mpl')
118
+
119
+ **References:**
120
+
121
+ [1] M. Hein, J. Eisert, H.J. Briegel, Multi-party Entanglement in Graph States,
122
+ `arXiv:0307130 <https://arxiv.org/pdf/quant-ph/0307130.pdf>`_
123
+ [2] D. Koh, Further Extensions of Clifford Circuits & their Classical Simulation Complexities.
124
+ `arXiv:1512.07892 <https://arxiv.org/pdf/1512.07892.pdf>`_
125
+ """
126
+
127
+ def __init__(self, adjacency_matrix: list | np.ndarray) -> None:
128
+ """
129
+ Args:
130
+ adjacency_matrix: input graph as n-by-n list of 0-1 lists
131
+
132
+ Raises:
133
+ CircuitError: If adjacency_matrix is not symmetric.
134
+
135
+ The gate represents a graph state with the given adjacency matrix.
136
+ """
137
+
138
+ adjacency_matrix = np.asarray(adjacency_matrix)
139
+ if not np.allclose(adjacency_matrix, adjacency_matrix.transpose()):
140
+ raise CircuitError("The adjacency matrix must be symmetric.")
76
141
  num_qubits = len(adjacency_matrix)
77
- circuit = QuantumCircuit(num_qubits, name=f"graph: {adjacency_matrix}")
78
142
 
79
- circuit.h(range(num_qubits))
80
- for i in range(num_qubits):
81
- for j in range(i + 1, num_qubits):
143
+ super().__init__(name="graph_state", num_qubits=num_qubits, params=[adjacency_matrix])
144
+
145
+ def _define(self):
146
+ adjacency_matrix = self.adjacency_matrix
147
+ circuit = QuantumCircuit(self.num_qubits, name=self.name)
148
+ circuit.h(range(self.num_qubits))
149
+ for i in range(self.num_qubits):
150
+ for j in range(i + 1, self.num_qubits):
82
151
  if adjacency_matrix[i][j] == 1:
83
152
  circuit.cz(i, j)
84
-
85
- super().__init__(*circuit.qregs, name=circuit.name)
86
- self.compose(circuit.to_gate(), qubits=self.qubits, inplace=True)
153
+ self.definition = circuit
154
+
155
+ def validate_parameter(self, parameter):
156
+ """Parameter validation"""
157
+ return parameter
158
+
159
+ @property
160
+ def adjacency_matrix(self):
161
+ """Returns the adjacency matrix."""
162
+ return self.params[0]
163
+
164
+ def __eq__(self, other):
165
+ return (
166
+ isinstance(other, GraphStateGate)
167
+ and self.num_qubits == other.num_qubits
168
+ and np.all(self.adjacency_matrix == other.adjacency_matrix)
169
+ )