qiskit 1.1.1__cp38-abi3-macosx_11_0_arm64.whl → 1.2.0__cp38-abi3-macosx_11_0_arm64.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 (347) hide show
  1. qiskit/VERSION.txt +1 -1
  2. qiskit/__init__.py +27 -24
  3. qiskit/_accelerate.abi3.so +0 -0
  4. qiskit/_numpy_compat.py +1 -1
  5. qiskit/assembler/assemble_circuits.py +107 -64
  6. qiskit/assembler/assemble_schedules.py +5 -12
  7. qiskit/assembler/disassemble.py +10 -1
  8. qiskit/circuit/__init__.py +6 -3
  9. qiskit/circuit/_classical_resource_map.py +5 -5
  10. qiskit/circuit/_utils.py +0 -13
  11. qiskit/circuit/add_control.py +1 -1
  12. qiskit/circuit/annotated_operation.py +23 -1
  13. qiskit/circuit/classical/expr/expr.py +4 -4
  14. qiskit/circuit/classical/expr/visitors.py +1 -1
  15. qiskit/circuit/classical/types/__init__.py +1 -1
  16. qiskit/circuit/classical/types/types.py +2 -2
  17. qiskit/circuit/classicalfunction/__init__.py +8 -0
  18. qiskit/circuit/classicalfunction/boolean_expression.py +1 -1
  19. qiskit/circuit/classicalfunction/classical_function_visitor.py +5 -5
  20. qiskit/circuit/classicalfunction/utils.py +1 -1
  21. qiskit/circuit/classicalregister.py +1 -1
  22. qiskit/circuit/commutation_checker.py +83 -35
  23. qiskit/circuit/controlflow/_builder_utils.py +1 -1
  24. qiskit/circuit/controlflow/builder.py +10 -6
  25. qiskit/circuit/controlflow/if_else.py +2 -2
  26. qiskit/circuit/controlflow/switch_case.py +1 -1
  27. qiskit/circuit/delay.py +1 -1
  28. qiskit/circuit/duration.py +2 -2
  29. qiskit/circuit/equivalence.py +5 -7
  30. qiskit/circuit/gate.py +11 -8
  31. qiskit/circuit/instruction.py +31 -13
  32. qiskit/circuit/instructionset.py +2 -5
  33. qiskit/circuit/library/__init__.py +2 -1
  34. qiskit/circuit/library/arithmetic/linear_amplitude_function.py +1 -1
  35. qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +1 -1
  36. qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +1 -1
  37. qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +1 -1
  38. qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +3 -3
  39. qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py +1 -1
  40. qiskit/circuit/library/basis_change/__init__.py +1 -1
  41. qiskit/circuit/library/basis_change/qft.py +40 -6
  42. qiskit/circuit/library/blueprintcircuit.py +3 -5
  43. qiskit/circuit/library/data_preparation/__init__.py +9 -2
  44. qiskit/circuit/library/data_preparation/initializer.py +8 -0
  45. qiskit/circuit/library/data_preparation/state_preparation.py +98 -178
  46. qiskit/circuit/library/generalized_gates/isometry.py +8 -8
  47. qiskit/circuit/library/generalized_gates/linear_function.py +3 -2
  48. qiskit/circuit/library/generalized_gates/mcg_up_to_diagonal.py +4 -4
  49. qiskit/circuit/library/generalized_gates/permutation.py +8 -9
  50. qiskit/circuit/library/generalized_gates/uc.py +3 -3
  51. qiskit/circuit/library/generalized_gates/uc_pauli_rot.py +2 -2
  52. qiskit/circuit/library/generalized_gates/unitary.py +13 -11
  53. qiskit/circuit/library/graph_state.py +1 -1
  54. qiskit/circuit/library/hamiltonian_gate.py +1 -2
  55. qiskit/circuit/library/hidden_linear_function.py +1 -1
  56. qiskit/circuit/library/n_local/evolved_operator_ansatz.py +3 -2
  57. qiskit/circuit/library/n_local/n_local.py +4 -5
  58. qiskit/circuit/library/n_local/pauli_two_design.py +1 -1
  59. qiskit/circuit/library/n_local/qaoa_ansatz.py +6 -8
  60. qiskit/circuit/library/n_local/two_local.py +1 -1
  61. qiskit/circuit/library/overlap.py +11 -5
  62. qiskit/circuit/library/pauli_evolution.py +7 -3
  63. qiskit/circuit/library/standard_gates/dcx.py +3 -0
  64. qiskit/circuit/library/standard_gates/ecr.py +3 -0
  65. qiskit/circuit/library/standard_gates/global_phase.py +3 -0
  66. qiskit/circuit/library/standard_gates/h.py +13 -5
  67. qiskit/circuit/library/standard_gates/i.py +3 -0
  68. qiskit/circuit/library/standard_gates/iswap.py +3 -0
  69. qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +19 -10
  70. qiskit/circuit/library/standard_gates/p.py +14 -9
  71. qiskit/circuit/library/standard_gates/r.py +3 -0
  72. qiskit/circuit/library/standard_gates/rx.py +21 -6
  73. qiskit/circuit/library/standard_gates/rxx.py +40 -1
  74. qiskit/circuit/library/standard_gates/ry.py +21 -6
  75. qiskit/circuit/library/standard_gates/ryy.py +40 -1
  76. qiskit/circuit/library/standard_gates/rz.py +22 -6
  77. qiskit/circuit/library/standard_gates/rzx.py +40 -1
  78. qiskit/circuit/library/standard_gates/rzz.py +41 -2
  79. qiskit/circuit/library/standard_gates/s.py +77 -0
  80. qiskit/circuit/library/standard_gates/swap.py +12 -5
  81. qiskit/circuit/library/standard_gates/sx.py +14 -5
  82. qiskit/circuit/library/standard_gates/t.py +5 -0
  83. qiskit/circuit/library/standard_gates/u.py +22 -7
  84. qiskit/circuit/library/standard_gates/u1.py +8 -3
  85. qiskit/circuit/library/standard_gates/u2.py +3 -0
  86. qiskit/circuit/library/standard_gates/u3.py +22 -7
  87. qiskit/circuit/library/standard_gates/x.py +158 -92
  88. qiskit/circuit/library/standard_gates/xx_minus_yy.py +40 -1
  89. qiskit/circuit/library/standard_gates/xx_plus_yy.py +52 -11
  90. qiskit/circuit/library/standard_gates/y.py +6 -1
  91. qiskit/circuit/library/standard_gates/z.py +8 -1
  92. qiskit/circuit/operation.py +1 -1
  93. qiskit/circuit/parameter.py +9 -10
  94. qiskit/circuit/parameterexpression.py +16 -13
  95. qiskit/circuit/parametertable.py +1 -190
  96. qiskit/circuit/parametervector.py +1 -1
  97. qiskit/circuit/quantumcircuit.py +395 -385
  98. qiskit/circuit/quantumcircuitdata.py +3 -5
  99. qiskit/circuit/quantumregister.py +1 -1
  100. qiskit/circuit/random/__init__.py +1 -1
  101. qiskit/circuit/random/utils.py +175 -26
  102. qiskit/circuit/register.py +5 -7
  103. qiskit/circuit/singleton.py +3 -3
  104. qiskit/circuit/tools/pi_check.py +4 -4
  105. qiskit/compiler/assembler.py +95 -24
  106. qiskit/compiler/scheduler.py +2 -2
  107. qiskit/compiler/transpiler.py +42 -128
  108. qiskit/converters/circuit_to_dag.py +4 -6
  109. qiskit/converters/circuit_to_gate.py +4 -8
  110. qiskit/converters/circuit_to_instruction.py +5 -17
  111. qiskit/converters/dag_to_circuit.py +2 -6
  112. qiskit/dagcircuit/collect_blocks.py +2 -2
  113. qiskit/dagcircuit/dagcircuit.py +197 -187
  114. qiskit/dagcircuit/dagdependency.py +4 -4
  115. qiskit/dagcircuit/dagdependency_v2.py +4 -4
  116. qiskit/dagcircuit/dagdepnode.py +1 -1
  117. qiskit/dagcircuit/dagnode.py +66 -157
  118. qiskit/passmanager/flow_controllers.py +1 -1
  119. qiskit/passmanager/passmanager.py +3 -3
  120. qiskit/primitives/__init__.py +1 -5
  121. qiskit/primitives/backend_estimator.py +25 -15
  122. qiskit/primitives/backend_estimator_v2.py +31 -7
  123. qiskit/primitives/backend_sampler.py +21 -12
  124. qiskit/primitives/backend_sampler_v2.py +12 -3
  125. qiskit/primitives/base/base_estimator.py +31 -4
  126. qiskit/primitives/base/base_primitive.py +2 -2
  127. qiskit/primitives/base/base_result.py +2 -2
  128. qiskit/primitives/base/base_sampler.py +26 -2
  129. qiskit/primitives/base/estimator_result.py +2 -2
  130. qiskit/primitives/base/sampler_result.py +2 -2
  131. qiskit/primitives/containers/__init__.py +0 -1
  132. qiskit/primitives/containers/bindings_array.py +2 -2
  133. qiskit/primitives/containers/bit_array.py +113 -12
  134. qiskit/primitives/containers/shape.py +3 -3
  135. qiskit/primitives/estimator.py +9 -2
  136. qiskit/primitives/primitive_job.py +1 -1
  137. qiskit/primitives/sampler.py +10 -3
  138. qiskit/primitives/statevector_estimator.py +5 -3
  139. qiskit/primitives/statevector_sampler.py +11 -5
  140. qiskit/primitives/utils.py +16 -0
  141. qiskit/providers/backend.py +15 -6
  142. qiskit/providers/backend_compat.py +7 -4
  143. qiskit/providers/basic_provider/basic_provider_tools.py +1 -1
  144. qiskit/providers/basic_provider/basic_simulator.py +33 -25
  145. qiskit/providers/fake_provider/fake_backend.py +10 -3
  146. qiskit/providers/fake_provider/fake_openpulse_2q.py +157 -149
  147. qiskit/providers/fake_provider/fake_openpulse_3q.py +228 -220
  148. qiskit/providers/fake_provider/fake_pulse_backend.py +2 -1
  149. qiskit/providers/fake_provider/fake_qasm_backend.py +7 -2
  150. qiskit/providers/fake_provider/generic_backend_v2.py +519 -68
  151. qiskit/providers/models/__init__.py +48 -11
  152. qiskit/providers/models/backendconfiguration.py +50 -4
  153. qiskit/providers/models/backendproperties.py +13 -2
  154. qiskit/providers/models/pulsedefaults.py +10 -11
  155. qiskit/providers/options.py +13 -13
  156. qiskit/providers/providerutils.py +3 -1
  157. qiskit/pulse/configuration.py +8 -12
  158. qiskit/pulse/instruction_schedule_map.py +3 -5
  159. qiskit/pulse/instructions/acquire.py +7 -8
  160. qiskit/pulse/instructions/instruction.py +2 -3
  161. qiskit/pulse/library/samplers/decorators.py +5 -9
  162. qiskit/pulse/library/symbolic_pulses.py +4 -7
  163. qiskit/pulse/library/waveform.py +2 -5
  164. qiskit/pulse/macros.py +11 -6
  165. qiskit/pulse/parser.py +8 -10
  166. qiskit/pulse/schedule.py +12 -20
  167. qiskit/pulse/transforms/alignments.py +1 -3
  168. qiskit/pulse/utils.py +1 -2
  169. qiskit/qasm/libs/stdgates.inc +35 -28
  170. qiskit/qasm2/__init__.py +7 -7
  171. qiskit/qasm2/export.py +5 -9
  172. qiskit/qasm2/parse.py +1 -1
  173. qiskit/qasm3/ast.py +9 -25
  174. qiskit/qasm3/exporter.py +582 -479
  175. qiskit/qasm3/printer.py +7 -16
  176. qiskit/qobj/common.py +10 -0
  177. qiskit/qobj/converters/lo_config.py +9 -0
  178. qiskit/qobj/converters/pulse_instruction.py +13 -6
  179. qiskit/qobj/pulse_qobj.py +69 -15
  180. qiskit/qobj/qasm_qobj.py +72 -20
  181. qiskit/qobj/utils.py +9 -0
  182. qiskit/qpy/__init__.py +1 -1
  183. qiskit/qpy/binary_io/circuits.py +8 -5
  184. qiskit/qpy/binary_io/schedules.py +1 -1
  185. qiskit/qpy/binary_io/value.py +3 -3
  186. qiskit/qpy/interface.py +3 -2
  187. qiskit/qpy/type_keys.py +2 -2
  188. qiskit/quantum_info/operators/channel/quantum_channel.py +3 -6
  189. qiskit/quantum_info/operators/channel/superop.py +2 -2
  190. qiskit/quantum_info/operators/channel/transformations.py +1 -1
  191. qiskit/quantum_info/operators/dihedral/dihedral.py +3 -4
  192. qiskit/quantum_info/operators/dihedral/dihedral_circuits.py +1 -3
  193. qiskit/quantum_info/operators/dihedral/random.py +6 -3
  194. qiskit/quantum_info/operators/measures.py +2 -2
  195. qiskit/quantum_info/operators/op_shape.py +12 -20
  196. qiskit/quantum_info/operators/operator.py +14 -21
  197. qiskit/quantum_info/operators/predicates.py +1 -0
  198. qiskit/quantum_info/operators/symplectic/base_pauli.py +7 -11
  199. qiskit/quantum_info/operators/symplectic/clifford.py +1 -1
  200. qiskit/quantum_info/operators/symplectic/pauli.py +14 -12
  201. qiskit/quantum_info/operators/symplectic/pauli_list.py +9 -10
  202. qiskit/quantum_info/operators/symplectic/random.py +1 -1
  203. qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +15 -17
  204. qiskit/quantum_info/quaternion.py +1 -1
  205. qiskit/quantum_info/states/densitymatrix.py +5 -8
  206. qiskit/quantum_info/states/stabilizerstate.py +128 -37
  207. qiskit/quantum_info/states/statevector.py +4 -8
  208. qiskit/result/counts.py +2 -2
  209. qiskit/result/mitigation/correlated_readout_mitigator.py +2 -2
  210. qiskit/result/mitigation/local_readout_mitigator.py +2 -2
  211. qiskit/result/mitigation/utils.py +1 -3
  212. qiskit/result/models.py +17 -16
  213. qiskit/result/result.py +15 -20
  214. qiskit/scheduler/lowering.py +2 -2
  215. qiskit/synthesis/__init__.py +2 -1
  216. qiskit/synthesis/clifford/__init__.py +1 -1
  217. qiskit/synthesis/clifford/clifford_decompose_ag.py +2 -2
  218. qiskit/synthesis/clifford/clifford_decompose_bm.py +10 -240
  219. qiskit/synthesis/clifford/clifford_decompose_greedy.py +9 -303
  220. qiskit/synthesis/clifford/clifford_decompose_layers.py +25 -23
  221. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_full.py +1 -1
  222. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_general.py +1 -1
  223. qiskit/synthesis/discrete_basis/generate_basis_approximations.py +2 -2
  224. qiskit/synthesis/discrete_basis/solovay_kitaev.py +24 -14
  225. qiskit/synthesis/evolution/evolution_synthesis.py +4 -2
  226. qiskit/synthesis/evolution/lie_trotter.py +46 -19
  227. qiskit/synthesis/evolution/product_formula.py +111 -55
  228. qiskit/synthesis/evolution/qdrift.py +40 -10
  229. qiskit/synthesis/evolution/suzuki_trotter.py +43 -33
  230. qiskit/synthesis/linear/__init__.py +1 -0
  231. qiskit/synthesis/linear/cnot_synth.py +22 -96
  232. qiskit/synthesis/linear/linear_depth_lnn.py +8 -8
  233. qiskit/synthesis/linear/linear_matrix_utils.py +13 -161
  234. qiskit/synthesis/linear_phase/cnot_phase_synth.py +1 -1
  235. qiskit/synthesis/linear_phase/cx_cz_depth_lnn.py +3 -3
  236. qiskit/synthesis/linear_phase/cz_depth_lnn.py +1 -1
  237. qiskit/synthesis/one_qubit/one_qubit_decompose.py +29 -29
  238. qiskit/synthesis/permutation/permutation_full.py +5 -29
  239. qiskit/synthesis/permutation/permutation_lnn.py +2 -24
  240. qiskit/synthesis/permutation/permutation_utils.py +2 -59
  241. qiskit/synthesis/qft/__init__.py +1 -0
  242. qiskit/synthesis/qft/qft_decompose_full.py +79 -0
  243. qiskit/synthesis/qft/qft_decompose_lnn.py +17 -9
  244. qiskit/synthesis/stabilizer/stabilizer_circuit.py +6 -6
  245. qiskit/synthesis/stabilizer/stabilizer_decompose.py +2 -2
  246. qiskit/synthesis/two_qubit/local_invariance.py +8 -38
  247. qiskit/synthesis/two_qubit/two_qubit_decompose.py +48 -129
  248. qiskit/synthesis/unitary/aqc/cnot_structures.py +1 -1
  249. qiskit/synthesis/unitary/qsd.py +5 -3
  250. qiskit/transpiler/__init__.py +6 -5
  251. qiskit/transpiler/basepasses.py +1 -1
  252. qiskit/transpiler/coupling.py +3 -3
  253. qiskit/transpiler/instruction_durations.py +1 -2
  254. qiskit/transpiler/layout.py +6 -6
  255. qiskit/transpiler/passes/__init__.py +2 -0
  256. qiskit/transpiler/passes/basis/basis_translator.py +84 -64
  257. qiskit/transpiler/passes/basis/translate_parameterized.py +3 -5
  258. qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
  259. qiskit/transpiler/passes/basis/unroll_custom_definitions.py +10 -10
  260. qiskit/transpiler/passes/calibration/rx_builder.py +3 -3
  261. qiskit/transpiler/passes/calibration/rzx_builder.py +3 -3
  262. qiskit/transpiler/passes/layout/apply_layout.py +13 -3
  263. qiskit/transpiler/passes/layout/sabre_layout.py +10 -8
  264. qiskit/transpiler/passes/layout/sabre_pre_layout.py +4 -1
  265. qiskit/transpiler/passes/layout/set_layout.py +2 -2
  266. qiskit/transpiler/passes/layout/vf2_layout.py +1 -1
  267. qiskit/transpiler/passes/layout/vf2_utils.py +3 -3
  268. qiskit/transpiler/passes/optimization/__init__.py +1 -0
  269. qiskit/transpiler/passes/optimization/collect_cliffords.py +6 -15
  270. qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +2 -2
  271. qiskit/transpiler/passes/optimization/commutation_analysis.py +7 -10
  272. qiskit/transpiler/passes/optimization/commutative_cancellation.py +35 -19
  273. qiskit/transpiler/passes/optimization/consolidate_blocks.py +17 -8
  274. qiskit/transpiler/passes/optimization/inverse_cancellation.py +6 -6
  275. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +64 -41
  276. qiskit/transpiler/passes/optimization/optimize_1q_gates.py +1 -1
  277. qiskit/transpiler/passes/optimization/split_2q_unitaries.py +83 -0
  278. qiskit/transpiler/passes/optimization/template_matching/backward_match.py +1 -1
  279. qiskit/transpiler/passes/optimization/template_matching/forward_match.py +2 -2
  280. qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +1 -1
  281. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +3 -2
  282. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/pauli_2q_evolution_commutation.py +5 -1
  283. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +1 -1
  284. qiskit/transpiler/passes/routing/layout_transformation.py +2 -1
  285. qiskit/transpiler/passes/routing/sabre_swap.py +35 -26
  286. qiskit/transpiler/passes/routing/star_prerouting.py +80 -105
  287. qiskit/transpiler/passes/routing/stochastic_swap.py +1 -3
  288. qiskit/transpiler/passes/scheduling/alap.py +1 -2
  289. qiskit/transpiler/passes/scheduling/alignments/__init__.py +2 -2
  290. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
  291. qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +2 -2
  292. qiskit/transpiler/passes/scheduling/alignments/reschedule.py +1 -1
  293. qiskit/transpiler/passes/scheduling/asap.py +1 -2
  294. qiskit/transpiler/passes/scheduling/base_scheduler.py +5 -5
  295. qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +3 -3
  296. qiskit/transpiler/passes/scheduling/padding/base_padding.py +1 -1
  297. qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +20 -14
  298. qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +7 -6
  299. qiskit/transpiler/passes/scheduling/time_unit_conversion.py +4 -3
  300. qiskit/transpiler/passes/synthesis/high_level_synthesis.py +211 -36
  301. qiskit/transpiler/passes/synthesis/plugin.py +2 -2
  302. qiskit/transpiler/passes/synthesis/unitary_synthesis.py +83 -40
  303. qiskit/transpiler/passes/utils/__init__.py +0 -1
  304. qiskit/transpiler/passes/utils/check_gate_direction.py +4 -4
  305. qiskit/transpiler/passes/utils/check_map.py +3 -6
  306. qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +3 -4
  307. qiskit/transpiler/passes/utils/error.py +2 -2
  308. qiskit/transpiler/passes/utils/fixed_point.py +3 -3
  309. qiskit/transpiler/passes/utils/gate_direction.py +1 -1
  310. qiskit/transpiler/passes/utils/gates_basis.py +1 -2
  311. qiskit/transpiler/passmanager.py +7 -6
  312. qiskit/transpiler/preset_passmanagers/__init__.py +4 -228
  313. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +73 -18
  314. qiskit/transpiler/preset_passmanagers/common.py +3 -6
  315. qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +518 -0
  316. qiskit/transpiler/preset_passmanagers/level0.py +1 -1
  317. qiskit/transpiler/target.py +27 -8
  318. qiskit/user_config.py +29 -6
  319. qiskit/utils/classtools.py +3 -3
  320. qiskit/utils/deprecation.py +3 -2
  321. qiskit/utils/lazy_tester.py +2 -2
  322. qiskit/utils/optionals.py +8 -8
  323. qiskit/visualization/bloch.py +62 -24
  324. qiskit/visualization/circuit/_utils.py +34 -10
  325. qiskit/visualization/circuit/circuit_visualization.py +23 -16
  326. qiskit/visualization/circuit/latex.py +29 -27
  327. qiskit/visualization/circuit/matplotlib.py +4 -2
  328. qiskit/visualization/circuit/qcstyle.py +2 -2
  329. qiskit/visualization/circuit/text.py +9 -15
  330. qiskit/visualization/dag_visualization.py +12 -5
  331. qiskit/visualization/pass_manager_visualization.py +9 -9
  332. qiskit/visualization/pulse_v2/core.py +1 -1
  333. qiskit/visualization/pulse_v2/events.py +1 -1
  334. qiskit/visualization/pulse_v2/generators/frame.py +3 -4
  335. qiskit/visualization/pulse_v2/generators/waveform.py +5 -9
  336. qiskit/visualization/pulse_v2/layouts.py +1 -5
  337. qiskit/visualization/pulse_v2/plotters/matplotlib.py +1 -2
  338. qiskit/visualization/state_visualization.py +5 -6
  339. qiskit/visualization/timeline/plotters/matplotlib.py +1 -2
  340. qiskit/visualization/transition_visualization.py +7 -2
  341. {qiskit-1.1.1.dist-info → qiskit-1.2.0.dist-info}/METADATA +28 -28
  342. {qiskit-1.1.1.dist-info → qiskit-1.2.0.dist-info}/RECORD +346 -344
  343. {qiskit-1.1.1.dist-info → qiskit-1.2.0.dist-info}/WHEEL +1 -1
  344. {qiskit-1.1.1.dist-info → qiskit-1.2.0.dist-info}/entry_points.txt +3 -0
  345. qiskit/transpiler/passes/utils/block_to_matrix.py +0 -47
  346. {qiskit-1.1.1.dist-info → qiskit-1.2.0.dist-info}/LICENSE.txt +0 -0
  347. {qiskit-1.1.1.dist-info → qiskit-1.2.0.dist-info}/top_level.txt +0 -0
@@ -15,6 +15,8 @@
15
15
  """Quantum circuit object."""
16
16
 
17
17
  from __future__ import annotations
18
+
19
+ import collections.abc
18
20
  import copy as _copy
19
21
  import itertools
20
22
  import multiprocessing as mp
@@ -37,14 +39,15 @@ from typing import (
37
39
  )
38
40
  import numpy as np
39
41
  from qiskit._accelerate.circuit import CircuitData
42
+ from qiskit._accelerate.circuit import StandardGate
40
43
  from qiskit.exceptions import QiskitError
41
44
  from qiskit.utils.multiprocessing import is_main_process
42
45
  from qiskit.circuit.instruction import Instruction
43
46
  from qiskit.circuit.gate import Gate
44
47
  from qiskit.circuit.parameter import Parameter
45
48
  from qiskit.circuit.exceptions import CircuitError
49
+ from qiskit.utils import deprecate_func
46
50
  from . import _classical_resource_map
47
- from ._utils import sort_parameters
48
51
  from .controlflow import ControlFlowOp, _builder_utils
49
52
  from .controlflow.builder import CircuitScopeInterface, ControlFlowBuilderBlock
50
53
  from .controlflow.break_loop import BreakLoopOp, BreakLoopPlaceholder
@@ -57,7 +60,7 @@ from .classical import expr, types
57
60
  from .parameterexpression import ParameterExpression, ParameterValueType
58
61
  from .quantumregister import QuantumRegister, Qubit, AncillaRegister, AncillaQubit
59
62
  from .classicalregister import ClassicalRegister, Clbit
60
- from .parametertable import ParameterReferences, ParameterTable, ParameterView
63
+ from .parametertable import ParameterView
61
64
  from .parametervector import ParameterVector
62
65
  from .instructionset import InstructionSet
63
66
  from .operation import Operation
@@ -110,7 +113,7 @@ BitType = TypeVar("BitType", Qubit, Clbit)
110
113
  #
111
114
  # If you're adding methods or attributes to `QuantumCircuit`, be sure to update the class docstring
112
115
  # to document them in a suitable place. The class is huge, so we do its documentation manually so
113
- # it has at least some amount of organisational structure.
116
+ # it has at least some amount of organizational structure.
114
117
 
115
118
 
116
119
  class QuantumCircuit:
@@ -368,7 +371,7 @@ class QuantumCircuit:
368
371
  -------------------------------
369
372
 
370
373
  A :class:`.Bit` instance is, on its own, just a unique handle for circuits to use in their own
371
- contexts. If you have got a :class:`.Bit` instance and a cirucit, just can find the contexts
374
+ contexts. If you have got a :class:`.Bit` instance and a circuit, just can find the contexts
372
375
  that the bit exists in using :meth:`find_bit`, such as its integer index in the circuit and any
373
376
  registers it is contained in.
374
377
 
@@ -649,7 +652,7 @@ class QuantumCircuit:
649
652
 
650
653
  Finally, these methods apply particular generalized multiply controlled gates to the circuit,
651
654
  often with eager syntheses. They are listed in terms of the *base* gate they are controlling,
652
- since their exact output is often a synthesised version of a gate.
655
+ since their exact output is often a synthesized version of a gate.
653
656
 
654
657
  =============================== =================================================
655
658
  :class:`QuantumCircuit` method Base :mod:`qiskit.circuit.library` :class:`.Gate`
@@ -1066,8 +1069,9 @@ class QuantumCircuit:
1066
1069
 
1067
1070
  if not valid_reg_size:
1068
1071
  raise CircuitError(
1069
- "Circuit args must be Registers or integers. (%s '%s' was "
1070
- "provided)" % ([type(reg).__name__ for reg in regs], regs)
1072
+ "Circuit args must be Registers or integers. ("
1073
+ f"{[type(reg).__name__ for reg in regs]} '{regs}' was "
1074
+ "provided)"
1071
1075
  )
1072
1076
 
1073
1077
  regs = tuple(int(reg) for reg in regs) # cast to int
@@ -1075,7 +1079,7 @@ class QuantumCircuit:
1075
1079
  self.name: str
1076
1080
  """A human-readable name for the circuit."""
1077
1081
  if name is None:
1078
- self._base_name = self.cls_prefix()
1082
+ self._base_name = self._cls_prefix()
1079
1083
  self._name_update()
1080
1084
  elif not isinstance(name, str):
1081
1085
  raise CircuitError(
@@ -1124,14 +1128,7 @@ class QuantumCircuit:
1124
1128
  self._calibrations: DefaultDict[str, dict[tuple, Any]] = defaultdict(dict)
1125
1129
  self.add_register(*regs)
1126
1130
 
1127
- # Parameter table tracks instructions with variable parameters.
1128
- self._parameter_table = ParameterTable()
1129
-
1130
- # Cache to avoid re-sorting parameters
1131
- self._parameters = None
1132
-
1133
1131
  self._layout = None
1134
- self._global_phase: ParameterValueType = 0
1135
1132
  self.global_phase = global_phase
1136
1133
 
1137
1134
  # Add classical variables. Resolve inputs and captures first because they can't depend on
@@ -1159,6 +1156,15 @@ class QuantumCircuit:
1159
1156
  Qiskit will not examine the content of this mapping, but it will pass it through the
1160
1157
  transpiler and reattach it to the output, so you can track your own metadata."""
1161
1158
 
1159
+ @classmethod
1160
+ def _from_circuit_data(cls, data: CircuitData) -> typing.Self:
1161
+ """A private constructor from rust space circuit data."""
1162
+ out = QuantumCircuit()
1163
+ out._data = data
1164
+ out._qubit_indices = {bit: BitLocations(index, []) for index, bit in enumerate(data.qubits)}
1165
+ out._clbit_indices = {bit: BitLocations(index, []) for index, bit in enumerate(data.clbits)}
1166
+ return out
1167
+
1162
1168
  @staticmethod
1163
1169
  def from_instructions(
1164
1170
  instructions: Iterable[
@@ -1258,8 +1264,6 @@ class QuantumCircuit:
1258
1264
  else:
1259
1265
  data_input = list(data_input)
1260
1266
  self._data.clear()
1261
- self._parameters = None
1262
- self._parameter_table = ParameterTable()
1263
1267
  # Repopulate the parameter table with any global-phase entries.
1264
1268
  self.global_phase = self.global_phase
1265
1269
  if not data_input:
@@ -1382,12 +1386,11 @@ class QuantumCircuit:
1382
1386
 
1383
1387
  # Avoids pulling self._data into a Python list
1384
1388
  # like we would when pickling.
1385
- result._data = self._data.copy()
1389
+ result._data = self._data.copy(deepcopy=True)
1386
1390
  result._data.replace_bits(
1387
1391
  qubits=_copy.deepcopy(self._data.qubits, memo),
1388
1392
  clbits=_copy.deepcopy(self._data.clbits, memo),
1389
1393
  )
1390
- result._data.map_ops(lambda op: _copy.deepcopy(op, memo))
1391
1394
  return result
1392
1395
 
1393
1396
  @classmethod
@@ -1395,16 +1398,39 @@ class QuantumCircuit:
1395
1398
  cls.instances += 1
1396
1399
 
1397
1400
  @classmethod
1401
+ @deprecate_func(
1402
+ since=1.2,
1403
+ removal_timeline="in the 2.0 release",
1404
+ additional_msg="This method is only used as an internal helper "
1405
+ "and will be removed with no replacement.",
1406
+ )
1398
1407
  def cls_instances(cls) -> int:
1399
1408
  """Return the current number of instances of this class,
1400
1409
  useful for auto naming."""
1401
1410
  return cls.instances
1402
1411
 
1403
1412
  @classmethod
1413
+ def _cls_instances(cls) -> int:
1414
+ """Return the current number of instances of this class,
1415
+ useful for auto naming."""
1416
+ return cls.instances
1417
+
1418
+ @classmethod
1419
+ @deprecate_func(
1420
+ since=1.2,
1421
+ removal_timeline="in the 2.0 release",
1422
+ additional_msg="This method is only used as an internal helper "
1423
+ "and will be removed with no replacement.",
1424
+ )
1404
1425
  def cls_prefix(cls) -> str:
1405
1426
  """Return the prefix to use for auto naming."""
1406
1427
  return cls.prefix
1407
1428
 
1429
+ @classmethod
1430
+ def _cls_prefix(cls) -> str:
1431
+ """Return the prefix to use for auto naming."""
1432
+ return cls.prefix
1433
+
1408
1434
  def _name_update(self) -> None:
1409
1435
  """update name of instance using instance number"""
1410
1436
  if not is_main_process():
@@ -1412,7 +1438,7 @@ class QuantumCircuit:
1412
1438
  else:
1413
1439
  pid_name = ""
1414
1440
 
1415
- self.name = f"{self._base_name}-{self.cls_instances()}{pid_name}"
1441
+ self.name = f"{self._base_name}-{self._cls_instances()}{pid_name}"
1416
1442
 
1417
1443
  def has_register(self, register: Register) -> bool:
1418
1444
  """
@@ -1591,11 +1617,12 @@ class QuantumCircuit:
1591
1617
  )
1592
1618
  return inverse_circ
1593
1619
 
1594
- def repeat(self, reps: int) -> "QuantumCircuit":
1620
+ def repeat(self, reps: int, *, insert_barriers: bool = False) -> "QuantumCircuit":
1595
1621
  """Repeat this circuit ``reps`` times.
1596
1622
 
1597
1623
  Args:
1598
1624
  reps (int): How often this circuit should be repeated.
1625
+ insert_barriers (bool): Whether to include barriers between circuit repetitions.
1599
1626
 
1600
1627
  Returns:
1601
1628
  QuantumCircuit: A circuit containing ``reps`` repetitions of this circuit.
@@ -1611,8 +1638,10 @@ class QuantumCircuit:
1611
1638
  inst: Instruction = self.to_gate()
1612
1639
  except QiskitError:
1613
1640
  inst = self.to_instruction()
1614
- for _ in range(reps):
1641
+ for i in range(reps):
1615
1642
  repeated_circ._append(inst, self.qubits, self.clbits)
1643
+ if insert_barriers and i != reps - 1:
1644
+ repeated_circ.barrier()
1616
1645
 
1617
1646
  return repeated_circ
1618
1647
 
@@ -1655,7 +1684,7 @@ class QuantumCircuit:
1655
1684
  raise CircuitError(
1656
1685
  "Cannot raise a parameterized circuit to a non-positive power "
1657
1686
  "or matrix-power, please bind the free parameters: "
1658
- "{}".format(self.parameters)
1687
+ f"{self.parameters}"
1659
1688
  )
1660
1689
 
1661
1690
  try:
@@ -1685,7 +1714,7 @@ class QuantumCircuit:
1685
1714
  label (str): An optional label to give the controlled operation for visualization.
1686
1715
  ctrl_state (str or int): The control state in decimal or as a bitstring
1687
1716
  (e.g. '111'). If None, use ``2**num_ctrl_qubits - 1``.
1688
- annotated: indicates whether the controlled gate can be implemented
1717
+ annotated: indicates whether the controlled gate should be implemented
1689
1718
  as an annotated gate.
1690
1719
 
1691
1720
  Returns:
@@ -1757,14 +1786,14 @@ class QuantumCircuit:
1757
1786
  this can be anything that :obj:`.append` will accept.
1758
1787
  qubits (list[Qubit|int]): qubits of self to compose onto.
1759
1788
  clbits (list[Clbit|int]): clbits of self to compose onto.
1760
- front (bool): If True, front composition will be performed. This is not possible within
1789
+ front (bool): If ``True``, front composition will be performed. This is not possible within
1761
1790
  control-flow builder context managers.
1762
- inplace (bool): If True, modify the object. Otherwise return composed circuit.
1791
+ inplace (bool): If ``True``, modify the object. Otherwise, return composed circuit.
1763
1792
  copy (bool): If ``True`` (the default), then the input is treated as shared, and any
1764
1793
  contained instructions will be copied, if they might need to be mutated in the
1765
1794
  future. You can set this to ``False`` if the input should be considered owned by
1766
1795
  the base circuit, in order to avoid unnecessary copies; in this case, it is not
1767
- valid to use ``other`` afterwards, and some instructions may have been mutated in
1796
+ valid to use ``other`` afterward, and some instructions may have been mutated in
1768
1797
  place.
1769
1798
  var_remap (Mapping): mapping to use to rewrite :class:`.expr.Var` nodes in ``other`` as
1770
1799
  they are inlined into ``self``. This can be used to avoid naming conflicts.
@@ -1896,7 +1925,7 @@ class QuantumCircuit:
1896
1925
  clbits = self.clbits[: other.num_clbits]
1897
1926
  if front:
1898
1927
  # Need to keep a reference to the data for use after we've emptied it.
1899
- old_data = dest._data.copy()
1928
+ old_data = dest._data.copy(copy_instructions=copy)
1900
1929
  dest.clear()
1901
1930
  dest.append(other, qubits, clbits, copy=copy)
1902
1931
  for instruction in old_data:
@@ -1918,11 +1947,11 @@ class QuantumCircuit:
1918
1947
  mapped_qubits = dest.qubits
1919
1948
  edge_map.update(zip(other.qubits, dest.qubits))
1920
1949
  else:
1921
- mapped_qubits = dest.qbit_argument_conversion(qubits)
1922
- if len(mapped_qubits) != len(other.qubits):
1950
+ mapped_qubits = dest._qbit_argument_conversion(qubits)
1951
+ if len(mapped_qubits) != other.num_qubits:
1923
1952
  raise CircuitError(
1924
1953
  f"Number of items in qubits parameter ({len(mapped_qubits)}) does not"
1925
- f" match number of qubits in the circuit ({len(other.qubits)})."
1954
+ f" match number of qubits in the circuit ({other.num_qubits})."
1926
1955
  )
1927
1956
  if len(set(mapped_qubits)) != len(mapped_qubits):
1928
1957
  raise CircuitError(
@@ -1934,17 +1963,17 @@ class QuantumCircuit:
1934
1963
  mapped_clbits = dest.clbits
1935
1964
  edge_map.update(zip(other.clbits, dest.clbits))
1936
1965
  else:
1937
- mapped_clbits = dest.cbit_argument_conversion(clbits)
1938
- if len(mapped_clbits) != len(other.clbits):
1966
+ mapped_clbits = dest._cbit_argument_conversion(clbits)
1967
+ if len(mapped_clbits) != other.num_clbits:
1939
1968
  raise CircuitError(
1940
1969
  f"Number of items in clbits parameter ({len(mapped_clbits)}) does not"
1941
- f" match number of clbits in the circuit ({len(other.clbits)})."
1970
+ f" match number of clbits in the circuit ({other.num_clbits})."
1942
1971
  )
1943
1972
  if len(set(mapped_clbits)) != len(mapped_clbits):
1944
1973
  raise CircuitError(
1945
1974
  f"Duplicate clbits referenced in 'clbits' parameter: '{mapped_clbits}'"
1946
1975
  )
1947
- edge_map.update(zip(other.clbits, dest.cbit_argument_conversion(clbits)))
1976
+ edge_map.update(zip(other.clbits, dest._cbit_argument_conversion(clbits)))
1948
1977
 
1949
1978
  for gate, cals in other.calibrations.items():
1950
1979
  dest._calibrations[gate].update(cals)
@@ -2024,14 +2053,14 @@ class QuantumCircuit:
2024
2053
  )
2025
2054
  return n_op.copy() if n_op is op and copy else n_op
2026
2055
 
2027
- instructions = source._data.copy()
2056
+ instructions = source._data.copy(copy_instructions=copy)
2028
2057
  instructions.replace_bits(qubits=new_qubits, clbits=new_clbits)
2029
- instructions.map_ops(map_vars)
2058
+ instructions.map_nonstandard_ops(map_vars)
2030
2059
  dest._current_scope().extend(instructions)
2031
2060
 
2032
2061
  append_existing = None
2033
2062
  if front:
2034
- append_existing = dest._data.copy()
2063
+ append_existing = dest._data.copy(copy_instructions=copy)
2035
2064
  dest.clear()
2036
2065
  copy_with_remapping(
2037
2066
  other,
@@ -2068,7 +2097,7 @@ class QuantumCircuit:
2068
2097
 
2069
2098
  Args:
2070
2099
  other (QuantumCircuit): The other circuit to tensor this circuit with.
2071
- inplace (bool): If True, modify the object. Otherwise return composed circuit.
2100
+ inplace (bool): If ``True``, modify the object. Otherwise return composed circuit.
2072
2101
 
2073
2102
  Examples:
2074
2103
 
@@ -2084,7 +2113,7 @@ class QuantumCircuit:
2084
2113
  tensored.draw('mpl')
2085
2114
 
2086
2115
  Returns:
2087
- QuantumCircuit: The tensored circuit (returns None if inplace==True).
2116
+ QuantumCircuit: The tensored circuit (returns ``None`` if ``inplace=True``).
2088
2117
  """
2089
2118
  num_qubits = self.num_qubits + other.num_qubits
2090
2119
  num_clbits = self.num_clbits + other.num_clbits
@@ -2259,6 +2288,12 @@ class QuantumCircuit:
2259
2288
  return self._data[item]
2260
2289
 
2261
2290
  @staticmethod
2291
+ @deprecate_func(
2292
+ since=1.2,
2293
+ removal_timeline="in the 2.0 release",
2294
+ additional_msg="This method is only used as an internal helper "
2295
+ "and will be removed with no replacement.",
2296
+ )
2262
2297
  def cast(value: S, type_: Callable[..., T]) -> Union[S, T]:
2263
2298
  """Best effort to cast value to type. Otherwise, returns the value."""
2264
2299
  try:
@@ -2266,36 +2301,108 @@ class QuantumCircuit:
2266
2301
  except (ValueError, TypeError):
2267
2302
  return value
2268
2303
 
2304
+ @staticmethod
2305
+ def _cast(value: S, type_: Callable[..., T]) -> Union[S, T]:
2306
+ """Best effort to cast value to type. Otherwise, returns the value."""
2307
+ try:
2308
+ return type_(value)
2309
+ except (ValueError, TypeError):
2310
+ return value
2311
+
2312
+ @deprecate_func(
2313
+ since=1.2,
2314
+ removal_timeline="in the 2.0 release",
2315
+ additional_msg="This method is only used as an internal helper "
2316
+ "and will be removed with no replacement.",
2317
+ )
2269
2318
  def qbit_argument_conversion(self, qubit_representation: QubitSpecifier) -> list[Qubit]:
2270
2319
  """
2271
2320
  Converts several qubit representations (such as indexes, range, etc.)
2272
2321
  into a list of qubits.
2273
2322
 
2274
2323
  Args:
2275
- qubit_representation (Object): representation to expand
2324
+ qubit_representation: Representation to expand.
2325
+
2326
+ Returns:
2327
+ The resolved instances of the qubits.
2328
+ """
2329
+
2330
+ return self._qbit_argument_conversion(qubit_representation)
2331
+
2332
+ def _qbit_argument_conversion(self, qubit_representation: QubitSpecifier) -> list[Qubit]:
2333
+ """
2334
+ Converts several qubit representations (such as indexes, range, etc.)
2335
+ into a list of qubits.
2336
+
2337
+ Args:
2338
+ qubit_representation: Representation to expand.
2276
2339
 
2277
2340
  Returns:
2278
- List(Qubit): the resolved instances of the qubits.
2341
+ The resolved instances of the qubits.
2279
2342
  """
2280
2343
  return _bit_argument_conversion(
2281
2344
  qubit_representation, self.qubits, self._qubit_indices, Qubit
2282
2345
  )
2283
2346
 
2347
+ @deprecate_func(
2348
+ since=1.2,
2349
+ removal_timeline="in the 2.0 release",
2350
+ additional_msg="This method is only used as an internal helper "
2351
+ "and will be removed with no replacement.",
2352
+ )
2284
2353
  def cbit_argument_conversion(self, clbit_representation: ClbitSpecifier) -> list[Clbit]:
2285
2354
  """
2286
2355
  Converts several classical bit representations (such as indexes, range, etc.)
2287
2356
  into a list of classical bits.
2288
2357
 
2289
2358
  Args:
2290
- clbit_representation (Object): representation to expand
2359
+ clbit_representation : Representation to expand.
2360
+
2361
+ Returns:
2362
+ A list of tuples where each tuple is a classical bit.
2363
+ """
2364
+ return self._cbit_argument_conversion(clbit_representation)
2365
+
2366
+ def _cbit_argument_conversion(self, clbit_representation: ClbitSpecifier) -> list[Clbit]:
2367
+ """
2368
+ Converts several classical bit representations (such as indexes, range, etc.)
2369
+ into a list of classical bits.
2370
+
2371
+ Args:
2372
+ clbit_representation: Representation to expand.
2291
2373
 
2292
2374
  Returns:
2293
- List(tuple): Where each tuple is a classical bit.
2375
+ A list of tuples where each tuple is a classical bit.
2294
2376
  """
2295
2377
  return _bit_argument_conversion(
2296
2378
  clbit_representation, self.clbits, self._clbit_indices, Clbit
2297
2379
  )
2298
2380
 
2381
+ def _append_standard_gate(
2382
+ self,
2383
+ op: StandardGate,
2384
+ qargs: Sequence[QubitSpecifier] = (),
2385
+ params: Sequence[ParameterValueType] = (),
2386
+ label: str | None = None,
2387
+ ) -> InstructionSet:
2388
+ """An internal method to bypass some checking when directly appending a standard gate."""
2389
+ circuit_scope = self._current_scope()
2390
+
2391
+ if params is None:
2392
+ params = []
2393
+
2394
+ expanded_qargs = [self._qbit_argument_conversion(qarg) for qarg in qargs or []]
2395
+ for param in params:
2396
+ Gate.validate_parameter(op, param)
2397
+
2398
+ instructions = InstructionSet(resource_requester=circuit_scope.resolve_classical_resource)
2399
+ for qarg, _ in Gate.broadcast_arguments(op, expanded_qargs, []):
2400
+ self._check_dups(qarg)
2401
+ instruction = CircuitInstruction.from_standard(op, qarg, params, label=label)
2402
+ circuit_scope.append(instruction, _standard_gate=True)
2403
+ instructions._add_ref(circuit_scope.instructions, len(circuit_scope.instructions) - 1)
2404
+ return instructions
2405
+
2299
2406
  def append(
2300
2407
  self,
2301
2408
  instruction: Operation | CircuitInstruction,
@@ -2383,8 +2490,8 @@ class QuantumCircuit:
2383
2490
  " which are not in this circuit"
2384
2491
  )
2385
2492
 
2386
- expanded_qargs = [self.qbit_argument_conversion(qarg) for qarg in qargs or []]
2387
- expanded_cargs = [self.cbit_argument_conversion(carg) for carg in cargs or []]
2493
+ expanded_qargs = [self._qbit_argument_conversion(qarg) for qarg in qargs or []]
2494
+ expanded_cargs = [self._cbit_argument_conversion(carg) for carg in cargs or []]
2388
2495
 
2389
2496
  instructions = InstructionSet(resource_requester=circuit_scope.resolve_classical_resource)
2390
2497
  # For Operations that are non-Instructions, we use the Instruction's default method
@@ -2393,16 +2500,19 @@ class QuantumCircuit:
2393
2500
  if isinstance(operation, Instruction)
2394
2501
  else Instruction.broadcast_arguments(operation, expanded_qargs, expanded_cargs)
2395
2502
  )
2503
+ base_instruction = CircuitInstruction(operation, (), ())
2396
2504
  for qarg, carg in broadcast_iter:
2397
2505
  self._check_dups(qarg)
2398
- instruction = CircuitInstruction(operation, qarg, carg)
2506
+ instruction = base_instruction.replace(qubits=qarg, clbits=carg)
2399
2507
  circuit_scope.append(instruction)
2400
2508
  instructions._add_ref(circuit_scope.instructions, len(circuit_scope.instructions) - 1)
2401
2509
  return instructions
2402
2510
 
2403
2511
  # Preferred new style.
2404
2512
  @typing.overload
2405
- def _append(self, instruction: CircuitInstruction) -> CircuitInstruction: ...
2513
+ def _append(
2514
+ self, instruction: CircuitInstruction, *, _standard_gate: bool
2515
+ ) -> CircuitInstruction: ...
2406
2516
 
2407
2517
  # To-be-deprecated old style.
2408
2518
  @typing.overload
@@ -2413,7 +2523,7 @@ class QuantumCircuit:
2413
2523
  cargs: Sequence[Clbit],
2414
2524
  ) -> Operation: ...
2415
2525
 
2416
- def _append(self, instruction, qargs=(), cargs=()):
2526
+ def _append(self, instruction, qargs=(), cargs=(), *, _standard_gate: bool = False):
2417
2527
  """Append an instruction to the end of the circuit, modifying the circuit in place.
2418
2528
 
2419
2529
  .. warning::
@@ -2435,7 +2545,7 @@ class QuantumCircuit:
2435
2545
  and the only reference to the circuit the instructions are being appended to is within
2436
2546
  that same function. In particular, it is not safe to call
2437
2547
  :meth:`QuantumCircuit._append` on a circuit that is received by a function argument.
2438
- This is because :meth:`.QuantumCircuit._append` will not recognise the scoping
2548
+ This is because :meth:`.QuantumCircuit._append` will not recognize the scoping
2439
2549
  constructs of the control-flow builder interface.
2440
2550
 
2441
2551
  Args:
@@ -2454,40 +2564,34 @@ class QuantumCircuit:
2454
2564
 
2455
2565
  :meta public:
2456
2566
  """
2567
+ if _standard_gate:
2568
+ self._data.append(instruction)
2569
+ self.duration = None
2570
+ self.unit = "dt"
2571
+ return instruction
2572
+
2457
2573
  old_style = not isinstance(instruction, CircuitInstruction)
2458
2574
  if old_style:
2459
2575
  instruction = CircuitInstruction(instruction, qargs, cargs)
2460
- self._data.append(instruction)
2461
- self._track_operation(instruction.operation)
2462
- return instruction.operation if old_style else instruction
2463
-
2464
- def _track_operation(self, operation: Operation):
2465
- """Sync all non-data-list internal data structures for a newly tracked operation."""
2466
- if isinstance(operation, Instruction):
2467
- self._update_parameter_table(operation)
2576
+ # If there is a reference to the outer circuit in an
2577
+ # instruction param the inner rust append method will raise a runtime error.
2578
+ # When this happens we need to handle the parameters separately.
2579
+ # This shouldn't happen in practice but 2 tests were doing this and it's not
2580
+ # explicitly prohibted by the API.
2581
+ try:
2582
+ self._data.append(instruction)
2583
+ except RuntimeError:
2584
+ params = [
2585
+ (idx, param.parameters)
2586
+ for idx, param in enumerate(instruction.operation.params)
2587
+ if isinstance(param, (ParameterExpression, QuantumCircuit))
2588
+ ]
2589
+ self._data.append_manual_params(instruction, params)
2590
+
2591
+ # Invalidate whole circuit duration if an instruction is added
2468
2592
  self.duration = None
2469
2593
  self.unit = "dt"
2470
-
2471
- def _update_parameter_table(self, instruction: Instruction):
2472
- for param_index, param in enumerate(instruction.params):
2473
- if isinstance(param, (ParameterExpression, QuantumCircuit)):
2474
- # Scoped constructs like the control-flow ops use QuantumCircuit as a parameter.
2475
- atomic_parameters = set(param.parameters)
2476
- else:
2477
- atomic_parameters = set()
2478
-
2479
- for parameter in atomic_parameters:
2480
- if parameter in self._parameter_table:
2481
- self._parameter_table[parameter].add((instruction, param_index))
2482
- else:
2483
- if parameter.name in self._parameter_table.get_names():
2484
- raise CircuitError(f"Name conflict on adding parameter: {parameter.name}")
2485
- self._parameter_table[parameter] = ParameterReferences(
2486
- ((instruction, param_index),)
2487
- )
2488
-
2489
- # clear cache if new parameter is added
2490
- self._parameters = None
2594
+ return instruction.operation if old_style else instruction
2491
2595
 
2492
2596
  @typing.overload
2493
2597
  def get_parameter(self, name: str, default: T) -> Union[Parameter, T]: ...
@@ -2518,7 +2622,7 @@ class QuantumCircuit:
2518
2622
 
2519
2623
  my_param = Parameter("my_param")
2520
2624
 
2521
- # Create a parametrised circuit.
2625
+ # Create a parametrized circuit.
2522
2626
  qc = QuantumCircuit(1)
2523
2627
  qc.rx(my_param, 0)
2524
2628
 
@@ -2538,7 +2642,7 @@ class QuantumCircuit:
2538
2642
  A similar method, but for :class:`.expr.Var` run-time variables instead of
2539
2643
  :class:`.Parameter` compile-time parameters.
2540
2644
  """
2541
- if (parameter := self._parameter_table.parameter_from_name(name, None)) is None:
2645
+ if (parameter := self._data.get_parameter_by_name(name)) is None:
2542
2646
  if default is Ellipsis:
2543
2647
  raise KeyError(f"no parameter named '{name}' is present")
2544
2648
  return default
@@ -2734,8 +2838,8 @@ class QuantumCircuit:
2734
2838
  # two classical registers we measured into above.
2735
2839
  qc.add_var(my_var, expr.bit_and(cr1, cr2))
2736
2840
  """
2737
- # Validate the initialiser first to catch cases where the variable to be declared is being
2738
- # used in the initialiser.
2841
+ # Validate the initializer first to catch cases where the variable to be declared is being
2842
+ # used in the initializer.
2739
2843
  circuit_scope = self._current_scope()
2740
2844
  # Convenience method to widen Python integer literals to the right width during the initial
2741
2845
  # lift, if the type is already known via the variable.
@@ -2759,7 +2863,7 @@ class QuantumCircuit:
2759
2863
  var = name_or_var
2760
2864
  circuit_scope.add_uninitialized_var(var)
2761
2865
  try:
2762
- # Store is responsible for ensuring the type safety of the initialisation.
2866
+ # Store is responsible for ensuring the type safety of the initialization.
2763
2867
  store = Store(var, initial)
2764
2868
  except CircuitError:
2765
2869
  circuit_scope.remove_var(var)
@@ -2789,7 +2893,7 @@ class QuantumCircuit:
2789
2893
  # name, and to be a bit less ergonomic than `add_var` (i.e. not allowing the (name, type)
2790
2894
  # overload) to discourage people from using it when they should use `add_var`.
2791
2895
  #
2792
- # This function exists so that there is a method to emulate `copy_empty_like`'s behaviour of
2896
+ # This function exists so that there is a method to emulate `copy_empty_like`'s behavior of
2793
2897
  # adding uninitialised variables, which there's no obvious way around. We need to be sure
2794
2898
  # that _some_ sort of handling of uninitialised variables is taken into account in our
2795
2899
  # structures, so that doesn't become a huge edge case, even though we make no assertions
@@ -2823,7 +2927,7 @@ class QuantumCircuit:
2823
2927
  """
2824
2928
  if self._control_flow_scopes:
2825
2929
  # Allow manual capturing. Not sure why it'd be useful, but there's a clear expected
2826
- # behaviour here.
2930
+ # behavior here.
2827
2931
  self._control_flow_scopes[-1].use_var(var)
2828
2932
  return
2829
2933
  if self._vars_input:
@@ -2894,14 +2998,14 @@ class QuantumCircuit:
2894
2998
  raise CircuitError(
2895
2999
  "QuantumCircuit parameters can be Registers or Integers."
2896
3000
  " If Integers, up to 2 arguments. QuantumCircuit was called"
2897
- " with %s." % (regs,)
3001
+ f" with {(regs,)}."
2898
3002
  )
2899
3003
 
2900
3004
  for register in regs:
2901
3005
  if isinstance(register, Register) and any(
2902
3006
  register.name == reg.name for reg in self.qregs + self.cregs
2903
3007
  ):
2904
- raise CircuitError('register name "%s" already exists' % register.name)
3008
+ raise CircuitError(f'register name "{register.name}" already exists')
2905
3009
 
2906
3010
  if isinstance(register, AncillaRegister):
2907
3011
  for bit in register:
@@ -2917,7 +3021,7 @@ class QuantumCircuit:
2917
3021
  else:
2918
3022
  self._data.add_qubit(bit)
2919
3023
  self._qubit_indices[bit] = BitLocations(
2920
- len(self._data.qubits) - 1, [(register, idx)]
3024
+ self._data.num_qubits - 1, [(register, idx)]
2921
3025
  )
2922
3026
 
2923
3027
  elif isinstance(register, ClassicalRegister):
@@ -2929,7 +3033,7 @@ class QuantumCircuit:
2929
3033
  else:
2930
3034
  self._data.add_clbit(bit)
2931
3035
  self._clbit_indices[bit] = BitLocations(
2932
- len(self._data.clbits) - 1, [(register, idx)]
3036
+ self._data.num_clbits - 1, [(register, idx)]
2933
3037
  )
2934
3038
 
2935
3039
  elif isinstance(register, list):
@@ -2950,14 +3054,14 @@ class QuantumCircuit:
2950
3054
  self._ancillas.append(bit)
2951
3055
  if isinstance(bit, Qubit):
2952
3056
  self._data.add_qubit(bit)
2953
- self._qubit_indices[bit] = BitLocations(len(self._data.qubits) - 1, [])
3057
+ self._qubit_indices[bit] = BitLocations(self._data.num_qubits - 1, [])
2954
3058
  elif isinstance(bit, Clbit):
2955
3059
  self._data.add_clbit(bit)
2956
- self._clbit_indices[bit] = BitLocations(len(self._data.clbits) - 1, [])
3060
+ self._clbit_indices[bit] = BitLocations(self._data.num_clbits - 1, [])
2957
3061
  else:
2958
3062
  raise CircuitError(
2959
3063
  "Expected an instance of Qubit, Clbit, or "
2960
- "AncillaQubit, but was passed {}".format(bit)
3064
+ f"AncillaQubit, but was passed {bit}"
2961
3065
  )
2962
3066
 
2963
3067
  def find_bit(self, bit: Bit) -> BitLocations:
@@ -3126,7 +3230,7 @@ class QuantumCircuit:
3126
3230
  reverse_bits: bool | None = None,
3127
3231
  justify: str | None = None,
3128
3232
  vertical_compression: str | None = "medium",
3129
- idle_wires: bool = True,
3233
+ idle_wires: bool | None = None,
3130
3234
  with_layout: bool = True,
3131
3235
  fold: int | None = None,
3132
3236
  # The type of ax is matplotlib.axes.Axes, but this is not a fixed dependency, so cannot be
@@ -3157,7 +3261,7 @@ class QuantumCircuit:
3157
3261
  Args:
3158
3262
  output: Select the output method to use for drawing the circuit.
3159
3263
  Valid choices are ``text``, ``mpl``, ``latex``, ``latex_source``.
3160
- By default the `text` drawer is used unless the user config file
3264
+ By default, the ``text`` drawer is used unless the user config file
3161
3265
  (usually ``~/.qiskit/settings.conf``) has an alternative backend set
3162
3266
  as the default. For example, ``circuit_drawer = latex``. If the output
3163
3267
  kwarg is set, that backend will always be used over the default in
@@ -3193,17 +3297,19 @@ class QuantumCircuit:
3193
3297
  alternative value set. For example, ``circuit_reverse_bits = True``.
3194
3298
  plot_barriers: Enable/disable drawing barriers in the output
3195
3299
  circuit. Defaults to ``True``.
3196
- justify: Options are ``left``, ``right`` or ``none``. If
3197
- anything else is supplied, it defaults to left justified. It refers
3198
- to where gates should be placed in the output circuit if there is
3199
- an option. ``none`` results in each gate being placed in its own
3200
- column.
3300
+ justify: Options are ``"left"``, ``"right"`` or ``"none"`` (str).
3301
+ If anything else is supplied, left justified will be used instead.
3302
+ It refers to where gates should be placed in the output circuit if
3303
+ there is an option. ``none`` results in each gate being placed in
3304
+ its own column. Defaults to ``left``.
3201
3305
  vertical_compression: ``high``, ``medium`` or ``low``. It
3202
3306
  merges the lines generated by the `text` output so the drawing
3203
3307
  will take less vertical room. Default is ``medium``. Only used by
3204
3308
  the ``text`` output, will be silently ignored otherwise.
3205
3309
  idle_wires: Include idle wires (wires with no circuit elements)
3206
- in output visualization. Default is ``True``.
3310
+ in output visualization. Default is ``True`` unless the
3311
+ user config file (usually ``~/.qiskit/settings.conf``) has an
3312
+ alternative value set. For example, ``circuit_idle_wires = False``.
3207
3313
  with_layout: Include layout information, with labels on the
3208
3314
  physical layout. Default is ``True``.
3209
3315
  fold: Sets pagination. It can be disabled using -1. In ``text``,
@@ -3292,7 +3398,7 @@ class QuantumCircuit:
3292
3398
  Args:
3293
3399
  filter_function (callable): a function to filter out some instructions.
3294
3400
  Should take as input a tuple of (Instruction, list(Qubit), list(Clbit)).
3295
- By default filters out "directives", such as barrier or snapshot.
3401
+ By default, filters out "directives", such as barrier or snapshot.
3296
3402
 
3297
3403
  Returns:
3298
3404
  int: Total number of gate operations.
@@ -3314,7 +3420,7 @@ class QuantumCircuit:
3314
3420
  filter_function: A function to decide which instructions count to increase depth.
3315
3421
  Should take as a single positional input a :class:`CircuitInstruction`.
3316
3422
  Instructions for which the function returns ``False`` are ignored in the
3317
- computation of the circuit depth. By default filters out "directives", such as
3423
+ computation of the circuit depth. By default, filters out "directives", such as
3318
3424
  :class:`.Barrier`.
3319
3425
 
3320
3426
  Returns:
@@ -3377,12 +3483,12 @@ class QuantumCircuit:
3377
3483
  int: Width of circuit.
3378
3484
 
3379
3485
  """
3380
- return len(self.qubits) + len(self.clbits)
3486
+ return self._data.width()
3381
3487
 
3382
3488
  @property
3383
3489
  def num_qubits(self) -> int:
3384
3490
  """Return number of qubits."""
3385
- return len(self.qubits)
3491
+ return self._data.num_qubits
3386
3492
 
3387
3493
  @property
3388
3494
  def num_ancillas(self) -> int:
@@ -3392,7 +3498,7 @@ class QuantumCircuit:
3392
3498
  @property
3393
3499
  def num_clbits(self) -> int:
3394
3500
  """Return number of classical bits."""
3395
- return len(self.clbits)
3501
+ return self._data.num_clbits
3396
3502
 
3397
3503
  # The stringified return type is because OrderedDict can't be subscripted before Python 3.9, and
3398
3504
  # typing.OrderedDict wasn't added until 3.7.2. It can be turned into a proper type once 3.6
@@ -3413,13 +3519,7 @@ class QuantumCircuit:
3413
3519
 
3414
3520
  Conditional nonlocal gates are also included.
3415
3521
  """
3416
- multi_qubit_gates = 0
3417
- for instruction in self._data:
3418
- if instruction.operation.num_qubits > 1 and not getattr(
3419
- instruction.operation, "_directive", False
3420
- ):
3421
- multi_qubit_gates += 1
3422
- return multi_qubit_gates
3522
+ return self._data.num_nonlocal_gates()
3423
3523
 
3424
3524
  def get_instructions(self, name: str) -> list[CircuitInstruction]:
3425
3525
  """Get instructions matching name.
@@ -3445,7 +3545,7 @@ class QuantumCircuit:
3445
3545
  bits = self.qubits if unitary_only else (self.qubits + self.clbits)
3446
3546
  bit_indices: dict[Qubit | Clbit, int] = {bit: idx for idx, bit in enumerate(bits)}
3447
3547
 
3448
- # Start with each qubit or cbit being its own subgraph.
3548
+ # Start with each qubit or clbit being its own subgraph.
3449
3549
  sub_graphs = [[bit] for bit in range(len(bit_indices))]
3450
3550
 
3451
3551
  num_sub_graphs = len(sub_graphs)
@@ -3533,29 +3633,6 @@ class QuantumCircuit:
3533
3633
  """
3534
3634
  cpy = self.copy_empty_like(name)
3535
3635
  cpy._data = self._data.copy()
3536
-
3537
- # The special global-phase sentinel doesn't need copying, but it's
3538
- # added here to ensure it's recognised. The global phase itself was
3539
- # already copied over in `copy_empty_like`.
3540
- operation_copies = {id(ParameterTable.GLOBAL_PHASE): ParameterTable.GLOBAL_PHASE}
3541
-
3542
- def memo_copy(op):
3543
- if (out := operation_copies.get(id(op))) is not None:
3544
- return out
3545
- copied = op.copy()
3546
- operation_copies[id(op)] = copied
3547
- return copied
3548
-
3549
- cpy._data.map_ops(memo_copy)
3550
- cpy._parameter_table = ParameterTable(
3551
- {
3552
- param: ParameterReferences(
3553
- (operation_copies[id(operation)], param_index)
3554
- for operation, param_index in self._parameter_table[param]
3555
- )
3556
- for param in self._parameter_table
3557
- }
3558
- )
3559
3636
  return cpy
3560
3637
 
3561
3638
  def copy_empty_like(
@@ -3619,7 +3696,7 @@ class QuantumCircuit:
3619
3696
  if vars_mode == "alike":
3620
3697
  # Note that this causes the local variables to be uninitialised, because the stores are
3621
3698
  # not copied. This can leave the circuit in a potentially dangerous state for users if
3622
- # they don't re-add initialiser stores.
3699
+ # they don't re-add initializer stores.
3623
3700
  cpy._vars_local = self._vars_local.copy()
3624
3701
  cpy._vars_input = self._vars_input.copy()
3625
3702
  cpy._vars_capture = self._vars_capture.copy()
@@ -3634,12 +3711,9 @@ class QuantumCircuit:
3634
3711
  else: # pragma: no cover
3635
3712
  raise ValueError(f"unknown vars_mode: '{vars_mode}'")
3636
3713
 
3637
- cpy._parameter_table = ParameterTable()
3638
- for parameter in getattr(cpy.global_phase, "parameters", ()):
3639
- cpy._parameter_table[parameter] = ParameterReferences(
3640
- [(ParameterTable.GLOBAL_PHASE, None)]
3641
- )
3642
- cpy._data = CircuitData(self._data.qubits, self._data.clbits)
3714
+ cpy._data = CircuitData(
3715
+ self._data.qubits, self._data.clbits, global_phase=self._data.global_phase
3716
+ )
3643
3717
 
3644
3718
  cpy._calibrations = _copy.deepcopy(self._calibrations)
3645
3719
  cpy._metadata = _copy.deepcopy(self._metadata)
@@ -3659,7 +3733,6 @@ class QuantumCircuit:
3659
3733
  quantum and classical typed data, but without mutating the original circuit.
3660
3734
  """
3661
3735
  self._data.clear()
3662
- self._parameter_table.clear()
3663
3736
  # Repopulate the parameter table with any phase symbols.
3664
3737
  self.global_phase = self.global_phase
3665
3738
 
@@ -3816,7 +3889,7 @@ class QuantumCircuit:
3816
3889
  inplace (bool): All measurements inplace or return new circuit.
3817
3890
 
3818
3891
  Returns:
3819
- QuantumCircuit: Returns circuit with measurements when `inplace = False`.
3892
+ QuantumCircuit: Returns circuit with measurements when ``inplace = False``.
3820
3893
  """
3821
3894
  from qiskit.converters.circuit_to_dag import circuit_to_dag
3822
3895
 
@@ -3863,18 +3936,18 @@ class QuantumCircuit:
3863
3936
  else:
3864
3937
  circ = self.copy()
3865
3938
  if add_bits:
3866
- new_creg = circ._create_creg(len(circ.qubits), "meas")
3939
+ new_creg = circ._create_creg(circ.num_qubits, "meas")
3867
3940
  circ.add_register(new_creg)
3868
3941
  circ.barrier()
3869
3942
  circ.measure(circ.qubits, new_creg)
3870
3943
  else:
3871
- if len(circ.clbits) < len(circ.qubits):
3944
+ if circ.num_clbits < circ.num_qubits:
3872
3945
  raise CircuitError(
3873
3946
  "The number of classical bits must be equal or greater than "
3874
3947
  "the number of qubits."
3875
3948
  )
3876
3949
  circ.barrier()
3877
- circ.measure(circ.qubits, circ.clbits[0 : len(circ.qubits)])
3950
+ circ.measure(circ.qubits, circ.clbits[0 : circ.num_qubits])
3878
3951
 
3879
3952
  if not inplace:
3880
3953
  return circ
@@ -3943,10 +4016,9 @@ class QuantumCircuit:
3943
4016
  circ._clbit_indices = {}
3944
4017
 
3945
4018
  # Clear instruction info
3946
- circ._data = CircuitData(qubits=circ._data.qubits, reserve=len(circ._data))
3947
- circ._parameter_table.clear()
3948
- # Repopulate the parameter table with any global-phase entries.
3949
- circ.global_phase = circ.global_phase
4019
+ circ._data = CircuitData(
4020
+ qubits=circ._data.qubits, reserve=len(circ._data), global_phase=circ.global_phase
4021
+ )
3950
4022
 
3951
4023
  # We must add the clbits first to preserve the original circuit
3952
4024
  # order. This way, add_register never adds clbits and just
@@ -4019,7 +4091,7 @@ class QuantumCircuit:
4019
4091
  """The global phase of the current circuit scope in radians."""
4020
4092
  if self._control_flow_scopes:
4021
4093
  return self._control_flow_scopes[-1].global_phase
4022
- return self._global_phase
4094
+ return self._data.global_phase
4023
4095
 
4024
4096
  @global_phase.setter
4025
4097
  def global_phase(self, angle: ParameterValueType):
@@ -4028,25 +4100,10 @@ class QuantumCircuit:
4028
4100
  Args:
4029
4101
  angle (float, ParameterExpression): radians
4030
4102
  """
4031
- # If we're currently parametric, we need to throw away the references. This setter is
4032
- # called by some subclasses before the inner `_global_phase` is initialised.
4033
- global_phase_reference = (ParameterTable.GLOBAL_PHASE, None)
4034
- if isinstance(previous := getattr(self, "_global_phase", None), ParameterExpression):
4035
- self._parameters = None
4036
- self._parameter_table.discard_references(previous, global_phase_reference)
4037
-
4038
- if isinstance(angle, ParameterExpression) and angle.parameters:
4039
- for parameter in angle.parameters:
4040
- if parameter not in self._parameter_table:
4041
- self._parameters = None
4042
- self._parameter_table[parameter] = ParameterReferences(())
4043
- self._parameter_table[parameter].add(global_phase_reference)
4044
- else:
4045
- angle = _normalize_global_phase(angle)
4046
4103
  if self._control_flow_scopes:
4047
4104
  self._control_flow_scopes[-1].global_phase = angle
4048
4105
  else:
4049
- self._global_phase = angle
4106
+ self._data.global_phase = angle
4050
4107
 
4051
4108
  @property
4052
4109
  def parameters(self) -> ParameterView:
@@ -4107,16 +4164,13 @@ class QuantumCircuit:
4107
4164
  Returns:
4108
4165
  The sorted :class:`.Parameter` objects in the circuit.
4109
4166
  """
4110
- # parameters from gates
4111
- if self._parameters is None:
4112
- self._parameters = sort_parameters(self._unsorted_parameters())
4113
4167
  # return as parameter view, which implements the set and list interface
4114
- return ParameterView(self._parameters)
4168
+ return ParameterView(self._data.parameters)
4115
4169
 
4116
4170
  @property
4117
4171
  def num_parameters(self) -> int:
4118
4172
  """The number of parameter objects in the circuit."""
4119
- return len(self._parameter_table)
4173
+ return self._data.num_parameters()
4120
4174
 
4121
4175
  def _unsorted_parameters(self) -> set[Parameter]:
4122
4176
  """Efficiently get all parameters in the circuit, without any sorting overhead.
@@ -4129,12 +4183,12 @@ class QuantumCircuit:
4129
4183
  """
4130
4184
  # This should be free, by accessing the actual backing data structure of the table, but that
4131
4185
  # means that we need to copy it if adding keys from the global phase.
4132
- return self._parameter_table.get_keys()
4186
+ return self._data.unsorted_parameters()
4133
4187
 
4134
4188
  @overload
4135
4189
  def assign_parameters(
4136
4190
  self,
4137
- parameters: Union[Mapping[Parameter, ParameterValueType], Sequence[ParameterValueType]],
4191
+ parameters: Union[Mapping[Parameter, ParameterValueType], Iterable[ParameterValueType]],
4138
4192
  inplace: Literal[False] = ...,
4139
4193
  *,
4140
4194
  flat_input: bool = ...,
@@ -4144,7 +4198,7 @@ class QuantumCircuit:
4144
4198
  @overload
4145
4199
  def assign_parameters(
4146
4200
  self,
4147
- parameters: Union[Mapping[Parameter, ParameterValueType], Sequence[ParameterValueType]],
4201
+ parameters: Union[Mapping[Parameter, ParameterValueType], Iterable[ParameterValueType]],
4148
4202
  inplace: Literal[True] = ...,
4149
4203
  *,
4150
4204
  flat_input: bool = ...,
@@ -4153,7 +4207,7 @@ class QuantumCircuit:
4153
4207
 
4154
4208
  def assign_parameters( # pylint: disable=missing-raises-doc
4155
4209
  self,
4156
- parameters: Union[Mapping[Parameter, ParameterValueType], Sequence[ParameterValueType]],
4210
+ parameters: Union[Mapping[Parameter, ParameterValueType], Iterable[ParameterValueType]],
4157
4211
  inplace: bool = False,
4158
4212
  *,
4159
4213
  flat_input: bool = False,
@@ -4242,94 +4296,28 @@ class QuantumCircuit:
4242
4296
  if inplace:
4243
4297
  target = self
4244
4298
  else:
4299
+ if not isinstance(parameters, dict):
4300
+ # We're going to need to access the sorted order wihin the inner Rust method on
4301
+ # `target`, so warm up our own cache first so that subsequent calls to
4302
+ # `assign_parameters` on `self` benefit as well.
4303
+ _ = self._data.parameters
4245
4304
  target = self.copy()
4246
4305
  target._increment_instances()
4247
4306
  target._name_update()
4248
4307
 
4249
- # Normalise the inputs into simple abstract interfaces, so we've dispatched the "iteration"
4250
- # logic in one place at the start of the function. This lets us do things like calculate
4251
- # and cache expensive properties for (e.g.) the sequence format only if they're used; for
4252
- # many large, close-to-hardware circuits, we won't need the extra handling for
4253
- # `global_phase` or recursive definition binding.
4254
- #
4255
- # During normalisation, be sure to reference 'parameters' and related things from 'self' not
4256
- # 'target' so we can take advantage of any caching we might be doing.
4257
- if isinstance(parameters, dict):
4308
+ if isinstance(parameters, collections.abc.Mapping):
4258
4309
  raw_mapping = parameters if flat_input else self._unroll_param_dict(parameters)
4259
- # Remember that we _must not_ mutate the output of `_unsorted_parameters`.
4260
- our_parameters = self._unsorted_parameters()
4310
+ our_parameters = self._data.unsorted_parameters()
4261
4311
  if strict and (extras := raw_mapping.keys() - our_parameters):
4262
4312
  raise CircuitError(
4263
4313
  f"Cannot bind parameters ({', '.join(str(x) for x in extras)}) not present in"
4264
4314
  " the circuit."
4265
4315
  )
4266
4316
  parameter_binds = _ParameterBindsDict(raw_mapping, our_parameters)
4317
+ target._data.assign_parameters_mapping(parameter_binds)
4267
4318
  else:
4268
- our_parameters = self.parameters
4269
- if len(parameters) != len(our_parameters):
4270
- raise ValueError(
4271
- "Mismatching number of values and parameters. For partial binding "
4272
- "please pass a dictionary of {parameter: value} pairs."
4273
- )
4274
- parameter_binds = _ParameterBindsSequence(our_parameters, parameters)
4275
-
4276
- # Clear out the parameter table for the relevant entries, since we'll be binding those.
4277
- # Any new references to parameters are reinserted as part of the bind.
4278
- target._parameters = None
4279
- # This is deliberately eager, because we want the side effect of clearing the table.
4280
- all_references = [
4281
- (parameter, value, target._parameter_table.pop(parameter, ()))
4282
- for parameter, value in parameter_binds.items()
4283
- ]
4284
- seen_operations = {}
4285
- # The meat of the actual binding for regular operations.
4286
- for to_bind, bound_value, references in all_references:
4287
- update_parameters = (
4288
- tuple(bound_value.parameters)
4289
- if isinstance(bound_value, ParameterExpression)
4290
- else ()
4291
- )
4292
- for operation, index in references:
4293
- seen_operations[id(operation)] = operation
4294
- if operation is ParameterTable.GLOBAL_PHASE:
4295
- assignee = target.global_phase
4296
- validate = _normalize_global_phase
4297
- else:
4298
- assignee = operation.params[index]
4299
- validate = operation.validate_parameter
4300
- if isinstance(assignee, ParameterExpression):
4301
- new_parameter = assignee.assign(to_bind, bound_value)
4302
- for parameter in update_parameters:
4303
- if parameter not in target._parameter_table:
4304
- target._parameter_table[parameter] = ParameterReferences(())
4305
- target._parameter_table[parameter].add((operation, index))
4306
- if not new_parameter.parameters:
4307
- new_parameter = validate(new_parameter.numeric())
4308
- elif isinstance(assignee, QuantumCircuit):
4309
- new_parameter = assignee.assign_parameters(
4310
- {to_bind: bound_value}, inplace=False, flat_input=True
4311
- )
4312
- else:
4313
- raise RuntimeError( # pragma: no cover
4314
- f"Saw an unknown type during symbolic binding: {assignee}."
4315
- " This may indicate an internal logic error in symbol tracking."
4316
- )
4317
- if operation is ParameterTable.GLOBAL_PHASE:
4318
- # We've already handled parameter table updates in bulk, so we need to skip the
4319
- # public setter trying to do it again.
4320
- target._global_phase = new_parameter
4321
- else:
4322
- operation.params[index] = new_parameter
4323
-
4324
- # After we've been through everything at the top level, make a single visit to each
4325
- # operation we've seen, rebinding its definition if necessary.
4326
- for operation in seen_operations.values():
4327
- if (
4328
- definition := getattr(operation, "_definition", None)
4329
- ) is not None and definition.num_parameters:
4330
- definition.assign_parameters(
4331
- parameter_binds.mapping, inplace=True, flat_input=True, strict=False
4332
- )
4319
+ parameter_binds = _ParameterBindsSequence(target._data.parameters, parameters)
4320
+ target._data.assign_parameters_iterable(parameters)
4333
4321
 
4334
4322
  # Finally, assign the parameters inside any of the calibrations. We don't track these in
4335
4323
  # the `ParameterTable`, so we manually reconstruct things.
@@ -4401,7 +4389,9 @@ class QuantumCircuit:
4401
4389
 
4402
4390
  if qargs:
4403
4391
  # This uses a `dict` not a `set` to guarantee a deterministic order to the arguments.
4404
- qubits = tuple({q: None for qarg in qargs for q in self.qbit_argument_conversion(qarg)})
4392
+ qubits = tuple(
4393
+ {q: None for qarg in qargs for q in self._qbit_argument_conversion(qarg)}
4394
+ )
4405
4395
  return self.append(
4406
4396
  CircuitInstruction(Barrier(len(qubits), label=label), qubits, ()), copy=False
4407
4397
  )
@@ -4448,9 +4438,7 @@ class QuantumCircuit:
4448
4438
  Returns:
4449
4439
  A handle to the instructions created.
4450
4440
  """
4451
- from .library.standard_gates.h import HGate
4452
-
4453
- return self.append(HGate(), [qubit], [], copy=False)
4441
+ return self._append_standard_gate(StandardGate.HGate, [qubit], ())
4454
4442
 
4455
4443
  def ch(
4456
4444
  self,
@@ -4474,6 +4462,12 @@ class QuantumCircuit:
4474
4462
  Returns:
4475
4463
  A handle to the instructions created.
4476
4464
  """
4465
+ # if the control state is |1> use the fast Rust version of the gate
4466
+ if ctrl_state is None or ctrl_state in ["1", 1]:
4467
+ return self._append_standard_gate(
4468
+ StandardGate.CHGate, [control_qubit, target_qubit], (), label=label
4469
+ )
4470
+
4477
4471
  from .library.standard_gates.h import CHGate
4478
4472
 
4479
4473
  return self.append(
@@ -4494,9 +4488,7 @@ class QuantumCircuit:
4494
4488
  Returns:
4495
4489
  A handle to the instructions created.
4496
4490
  """
4497
- from .library.standard_gates.i import IGate
4498
-
4499
- return self.append(IGate(), [qubit], [], copy=False)
4491
+ return self._append_standard_gate(StandardGate.IGate, [qubit], ())
4500
4492
 
4501
4493
  def ms(self, theta: ParameterValueType, qubits: Sequence[QubitSpecifier]) -> InstructionSet:
4502
4494
  """Apply :class:`~qiskit.circuit.library.MSGate`.
@@ -4527,9 +4519,7 @@ class QuantumCircuit:
4527
4519
  Returns:
4528
4520
  A handle to the instructions created.
4529
4521
  """
4530
- from .library.standard_gates.p import PhaseGate
4531
-
4532
- return self.append(PhaseGate(theta), [qubit], [], copy=False)
4522
+ return self._append_standard_gate(StandardGate.PhaseGate, [qubit], (theta,))
4533
4523
 
4534
4524
  def cp(
4535
4525
  self,
@@ -4555,6 +4545,12 @@ class QuantumCircuit:
4555
4545
  Returns:
4556
4546
  A handle to the instructions created.
4557
4547
  """
4548
+ # if the control state is |1> use the fast Rust version of the gate
4549
+ if ctrl_state is None or ctrl_state in ["1", 1]:
4550
+ return self._append_standard_gate(
4551
+ StandardGate.CPhaseGate, [control_qubit, target_qubit], (theta,), label=label
4552
+ )
4553
+
4558
4554
  from .library.standard_gates.p import CPhaseGate
4559
4555
 
4560
4556
  return self.append(
@@ -4611,9 +4607,7 @@ class QuantumCircuit:
4611
4607
  Returns:
4612
4608
  A handle to the instructions created.
4613
4609
  """
4614
- from .library.standard_gates.r import RGate
4615
-
4616
- return self.append(RGate(theta, phi), [qubit], [], copy=False)
4610
+ return self._append_standard_gate(StandardGate.RGate, [qubit], [theta, phi])
4617
4611
 
4618
4612
  def rv(
4619
4613
  self,
@@ -4660,10 +4654,8 @@ class QuantumCircuit:
4660
4654
  Returns:
4661
4655
  A handle to the instructions created.
4662
4656
  """
4663
- from .library.standard_gates.x import RCCXGate
4664
-
4665
- return self.append(
4666
- RCCXGate(), [control_qubit1, control_qubit2, target_qubit], [], copy=False
4657
+ return self._append_standard_gate(
4658
+ StandardGate.RCCXGate, [control_qubit1, control_qubit2, target_qubit], ()
4667
4659
  )
4668
4660
 
4669
4661
  def rcccx(
@@ -4686,13 +4678,10 @@ class QuantumCircuit:
4686
4678
  Returns:
4687
4679
  A handle to the instructions created.
4688
4680
  """
4689
- from .library.standard_gates.x import RC3XGate
4690
-
4691
- return self.append(
4692
- RC3XGate(),
4681
+ return self._append_standard_gate(
4682
+ StandardGate.RC3XGate,
4693
4683
  [control_qubit1, control_qubit2, control_qubit3, target_qubit],
4694
- [],
4695
- copy=False,
4684
+ (),
4696
4685
  )
4697
4686
 
4698
4687
  def rx(
@@ -4710,9 +4699,7 @@ class QuantumCircuit:
4710
4699
  Returns:
4711
4700
  A handle to the instructions created.
4712
4701
  """
4713
- from .library.standard_gates.rx import RXGate
4714
-
4715
- return self.append(RXGate(theta, label=label), [qubit], [], copy=False)
4702
+ return self._append_standard_gate(StandardGate.RXGate, [qubit], [theta], label=label)
4716
4703
 
4717
4704
  def crx(
4718
4705
  self,
@@ -4738,6 +4725,12 @@ class QuantumCircuit:
4738
4725
  Returns:
4739
4726
  A handle to the instructions created.
4740
4727
  """
4728
+ # if the control state is |1> use the fast Rust version of the gate
4729
+ if ctrl_state is None or ctrl_state in ["1", 1]:
4730
+ return self._append_standard_gate(
4731
+ StandardGate.CRXGate, [control_qubit, target_qubit], [theta], label=label
4732
+ )
4733
+
4741
4734
  from .library.standard_gates.rx import CRXGate
4742
4735
 
4743
4736
  return self.append(
@@ -4762,9 +4755,7 @@ class QuantumCircuit:
4762
4755
  Returns:
4763
4756
  A handle to the instructions created.
4764
4757
  """
4765
- from .library.standard_gates.rxx import RXXGate
4766
-
4767
- return self.append(RXXGate(theta), [qubit1, qubit2], [], copy=False)
4758
+ return self._append_standard_gate(StandardGate.RXXGate, [qubit1, qubit2], [theta])
4768
4759
 
4769
4760
  def ry(
4770
4761
  self, theta: ParameterValueType, qubit: QubitSpecifier, label: str | None = None
@@ -4781,9 +4772,7 @@ class QuantumCircuit:
4781
4772
  Returns:
4782
4773
  A handle to the instructions created.
4783
4774
  """
4784
- from .library.standard_gates.ry import RYGate
4785
-
4786
- return self.append(RYGate(theta, label=label), [qubit], [], copy=False)
4775
+ return self._append_standard_gate(StandardGate.RYGate, [qubit], [theta], label=label)
4787
4776
 
4788
4777
  def cry(
4789
4778
  self,
@@ -4809,6 +4798,12 @@ class QuantumCircuit:
4809
4798
  Returns:
4810
4799
  A handle to the instructions created.
4811
4800
  """
4801
+ # if the control state is |1> use the fast Rust version of the gate
4802
+ if ctrl_state is None or ctrl_state in ["1", 1]:
4803
+ return self._append_standard_gate(
4804
+ StandardGate.CRYGate, [control_qubit, target_qubit], [theta], label=label
4805
+ )
4806
+
4812
4807
  from .library.standard_gates.ry import CRYGate
4813
4808
 
4814
4809
  return self.append(
@@ -4833,9 +4828,7 @@ class QuantumCircuit:
4833
4828
  Returns:
4834
4829
  A handle to the instructions created.
4835
4830
  """
4836
- from .library.standard_gates.ryy import RYYGate
4837
-
4838
- return self.append(RYYGate(theta), [qubit1, qubit2], [], copy=False)
4831
+ return self._append_standard_gate(StandardGate.RYYGate, [qubit1, qubit2], [theta])
4839
4832
 
4840
4833
  def rz(self, phi: ParameterValueType, qubit: QubitSpecifier) -> InstructionSet:
4841
4834
  """Apply :class:`~qiskit.circuit.library.RZGate`.
@@ -4849,9 +4842,7 @@ class QuantumCircuit:
4849
4842
  Returns:
4850
4843
  A handle to the instructions created.
4851
4844
  """
4852
- from .library.standard_gates.rz import RZGate
4853
-
4854
- return self.append(RZGate(phi), [qubit], [], copy=False)
4845
+ return self._append_standard_gate(StandardGate.RZGate, [qubit], [phi])
4855
4846
 
4856
4847
  def crz(
4857
4848
  self,
@@ -4877,6 +4868,12 @@ class QuantumCircuit:
4877
4868
  Returns:
4878
4869
  A handle to the instructions created.
4879
4870
  """
4871
+ # if the control state is |1> use the fast Rust version of the gate
4872
+ if ctrl_state is None or ctrl_state in ["1", 1]:
4873
+ return self._append_standard_gate(
4874
+ StandardGate.CRZGate, [control_qubit, target_qubit], [theta], label=label
4875
+ )
4876
+
4880
4877
  from .library.standard_gates.rz import CRZGate
4881
4878
 
4882
4879
  return self.append(
@@ -4901,9 +4898,7 @@ class QuantumCircuit:
4901
4898
  Returns:
4902
4899
  A handle to the instructions created.
4903
4900
  """
4904
- from .library.standard_gates.rzx import RZXGate
4905
-
4906
- return self.append(RZXGate(theta), [qubit1, qubit2], [], copy=False)
4901
+ return self._append_standard_gate(StandardGate.RZXGate, [qubit1, qubit2], [theta])
4907
4902
 
4908
4903
  def rzz(
4909
4904
  self, theta: ParameterValueType, qubit1: QubitSpecifier, qubit2: QubitSpecifier
@@ -4920,9 +4915,7 @@ class QuantumCircuit:
4920
4915
  Returns:
4921
4916
  A handle to the instructions created.
4922
4917
  """
4923
- from .library.standard_gates.rzz import RZZGate
4924
-
4925
- return self.append(RZZGate(theta), [qubit1, qubit2], [], copy=False)
4918
+ return self._append_standard_gate(StandardGate.RZZGate, [qubit1, qubit2], [theta])
4926
4919
 
4927
4920
  def ecr(self, qubit1: QubitSpecifier, qubit2: QubitSpecifier) -> InstructionSet:
4928
4921
  """Apply :class:`~qiskit.circuit.library.ECRGate`.
@@ -4935,9 +4928,7 @@ class QuantumCircuit:
4935
4928
  Returns:
4936
4929
  A handle to the instructions created.
4937
4930
  """
4938
- from .library.standard_gates.ecr import ECRGate
4939
-
4940
- return self.append(ECRGate(), [qubit1, qubit2], [], copy=False)
4931
+ return self._append_standard_gate(StandardGate.ECRGate, [qubit1, qubit2], ())
4941
4932
 
4942
4933
  def s(self, qubit: QubitSpecifier) -> InstructionSet:
4943
4934
  """Apply :class:`~qiskit.circuit.library.SGate`.
@@ -4950,9 +4941,7 @@ class QuantumCircuit:
4950
4941
  Returns:
4951
4942
  A handle to the instructions created.
4952
4943
  """
4953
- from .library.standard_gates.s import SGate
4954
-
4955
- return self.append(SGate(), [qubit], [], copy=False)
4944
+ return self._append_standard_gate(StandardGate.SGate, [qubit], ())
4956
4945
 
4957
4946
  def sdg(self, qubit: QubitSpecifier) -> InstructionSet:
4958
4947
  """Apply :class:`~qiskit.circuit.library.SdgGate`.
@@ -4965,9 +4954,7 @@ class QuantumCircuit:
4965
4954
  Returns:
4966
4955
  A handle to the instructions created.
4967
4956
  """
4968
- from .library.standard_gates.s import SdgGate
4969
-
4970
- return self.append(SdgGate(), [qubit], [], copy=False)
4957
+ return self._append_standard_gate(StandardGate.SdgGate, [qubit], ())
4971
4958
 
4972
4959
  def cs(
4973
4960
  self,
@@ -4991,6 +4978,12 @@ class QuantumCircuit:
4991
4978
  Returns:
4992
4979
  A handle to the instructions created.
4993
4980
  """
4981
+ # if the control state is |1> use the fast Rust version of the gate
4982
+ if ctrl_state is None or ctrl_state in ["1", 1]:
4983
+ return self._append_standard_gate(
4984
+ StandardGate.CSGate, [control_qubit, target_qubit], (), label=label
4985
+ )
4986
+
4994
4987
  from .library.standard_gates.s import CSGate
4995
4988
 
4996
4989
  return self.append(
@@ -5022,6 +5015,12 @@ class QuantumCircuit:
5022
5015
  Returns:
5023
5016
  A handle to the instructions created.
5024
5017
  """
5018
+ # if the control state is |1> use the fast Rust version of the gate
5019
+ if ctrl_state is None or ctrl_state in ["1", 1]:
5020
+ return self._append_standard_gate(
5021
+ StandardGate.CSdgGate, [control_qubit, target_qubit], (), label=label
5022
+ )
5023
+
5025
5024
  from .library.standard_gates.s import CSdgGate
5026
5025
 
5027
5026
  return self.append(
@@ -5042,9 +5041,11 @@ class QuantumCircuit:
5042
5041
  Returns:
5043
5042
  A handle to the instructions created.
5044
5043
  """
5045
- from .library.standard_gates.swap import SwapGate
5046
-
5047
- return self.append(SwapGate(), [qubit1, qubit2], [], copy=False)
5044
+ return self._append_standard_gate(
5045
+ StandardGate.SwapGate,
5046
+ [qubit1, qubit2],
5047
+ (),
5048
+ )
5048
5049
 
5049
5050
  def iswap(self, qubit1: QubitSpecifier, qubit2: QubitSpecifier) -> InstructionSet:
5050
5051
  """Apply :class:`~qiskit.circuit.library.iSwapGate`.
@@ -5057,9 +5058,7 @@ class QuantumCircuit:
5057
5058
  Returns:
5058
5059
  A handle to the instructions created.
5059
5060
  """
5060
- from .library.standard_gates.iswap import iSwapGate
5061
-
5062
- return self.append(iSwapGate(), [qubit1, qubit2], [], copy=False)
5061
+ return self._append_standard_gate(StandardGate.ISwapGate, [qubit1, qubit2], ())
5063
5062
 
5064
5063
  def cswap(
5065
5064
  self,
@@ -5085,6 +5084,15 @@ class QuantumCircuit:
5085
5084
  Returns:
5086
5085
  A handle to the instructions created.
5087
5086
  """
5087
+ # if the control state is |1> use the fast Rust version of the gate
5088
+ if ctrl_state is None or ctrl_state in ["1", 1]:
5089
+ return self._append_standard_gate(
5090
+ StandardGate.CSwapGate,
5091
+ [control_qubit, target_qubit1, target_qubit2],
5092
+ (),
5093
+ label=label,
5094
+ )
5095
+
5088
5096
  from .library.standard_gates.swap import CSwapGate
5089
5097
 
5090
5098
  return self.append(
@@ -5105,9 +5113,7 @@ class QuantumCircuit:
5105
5113
  Returns:
5106
5114
  A handle to the instructions created.
5107
5115
  """
5108
- from .library.standard_gates.sx import SXGate
5109
-
5110
- return self.append(SXGate(), [qubit], [], copy=False)
5116
+ return self._append_standard_gate(StandardGate.SXGate, [qubit], ())
5111
5117
 
5112
5118
  def sxdg(self, qubit: QubitSpecifier) -> InstructionSet:
5113
5119
  """Apply :class:`~qiskit.circuit.library.SXdgGate`.
@@ -5120,9 +5126,7 @@ class QuantumCircuit:
5120
5126
  Returns:
5121
5127
  A handle to the instructions created.
5122
5128
  """
5123
- from .library.standard_gates.sx import SXdgGate
5124
-
5125
- return self.append(SXdgGate(), [qubit], [], copy=False)
5129
+ return self._append_standard_gate(StandardGate.SXdgGate, [qubit], ())
5126
5130
 
5127
5131
  def csx(
5128
5132
  self,
@@ -5146,6 +5150,12 @@ class QuantumCircuit:
5146
5150
  Returns:
5147
5151
  A handle to the instructions created.
5148
5152
  """
5153
+ # if the control state is |1> use the fast Rust version of the gate
5154
+ if ctrl_state is None or ctrl_state in ["1", 1]:
5155
+ return self._append_standard_gate(
5156
+ StandardGate.CSXGate, [control_qubit, target_qubit], (), label=label
5157
+ )
5158
+
5149
5159
  from .library.standard_gates.sx import CSXGate
5150
5160
 
5151
5161
  return self.append(
@@ -5166,9 +5176,7 @@ class QuantumCircuit:
5166
5176
  Returns:
5167
5177
  A handle to the instructions created.
5168
5178
  """
5169
- from .library.standard_gates.t import TGate
5170
-
5171
- return self.append(TGate(), [qubit], [], copy=False)
5179
+ return self._append_standard_gate(StandardGate.TGate, [qubit], ())
5172
5180
 
5173
5181
  def tdg(self, qubit: QubitSpecifier) -> InstructionSet:
5174
5182
  """Apply :class:`~qiskit.circuit.library.TdgGate`.
@@ -5181,9 +5189,7 @@ class QuantumCircuit:
5181
5189
  Returns:
5182
5190
  A handle to the instructions created.
5183
5191
  """
5184
- from .library.standard_gates.t import TdgGate
5185
-
5186
- return self.append(TdgGate(), [qubit], [], copy=False)
5192
+ return self._append_standard_gate(StandardGate.TdgGate, [qubit], ())
5187
5193
 
5188
5194
  def u(
5189
5195
  self,
@@ -5205,9 +5211,7 @@ class QuantumCircuit:
5205
5211
  Returns:
5206
5212
  A handle to the instructions created.
5207
5213
  """
5208
- from .library.standard_gates.u import UGate
5209
-
5210
- return self.append(UGate(theta, phi, lam), [qubit], [], copy=False)
5214
+ return self._append_standard_gate(StandardGate.UGate, [qubit], [theta, phi, lam])
5211
5215
 
5212
5216
  def cu(
5213
5217
  self,
@@ -5239,6 +5243,15 @@ class QuantumCircuit:
5239
5243
  Returns:
5240
5244
  A handle to the instructions created.
5241
5245
  """
5246
+ # if the control state is |1> use the fast Rust version of the gate
5247
+ if ctrl_state is None or ctrl_state in ["1", 1]:
5248
+ return self._append_standard_gate(
5249
+ StandardGate.CUGate,
5250
+ [control_qubit, target_qubit],
5251
+ [theta, phi, lam, gamma],
5252
+ label=label,
5253
+ )
5254
+
5242
5255
  from .library.standard_gates.u import CUGate
5243
5256
 
5244
5257
  return self.append(
@@ -5260,9 +5273,7 @@ class QuantumCircuit:
5260
5273
  Returns:
5261
5274
  A handle to the instructions created.
5262
5275
  """
5263
- from .library.standard_gates.x import XGate
5264
-
5265
- return self.append(XGate(label=label), [qubit], [], copy=False)
5276
+ return self._append_standard_gate(StandardGate.XGate, [qubit], (), label=label)
5266
5277
 
5267
5278
  def cx(
5268
5279
  self,
@@ -5286,6 +5297,14 @@ class QuantumCircuit:
5286
5297
  Returns:
5287
5298
  A handle to the instructions created.
5288
5299
  """
5300
+ # if the control state is |1> use the fast Rust version of the gate
5301
+ if ctrl_state is None or ctrl_state in ["1", 1]:
5302
+ return self._append_standard_gate(
5303
+ StandardGate.CXGate,
5304
+ [control_qubit, target_qubit],
5305
+ (),
5306
+ label=label,
5307
+ )
5289
5308
 
5290
5309
  from .library.standard_gates.x import CXGate
5291
5310
 
@@ -5308,9 +5327,7 @@ class QuantumCircuit:
5308
5327
  Returns:
5309
5328
  A handle to the instructions created.
5310
5329
  """
5311
- from .library.standard_gates.dcx import DCXGate
5312
-
5313
- return self.append(DCXGate(), [qubit1, qubit2], [], copy=False)
5330
+ return self._append_standard_gate(StandardGate.DCXGate, [qubit1, qubit2], ())
5314
5331
 
5315
5332
  def ccx(
5316
5333
  self,
@@ -5334,6 +5351,14 @@ class QuantumCircuit:
5334
5351
  Returns:
5335
5352
  A handle to the instructions created.
5336
5353
  """
5354
+ # if the control state is |11> use the fast Rust version of the gate
5355
+ if ctrl_state is None or ctrl_state in ["11", 3]:
5356
+ return self._append_standard_gate(
5357
+ StandardGate.CCXGate,
5358
+ [control_qubit1, control_qubit2, target_qubit],
5359
+ (),
5360
+ )
5361
+
5337
5362
  from .library.standard_gates.x import CCXGate
5338
5363
 
5339
5364
  return self.append(
@@ -5379,12 +5404,12 @@ class QuantumCircuit:
5379
5404
  ValueError: if the given mode is not known, or if too few ancilla qubits are passed.
5380
5405
  AttributeError: if no ancilla qubits are passed, but some are needed.
5381
5406
  """
5382
- from .library.standard_gates.x import MCXGrayCode, MCXRecursive, MCXVChain
5407
+ from .library.standard_gates.x import MCXGate, MCXRecursive, MCXVChain
5383
5408
 
5384
5409
  num_ctrl_qubits = len(control_qubits)
5385
5410
 
5386
5411
  available_implementations = {
5387
- "noancilla": MCXGrayCode(num_ctrl_qubits, ctrl_state=ctrl_state),
5412
+ "noancilla": MCXGate(num_ctrl_qubits, ctrl_state=ctrl_state),
5388
5413
  "recursion": MCXRecursive(num_ctrl_qubits, ctrl_state=ctrl_state),
5389
5414
  "v-chain": MCXVChain(num_ctrl_qubits, False, ctrl_state=ctrl_state),
5390
5415
  "v-chain-dirty": MCXVChain(num_ctrl_qubits, dirty_ancillas=True, ctrl_state=ctrl_state),
@@ -5398,7 +5423,7 @@ class QuantumCircuit:
5398
5423
 
5399
5424
  # check ancilla input
5400
5425
  if ancilla_qubits:
5401
- _ = self.qbit_argument_conversion(ancilla_qubits)
5426
+ _ = self._qbit_argument_conversion(ancilla_qubits)
5402
5427
 
5403
5428
  try:
5404
5429
  gate = available_implementations[mode]
@@ -5438,9 +5463,7 @@ class QuantumCircuit:
5438
5463
  Returns:
5439
5464
  A handle to the instructions created.
5440
5465
  """
5441
- from .library.standard_gates.y import YGate
5442
-
5443
- return self.append(YGate(), [qubit], [], copy=False)
5466
+ return self._append_standard_gate(StandardGate.YGate, [qubit], ())
5444
5467
 
5445
5468
  def cy(
5446
5469
  self,
@@ -5464,6 +5487,15 @@ class QuantumCircuit:
5464
5487
  Returns:
5465
5488
  A handle to the instructions created.
5466
5489
  """
5490
+ # if the control state is |1> use the fast Rust version of the gate
5491
+ if ctrl_state is None or ctrl_state in ["1", 1]:
5492
+ return self._append_standard_gate(
5493
+ StandardGate.CYGate,
5494
+ [control_qubit, target_qubit],
5495
+ (),
5496
+ label=label,
5497
+ )
5498
+
5467
5499
  from .library.standard_gates.y import CYGate
5468
5500
 
5469
5501
  return self.append(
@@ -5484,9 +5516,7 @@ class QuantumCircuit:
5484
5516
  Returns:
5485
5517
  A handle to the instructions created.
5486
5518
  """
5487
- from .library.standard_gates.z import ZGate
5488
-
5489
- return self.append(ZGate(), [qubit], [], copy=False)
5519
+ return self._append_standard_gate(StandardGate.ZGate, [qubit], ())
5490
5520
 
5491
5521
  def cz(
5492
5522
  self,
@@ -5510,6 +5540,12 @@ class QuantumCircuit:
5510
5540
  Returns:
5511
5541
  A handle to the instructions created.
5512
5542
  """
5543
+ # if the control state is |1> use the fast Rust version of the gate
5544
+ if ctrl_state is None or ctrl_state in ["1", 1]:
5545
+ return self._append_standard_gate(
5546
+ StandardGate.CZGate, [control_qubit, target_qubit], (), label=label
5547
+ )
5548
+
5513
5549
  from .library.standard_gates.z import CZGate
5514
5550
 
5515
5551
  return self.append(
@@ -5543,6 +5579,15 @@ class QuantumCircuit:
5543
5579
  Returns:
5544
5580
  A handle to the instructions created.
5545
5581
  """
5582
+ # if the control state is |11> use the fast Rust version of the gate
5583
+ if ctrl_state is None or ctrl_state in ["11", 3]:
5584
+ return self._append_standard_gate(
5585
+ StandardGate.CCZGate,
5586
+ [control_qubit1, control_qubit2, target_qubit],
5587
+ (),
5588
+ label=label,
5589
+ )
5590
+
5546
5591
  from .library.standard_gates.z import CCZGate
5547
5592
 
5548
5593
  return self.append(
@@ -5704,7 +5749,7 @@ class QuantumCircuit:
5704
5749
  * Statevector or vector of complex amplitudes to initialize to.
5705
5750
  * Labels of basis states of the Pauli eigenstates Z, X, Y. See
5706
5751
  :meth:`.Statevector.from_label`. Notice the order of the labels is reversed with
5707
- respect to the qubit index to be applied to. Example label '01' initializes the
5752
+ respect to the qubit index to be applied to. Example label ``'01'`` initializes the
5708
5753
  qubit zero to :math:`|1\rangle` and the qubit one to :math:`|0\rangle`.
5709
5754
  * An integer that is used as a bitmap indicating which qubits to initialize to
5710
5755
  :math:`|1\rangle`. Example: setting params to 5 would initialize qubit 0 and qubit
@@ -5878,7 +5923,7 @@ class QuantumCircuit:
5878
5923
  """Finish a scope used in the control-flow builder interface, and return it to the caller.
5879
5924
 
5880
5925
  This should only be done by the control-flow context managers, since they naturally
5881
- synchronise the creation and deletion of stack elements."""
5926
+ synchronize the creation and deletion of stack elements."""
5882
5927
  return self._control_flow_scopes.pop()
5883
5928
 
5884
5929
  def _peek_previous_instruction_in_scope(self) -> CircuitInstruction:
@@ -5905,36 +5950,8 @@ class QuantumCircuit:
5905
5950
  if not self._data:
5906
5951
  raise CircuitError("This circuit contains no instructions.")
5907
5952
  instruction = self._data.pop()
5908
- if isinstance(instruction.operation, Instruction):
5909
- self._update_parameter_table_on_instruction_removal(instruction)
5910
5953
  return instruction
5911
5954
 
5912
- def _update_parameter_table_on_instruction_removal(self, instruction: CircuitInstruction):
5913
- """Update the :obj:`.ParameterTable` of this circuit given that an instance of the given
5914
- ``instruction`` has just been removed from the circuit.
5915
-
5916
- .. note::
5917
-
5918
- This does not account for the possibility for the same instruction instance being added
5919
- more than once to the circuit. At the time of writing (2021-11-17, main commit 271a82f)
5920
- there is a defensive ``deepcopy`` of parameterised instructions inside
5921
- :meth:`.QuantumCircuit.append`, so this should be safe. Trying to account for it would
5922
- involve adding a potentially quadratic-scaling loop to check each entry in ``data``.
5923
- """
5924
- atomic_parameters: list[tuple[Parameter, int]] = []
5925
- for index, parameter in enumerate(instruction.operation.params):
5926
- if isinstance(parameter, (ParameterExpression, QuantumCircuit)):
5927
- atomic_parameters.extend((p, index) for p in parameter.parameters)
5928
- for atomic_parameter, index in atomic_parameters:
5929
- new_entries = self._parameter_table[atomic_parameter].copy()
5930
- new_entries.discard((instruction.operation, index))
5931
- if not new_entries:
5932
- del self._parameter_table[atomic_parameter]
5933
- # Invalidate cache.
5934
- self._parameters = None
5935
- else:
5936
- self._parameter_table[atomic_parameter] = new_entries
5937
-
5938
5955
  @typing.overload
5939
5956
  def while_loop(
5940
5957
  self,
@@ -6580,13 +6597,14 @@ class _OuterCircuitScopeInterface(CircuitScopeInterface):
6580
6597
  def instructions(self):
6581
6598
  return self.circuit._data
6582
6599
 
6583
- def append(self, instruction):
6600
+ def append(self, instruction, *, _standard_gate: bool = False):
6584
6601
  # QuantumCircuit._append is semi-public, so we just call back to it.
6585
- return self.circuit._append(instruction)
6602
+ return self.circuit._append(instruction, _standard_gate=_standard_gate)
6586
6603
 
6587
6604
  def extend(self, data: CircuitData):
6588
6605
  self.circuit._data.extend(data)
6589
- data.foreach_op(self.circuit._track_operation)
6606
+ self.circuit.duration = None
6607
+ self.circuit.unit = "dt"
6590
6608
 
6591
6609
  def resolve_classical_resource(self, specifier):
6592
6610
  # This is slightly different to cbit_argument_conversion, because it should not
@@ -6743,11 +6761,3 @@ def _bit_argument_conversion_scalar(specifier, bit_sequence, bit_set, type_):
6743
6761
  else f"Invalid bit index: '{specifier}' of type '{type(specifier)}'"
6744
6762
  )
6745
6763
  raise CircuitError(message)
6746
-
6747
-
6748
- def _normalize_global_phase(angle):
6749
- """Return the normalized form of an angle for use in the global phase. This coerces to float if
6750
- possible, and fixes to the interval :math:`[0, 2\\pi)`."""
6751
- if isinstance(angle, ParameterExpression) and angle.parameters:
6752
- return angle
6753
- return float(angle) % (2.0 * np.pi)