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.
- qiskit/VERSION.txt +1 -1
- qiskit/__init__.py +27 -24
- qiskit/_accelerate.pyd +0 -0
- qiskit/_numpy_compat.py +1 -1
- qiskit/assembler/assemble_circuits.py +107 -64
- qiskit/assembler/assemble_schedules.py +5 -12
- qiskit/assembler/disassemble.py +10 -1
- qiskit/circuit/__init__.py +1 -1
- qiskit/circuit/_classical_resource_map.py +5 -5
- qiskit/circuit/_utils.py +0 -13
- qiskit/circuit/add_control.py +1 -1
- qiskit/circuit/annotated_operation.py +23 -1
- qiskit/circuit/classical/expr/expr.py +4 -4
- qiskit/circuit/classical/expr/visitors.py +1 -1
- qiskit/circuit/classical/types/__init__.py +1 -1
- qiskit/circuit/classical/types/types.py +2 -2
- qiskit/circuit/classicalfunction/boolean_expression.py +1 -1
- qiskit/circuit/classicalfunction/classical_function_visitor.py +5 -5
- qiskit/circuit/classicalfunction/utils.py +1 -1
- qiskit/circuit/classicalregister.py +1 -1
- qiskit/circuit/commutation_checker.py +83 -35
- qiskit/circuit/controlflow/_builder_utils.py +1 -1
- qiskit/circuit/controlflow/builder.py +10 -6
- qiskit/circuit/controlflow/if_else.py +2 -2
- qiskit/circuit/controlflow/switch_case.py +1 -1
- qiskit/circuit/delay.py +1 -1
- qiskit/circuit/duration.py +2 -2
- qiskit/circuit/equivalence.py +5 -7
- qiskit/circuit/gate.py +11 -8
- qiskit/circuit/instruction.py +31 -13
- qiskit/circuit/instructionset.py +2 -5
- qiskit/circuit/library/__init__.py +2 -1
- qiskit/circuit/library/arithmetic/linear_amplitude_function.py +1 -1
- qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +1 -1
- qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +1 -1
- qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +1 -1
- qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +3 -3
- qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py +1 -1
- qiskit/circuit/library/basis_change/__init__.py +1 -1
- qiskit/circuit/library/basis_change/qft.py +40 -6
- qiskit/circuit/library/blueprintcircuit.py +3 -5
- qiskit/circuit/library/data_preparation/__init__.py +9 -2
- qiskit/circuit/library/data_preparation/initializer.py +8 -0
- qiskit/circuit/library/data_preparation/state_preparation.py +98 -178
- qiskit/circuit/library/generalized_gates/isometry.py +8 -8
- qiskit/circuit/library/generalized_gates/linear_function.py +3 -2
- qiskit/circuit/library/generalized_gates/mcg_up_to_diagonal.py +4 -4
- qiskit/circuit/library/generalized_gates/permutation.py +8 -9
- qiskit/circuit/library/generalized_gates/uc.py +3 -3
- qiskit/circuit/library/generalized_gates/uc_pauli_rot.py +2 -2
- qiskit/circuit/library/generalized_gates/unitary.py +13 -11
- qiskit/circuit/library/graph_state.py +1 -1
- qiskit/circuit/library/hamiltonian_gate.py +1 -2
- qiskit/circuit/library/hidden_linear_function.py +1 -1
- qiskit/circuit/library/n_local/evolved_operator_ansatz.py +3 -2
- qiskit/circuit/library/n_local/n_local.py +4 -5
- qiskit/circuit/library/n_local/pauli_two_design.py +1 -1
- qiskit/circuit/library/n_local/qaoa_ansatz.py +6 -8
- qiskit/circuit/library/n_local/two_local.py +1 -1
- qiskit/circuit/library/overlap.py +11 -5
- qiskit/circuit/library/pauli_evolution.py +7 -3
- qiskit/circuit/library/standard_gates/dcx.py +3 -0
- qiskit/circuit/library/standard_gates/ecr.py +3 -0
- qiskit/circuit/library/standard_gates/global_phase.py +3 -0
- qiskit/circuit/library/standard_gates/h.py +13 -5
- qiskit/circuit/library/standard_gates/i.py +3 -0
- qiskit/circuit/library/standard_gates/iswap.py +3 -0
- qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +19 -10
- qiskit/circuit/library/standard_gates/p.py +14 -9
- qiskit/circuit/library/standard_gates/r.py +3 -0
- qiskit/circuit/library/standard_gates/rx.py +21 -6
- qiskit/circuit/library/standard_gates/rxx.py +40 -1
- qiskit/circuit/library/standard_gates/ry.py +21 -6
- qiskit/circuit/library/standard_gates/ryy.py +40 -1
- qiskit/circuit/library/standard_gates/rz.py +22 -6
- qiskit/circuit/library/standard_gates/rzx.py +40 -1
- qiskit/circuit/library/standard_gates/rzz.py +41 -2
- qiskit/circuit/library/standard_gates/s.py +77 -0
- qiskit/circuit/library/standard_gates/swap.py +12 -5
- qiskit/circuit/library/standard_gates/sx.py +14 -5
- qiskit/circuit/library/standard_gates/t.py +5 -0
- qiskit/circuit/library/standard_gates/u.py +22 -7
- qiskit/circuit/library/standard_gates/u1.py +8 -3
- qiskit/circuit/library/standard_gates/u2.py +3 -0
- qiskit/circuit/library/standard_gates/u3.py +22 -7
- qiskit/circuit/library/standard_gates/x.py +156 -92
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +40 -1
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +52 -11
- qiskit/circuit/library/standard_gates/y.py +6 -1
- qiskit/circuit/library/standard_gates/z.py +8 -1
- qiskit/circuit/operation.py +1 -1
- qiskit/circuit/parameter.py +9 -10
- qiskit/circuit/parameterexpression.py +16 -13
- qiskit/circuit/parametertable.py +1 -190
- qiskit/circuit/parametervector.py +1 -1
- qiskit/circuit/quantumcircuit.py +392 -384
- qiskit/circuit/quantumcircuitdata.py +3 -5
- qiskit/circuit/quantumregister.py +1 -1
- qiskit/circuit/random/__init__.py +1 -1
- qiskit/circuit/random/utils.py +175 -26
- qiskit/circuit/register.py +5 -7
- qiskit/circuit/singleton.py +3 -3
- qiskit/circuit/tools/pi_check.py +4 -4
- qiskit/compiler/assembler.py +95 -24
- qiskit/compiler/scheduler.py +2 -2
- qiskit/compiler/transpiler.py +41 -127
- qiskit/converters/circuit_to_dag.py +4 -6
- qiskit/converters/circuit_to_gate.py +4 -8
- qiskit/converters/circuit_to_instruction.py +5 -17
- qiskit/converters/dag_to_circuit.py +2 -6
- qiskit/dagcircuit/collect_blocks.py +2 -2
- qiskit/dagcircuit/dagcircuit.py +190 -187
- qiskit/dagcircuit/dagdependency.py +4 -4
- qiskit/dagcircuit/dagdependency_v2.py +4 -4
- qiskit/dagcircuit/dagdepnode.py +1 -1
- qiskit/dagcircuit/dagnode.py +66 -157
- qiskit/passmanager/flow_controllers.py +1 -1
- qiskit/passmanager/passmanager.py +3 -3
- qiskit/primitives/__init__.py +1 -5
- qiskit/primitives/backend_estimator.py +25 -15
- qiskit/primitives/backend_estimator_v2.py +31 -7
- qiskit/primitives/backend_sampler.py +21 -12
- qiskit/primitives/backend_sampler_v2.py +12 -3
- qiskit/primitives/base/base_estimator.py +31 -4
- qiskit/primitives/base/base_primitive.py +2 -2
- qiskit/primitives/base/base_result.py +2 -2
- qiskit/primitives/base/base_sampler.py +26 -2
- qiskit/primitives/base/estimator_result.py +2 -2
- qiskit/primitives/base/sampler_result.py +2 -2
- qiskit/primitives/containers/__init__.py +0 -1
- qiskit/primitives/containers/bindings_array.py +2 -2
- qiskit/primitives/containers/bit_array.py +108 -10
- qiskit/primitives/containers/shape.py +3 -3
- qiskit/primitives/estimator.py +9 -2
- qiskit/primitives/primitive_job.py +1 -1
- qiskit/primitives/sampler.py +10 -3
- qiskit/primitives/statevector_estimator.py +5 -3
- qiskit/primitives/statevector_sampler.py +11 -5
- qiskit/primitives/utils.py +16 -0
- qiskit/providers/backend.py +15 -6
- qiskit/providers/backend_compat.py +7 -4
- qiskit/providers/basic_provider/basic_provider_tools.py +1 -1
- qiskit/providers/basic_provider/basic_simulator.py +32 -24
- qiskit/providers/fake_provider/fake_backend.py +10 -3
- qiskit/providers/fake_provider/fake_openpulse_2q.py +154 -146
- qiskit/providers/fake_provider/fake_openpulse_3q.py +226 -217
- qiskit/providers/fake_provider/fake_qasm_backend.py +5 -1
- qiskit/providers/fake_provider/generic_backend_v2.py +80 -50
- qiskit/providers/models/__init__.py +11 -0
- qiskit/providers/models/backendconfiguration.py +50 -4
- qiskit/providers/models/backendproperties.py +13 -2
- qiskit/providers/models/pulsedefaults.py +10 -11
- qiskit/providers/options.py +13 -13
- qiskit/providers/providerutils.py +3 -1
- qiskit/pulse/configuration.py +8 -12
- qiskit/pulse/instruction_schedule_map.py +3 -5
- qiskit/pulse/instructions/acquire.py +7 -8
- qiskit/pulse/instructions/instruction.py +2 -3
- qiskit/pulse/library/samplers/decorators.py +5 -9
- qiskit/pulse/library/symbolic_pulses.py +4 -7
- qiskit/pulse/library/waveform.py +2 -5
- qiskit/pulse/macros.py +11 -6
- qiskit/pulse/parser.py +8 -10
- qiskit/pulse/schedule.py +9 -17
- qiskit/pulse/transforms/alignments.py +1 -3
- qiskit/pulse/utils.py +1 -2
- qiskit/qasm/libs/stdgates.inc +35 -28
- qiskit/qasm2/__init__.py +7 -7
- qiskit/qasm2/export.py +5 -9
- qiskit/qasm2/parse.py +1 -1
- qiskit/qasm3/ast.py +9 -25
- qiskit/qasm3/exporter.py +578 -481
- qiskit/qasm3/printer.py +7 -16
- qiskit/qobj/common.py +10 -0
- qiskit/qobj/converters/lo_config.py +9 -0
- qiskit/qobj/converters/pulse_instruction.py +13 -6
- qiskit/qobj/pulse_qobj.py +69 -15
- qiskit/qobj/qasm_qobj.py +72 -20
- qiskit/qobj/utils.py +9 -0
- qiskit/qpy/binary_io/circuits.py +8 -5
- qiskit/qpy/binary_io/schedules.py +1 -1
- qiskit/qpy/binary_io/value.py +3 -3
- qiskit/qpy/interface.py +3 -2
- qiskit/qpy/type_keys.py +2 -2
- qiskit/quantum_info/operators/channel/quantum_channel.py +3 -6
- qiskit/quantum_info/operators/channel/superop.py +2 -2
- qiskit/quantum_info/operators/channel/transformations.py +1 -1
- qiskit/quantum_info/operators/dihedral/dihedral.py +3 -4
- qiskit/quantum_info/operators/dihedral/dihedral_circuits.py +1 -3
- qiskit/quantum_info/operators/dihedral/random.py +6 -3
- qiskit/quantum_info/operators/measures.py +2 -2
- qiskit/quantum_info/operators/op_shape.py +12 -20
- qiskit/quantum_info/operators/operator.py +14 -21
- qiskit/quantum_info/operators/predicates.py +1 -0
- qiskit/quantum_info/operators/symplectic/base_pauli.py +7 -11
- qiskit/quantum_info/operators/symplectic/clifford.py +1 -1
- qiskit/quantum_info/operators/symplectic/pauli.py +3 -3
- qiskit/quantum_info/operators/symplectic/pauli_list.py +9 -10
- qiskit/quantum_info/operators/symplectic/random.py +1 -1
- qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +14 -16
- qiskit/quantum_info/quaternion.py +1 -1
- qiskit/quantum_info/states/densitymatrix.py +5 -8
- qiskit/quantum_info/states/stabilizerstate.py +128 -37
- qiskit/quantum_info/states/statevector.py +4 -8
- qiskit/result/counts.py +2 -2
- qiskit/result/mitigation/correlated_readout_mitigator.py +2 -2
- qiskit/result/mitigation/local_readout_mitigator.py +2 -2
- qiskit/result/mitigation/utils.py +1 -3
- qiskit/result/models.py +17 -16
- qiskit/result/result.py +15 -20
- qiskit/scheduler/lowering.py +2 -2
- qiskit/synthesis/__init__.py +2 -1
- qiskit/synthesis/clifford/__init__.py +1 -1
- qiskit/synthesis/clifford/clifford_decompose_ag.py +2 -2
- qiskit/synthesis/clifford/clifford_decompose_bm.py +10 -240
- qiskit/synthesis/clifford/clifford_decompose_greedy.py +9 -303
- qiskit/synthesis/clifford/clifford_decompose_layers.py +25 -23
- qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_full.py +1 -1
- qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_general.py +1 -1
- qiskit/synthesis/discrete_basis/generate_basis_approximations.py +1 -1
- qiskit/synthesis/discrete_basis/solovay_kitaev.py +2 -2
- qiskit/synthesis/evolution/evolution_synthesis.py +4 -2
- qiskit/synthesis/evolution/lie_trotter.py +46 -19
- qiskit/synthesis/evolution/product_formula.py +111 -55
- qiskit/synthesis/evolution/qdrift.py +40 -10
- qiskit/synthesis/evolution/suzuki_trotter.py +43 -33
- qiskit/synthesis/linear/__init__.py +1 -0
- qiskit/synthesis/linear/cnot_synth.py +22 -96
- qiskit/synthesis/linear/linear_depth_lnn.py +8 -8
- qiskit/synthesis/linear/linear_matrix_utils.py +13 -161
- qiskit/synthesis/linear_phase/cnot_phase_synth.py +1 -1
- qiskit/synthesis/linear_phase/cx_cz_depth_lnn.py +3 -3
- qiskit/synthesis/linear_phase/cz_depth_lnn.py +1 -1
- qiskit/synthesis/one_qubit/one_qubit_decompose.py +29 -29
- qiskit/synthesis/permutation/permutation_full.py +5 -29
- qiskit/synthesis/permutation/permutation_lnn.py +2 -24
- qiskit/synthesis/permutation/permutation_utils.py +2 -59
- qiskit/synthesis/qft/__init__.py +1 -0
- qiskit/synthesis/qft/qft_decompose_full.py +79 -0
- qiskit/synthesis/qft/qft_decompose_lnn.py +17 -9
- qiskit/synthesis/stabilizer/stabilizer_circuit.py +6 -6
- qiskit/synthesis/stabilizer/stabilizer_decompose.py +2 -2
- qiskit/synthesis/two_qubit/local_invariance.py +8 -38
- qiskit/synthesis/two_qubit/two_qubit_decompose.py +48 -129
- qiskit/synthesis/unitary/aqc/cnot_structures.py +1 -1
- qiskit/synthesis/unitary/qsd.py +5 -3
- qiskit/transpiler/__init__.py +1 -0
- qiskit/transpiler/basepasses.py +1 -1
- qiskit/transpiler/coupling.py +3 -3
- qiskit/transpiler/instruction_durations.py +1 -2
- qiskit/transpiler/layout.py +3 -3
- qiskit/transpiler/passes/__init__.py +2 -0
- qiskit/transpiler/passes/basis/basis_translator.py +82 -63
- qiskit/transpiler/passes/basis/translate_parameterized.py +3 -5
- qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
- qiskit/transpiler/passes/basis/unroll_custom_definitions.py +10 -10
- qiskit/transpiler/passes/calibration/rx_builder.py +3 -3
- qiskit/transpiler/passes/calibration/rzx_builder.py +3 -3
- qiskit/transpiler/passes/layout/apply_layout.py +13 -3
- qiskit/transpiler/passes/layout/sabre_layout.py +10 -8
- qiskit/transpiler/passes/layout/sabre_pre_layout.py +4 -1
- qiskit/transpiler/passes/layout/set_layout.py +2 -2
- qiskit/transpiler/passes/layout/vf2_layout.py +1 -1
- qiskit/transpiler/passes/layout/vf2_utils.py +3 -3
- qiskit/transpiler/passes/optimization/__init__.py +1 -0
- qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +2 -2
- qiskit/transpiler/passes/optimization/commutation_analysis.py +7 -10
- qiskit/transpiler/passes/optimization/commutative_cancellation.py +35 -19
- qiskit/transpiler/passes/optimization/consolidate_blocks.py +11 -8
- qiskit/transpiler/passes/optimization/inverse_cancellation.py +6 -6
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +64 -41
- qiskit/transpiler/passes/optimization/optimize_1q_gates.py +1 -1
- qiskit/transpiler/passes/optimization/split_2q_unitaries.py +83 -0
- qiskit/transpiler/passes/optimization/template_matching/backward_match.py +1 -1
- qiskit/transpiler/passes/optimization/template_matching/forward_match.py +2 -2
- qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +1 -1
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +3 -2
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +1 -1
- qiskit/transpiler/passes/routing/layout_transformation.py +2 -1
- qiskit/transpiler/passes/routing/sabre_swap.py +35 -26
- qiskit/transpiler/passes/routing/star_prerouting.py +80 -105
- qiskit/transpiler/passes/routing/stochastic_swap.py +1 -3
- qiskit/transpiler/passes/scheduling/alap.py +1 -2
- qiskit/transpiler/passes/scheduling/alignments/__init__.py +2 -2
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
- qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +1 -1
- qiskit/transpiler/passes/scheduling/alignments/reschedule.py +1 -1
- qiskit/transpiler/passes/scheduling/asap.py +1 -2
- qiskit/transpiler/passes/scheduling/base_scheduler.py +5 -5
- qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +3 -3
- qiskit/transpiler/passes/scheduling/padding/base_padding.py +1 -1
- qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +11 -11
- qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +7 -6
- qiskit/transpiler/passes/scheduling/time_unit_conversion.py +4 -3
- qiskit/transpiler/passes/synthesis/high_level_synthesis.py +211 -36
- qiskit/transpiler/passes/synthesis/plugin.py +2 -2
- qiskit/transpiler/passes/synthesis/unitary_synthesis.py +80 -40
- qiskit/transpiler/passes/utils/__init__.py +0 -1
- qiskit/transpiler/passes/utils/check_gate_direction.py +4 -4
- qiskit/transpiler/passes/utils/check_map.py +3 -6
- qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +3 -4
- qiskit/transpiler/passes/utils/error.py +2 -2
- qiskit/transpiler/passes/utils/fixed_point.py +3 -3
- qiskit/transpiler/passes/utils/gate_direction.py +1 -1
- qiskit/transpiler/passes/utils/gates_basis.py +1 -2
- qiskit/transpiler/passmanager.py +7 -6
- qiskit/transpiler/preset_passmanagers/__init__.py +4 -228
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +117 -18
- qiskit/transpiler/preset_passmanagers/common.py +3 -6
- qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +518 -0
- qiskit/transpiler/preset_passmanagers/level0.py +1 -1
- qiskit/transpiler/target.py +27 -8
- qiskit/user_config.py +29 -6
- qiskit/utils/classtools.py +3 -3
- qiskit/utils/deprecation.py +3 -2
- qiskit/utils/lazy_tester.py +2 -2
- qiskit/utils/optionals.py +8 -8
- qiskit/visualization/bloch.py +19 -67
- qiskit/visualization/circuit/_utils.py +34 -10
- qiskit/visualization/circuit/circuit_visualization.py +23 -16
- qiskit/visualization/circuit/latex.py +29 -27
- qiskit/visualization/circuit/matplotlib.py +4 -2
- qiskit/visualization/circuit/qcstyle.py +2 -2
- qiskit/visualization/circuit/text.py +9 -15
- qiskit/visualization/dag_visualization.py +5 -12
- qiskit/visualization/pulse_v2/core.py +1 -1
- qiskit/visualization/pulse_v2/events.py +1 -1
- qiskit/visualization/pulse_v2/generators/frame.py +3 -4
- qiskit/visualization/pulse_v2/generators/waveform.py +5 -9
- qiskit/visualization/pulse_v2/layouts.py +1 -5
- qiskit/visualization/pulse_v2/plotters/matplotlib.py +1 -2
- qiskit/visualization/state_visualization.py +5 -6
- qiskit/visualization/timeline/plotters/matplotlib.py +1 -2
- qiskit/visualization/transition_visualization.py +7 -2
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/METADATA +26 -26
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/RECORD +340 -338
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/WHEEL +1 -1
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/entry_points.txt +3 -0
- qiskit/transpiler/passes/utils/block_to_matrix.py +0 -47
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/LICENSE.txt +0 -0
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/top_level.txt +0 -0
qiskit/circuit/quantumcircuit.py
CHANGED
@@ -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
|
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
|
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
|
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
|
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. (
|
1070
|
-
"
|
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.
|
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.
|
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
|
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
|
-
"{
|
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
|
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
|
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
|
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``
|
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.
|
1922
|
-
if len(mapped_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 ({
|
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.
|
1938
|
-
if len(mapped_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 ({
|
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.
|
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.
|
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
|
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
|
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
|
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
|
-
|
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
|
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
|
-
|
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.
|
2387
|
-
expanded_cargs = [self.
|
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 =
|
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(
|
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
|
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
|
-
|
2461
|
-
|
2462
|
-
|
2463
|
-
|
2464
|
-
|
2465
|
-
|
2466
|
-
|
2467
|
-
|
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
|
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.
|
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
|
2738
|
-
# used in the
|
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
|
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
|
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
|
-
#
|
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
|
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 "
|
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
|
-
|
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
|
-
|
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(
|
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(
|
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 {}"
|
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 =
|
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
|
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
|
3197
|
-
anything else is supplied,
|
3198
|
-
to where gates should be placed in the output circuit if
|
3199
|
-
an option. ``none`` results in each gate being placed in
|
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
|
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
|
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
|
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
|
-
|
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
|
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
|
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.
|
3638
|
-
|
3639
|
-
|
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
|
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(
|
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
|
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 :
|
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(
|
3949
|
-
|
3950
|
-
|
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.
|
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.
|
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.
|
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
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
4271
|
-
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
5048
|
-
|
5049
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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":
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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)
|