qiskit 1.1.2__cp38-abi3-win32.whl → 1.2.0rc1__cp38-abi3-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. qiskit/VERSION.txt +1 -1
  2. qiskit/__init__.py +27 -24
  3. qiskit/_accelerate.pyd +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 +1 -1
  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/boolean_expression.py +1 -1
  18. qiskit/circuit/classicalfunction/classical_function_visitor.py +5 -5
  19. qiskit/circuit/classicalfunction/utils.py +1 -1
  20. qiskit/circuit/classicalregister.py +1 -1
  21. qiskit/circuit/commutation_checker.py +83 -35
  22. qiskit/circuit/controlflow/_builder_utils.py +1 -1
  23. qiskit/circuit/controlflow/builder.py +10 -6
  24. qiskit/circuit/controlflow/if_else.py +2 -2
  25. qiskit/circuit/controlflow/switch_case.py +1 -1
  26. qiskit/circuit/delay.py +1 -1
  27. qiskit/circuit/duration.py +2 -2
  28. qiskit/circuit/equivalence.py +5 -7
  29. qiskit/circuit/gate.py +11 -8
  30. qiskit/circuit/instruction.py +31 -13
  31. qiskit/circuit/instructionset.py +2 -5
  32. qiskit/circuit/library/__init__.py +2 -1
  33. qiskit/circuit/library/arithmetic/linear_amplitude_function.py +1 -1
  34. qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +1 -1
  35. qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +1 -1
  36. qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +1 -1
  37. qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +3 -3
  38. qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py +1 -1
  39. qiskit/circuit/library/basis_change/__init__.py +1 -1
  40. qiskit/circuit/library/basis_change/qft.py +40 -6
  41. qiskit/circuit/library/blueprintcircuit.py +3 -5
  42. qiskit/circuit/library/data_preparation/__init__.py +9 -2
  43. qiskit/circuit/library/data_preparation/initializer.py +8 -0
  44. qiskit/circuit/library/data_preparation/state_preparation.py +98 -178
  45. qiskit/circuit/library/generalized_gates/isometry.py +8 -8
  46. qiskit/circuit/library/generalized_gates/linear_function.py +3 -2
  47. qiskit/circuit/library/generalized_gates/mcg_up_to_diagonal.py +4 -4
  48. qiskit/circuit/library/generalized_gates/permutation.py +8 -9
  49. qiskit/circuit/library/generalized_gates/uc.py +3 -3
  50. qiskit/circuit/library/generalized_gates/uc_pauli_rot.py +2 -2
  51. qiskit/circuit/library/generalized_gates/unitary.py +13 -11
  52. qiskit/circuit/library/graph_state.py +1 -1
  53. qiskit/circuit/library/hamiltonian_gate.py +1 -2
  54. qiskit/circuit/library/hidden_linear_function.py +1 -1
  55. qiskit/circuit/library/n_local/evolved_operator_ansatz.py +3 -2
  56. qiskit/circuit/library/n_local/n_local.py +4 -5
  57. qiskit/circuit/library/n_local/pauli_two_design.py +1 -1
  58. qiskit/circuit/library/n_local/qaoa_ansatz.py +6 -8
  59. qiskit/circuit/library/n_local/two_local.py +1 -1
  60. qiskit/circuit/library/overlap.py +11 -5
  61. qiskit/circuit/library/pauli_evolution.py +7 -3
  62. qiskit/circuit/library/standard_gates/dcx.py +3 -0
  63. qiskit/circuit/library/standard_gates/ecr.py +3 -0
  64. qiskit/circuit/library/standard_gates/global_phase.py +3 -0
  65. qiskit/circuit/library/standard_gates/h.py +13 -5
  66. qiskit/circuit/library/standard_gates/i.py +3 -0
  67. qiskit/circuit/library/standard_gates/iswap.py +3 -0
  68. qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +19 -10
  69. qiskit/circuit/library/standard_gates/p.py +14 -9
  70. qiskit/circuit/library/standard_gates/r.py +3 -0
  71. qiskit/circuit/library/standard_gates/rx.py +21 -6
  72. qiskit/circuit/library/standard_gates/rxx.py +40 -1
  73. qiskit/circuit/library/standard_gates/ry.py +21 -6
  74. qiskit/circuit/library/standard_gates/ryy.py +40 -1
  75. qiskit/circuit/library/standard_gates/rz.py +22 -6
  76. qiskit/circuit/library/standard_gates/rzx.py +40 -1
  77. qiskit/circuit/library/standard_gates/rzz.py +41 -2
  78. qiskit/circuit/library/standard_gates/s.py +77 -0
  79. qiskit/circuit/library/standard_gates/swap.py +12 -5
  80. qiskit/circuit/library/standard_gates/sx.py +14 -5
  81. qiskit/circuit/library/standard_gates/t.py +5 -0
  82. qiskit/circuit/library/standard_gates/u.py +22 -7
  83. qiskit/circuit/library/standard_gates/u1.py +8 -3
  84. qiskit/circuit/library/standard_gates/u2.py +3 -0
  85. qiskit/circuit/library/standard_gates/u3.py +22 -7
  86. qiskit/circuit/library/standard_gates/x.py +156 -92
  87. qiskit/circuit/library/standard_gates/xx_minus_yy.py +40 -1
  88. qiskit/circuit/library/standard_gates/xx_plus_yy.py +52 -11
  89. qiskit/circuit/library/standard_gates/y.py +6 -1
  90. qiskit/circuit/library/standard_gates/z.py +8 -1
  91. qiskit/circuit/operation.py +1 -1
  92. qiskit/circuit/parameter.py +9 -10
  93. qiskit/circuit/parameterexpression.py +16 -13
  94. qiskit/circuit/parametertable.py +1 -190
  95. qiskit/circuit/parametervector.py +1 -1
  96. qiskit/circuit/quantumcircuit.py +392 -384
  97. qiskit/circuit/quantumcircuitdata.py +3 -5
  98. qiskit/circuit/quantumregister.py +1 -1
  99. qiskit/circuit/random/__init__.py +1 -1
  100. qiskit/circuit/random/utils.py +175 -26
  101. qiskit/circuit/register.py +5 -7
  102. qiskit/circuit/singleton.py +3 -3
  103. qiskit/circuit/tools/pi_check.py +4 -4
  104. qiskit/compiler/assembler.py +95 -24
  105. qiskit/compiler/scheduler.py +2 -2
  106. qiskit/compiler/transpiler.py +41 -127
  107. qiskit/converters/circuit_to_dag.py +4 -6
  108. qiskit/converters/circuit_to_gate.py +4 -8
  109. qiskit/converters/circuit_to_instruction.py +5 -17
  110. qiskit/converters/dag_to_circuit.py +2 -6
  111. qiskit/dagcircuit/collect_blocks.py +2 -2
  112. qiskit/dagcircuit/dagcircuit.py +190 -187
  113. qiskit/dagcircuit/dagdependency.py +4 -4
  114. qiskit/dagcircuit/dagdependency_v2.py +4 -4
  115. qiskit/dagcircuit/dagdepnode.py +1 -1
  116. qiskit/dagcircuit/dagnode.py +66 -157
  117. qiskit/passmanager/flow_controllers.py +1 -1
  118. qiskit/passmanager/passmanager.py +3 -3
  119. qiskit/primitives/__init__.py +1 -5
  120. qiskit/primitives/backend_estimator.py +25 -15
  121. qiskit/primitives/backend_estimator_v2.py +31 -7
  122. qiskit/primitives/backend_sampler.py +21 -12
  123. qiskit/primitives/backend_sampler_v2.py +12 -3
  124. qiskit/primitives/base/base_estimator.py +31 -4
  125. qiskit/primitives/base/base_primitive.py +2 -2
  126. qiskit/primitives/base/base_result.py +2 -2
  127. qiskit/primitives/base/base_sampler.py +26 -2
  128. qiskit/primitives/base/estimator_result.py +2 -2
  129. qiskit/primitives/base/sampler_result.py +2 -2
  130. qiskit/primitives/containers/__init__.py +0 -1
  131. qiskit/primitives/containers/bindings_array.py +2 -2
  132. qiskit/primitives/containers/bit_array.py +108 -10
  133. qiskit/primitives/containers/shape.py +3 -3
  134. qiskit/primitives/estimator.py +9 -2
  135. qiskit/primitives/primitive_job.py +1 -1
  136. qiskit/primitives/sampler.py +10 -3
  137. qiskit/primitives/statevector_estimator.py +5 -3
  138. qiskit/primitives/statevector_sampler.py +11 -5
  139. qiskit/primitives/utils.py +16 -0
  140. qiskit/providers/backend.py +15 -6
  141. qiskit/providers/backend_compat.py +7 -4
  142. qiskit/providers/basic_provider/basic_provider_tools.py +1 -1
  143. qiskit/providers/basic_provider/basic_simulator.py +32 -24
  144. qiskit/providers/fake_provider/fake_backend.py +10 -3
  145. qiskit/providers/fake_provider/fake_openpulse_2q.py +154 -146
  146. qiskit/providers/fake_provider/fake_openpulse_3q.py +226 -217
  147. qiskit/providers/fake_provider/fake_qasm_backend.py +5 -1
  148. qiskit/providers/fake_provider/generic_backend_v2.py +80 -50
  149. qiskit/providers/models/__init__.py +11 -0
  150. qiskit/providers/models/backendconfiguration.py +50 -4
  151. qiskit/providers/models/backendproperties.py +13 -2
  152. qiskit/providers/models/pulsedefaults.py +10 -11
  153. qiskit/providers/options.py +13 -13
  154. qiskit/providers/providerutils.py +3 -1
  155. qiskit/pulse/configuration.py +8 -12
  156. qiskit/pulse/instruction_schedule_map.py +3 -5
  157. qiskit/pulse/instructions/acquire.py +7 -8
  158. qiskit/pulse/instructions/instruction.py +2 -3
  159. qiskit/pulse/library/samplers/decorators.py +5 -9
  160. qiskit/pulse/library/symbolic_pulses.py +4 -7
  161. qiskit/pulse/library/waveform.py +2 -5
  162. qiskit/pulse/macros.py +11 -6
  163. qiskit/pulse/parser.py +8 -10
  164. qiskit/pulse/schedule.py +9 -17
  165. qiskit/pulse/transforms/alignments.py +1 -3
  166. qiskit/pulse/utils.py +1 -2
  167. qiskit/qasm/libs/stdgates.inc +35 -28
  168. qiskit/qasm2/__init__.py +7 -7
  169. qiskit/qasm2/export.py +5 -9
  170. qiskit/qasm2/parse.py +1 -1
  171. qiskit/qasm3/ast.py +9 -25
  172. qiskit/qasm3/exporter.py +578 -481
  173. qiskit/qasm3/printer.py +7 -16
  174. qiskit/qobj/common.py +10 -0
  175. qiskit/qobj/converters/lo_config.py +9 -0
  176. qiskit/qobj/converters/pulse_instruction.py +13 -6
  177. qiskit/qobj/pulse_qobj.py +69 -15
  178. qiskit/qobj/qasm_qobj.py +72 -20
  179. qiskit/qobj/utils.py +9 -0
  180. qiskit/qpy/binary_io/circuits.py +8 -5
  181. qiskit/qpy/binary_io/schedules.py +1 -1
  182. qiskit/qpy/binary_io/value.py +3 -3
  183. qiskit/qpy/interface.py +3 -2
  184. qiskit/qpy/type_keys.py +2 -2
  185. qiskit/quantum_info/operators/channel/quantum_channel.py +3 -6
  186. qiskit/quantum_info/operators/channel/superop.py +2 -2
  187. qiskit/quantum_info/operators/channel/transformations.py +1 -1
  188. qiskit/quantum_info/operators/dihedral/dihedral.py +3 -4
  189. qiskit/quantum_info/operators/dihedral/dihedral_circuits.py +1 -3
  190. qiskit/quantum_info/operators/dihedral/random.py +6 -3
  191. qiskit/quantum_info/operators/measures.py +2 -2
  192. qiskit/quantum_info/operators/op_shape.py +12 -20
  193. qiskit/quantum_info/operators/operator.py +14 -21
  194. qiskit/quantum_info/operators/predicates.py +1 -0
  195. qiskit/quantum_info/operators/symplectic/base_pauli.py +7 -11
  196. qiskit/quantum_info/operators/symplectic/clifford.py +1 -1
  197. qiskit/quantum_info/operators/symplectic/pauli.py +3 -3
  198. qiskit/quantum_info/operators/symplectic/pauli_list.py +9 -10
  199. qiskit/quantum_info/operators/symplectic/random.py +1 -1
  200. qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +14 -16
  201. qiskit/quantum_info/quaternion.py +1 -1
  202. qiskit/quantum_info/states/densitymatrix.py +5 -8
  203. qiskit/quantum_info/states/stabilizerstate.py +128 -37
  204. qiskit/quantum_info/states/statevector.py +4 -8
  205. qiskit/result/counts.py +2 -2
  206. qiskit/result/mitigation/correlated_readout_mitigator.py +2 -2
  207. qiskit/result/mitigation/local_readout_mitigator.py +2 -2
  208. qiskit/result/mitigation/utils.py +1 -3
  209. qiskit/result/models.py +17 -16
  210. qiskit/result/result.py +15 -20
  211. qiskit/scheduler/lowering.py +2 -2
  212. qiskit/synthesis/__init__.py +2 -1
  213. qiskit/synthesis/clifford/__init__.py +1 -1
  214. qiskit/synthesis/clifford/clifford_decompose_ag.py +2 -2
  215. qiskit/synthesis/clifford/clifford_decompose_bm.py +10 -240
  216. qiskit/synthesis/clifford/clifford_decompose_greedy.py +9 -303
  217. qiskit/synthesis/clifford/clifford_decompose_layers.py +25 -23
  218. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_full.py +1 -1
  219. qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_general.py +1 -1
  220. qiskit/synthesis/discrete_basis/generate_basis_approximations.py +1 -1
  221. qiskit/synthesis/discrete_basis/solovay_kitaev.py +2 -2
  222. qiskit/synthesis/evolution/evolution_synthesis.py +4 -2
  223. qiskit/synthesis/evolution/lie_trotter.py +46 -19
  224. qiskit/synthesis/evolution/product_formula.py +111 -55
  225. qiskit/synthesis/evolution/qdrift.py +40 -10
  226. qiskit/synthesis/evolution/suzuki_trotter.py +43 -33
  227. qiskit/synthesis/linear/__init__.py +1 -0
  228. qiskit/synthesis/linear/cnot_synth.py +22 -96
  229. qiskit/synthesis/linear/linear_depth_lnn.py +8 -8
  230. qiskit/synthesis/linear/linear_matrix_utils.py +13 -161
  231. qiskit/synthesis/linear_phase/cnot_phase_synth.py +1 -1
  232. qiskit/synthesis/linear_phase/cx_cz_depth_lnn.py +3 -3
  233. qiskit/synthesis/linear_phase/cz_depth_lnn.py +1 -1
  234. qiskit/synthesis/one_qubit/one_qubit_decompose.py +29 -29
  235. qiskit/synthesis/permutation/permutation_full.py +5 -29
  236. qiskit/synthesis/permutation/permutation_lnn.py +2 -24
  237. qiskit/synthesis/permutation/permutation_utils.py +2 -59
  238. qiskit/synthesis/qft/__init__.py +1 -0
  239. qiskit/synthesis/qft/qft_decompose_full.py +79 -0
  240. qiskit/synthesis/qft/qft_decompose_lnn.py +17 -9
  241. qiskit/synthesis/stabilizer/stabilizer_circuit.py +6 -6
  242. qiskit/synthesis/stabilizer/stabilizer_decompose.py +2 -2
  243. qiskit/synthesis/two_qubit/local_invariance.py +8 -38
  244. qiskit/synthesis/two_qubit/two_qubit_decompose.py +48 -129
  245. qiskit/synthesis/unitary/aqc/cnot_structures.py +1 -1
  246. qiskit/synthesis/unitary/qsd.py +5 -3
  247. qiskit/transpiler/__init__.py +1 -0
  248. qiskit/transpiler/basepasses.py +1 -1
  249. qiskit/transpiler/coupling.py +3 -3
  250. qiskit/transpiler/instruction_durations.py +1 -2
  251. qiskit/transpiler/layout.py +3 -3
  252. qiskit/transpiler/passes/__init__.py +2 -0
  253. qiskit/transpiler/passes/basis/basis_translator.py +82 -63
  254. qiskit/transpiler/passes/basis/translate_parameterized.py +3 -5
  255. qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
  256. qiskit/transpiler/passes/basis/unroll_custom_definitions.py +10 -10
  257. qiskit/transpiler/passes/calibration/rx_builder.py +3 -3
  258. qiskit/transpiler/passes/calibration/rzx_builder.py +3 -3
  259. qiskit/transpiler/passes/layout/apply_layout.py +13 -3
  260. qiskit/transpiler/passes/layout/sabre_layout.py +10 -8
  261. qiskit/transpiler/passes/layout/sabre_pre_layout.py +4 -1
  262. qiskit/transpiler/passes/layout/set_layout.py +2 -2
  263. qiskit/transpiler/passes/layout/vf2_layout.py +1 -1
  264. qiskit/transpiler/passes/layout/vf2_utils.py +3 -3
  265. qiskit/transpiler/passes/optimization/__init__.py +1 -0
  266. qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +2 -2
  267. qiskit/transpiler/passes/optimization/commutation_analysis.py +7 -10
  268. qiskit/transpiler/passes/optimization/commutative_cancellation.py +35 -19
  269. qiskit/transpiler/passes/optimization/consolidate_blocks.py +11 -8
  270. qiskit/transpiler/passes/optimization/inverse_cancellation.py +6 -6
  271. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +64 -41
  272. qiskit/transpiler/passes/optimization/optimize_1q_gates.py +1 -1
  273. qiskit/transpiler/passes/optimization/split_2q_unitaries.py +83 -0
  274. qiskit/transpiler/passes/optimization/template_matching/backward_match.py +1 -1
  275. qiskit/transpiler/passes/optimization/template_matching/forward_match.py +2 -2
  276. qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +1 -1
  277. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +3 -2
  278. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +1 -1
  279. qiskit/transpiler/passes/routing/layout_transformation.py +2 -1
  280. qiskit/transpiler/passes/routing/sabre_swap.py +35 -26
  281. qiskit/transpiler/passes/routing/star_prerouting.py +80 -105
  282. qiskit/transpiler/passes/routing/stochastic_swap.py +1 -3
  283. qiskit/transpiler/passes/scheduling/alap.py +1 -2
  284. qiskit/transpiler/passes/scheduling/alignments/__init__.py +2 -2
  285. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
  286. qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +1 -1
  287. qiskit/transpiler/passes/scheduling/alignments/reschedule.py +1 -1
  288. qiskit/transpiler/passes/scheduling/asap.py +1 -2
  289. qiskit/transpiler/passes/scheduling/base_scheduler.py +5 -5
  290. qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +3 -3
  291. qiskit/transpiler/passes/scheduling/padding/base_padding.py +1 -1
  292. qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +11 -11
  293. qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +7 -6
  294. qiskit/transpiler/passes/scheduling/time_unit_conversion.py +4 -3
  295. qiskit/transpiler/passes/synthesis/high_level_synthesis.py +211 -36
  296. qiskit/transpiler/passes/synthesis/plugin.py +2 -2
  297. qiskit/transpiler/passes/synthesis/unitary_synthesis.py +80 -40
  298. qiskit/transpiler/passes/utils/__init__.py +0 -1
  299. qiskit/transpiler/passes/utils/check_gate_direction.py +4 -4
  300. qiskit/transpiler/passes/utils/check_map.py +3 -6
  301. qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +3 -4
  302. qiskit/transpiler/passes/utils/error.py +2 -2
  303. qiskit/transpiler/passes/utils/fixed_point.py +3 -3
  304. qiskit/transpiler/passes/utils/gate_direction.py +1 -1
  305. qiskit/transpiler/passes/utils/gates_basis.py +1 -2
  306. qiskit/transpiler/passmanager.py +7 -6
  307. qiskit/transpiler/preset_passmanagers/__init__.py +4 -228
  308. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +117 -18
  309. qiskit/transpiler/preset_passmanagers/common.py +3 -6
  310. qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +518 -0
  311. qiskit/transpiler/preset_passmanagers/level0.py +1 -1
  312. qiskit/transpiler/target.py +27 -8
  313. qiskit/user_config.py +29 -6
  314. qiskit/utils/classtools.py +3 -3
  315. qiskit/utils/deprecation.py +3 -2
  316. qiskit/utils/lazy_tester.py +2 -2
  317. qiskit/utils/optionals.py +8 -8
  318. qiskit/visualization/bloch.py +19 -67
  319. qiskit/visualization/circuit/_utils.py +34 -10
  320. qiskit/visualization/circuit/circuit_visualization.py +23 -16
  321. qiskit/visualization/circuit/latex.py +29 -27
  322. qiskit/visualization/circuit/matplotlib.py +4 -2
  323. qiskit/visualization/circuit/qcstyle.py +2 -2
  324. qiskit/visualization/circuit/text.py +9 -15
  325. qiskit/visualization/dag_visualization.py +5 -12
  326. qiskit/visualization/pulse_v2/core.py +1 -1
  327. qiskit/visualization/pulse_v2/events.py +1 -1
  328. qiskit/visualization/pulse_v2/generators/frame.py +3 -4
  329. qiskit/visualization/pulse_v2/generators/waveform.py +5 -9
  330. qiskit/visualization/pulse_v2/layouts.py +1 -5
  331. qiskit/visualization/pulse_v2/plotters/matplotlib.py +1 -2
  332. qiskit/visualization/state_visualization.py +5 -6
  333. qiskit/visualization/timeline/plotters/matplotlib.py +1 -2
  334. qiskit/visualization/transition_visualization.py +7 -2
  335. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/METADATA +26 -26
  336. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/RECORD +340 -338
  337. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/WHEEL +1 -1
  338. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/entry_points.txt +3 -0
  339. qiskit/transpiler/passes/utils/block_to_matrix.py +0 -47
  340. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/LICENSE.txt +0 -0
  341. {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.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,14 +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)
3643
- # Invalidate parameters caching.
3644
- cpy._parameters = None
3714
+ cpy._data = CircuitData(
3715
+ self._data.qubits, self._data.clbits, global_phase=self._data.global_phase
3716
+ )
3645
3717
 
3646
3718
  cpy._calibrations = _copy.deepcopy(self._calibrations)
3647
3719
  cpy._metadata = _copy.deepcopy(self._metadata)
@@ -3661,7 +3733,6 @@ class QuantumCircuit:
3661
3733
  quantum and classical typed data, but without mutating the original circuit.
3662
3734
  """
3663
3735
  self._data.clear()
3664
- self._parameter_table.clear()
3665
3736
  # Repopulate the parameter table with any phase symbols.
3666
3737
  self.global_phase = self.global_phase
3667
3738
 
@@ -3818,7 +3889,7 @@ class QuantumCircuit:
3818
3889
  inplace (bool): All measurements inplace or return new circuit.
3819
3890
 
3820
3891
  Returns:
3821
- QuantumCircuit: Returns circuit with measurements when `inplace = False`.
3892
+ QuantumCircuit: Returns circuit with measurements when ``inplace = False``.
3822
3893
  """
3823
3894
  from qiskit.converters.circuit_to_dag import circuit_to_dag
3824
3895
 
@@ -3865,18 +3936,18 @@ class QuantumCircuit:
3865
3936
  else:
3866
3937
  circ = self.copy()
3867
3938
  if add_bits:
3868
- new_creg = circ._create_creg(len(circ.qubits), "meas")
3939
+ new_creg = circ._create_creg(circ.num_qubits, "meas")
3869
3940
  circ.add_register(new_creg)
3870
3941
  circ.barrier()
3871
3942
  circ.measure(circ.qubits, new_creg)
3872
3943
  else:
3873
- if len(circ.clbits) < len(circ.qubits):
3944
+ if circ.num_clbits < circ.num_qubits:
3874
3945
  raise CircuitError(
3875
3946
  "The number of classical bits must be equal or greater than "
3876
3947
  "the number of qubits."
3877
3948
  )
3878
3949
  circ.barrier()
3879
- circ.measure(circ.qubits, circ.clbits[0 : len(circ.qubits)])
3950
+ circ.measure(circ.qubits, circ.clbits[0 : circ.num_qubits])
3880
3951
 
3881
3952
  if not inplace:
3882
3953
  return circ
@@ -3945,10 +4016,9 @@ class QuantumCircuit:
3945
4016
  circ._clbit_indices = {}
3946
4017
 
3947
4018
  # Clear instruction info
3948
- circ._data = CircuitData(qubits=circ._data.qubits, reserve=len(circ._data))
3949
- circ._parameter_table.clear()
3950
- # Repopulate the parameter table with any global-phase entries.
3951
- 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
+ )
3952
4022
 
3953
4023
  # We must add the clbits first to preserve the original circuit
3954
4024
  # order. This way, add_register never adds clbits and just
@@ -4021,7 +4091,7 @@ class QuantumCircuit:
4021
4091
  """The global phase of the current circuit scope in radians."""
4022
4092
  if self._control_flow_scopes:
4023
4093
  return self._control_flow_scopes[-1].global_phase
4024
- return self._global_phase
4094
+ return self._data.global_phase
4025
4095
 
4026
4096
  @global_phase.setter
4027
4097
  def global_phase(self, angle: ParameterValueType):
@@ -4030,25 +4100,10 @@ class QuantumCircuit:
4030
4100
  Args:
4031
4101
  angle (float, ParameterExpression): radians
4032
4102
  """
4033
- # If we're currently parametric, we need to throw away the references. This setter is
4034
- # called by some subclasses before the inner `_global_phase` is initialised.
4035
- global_phase_reference = (ParameterTable.GLOBAL_PHASE, None)
4036
- if isinstance(previous := getattr(self, "_global_phase", None), ParameterExpression):
4037
- self._parameters = None
4038
- self._parameter_table.discard_references(previous, global_phase_reference)
4039
-
4040
- if isinstance(angle, ParameterExpression) and angle.parameters:
4041
- for parameter in angle.parameters:
4042
- if parameter not in self._parameter_table:
4043
- self._parameters = None
4044
- self._parameter_table[parameter] = ParameterReferences(())
4045
- self._parameter_table[parameter].add(global_phase_reference)
4046
- else:
4047
- angle = _normalize_global_phase(angle)
4048
4103
  if self._control_flow_scopes:
4049
4104
  self._control_flow_scopes[-1].global_phase = angle
4050
4105
  else:
4051
- self._global_phase = angle
4106
+ self._data.global_phase = angle
4052
4107
 
4053
4108
  @property
4054
4109
  def parameters(self) -> ParameterView:
@@ -4109,16 +4164,13 @@ class QuantumCircuit:
4109
4164
  Returns:
4110
4165
  The sorted :class:`.Parameter` objects in the circuit.
4111
4166
  """
4112
- # parameters from gates
4113
- if self._parameters is None:
4114
- self._parameters = sort_parameters(self._unsorted_parameters())
4115
4167
  # return as parameter view, which implements the set and list interface
4116
- return ParameterView(self._parameters)
4168
+ return ParameterView(self._data.parameters)
4117
4169
 
4118
4170
  @property
4119
4171
  def num_parameters(self) -> int:
4120
4172
  """The number of parameter objects in the circuit."""
4121
- return len(self._parameter_table)
4173
+ return self._data.num_parameters()
4122
4174
 
4123
4175
  def _unsorted_parameters(self) -> set[Parameter]:
4124
4176
  """Efficiently get all parameters in the circuit, without any sorting overhead.
@@ -4131,7 +4183,7 @@ class QuantumCircuit:
4131
4183
  """
4132
4184
  # This should be free, by accessing the actual backing data structure of the table, but that
4133
4185
  # means that we need to copy it if adding keys from the global phase.
4134
- return self._parameter_table.get_keys()
4186
+ return self._data.unsorted_parameters()
4135
4187
 
4136
4188
  @overload
4137
4189
  def assign_parameters(
@@ -4244,94 +4296,28 @@ class QuantumCircuit:
4244
4296
  if inplace:
4245
4297
  target = self
4246
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
4247
4304
  target = self.copy()
4248
4305
  target._increment_instances()
4249
4306
  target._name_update()
4250
4307
 
4251
- # Normalise the inputs into simple abstract interfaces, so we've dispatched the "iteration"
4252
- # logic in one place at the start of the function. This lets us do things like calculate
4253
- # and cache expensive properties for (e.g.) the sequence format only if they're used; for
4254
- # many large, close-to-hardware circuits, we won't need the extra handling for
4255
- # `global_phase` or recursive definition binding.
4256
- #
4257
- # During normalisation, be sure to reference 'parameters' and related things from 'self' not
4258
- # 'target' so we can take advantage of any caching we might be doing.
4259
- if isinstance(parameters, dict):
4308
+ if isinstance(parameters, collections.abc.Mapping):
4260
4309
  raw_mapping = parameters if flat_input else self._unroll_param_dict(parameters)
4261
- # Remember that we _must not_ mutate the output of `_unsorted_parameters`.
4262
- our_parameters = self._unsorted_parameters()
4310
+ our_parameters = self._data.unsorted_parameters()
4263
4311
  if strict and (extras := raw_mapping.keys() - our_parameters):
4264
4312
  raise CircuitError(
4265
4313
  f"Cannot bind parameters ({', '.join(str(x) for x in extras)}) not present in"
4266
4314
  " the circuit."
4267
4315
  )
4268
4316
  parameter_binds = _ParameterBindsDict(raw_mapping, our_parameters)
4317
+ target._data.assign_parameters_mapping(parameter_binds)
4269
4318
  else:
4270
- our_parameters = self.parameters
4271
- if len(parameters) != len(our_parameters):
4272
- raise ValueError(
4273
- "Mismatching number of values and parameters. For partial binding "
4274
- "please pass a dictionary of {parameter: value} pairs."
4275
- )
4276
- parameter_binds = _ParameterBindsSequence(our_parameters, parameters)
4277
-
4278
- # Clear out the parameter table for the relevant entries, since we'll be binding those.
4279
- # Any new references to parameters are reinserted as part of the bind.
4280
- target._parameters = None
4281
- # This is deliberately eager, because we want the side effect of clearing the table.
4282
- all_references = [
4283
- (parameter, value, target._parameter_table.pop(parameter, ()))
4284
- for parameter, value in parameter_binds.items()
4285
- ]
4286
- seen_operations = {}
4287
- # The meat of the actual binding for regular operations.
4288
- for to_bind, bound_value, references in all_references:
4289
- update_parameters = (
4290
- tuple(bound_value.parameters)
4291
- if isinstance(bound_value, ParameterExpression)
4292
- else ()
4293
- )
4294
- for operation, index in references:
4295
- seen_operations[id(operation)] = operation
4296
- if operation is ParameterTable.GLOBAL_PHASE:
4297
- assignee = target.global_phase
4298
- validate = _normalize_global_phase
4299
- else:
4300
- assignee = operation.params[index]
4301
- validate = operation.validate_parameter
4302
- if isinstance(assignee, ParameterExpression):
4303
- new_parameter = assignee.assign(to_bind, bound_value)
4304
- for parameter in update_parameters:
4305
- if parameter not in target._parameter_table:
4306
- target._parameter_table[parameter] = ParameterReferences(())
4307
- target._parameter_table[parameter].add((operation, index))
4308
- if not new_parameter.parameters:
4309
- new_parameter = validate(new_parameter.numeric())
4310
- elif isinstance(assignee, QuantumCircuit):
4311
- new_parameter = assignee.assign_parameters(
4312
- {to_bind: bound_value}, inplace=False, flat_input=True
4313
- )
4314
- else:
4315
- raise RuntimeError( # pragma: no cover
4316
- f"Saw an unknown type during symbolic binding: {assignee}."
4317
- " This may indicate an internal logic error in symbol tracking."
4318
- )
4319
- if operation is ParameterTable.GLOBAL_PHASE:
4320
- # We've already handled parameter table updates in bulk, so we need to skip the
4321
- # public setter trying to do it again.
4322
- target._global_phase = new_parameter
4323
- else:
4324
- operation.params[index] = new_parameter
4325
-
4326
- # After we've been through everything at the top level, make a single visit to each
4327
- # operation we've seen, rebinding its definition if necessary.
4328
- for operation in seen_operations.values():
4329
- if (
4330
- definition := getattr(operation, "_definition", None)
4331
- ) is not None and definition.num_parameters:
4332
- definition.assign_parameters(
4333
- parameter_binds.mapping, inplace=True, flat_input=True, strict=False
4334
- )
4319
+ parameter_binds = _ParameterBindsSequence(target._data.parameters, parameters)
4320
+ target._data.assign_parameters_sequence(parameters)
4335
4321
 
4336
4322
  # Finally, assign the parameters inside any of the calibrations. We don't track these in
4337
4323
  # the `ParameterTable`, so we manually reconstruct things.
@@ -4403,7 +4389,9 @@ class QuantumCircuit:
4403
4389
 
4404
4390
  if qargs:
4405
4391
  # This uses a `dict` not a `set` to guarantee a deterministic order to the arguments.
4406
- 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
+ )
4407
4395
  return self.append(
4408
4396
  CircuitInstruction(Barrier(len(qubits), label=label), qubits, ()), copy=False
4409
4397
  )
@@ -4450,9 +4438,7 @@ class QuantumCircuit:
4450
4438
  Returns:
4451
4439
  A handle to the instructions created.
4452
4440
  """
4453
- from .library.standard_gates.h import HGate
4454
-
4455
- return self.append(HGate(), [qubit], [], copy=False)
4441
+ return self._append_standard_gate(StandardGate.HGate, [qubit], ())
4456
4442
 
4457
4443
  def ch(
4458
4444
  self,
@@ -4476,6 +4462,12 @@ class QuantumCircuit:
4476
4462
  Returns:
4477
4463
  A handle to the instructions created.
4478
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
+
4479
4471
  from .library.standard_gates.h import CHGate
4480
4472
 
4481
4473
  return self.append(
@@ -4496,9 +4488,7 @@ class QuantumCircuit:
4496
4488
  Returns:
4497
4489
  A handle to the instructions created.
4498
4490
  """
4499
- from .library.standard_gates.i import IGate
4500
-
4501
- return self.append(IGate(), [qubit], [], copy=False)
4491
+ return self._append_standard_gate(StandardGate.IGate, [qubit], ())
4502
4492
 
4503
4493
  def ms(self, theta: ParameterValueType, qubits: Sequence[QubitSpecifier]) -> InstructionSet:
4504
4494
  """Apply :class:`~qiskit.circuit.library.MSGate`.
@@ -4529,9 +4519,7 @@ class QuantumCircuit:
4529
4519
  Returns:
4530
4520
  A handle to the instructions created.
4531
4521
  """
4532
- from .library.standard_gates.p import PhaseGate
4533
-
4534
- return self.append(PhaseGate(theta), [qubit], [], copy=False)
4522
+ return self._append_standard_gate(StandardGate.PhaseGate, [qubit], (theta,))
4535
4523
 
4536
4524
  def cp(
4537
4525
  self,
@@ -4557,6 +4545,12 @@ class QuantumCircuit:
4557
4545
  Returns:
4558
4546
  A handle to the instructions created.
4559
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
+
4560
4554
  from .library.standard_gates.p import CPhaseGate
4561
4555
 
4562
4556
  return self.append(
@@ -4613,9 +4607,7 @@ class QuantumCircuit:
4613
4607
  Returns:
4614
4608
  A handle to the instructions created.
4615
4609
  """
4616
- from .library.standard_gates.r import RGate
4617
-
4618
- return self.append(RGate(theta, phi), [qubit], [], copy=False)
4610
+ return self._append_standard_gate(StandardGate.RGate, [qubit], [theta, phi])
4619
4611
 
4620
4612
  def rv(
4621
4613
  self,
@@ -4662,10 +4654,8 @@ class QuantumCircuit:
4662
4654
  Returns:
4663
4655
  A handle to the instructions created.
4664
4656
  """
4665
- from .library.standard_gates.x import RCCXGate
4666
-
4667
- return self.append(
4668
- RCCXGate(), [control_qubit1, control_qubit2, target_qubit], [], copy=False
4657
+ return self._append_standard_gate(
4658
+ StandardGate.RCCXGate, [control_qubit1, control_qubit2, target_qubit], ()
4669
4659
  )
4670
4660
 
4671
4661
  def rcccx(
@@ -4688,13 +4678,10 @@ class QuantumCircuit:
4688
4678
  Returns:
4689
4679
  A handle to the instructions created.
4690
4680
  """
4691
- from .library.standard_gates.x import RC3XGate
4692
-
4693
- return self.append(
4694
- RC3XGate(),
4681
+ return self._append_standard_gate(
4682
+ StandardGate.RC3XGate,
4695
4683
  [control_qubit1, control_qubit2, control_qubit3, target_qubit],
4696
- [],
4697
- copy=False,
4684
+ (),
4698
4685
  )
4699
4686
 
4700
4687
  def rx(
@@ -4712,9 +4699,7 @@ class QuantumCircuit:
4712
4699
  Returns:
4713
4700
  A handle to the instructions created.
4714
4701
  """
4715
- from .library.standard_gates.rx import RXGate
4716
-
4717
- return self.append(RXGate(theta, label=label), [qubit], [], copy=False)
4702
+ return self._append_standard_gate(StandardGate.RXGate, [qubit], [theta], label=label)
4718
4703
 
4719
4704
  def crx(
4720
4705
  self,
@@ -4740,6 +4725,12 @@ class QuantumCircuit:
4740
4725
  Returns:
4741
4726
  A handle to the instructions created.
4742
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
+
4743
4734
  from .library.standard_gates.rx import CRXGate
4744
4735
 
4745
4736
  return self.append(
@@ -4764,9 +4755,7 @@ class QuantumCircuit:
4764
4755
  Returns:
4765
4756
  A handle to the instructions created.
4766
4757
  """
4767
- from .library.standard_gates.rxx import RXXGate
4768
-
4769
- return self.append(RXXGate(theta), [qubit1, qubit2], [], copy=False)
4758
+ return self._append_standard_gate(StandardGate.RXXGate, [qubit1, qubit2], [theta])
4770
4759
 
4771
4760
  def ry(
4772
4761
  self, theta: ParameterValueType, qubit: QubitSpecifier, label: str | None = None
@@ -4783,9 +4772,7 @@ class QuantumCircuit:
4783
4772
  Returns:
4784
4773
  A handle to the instructions created.
4785
4774
  """
4786
- from .library.standard_gates.ry import RYGate
4787
-
4788
- return self.append(RYGate(theta, label=label), [qubit], [], copy=False)
4775
+ return self._append_standard_gate(StandardGate.RYGate, [qubit], [theta], label=label)
4789
4776
 
4790
4777
  def cry(
4791
4778
  self,
@@ -4811,6 +4798,12 @@ class QuantumCircuit:
4811
4798
  Returns:
4812
4799
  A handle to the instructions created.
4813
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
+
4814
4807
  from .library.standard_gates.ry import CRYGate
4815
4808
 
4816
4809
  return self.append(
@@ -4835,9 +4828,7 @@ class QuantumCircuit:
4835
4828
  Returns:
4836
4829
  A handle to the instructions created.
4837
4830
  """
4838
- from .library.standard_gates.ryy import RYYGate
4839
-
4840
- return self.append(RYYGate(theta), [qubit1, qubit2], [], copy=False)
4831
+ return self._append_standard_gate(StandardGate.RYYGate, [qubit1, qubit2], [theta])
4841
4832
 
4842
4833
  def rz(self, phi: ParameterValueType, qubit: QubitSpecifier) -> InstructionSet:
4843
4834
  """Apply :class:`~qiskit.circuit.library.RZGate`.
@@ -4851,9 +4842,7 @@ class QuantumCircuit:
4851
4842
  Returns:
4852
4843
  A handle to the instructions created.
4853
4844
  """
4854
- from .library.standard_gates.rz import RZGate
4855
-
4856
- return self.append(RZGate(phi), [qubit], [], copy=False)
4845
+ return self._append_standard_gate(StandardGate.RZGate, [qubit], [phi])
4857
4846
 
4858
4847
  def crz(
4859
4848
  self,
@@ -4879,6 +4868,12 @@ class QuantumCircuit:
4879
4868
  Returns:
4880
4869
  A handle to the instructions created.
4881
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
+
4882
4877
  from .library.standard_gates.rz import CRZGate
4883
4878
 
4884
4879
  return self.append(
@@ -4903,9 +4898,7 @@ class QuantumCircuit:
4903
4898
  Returns:
4904
4899
  A handle to the instructions created.
4905
4900
  """
4906
- from .library.standard_gates.rzx import RZXGate
4907
-
4908
- return self.append(RZXGate(theta), [qubit1, qubit2], [], copy=False)
4901
+ return self._append_standard_gate(StandardGate.RZXGate, [qubit1, qubit2], [theta])
4909
4902
 
4910
4903
  def rzz(
4911
4904
  self, theta: ParameterValueType, qubit1: QubitSpecifier, qubit2: QubitSpecifier
@@ -4922,9 +4915,7 @@ class QuantumCircuit:
4922
4915
  Returns:
4923
4916
  A handle to the instructions created.
4924
4917
  """
4925
- from .library.standard_gates.rzz import RZZGate
4926
-
4927
- return self.append(RZZGate(theta), [qubit1, qubit2], [], copy=False)
4918
+ return self._append_standard_gate(StandardGate.RZZGate, [qubit1, qubit2], [theta])
4928
4919
 
4929
4920
  def ecr(self, qubit1: QubitSpecifier, qubit2: QubitSpecifier) -> InstructionSet:
4930
4921
  """Apply :class:`~qiskit.circuit.library.ECRGate`.
@@ -4937,9 +4928,7 @@ class QuantumCircuit:
4937
4928
  Returns:
4938
4929
  A handle to the instructions created.
4939
4930
  """
4940
- from .library.standard_gates.ecr import ECRGate
4941
-
4942
- return self.append(ECRGate(), [qubit1, qubit2], [], copy=False)
4931
+ return self._append_standard_gate(StandardGate.ECRGate, [qubit1, qubit2], ())
4943
4932
 
4944
4933
  def s(self, qubit: QubitSpecifier) -> InstructionSet:
4945
4934
  """Apply :class:`~qiskit.circuit.library.SGate`.
@@ -4952,9 +4941,7 @@ class QuantumCircuit:
4952
4941
  Returns:
4953
4942
  A handle to the instructions created.
4954
4943
  """
4955
- from .library.standard_gates.s import SGate
4956
-
4957
- return self.append(SGate(), [qubit], [], copy=False)
4944
+ return self._append_standard_gate(StandardGate.SGate, [qubit], ())
4958
4945
 
4959
4946
  def sdg(self, qubit: QubitSpecifier) -> InstructionSet:
4960
4947
  """Apply :class:`~qiskit.circuit.library.SdgGate`.
@@ -4967,9 +4954,7 @@ class QuantumCircuit:
4967
4954
  Returns:
4968
4955
  A handle to the instructions created.
4969
4956
  """
4970
- from .library.standard_gates.s import SdgGate
4971
-
4972
- return self.append(SdgGate(), [qubit], [], copy=False)
4957
+ return self._append_standard_gate(StandardGate.SdgGate, [qubit], ())
4973
4958
 
4974
4959
  def cs(
4975
4960
  self,
@@ -4993,6 +4978,12 @@ class QuantumCircuit:
4993
4978
  Returns:
4994
4979
  A handle to the instructions created.
4995
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
+
4996
4987
  from .library.standard_gates.s import CSGate
4997
4988
 
4998
4989
  return self.append(
@@ -5024,6 +5015,12 @@ class QuantumCircuit:
5024
5015
  Returns:
5025
5016
  A handle to the instructions created.
5026
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
+
5027
5024
  from .library.standard_gates.s import CSdgGate
5028
5025
 
5029
5026
  return self.append(
@@ -5044,9 +5041,11 @@ class QuantumCircuit:
5044
5041
  Returns:
5045
5042
  A handle to the instructions created.
5046
5043
  """
5047
- from .library.standard_gates.swap import SwapGate
5048
-
5049
- return self.append(SwapGate(), [qubit1, qubit2], [], copy=False)
5044
+ return self._append_standard_gate(
5045
+ StandardGate.SwapGate,
5046
+ [qubit1, qubit2],
5047
+ (),
5048
+ )
5050
5049
 
5051
5050
  def iswap(self, qubit1: QubitSpecifier, qubit2: QubitSpecifier) -> InstructionSet:
5052
5051
  """Apply :class:`~qiskit.circuit.library.iSwapGate`.
@@ -5059,9 +5058,7 @@ class QuantumCircuit:
5059
5058
  Returns:
5060
5059
  A handle to the instructions created.
5061
5060
  """
5062
- from .library.standard_gates.iswap import iSwapGate
5063
-
5064
- return self.append(iSwapGate(), [qubit1, qubit2], [], copy=False)
5061
+ return self._append_standard_gate(StandardGate.ISwapGate, [qubit1, qubit2], ())
5065
5062
 
5066
5063
  def cswap(
5067
5064
  self,
@@ -5087,6 +5084,15 @@ class QuantumCircuit:
5087
5084
  Returns:
5088
5085
  A handle to the instructions created.
5089
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
+
5090
5096
  from .library.standard_gates.swap import CSwapGate
5091
5097
 
5092
5098
  return self.append(
@@ -5107,9 +5113,7 @@ class QuantumCircuit:
5107
5113
  Returns:
5108
5114
  A handle to the instructions created.
5109
5115
  """
5110
- from .library.standard_gates.sx import SXGate
5111
-
5112
- return self.append(SXGate(), [qubit], [], copy=False)
5116
+ return self._append_standard_gate(StandardGate.SXGate, [qubit], ())
5113
5117
 
5114
5118
  def sxdg(self, qubit: QubitSpecifier) -> InstructionSet:
5115
5119
  """Apply :class:`~qiskit.circuit.library.SXdgGate`.
@@ -5122,9 +5126,7 @@ class QuantumCircuit:
5122
5126
  Returns:
5123
5127
  A handle to the instructions created.
5124
5128
  """
5125
- from .library.standard_gates.sx import SXdgGate
5126
-
5127
- return self.append(SXdgGate(), [qubit], [], copy=False)
5129
+ return self._append_standard_gate(StandardGate.SXdgGate, [qubit], ())
5128
5130
 
5129
5131
  def csx(
5130
5132
  self,
@@ -5148,6 +5150,12 @@ class QuantumCircuit:
5148
5150
  Returns:
5149
5151
  A handle to the instructions created.
5150
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
+
5151
5159
  from .library.standard_gates.sx import CSXGate
5152
5160
 
5153
5161
  return self.append(
@@ -5168,9 +5176,7 @@ class QuantumCircuit:
5168
5176
  Returns:
5169
5177
  A handle to the instructions created.
5170
5178
  """
5171
- from .library.standard_gates.t import TGate
5172
-
5173
- return self.append(TGate(), [qubit], [], copy=False)
5179
+ return self._append_standard_gate(StandardGate.TGate, [qubit], ())
5174
5180
 
5175
5181
  def tdg(self, qubit: QubitSpecifier) -> InstructionSet:
5176
5182
  """Apply :class:`~qiskit.circuit.library.TdgGate`.
@@ -5183,9 +5189,7 @@ class QuantumCircuit:
5183
5189
  Returns:
5184
5190
  A handle to the instructions created.
5185
5191
  """
5186
- from .library.standard_gates.t import TdgGate
5187
-
5188
- return self.append(TdgGate(), [qubit], [], copy=False)
5192
+ return self._append_standard_gate(StandardGate.TdgGate, [qubit], ())
5189
5193
 
5190
5194
  def u(
5191
5195
  self,
@@ -5207,9 +5211,7 @@ class QuantumCircuit:
5207
5211
  Returns:
5208
5212
  A handle to the instructions created.
5209
5213
  """
5210
- from .library.standard_gates.u import UGate
5211
-
5212
- return self.append(UGate(theta, phi, lam), [qubit], [], copy=False)
5214
+ return self._append_standard_gate(StandardGate.UGate, [qubit], [theta, phi, lam])
5213
5215
 
5214
5216
  def cu(
5215
5217
  self,
@@ -5241,6 +5243,15 @@ class QuantumCircuit:
5241
5243
  Returns:
5242
5244
  A handle to the instructions created.
5243
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
+
5244
5255
  from .library.standard_gates.u import CUGate
5245
5256
 
5246
5257
  return self.append(
@@ -5262,9 +5273,7 @@ class QuantumCircuit:
5262
5273
  Returns:
5263
5274
  A handle to the instructions created.
5264
5275
  """
5265
- from .library.standard_gates.x import XGate
5266
-
5267
- return self.append(XGate(label=label), [qubit], [], copy=False)
5276
+ return self._append_standard_gate(StandardGate.XGate, [qubit], (), label=label)
5268
5277
 
5269
5278
  def cx(
5270
5279
  self,
@@ -5288,6 +5297,14 @@ class QuantumCircuit:
5288
5297
  Returns:
5289
5298
  A handle to the instructions created.
5290
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
+ )
5291
5308
 
5292
5309
  from .library.standard_gates.x import CXGate
5293
5310
 
@@ -5310,9 +5327,7 @@ class QuantumCircuit:
5310
5327
  Returns:
5311
5328
  A handle to the instructions created.
5312
5329
  """
5313
- from .library.standard_gates.dcx import DCXGate
5314
-
5315
- return self.append(DCXGate(), [qubit1, qubit2], [], copy=False)
5330
+ return self._append_standard_gate(StandardGate.DCXGate, [qubit1, qubit2], ())
5316
5331
 
5317
5332
  def ccx(
5318
5333
  self,
@@ -5336,6 +5351,14 @@ class QuantumCircuit:
5336
5351
  Returns:
5337
5352
  A handle to the instructions created.
5338
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
+
5339
5362
  from .library.standard_gates.x import CCXGate
5340
5363
 
5341
5364
  return self.append(
@@ -5381,12 +5404,12 @@ class QuantumCircuit:
5381
5404
  ValueError: if the given mode is not known, or if too few ancilla qubits are passed.
5382
5405
  AttributeError: if no ancilla qubits are passed, but some are needed.
5383
5406
  """
5384
- from .library.standard_gates.x import MCXGrayCode, MCXRecursive, MCXVChain
5407
+ from .library.standard_gates.x import MCXGate, MCXRecursive, MCXVChain
5385
5408
 
5386
5409
  num_ctrl_qubits = len(control_qubits)
5387
5410
 
5388
5411
  available_implementations = {
5389
- "noancilla": MCXGrayCode(num_ctrl_qubits, ctrl_state=ctrl_state),
5412
+ "noancilla": MCXGate(num_ctrl_qubits, ctrl_state=ctrl_state),
5390
5413
  "recursion": MCXRecursive(num_ctrl_qubits, ctrl_state=ctrl_state),
5391
5414
  "v-chain": MCXVChain(num_ctrl_qubits, False, ctrl_state=ctrl_state),
5392
5415
  "v-chain-dirty": MCXVChain(num_ctrl_qubits, dirty_ancillas=True, ctrl_state=ctrl_state),
@@ -5400,7 +5423,7 @@ class QuantumCircuit:
5400
5423
 
5401
5424
  # check ancilla input
5402
5425
  if ancilla_qubits:
5403
- _ = self.qbit_argument_conversion(ancilla_qubits)
5426
+ _ = self._qbit_argument_conversion(ancilla_qubits)
5404
5427
 
5405
5428
  try:
5406
5429
  gate = available_implementations[mode]
@@ -5440,9 +5463,7 @@ class QuantumCircuit:
5440
5463
  Returns:
5441
5464
  A handle to the instructions created.
5442
5465
  """
5443
- from .library.standard_gates.y import YGate
5444
-
5445
- return self.append(YGate(), [qubit], [], copy=False)
5466
+ return self._append_standard_gate(StandardGate.YGate, [qubit], ())
5446
5467
 
5447
5468
  def cy(
5448
5469
  self,
@@ -5466,6 +5487,15 @@ class QuantumCircuit:
5466
5487
  Returns:
5467
5488
  A handle to the instructions created.
5468
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
+
5469
5499
  from .library.standard_gates.y import CYGate
5470
5500
 
5471
5501
  return self.append(
@@ -5486,9 +5516,7 @@ class QuantumCircuit:
5486
5516
  Returns:
5487
5517
  A handle to the instructions created.
5488
5518
  """
5489
- from .library.standard_gates.z import ZGate
5490
-
5491
- return self.append(ZGate(), [qubit], [], copy=False)
5519
+ return self._append_standard_gate(StandardGate.ZGate, [qubit], ())
5492
5520
 
5493
5521
  def cz(
5494
5522
  self,
@@ -5512,6 +5540,12 @@ class QuantumCircuit:
5512
5540
  Returns:
5513
5541
  A handle to the instructions created.
5514
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
+
5515
5549
  from .library.standard_gates.z import CZGate
5516
5550
 
5517
5551
  return self.append(
@@ -5545,6 +5579,15 @@ class QuantumCircuit:
5545
5579
  Returns:
5546
5580
  A handle to the instructions created.
5547
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
+
5548
5591
  from .library.standard_gates.z import CCZGate
5549
5592
 
5550
5593
  return self.append(
@@ -5706,7 +5749,7 @@ class QuantumCircuit:
5706
5749
  * Statevector or vector of complex amplitudes to initialize to.
5707
5750
  * Labels of basis states of the Pauli eigenstates Z, X, Y. See
5708
5751
  :meth:`.Statevector.from_label`. Notice the order of the labels is reversed with
5709
- 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
5710
5753
  qubit zero to :math:`|1\rangle` and the qubit one to :math:`|0\rangle`.
5711
5754
  * An integer that is used as a bitmap indicating which qubits to initialize to
5712
5755
  :math:`|1\rangle`. Example: setting params to 5 would initialize qubit 0 and qubit
@@ -5880,7 +5923,7 @@ class QuantumCircuit:
5880
5923
  """Finish a scope used in the control-flow builder interface, and return it to the caller.
5881
5924
 
5882
5925
  This should only be done by the control-flow context managers, since they naturally
5883
- synchronise the creation and deletion of stack elements."""
5926
+ synchronize the creation and deletion of stack elements."""
5884
5927
  return self._control_flow_scopes.pop()
5885
5928
 
5886
5929
  def _peek_previous_instruction_in_scope(self) -> CircuitInstruction:
@@ -5907,36 +5950,8 @@ class QuantumCircuit:
5907
5950
  if not self._data:
5908
5951
  raise CircuitError("This circuit contains no instructions.")
5909
5952
  instruction = self._data.pop()
5910
- if isinstance(instruction.operation, Instruction):
5911
- self._update_parameter_table_on_instruction_removal(instruction)
5912
5953
  return instruction
5913
5954
 
5914
- def _update_parameter_table_on_instruction_removal(self, instruction: CircuitInstruction):
5915
- """Update the :obj:`.ParameterTable` of this circuit given that an instance of the given
5916
- ``instruction`` has just been removed from the circuit.
5917
-
5918
- .. note::
5919
-
5920
- This does not account for the possibility for the same instruction instance being added
5921
- more than once to the circuit. At the time of writing (2021-11-17, main commit 271a82f)
5922
- there is a defensive ``deepcopy`` of parameterised instructions inside
5923
- :meth:`.QuantumCircuit.append`, so this should be safe. Trying to account for it would
5924
- involve adding a potentially quadratic-scaling loop to check each entry in ``data``.
5925
- """
5926
- atomic_parameters: list[tuple[Parameter, int]] = []
5927
- for index, parameter in enumerate(instruction.operation.params):
5928
- if isinstance(parameter, (ParameterExpression, QuantumCircuit)):
5929
- atomic_parameters.extend((p, index) for p in parameter.parameters)
5930
- for atomic_parameter, index in atomic_parameters:
5931
- new_entries = self._parameter_table[atomic_parameter].copy()
5932
- new_entries.discard((instruction.operation, index))
5933
- if not new_entries:
5934
- del self._parameter_table[atomic_parameter]
5935
- # Invalidate cache.
5936
- self._parameters = None
5937
- else:
5938
- self._parameter_table[atomic_parameter] = new_entries
5939
-
5940
5955
  @typing.overload
5941
5956
  def while_loop(
5942
5957
  self,
@@ -6582,13 +6597,14 @@ class _OuterCircuitScopeInterface(CircuitScopeInterface):
6582
6597
  def instructions(self):
6583
6598
  return self.circuit._data
6584
6599
 
6585
- def append(self, instruction):
6600
+ def append(self, instruction, *, _standard_gate: bool = False):
6586
6601
  # QuantumCircuit._append is semi-public, so we just call back to it.
6587
- return self.circuit._append(instruction)
6602
+ return self.circuit._append(instruction, _standard_gate=_standard_gate)
6588
6603
 
6589
6604
  def extend(self, data: CircuitData):
6590
6605
  self.circuit._data.extend(data)
6591
- data.foreach_op(self.circuit._track_operation)
6606
+ self.circuit.duration = None
6607
+ self.circuit.unit = "dt"
6592
6608
 
6593
6609
  def resolve_classical_resource(self, specifier):
6594
6610
  # This is slightly different to cbit_argument_conversion, because it should not
@@ -6745,11 +6761,3 @@ def _bit_argument_conversion_scalar(specifier, bit_sequence, bit_set, type_):
6745
6761
  else f"Invalid bit index: '{specifier}' of type '{type(specifier)}'"
6746
6762
  )
6747
6763
  raise CircuitError(message)
6748
-
6749
-
6750
- def _normalize_global_phase(angle):
6751
- """Return the normalized form of an angle for use in the global phase. This coerces to float if
6752
- possible, and fixes to the interval :math:`[0, 2\\pi)`."""
6753
- if isinstance(angle, ParameterExpression) and angle.parameters:
6754
- return angle
6755
- return float(angle) % (2.0 * np.pi)