qiskit 1.0.2__cp38-abi3-win32.whl → 1.1.0__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 -16
- qiskit/_accelerate.pyd +0 -0
- qiskit/_numpy_compat.py +73 -0
- qiskit/assembler/__init__.py +5 -10
- qiskit/assembler/disassemble.py +5 -6
- qiskit/circuit/__init__.py +1061 -232
- qiskit/circuit/_classical_resource_map.py +10 -6
- qiskit/circuit/_utils.py +18 -8
- qiskit/circuit/annotated_operation.py +21 -0
- qiskit/circuit/barrier.py +10 -13
- qiskit/circuit/bit.py +0 -1
- qiskit/circuit/classical/__init__.py +2 -2
- qiskit/circuit/classical/expr/__init__.py +39 -5
- qiskit/circuit/classical/expr/constructors.py +84 -1
- qiskit/circuit/classical/expr/expr.py +83 -13
- qiskit/circuit/classical/expr/visitors.py +83 -0
- qiskit/circuit/classical/types/__init__.py +5 -4
- qiskit/circuit/classicalfunction/__init__.py +1 -0
- qiskit/circuit/commutation_checker.py +86 -51
- qiskit/circuit/controlflow/_builder_utils.py +9 -1
- qiskit/circuit/controlflow/break_loop.py +8 -22
- qiskit/circuit/controlflow/builder.py +116 -1
- qiskit/circuit/controlflow/continue_loop.py +8 -22
- qiskit/circuit/controlflow/control_flow.py +47 -8
- qiskit/circuit/controlflow/for_loop.py +8 -23
- qiskit/circuit/controlflow/if_else.py +13 -27
- qiskit/circuit/controlflow/switch_case.py +14 -21
- qiskit/circuit/controlflow/while_loop.py +9 -23
- qiskit/circuit/controlledgate.py +2 -2
- qiskit/circuit/delay.py +7 -5
- qiskit/circuit/gate.py +20 -7
- qiskit/circuit/instruction.py +31 -30
- qiskit/circuit/instructionset.py +9 -22
- qiskit/circuit/library/__init__.py +3 -13
- qiskit/circuit/library/arithmetic/integer_comparator.py +2 -2
- qiskit/circuit/library/arithmetic/quadratic_form.py +3 -2
- qiskit/circuit/library/blueprintcircuit.py +29 -7
- qiskit/circuit/library/data_preparation/state_preparation.py +6 -5
- qiskit/circuit/library/generalized_gates/diagonal.py +5 -4
- qiskit/circuit/library/generalized_gates/isometry.py +51 -254
- qiskit/circuit/library/generalized_gates/pauli.py +2 -2
- qiskit/circuit/library/generalized_gates/permutation.py +4 -1
- qiskit/circuit/library/generalized_gates/rv.py +15 -11
- qiskit/circuit/library/generalized_gates/uc.py +2 -98
- qiskit/circuit/library/generalized_gates/unitary.py +9 -4
- qiskit/circuit/library/hamiltonian_gate.py +11 -5
- qiskit/circuit/library/n_local/efficient_su2.py +5 -5
- qiskit/circuit/library/n_local/n_local.py +100 -49
- qiskit/circuit/library/n_local/two_local.py +3 -59
- qiskit/circuit/library/overlap.py +3 -3
- qiskit/circuit/library/phase_oracle.py +1 -1
- qiskit/circuit/library/quantum_volume.py +39 -38
- qiskit/circuit/library/standard_gates/equivalence_library.py +50 -0
- qiskit/circuit/library/standard_gates/global_phase.py +4 -2
- qiskit/circuit/library/standard_gates/i.py +1 -2
- qiskit/circuit/library/standard_gates/iswap.py +1 -2
- qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +11 -5
- qiskit/circuit/library/standard_gates/p.py +31 -15
- qiskit/circuit/library/standard_gates/r.py +4 -3
- qiskit/circuit/library/standard_gates/rx.py +7 -4
- qiskit/circuit/library/standard_gates/rxx.py +4 -3
- qiskit/circuit/library/standard_gates/ry.py +7 -4
- qiskit/circuit/library/standard_gates/ryy.py +4 -3
- qiskit/circuit/library/standard_gates/rz.py +7 -4
- qiskit/circuit/library/standard_gates/rzx.py +4 -3
- qiskit/circuit/library/standard_gates/rzz.py +4 -3
- qiskit/circuit/library/standard_gates/s.py +4 -8
- qiskit/circuit/library/standard_gates/t.py +2 -4
- qiskit/circuit/library/standard_gates/u.py +16 -11
- qiskit/circuit/library/standard_gates/u1.py +6 -2
- qiskit/circuit/library/standard_gates/u2.py +4 -2
- qiskit/circuit/library/standard_gates/u3.py +9 -5
- qiskit/circuit/library/standard_gates/x.py +22 -11
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +4 -3
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +7 -5
- qiskit/circuit/library/standard_gates/z.py +1 -2
- qiskit/circuit/measure.py +4 -1
- qiskit/circuit/operation.py +13 -8
- qiskit/circuit/parameter.py +11 -6
- qiskit/circuit/quantumcircuit.py +1910 -260
- qiskit/circuit/quantumcircuitdata.py +2 -2
- qiskit/circuit/reset.py +5 -2
- qiskit/circuit/store.py +95 -0
- qiskit/compiler/assembler.py +22 -22
- qiskit/compiler/transpiler.py +63 -112
- qiskit/converters/__init__.py +17 -2
- qiskit/converters/circuit_to_dag.py +7 -0
- qiskit/converters/circuit_to_dagdependency_v2.py +47 -0
- qiskit/converters/circuit_to_gate.py +2 -0
- qiskit/converters/circuit_to_instruction.py +22 -0
- qiskit/converters/dag_to_circuit.py +4 -0
- qiskit/converters/dag_to_dagdependency_v2.py +44 -0
- qiskit/dagcircuit/collect_blocks.py +15 -10
- qiskit/dagcircuit/dagcircuit.py +434 -124
- qiskit/dagcircuit/dagdependency.py +19 -12
- qiskit/dagcircuit/dagdependency_v2.py +641 -0
- qiskit/dagcircuit/dagdepnode.py +19 -16
- qiskit/dagcircuit/dagnode.py +14 -4
- qiskit/passmanager/passmanager.py +11 -11
- qiskit/primitives/__init__.py +22 -12
- qiskit/primitives/backend_estimator.py +3 -5
- qiskit/primitives/backend_estimator_v2.py +410 -0
- qiskit/primitives/backend_sampler_v2.py +287 -0
- qiskit/primitives/base/base_estimator.py +4 -9
- qiskit/primitives/base/base_sampler.py +2 -2
- qiskit/primitives/containers/__init__.py +6 -4
- qiskit/primitives/containers/bit_array.py +293 -2
- qiskit/primitives/containers/data_bin.py +123 -50
- qiskit/primitives/containers/estimator_pub.py +10 -3
- qiskit/primitives/containers/observables_array.py +2 -2
- qiskit/primitives/containers/pub_result.py +1 -1
- qiskit/primitives/containers/sampler_pub.py +19 -3
- qiskit/primitives/containers/sampler_pub_result.py +74 -0
- qiskit/primitives/containers/shape.py +4 -4
- qiskit/primitives/statevector_estimator.py +4 -4
- qiskit/primitives/statevector_sampler.py +7 -12
- qiskit/providers/__init__.py +65 -34
- qiskit/providers/backend.py +2 -2
- qiskit/providers/backend_compat.py +8 -10
- qiskit/providers/basic_provider/__init__.py +2 -23
- qiskit/providers/basic_provider/basic_provider_tools.py +67 -31
- qiskit/providers/basic_provider/basic_simulator.py +81 -21
- qiskit/providers/fake_provider/__init__.py +1 -1
- qiskit/providers/fake_provider/fake_1q.py +1 -1
- qiskit/providers/fake_provider/fake_backend.py +3 -408
- qiskit/providers/fake_provider/generic_backend_v2.py +26 -14
- qiskit/providers/models/__init__.py +2 -2
- qiskit/providers/provider.py +16 -0
- qiskit/pulse/builder.py +4 -1
- qiskit/pulse/parameter_manager.py +60 -4
- qiskit/pulse/schedule.py +29 -13
- qiskit/pulse/utils.py +61 -20
- qiskit/qasm2/__init__.py +1 -5
- qiskit/qasm2/parse.py +1 -4
- qiskit/qasm3/__init__.py +42 -5
- qiskit/qasm3/ast.py +19 -0
- qiskit/qasm3/exporter.py +178 -106
- qiskit/qasm3/printer.py +27 -5
- qiskit/qobj/converters/pulse_instruction.py +6 -6
- qiskit/qpy/__init__.py +299 -67
- qiskit/qpy/binary_io/circuits.py +216 -47
- qiskit/qpy/binary_io/schedules.py +42 -36
- qiskit/qpy/binary_io/value.py +201 -22
- qiskit/qpy/common.py +1 -1
- qiskit/qpy/exceptions.py +20 -0
- qiskit/qpy/formats.py +29 -0
- qiskit/qpy/type_keys.py +21 -0
- qiskit/quantum_info/analysis/distance.py +3 -3
- qiskit/quantum_info/analysis/make_observable.py +2 -1
- qiskit/quantum_info/analysis/z2_symmetries.py +2 -1
- qiskit/quantum_info/operators/channel/chi.py +9 -8
- qiskit/quantum_info/operators/channel/choi.py +10 -9
- qiskit/quantum_info/operators/channel/kraus.py +2 -1
- qiskit/quantum_info/operators/channel/ptm.py +10 -9
- qiskit/quantum_info/operators/channel/quantum_channel.py +2 -1
- qiskit/quantum_info/operators/channel/stinespring.py +2 -1
- qiskit/quantum_info/operators/channel/superop.py +12 -11
- qiskit/quantum_info/operators/channel/transformations.py +12 -11
- qiskit/quantum_info/operators/dihedral/dihedral.py +5 -4
- qiskit/quantum_info/operators/operator.py +43 -30
- qiskit/quantum_info/operators/scalar_op.py +10 -9
- qiskit/quantum_info/operators/symplectic/base_pauli.py +70 -59
- qiskit/quantum_info/operators/symplectic/clifford.py +36 -9
- qiskit/quantum_info/operators/symplectic/pauli.py +53 -6
- qiskit/quantum_info/operators/symplectic/pauli_list.py +36 -14
- qiskit/quantum_info/operators/symplectic/random.py +3 -2
- qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +61 -36
- qiskit/quantum_info/states/densitymatrix.py +13 -13
- qiskit/quantum_info/states/stabilizerstate.py +3 -3
- qiskit/quantum_info/states/statevector.py +14 -13
- qiskit/quantum_info/states/utils.py +5 -3
- qiskit/result/__init__.py +6 -0
- qiskit/result/mitigation/correlated_readout_mitigator.py +3 -2
- qiskit/result/mitigation/local_readout_mitigator.py +2 -1
- qiskit/result/mitigation/utils.py +3 -2
- qiskit/scheduler/__init__.py +10 -1
- qiskit/scheduler/methods/__init__.py +1 -8
- qiskit/synthesis/__init__.py +3 -6
- qiskit/synthesis/discrete_basis/commutator_decompose.py +2 -2
- qiskit/synthesis/evolution/lie_trotter.py +7 -14
- qiskit/synthesis/evolution/qdrift.py +3 -4
- qiskit/synthesis/linear/cnot_synth.py +1 -3
- qiskit/synthesis/linear/linear_circuits_utils.py +1 -1
- qiskit/synthesis/linear_phase/cz_depth_lnn.py +4 -18
- qiskit/synthesis/permutation/__init__.py +1 -0
- qiskit/synthesis/permutation/permutation_reverse_lnn.py +90 -0
- qiskit/synthesis/qft/qft_decompose_lnn.py +2 -6
- qiskit/synthesis/two_qubit/two_qubit_decompose.py +165 -954
- qiskit/synthesis/two_qubit/xx_decompose/circuits.py +13 -12
- qiskit/synthesis/two_qubit/xx_decompose/decomposer.py +7 -1
- qiskit/synthesis/unitary/aqc/__init__.py +1 -1
- qiskit/synthesis/unitary/aqc/cnot_structures.py +2 -1
- qiskit/synthesis/unitary/aqc/fast_gradient/fast_gradient.py +2 -1
- qiskit/synthesis/unitary/qsd.py +3 -2
- qiskit/transpiler/__init__.py +7 -3
- qiskit/transpiler/layout.py +140 -61
- qiskit/transpiler/passes/__init__.py +10 -2
- qiskit/transpiler/passes/basis/basis_translator.py +9 -4
- qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
- qiskit/transpiler/passes/basis/unroll_custom_definitions.py +1 -1
- qiskit/transpiler/passes/calibration/rzx_builder.py +2 -1
- qiskit/transpiler/passes/layout/apply_layout.py +8 -3
- qiskit/transpiler/passes/layout/sabre_layout.py +15 -3
- qiskit/transpiler/passes/layout/set_layout.py +1 -1
- qiskit/transpiler/passes/optimization/__init__.py +2 -0
- qiskit/transpiler/passes/optimization/commutation_analysis.py +2 -2
- qiskit/transpiler/passes/optimization/commutative_cancellation.py +1 -1
- qiskit/transpiler/passes/optimization/consolidate_blocks.py +1 -1
- qiskit/transpiler/passes/optimization/cx_cancellation.py +10 -0
- qiskit/transpiler/passes/optimization/elide_permutations.py +114 -0
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +9 -3
- qiskit/transpiler/passes/optimization/optimize_annotated.py +248 -12
- qiskit/transpiler/passes/optimization/remove_final_reset.py +37 -0
- qiskit/transpiler/passes/optimization/template_matching/forward_match.py +1 -3
- qiskit/transpiler/passes/routing/__init__.py +1 -0
- qiskit/transpiler/passes/routing/basic_swap.py +13 -2
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +8 -1
- qiskit/transpiler/passes/routing/lookahead_swap.py +7 -1
- qiskit/transpiler/passes/routing/sabre_swap.py +10 -6
- qiskit/transpiler/passes/routing/star_prerouting.py +417 -0
- qiskit/transpiler/passes/routing/stochastic_swap.py +24 -8
- qiskit/transpiler/passes/scheduling/__init__.py +1 -1
- qiskit/transpiler/passes/scheduling/alap.py +1 -2
- qiskit/transpiler/passes/scheduling/alignments/align_measures.py +1 -2
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +9 -6
- qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +8 -0
- qiskit/transpiler/passes/scheduling/alignments/reschedule.py +13 -4
- qiskit/transpiler/passes/scheduling/asap.py +1 -2
- qiskit/transpiler/passes/scheduling/base_scheduler.py +21 -2
- qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +26 -4
- qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +24 -2
- qiskit/transpiler/passes/scheduling/time_unit_conversion.py +28 -4
- qiskit/transpiler/passes/synthesis/aqc_plugin.py +2 -2
- qiskit/transpiler/passes/synthesis/high_level_synthesis.py +120 -13
- qiskit/transpiler/passes/synthesis/unitary_synthesis.py +162 -55
- qiskit/transpiler/passes/utils/gates_basis.py +3 -3
- qiskit/transpiler/passmanager.py +44 -1
- qiskit/transpiler/preset_passmanagers/__init__.py +3 -3
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +34 -16
- qiskit/transpiler/preset_passmanagers/common.py +4 -6
- qiskit/transpiler/preset_passmanagers/plugin.py +9 -1
- qiskit/utils/__init__.py +3 -2
- qiskit/utils/optionals.py +6 -2
- qiskit/utils/parallel.py +24 -15
- qiskit/visualization/array.py +1 -1
- qiskit/visualization/bloch.py +2 -3
- qiskit/visualization/circuit/matplotlib.py +44 -14
- qiskit/visualization/circuit/text.py +38 -18
- qiskit/visualization/counts_visualization.py +3 -6
- qiskit/visualization/dag_visualization.py +6 -7
- qiskit/visualization/gate_map.py +9 -1
- qiskit/visualization/pulse_v2/interface.py +8 -3
- qiskit/visualization/state_visualization.py +3 -2
- qiskit/visualization/timeline/interface.py +18 -8
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/METADATA +12 -8
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/RECORD +261 -251
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/WHEEL +1 -1
- qiskit/_qasm2.pyd +0 -0
- qiskit/_qasm3.pyd +0 -0
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/LICENSE.txt +0 -0
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/entry_points.txt +0 -0
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/top_level.txt +0 -0
qiskit/circuit/quantumcircuit.py
CHANGED
@@ -15,7 +15,8 @@
|
|
15
15
|
"""Quantum circuit object."""
|
16
16
|
|
17
17
|
from __future__ import annotations
|
18
|
-
import copy
|
18
|
+
import copy as _copy
|
19
|
+
import itertools
|
19
20
|
import multiprocessing as mp
|
20
21
|
import typing
|
21
22
|
from collections import OrderedDict, defaultdict, namedtuple
|
@@ -35,7 +36,7 @@ from typing import (
|
|
35
36
|
overload,
|
36
37
|
)
|
37
38
|
import numpy as np
|
38
|
-
from qiskit._accelerate.
|
39
|
+
from qiskit._accelerate.circuit import CircuitData
|
39
40
|
from qiskit.exceptions import QiskitError
|
40
41
|
from qiskit.utils.multiprocessing import is_main_process
|
41
42
|
from qiskit.circuit.instruction import Instruction
|
@@ -44,6 +45,7 @@ from qiskit.circuit.parameter import Parameter
|
|
44
45
|
from qiskit.circuit.exceptions import CircuitError
|
45
46
|
from . import _classical_resource_map
|
46
47
|
from ._utils import sort_parameters
|
48
|
+
from .controlflow import ControlFlowOp
|
47
49
|
from .controlflow.builder import CircuitScopeInterface, ControlFlowBuilderBlock
|
48
50
|
from .controlflow.break_loop import BreakLoopOp, BreakLoopPlaceholder
|
49
51
|
from .controlflow.continue_loop import ContinueLoopOp, ContinueLoopPlaceholder
|
@@ -51,7 +53,7 @@ from .controlflow.for_loop import ForLoopOp, ForLoopContext
|
|
51
53
|
from .controlflow.if_else import IfElseOp, IfContext
|
52
54
|
from .controlflow.switch_case import SwitchCaseOp, SwitchContext
|
53
55
|
from .controlflow.while_loop import WhileLoopOp, WhileLoopContext
|
54
|
-
from .classical import expr
|
56
|
+
from .classical import expr, types
|
55
57
|
from .parameterexpression import ParameterExpression, ParameterValueType
|
56
58
|
from .quantumregister import QuantumRegister, Qubit, AncillaRegister, AncillaQubit
|
57
59
|
from .classicalregister import ClassicalRegister, Clbit
|
@@ -63,6 +65,7 @@ from .register import Register
|
|
63
65
|
from .bit import Bit
|
64
66
|
from .quantumcircuitdata import QuantumCircuitData, CircuitInstruction
|
65
67
|
from .delay import Delay
|
68
|
+
from .store import Store
|
66
69
|
|
67
70
|
if typing.TYPE_CHECKING:
|
68
71
|
import qiskit # pylint: disable=cyclic-import
|
@@ -103,95 +106,878 @@ ClbitSpecifier = Union[
|
|
103
106
|
BitType = TypeVar("BitType", Qubit, Clbit)
|
104
107
|
|
105
108
|
|
109
|
+
# NOTE:
|
110
|
+
#
|
111
|
+
# If you're adding methods or attributes to `QuantumCircuit`, be sure to update the class docstring
|
112
|
+
# to document them in a suitable place. The class is huge, so we do its documentation manually so
|
113
|
+
# it has at least some amount of organisational structure.
|
114
|
+
|
115
|
+
|
106
116
|
class QuantumCircuit:
|
107
|
-
"""
|
117
|
+
"""Core Qiskit representation of a quantum circuit.
|
118
|
+
|
119
|
+
.. note::
|
120
|
+
For more details setting the :class:`QuantumCircuit` in context of all of the data
|
121
|
+
structures that go with it, how it fits into the rest of the :mod:`qiskit` package, and the
|
122
|
+
different regimes of quantum-circuit descriptions in Qiskit, see the module-level
|
123
|
+
documentation of :mod:`qiskit.circuit`.
|
124
|
+
|
125
|
+
Circuit attributes
|
126
|
+
==================
|
127
|
+
|
128
|
+
:class:`QuantumCircuit` has a small number of public attributes, which are mostly older
|
129
|
+
functionality. Most of its functionality is accessed through methods.
|
130
|
+
|
131
|
+
A small handful of the attributes are intentionally mutable, the rest are data attributes that
|
132
|
+
should be considered immutable.
|
133
|
+
|
134
|
+
========================= ======================================================================
|
135
|
+
Mutable attribute Summary
|
136
|
+
========================= ======================================================================
|
137
|
+
:attr:`global_phase` The global phase of the circuit, measured in radians.
|
138
|
+
:attr:`metadata` Arbitrary user mapping, which Qiskit will preserve through the
|
139
|
+
transpiler, but otherwise completely ignore.
|
140
|
+
:attr:`name` An optional string name for the circuit.
|
141
|
+
========================= ======================================================================
|
142
|
+
|
143
|
+
========================= ======================================================================
|
144
|
+
Immutable data attribute Summary
|
145
|
+
========================= ======================================================================
|
146
|
+
:attr:`ancillas` List of :class:`AncillaQubit`\\ s tracked by the circuit.
|
147
|
+
:attr:`calibrations` Custom user-supplied pulse calibrations for individual instructions.
|
148
|
+
:attr:`cregs` List of :class:`ClassicalRegister`\\ s tracked by the circuit.
|
149
|
+
|
150
|
+
:attr:`clbits` List of :class:`Clbit`\\ s tracked by the circuit.
|
151
|
+
:attr:`data` List of individual :class:`CircuitInstruction`\\ s that make up the
|
152
|
+
circuit.
|
153
|
+
:attr:`duration` Total duration of the circuit, added by scheduling transpiler passes.
|
154
|
+
|
155
|
+
:attr:`layout` Hardware layout and routing information added by the transpiler.
|
156
|
+
:attr:`num_ancillas` The number of ancilla qubits in the circuit.
|
157
|
+
:attr:`num_clbits` The number of clbits in the circuit.
|
158
|
+
:attr:`num_captured_vars` Number of captured real-time classical variables.
|
159
|
+
|
160
|
+
:attr:`num_declared_vars` Number of locally declared real-time classical variables in the outer
|
161
|
+
circuit scope.
|
162
|
+
:attr:`num_input_vars` Number of input real-time classical variables.
|
163
|
+
:attr:`num_parameters` Number of compile-time :class:`Parameter`\\ s in the circuit.
|
164
|
+
:attr:`num_qubits` Number of qubits in the circuit.
|
165
|
+
|
166
|
+
:attr:`num_vars` Total number of real-time classical variables in the outer circuit
|
167
|
+
scope.
|
168
|
+
:attr:`op_start_times` Start times of scheduled operations, added by scheduling transpiler
|
169
|
+
passes.
|
170
|
+
:attr:`parameters` Ordered set-like view of the compile-time :class:`Parameter`\\ s
|
171
|
+
tracked by the circuit.
|
172
|
+
:attr:`qregs` List of :class:`QuantumRegister`\\ s tracked by the circuit.
|
173
|
+
|
174
|
+
:attr:`qubits` List of :class:`Qubit`\\ s tracked by the circuit.
|
175
|
+
:attr:`unit` The unit of the :attr:`duration` field.
|
176
|
+
========================= ======================================================================
|
177
|
+
|
178
|
+
The core attribute is :attr:`data`. This is a sequence-like object that exposes the
|
179
|
+
:class:`CircuitInstruction`\\ s contained in an ordered form. You generally should not mutate
|
180
|
+
this object directly; :class:`QuantumCircuit` is only designed for append-only operations (which
|
181
|
+
should use :meth:`append`). Most operations that mutate circuits in place should be written as
|
182
|
+
transpiler passes (:mod:`qiskit.transpiler`).
|
183
|
+
|
184
|
+
.. autoattribute:: data
|
185
|
+
|
186
|
+
Alongside the :attr:`data`, the :attr:`global_phase` of a circuit can have some impact on its
|
187
|
+
output, if the circuit is used to describe a :class:`.Gate` that may be controlled. This is
|
188
|
+
measured in radians and is directly settable.
|
189
|
+
|
190
|
+
.. autoattribute:: global_phase
|
191
|
+
|
192
|
+
The :attr:`name` of a circuit becomes the name of the :class:`~.circuit.Instruction` or
|
193
|
+
:class:`.Gate` resulting from :meth:`to_instruction` and :meth:`to_gate` calls, which can be
|
194
|
+
handy for visualizations.
|
195
|
+
|
196
|
+
.. autoattribute:: name
|
197
|
+
|
198
|
+
You can attach arbitrary :attr:`metadata` to a circuit. No part of core Qiskit will inspect
|
199
|
+
this or change its behavior based on metadata, but it will be faithfully passed through the
|
200
|
+
transpiler, so you can tag your circuits yourself. When serializing a circuit with QPY (see
|
201
|
+
:mod:`qiskit.qpy`), the metadata will be JSON-serialized and you may need to pass a custom
|
202
|
+
serializer to handle non-JSON-compatible objects within it (see :func:`.qpy.dump` for more
|
203
|
+
detail). This field is ignored during export to OpenQASM 2 or 3.
|
204
|
+
|
205
|
+
.. autoattribute:: metadata
|
206
|
+
|
207
|
+
:class:`QuantumCircuit` exposes data attributes tracking its internal quantum and classical bits
|
208
|
+
and registers. These appear as Python :class:`list`\\ s, but you should treat them as
|
209
|
+
immutable; changing them will *at best* have no effect, and more likely will simply corrupt
|
210
|
+
the internal data of the :class:`QuantumCircuit`.
|
211
|
+
|
212
|
+
.. autoattribute:: qregs
|
213
|
+
.. autoattribute:: cregs
|
214
|
+
.. autoattribute:: qubits
|
215
|
+
.. autoattribute:: ancillas
|
216
|
+
.. autoattribute:: clbits
|
217
|
+
|
218
|
+
The :ref:`compile-time parameters <circuit-compile-time-parameters>` present in instructions on
|
219
|
+
the circuit are available in :attr:`parameters`. This has a canonical order (mostly lexical,
|
220
|
+
except in the case of :class:`.ParameterVector`), which matches the order that parameters will
|
221
|
+
be assigned when using the list forms of :meth:`assign_parameters`, but also supports
|
222
|
+
:class:`set`-like constant-time membership testing.
|
223
|
+
|
224
|
+
.. autoattribute:: parameters
|
225
|
+
|
226
|
+
The storage of any :ref:`manual pulse-level calibrations <circuit-calibrations>` for individual
|
227
|
+
instructions on the circuit is in :attr:`calibrations`. This presents as a :class:`dict`, but
|
228
|
+
should not be mutated directly; use the methods discussed in :ref:`circuit-calibrations`.
|
229
|
+
|
230
|
+
.. autoattribute:: calibrations
|
231
|
+
|
232
|
+
If you have transpiled your circuit, so you have a physical circuit, you can inspect the
|
233
|
+
:attr:`layout` attribute for information stored by the transpiler about how the virtual qubits
|
234
|
+
of the source circuit map to the hardware qubits of your physical circuit, both at the start and
|
235
|
+
end of the circuit.
|
236
|
+
|
237
|
+
.. autoattribute:: layout
|
238
|
+
|
239
|
+
If your circuit was also *scheduled* as part of a transpilation, it will expose the individual
|
240
|
+
timings of each instruction, along with the total :attr:`duration` of the circuit.
|
241
|
+
|
242
|
+
.. autoattribute:: duration
|
243
|
+
.. autoattribute:: unit
|
244
|
+
.. autoattribute:: op_start_times
|
245
|
+
|
246
|
+
Finally, :class:`QuantumCircuit` exposes several simple properties as dynamic read-only numeric
|
247
|
+
attributes.
|
248
|
+
|
249
|
+
.. autoattribute:: num_ancillas
|
250
|
+
.. autoattribute:: num_clbits
|
251
|
+
.. autoattribute:: num_captured_vars
|
252
|
+
.. autoattribute:: num_declared_vars
|
253
|
+
.. autoattribute:: num_input_vars
|
254
|
+
.. autoattribute:: num_parameters
|
255
|
+
.. autoattribute:: num_qubits
|
256
|
+
.. autoattribute:: num_vars
|
257
|
+
|
258
|
+
Creating new circuits
|
259
|
+
=====================
|
260
|
+
|
261
|
+
========================= =====================================================================
|
262
|
+
Method Summary
|
263
|
+
========================= =====================================================================
|
264
|
+
:meth:`__init__` Default constructor of no-instruction circuits.
|
265
|
+
:meth:`copy` Make a complete copy of an existing circuit.
|
266
|
+
:meth:`copy_empty_like` Copy data objects from one circuit into a new one without any
|
267
|
+
instructions.
|
268
|
+
:meth:`from_instructions` Infer data objects needed from a list of instructions.
|
269
|
+
:meth:`from_qasm_file` Legacy interface to :func:`.qasm2.load`.
|
270
|
+
:meth:`from_qasm_str` Legacy interface to :func:`.qasm2.loads`.
|
271
|
+
========================= =====================================================================
|
272
|
+
|
273
|
+
The default constructor (``QuantumCircuit(...)``) produces a circuit with no initial
|
274
|
+
instructions. The arguments to the default constructor can be used to seed the circuit with
|
275
|
+
quantum and classical data storage, and to provide a name, global phase and arbitrary metadata.
|
276
|
+
All of these fields can be expanded later.
|
277
|
+
|
278
|
+
.. automethod:: __init__
|
279
|
+
|
280
|
+
If you have an existing circuit, you can produce a copy of it using :meth:`copy`, including all
|
281
|
+
its instructions. This is useful if you want to keep partial circuits while extending another,
|
282
|
+
or to have a version you can mutate in-place while leaving the prior one intact.
|
108
283
|
|
109
|
-
|
284
|
+
.. automethod:: copy
|
110
285
|
|
111
|
-
|
112
|
-
|
113
|
-
|
286
|
+
Similarly, if you want a circuit that contains all the same data objects (bits, registers,
|
287
|
+
variables, etc) but with none of the instructions, you can use :meth:`copy_empty_like`. This is
|
288
|
+
quite common when you want to build up a new layer of a circuit to then use apply onto the back
|
289
|
+
with :meth:`compose`, or to do a full rewrite of a circuit's instructions.
|
290
|
+
|
291
|
+
.. automethod:: copy_empty_like
|
292
|
+
|
293
|
+
In some cases, it is most convenient to generate a list of :class:`.CircuitInstruction`\\ s
|
294
|
+
separately to an entire circuit context, and then to build a circuit from this. The
|
295
|
+
:meth:`from_instructions` constructor will automatically capture all :class:`.Qubit` and
|
296
|
+
:class:`.Clbit` instances used in the instructions, and create a new :class:`QuantumCircuit`
|
297
|
+
object that has the correct resources and all the instructions.
|
298
|
+
|
299
|
+
.. automethod:: from_instructions
|
300
|
+
|
301
|
+
:class:`QuantumCircuit` also still has two constructor methods that are legacy wrappers around
|
302
|
+
the importers in :mod:`qiskit.qasm2`. These automatically apply :ref:`the legacy compatibility
|
303
|
+
settings <qasm2-legacy-compatibility>` of :func:`~.qasm2.load` and :func:`~.qasm2.loads`.
|
304
|
+
|
305
|
+
.. automethod:: from_qasm_file
|
306
|
+
.. automethod:: from_qasm_str
|
307
|
+
|
308
|
+
Data objects on circuits
|
309
|
+
========================
|
114
310
|
|
115
|
-
|
116
|
-
|
311
|
+
.. _circuit-adding-data-objects:
|
312
|
+
|
313
|
+
Adding data objects
|
314
|
+
-------------------
|
117
315
|
|
118
|
-
|
316
|
+
============================= =================================================================
|
317
|
+
Method Adds this kind of data
|
318
|
+
============================= =================================================================
|
319
|
+
:meth:`add_bits` :class:`.Qubit`\\ s and :class:`.Clbit`\\ s.
|
320
|
+
:meth:`add_register` :class:`.QuantumRegister` and :class:`.ClassicalRegister`.
|
321
|
+
:meth:`add_var` :class:`~.expr.Var` nodes with local scope and initializers.
|
322
|
+
:meth:`add_input` :class:`~.expr.Var` nodes that are treated as circuit inputs.
|
323
|
+
:meth:`add_capture` :class:`~.expr.Var` nodes captured from containing scopes.
|
324
|
+
:meth:`add_uninitialized_var` :class:`~.expr.Var` nodes with local scope and undefined state.
|
325
|
+
============================= =================================================================
|
119
326
|
|
120
|
-
|
121
|
-
|
122
|
-
|
327
|
+
Typically you add most of the data objects (:class:`.Qubit`, :class:`.Clbit`,
|
328
|
+
:class:`.ClassicalRegister`, etc) to the circuit as part of using the :meth:`__init__` default
|
329
|
+
constructor, or :meth:`copy_empty_like`. However, it is also possible to add these afterwards.
|
330
|
+
Typed classical data, such as standalone :class:`~.expr.Var` nodes (see
|
331
|
+
:ref:`circuit-repr-real-time-classical`), can be both constructed and added with separate
|
332
|
+
methods.
|
123
333
|
|
124
|
-
|
125
|
-
|
126
|
-
|
334
|
+
New registerless :class:`.Qubit` and :class:`.Clbit` objects are added using :meth:`add_bits`.
|
335
|
+
These objects must not already be present in the circuit. You can check if a bit exists in the
|
336
|
+
circuit already using :meth:`find_bit`.
|
337
|
+
|
338
|
+
.. automethod:: add_bits
|
339
|
+
|
340
|
+
Registers are added to the circuit with :meth:`add_register`. In this method, it is not an
|
341
|
+
error if some of the bits are already present in the circuit. In this case, the register will
|
342
|
+
be an "alias" over the bits. This is not generally well-supported by hardware backends; it is
|
343
|
+
probably best to stay away from relying on it. The registers a given bit is in are part of the
|
344
|
+
return of :meth:`find_bit`.
|
127
345
|
|
128
|
-
|
346
|
+
.. automethod:: add_register
|
129
347
|
|
130
|
-
|
131
|
-
|
348
|
+
:ref:`Real-time, typed classical data <circuit-repr-real-time-classical>` is represented on the
|
349
|
+
circuit by :class:`~.expr.Var` nodes with a well-defined :class:`~.types.Type`. It is possible
|
350
|
+
to instantiate these separately to a circuit (see :meth:`.Var.new`), but it is often more
|
351
|
+
convenient to use circuit methods that will automatically manage the types and expression
|
352
|
+
initialization for you. The two most common methods are :meth:`add_var` (locally scoped
|
353
|
+
variables) and :meth:`add_input` (inputs to the circuit).
|
132
354
|
|
133
|
-
|
134
|
-
|
355
|
+
.. automethod:: add_var
|
356
|
+
.. automethod:: add_input
|
135
357
|
|
358
|
+
In addition, there are two lower-level methods that can be useful for programmatic generation of
|
359
|
+
circuits. When working interactively, you will most likely not need these; most uses of
|
360
|
+
:meth:`add_uninitialized_var` are part of :meth:`copy_empty_like`, and most uses of
|
361
|
+
:meth:`add_capture` would be better off using :ref:`the control-flow builder interface
|
362
|
+
<circuit-control-flow-methods>`.
|
136
363
|
|
137
|
-
|
138
|
-
|
139
|
-
global_phase (float or ParameterExpression): The global phase of the circuit in radians.
|
140
|
-
metadata (dict): Arbitrary key value metadata to associate with the
|
141
|
-
circuit. This gets stored as free-form data in a dict in the
|
142
|
-
:attr:`~qiskit.circuit.QuantumCircuit.metadata` attribute. It will
|
143
|
-
not be directly used in the circuit.
|
364
|
+
.. automethod:: add_uninitialized_var
|
365
|
+
.. automethod:: add_capture
|
144
366
|
|
145
|
-
|
146
|
-
|
367
|
+
Working with bits and registers
|
368
|
+
-------------------------------
|
369
|
+
|
370
|
+
A :class:`.Bit` instance is, on its own, just a unique handle for circuits to use in their own
|
371
|
+
contexts. If you have got a :class:`.Bit` instance and a cirucit, just can find the contexts
|
372
|
+
that the bit exists in using :meth:`find_bit`, such as its integer index in the circuit and any
|
373
|
+
registers it is contained in.
|
374
|
+
|
375
|
+
.. automethod:: find_bit
|
376
|
+
|
377
|
+
Similarly, you can query a circuit to see if a register has already been added to it by using
|
378
|
+
:meth:`has_register`.
|
379
|
+
|
380
|
+
.. automethod:: has_register
|
381
|
+
|
382
|
+
Working with compile-time parameters
|
383
|
+
------------------------------------
|
384
|
+
|
385
|
+
.. seealso::
|
386
|
+
:ref:`circuit-compile-time-parameters`
|
387
|
+
A more complete discussion of what compile-time parametrization is, and how it fits into
|
388
|
+
Qiskit's data model.
|
389
|
+
|
390
|
+
Unlike bits, registers, and real-time typed classical data, compile-time symbolic parameters are
|
391
|
+
not manually added to a circuit. Their presence is inferred by being contained in operations
|
392
|
+
added to circuits and the global phase. An ordered list of all parameters currently in a
|
393
|
+
circuit is at :attr:`QuantumCircuit.parameters`.
|
394
|
+
|
395
|
+
The most common operation on :class:`.Parameter` instances is to replace them in symbolic
|
396
|
+
operations with some numeric value, or another symbolic expression. This is done with
|
397
|
+
:meth:`assign_parameters`.
|
398
|
+
|
399
|
+
.. automethod:: assign_parameters
|
400
|
+
|
401
|
+
The circuit tracks parameters by :class:`.Parameter` instances themselves, and forbids having
|
402
|
+
multiple parameters of the same name to avoid some problems when interoperating with OpenQASM or
|
403
|
+
other external formats. You can use :meth:`has_parameter` and :meth:`get_parameter` to query
|
404
|
+
the circuit for a parameter with the given string name.
|
405
|
+
|
406
|
+
.. automethod:: has_parameter
|
407
|
+
.. automethod:: get_parameter
|
408
|
+
|
409
|
+
.. _circuit-real-time-methods:
|
410
|
+
|
411
|
+
Working with real-time typed classical data
|
412
|
+
-------------------------------------------
|
413
|
+
|
414
|
+
.. seealso::
|
415
|
+
:mod:`qiskit.circuit.classical`
|
416
|
+
Module-level documentation for how the variable-, expression- and type-systems work, the
|
417
|
+
objects used to represent them, and the classical operations available.
|
418
|
+
|
419
|
+
:ref:`circuit-repr-real-time-classical`
|
420
|
+
A discussion of how real-time data fits into the entire :mod:`qiskit.circuit` data model
|
421
|
+
as a whole.
|
422
|
+
|
423
|
+
:ref:`circuit-adding-data-objects`
|
424
|
+
The methods for adding new :class:`~.expr.Var` variables to a circuit after
|
425
|
+
initialization.
|
426
|
+
|
427
|
+
You can retrive a :class:`~.expr.Var` instance attached to a circuit by using its variable name
|
428
|
+
using :meth:`get_var`, or check if a circuit contains a given variable with :meth:`has_var`.
|
429
|
+
|
430
|
+
.. automethod:: get_var
|
431
|
+
.. automethod:: has_var
|
432
|
+
|
433
|
+
There are also several iterator methods that you can use to get the full set of variables
|
434
|
+
tracked by a circuit. At least one of :meth:`iter_input_vars` and :meth:`iter_captured_vars`
|
435
|
+
will be empty, as inputs and captures are mutually exclusive. All of the iterators have
|
436
|
+
corresponding dynamic properties on :class:`QuantumCircuit` that contain their length:
|
437
|
+
:attr:`num_vars`, :attr:`num_input_vars`, :attr:`num_captured_vars` and
|
438
|
+
:attr:`num_declared_vars`.
|
439
|
+
|
440
|
+
.. automethod:: iter_vars
|
441
|
+
.. automethod:: iter_input_vars
|
442
|
+
.. automethod:: iter_captured_vars
|
443
|
+
.. automethod:: iter_declared_vars
|
444
|
+
|
445
|
+
|
446
|
+
.. _circuit-adding-operations:
|
447
|
+
|
448
|
+
Adding operations to circuits
|
449
|
+
=============================
|
450
|
+
|
451
|
+
You can add anything that implements the :class:`.Operation` interface to a circuit as a single
|
452
|
+
instruction, though most things you will want to add will be :class:`~.circuit.Instruction` or
|
453
|
+
:class:`~.circuit.Gate` instances.
|
454
|
+
|
455
|
+
.. seealso::
|
456
|
+
:ref:`circuit-operations-instructions`
|
457
|
+
The :mod:`qiskit.circuit`-level documentation on the different interfaces that Qiskit
|
458
|
+
uses to define circuit-level instructions.
|
459
|
+
|
460
|
+
.. _circuit-append-compose:
|
461
|
+
|
462
|
+
Methods to add general operations
|
463
|
+
---------------------------------
|
464
|
+
|
465
|
+
These are the base methods that handle adding any object, including user-defined ones, onto
|
466
|
+
circuits.
|
467
|
+
|
468
|
+
=============== ===============================================================================
|
469
|
+
Method When to use it
|
470
|
+
=============== ===============================================================================
|
471
|
+
:meth:`append` Add an instruction as a single object onto a circuit.
|
472
|
+
:meth:`_append` Same as :meth:`append`, but a low-level interface that elides almost all error
|
473
|
+
checking.
|
474
|
+
:meth:`compose` Inline the instructions from one circuit onto another.
|
475
|
+
:meth:`tensor` Like :meth:`compose`, but strictly for joining circuits that act on disjoint
|
476
|
+
qubits.
|
477
|
+
=============== ===============================================================================
|
478
|
+
|
479
|
+
:class:`QuantumCircuit` has two main ways that you will add more operations onto a circuit.
|
480
|
+
Which to use depends on whether you want to add your object as a single "instruction"
|
481
|
+
(:meth:`append`), or whether you want to join the instructions from two circuits together
|
482
|
+
(:meth:`compose`).
|
483
|
+
|
484
|
+
A single instruction or operation appears as a single entry in the :attr:`data` of the circuit,
|
485
|
+
and as a single box when drawn in the circuit visualizers (see :meth:`draw`). A single
|
486
|
+
instruction is the "unit" that a hardware backend might be defined in terms of (see
|
487
|
+
:class:`.Target`). An :class:`~.circuit.Instruction` can come with a
|
488
|
+
:attr:`~.circuit.Instruction.definition`, which is one rule the transpiler (see
|
489
|
+
:mod:`qiskit.transpiler`) will be able to fall back on to decompose it for hardware, if needed.
|
490
|
+
An :class:`.Operation` that is not also an :class:`~.circuit.Instruction` can
|
491
|
+
only be decomposed if it has some associated high-level synthesis method registered for it (see
|
492
|
+
:mod:`qiskit.transpiler.passes.synthesis.plugin`).
|
493
|
+
|
494
|
+
A :class:`QuantumCircuit` alone is not a single :class:`~.circuit.Instruction`; it is rather
|
495
|
+
more complicated, since it can, in general, represent a complete program with typed classical
|
496
|
+
memory inputs and outputs, and control flow. Qiskit's (and most hardware's) data model does not
|
497
|
+
yet have the concept of re-usable callable subroutines with virtual quantum operands. You can
|
498
|
+
convert simple circuits that act only on qubits with unitary operations into a :class:`.Gate`
|
499
|
+
using :meth:`to_gate`, and simple circuits acting only on qubits and clbits into a
|
500
|
+
:class:`~.circuit.Instruction` with :meth:`to_instruction`.
|
501
|
+
|
502
|
+
When you have an :class:`.Operation`, :class:`~.circuit.Instruction`, or :class:`.Gate`, add it
|
503
|
+
to the circuit, specifying the qubit and clbit arguments with :meth:`append`.
|
504
|
+
|
505
|
+
.. automethod:: append
|
506
|
+
|
507
|
+
:meth:`append` does quite substantial error checking to ensure that you cannot accidentally
|
508
|
+
break the data model of :class:`QuantumCircuit`. If you are programmatically generating a
|
509
|
+
circuit from known-good data, you can elide much of this error checking by using the fast-path
|
510
|
+
appender :meth:`_append`, but at the risk that the caller is responsible for ensuring they are
|
511
|
+
passing only valid data.
|
512
|
+
|
513
|
+
.. automethod:: _append
|
514
|
+
|
515
|
+
In other cases, you may want to join two circuits together, applying the instructions from one
|
516
|
+
circuit onto specified qubits and clbits on another circuit. This "inlining" operation is
|
517
|
+
called :meth:`compose` in Qiskit. :meth:`compose` is, in general, more powerful than
|
518
|
+
a :meth:`to_instruction`-plus-:meth:`append` combination for joining two circuits, because it
|
519
|
+
can also link typed classical data together, and allows for circuit control-flow operations to
|
520
|
+
be joined onto another circuit.
|
521
|
+
|
522
|
+
The downsides to :meth:`compose` are that it is a more complex operation that can involve more
|
523
|
+
rewriting of the operand, and that it necessarily must move data from one circuit object to
|
524
|
+
another. If you are building up a circuit for yourself and raw performance is a core goal,
|
525
|
+
consider passing around your base circuit and having different parts of your algorithm write
|
526
|
+
directly to the base circuit, rather than building a temporary layer circuit.
|
527
|
+
|
528
|
+
.. automethod:: compose
|
529
|
+
|
530
|
+
If you are trying to join two circuits that will apply to completely disjoint qubits and clbits,
|
531
|
+
:meth:`tensor` is a convenient wrapper around manually adding bit objects and calling
|
532
|
+
:meth:`compose`.
|
533
|
+
|
534
|
+
.. automethod:: tensor
|
535
|
+
|
536
|
+
As some rules of thumb:
|
537
|
+
|
538
|
+
* If you have a single :class:`.Operation`, :class:`~.circuit.Instruction` or :class:`.Gate`,
|
539
|
+
you should definitely use :meth:`append` or :meth:`_append`.
|
540
|
+
* If you have a :class:`QuantumCircuit` that represents a single atomic instruction for a larger
|
541
|
+
circuit that you want to re-use, you probably want to call :meth:`to_instruction` or
|
542
|
+
:meth:`to_gate`, and then apply the result of that to the circuit using :meth:`append`.
|
543
|
+
* If you have a :class:`QuantumCircuit` that represents a larger "layer" of another circuit, or
|
544
|
+
contains typed classical variables or control flow, you should use :meth:`compose` to merge it
|
545
|
+
onto another circuit.
|
546
|
+
* :meth:`tensor` is wanted far more rarely than either :meth:`append` or :meth:`compose`.
|
547
|
+
Internally, it is mostly a wrapper around :meth:`add_bits` and :meth:`compose`.
|
548
|
+
|
549
|
+
Some potential pitfalls to beware of:
|
550
|
+
|
551
|
+
* Even if you re-use a custom :class:`~.circuit.Instruction` during circuit construction, the
|
552
|
+
transpiler will generally have to "unroll" each invocation of it to its inner decomposition
|
553
|
+
before beginning work on it. This should not prevent you from using the
|
554
|
+
:meth:`to_instruction`-plus-:meth:`append` pattern, as the transpiler will improve in this
|
555
|
+
regard over time.
|
556
|
+
* :meth:`compose` will, by default, produce a new circuit for backwards compatibility. This is
|
557
|
+
more expensive, and not usually what you want, so you should set ``inplace=True``.
|
558
|
+
* Both :meth:`append` and :meth:`compose` (but not :meth:`_append`) have a ``copy`` keyword
|
559
|
+
argument that defaults to ``True``. In these cases, the incoming :class:`.Operation`
|
560
|
+
instances will be copied if Qiskit detects that the objects have mutability about them (such
|
561
|
+
as taking gate parameters). If you are sure that you will not re-use the objects again in
|
562
|
+
other places, you should set ``copy=False`` to prevent this copying, which can be a
|
563
|
+
substantial speed-up for large objects.
|
564
|
+
|
565
|
+
Methods to add standard instructions
|
566
|
+
------------------------------------
|
567
|
+
|
568
|
+
The :class:`QuantumCircuit` class has helper methods to add many of the Qiskit standard-library
|
569
|
+
instructions and gates onto a circuit. These are generally equivalent to manually constructing
|
570
|
+
an instance of the relevent :mod:`qiskit.circuit.library` object, then passing that to
|
571
|
+
:meth:`append` with the remaining arguments placed into the ``qargs`` and ``cargs`` fields as
|
572
|
+
appropriate.
|
573
|
+
|
574
|
+
The following methods apply special non-unitary :class:`~.circuit.Instruction` operations to the
|
575
|
+
circuit:
|
576
|
+
|
577
|
+
=============================== ====================================================
|
578
|
+
:class:`QuantumCircuit` method :mod:`qiskit.circuit` :class:`~.circuit.Instruction`
|
579
|
+
=============================== ====================================================
|
580
|
+
:meth:`barrier` :class:`Barrier`
|
581
|
+
:meth:`delay` :class:`Delay`
|
582
|
+
:meth:`initialize` :class:`~library.Initialize`
|
583
|
+
:meth:`measure` :class:`Measure`
|
584
|
+
:meth:`reset` :class:`Reset`
|
585
|
+
:meth:`store` :class:`Store`
|
586
|
+
=============================== ====================================================
|
587
|
+
|
588
|
+
These methods apply uncontrolled unitary :class:`.Gate` instances to the circuit:
|
589
|
+
|
590
|
+
=============================== ============================================
|
591
|
+
:class:`QuantumCircuit` method :mod:`qiskit.circuit.library` :class:`.Gate`
|
592
|
+
=============================== ============================================
|
593
|
+
:meth:`dcx` :class:`~library.DCXGate`
|
594
|
+
:meth:`ecr` :class:`~library.ECRGate`
|
595
|
+
:meth:`h` :class:`~library.HGate`
|
596
|
+
:meth:`id` :class:`~library.IGate`
|
597
|
+
:meth:`iswap` :class:`~library.iSwapGate`
|
598
|
+
:meth:`ms` :class:`~library.MSGate`
|
599
|
+
:meth:`p` :class:`~library.PhaseGate`
|
600
|
+
:meth:`pauli` :class:`~library.PauliGate`
|
601
|
+
:meth:`prepare_state` :class:`~library.StatePreparation`
|
602
|
+
:meth:`r` :class:`~library.RGate`
|
603
|
+
:meth:`rcccx` :class:`~library.RC3XGate`
|
604
|
+
:meth:`rccx` :class:`~library.RCCXGate`
|
605
|
+
:meth:`rv` :class:`~library.RVGate`
|
606
|
+
:meth:`rx` :class:`~library.RXGate`
|
607
|
+
:meth:`rxx` :class:`~library.RXXGate`
|
608
|
+
:meth:`ry` :class:`~library.RYGate`
|
609
|
+
:meth:`ryy` :class:`~library.RYYGate`
|
610
|
+
:meth:`rz` :class:`~library.RZGate`
|
611
|
+
:meth:`rzx` :class:`~library.RZXGate`
|
612
|
+
:meth:`rzz` :class:`~library.RZZGate`
|
613
|
+
:meth:`s` :class:`~library.SGate`
|
614
|
+
:meth:`sdg` :class:`~library.SdgGate`
|
615
|
+
:meth:`swap` :class:`~library.SwapGate`
|
616
|
+
:meth:`sx` :class:`~library.SXGate`
|
617
|
+
:meth:`sxdg` :class:`~library.SXdgGate`
|
618
|
+
:meth:`t` :class:`~library.TGate`
|
619
|
+
:meth:`tdg` :class:`~library.TdgGate`
|
620
|
+
:meth:`u` :class:`~library.UGate`
|
621
|
+
:meth:`unitary` :class:`~library.UnitaryGate`
|
622
|
+
:meth:`x` :class:`~library.XGate`
|
623
|
+
:meth:`y` :class:`~library.YGate`
|
624
|
+
:meth:`z` :class:`~library.ZGate`
|
625
|
+
=============================== ============================================
|
626
|
+
|
627
|
+
The following methods apply :class:`Gate` instances that are also controlled gates, so are
|
628
|
+
direct subclasses of :class:`ControlledGate`:
|
629
|
+
|
630
|
+
=============================== ======================================================
|
631
|
+
:class:`QuantumCircuit` method :mod:`qiskit.circuit.library` :class:`.ControlledGate`
|
632
|
+
=============================== ======================================================
|
633
|
+
:meth:`ccx` :class:`~library.CCXGate`
|
634
|
+
:meth:`ccz` :class:`~library.CCZGate`
|
635
|
+
:meth:`ch` :class:`~library.CHGate`
|
636
|
+
:meth:`cp` :class:`~library.CPhaseGate`
|
637
|
+
:meth:`crx` :class:`~library.CRXGate`
|
638
|
+
:meth:`cry` :class:`~library.CRYGate`
|
639
|
+
:meth:`crz` :class:`~library.CRZGate`
|
640
|
+
:meth:`cs` :class:`~library.CSGate`
|
641
|
+
:meth:`csdg` :class:`~library.CSdgGate`
|
642
|
+
:meth:`cswap` :class:`~library.CSwapGate`
|
643
|
+
:meth:`csx` :class:`~library.CSXGate`
|
644
|
+
:meth:`cu` :class:`~library.CUGate`
|
645
|
+
:meth:`cx` :class:`~library.CXGate`
|
646
|
+
:meth:`cy` :class:`~library.CYGate`
|
647
|
+
:meth:`cz` :class:`~library.CZGate`
|
648
|
+
=============================== ======================================================
|
649
|
+
|
650
|
+
Finally, these methods apply particular generalized multiply controlled gates to the circuit,
|
651
|
+
often with eager syntheses. They are listed in terms of the *base* gate they are controlling,
|
652
|
+
since their exact output is often a synthesised version of a gate.
|
653
|
+
|
654
|
+
=============================== =================================================
|
655
|
+
:class:`QuantumCircuit` method Base :mod:`qiskit.circuit.library` :class:`.Gate`
|
656
|
+
=============================== =================================================
|
657
|
+
:meth:`mcp` :class:`~library.PhaseGate`
|
658
|
+
:meth:`mcrx` :class:`~library.RXGate`
|
659
|
+
:meth:`mcry` :class:`~library.RYGate`
|
660
|
+
:meth:`mcrz` :class:`~library.RZGate`
|
661
|
+
:meth:`mcx` :class:`~library.XGate`
|
662
|
+
=============================== =================================================
|
663
|
+
|
664
|
+
The rest of this section is the API listing of all the individual methods; the tables above are
|
665
|
+
summaries whose links will jump you to the correct place.
|
666
|
+
|
667
|
+
.. automethod:: barrier
|
668
|
+
.. automethod:: ccx
|
669
|
+
.. automethod:: ccz
|
670
|
+
.. automethod:: ch
|
671
|
+
.. automethod:: cp
|
672
|
+
.. automethod:: crx
|
673
|
+
.. automethod:: cry
|
674
|
+
.. automethod:: crz
|
675
|
+
.. automethod:: cs
|
676
|
+
.. automethod:: csdg
|
677
|
+
.. automethod:: cswap
|
678
|
+
.. automethod:: csx
|
679
|
+
.. automethod:: cu
|
680
|
+
.. automethod:: cx
|
681
|
+
.. automethod:: cy
|
682
|
+
.. automethod:: cz
|
683
|
+
.. automethod:: dcx
|
684
|
+
.. automethod:: delay
|
685
|
+
.. automethod:: ecr
|
686
|
+
.. automethod:: h
|
687
|
+
.. automethod:: id
|
688
|
+
.. automethod:: initialize
|
689
|
+
.. automethod:: iswap
|
690
|
+
.. automethod:: mcp
|
691
|
+
.. automethod:: mcrx
|
692
|
+
.. automethod:: mcry
|
693
|
+
.. automethod:: mcrz
|
694
|
+
.. automethod:: mcx
|
695
|
+
.. automethod:: measure
|
696
|
+
.. automethod:: ms
|
697
|
+
.. automethod:: p
|
698
|
+
.. automethod:: pauli
|
699
|
+
.. automethod:: prepare_state
|
700
|
+
.. automethod:: r
|
701
|
+
.. automethod:: rcccx
|
702
|
+
.. automethod:: rccx
|
703
|
+
.. automethod:: reset
|
704
|
+
.. automethod:: rv
|
705
|
+
.. automethod:: rx
|
706
|
+
.. automethod:: rxx
|
707
|
+
.. automethod:: ry
|
708
|
+
.. automethod:: ryy
|
709
|
+
.. automethod:: rz
|
710
|
+
.. automethod:: rzx
|
711
|
+
.. automethod:: rzz
|
712
|
+
.. automethod:: s
|
713
|
+
.. automethod:: sdg
|
714
|
+
.. automethod:: store
|
715
|
+
.. automethod:: swap
|
716
|
+
.. automethod:: sx
|
717
|
+
.. automethod:: sxdg
|
718
|
+
.. automethod:: t
|
719
|
+
.. automethod:: tdg
|
720
|
+
.. automethod:: u
|
721
|
+
.. automethod:: unitary
|
722
|
+
.. automethod:: x
|
723
|
+
.. automethod:: y
|
724
|
+
.. automethod:: z
|
725
|
+
|
726
|
+
|
727
|
+
.. _circuit-control-flow-methods:
|
728
|
+
|
729
|
+
Adding control flow to circuits
|
730
|
+
-------------------------------
|
731
|
+
|
732
|
+
.. seealso::
|
733
|
+
:ref:`circuit-control-flow-repr`
|
734
|
+
|
735
|
+
Discussion of how control-flow operations are represented in the whole :mod:`qiskit.circuit`
|
736
|
+
context.
|
737
|
+
|
738
|
+
============================== ================================================================
|
739
|
+
:class:`QuantumCircuit` method Control-flow instruction
|
740
|
+
============================== ================================================================
|
741
|
+
:meth:`if_test` :class:`.IfElseOp` with only a ``True`` body.
|
742
|
+
:meth:`if_else` :class:`.IfElseOp` with both ``True`` and ``False`` bodies.
|
743
|
+
:meth:`while_loop` :class:`.WhileLoopOp`.
|
744
|
+
:meth:`switch` :class:`.SwitchCaseOp`.
|
745
|
+
:meth:`for_loop` :class:`.ForLoopOp`.
|
746
|
+
:meth:`break_loop` :class:`.BreakLoopOp`.
|
747
|
+
:meth:`continue_loop` :class:`.ContinueLoopOp`.
|
748
|
+
============================== ================================================================
|
749
|
+
|
750
|
+
:class:`QuantumCircuit` has corresponding methods for all of the control-flow operations that
|
751
|
+
are supported by Qiskit. These have two forms for calling them. The first is a very
|
752
|
+
straightfowards convenience wrapper that takes in the block bodies of the instructions as
|
753
|
+
:class:`QuantumCircuit` arguments, and simply constructs and appends the corresponding
|
754
|
+
:class:`.ControlFlowOp`.
|
755
|
+
|
756
|
+
The second form, which we strongly recommend you use for constructing control flow, is called
|
757
|
+
*the builder interface*. Here, the methods take only the real-time discriminant of the
|
758
|
+
operation, and return `context managers
|
759
|
+
<https://docs.python.org/3/library/stdtypes.html#typecontextmanager>`__ that you enter using
|
760
|
+
``with``. You can then use regular :class:`QuantumCircuit` methods within those blocks to build
|
761
|
+
up the control-flow bodies, and Qiskit will automatically track which of the data resources are
|
762
|
+
needed for the inner blocks, building the complete :class:`.ControlFlowOp` as you leave the
|
763
|
+
``with`` statement. It is far simpler and less error-prone to build control flow
|
764
|
+
programmatically this way.
|
765
|
+
|
766
|
+
..
|
767
|
+
TODO: expand the examples of the builder interface.
|
768
|
+
|
769
|
+
.. automethod:: break_loop
|
770
|
+
.. automethod:: continue_loop
|
771
|
+
.. automethod:: for_loop
|
772
|
+
.. automethod:: if_else
|
773
|
+
.. automethod:: if_test
|
774
|
+
.. automethod:: switch
|
775
|
+
.. automethod:: while_loop
|
776
|
+
|
777
|
+
|
778
|
+
Converting circuits to single objects
|
779
|
+
-------------------------------------
|
780
|
+
|
781
|
+
As discussed in :ref:`circuit-append-compose`, you can convert a circuit to either an
|
782
|
+
:class:`~.circuit.Instruction` or a :class:`.Gate` using two helper methods.
|
783
|
+
|
784
|
+
.. automethod:: to_instruction
|
785
|
+
.. automethod:: to_gate
|
786
|
+
|
787
|
+
|
788
|
+
Helper mutation methods
|
789
|
+
-----------------------
|
790
|
+
|
791
|
+
There are two higher-level methods on :class:`QuantumCircuit` for appending measurements to the
|
792
|
+
end of a circuit. Note that by default, these also add an extra register.
|
793
|
+
|
794
|
+
.. automethod:: measure_active
|
795
|
+
.. automethod:: measure_all
|
796
|
+
|
797
|
+
There are two "subtractive" methods on :class:`QuantumCircuit` as well. This is not a use-case
|
798
|
+
that :class:`QuantumCircuit` is designed for; typically you should just look to use
|
799
|
+
:meth:`copy_empty_like` in place of :meth:`clear`, and run :meth:`remove_final_measurements` as
|
800
|
+
its transpiler-pass form :class:`.RemoveFinalMeasurements`.
|
801
|
+
|
802
|
+
.. automethod:: clear
|
803
|
+
.. automethod:: remove_final_measurements
|
804
|
+
|
805
|
+
.. _circuit-calibrations:
|
806
|
+
|
807
|
+
Manual calibration of instructions
|
808
|
+
----------------------------------
|
809
|
+
|
810
|
+
:class:`QuantumCircuit` can store :attr:`calibrations` of instructions that define the pulses
|
811
|
+
used to run them on one particular hardware backend. You can
|
812
|
+
|
813
|
+
.. automethod:: add_calibration
|
814
|
+
.. automethod:: has_calibration_for
|
815
|
+
|
816
|
+
|
817
|
+
Circuit properties
|
818
|
+
==================
|
819
|
+
|
820
|
+
Simple circuit metrics
|
821
|
+
----------------------
|
822
|
+
|
823
|
+
When constructing quantum circuits, there are several properties that help quantify
|
824
|
+
the "size" of the circuits, and their ability to be run on a noisy quantum device.
|
825
|
+
Some of these, like number of qubits, are straightforward to understand, while others
|
826
|
+
like depth and number of tensor components require a bit more explanation. Here we will
|
827
|
+
explain all of these properties, and, in preparation for understanding how circuits change
|
828
|
+
when run on actual devices, highlight the conditions under which they change.
|
829
|
+
|
830
|
+
Consider the following circuit:
|
147
831
|
|
148
|
-
|
832
|
+
.. plot::
|
833
|
+
:include-source:
|
149
834
|
|
150
|
-
|
835
|
+
from qiskit import QuantumCircuit
|
836
|
+
qc = QuantumCircuit(12)
|
837
|
+
for idx in range(5):
|
838
|
+
qc.h(idx)
|
839
|
+
qc.cx(idx, idx+5)
|
151
840
|
|
152
|
-
|
153
|
-
|
841
|
+
qc.cx(1, 7)
|
842
|
+
qc.x(8)
|
843
|
+
qc.cx(1, 9)
|
844
|
+
qc.x(7)
|
845
|
+
qc.cx(1, 11)
|
846
|
+
qc.swap(6, 11)
|
847
|
+
qc.swap(6, 9)
|
848
|
+
qc.swap(6, 10)
|
849
|
+
qc.x(6)
|
850
|
+
qc.draw('mpl')
|
154
851
|
|
155
|
-
|
852
|
+
From the plot, it is easy to see that this circuit has 12 qubits, and a collection of
|
853
|
+
Hadamard, CNOT, X, and SWAP gates. But how to quantify this programmatically? Because we
|
854
|
+
can do single-qubit gates on all the qubits simultaneously, the number of qubits in this
|
855
|
+
circuit is equal to the :meth:`width` of the circuit::
|
156
856
|
|
157
|
-
|
158
|
-
qc.h(0)
|
159
|
-
qc.cx(0, 1)
|
160
|
-
qc.measure([0, 1], [0, 1])
|
161
|
-
qc.draw('mpl')
|
857
|
+
assert qc.width() == 12
|
162
858
|
|
163
|
-
|
859
|
+
We can also just get the number of qubits directly using :attr:`num_qubits`::
|
164
860
|
|
165
|
-
|
861
|
+
assert qc.num_qubits == 12
|
166
862
|
|
167
|
-
|
863
|
+
.. important::
|
168
864
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
865
|
+
For a quantum circuit composed from just qubits, the circuit width is equal
|
866
|
+
to the number of qubits. This is the definition used in quantum computing. However,
|
867
|
+
for more complicated circuits with classical registers, and classically controlled gates,
|
868
|
+
this equivalence breaks down. As such, from now on we will not refer to the number of
|
869
|
+
qubits in a quantum circuit as the width.
|
173
870
|
|
174
|
-
|
871
|
+
It is also straightforward to get the number and type of the gates in a circuit using
|
872
|
+
:meth:`count_ops`::
|
175
873
|
|
176
|
-
|
177
|
-
:include-source:
|
874
|
+
qc.count_ops()
|
178
875
|
|
179
|
-
|
876
|
+
.. parsed-literal::
|
180
877
|
|
181
|
-
|
182
|
-
anc = QuantumRegister(1, 'ancilla')
|
183
|
-
cr = ClassicalRegister(3, 'c')
|
184
|
-
qc = QuantumCircuit(qr, anc, cr)
|
878
|
+
OrderedDict([('cx', 8), ('h', 5), ('x', 3), ('swap', 3)])
|
185
879
|
|
186
|
-
|
187
|
-
|
188
|
-
qc.h(qr[0:3])
|
189
|
-
qc.cx(qr[0:3], anc[0])
|
190
|
-
qc.h(qr[0:3])
|
191
|
-
qc.barrier(qr)
|
192
|
-
qc.measure(qr, cr)
|
880
|
+
We can also get just the raw count of operations by computing the circuits
|
881
|
+
:meth:`size`::
|
193
882
|
|
194
|
-
|
883
|
+
assert qc.size() == 19
|
884
|
+
|
885
|
+
A particularly important circuit property is known as the circuit :meth:`depth`. The depth
|
886
|
+
of a quantum circuit is a measure of how many "layers" of quantum gates, executed in
|
887
|
+
parallel, it takes to complete the computation defined by the circuit. Because quantum
|
888
|
+
gates take time to implement, the depth of a circuit roughly corresponds to the amount of
|
889
|
+
time it takes the quantum computer to execute the circuit. Thus, the depth of a circuit
|
890
|
+
is one important quantity used to measure if a quantum circuit can be run on a device.
|
891
|
+
|
892
|
+
The depth of a quantum circuit has a mathematical definition as the longest path in a
|
893
|
+
directed acyclic graph (DAG). However, such a definition is a bit hard to grasp, even for
|
894
|
+
experts. Fortunately, the depth of a circuit can be easily understood by anyone familiar
|
895
|
+
with playing `Tetris <https://en.wikipedia.org/wiki/Tetris>`_. Lets see how to compute this
|
896
|
+
graphically:
|
897
|
+
|
898
|
+
.. image:: /source_images/depth.gif
|
899
|
+
|
900
|
+
We can verify our graphical result using :meth:`QuantumCircuit.depth`::
|
901
|
+
|
902
|
+
assert qc.depth() == 9
|
903
|
+
|
904
|
+
.. automethod:: count_ops
|
905
|
+
.. automethod:: depth
|
906
|
+
.. automethod:: get_instructions
|
907
|
+
.. automethod:: num_connected_components
|
908
|
+
.. automethod:: num_nonlocal_gates
|
909
|
+
.. automethod:: num_tensor_factors
|
910
|
+
.. automethod:: num_unitary_factors
|
911
|
+
.. automethod:: size
|
912
|
+
.. automethod:: width
|
913
|
+
|
914
|
+
Accessing scheduling information
|
915
|
+
--------------------------------
|
916
|
+
|
917
|
+
If a :class:`QuantumCircuit` has been scheduled as part of a transpilation pipeline, the timing
|
918
|
+
information for individual qubits can be accessed. The whole-circuit timing information is
|
919
|
+
available through the :attr:`duration`, :attr:`unit` and :attr:`op_start_times` attributes.
|
920
|
+
|
921
|
+
.. automethod:: qubit_duration
|
922
|
+
.. automethod:: qubit_start_time
|
923
|
+
.. automethod:: qubit_stop_time
|
924
|
+
|
925
|
+
Instruction-like methods
|
926
|
+
========================
|
927
|
+
|
928
|
+
..
|
929
|
+
These methods really shouldn't be on `QuantumCircuit` at all. They're generally more
|
930
|
+
appropriate as `Instruction` or `Gate` methods. `reverse_ops` shouldn't be a method _full
|
931
|
+
stop_---it was copying a `DAGCircuit` method from an implementation detail of the original
|
932
|
+
`SabreLayout` pass in Qiskit.
|
933
|
+
|
934
|
+
:class:`QuantumCircuit` also contains a small number of methods that are very
|
935
|
+
:class:`~.circuit.Instruction`-like in detail. You may well find better integration and more
|
936
|
+
API support if you first convert your circuit to an :class:`~.circuit.Instruction`
|
937
|
+
(:meth:`to_instruction`) or :class:`.Gate` (:meth:`to_gate`) as appropriate, then call the
|
938
|
+
corresponding method.
|
939
|
+
|
940
|
+
.. automethod:: control
|
941
|
+
.. automethod:: inverse
|
942
|
+
.. automethod:: power
|
943
|
+
.. automethod:: repeat
|
944
|
+
.. automethod:: reverse_ops
|
945
|
+
|
946
|
+
Visualization
|
947
|
+
=============
|
948
|
+
|
949
|
+
Qiskit includes some drawing tools to give you a quick feel for what your circuit looks like.
|
950
|
+
This tooling is primarily targeted at producing either a `Matplotlib
|
951
|
+
<https://matplotlib.org/>`__- or text-based drawing. There is also a lesser-featured LaTeX
|
952
|
+
backend for drawing, but this is only for simple circuits, and is not as actively maintained.
|
953
|
+
|
954
|
+
.. seealso::
|
955
|
+
:mod:`qiskit.visualization`
|
956
|
+
The primary documentation for all of Qiskit's visualization tooling.
|
957
|
+
|
958
|
+
.. automethod:: draw
|
959
|
+
|
960
|
+
In addition to the core :meth:`draw` driver, there are two visualization-related helper methods,
|
961
|
+
which are mostly useful for quickly unwrapping some inner instructions or reversing the
|
962
|
+
:ref:`qubit-labelling conventions <circuit-conventions>` in the drawing. For more general
|
963
|
+
mutation, including basis-gate rewriting, you should use the transpiler
|
964
|
+
(:mod:`qiskit.transpiler`).
|
965
|
+
|
966
|
+
.. automethod:: decompose
|
967
|
+
.. automethod:: reverse_bits
|
968
|
+
|
969
|
+
Internal utilities
|
970
|
+
==================
|
971
|
+
|
972
|
+
These functions are not intended for public use, but were accidentally left documented in the
|
973
|
+
public API during the 1.0 release. They will be removed in Qiskit 2.0, but will be supported
|
974
|
+
until then.
|
975
|
+
|
976
|
+
.. automethod:: cast
|
977
|
+
.. automethod:: cbit_argument_conversion
|
978
|
+
.. automethod:: cls_instances
|
979
|
+
.. automethod:: cls_prefix
|
980
|
+
.. automethod:: qbit_argument_conversion
|
195
981
|
"""
|
196
982
|
|
197
983
|
instances = 0
|
@@ -203,7 +989,73 @@ class QuantumCircuit:
|
|
203
989
|
name: str | None = None,
|
204
990
|
global_phase: ParameterValueType = 0,
|
205
991
|
metadata: dict | None = None,
|
992
|
+
inputs: Iterable[expr.Var] = (),
|
993
|
+
captures: Iterable[expr.Var] = (),
|
994
|
+
declarations: Mapping[expr.Var, expr.Expr] | Iterable[Tuple[expr.Var, expr.Expr]] = (),
|
206
995
|
):
|
996
|
+
"""
|
997
|
+
Default constructor of :class:`QuantumCircuit`.
|
998
|
+
|
999
|
+
..
|
1000
|
+
`QuantumCirucit` documents its `__init__` method explicitly, unlike most classes where
|
1001
|
+
it's implicitly appended to the class-level documentation, just because the class is so
|
1002
|
+
huge and has a lot of introductory material to its class docstring.
|
1003
|
+
|
1004
|
+
Args:
|
1005
|
+
regs: The registers to be included in the circuit.
|
1006
|
+
|
1007
|
+
* If a list of :class:`~.Register` objects, represents the :class:`.QuantumRegister`
|
1008
|
+
and/or :class:`.ClassicalRegister` objects to include in the circuit.
|
1009
|
+
|
1010
|
+
For example:
|
1011
|
+
|
1012
|
+
* ``QuantumCircuit(QuantumRegister(4))``
|
1013
|
+
* ``QuantumCircuit(QuantumRegister(4), ClassicalRegister(3))``
|
1014
|
+
* ``QuantumCircuit(QuantumRegister(4, 'qr0'), QuantumRegister(2, 'qr1'))``
|
1015
|
+
|
1016
|
+
* If a list of ``int``, the amount of qubits and/or classical bits to include in
|
1017
|
+
the circuit. It can either be a single int for just the number of quantum bits,
|
1018
|
+
or 2 ints for the number of quantum bits and classical bits, respectively.
|
1019
|
+
|
1020
|
+
For example:
|
1021
|
+
|
1022
|
+
* ``QuantumCircuit(4) # A QuantumCircuit with 4 qubits``
|
1023
|
+
* ``QuantumCircuit(4, 3) # A QuantumCircuit with 4 qubits and 3 classical bits``
|
1024
|
+
|
1025
|
+
* If a list of python lists containing :class:`.Bit` objects, a collection of
|
1026
|
+
:class:`.Bit` s to be added to the circuit.
|
1027
|
+
|
1028
|
+
name: the name of the quantum circuit. If not set, an automatically generated string
|
1029
|
+
will be assigned.
|
1030
|
+
global_phase: The global phase of the circuit in radians.
|
1031
|
+
metadata: Arbitrary key value metadata to associate with the circuit. This gets
|
1032
|
+
stored as free-form data in a dict in the
|
1033
|
+
:attr:`~qiskit.circuit.QuantumCircuit.metadata` attribute. It will not be directly
|
1034
|
+
used in the circuit.
|
1035
|
+
inputs: any variables to declare as ``input`` runtime variables for this circuit. These
|
1036
|
+
should already be existing :class:`.expr.Var` nodes that you build from somewhere
|
1037
|
+
else; if you need to create the inputs as well, use
|
1038
|
+
:meth:`QuantumCircuit.add_input`. The variables given in this argument will be
|
1039
|
+
passed directly to :meth:`add_input`. A circuit cannot have both ``inputs`` and
|
1040
|
+
``captures``.
|
1041
|
+
captures: any variables that that this circuit scope should capture from a containing
|
1042
|
+
scope. The variables given here will be passed directly to :meth:`add_capture`. A
|
1043
|
+
circuit cannot have both ``inputs`` and ``captures``.
|
1044
|
+
declarations: any variables that this circuit should declare and initialize immediately.
|
1045
|
+
You can order this input so that later declarations depend on earlier ones
|
1046
|
+
(including inputs or captures). If you need to depend on values that will be
|
1047
|
+
computed later at runtime, use :meth:`add_var` at an appropriate point in the
|
1048
|
+
circuit execution.
|
1049
|
+
|
1050
|
+
This argument is intended for convenient circuit initialization when you already
|
1051
|
+
have a set of created variables. The variables used here will be directly passed to
|
1052
|
+
:meth:`add_var`, which you can use directly if this is the first time you are
|
1053
|
+
creating the variable.
|
1054
|
+
|
1055
|
+
Raises:
|
1056
|
+
CircuitError: if the circuit name, if given, is not valid.
|
1057
|
+
CircuitError: if both ``inputs`` and ``captures`` are given.
|
1058
|
+
"""
|
207
1059
|
if any(not isinstance(reg, (list, QuantumRegister, ClassicalRegister)) for reg in regs):
|
208
1060
|
# check if inputs are integers, but also allow e.g. 2.0
|
209
1061
|
|
@@ -220,6 +1072,8 @@ class QuantumCircuit:
|
|
220
1072
|
|
221
1073
|
regs = tuple(int(reg) for reg in regs) # cast to int
|
222
1074
|
self._base_name = None
|
1075
|
+
self.name: str
|
1076
|
+
"""A human-readable name for the circuit."""
|
223
1077
|
if name is None:
|
224
1078
|
self._base_name = self.cls_prefix()
|
225
1079
|
self._name_update()
|
@@ -249,7 +1103,11 @@ class QuantumCircuit:
|
|
249
1103
|
] = []
|
250
1104
|
|
251
1105
|
self.qregs: list[QuantumRegister] = []
|
1106
|
+
"""A list of the :class:`QuantumRegister`\\ s in this circuit. You should not mutate
|
1107
|
+
this."""
|
252
1108
|
self.cregs: list[ClassicalRegister] = []
|
1109
|
+
"""A list of the :class:`ClassicalRegister`\\ s in this circuit. You should not mutate
|
1110
|
+
this."""
|
253
1111
|
|
254
1112
|
# Dict mapping Qubit or Clbit instances to tuple comprised of 0) the
|
255
1113
|
# corresponding index in circuit.{qubits,clbits} and 1) a list of
|
@@ -276,9 +1134,30 @@ class QuantumCircuit:
|
|
276
1134
|
self._global_phase: ParameterValueType = 0
|
277
1135
|
self.global_phase = global_phase
|
278
1136
|
|
279
|
-
|
1137
|
+
# Add classical variables. Resolve inputs and captures first because they can't depend on
|
1138
|
+
# anything, but declarations might depend on them.
|
1139
|
+
self._vars_input: dict[str, expr.Var] = {}
|
1140
|
+
self._vars_capture: dict[str, expr.Var] = {}
|
1141
|
+
self._vars_local: dict[str, expr.Var] = {}
|
1142
|
+
for input_ in inputs:
|
1143
|
+
self.add_input(input_)
|
1144
|
+
for capture in captures:
|
1145
|
+
self.add_capture(capture)
|
1146
|
+
if isinstance(declarations, Mapping):
|
1147
|
+
declarations = declarations.items()
|
1148
|
+
for var, initial in declarations:
|
1149
|
+
self.add_var(var, initial)
|
1150
|
+
|
1151
|
+
self.duration: int | float | None = None
|
1152
|
+
"""The total duration of the circuit, set by a scheduling transpiler pass. Its unit is
|
1153
|
+
specified by :attr:`unit`."""
|
280
1154
|
self.unit = "dt"
|
1155
|
+
"""The unit that :attr:`duration` is specified in."""
|
281
1156
|
self.metadata = {} if metadata is None else metadata
|
1157
|
+
"""Arbitrary user-defined metadata for the circuit.
|
1158
|
+
|
1159
|
+
Qiskit will not examine the content of this mapping, but it will pass it through the
|
1160
|
+
transpiler and reattach it to the output, so you can track your own metadata."""
|
282
1161
|
|
283
1162
|
@staticmethod
|
284
1163
|
def from_instructions(
|
@@ -295,7 +1174,7 @@ class QuantumCircuit:
|
|
295
1174
|
global_phase: ParameterValueType = 0,
|
296
1175
|
metadata: dict | None = None,
|
297
1176
|
) -> "QuantumCircuit":
|
298
|
-
"""Construct a circuit from an iterable of
|
1177
|
+
"""Construct a circuit from an iterable of :class:`.CircuitInstruction`\\ s.
|
299
1178
|
|
300
1179
|
Args:
|
301
1180
|
instructions: The instructions to add to the circuit.
|
@@ -352,7 +1231,7 @@ class QuantumCircuit:
|
|
352
1231
|
|
353
1232
|
@property
|
354
1233
|
def data(self) -> QuantumCircuitData:
|
355
|
-
"""
|
1234
|
+
"""The circuit data (instructions and context).
|
356
1235
|
|
357
1236
|
Returns:
|
358
1237
|
QuantumCircuitData: a list-like object containing the :class:`.CircuitInstruction`\\ s
|
@@ -387,10 +1266,10 @@ class QuantumCircuit:
|
|
387
1266
|
return
|
388
1267
|
if isinstance(data_input[0], CircuitInstruction):
|
389
1268
|
for instruction in data_input:
|
390
|
-
self.append(instruction)
|
1269
|
+
self.append(instruction, copy=False)
|
391
1270
|
else:
|
392
1271
|
for instruction, qargs, cargs in data_input:
|
393
|
-
self.append(instruction, qargs, cargs)
|
1272
|
+
self.append(instruction, qargs, cargs, copy=False)
|
394
1273
|
|
395
1274
|
@property
|
396
1275
|
def op_start_times(self) -> list[int]:
|
@@ -497,7 +1376,7 @@ class QuantumCircuit:
|
|
497
1376
|
cls = self.__class__
|
498
1377
|
result = cls.__new__(cls)
|
499
1378
|
for k in self.__dict__.keys() - {"_data", "_builder_api"}:
|
500
|
-
setattr(result, k,
|
1379
|
+
setattr(result, k, _copy.deepcopy(self.__dict__[k], memo))
|
501
1380
|
|
502
1381
|
result._builder_api = _OuterCircuitScopeInterface(result)
|
503
1382
|
|
@@ -505,10 +1384,10 @@ class QuantumCircuit:
|
|
505
1384
|
# like we would when pickling.
|
506
1385
|
result._data = self._data.copy()
|
507
1386
|
result._data.replace_bits(
|
508
|
-
qubits=
|
509
|
-
clbits=
|
1387
|
+
qubits=_copy.deepcopy(self._data.qubits, memo),
|
1388
|
+
clbits=_copy.deepcopy(self._data.clbits, memo),
|
510
1389
|
)
|
511
|
-
result._data.map_ops(lambda op:
|
1390
|
+
result._data.map_ops(lambda op: _copy.deepcopy(op, memo))
|
512
1391
|
return result
|
513
1392
|
|
514
1393
|
@classmethod
|
@@ -583,9 +1462,7 @@ class QuantumCircuit:
|
|
583
1462
|
q_1: ┤ RX(1.57) ├─────
|
584
1463
|
└──────────┘
|
585
1464
|
"""
|
586
|
-
reverse_circ =
|
587
|
-
self.qubits, self.clbits, *self.qregs, *self.cregs, name=self.name + "_reverse"
|
588
|
-
)
|
1465
|
+
reverse_circ = self.copy_empty_like(self.name + "_reverse")
|
589
1466
|
|
590
1467
|
for instruction in reversed(self.data):
|
591
1468
|
reverse_circ._append(instruction.replace(operation=instruction.operation.reverse_ops()))
|
@@ -739,26 +1616,38 @@ class QuantumCircuit:
|
|
739
1616
|
|
740
1617
|
return repeated_circ
|
741
1618
|
|
742
|
-
def power(
|
1619
|
+
def power(
|
1620
|
+
self, power: float, matrix_power: bool = False, annotated: bool = False
|
1621
|
+
) -> "QuantumCircuit":
|
743
1622
|
"""Raise this circuit to the power of ``power``.
|
744
1623
|
|
745
|
-
If ``power`` is a positive integer and ``matrix_power``
|
746
|
-
defaults to calling ``repeat``. Otherwise,
|
747
|
-
|
1624
|
+
If ``power`` is a positive integer and both ``matrix_power`` and ``annotated``
|
1625
|
+
are ``False``, this implementation defaults to calling ``repeat``. Otherwise,
|
1626
|
+
the circuit is converted into a gate, and a new circuit, containing this gate
|
1627
|
+
raised to the given power, is returned. The gate raised to the given power is
|
1628
|
+
implemented either as a unitary gate if ``annotated`` is ``False`` or as an
|
1629
|
+
annotated operation if ``annotated`` is ``True``.
|
748
1630
|
|
749
1631
|
Args:
|
750
1632
|
power (float): The power to raise this circuit to.
|
751
|
-
matrix_power (bool):
|
752
|
-
|
753
|
-
|
1633
|
+
matrix_power (bool): indicates whether the inner power gate can be implemented
|
1634
|
+
as a unitary gate.
|
1635
|
+
annotated (bool): indicates whether the inner power gate can be implemented
|
1636
|
+
as an annotated operation.
|
754
1637
|
|
755
1638
|
Raises:
|
756
|
-
CircuitError: If the circuit needs to be converted to a gate but
|
1639
|
+
CircuitError: If the circuit needs to be converted to a unitary gate, but is
|
1640
|
+
not unitary.
|
757
1641
|
|
758
1642
|
Returns:
|
759
1643
|
QuantumCircuit: A circuit implementing this circuit raised to the power of ``power``.
|
760
1644
|
"""
|
761
|
-
if
|
1645
|
+
if (
|
1646
|
+
power >= 0
|
1647
|
+
and isinstance(power, (int, np.integer))
|
1648
|
+
and not matrix_power
|
1649
|
+
and not annotated
|
1650
|
+
):
|
762
1651
|
return self.repeat(power)
|
763
1652
|
|
764
1653
|
# attempt conversion to gate
|
@@ -774,12 +1663,12 @@ class QuantumCircuit:
|
|
774
1663
|
except QiskitError as ex:
|
775
1664
|
raise CircuitError(
|
776
1665
|
"The circuit contains non-unitary operations and cannot be "
|
777
|
-
"
|
778
|
-
"be in the circuit for this operation."
|
1666
|
+
"raised to a power. Note that no qiskit.circuit.Instruction "
|
1667
|
+
"objects may be in the circuit for this operation."
|
779
1668
|
) from ex
|
780
1669
|
|
781
1670
|
power_circuit = QuantumCircuit(self.qubits, self.clbits, *self.qregs, *self.cregs)
|
782
|
-
power_circuit.append(gate.power(power), list(range(gate.num_qubits)))
|
1671
|
+
power_circuit.append(gate.power(power, annotated=annotated), list(range(gate.num_qubits)))
|
783
1672
|
return power_circuit
|
784
1673
|
|
785
1674
|
def control(
|
@@ -831,10 +1720,36 @@ class QuantumCircuit:
|
|
831
1720
|
front: bool = False,
|
832
1721
|
inplace: bool = False,
|
833
1722
|
wrap: bool = False,
|
1723
|
+
*,
|
1724
|
+
copy: bool = True,
|
1725
|
+
var_remap: Mapping[str | expr.Var, str | expr.Var] | None = None,
|
1726
|
+
inline_captures: bool = False,
|
834
1727
|
) -> Optional["QuantumCircuit"]:
|
835
|
-
"""
|
1728
|
+
"""Apply the instructions from one circuit onto specified qubits and/or clbits on another.
|
1729
|
+
|
1730
|
+
.. note::
|
1731
|
+
|
1732
|
+
By default, this creates a new circuit object, leaving ``self`` untouched. For most
|
1733
|
+
uses of this function, it is far more efficient to set ``inplace=True`` and modify the
|
1734
|
+
base circuit in-place.
|
836
1735
|
|
837
|
-
|
1736
|
+
When dealing with realtime variables (:class:`.expr.Var` instances), there are two principal
|
1737
|
+
strategies for using :meth:`compose`:
|
1738
|
+
|
1739
|
+
1. The ``other`` circuit is treated as entirely additive, including its variables. The
|
1740
|
+
variables in ``other`` must be entirely distinct from those in ``self`` (use
|
1741
|
+
``var_remap`` to help with this), and all variables in ``other`` will be declared anew in
|
1742
|
+
the output with matching input/capture/local scoping to how they are in ``other``. This
|
1743
|
+
is generally what you want if you're joining two unrelated circuits.
|
1744
|
+
|
1745
|
+
2. The ``other`` circuit was created as an exact extension to ``self`` to be inlined onto
|
1746
|
+
it, including acting on the existing variables in their states at the end of ``self``.
|
1747
|
+
In this case, ``other`` should be created with all these variables to be inlined declared
|
1748
|
+
as "captures", and then you can use ``inline_captures=True`` in this method to link them.
|
1749
|
+
This is generally what you want if you're building up a circuit by defining layers
|
1750
|
+
on-the-fly, or rebuilding a circuit using layers taken from itself. You might find the
|
1751
|
+
``vars_mode="captures"`` argument to :meth:`copy_empty_like` useful to create each
|
1752
|
+
layer's base, in this case.
|
838
1753
|
|
839
1754
|
Args:
|
840
1755
|
other (qiskit.circuit.Instruction or QuantumCircuit):
|
@@ -845,8 +1760,35 @@ class QuantumCircuit:
|
|
845
1760
|
front (bool): If True, front composition will be performed. This is not possible within
|
846
1761
|
control-flow builder context managers.
|
847
1762
|
inplace (bool): If True, modify the object. Otherwise return composed circuit.
|
1763
|
+
copy (bool): If ``True`` (the default), then the input is treated as shared, and any
|
1764
|
+
contained instructions will be copied, if they might need to be mutated in the
|
1765
|
+
future. You can set this to ``False`` if the input should be considered owned by
|
1766
|
+
the base circuit, in order to avoid unnecessary copies; in this case, it is not
|
1767
|
+
valid to use ``other`` afterwards, and some instructions may have been mutated in
|
1768
|
+
place.
|
1769
|
+
var_remap (Mapping): mapping to use to rewrite :class:`.expr.Var` nodes in ``other`` as
|
1770
|
+
they are inlined into ``self``. This can be used to avoid naming conflicts.
|
1771
|
+
|
1772
|
+
Both keys and values can be given as strings or direct :class:`.expr.Var` instances.
|
1773
|
+
If a key is a string, it matches any :class:`~.expr.Var` with the same name. If a
|
1774
|
+
value is a string, whenever a new key matches a it, a new :class:`~.expr.Var` is
|
1775
|
+
created with the correct type. If a value is a :class:`~.expr.Var`, its
|
1776
|
+
:class:`~.expr.Expr.type` must exactly match that of the variable it is replacing.
|
1777
|
+
inline_captures (bool): if ``True``, then all "captured" :class:`~.expr.Var` nodes in
|
1778
|
+
the ``other`` :class:`.QuantumCircuit` are assumed to refer to variables already
|
1779
|
+
declared in ``self`` (as any input/capture/local type), and the uses in ``other``
|
1780
|
+
will apply to the existing variables. If you want to build up a layer for an
|
1781
|
+
existing circuit to use with :meth:`compose`, you might find the
|
1782
|
+
``vars_mode="captures"`` argument to :meth:`copy_empty_like` useful. Any remapping
|
1783
|
+
in ``vars_remap`` occurs before evaluating this variable inlining.
|
1784
|
+
|
1785
|
+
If this is ``False`` (the default), then all variables in ``other`` will be required
|
1786
|
+
to be distinct from those in ``self``, and new declarations will be made for them.
|
848
1787
|
wrap (bool): If True, wraps the other circuit into a gate (or instruction, depending on
|
849
1788
|
whether it contains only unitary instructions) before composing it onto self.
|
1789
|
+
Rather than using this option, it is almost always better to manually control this
|
1790
|
+
yourself by using :meth:`to_instruction` or :meth:`to_gate`, and then call
|
1791
|
+
:meth:`append`.
|
850
1792
|
|
851
1793
|
Returns:
|
852
1794
|
QuantumCircuit: the composed circuit (returns None if inplace==True).
|
@@ -903,6 +1845,31 @@ class QuantumCircuit:
|
|
903
1845
|
# error that the user might want to correct in an interactive session.
|
904
1846
|
dest = self if inplace else self.copy()
|
905
1847
|
|
1848
|
+
var_remap = {} if var_remap is None else var_remap
|
1849
|
+
|
1850
|
+
# This doesn't use `functools.cache` so we can access it during the variable remapping of
|
1851
|
+
# instructions. We cache all replacement lookups for a) speed and b) to ensure that
|
1852
|
+
# the same variable _always_ maps to the same replacement even if it's used in different
|
1853
|
+
# places in the recursion tree (such as being a captured variable).
|
1854
|
+
def replace_var(var: expr.Var, cache: Mapping[expr.Var, expr.Var]) -> expr.Var:
|
1855
|
+
# This is closing over an argument to `compose`.
|
1856
|
+
nonlocal var_remap
|
1857
|
+
|
1858
|
+
if out := cache.get(var):
|
1859
|
+
return out
|
1860
|
+
if (replacement := var_remap.get(var)) or (replacement := var_remap.get(var.name)):
|
1861
|
+
if isinstance(replacement, str):
|
1862
|
+
replacement = expr.Var.new(replacement, var.type)
|
1863
|
+
if replacement.type != var.type:
|
1864
|
+
raise CircuitError(
|
1865
|
+
f"mismatched types in replacement for '{var.name}':"
|
1866
|
+
f" '{var.type}' cannot become '{replacement.type}'"
|
1867
|
+
)
|
1868
|
+
else:
|
1869
|
+
replacement = var
|
1870
|
+
cache[var] = replacement
|
1871
|
+
return replacement
|
1872
|
+
|
906
1873
|
# As a special case, allow composing some clbits onto no clbits - normally the destination
|
907
1874
|
# has to be strictly larger. This allows composing final measurements onto unitary circuits.
|
908
1875
|
if isinstance(other, QuantumCircuit):
|
@@ -931,11 +1898,11 @@ class QuantumCircuit:
|
|
931
1898
|
# Need to keep a reference to the data for use after we've emptied it.
|
932
1899
|
old_data = dest._data.copy()
|
933
1900
|
dest.clear()
|
934
|
-
dest.append(other, qubits, clbits)
|
1901
|
+
dest.append(other, qubits, clbits, copy=copy)
|
935
1902
|
for instruction in old_data:
|
936
1903
|
dest._append(instruction)
|
937
1904
|
else:
|
938
|
-
dest.append(other, qargs=qubits, cargs=clbits)
|
1905
|
+
dest.append(other, qargs=qubits, cargs=clbits, copy=copy)
|
939
1906
|
return None if inplace else dest
|
940
1907
|
|
941
1908
|
if other.num_qubits > dest.num_qubits or other.num_clbits > dest.num_clbits:
|
@@ -986,37 +1953,100 @@ class QuantumCircuit:
|
|
986
1953
|
dest.unit = "dt"
|
987
1954
|
dest.global_phase += other.global_phase
|
988
1955
|
|
989
|
-
if
|
990
|
-
|
991
|
-
|
992
|
-
# directly.
|
993
|
-
return None if inplace else dest
|
1956
|
+
# This is required to trigger data builds if the `other` is an unbuilt `BlueprintCircuit`,
|
1957
|
+
# so we can the access the complete `CircuitData` object at `_data`.
|
1958
|
+
_ = other.data
|
994
1959
|
|
995
|
-
|
996
|
-
dest
|
997
|
-
)
|
1960
|
+
def copy_with_remapping(
|
1961
|
+
source, dest, bit_map, var_map, inline_captures, new_qubits=None, new_clbits=None
|
1962
|
+
):
|
1963
|
+
# Copy the instructions from `source` into `dest`, remapping variables in instructions
|
1964
|
+
# according to `var_map`. If `new_qubits` or `new_clbits` are given, the qubits and
|
1965
|
+
# clbits of the source instruction are remapped to those as well.
|
1966
|
+
for var in source.iter_input_vars():
|
1967
|
+
dest.add_input(replace_var(var, var_map))
|
1968
|
+
if inline_captures:
|
1969
|
+
for var in source.iter_captured_vars():
|
1970
|
+
replacement = replace_var(var, var_map)
|
1971
|
+
if not dest.has_var(replace_var(var, var_map)):
|
1972
|
+
if var is replacement:
|
1973
|
+
raise CircuitError(
|
1974
|
+
f"Variable '{var}' to be inlined is not in the base circuit."
|
1975
|
+
" If you wanted it to be automatically added, use"
|
1976
|
+
" `inline_captures=False`."
|
1977
|
+
)
|
1978
|
+
raise CircuitError(
|
1979
|
+
f"Replacement '{replacement}' for variable '{var}' is not in the"
|
1980
|
+
" base circuit. Is the replacement correct?"
|
1981
|
+
)
|
1982
|
+
else:
|
1983
|
+
for var in source.iter_captured_vars():
|
1984
|
+
dest.add_capture(replace_var(var, var_map))
|
1985
|
+
for var in source.iter_declared_vars():
|
1986
|
+
dest.add_uninitialized_var(replace_var(var, var_map))
|
1987
|
+
|
1988
|
+
def recurse_block(block):
|
1989
|
+
# Recurse the remapping into a control-flow block. Note that this doesn't remap the
|
1990
|
+
# clbits within; the story around nested classical-register-based control-flow
|
1991
|
+
# doesn't really work in the current data model, and we hope to replace it with
|
1992
|
+
# `Expr`-based control-flow everywhere.
|
1993
|
+
new_block = block.copy_empty_like()
|
1994
|
+
new_block._vars_input = {}
|
1995
|
+
new_block._vars_capture = {}
|
1996
|
+
new_block._vars_local = {}
|
1997
|
+
# For the recursion, we never want to inline captured variables because we're not
|
1998
|
+
# copying onto a base that has variables.
|
1999
|
+
copy_with_remapping(block, new_block, bit_map, var_map, inline_captures=False)
|
2000
|
+
return new_block
|
2001
|
+
|
2002
|
+
variable_mapper = _classical_resource_map.VariableMapper(
|
2003
|
+
dest.cregs, bit_map, var_map, add_register=dest.add_register
|
2004
|
+
)
|
998
2005
|
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
2006
|
+
def map_vars(op):
|
2007
|
+
n_op = op
|
2008
|
+
is_control_flow = isinstance(n_op, ControlFlowOp)
|
2009
|
+
if (
|
2010
|
+
not is_control_flow
|
2011
|
+
and (condition := getattr(n_op, "condition", None)) is not None
|
2012
|
+
):
|
2013
|
+
n_op = n_op.copy() if n_op is op and copy else n_op
|
2014
|
+
n_op.condition = variable_mapper.map_condition(condition)
|
2015
|
+
elif is_control_flow:
|
2016
|
+
n_op = n_op.replace_blocks(recurse_block(block) for block in n_op.blocks)
|
2017
|
+
if isinstance(n_op, (IfElseOp, WhileLoopOp)):
|
2018
|
+
n_op.condition = variable_mapper.map_condition(n_op.condition)
|
2019
|
+
elif isinstance(n_op, SwitchCaseOp):
|
2020
|
+
n_op.target = variable_mapper.map_target(n_op.target)
|
2021
|
+
elif isinstance(n_op, Store):
|
2022
|
+
n_op = Store(
|
2023
|
+
variable_mapper.map_expr(n_op.lvalue), variable_mapper.map_expr(n_op.rvalue)
|
2024
|
+
)
|
2025
|
+
return n_op.copy() if n_op is op and copy else n_op
|
1006
2026
|
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
2027
|
+
instructions = source._data.copy()
|
2028
|
+
instructions.replace_bits(qubits=new_qubits, clbits=new_clbits)
|
2029
|
+
instructions.map_ops(map_vars)
|
2030
|
+
dest._current_scope().extend(instructions)
|
1010
2031
|
|
1011
2032
|
append_existing = None
|
1012
2033
|
if front:
|
1013
2034
|
append_existing = dest._data.copy()
|
1014
2035
|
dest.clear()
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
2036
|
+
copy_with_remapping(
|
2037
|
+
other,
|
2038
|
+
dest,
|
2039
|
+
bit_map=edge_map,
|
2040
|
+
# The actual `Var: Var` map gets built up from the more freeform user input as we
|
2041
|
+
# encounter the variables, since the user might be using string keys to refer to more
|
2042
|
+
# than one variable in separated scopes of control-flow operations.
|
2043
|
+
var_map={},
|
2044
|
+
inline_captures=inline_captures,
|
2045
|
+
new_qubits=mapped_qubits,
|
2046
|
+
new_clbits=mapped_clbits,
|
2047
|
+
)
|
1018
2048
|
if append_existing:
|
1019
|
-
|
2049
|
+
dest._current_scope().extend(append_existing)
|
1020
2050
|
|
1021
2051
|
return None if inplace else dest
|
1022
2052
|
|
@@ -1112,25 +2142,90 @@ class QuantumCircuit:
|
|
1112
2142
|
|
1113
2143
|
@property
|
1114
2144
|
def qubits(self) -> list[Qubit]:
|
1115
|
-
"""
|
1116
|
-
|
1117
|
-
"""
|
2145
|
+
"""A list of :class:`Qubit`\\ s in the order that they were added. You should not mutate
|
2146
|
+
this."""
|
1118
2147
|
return self._data.qubits
|
1119
2148
|
|
1120
2149
|
@property
|
1121
2150
|
def clbits(self) -> list[Clbit]:
|
1122
|
-
"""
|
1123
|
-
|
1124
|
-
"""
|
2151
|
+
"""A list of :class:`Clbit`\\ s in the order that they were added. You should not mutate
|
2152
|
+
this."""
|
1125
2153
|
return self._data.clbits
|
1126
2154
|
|
1127
2155
|
@property
|
1128
2156
|
def ancillas(self) -> list[AncillaQubit]:
|
1129
|
-
"""
|
1130
|
-
|
1131
|
-
"""
|
2157
|
+
"""A list of :class:`AncillaQubit`\\ s in the order that they were added. You should not
|
2158
|
+
mutate this."""
|
1132
2159
|
return self._ancillas
|
1133
2160
|
|
2161
|
+
@property
|
2162
|
+
def num_vars(self) -> int:
|
2163
|
+
"""The number of real-time classical variables in the circuit.
|
2164
|
+
|
2165
|
+
This is the length of the :meth:`iter_vars` iterable."""
|
2166
|
+
return self.num_input_vars + self.num_captured_vars + self.num_declared_vars
|
2167
|
+
|
2168
|
+
@property
|
2169
|
+
def num_input_vars(self) -> int:
|
2170
|
+
"""The number of real-time classical variables in the circuit marked as circuit inputs.
|
2171
|
+
|
2172
|
+
This is the length of the :meth:`iter_input_vars` iterable. If this is non-zero,
|
2173
|
+
:attr:`num_captured_vars` must be zero."""
|
2174
|
+
return len(self._vars_input)
|
2175
|
+
|
2176
|
+
@property
|
2177
|
+
def num_captured_vars(self) -> int:
|
2178
|
+
"""The number of real-time classical variables in the circuit marked as captured from an
|
2179
|
+
enclosing scope.
|
2180
|
+
|
2181
|
+
This is the length of the :meth:`iter_captured_vars` iterable. If this is non-zero,
|
2182
|
+
:attr:`num_input_vars` must be zero."""
|
2183
|
+
return len(self._vars_capture)
|
2184
|
+
|
2185
|
+
@property
|
2186
|
+
def num_declared_vars(self) -> int:
|
2187
|
+
"""The number of real-time classical variables in the circuit that are declared by this
|
2188
|
+
circuit scope, excluding inputs or captures.
|
2189
|
+
|
2190
|
+
This is the length of the :meth:`iter_declared_vars` iterable."""
|
2191
|
+
return len(self._vars_local)
|
2192
|
+
|
2193
|
+
def iter_vars(self) -> typing.Iterable[expr.Var]:
|
2194
|
+
"""Get an iterable over all real-time classical variables in scope within this circuit.
|
2195
|
+
|
2196
|
+
This method will iterate over all variables in scope. For more fine-grained iterators, see
|
2197
|
+
:meth:`iter_declared_vars`, :meth:`iter_input_vars` and :meth:`iter_captured_vars`."""
|
2198
|
+
if self._control_flow_scopes:
|
2199
|
+
builder = self._control_flow_scopes[-1]
|
2200
|
+
return itertools.chain(builder.iter_captured_vars(), builder.iter_local_vars())
|
2201
|
+
return itertools.chain(
|
2202
|
+
self._vars_input.values(), self._vars_capture.values(), self._vars_local.values()
|
2203
|
+
)
|
2204
|
+
|
2205
|
+
def iter_declared_vars(self) -> typing.Iterable[expr.Var]:
|
2206
|
+
"""Get an iterable over all real-time classical variables that are declared with automatic
|
2207
|
+
storage duration in this scope. This excludes input variables (see :meth:`iter_input_vars`)
|
2208
|
+
and captured variables (see :meth:`iter_captured_vars`)."""
|
2209
|
+
if self._control_flow_scopes:
|
2210
|
+
return self._control_flow_scopes[-1].iter_local_vars()
|
2211
|
+
return self._vars_local.values()
|
2212
|
+
|
2213
|
+
def iter_input_vars(self) -> typing.Iterable[expr.Var]:
|
2214
|
+
"""Get an iterable over all real-time classical variables that are declared as inputs to
|
2215
|
+
this circuit scope. This excludes locally declared variables (see
|
2216
|
+
:meth:`iter_declared_vars`) and captured variables (see :meth:`iter_captured_vars`)."""
|
2217
|
+
if self._control_flow_scopes:
|
2218
|
+
return ()
|
2219
|
+
return self._vars_input.values()
|
2220
|
+
|
2221
|
+
def iter_captured_vars(self) -> typing.Iterable[expr.Var]:
|
2222
|
+
"""Get an iterable over all real-time classical variables that are captured by this circuit
|
2223
|
+
scope from a containing scope. This excludes input variables (see :meth:`iter_input_vars`)
|
2224
|
+
and locally declared variables (see :meth:`iter_declared_vars`)."""
|
2225
|
+
if self._control_flow_scopes:
|
2226
|
+
return self._control_flow_scopes[-1].iter_captured_vars()
|
2227
|
+
return self._vars_capture.values()
|
2228
|
+
|
1134
2229
|
def __and__(self, rhs: "QuantumCircuit") -> "QuantumCircuit":
|
1135
2230
|
"""Overload & to implement self.compose."""
|
1136
2231
|
return self.compose(rhs)
|
@@ -1206,6 +2301,8 @@ class QuantumCircuit:
|
|
1206
2301
|
instruction: Operation | CircuitInstruction,
|
1207
2302
|
qargs: Sequence[QubitSpecifier] | None = None,
|
1208
2303
|
cargs: Sequence[ClbitSpecifier] | None = None,
|
2304
|
+
*,
|
2305
|
+
copy: bool = True,
|
1209
2306
|
) -> InstructionSet:
|
1210
2307
|
"""Append one or more instructions to the end of the circuit, modifying the circuit in
|
1211
2308
|
place.
|
@@ -1223,6 +2320,11 @@ class QuantumCircuit:
|
|
1223
2320
|
:class:`.CircuitInstruction` with all its context.
|
1224
2321
|
qargs: specifiers of the :class:`~.circuit.Qubit`\\ s to attach instruction to.
|
1225
2322
|
cargs: specifiers of the :class:`.Clbit`\\ s to attach instruction to.
|
2323
|
+
copy: if ``True`` (the default), then the incoming ``instruction`` is copied before
|
2324
|
+
adding it to the circuit if it contains symbolic parameters, so it can be safely
|
2325
|
+
mutated without affecting other circuits the same instruction might be in. If you
|
2326
|
+
are sure this instruction will not be in other circuits, you can set this ``False``
|
2327
|
+
for a small speedup.
|
1226
2328
|
|
1227
2329
|
Returns:
|
1228
2330
|
qiskit.circuit.InstructionSet: a handle to the :class:`.CircuitInstruction`\\ s that
|
@@ -1261,11 +2363,25 @@ class QuantumCircuit:
|
|
1261
2363
|
if params := getattr(operation, "params", ()):
|
1262
2364
|
is_parameter = False
|
1263
2365
|
for param in params:
|
1264
|
-
is_parameter = is_parameter or isinstance(param,
|
2366
|
+
is_parameter = is_parameter or isinstance(param, ParameterExpression)
|
1265
2367
|
if isinstance(param, expr.Expr):
|
1266
2368
|
param = _validate_expr(circuit_scope, param)
|
1267
|
-
if is_parameter:
|
1268
|
-
operation =
|
2369
|
+
if copy and is_parameter:
|
2370
|
+
operation = _copy.deepcopy(operation)
|
2371
|
+
if isinstance(operation, ControlFlowOp):
|
2372
|
+
# Verify that any variable bindings are valid. Control-flow ops are already enforced
|
2373
|
+
# by the class not to contain 'input' variables.
|
2374
|
+
if bad_captures := {
|
2375
|
+
var
|
2376
|
+
for var in itertools.chain.from_iterable(
|
2377
|
+
block.iter_captured_vars() for block in operation.blocks
|
2378
|
+
)
|
2379
|
+
if not self.has_var(var)
|
2380
|
+
}:
|
2381
|
+
raise CircuitError(
|
2382
|
+
f"Control-flow op attempts to capture '{bad_captures}'"
|
2383
|
+
" which are not in this circuit"
|
2384
|
+
)
|
1269
2385
|
|
1270
2386
|
expanded_qargs = [self.qbit_argument_conversion(qarg) for qarg in qargs or []]
|
1271
2387
|
expanded_cargs = [self.cbit_argument_conversion(carg) for carg in cargs or []]
|
@@ -1286,33 +2402,31 @@ class QuantumCircuit:
|
|
1286
2402
|
|
1287
2403
|
# Preferred new style.
|
1288
2404
|
@typing.overload
|
1289
|
-
def _append(
|
1290
|
-
self, instruction: CircuitInstruction, _qargs: None = None, _cargs: None = None
|
1291
|
-
) -> CircuitInstruction: ...
|
2405
|
+
def _append(self, instruction: CircuitInstruction) -> CircuitInstruction: ...
|
1292
2406
|
|
1293
2407
|
# To-be-deprecated old style.
|
1294
2408
|
@typing.overload
|
1295
2409
|
def _append(
|
1296
2410
|
self,
|
1297
|
-
|
2411
|
+
instruction: Operation,
|
1298
2412
|
qargs: Sequence[Qubit],
|
1299
2413
|
cargs: Sequence[Clbit],
|
1300
2414
|
) -> Operation: ...
|
1301
2415
|
|
1302
|
-
def _append(
|
1303
|
-
self,
|
1304
|
-
instruction: CircuitInstruction | Instruction,
|
1305
|
-
qargs: Sequence[Qubit] | None = None,
|
1306
|
-
cargs: Sequence[Clbit] | None = None,
|
1307
|
-
):
|
2416
|
+
def _append(self, instruction, qargs=(), cargs=()):
|
1308
2417
|
"""Append an instruction to the end of the circuit, modifying the circuit in place.
|
1309
2418
|
|
1310
2419
|
.. warning::
|
1311
2420
|
|
1312
2421
|
This is an internal fast-path function, and it is the responsibility of the caller to
|
1313
2422
|
ensure that all the arguments are valid; there is no error checking here. In
|
1314
|
-
particular
|
1315
|
-
|
2423
|
+
particular:
|
2424
|
+
|
2425
|
+
* all the qubits and clbits must already exist in the circuit and there can be no
|
2426
|
+
duplicates in the list.
|
2427
|
+
* any control-flow operations or classically conditioned instructions must act only on
|
2428
|
+
variables present in the circuit.
|
2429
|
+
* the circuit must not be within a control-flow builder context.
|
1316
2430
|
|
1317
2431
|
.. note::
|
1318
2432
|
|
@@ -1325,12 +2439,18 @@ class QuantumCircuit:
|
|
1325
2439
|
constructs of the control-flow builder interface.
|
1326
2440
|
|
1327
2441
|
Args:
|
1328
|
-
instruction:
|
1329
|
-
|
1330
|
-
|
2442
|
+
instruction: A complete well-formed :class:`.CircuitInstruction` of the operation and
|
2443
|
+
its context to be added.
|
2444
|
+
|
2445
|
+
In the legacy compatibility form, this can be a bare :class:`.Operation`, in which
|
2446
|
+
case ``qargs`` and ``cargs`` must be explicitly given.
|
2447
|
+
qargs: Legacy argument for qubits to attach the bare :class:`.Operation` to. Ignored if
|
2448
|
+
the first argument is in the preferential :class:`.CircuitInstruction` form.
|
2449
|
+
cargs: Legacy argument for clbits to attach the bare :class:`.Operation` to. Ignored if
|
2450
|
+
the first argument is in the preferential :class:`.CircuitInstruction` form.
|
1331
2451
|
|
1332
2452
|
Returns:
|
1333
|
-
|
2453
|
+
CircuitInstruction: a handle to the instruction that was just added.
|
1334
2454
|
|
1335
2455
|
:meta public:
|
1336
2456
|
"""
|
@@ -1412,6 +2532,11 @@ class QuantumCircuit:
|
|
1412
2532
|
|
1413
2533
|
assert qc.get_parameter("my_param", None) is my_param
|
1414
2534
|
assert qc.get_parameter("unknown_param", None) is None
|
2535
|
+
|
2536
|
+
See also:
|
2537
|
+
:meth:`get_var`
|
2538
|
+
A similar method, but for :class:`.expr.Var` run-time variables instead of
|
2539
|
+
:class:`.Parameter` compile-time parameters.
|
1415
2540
|
"""
|
1416
2541
|
if (parameter := self._parameter_table.parameter_from_name(name, None)) is None:
|
1417
2542
|
if default is Ellipsis:
|
@@ -1433,11 +2558,314 @@ class QuantumCircuit:
|
|
1433
2558
|
See also:
|
1434
2559
|
:meth:`QuantumCircuit.get_parameter`
|
1435
2560
|
Retrieve the :class:`.Parameter` instance from this circuit by name.
|
2561
|
+
:meth:`QuantumCircuit.has_var`
|
2562
|
+
A similar method to this, but for run-time :class:`.expr.Var` variables instead of
|
2563
|
+
compile-time :class:`.Parameter`\\ s.
|
1436
2564
|
"""
|
1437
2565
|
if isinstance(name_or_param, str):
|
1438
2566
|
return self.get_parameter(name_or_param, None) is not None
|
1439
2567
|
return self.get_parameter(name_or_param.name) == name_or_param
|
1440
2568
|
|
2569
|
+
@typing.overload
|
2570
|
+
def get_var(self, name: str, default: T) -> Union[expr.Var, T]: ...
|
2571
|
+
|
2572
|
+
# The builtin `types` module has `EllipsisType`, but only from 3.10+!
|
2573
|
+
@typing.overload
|
2574
|
+
def get_var(self, name: str, default: type(...) = ...) -> expr.Var: ...
|
2575
|
+
|
2576
|
+
# We use a _literal_ `Ellipsis` as the marker value to leave `None` available as a default.
|
2577
|
+
def get_var(self, name: str, default: typing.Any = ...):
|
2578
|
+
"""Retrieve a variable that is accessible in this circuit scope by name.
|
2579
|
+
|
2580
|
+
Args:
|
2581
|
+
name: the name of the variable to retrieve.
|
2582
|
+
default: if given, this value will be returned if the variable is not present. If it
|
2583
|
+
is not given, a :exc:`KeyError` is raised instead.
|
2584
|
+
|
2585
|
+
Returns:
|
2586
|
+
The corresponding variable.
|
2587
|
+
|
2588
|
+
Raises:
|
2589
|
+
KeyError: if no default is given, but the variable does not exist.
|
2590
|
+
|
2591
|
+
Examples:
|
2592
|
+
Retrieve a variable by name from a circuit::
|
2593
|
+
|
2594
|
+
from qiskit.circuit import QuantumCircuit
|
2595
|
+
|
2596
|
+
# Create a circuit and create a variable in it.
|
2597
|
+
qc = QuantumCircuit()
|
2598
|
+
my_var = qc.add_var("my_var", False)
|
2599
|
+
|
2600
|
+
# We can use 'my_var' as a variable, but let's say we've lost the Python object and
|
2601
|
+
# need to retrieve it.
|
2602
|
+
my_var_again = qc.get_var("my_var")
|
2603
|
+
|
2604
|
+
assert my_var is my_var_again
|
2605
|
+
|
2606
|
+
Get a variable from a circuit by name, returning some default if it is not present::
|
2607
|
+
|
2608
|
+
assert qc.get_var("my_var", None) is my_var
|
2609
|
+
assert qc.get_var("unknown_variable", None) is None
|
2610
|
+
|
2611
|
+
See also:
|
2612
|
+
:meth:`get_parameter`
|
2613
|
+
A similar method, but for :class:`.Parameter` compile-time parameters instead of
|
2614
|
+
:class:`.expr.Var` run-time variables.
|
2615
|
+
"""
|
2616
|
+
if (out := self._current_scope().get_var(name)) is not None:
|
2617
|
+
return out
|
2618
|
+
if default is Ellipsis:
|
2619
|
+
raise KeyError(f"no variable named '{name}' is present")
|
2620
|
+
return default
|
2621
|
+
|
2622
|
+
def has_var(self, name_or_var: str | expr.Var, /) -> bool:
|
2623
|
+
"""Check whether a variable is accessible in this scope.
|
2624
|
+
|
2625
|
+
Args:
|
2626
|
+
name_or_var: the variable, or name of a variable to check. If this is a
|
2627
|
+
:class:`.expr.Var` node, the variable must be exactly the given one for this
|
2628
|
+
function to return ``True``.
|
2629
|
+
|
2630
|
+
Returns:
|
2631
|
+
whether a matching variable is accessible.
|
2632
|
+
|
2633
|
+
See also:
|
2634
|
+
:meth:`QuantumCircuit.get_var`
|
2635
|
+
Retrieve the :class:`.expr.Var` instance from this circuit by name.
|
2636
|
+
:meth:`QuantumCircuit.has_parameter`
|
2637
|
+
A similar method to this, but for compile-time :class:`.Parameter`\\ s instead of
|
2638
|
+
run-time :class:`.expr.Var` variables.
|
2639
|
+
"""
|
2640
|
+
if isinstance(name_or_var, str):
|
2641
|
+
return self.get_var(name_or_var, None) is not None
|
2642
|
+
return self.get_var(name_or_var.name, None) == name_or_var
|
2643
|
+
|
2644
|
+
def _prepare_new_var(
|
2645
|
+
self, name_or_var: str | expr.Var, type_: types.Type | None, /
|
2646
|
+
) -> expr.Var:
|
2647
|
+
"""The common logic for preparing and validating a new :class:`~.expr.Var` for the circuit.
|
2648
|
+
|
2649
|
+
The given ``type_`` can be ``None`` if the variable specifier is already a :class:`.Var`,
|
2650
|
+
and must be a :class:`~.types.Type` if it is a string. The argument is ignored if the given
|
2651
|
+
first argument is a :class:`.Var` already.
|
2652
|
+
|
2653
|
+
Returns the validated variable, which is guaranteed to be safe to add to the circuit."""
|
2654
|
+
if isinstance(name_or_var, str):
|
2655
|
+
if type_ is None:
|
2656
|
+
raise CircuitError("the type must be known when creating a 'Var' from a string")
|
2657
|
+
var = expr.Var.new(name_or_var, type_)
|
2658
|
+
else:
|
2659
|
+
var = name_or_var
|
2660
|
+
if not var.standalone:
|
2661
|
+
raise CircuitError(
|
2662
|
+
"cannot add variables that wrap `Clbit` or `ClassicalRegister` instances."
|
2663
|
+
" Use `add_bits` or `add_register` as appropriate."
|
2664
|
+
)
|
2665
|
+
|
2666
|
+
# The `var` is guaranteed to have a name because we already excluded the cases where it's
|
2667
|
+
# wrapping a bit/register.
|
2668
|
+
if (previous := self.get_var(var.name, default=None)) is not None:
|
2669
|
+
if previous == var:
|
2670
|
+
raise CircuitError(f"'{var}' is already present in the circuit")
|
2671
|
+
raise CircuitError(f"cannot add '{var}' as its name shadows the existing '{previous}'")
|
2672
|
+
return var
|
2673
|
+
|
2674
|
+
def add_var(self, name_or_var: str | expr.Var, /, initial: typing.Any) -> expr.Var:
|
2675
|
+
"""Add a classical variable with automatic storage and scope to this circuit.
|
2676
|
+
|
2677
|
+
The variable is considered to have been "declared" at the beginning of the circuit, but it
|
2678
|
+
only becomes initialized at the point of the circuit that you call this method, so it can
|
2679
|
+
depend on variables defined before it.
|
2680
|
+
|
2681
|
+
Args:
|
2682
|
+
name_or_var: either a string of the variable name, or an existing instance of
|
2683
|
+
:class:`~.expr.Var` to re-use. Variables cannot shadow names that are already in
|
2684
|
+
use within the circuit.
|
2685
|
+
initial: the value to initialize this variable with. If the first argument was given
|
2686
|
+
as a string name, the type of the resulting variable is inferred from the initial
|
2687
|
+
expression; to control this more manually, either use :meth:`.Var.new` to manually
|
2688
|
+
construct a new variable with the desired type, or use :func:`.expr.cast` to cast
|
2689
|
+
the initializer to the desired type.
|
2690
|
+
|
2691
|
+
This must be either a :class:`~.expr.Expr` node, or a value that can be lifted to
|
2692
|
+
one using :class:`.expr.lift`.
|
2693
|
+
|
2694
|
+
Returns:
|
2695
|
+
The created variable. If a :class:`~.expr.Var` instance was given, the exact same
|
2696
|
+
object will be returned.
|
2697
|
+
|
2698
|
+
Raises:
|
2699
|
+
CircuitError: if the variable cannot be created due to shadowing an existing variable.
|
2700
|
+
|
2701
|
+
Examples:
|
2702
|
+
Define a new variable given just a name and an initializer expression::
|
2703
|
+
|
2704
|
+
from qiskit.circuit import QuantumCircuit
|
2705
|
+
|
2706
|
+
qc = QuantumCircuit(2)
|
2707
|
+
my_var = qc.add_var("my_var", False)
|
2708
|
+
|
2709
|
+
Reuse a variable that may have been taken from a related circuit, or otherwise
|
2710
|
+
constructed manually, and initialize it to some more complicated expression::
|
2711
|
+
|
2712
|
+
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
|
2713
|
+
from qiskit.circuit.classical import expr, types
|
2714
|
+
|
2715
|
+
my_var = expr.Var.new("my_var", types.Uint(8))
|
2716
|
+
|
2717
|
+
cr1 = ClassicalRegister(8, "cr1")
|
2718
|
+
cr2 = ClassicalRegister(8, "cr2")
|
2719
|
+
qc = QuantumCircuit(QuantumRegister(8), cr1, cr2)
|
2720
|
+
|
2721
|
+
# Get some measurement results into each register.
|
2722
|
+
qc.h(0)
|
2723
|
+
for i in range(1, 8):
|
2724
|
+
qc.cx(0, i)
|
2725
|
+
qc.measure(range(8), cr1)
|
2726
|
+
|
2727
|
+
qc.reset(range(8))
|
2728
|
+
qc.h(0)
|
2729
|
+
for i in range(1, 8):
|
2730
|
+
qc.cx(0, i)
|
2731
|
+
qc.measure(range(8), cr2)
|
2732
|
+
|
2733
|
+
# Now when we add the variable, it is initialized using the real-time state of the
|
2734
|
+
# two classical registers we measured into above.
|
2735
|
+
qc.add_var(my_var, expr.bit_and(cr1, cr2))
|
2736
|
+
"""
|
2737
|
+
# Validate the initialiser first to catch cases where the variable to be declared is being
|
2738
|
+
# used in the initialiser.
|
2739
|
+
circuit_scope = self._current_scope()
|
2740
|
+
# Convenience method to widen Python integer literals to the right width during the initial
|
2741
|
+
# lift, if the type is already known via the variable.
|
2742
|
+
if (
|
2743
|
+
isinstance(name_or_var, expr.Var)
|
2744
|
+
and name_or_var.type.kind is types.Uint
|
2745
|
+
and isinstance(initial, int)
|
2746
|
+
and not isinstance(initial, bool)
|
2747
|
+
):
|
2748
|
+
coerce_type = name_or_var.type
|
2749
|
+
else:
|
2750
|
+
coerce_type = None
|
2751
|
+
initial = _validate_expr(circuit_scope, expr.lift(initial, coerce_type))
|
2752
|
+
if isinstance(name_or_var, str):
|
2753
|
+
var = expr.Var.new(name_or_var, initial.type)
|
2754
|
+
elif not name_or_var.standalone:
|
2755
|
+
raise CircuitError(
|
2756
|
+
"cannot add variables that wrap `Clbit` or `ClassicalRegister` instances."
|
2757
|
+
)
|
2758
|
+
else:
|
2759
|
+
var = name_or_var
|
2760
|
+
circuit_scope.add_uninitialized_var(var)
|
2761
|
+
try:
|
2762
|
+
# Store is responsible for ensuring the type safety of the initialisation.
|
2763
|
+
store = Store(var, initial)
|
2764
|
+
except CircuitError:
|
2765
|
+
circuit_scope.remove_var(var)
|
2766
|
+
raise
|
2767
|
+
circuit_scope.append(CircuitInstruction(store, (), ()))
|
2768
|
+
return var
|
2769
|
+
|
2770
|
+
def add_uninitialized_var(self, var: expr.Var, /):
|
2771
|
+
"""Add a variable with no initializer.
|
2772
|
+
|
2773
|
+
In most cases, you should use :meth:`add_var` to initialize the variable. To use this
|
2774
|
+
function, you must already hold a :class:`~.expr.Var` instance, as the use of the function
|
2775
|
+
typically only makes sense in copying contexts.
|
2776
|
+
|
2777
|
+
.. warning::
|
2778
|
+
|
2779
|
+
Qiskit makes no assertions about what an uninitialized variable will evaluate to at
|
2780
|
+
runtime, and some hardware may reject this as an error.
|
2781
|
+
|
2782
|
+
You should treat this function with caution, and as a low-level primitive that is useful
|
2783
|
+
only in special cases of programmatically rebuilding two like circuits.
|
2784
|
+
|
2785
|
+
Args:
|
2786
|
+
var: the variable to add.
|
2787
|
+
"""
|
2788
|
+
# This function is deliberately meant to be a bit harder to find, to have a long descriptive
|
2789
|
+
# name, and to be a bit less ergonomic than `add_var` (i.e. not allowing the (name, type)
|
2790
|
+
# overload) to discourage people from using it when they should use `add_var`.
|
2791
|
+
#
|
2792
|
+
# This function exists so that there is a method to emulate `copy_empty_like`'s behaviour of
|
2793
|
+
# adding uninitialised variables, which there's no obvious way around. We need to be sure
|
2794
|
+
# that _some_ sort of handling of uninitialised variables is taken into account in our
|
2795
|
+
# structures, so that doesn't become a huge edge case, even though we make no assertions
|
2796
|
+
# about the _meaning_ if such an expression was run on hardware.
|
2797
|
+
if self._control_flow_scopes:
|
2798
|
+
raise CircuitError("cannot add an uninitialized variable in a control-flow scope")
|
2799
|
+
if not var.standalone:
|
2800
|
+
raise CircuitError("cannot add a variable wrapping a bit or register to a circuit")
|
2801
|
+
self._builder_api.add_uninitialized_var(var)
|
2802
|
+
|
2803
|
+
def add_capture(self, var: expr.Var):
|
2804
|
+
"""Add a variable to the circuit that it should capture from a scope it will be contained
|
2805
|
+
within.
|
2806
|
+
|
2807
|
+
This method requires a :class:`~.expr.Var` node to enforce that you've got a handle to one,
|
2808
|
+
because you will need to declare the same variable using the same object into the outer
|
2809
|
+
circuit.
|
2810
|
+
|
2811
|
+
This is a low-level method, which is only really useful if you are manually constructing
|
2812
|
+
control-flow operations. You typically will not need to call this method, assuming you
|
2813
|
+
are using the builder interface for control-flow scopes (``with`` context-manager statements
|
2814
|
+
for :meth:`if_test` and the other scoping constructs). The builder interface will
|
2815
|
+
automatically make the inner scopes closures on your behalf by capturing any variables that
|
2816
|
+
are used within them.
|
2817
|
+
|
2818
|
+
Args:
|
2819
|
+
var: the variable to capture from an enclosing scope.
|
2820
|
+
|
2821
|
+
Raises:
|
2822
|
+
CircuitError: if the variable cannot be created due to shadowing an existing variable.
|
2823
|
+
"""
|
2824
|
+
if self._control_flow_scopes:
|
2825
|
+
# Allow manual capturing. Not sure why it'd be useful, but there's a clear expected
|
2826
|
+
# behaviour here.
|
2827
|
+
self._control_flow_scopes[-1].use_var(var)
|
2828
|
+
return
|
2829
|
+
if self._vars_input:
|
2830
|
+
raise CircuitError(
|
2831
|
+
"circuits with input variables cannot be enclosed, so cannot be closures"
|
2832
|
+
)
|
2833
|
+
self._vars_capture[var.name] = self._prepare_new_var(var, None)
|
2834
|
+
|
2835
|
+
@typing.overload
|
2836
|
+
def add_input(self, name_or_var: str, type_: types.Type, /) -> expr.Var: ...
|
2837
|
+
|
2838
|
+
@typing.overload
|
2839
|
+
def add_input(self, name_or_var: expr.Var, type_: None = None, /) -> expr.Var: ...
|
2840
|
+
|
2841
|
+
def add_input( # pylint: disable=missing-raises-doc
|
2842
|
+
self, name_or_var: str | expr.Var, type_: types.Type | None = None, /
|
2843
|
+
) -> expr.Var:
|
2844
|
+
"""Register a variable as an input to the circuit.
|
2845
|
+
|
2846
|
+
Args:
|
2847
|
+
name_or_var: either a string name, or an existing :class:`~.expr.Var` node to use as the
|
2848
|
+
input variable.
|
2849
|
+
type_: if the name is given as a string, then this must be a :class:`~.types.Type` to
|
2850
|
+
use for the variable. If the variable is given as an existing :class:`~.expr.Var`,
|
2851
|
+
then this must not be given, and will instead be read from the object itself.
|
2852
|
+
|
2853
|
+
Returns:
|
2854
|
+
the variable created, or the same variable as was passed in.
|
2855
|
+
|
2856
|
+
Raises:
|
2857
|
+
CircuitError: if the variable cannot be created due to shadowing an existing variable.
|
2858
|
+
"""
|
2859
|
+
if self._control_flow_scopes:
|
2860
|
+
raise CircuitError("cannot add an input variable in a control-flow scope")
|
2861
|
+
if self._vars_capture:
|
2862
|
+
raise CircuitError("circuits to be enclosed with captures cannot have input variables")
|
2863
|
+
if isinstance(name_or_var, expr.Var) and type_ is not None:
|
2864
|
+
raise ValueError("cannot give an explicit type with an existing Var")
|
2865
|
+
var = self._prepare_new_var(name_or_var, type_)
|
2866
|
+
self._vars_input[var.name] = var
|
2867
|
+
return var
|
2868
|
+
|
1441
2869
|
def add_register(self, *regs: Register | int | Sequence[Bit]) -> None:
|
1442
2870
|
"""Add registers."""
|
1443
2871
|
if not regs:
|
@@ -1535,24 +2963,52 @@ class QuantumCircuit:
|
|
1535
2963
|
def find_bit(self, bit: Bit) -> BitLocations:
|
1536
2964
|
"""Find locations in the circuit which can be used to reference a given :obj:`~Bit`.
|
1537
2965
|
|
2966
|
+
In particular, this function can find the integer index of a qubit, which corresponds to its
|
2967
|
+
hardware index for a transpiled circuit.
|
2968
|
+
|
2969
|
+
.. note::
|
2970
|
+
The circuit index of a :class:`.AncillaQubit` will be its index in :attr:`qubits`, not
|
2971
|
+
:attr:`ancillas`.
|
2972
|
+
|
1538
2973
|
Args:
|
1539
2974
|
bit (Bit): The bit to locate.
|
1540
2975
|
|
1541
2976
|
Returns:
|
1542
2977
|
namedtuple(int, List[Tuple(Register, int)]): A 2-tuple. The first element (``index``)
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
Notes:
|
1550
|
-
The circuit index of an :obj:`~AncillaQubit` will be its index in
|
1551
|
-
:obj:`~QuantumCircuit.qubits`, not :obj:`~QuantumCircuit.ancillas`.
|
2978
|
+
contains the index at which the ``Bit`` can be found (in either
|
2979
|
+
:obj:`~QuantumCircuit.qubits`, :obj:`~QuantumCircuit.clbits`, depending on its
|
2980
|
+
type). The second element (``registers``) is a list of ``(register, index)``
|
2981
|
+
pairs with an entry for each :obj:`~Register` in the circuit which contains the
|
2982
|
+
:obj:`~Bit` (and the index in the :obj:`~Register` at which it can be found).
|
1552
2983
|
|
1553
2984
|
Raises:
|
1554
2985
|
CircuitError: If the supplied :obj:`~Bit` was of an unknown type.
|
1555
2986
|
CircuitError: If the supplied :obj:`~Bit` could not be found on the circuit.
|
2987
|
+
|
2988
|
+
Examples:
|
2989
|
+
Loop through a circuit, getting the qubit and clbit indices of each operation::
|
2990
|
+
|
2991
|
+
from qiskit.circuit import QuantumCircuit, Qubit
|
2992
|
+
|
2993
|
+
qc = QuantumCircuit(3, 3)
|
2994
|
+
qc.h(0)
|
2995
|
+
qc.cx(0, 1)
|
2996
|
+
qc.cx(1, 2)
|
2997
|
+
qc.measure([0, 1, 2], [0, 1, 2])
|
2998
|
+
|
2999
|
+
# The `.qubits` and `.clbits` fields are not integers.
|
3000
|
+
assert isinstance(qc.data[0].qubits[0], Qubit)
|
3001
|
+
# ... but we can use `find_bit` to retrieve them.
|
3002
|
+
assert qc.find_bit(qc.data[0].qubits[0]).index == 0
|
3003
|
+
|
3004
|
+
simple = [
|
3005
|
+
(
|
3006
|
+
instruction.operation.name,
|
3007
|
+
[qc.find_bit(bit).index for bit in instruction.qubits],
|
3008
|
+
[qc.find_bit(bit).index for bit in instruction.clbits],
|
3009
|
+
)
|
3010
|
+
for instruction in qc.data
|
3011
|
+
]
|
1556
3012
|
"""
|
1557
3013
|
|
1558
3014
|
try:
|
@@ -1578,18 +3034,22 @@ class QuantumCircuit:
|
|
1578
3034
|
parameter_map: dict[Parameter, ParameterValueType] | None = None,
|
1579
3035
|
label: str | None = None,
|
1580
3036
|
) -> Instruction:
|
1581
|
-
"""Create an Instruction out of this circuit.
|
3037
|
+
"""Create an :class:`~.circuit.Instruction` out of this circuit.
|
3038
|
+
|
3039
|
+
.. seealso::
|
3040
|
+
:func:`circuit_to_instruction`
|
3041
|
+
The underlying driver of this method.
|
1582
3042
|
|
1583
3043
|
Args:
|
1584
|
-
parameter_map
|
3044
|
+
parameter_map: For parameterized circuits, a mapping from
|
1585
3045
|
parameters in the circuit to parameters to be used in the
|
1586
3046
|
instruction. If None, existing circuit parameters will also
|
1587
3047
|
parameterize the instruction.
|
1588
|
-
label
|
3048
|
+
label: Optional gate label.
|
1589
3049
|
|
1590
3050
|
Returns:
|
1591
|
-
qiskit.circuit.Instruction: a composite instruction encapsulating this circuit
|
1592
|
-
|
3051
|
+
qiskit.circuit.Instruction: a composite instruction encapsulating this circuit (can be
|
3052
|
+
decomposed back).
|
1593
3053
|
"""
|
1594
3054
|
from qiskit.converters.circuit_to_instruction import circuit_to_instruction
|
1595
3055
|
|
@@ -1600,18 +3060,21 @@ class QuantumCircuit:
|
|
1600
3060
|
parameter_map: dict[Parameter, ParameterValueType] | None = None,
|
1601
3061
|
label: str | None = None,
|
1602
3062
|
) -> Gate:
|
1603
|
-
"""Create a Gate out of this circuit.
|
3063
|
+
"""Create a :class:`.Gate` out of this circuit. The circuit must act only qubits and
|
3064
|
+
contain only unitary operations.
|
3065
|
+
|
3066
|
+
.. seealso::
|
3067
|
+
:func:`circuit_to_gate`
|
3068
|
+
The underlying driver of this method.
|
1604
3069
|
|
1605
3070
|
Args:
|
1606
|
-
parameter_map
|
1607
|
-
|
1608
|
-
|
1609
|
-
|
1610
|
-
label (str): Optional gate label.
|
3071
|
+
parameter_map: For parameterized circuits, a mapping from parameters in the circuit to
|
3072
|
+
parameters to be used in the gate. If ``None``, existing circuit parameters will
|
3073
|
+
also parameterize the gate.
|
3074
|
+
label : Optional gate label.
|
1611
3075
|
|
1612
3076
|
Returns:
|
1613
|
-
Gate: a composite gate encapsulating this circuit
|
1614
|
-
(can be decomposed back)
|
3077
|
+
Gate: a composite gate encapsulating this circuit (can be decomposed back).
|
1615
3078
|
"""
|
1616
3079
|
from qiskit.converters.circuit_to_gate import circuit_to_gate
|
1617
3080
|
|
@@ -1838,25 +3301,36 @@ class QuantumCircuit:
|
|
1838
3301
|
|
1839
3302
|
def depth(
|
1840
3303
|
self,
|
1841
|
-
filter_function: Callable[
|
3304
|
+
filter_function: Callable[[CircuitInstruction], bool] = lambda x: not getattr(
|
1842
3305
|
x.operation, "_directive", False
|
1843
3306
|
),
|
1844
3307
|
) -> int:
|
1845
3308
|
"""Return circuit depth (i.e., length of critical path).
|
1846
3309
|
|
1847
3310
|
Args:
|
1848
|
-
filter_function
|
1849
|
-
Should take as
|
1850
|
-
Instructions for which the function returns False are ignored in the
|
1851
|
-
computation of the circuit depth.
|
1852
|
-
|
3311
|
+
filter_function: A function to decide which instructions count to increase depth.
|
3312
|
+
Should take as a single positional input a :class:`CircuitInstruction`.
|
3313
|
+
Instructions for which the function returns ``False`` are ignored in the
|
3314
|
+
computation of the circuit depth. By default filters out "directives", such as
|
3315
|
+
:class:`.Barrier`.
|
1853
3316
|
|
1854
3317
|
Returns:
|
1855
3318
|
int: Depth of circuit.
|
1856
3319
|
|
1857
|
-
|
1858
|
-
|
1859
|
-
|
3320
|
+
Examples:
|
3321
|
+
Simple calculation of total circuit depth::
|
3322
|
+
|
3323
|
+
from qiskit.circuit import QuantumCircuit
|
3324
|
+
qc = QuantumCircuit(4)
|
3325
|
+
qc.h(0)
|
3326
|
+
qc.cx(0, 1)
|
3327
|
+
qc.h(2)
|
3328
|
+
qc.cx(2, 3)
|
3329
|
+
assert qc.depth() == 2
|
3330
|
+
|
3331
|
+
Modifying the previous example to only calculate the depth of multi-qubit gates::
|
3332
|
+
|
3333
|
+
assert qc.depth(lambda instr: len(instr.qubits) > 1) == 1
|
1860
3334
|
"""
|
1861
3335
|
# Assign each bit in the circuit a unique integer
|
1862
3336
|
# to index into op_stack.
|
@@ -2064,7 +3538,7 @@ class QuantumCircuit:
|
|
2064
3538
|
"""
|
2065
3539
|
return self.num_unitary_factors()
|
2066
3540
|
|
2067
|
-
def copy(self, name: str | None = None) ->
|
3541
|
+
def copy(self, name: str | None = None) -> typing.Self:
|
2068
3542
|
"""Copy the circuit.
|
2069
3543
|
|
2070
3544
|
Args:
|
@@ -2100,16 +3574,47 @@ class QuantumCircuit:
|
|
2100
3574
|
)
|
2101
3575
|
return cpy
|
2102
3576
|
|
2103
|
-
def copy_empty_like(
|
3577
|
+
def copy_empty_like(
|
3578
|
+
self,
|
3579
|
+
name: str | None = None,
|
3580
|
+
*,
|
3581
|
+
vars_mode: Literal["alike", "captures", "drop"] = "alike",
|
3582
|
+
) -> typing.Self:
|
2104
3583
|
"""Return a copy of self with the same structure but empty.
|
2105
3584
|
|
2106
3585
|
That structure includes:
|
2107
|
-
|
2108
|
-
|
2109
|
-
|
3586
|
+
|
3587
|
+
* name, calibrations and other metadata
|
3588
|
+
* global phase
|
3589
|
+
* all the qubits and clbits, including the registers
|
3590
|
+
* the realtime variables defined in the circuit, handled according to the ``vars`` keyword
|
3591
|
+
argument.
|
3592
|
+
|
3593
|
+
.. warning::
|
3594
|
+
|
3595
|
+
If the circuit contains any local variable declarations (those added by the
|
3596
|
+
``declarations`` argument to the circuit constructor, or using :meth:`add_var`), they
|
3597
|
+
may be **uninitialized** in the output circuit. You will need to manually add store
|
3598
|
+
instructions for them (see :class:`.Store` and :meth:`.QuantumCircuit.store`) to
|
3599
|
+
initialize them.
|
2110
3600
|
|
2111
3601
|
Args:
|
2112
|
-
name
|
3602
|
+
name: Name for the copied circuit. If None, then the name stays the same.
|
3603
|
+
vars_mode: The mode to handle realtime variables in.
|
3604
|
+
|
3605
|
+
alike
|
3606
|
+
The variables in the output circuit will have the same declaration semantics as
|
3607
|
+
in the original circuit. For example, ``input`` variables in the source will be
|
3608
|
+
``input`` variables in the output circuit.
|
3609
|
+
|
3610
|
+
captures
|
3611
|
+
All variables will be converted to captured variables. This is useful when you
|
3612
|
+
are building a new layer for an existing circuit that you will want to
|
3613
|
+
:meth:`compose` onto the base, since :meth:`compose` can inline captures onto
|
3614
|
+
the base circuit (but not other variables).
|
3615
|
+
|
3616
|
+
drop
|
3617
|
+
The output circuit will have no variables defined.
|
2113
3618
|
|
2114
3619
|
Returns:
|
2115
3620
|
QuantumCircuit: An empty copy of self.
|
@@ -2118,7 +3623,7 @@ class QuantumCircuit:
|
|
2118
3623
|
raise TypeError(
|
2119
3624
|
f"invalid name for a circuit: '{name}'. The name must be a string or 'None'."
|
2120
3625
|
)
|
2121
|
-
cpy =
|
3626
|
+
cpy = _copy.copy(self)
|
2122
3627
|
# copy registers correctly, in copy.copy they are only copied via reference
|
2123
3628
|
cpy.qregs = self.qregs.copy()
|
2124
3629
|
cpy.cregs = self.cregs.copy()
|
@@ -2127,6 +3632,24 @@ class QuantumCircuit:
|
|
2127
3632
|
cpy._qubit_indices = self._qubit_indices.copy()
|
2128
3633
|
cpy._clbit_indices = self._clbit_indices.copy()
|
2129
3634
|
|
3635
|
+
if vars_mode == "alike":
|
3636
|
+
# Note that this causes the local variables to be uninitialised, because the stores are
|
3637
|
+
# not copied. This can leave the circuit in a potentially dangerous state for users if
|
3638
|
+
# they don't re-add initialiser stores.
|
3639
|
+
cpy._vars_local = self._vars_local.copy()
|
3640
|
+
cpy._vars_input = self._vars_input.copy()
|
3641
|
+
cpy._vars_capture = self._vars_capture.copy()
|
3642
|
+
elif vars_mode == "captures":
|
3643
|
+
cpy._vars_local = {}
|
3644
|
+
cpy._vars_input = {}
|
3645
|
+
cpy._vars_capture = {var.name: var for var in self.iter_vars()}
|
3646
|
+
elif vars_mode == "drop":
|
3647
|
+
cpy._vars_local = {}
|
3648
|
+
cpy._vars_input = {}
|
3649
|
+
cpy._vars_capture = {}
|
3650
|
+
else: # pragma: no cover
|
3651
|
+
raise ValueError(f"unknown vars_mode: '{vars_mode}'")
|
3652
|
+
|
2130
3653
|
cpy._parameter_table = ParameterTable()
|
2131
3654
|
for parameter in getattr(cpy.global_phase, "parameters", ()):
|
2132
3655
|
cpy._parameter_table[parameter] = ParameterReferences(
|
@@ -2134,8 +3657,8 @@ class QuantumCircuit:
|
|
2134
3657
|
)
|
2135
3658
|
cpy._data = CircuitData(self._data.qubits, self._data.clbits)
|
2136
3659
|
|
2137
|
-
cpy._calibrations =
|
2138
|
-
cpy._metadata =
|
3660
|
+
cpy._calibrations = _copy.deepcopy(self._calibrations)
|
3661
|
+
cpy._metadata = _copy.deepcopy(self._metadata)
|
2139
3662
|
|
2140
3663
|
if name:
|
2141
3664
|
cpy.name = name
|
@@ -2145,6 +3668,11 @@ class QuantumCircuit:
|
|
2145
3668
|
"""Clear all instructions in self.
|
2146
3669
|
|
2147
3670
|
Clearing the circuits will keep the metadata and calibrations.
|
3671
|
+
|
3672
|
+
.. seealso::
|
3673
|
+
:meth:`copy_empty_like`
|
3674
|
+
A method to produce a new circuit with no instructions and all the same tracking of
|
3675
|
+
quantum and classical typed data, but without mutating the original circuit.
|
2148
3676
|
"""
|
2149
3677
|
self._data.clear()
|
2150
3678
|
self._parameter_table.clear()
|
@@ -2184,7 +3712,38 @@ class QuantumCircuit:
|
|
2184
3712
|
"""
|
2185
3713
|
from .reset import Reset
|
2186
3714
|
|
2187
|
-
return self.append(Reset(), [qubit], [])
|
3715
|
+
return self.append(Reset(), [qubit], [], copy=False)
|
3716
|
+
|
3717
|
+
def store(self, lvalue: typing.Any, rvalue: typing.Any, /) -> InstructionSet:
|
3718
|
+
"""Store the result of the given real-time classical expression ``rvalue`` in the memory
|
3719
|
+
location defined by ``lvalue``.
|
3720
|
+
|
3721
|
+
Typically ``lvalue`` will be a :class:`~.expr.Var` node and ``rvalue`` will be some
|
3722
|
+
:class:`~.expr.Expr` to write into it, but anything that :func:`.expr.lift` can raise to an
|
3723
|
+
:class:`~.expr.Expr` is permissible in both places, and it will be called on them.
|
3724
|
+
|
3725
|
+
Args:
|
3726
|
+
lvalue: a valid specifier for a memory location in the circuit. This will typically be
|
3727
|
+
a :class:`~.expr.Var` node, but you can also write to :class:`.Clbit` or
|
3728
|
+
:class:`.ClassicalRegister` memory locations if your hardware supports it. The
|
3729
|
+
memory location must already be present in the circuit.
|
3730
|
+
rvalue: a real-time classical expression whose result should be written into the given
|
3731
|
+
memory location.
|
3732
|
+
|
3733
|
+
.. seealso::
|
3734
|
+
:class:`~.circuit.Store`
|
3735
|
+
The backing :class:`~.circuit.Instruction` class that represents this operation.
|
3736
|
+
|
3737
|
+
:meth:`add_var`
|
3738
|
+
Create a new variable in the circuit that can be written to with this method.
|
3739
|
+
"""
|
3740
|
+
# As a convenience, lift integer-literal rvalues to the matching width.
|
3741
|
+
lvalue = expr.lift(lvalue)
|
3742
|
+
rvalue_type = (
|
3743
|
+
lvalue.type if isinstance(rvalue, int) and not isinstance(rvalue, bool) else None
|
3744
|
+
)
|
3745
|
+
rvalue = expr.lift(rvalue, rvalue_type)
|
3746
|
+
return self.append(Store(lvalue, rvalue), (), (), copy=False)
|
2188
3747
|
|
2189
3748
|
def measure(self, qubit: QubitSpecifier, cbit: ClbitSpecifier) -> InstructionSet:
|
2190
3749
|
r"""Measure a quantum bit (``qubit``) in the Z basis into a classical bit (``cbit``).
|
@@ -2261,7 +3820,7 @@ class QuantumCircuit:
|
|
2261
3820
|
"""
|
2262
3821
|
from .measure import Measure
|
2263
3822
|
|
2264
|
-
return self.append(Measure(), [qubit], [cbit])
|
3823
|
+
return self.append(Measure(), [qubit], [cbit], copy=False)
|
2265
3824
|
|
2266
3825
|
def measure_active(self, inplace: bool = True) -> Optional["QuantumCircuit"]:
|
2267
3826
|
"""Adds measurement to all non-idle qubits. Creates a new ClassicalRegister with
|
@@ -2348,6 +3907,28 @@ class QuantumCircuit:
|
|
2348
3907
|
Measurements and barriers are considered final if they are
|
2349
3908
|
followed by no other operations (aside from other measurements or barriers.)
|
2350
3909
|
|
3910
|
+
.. note::
|
3911
|
+
This method has rather complex behavior, particularly around the removal of newly idle
|
3912
|
+
classical bits and registers. It is much more efficient to avoid adding unnecessary
|
3913
|
+
classical data in the first place, rather than trying to remove it later.
|
3914
|
+
|
3915
|
+
.. seealso::
|
3916
|
+
:class:`.RemoveFinalMeasurements`
|
3917
|
+
A transpiler pass that removes final measurements and barriers. This does not
|
3918
|
+
remove the classical data. If this is your goal, you can call that with::
|
3919
|
+
|
3920
|
+
from qiskit.circuit import QuantumCircuit
|
3921
|
+
from qiskit.transpiler.passes import RemoveFinalMeasurements
|
3922
|
+
|
3923
|
+
qc = QuantumCircuit(2, 2)
|
3924
|
+
qc.h(0)
|
3925
|
+
qc.cx(0, 1)
|
3926
|
+
qc.barrier()
|
3927
|
+
qc.measure([0, 1], [0, 1])
|
3928
|
+
|
3929
|
+
pass_ = RemoveFinalMeasurements()
|
3930
|
+
just_bell = pass_(qc)
|
3931
|
+
|
2351
3932
|
Args:
|
2352
3933
|
inplace (bool): All measurements removed inplace or return new circuit.
|
2353
3934
|
|
@@ -2451,7 +4032,7 @@ class QuantumCircuit:
|
|
2451
4032
|
|
2452
4033
|
@property
|
2453
4034
|
def global_phase(self) -> ParameterValueType:
|
2454
|
-
"""
|
4035
|
+
"""The global phase of the current circuit scope in radians."""
|
2455
4036
|
if self._control_flow_scopes:
|
2456
4037
|
return self._control_flow_scopes[-1].global_phase
|
2457
4038
|
return self._global_phase
|
@@ -2837,7 +4418,9 @@ class QuantumCircuit:
|
|
2837
4418
|
if qargs:
|
2838
4419
|
# This uses a `dict` not a `set` to guarantee a deterministic order to the arguments.
|
2839
4420
|
qubits = tuple({q: None for qarg in qargs for q in self.qbit_argument_conversion(qarg)})
|
2840
|
-
return self.append(
|
4421
|
+
return self.append(
|
4422
|
+
CircuitInstruction(Barrier(len(qubits), label=label), qubits, ()), copy=False
|
4423
|
+
)
|
2841
4424
|
else:
|
2842
4425
|
qubits = self.qubits.copy()
|
2843
4426
|
return self._current_scope().append(
|
@@ -2868,7 +4451,7 @@ class QuantumCircuit:
|
|
2868
4451
|
"""
|
2869
4452
|
if qarg is None:
|
2870
4453
|
qarg = self.qubits
|
2871
|
-
return self.append(Delay(duration, unit=unit), [qarg], [])
|
4454
|
+
return self.append(Delay(duration, unit=unit), [qarg], [], copy=False)
|
2872
4455
|
|
2873
4456
|
def h(self, qubit: QubitSpecifier) -> InstructionSet:
|
2874
4457
|
"""Apply :class:`~qiskit.circuit.library.HGate`.
|
@@ -2883,7 +4466,7 @@ class QuantumCircuit:
|
|
2883
4466
|
"""
|
2884
4467
|
from .library.standard_gates.h import HGate
|
2885
4468
|
|
2886
|
-
return self.append(HGate(), [qubit], [])
|
4469
|
+
return self.append(HGate(), [qubit], [], copy=False)
|
2887
4470
|
|
2888
4471
|
def ch(
|
2889
4472
|
self,
|
@@ -2910,7 +4493,10 @@ class QuantumCircuit:
|
|
2910
4493
|
from .library.standard_gates.h import CHGate
|
2911
4494
|
|
2912
4495
|
return self.append(
|
2913
|
-
CHGate(label=label, ctrl_state=ctrl_state),
|
4496
|
+
CHGate(label=label, ctrl_state=ctrl_state),
|
4497
|
+
[control_qubit, target_qubit],
|
4498
|
+
[],
|
4499
|
+
copy=False,
|
2914
4500
|
)
|
2915
4501
|
|
2916
4502
|
def id(self, qubit: QubitSpecifier) -> InstructionSet: # pylint: disable=invalid-name
|
@@ -2926,7 +4512,7 @@ class QuantumCircuit:
|
|
2926
4512
|
"""
|
2927
4513
|
from .library.standard_gates.i import IGate
|
2928
4514
|
|
2929
|
-
return self.append(IGate(), [qubit], [])
|
4515
|
+
return self.append(IGate(), [qubit], [], copy=False)
|
2930
4516
|
|
2931
4517
|
def ms(self, theta: ParameterValueType, qubits: Sequence[QubitSpecifier]) -> InstructionSet:
|
2932
4518
|
"""Apply :class:`~qiskit.circuit.library.MSGate`.
|
@@ -2943,7 +4529,7 @@ class QuantumCircuit:
|
|
2943
4529
|
# pylint: disable=cyclic-import
|
2944
4530
|
from .library.generalized_gates.gms import MSGate
|
2945
4531
|
|
2946
|
-
return self.append(MSGate(len(qubits), theta), qubits)
|
4532
|
+
return self.append(MSGate(len(qubits), theta), qubits, copy=False)
|
2947
4533
|
|
2948
4534
|
def p(self, theta: ParameterValueType, qubit: QubitSpecifier) -> InstructionSet:
|
2949
4535
|
"""Apply :class:`~qiskit.circuit.library.PhaseGate`.
|
@@ -2959,7 +4545,7 @@ class QuantumCircuit:
|
|
2959
4545
|
"""
|
2960
4546
|
from .library.standard_gates.p import PhaseGate
|
2961
4547
|
|
2962
|
-
return self.append(PhaseGate(theta), [qubit], [])
|
4548
|
+
return self.append(PhaseGate(theta), [qubit], [], copy=False)
|
2963
4549
|
|
2964
4550
|
def cp(
|
2965
4551
|
self,
|
@@ -2988,7 +4574,10 @@ class QuantumCircuit:
|
|
2988
4574
|
from .library.standard_gates.p import CPhaseGate
|
2989
4575
|
|
2990
4576
|
return self.append(
|
2991
|
-
CPhaseGate(theta, label=label, ctrl_state=ctrl_state),
|
4577
|
+
CPhaseGate(theta, label=label, ctrl_state=ctrl_state),
|
4578
|
+
[control_qubit, target_qubit],
|
4579
|
+
[],
|
4580
|
+
copy=False,
|
2992
4581
|
)
|
2993
4582
|
|
2994
4583
|
def mcp(
|
@@ -2996,6 +4585,7 @@ class QuantumCircuit:
|
|
2996
4585
|
lam: ParameterValueType,
|
2997
4586
|
control_qubits: Sequence[QubitSpecifier],
|
2998
4587
|
target_qubit: QubitSpecifier,
|
4588
|
+
ctrl_state: str | int | None = None,
|
2999
4589
|
) -> InstructionSet:
|
3000
4590
|
"""Apply :class:`~qiskit.circuit.library.MCPhaseGate`.
|
3001
4591
|
|
@@ -3005,6 +4595,9 @@ class QuantumCircuit:
|
|
3005
4595
|
lam: The angle of the rotation.
|
3006
4596
|
control_qubits: The qubits used as the controls.
|
3007
4597
|
target_qubit: The qubit(s) targeted by the gate.
|
4598
|
+
ctrl_state:
|
4599
|
+
The control state in decimal, or as a bitstring (e.g. '1'). Defaults to controlling
|
4600
|
+
on the '1' state.
|
3008
4601
|
|
3009
4602
|
Returns:
|
3010
4603
|
A handle to the instructions created.
|
@@ -3013,7 +4606,10 @@ class QuantumCircuit:
|
|
3013
4606
|
|
3014
4607
|
num_ctrl_qubits = len(control_qubits)
|
3015
4608
|
return self.append(
|
3016
|
-
MCPhaseGate(lam, num_ctrl_qubits
|
4609
|
+
MCPhaseGate(lam, num_ctrl_qubits, ctrl_state=ctrl_state),
|
4610
|
+
control_qubits[:] + [target_qubit],
|
4611
|
+
[],
|
4612
|
+
copy=False,
|
3017
4613
|
)
|
3018
4614
|
|
3019
4615
|
def r(
|
@@ -3033,7 +4629,7 @@ class QuantumCircuit:
|
|
3033
4629
|
"""
|
3034
4630
|
from .library.standard_gates.r import RGate
|
3035
4631
|
|
3036
|
-
return self.append(RGate(theta, phi), [qubit], [])
|
4632
|
+
return self.append(RGate(theta, phi), [qubit], [], copy=False)
|
3037
4633
|
|
3038
4634
|
def rv(
|
3039
4635
|
self,
|
@@ -3060,7 +4656,7 @@ class QuantumCircuit:
|
|
3060
4656
|
"""
|
3061
4657
|
from .library.generalized_gates.rv import RVGate
|
3062
4658
|
|
3063
|
-
return self.append(RVGate(vx, vy, vz), [qubit], [])
|
4659
|
+
return self.append(RVGate(vx, vy, vz), [qubit], [], copy=False)
|
3064
4660
|
|
3065
4661
|
def rccx(
|
3066
4662
|
self,
|
@@ -3082,7 +4678,9 @@ class QuantumCircuit:
|
|
3082
4678
|
"""
|
3083
4679
|
from .library.standard_gates.x import RCCXGate
|
3084
4680
|
|
3085
|
-
return self.append(
|
4681
|
+
return self.append(
|
4682
|
+
RCCXGate(), [control_qubit1, control_qubit2, target_qubit], [], copy=False
|
4683
|
+
)
|
3086
4684
|
|
3087
4685
|
def rcccx(
|
3088
4686
|
self,
|
@@ -3107,7 +4705,10 @@ class QuantumCircuit:
|
|
3107
4705
|
from .library.standard_gates.x import RC3XGate
|
3108
4706
|
|
3109
4707
|
return self.append(
|
3110
|
-
RC3XGate(),
|
4708
|
+
RC3XGate(),
|
4709
|
+
[control_qubit1, control_qubit2, control_qubit3, target_qubit],
|
4710
|
+
[],
|
4711
|
+
copy=False,
|
3111
4712
|
)
|
3112
4713
|
|
3113
4714
|
def rx(
|
@@ -3127,7 +4728,7 @@ class QuantumCircuit:
|
|
3127
4728
|
"""
|
3128
4729
|
from .library.standard_gates.rx import RXGate
|
3129
4730
|
|
3130
|
-
return self.append(RXGate(theta, label=label), [qubit], [])
|
4731
|
+
return self.append(RXGate(theta, label=label), [qubit], [], copy=False)
|
3131
4732
|
|
3132
4733
|
def crx(
|
3133
4734
|
self,
|
@@ -3156,7 +4757,10 @@ class QuantumCircuit:
|
|
3156
4757
|
from .library.standard_gates.rx import CRXGate
|
3157
4758
|
|
3158
4759
|
return self.append(
|
3159
|
-
CRXGate(theta, label=label, ctrl_state=ctrl_state),
|
4760
|
+
CRXGate(theta, label=label, ctrl_state=ctrl_state),
|
4761
|
+
[control_qubit, target_qubit],
|
4762
|
+
[],
|
4763
|
+
copy=False,
|
3160
4764
|
)
|
3161
4765
|
|
3162
4766
|
def rxx(
|
@@ -3176,7 +4780,7 @@ class QuantumCircuit:
|
|
3176
4780
|
"""
|
3177
4781
|
from .library.standard_gates.rxx import RXXGate
|
3178
4782
|
|
3179
|
-
return self.append(RXXGate(theta), [qubit1, qubit2], [])
|
4783
|
+
return self.append(RXXGate(theta), [qubit1, qubit2], [], copy=False)
|
3180
4784
|
|
3181
4785
|
def ry(
|
3182
4786
|
self, theta: ParameterValueType, qubit: QubitSpecifier, label: str | None = None
|
@@ -3195,7 +4799,7 @@ class QuantumCircuit:
|
|
3195
4799
|
"""
|
3196
4800
|
from .library.standard_gates.ry import RYGate
|
3197
4801
|
|
3198
|
-
return self.append(RYGate(theta, label=label), [qubit], [])
|
4802
|
+
return self.append(RYGate(theta, label=label), [qubit], [], copy=False)
|
3199
4803
|
|
3200
4804
|
def cry(
|
3201
4805
|
self,
|
@@ -3224,7 +4828,10 @@ class QuantumCircuit:
|
|
3224
4828
|
from .library.standard_gates.ry import CRYGate
|
3225
4829
|
|
3226
4830
|
return self.append(
|
3227
|
-
CRYGate(theta, label=label, ctrl_state=ctrl_state),
|
4831
|
+
CRYGate(theta, label=label, ctrl_state=ctrl_state),
|
4832
|
+
[control_qubit, target_qubit],
|
4833
|
+
[],
|
4834
|
+
copy=False,
|
3228
4835
|
)
|
3229
4836
|
|
3230
4837
|
def ryy(
|
@@ -3244,7 +4851,7 @@ class QuantumCircuit:
|
|
3244
4851
|
"""
|
3245
4852
|
from .library.standard_gates.ryy import RYYGate
|
3246
4853
|
|
3247
|
-
return self.append(RYYGate(theta), [qubit1, qubit2], [])
|
4854
|
+
return self.append(RYYGate(theta), [qubit1, qubit2], [], copy=False)
|
3248
4855
|
|
3249
4856
|
def rz(self, phi: ParameterValueType, qubit: QubitSpecifier) -> InstructionSet:
|
3250
4857
|
"""Apply :class:`~qiskit.circuit.library.RZGate`.
|
@@ -3260,7 +4867,7 @@ class QuantumCircuit:
|
|
3260
4867
|
"""
|
3261
4868
|
from .library.standard_gates.rz import RZGate
|
3262
4869
|
|
3263
|
-
return self.append(RZGate(phi), [qubit], [])
|
4870
|
+
return self.append(RZGate(phi), [qubit], [], copy=False)
|
3264
4871
|
|
3265
4872
|
def crz(
|
3266
4873
|
self,
|
@@ -3289,7 +4896,10 @@ class QuantumCircuit:
|
|
3289
4896
|
from .library.standard_gates.rz import CRZGate
|
3290
4897
|
|
3291
4898
|
return self.append(
|
3292
|
-
CRZGate(theta, label=label, ctrl_state=ctrl_state),
|
4899
|
+
CRZGate(theta, label=label, ctrl_state=ctrl_state),
|
4900
|
+
[control_qubit, target_qubit],
|
4901
|
+
[],
|
4902
|
+
copy=False,
|
3293
4903
|
)
|
3294
4904
|
|
3295
4905
|
def rzx(
|
@@ -3309,7 +4919,7 @@ class QuantumCircuit:
|
|
3309
4919
|
"""
|
3310
4920
|
from .library.standard_gates.rzx import RZXGate
|
3311
4921
|
|
3312
|
-
return self.append(RZXGate(theta), [qubit1, qubit2], [])
|
4922
|
+
return self.append(RZXGate(theta), [qubit1, qubit2], [], copy=False)
|
3313
4923
|
|
3314
4924
|
def rzz(
|
3315
4925
|
self, theta: ParameterValueType, qubit1: QubitSpecifier, qubit2: QubitSpecifier
|
@@ -3328,7 +4938,7 @@ class QuantumCircuit:
|
|
3328
4938
|
"""
|
3329
4939
|
from .library.standard_gates.rzz import RZZGate
|
3330
4940
|
|
3331
|
-
return self.append(RZZGate(theta), [qubit1, qubit2], [])
|
4941
|
+
return self.append(RZZGate(theta), [qubit1, qubit2], [], copy=False)
|
3332
4942
|
|
3333
4943
|
def ecr(self, qubit1: QubitSpecifier, qubit2: QubitSpecifier) -> InstructionSet:
|
3334
4944
|
"""Apply :class:`~qiskit.circuit.library.ECRGate`.
|
@@ -3343,7 +4953,7 @@ class QuantumCircuit:
|
|
3343
4953
|
"""
|
3344
4954
|
from .library.standard_gates.ecr import ECRGate
|
3345
4955
|
|
3346
|
-
return self.append(ECRGate(), [qubit1, qubit2], [])
|
4956
|
+
return self.append(ECRGate(), [qubit1, qubit2], [], copy=False)
|
3347
4957
|
|
3348
4958
|
def s(self, qubit: QubitSpecifier) -> InstructionSet:
|
3349
4959
|
"""Apply :class:`~qiskit.circuit.library.SGate`.
|
@@ -3358,7 +4968,7 @@ class QuantumCircuit:
|
|
3358
4968
|
"""
|
3359
4969
|
from .library.standard_gates.s import SGate
|
3360
4970
|
|
3361
|
-
return self.append(SGate(), [qubit], [])
|
4971
|
+
return self.append(SGate(), [qubit], [], copy=False)
|
3362
4972
|
|
3363
4973
|
def sdg(self, qubit: QubitSpecifier) -> InstructionSet:
|
3364
4974
|
"""Apply :class:`~qiskit.circuit.library.SdgGate`.
|
@@ -3373,7 +4983,7 @@ class QuantumCircuit:
|
|
3373
4983
|
"""
|
3374
4984
|
from .library.standard_gates.s import SdgGate
|
3375
4985
|
|
3376
|
-
return self.append(SdgGate(), [qubit], [])
|
4986
|
+
return self.append(SdgGate(), [qubit], [], copy=False)
|
3377
4987
|
|
3378
4988
|
def cs(
|
3379
4989
|
self,
|
@@ -3403,6 +5013,7 @@ class QuantumCircuit:
|
|
3403
5013
|
CSGate(label=label, ctrl_state=ctrl_state),
|
3404
5014
|
[control_qubit, target_qubit],
|
3405
5015
|
[],
|
5016
|
+
copy=False,
|
3406
5017
|
)
|
3407
5018
|
|
3408
5019
|
def csdg(
|
@@ -3433,6 +5044,7 @@ class QuantumCircuit:
|
|
3433
5044
|
CSdgGate(label=label, ctrl_state=ctrl_state),
|
3434
5045
|
[control_qubit, target_qubit],
|
3435
5046
|
[],
|
5047
|
+
copy=False,
|
3436
5048
|
)
|
3437
5049
|
|
3438
5050
|
def swap(self, qubit1: QubitSpecifier, qubit2: QubitSpecifier) -> InstructionSet:
|
@@ -3448,7 +5060,7 @@ class QuantumCircuit:
|
|
3448
5060
|
"""
|
3449
5061
|
from .library.standard_gates.swap import SwapGate
|
3450
5062
|
|
3451
|
-
return self.append(SwapGate(), [qubit1, qubit2], [])
|
5063
|
+
return self.append(SwapGate(), [qubit1, qubit2], [], copy=False)
|
3452
5064
|
|
3453
5065
|
def iswap(self, qubit1: QubitSpecifier, qubit2: QubitSpecifier) -> InstructionSet:
|
3454
5066
|
"""Apply :class:`~qiskit.circuit.library.iSwapGate`.
|
@@ -3463,7 +5075,7 @@ class QuantumCircuit:
|
|
3463
5075
|
"""
|
3464
5076
|
from .library.standard_gates.iswap import iSwapGate
|
3465
5077
|
|
3466
|
-
return self.append(iSwapGate(), [qubit1, qubit2], [])
|
5078
|
+
return self.append(iSwapGate(), [qubit1, qubit2], [], copy=False)
|
3467
5079
|
|
3468
5080
|
def cswap(
|
3469
5081
|
self,
|
@@ -3495,6 +5107,7 @@ class QuantumCircuit:
|
|
3495
5107
|
CSwapGate(label=label, ctrl_state=ctrl_state),
|
3496
5108
|
[control_qubit, target_qubit1, target_qubit2],
|
3497
5109
|
[],
|
5110
|
+
copy=False,
|
3498
5111
|
)
|
3499
5112
|
|
3500
5113
|
def sx(self, qubit: QubitSpecifier) -> InstructionSet:
|
@@ -3510,7 +5123,7 @@ class QuantumCircuit:
|
|
3510
5123
|
"""
|
3511
5124
|
from .library.standard_gates.sx import SXGate
|
3512
5125
|
|
3513
|
-
return self.append(SXGate(), [qubit], [])
|
5126
|
+
return self.append(SXGate(), [qubit], [], copy=False)
|
3514
5127
|
|
3515
5128
|
def sxdg(self, qubit: QubitSpecifier) -> InstructionSet:
|
3516
5129
|
"""Apply :class:`~qiskit.circuit.library.SXdgGate`.
|
@@ -3525,7 +5138,7 @@ class QuantumCircuit:
|
|
3525
5138
|
"""
|
3526
5139
|
from .library.standard_gates.sx import SXdgGate
|
3527
5140
|
|
3528
|
-
return self.append(SXdgGate(), [qubit], [])
|
5141
|
+
return self.append(SXdgGate(), [qubit], [], copy=False)
|
3529
5142
|
|
3530
5143
|
def csx(
|
3531
5144
|
self,
|
@@ -3555,6 +5168,7 @@ class QuantumCircuit:
|
|
3555
5168
|
CSXGate(label=label, ctrl_state=ctrl_state),
|
3556
5169
|
[control_qubit, target_qubit],
|
3557
5170
|
[],
|
5171
|
+
copy=False,
|
3558
5172
|
)
|
3559
5173
|
|
3560
5174
|
def t(self, qubit: QubitSpecifier) -> InstructionSet:
|
@@ -3570,7 +5184,7 @@ class QuantumCircuit:
|
|
3570
5184
|
"""
|
3571
5185
|
from .library.standard_gates.t import TGate
|
3572
5186
|
|
3573
|
-
return self.append(TGate(), [qubit], [])
|
5187
|
+
return self.append(TGate(), [qubit], [], copy=False)
|
3574
5188
|
|
3575
5189
|
def tdg(self, qubit: QubitSpecifier) -> InstructionSet:
|
3576
5190
|
"""Apply :class:`~qiskit.circuit.library.TdgGate`.
|
@@ -3585,7 +5199,7 @@ class QuantumCircuit:
|
|
3585
5199
|
"""
|
3586
5200
|
from .library.standard_gates.t import TdgGate
|
3587
5201
|
|
3588
|
-
return self.append(TdgGate(), [qubit], [])
|
5202
|
+
return self.append(TdgGate(), [qubit], [], copy=False)
|
3589
5203
|
|
3590
5204
|
def u(
|
3591
5205
|
self,
|
@@ -3609,7 +5223,7 @@ class QuantumCircuit:
|
|
3609
5223
|
"""
|
3610
5224
|
from .library.standard_gates.u import UGate
|
3611
5225
|
|
3612
|
-
return self.append(UGate(theta, phi, lam), [qubit], [])
|
5226
|
+
return self.append(UGate(theta, phi, lam), [qubit], [], copy=False)
|
3613
5227
|
|
3614
5228
|
def cu(
|
3615
5229
|
self,
|
@@ -3647,6 +5261,7 @@ class QuantumCircuit:
|
|
3647
5261
|
CUGate(theta, phi, lam, gamma, label=label, ctrl_state=ctrl_state),
|
3648
5262
|
[control_qubit, target_qubit],
|
3649
5263
|
[],
|
5264
|
+
copy=False,
|
3650
5265
|
)
|
3651
5266
|
|
3652
5267
|
def x(self, qubit: QubitSpecifier, label: str | None = None) -> InstructionSet:
|
@@ -3663,7 +5278,7 @@ class QuantumCircuit:
|
|
3663
5278
|
"""
|
3664
5279
|
from .library.standard_gates.x import XGate
|
3665
5280
|
|
3666
|
-
return self.append(XGate(label=label), [qubit], [])
|
5281
|
+
return self.append(XGate(label=label), [qubit], [], copy=False)
|
3667
5282
|
|
3668
5283
|
def cx(
|
3669
5284
|
self,
|
@@ -3691,7 +5306,10 @@ class QuantumCircuit:
|
|
3691
5306
|
from .library.standard_gates.x import CXGate
|
3692
5307
|
|
3693
5308
|
return self.append(
|
3694
|
-
CXGate(label=label, ctrl_state=ctrl_state),
|
5309
|
+
CXGate(label=label, ctrl_state=ctrl_state),
|
5310
|
+
[control_qubit, target_qubit],
|
5311
|
+
[],
|
5312
|
+
copy=False,
|
3695
5313
|
)
|
3696
5314
|
|
3697
5315
|
def dcx(self, qubit1: QubitSpecifier, qubit2: QubitSpecifier) -> InstructionSet:
|
@@ -3708,7 +5326,7 @@ class QuantumCircuit:
|
|
3708
5326
|
"""
|
3709
5327
|
from .library.standard_gates.dcx import DCXGate
|
3710
5328
|
|
3711
|
-
return self.append(DCXGate(), [qubit1, qubit2], [])
|
5329
|
+
return self.append(DCXGate(), [qubit1, qubit2], [], copy=False)
|
3712
5330
|
|
3713
5331
|
def ccx(
|
3714
5332
|
self,
|
@@ -3738,6 +5356,7 @@ class QuantumCircuit:
|
|
3738
5356
|
CCXGate(ctrl_state=ctrl_state),
|
3739
5357
|
[control_qubit1, control_qubit2, target_qubit],
|
3740
5358
|
[],
|
5359
|
+
copy=False,
|
3741
5360
|
)
|
3742
5361
|
|
3743
5362
|
def mcx(
|
@@ -3746,6 +5365,7 @@ class QuantumCircuit:
|
|
3746
5365
|
target_qubit: QubitSpecifier,
|
3747
5366
|
ancilla_qubits: QubitSpecifier | Sequence[QubitSpecifier] | None = None,
|
3748
5367
|
mode: str = "noancilla",
|
5368
|
+
ctrl_state: str | int | None = None,
|
3749
5369
|
) -> InstructionSet:
|
3750
5370
|
"""Apply :class:`~qiskit.circuit.library.MCXGate`.
|
3751
5371
|
|
@@ -3764,6 +5384,9 @@ class QuantumCircuit:
|
|
3764
5384
|
target_qubit: The qubit(s) targeted by the gate.
|
3765
5385
|
ancilla_qubits: The qubits used as the ancillae, if the mode requires them.
|
3766
5386
|
mode: The choice of mode, explained further above.
|
5387
|
+
ctrl_state:
|
5388
|
+
The control state in decimal, or as a bitstring (e.g. '1'). Defaults to controlling
|
5389
|
+
on the '1' state.
|
3767
5390
|
|
3768
5391
|
Returns:
|
3769
5392
|
A handle to the instructions created.
|
@@ -3777,14 +5400,16 @@ class QuantumCircuit:
|
|
3777
5400
|
num_ctrl_qubits = len(control_qubits)
|
3778
5401
|
|
3779
5402
|
available_implementations = {
|
3780
|
-
"noancilla": MCXGrayCode(num_ctrl_qubits),
|
3781
|
-
"recursion": MCXRecursive(num_ctrl_qubits),
|
3782
|
-
"v-chain": MCXVChain(num_ctrl_qubits, False),
|
3783
|
-
"v-chain-dirty": MCXVChain(num_ctrl_qubits, dirty_ancillas=True),
|
5403
|
+
"noancilla": MCXGrayCode(num_ctrl_qubits, ctrl_state=ctrl_state),
|
5404
|
+
"recursion": MCXRecursive(num_ctrl_qubits, ctrl_state=ctrl_state),
|
5405
|
+
"v-chain": MCXVChain(num_ctrl_qubits, False, ctrl_state=ctrl_state),
|
5406
|
+
"v-chain-dirty": MCXVChain(num_ctrl_qubits, dirty_ancillas=True, ctrl_state=ctrl_state),
|
3784
5407
|
# outdated, previous names
|
3785
|
-
"advanced": MCXRecursive(num_ctrl_qubits),
|
3786
|
-
"basic": MCXVChain(num_ctrl_qubits, dirty_ancillas=False),
|
3787
|
-
"basic-dirty-ancilla": MCXVChain(
|
5408
|
+
"advanced": MCXRecursive(num_ctrl_qubits, ctrl_state=ctrl_state),
|
5409
|
+
"basic": MCXVChain(num_ctrl_qubits, dirty_ancillas=False, ctrl_state=ctrl_state),
|
5410
|
+
"basic-dirty-ancilla": MCXVChain(
|
5411
|
+
num_ctrl_qubits, dirty_ancillas=True, ctrl_state=ctrl_state
|
5412
|
+
),
|
3788
5413
|
}
|
3789
5414
|
|
3790
5415
|
# check ancilla input
|
@@ -3831,7 +5456,7 @@ class QuantumCircuit:
|
|
3831
5456
|
"""
|
3832
5457
|
from .library.standard_gates.y import YGate
|
3833
5458
|
|
3834
|
-
return self.append(YGate(), [qubit], [])
|
5459
|
+
return self.append(YGate(), [qubit], [], copy=False)
|
3835
5460
|
|
3836
5461
|
def cy(
|
3837
5462
|
self,
|
@@ -3858,7 +5483,10 @@ class QuantumCircuit:
|
|
3858
5483
|
from .library.standard_gates.y import CYGate
|
3859
5484
|
|
3860
5485
|
return self.append(
|
3861
|
-
CYGate(label=label, ctrl_state=ctrl_state),
|
5486
|
+
CYGate(label=label, ctrl_state=ctrl_state),
|
5487
|
+
[control_qubit, target_qubit],
|
5488
|
+
[],
|
5489
|
+
copy=False,
|
3862
5490
|
)
|
3863
5491
|
|
3864
5492
|
def z(self, qubit: QubitSpecifier) -> InstructionSet:
|
@@ -3874,7 +5502,7 @@ class QuantumCircuit:
|
|
3874
5502
|
"""
|
3875
5503
|
from .library.standard_gates.z import ZGate
|
3876
5504
|
|
3877
|
-
return self.append(ZGate(), [qubit], [])
|
5505
|
+
return self.append(ZGate(), [qubit], [], copy=False)
|
3878
5506
|
|
3879
5507
|
def cz(
|
3880
5508
|
self,
|
@@ -3901,7 +5529,10 @@ class QuantumCircuit:
|
|
3901
5529
|
from .library.standard_gates.z import CZGate
|
3902
5530
|
|
3903
5531
|
return self.append(
|
3904
|
-
CZGate(label=label, ctrl_state=ctrl_state),
|
5532
|
+
CZGate(label=label, ctrl_state=ctrl_state),
|
5533
|
+
[control_qubit, target_qubit],
|
5534
|
+
[],
|
5535
|
+
copy=False,
|
3905
5536
|
)
|
3906
5537
|
|
3907
5538
|
def ccz(
|
@@ -3934,6 +5565,7 @@ class QuantumCircuit:
|
|
3934
5565
|
CCZGate(label=label, ctrl_state=ctrl_state),
|
3935
5566
|
[control_qubit1, control_qubit2, target_qubit],
|
3936
5567
|
[],
|
5568
|
+
copy=False,
|
3937
5569
|
)
|
3938
5570
|
|
3939
5571
|
def pauli(
|
@@ -3952,7 +5584,7 @@ class QuantumCircuit:
|
|
3952
5584
|
"""
|
3953
5585
|
from qiskit.circuit.library.generalized_gates.pauli import PauliGate
|
3954
5586
|
|
3955
|
-
return self.append(PauliGate(pauli_string), qubits, [])
|
5587
|
+
return self.append(PauliGate(pauli_string), qubits, [], copy=False)
|
3956
5588
|
|
3957
5589
|
def prepare_state(
|
3958
5590
|
self,
|
@@ -4063,7 +5695,9 @@ class QuantumCircuit:
|
|
4063
5695
|
num_qubits = len(qubits) if isinstance(state, int) else None
|
4064
5696
|
|
4065
5697
|
return self.append(
|
4066
|
-
StatePreparation(state, num_qubits, label=label, normalize=normalize),
|
5698
|
+
StatePreparation(state, num_qubits, label=label, normalize=normalize),
|
5699
|
+
qubits,
|
5700
|
+
copy=False,
|
4067
5701
|
)
|
4068
5702
|
|
4069
5703
|
def initialize(
|
@@ -4175,7 +5809,7 @@ class QuantumCircuit:
|
|
4175
5809
|
|
4176
5810
|
num_qubits = len(qubits) if isinstance(params, int) else None
|
4177
5811
|
|
4178
|
-
return self.append(Initialize(params, num_qubits, normalize), qubits)
|
5812
|
+
return self.append(Initialize(params, num_qubits, normalize), qubits, copy=False)
|
4179
5813
|
|
4180
5814
|
def unitary(
|
4181
5815
|
self,
|
@@ -4218,7 +5852,7 @@ class QuantumCircuit:
|
|
4218
5852
|
if isinstance(qubits, (int, Qubit)) or len(qubits) > 1:
|
4219
5853
|
qubits = [qubits]
|
4220
5854
|
|
4221
|
-
return self.append(gate, qubits, [])
|
5855
|
+
return self.append(gate, qubits, [], copy=False)
|
4222
5856
|
|
4223
5857
|
def _current_scope(self) -> CircuitScopeInterface:
|
4224
5858
|
if self._control_flow_scopes:
|
@@ -4400,7 +6034,7 @@ class QuantumCircuit:
|
|
4400
6034
|
"When using 'while_loop' with a body, you must pass qubits and clbits."
|
4401
6035
|
)
|
4402
6036
|
|
4403
|
-
return self.append(WhileLoopOp(condition, body, label), qubits, clbits)
|
6037
|
+
return self.append(WhileLoopOp(condition, body, label), qubits, clbits, copy=False)
|
4404
6038
|
|
4405
6039
|
@typing.overload
|
4406
6040
|
def for_loop(
|
@@ -4489,18 +6123,12 @@ class QuantumCircuit:
|
|
4489
6123
|
"When using 'for_loop' with a body, you must pass qubits and clbits."
|
4490
6124
|
)
|
4491
6125
|
|
4492
|
-
return self.append(
|
6126
|
+
return self.append(
|
6127
|
+
ForLoopOp(indexset, loop_parameter, body, label), qubits, clbits, copy=False
|
6128
|
+
)
|
4493
6129
|
|
4494
6130
|
@typing.overload
|
4495
|
-
def if_test(
|
4496
|
-
self,
|
4497
|
-
condition: tuple[ClassicalRegister | Clbit, int],
|
4498
|
-
true_body: None,
|
4499
|
-
qubits: None,
|
4500
|
-
clbits: None,
|
4501
|
-
*,
|
4502
|
-
label: str | None,
|
4503
|
-
) -> IfContext: ...
|
6131
|
+
def if_test(self, condition: tuple[ClassicalRegister | Clbit, int]) -> IfContext: ...
|
4504
6132
|
|
4505
6133
|
@typing.overload
|
4506
6134
|
def if_test(
|
@@ -4554,11 +6182,11 @@ class QuantumCircuit:
|
|
4554
6182
|
qc.z(2)
|
4555
6183
|
|
4556
6184
|
Args:
|
4557
|
-
condition (Tuple[Union[ClassicalRegister, Clbit], int]): A condition to be evaluated
|
4558
|
-
circuit
|
4559
|
-
specified as either a tuple of a ``ClassicalRegister`` to be
|
4560
|
-
with a given ``int``, or as a tuple of a ``Clbit`` to be
|
4561
|
-
``bool`` or an ``int``.
|
6185
|
+
condition (Tuple[Union[ClassicalRegister, Clbit], int]): A condition to be evaluated in
|
6186
|
+
real time during circuit execution, which, if true, will trigger the evaluation of
|
6187
|
+
``true_body``. Can be specified as either a tuple of a ``ClassicalRegister`` to be
|
6188
|
+
tested for equality with a given ``int``, or as a tuple of a ``Clbit`` to be
|
6189
|
+
compared to either a ``bool`` or an ``int``.
|
4562
6190
|
true_body (Optional[QuantumCircuit]): The circuit body to be run if ``condition`` is
|
4563
6191
|
true.
|
4564
6192
|
qubits (Optional[Sequence[QubitSpecifier]]): The circuit qubits over which the if/else
|
@@ -4599,7 +6227,7 @@ class QuantumCircuit:
|
|
4599
6227
|
elif qubits is None or clbits is None:
|
4600
6228
|
raise CircuitError("When using 'if_test' with a body, you must pass qubits and clbits.")
|
4601
6229
|
|
4602
|
-
return self.append(IfElseOp(condition, true_body, None, label), qubits, clbits)
|
6230
|
+
return self.append(IfElseOp(condition, true_body, None, label), qubits, clbits, copy=False)
|
4603
6231
|
|
4604
6232
|
def if_else(
|
4605
6233
|
self,
|
@@ -4630,7 +6258,7 @@ class QuantumCircuit:
|
|
4630
6258
|
qc.x(0)
|
4631
6259
|
|
4632
6260
|
Args:
|
4633
|
-
condition: A condition to be evaluated at circuit
|
6261
|
+
condition: A condition to be evaluated in real time at circuit execution, which,
|
4634
6262
|
if true, will trigger the evaluation of ``true_body``. Can be
|
4635
6263
|
specified as either a tuple of a ``ClassicalRegister`` to be
|
4636
6264
|
tested for equality with a given ``int``, or as a tuple of a
|
@@ -4654,7 +6282,9 @@ class QuantumCircuit:
|
|
4654
6282
|
else:
|
4655
6283
|
condition = (circuit_scope.resolve_classical_resource(condition[0]), condition[1])
|
4656
6284
|
|
4657
|
-
return self.append(
|
6285
|
+
return self.append(
|
6286
|
+
IfElseOp(condition, true_body, false_body, label), qubits, clbits, copy=False
|
6287
|
+
)
|
4658
6288
|
|
4659
6289
|
@typing.overload
|
4660
6290
|
def switch(
|
@@ -4745,7 +6375,7 @@ class QuantumCircuit:
|
|
4745
6375
|
|
4746
6376
|
if qubits is None or clbits is None:
|
4747
6377
|
raise CircuitError("When using 'switch' with cases, you must pass qubits and clbits.")
|
4748
|
-
return self.append(SwitchCaseOp(target, cases, label=label), qubits, clbits)
|
6378
|
+
return self.append(SwitchCaseOp(target, cases, label=label), qubits, clbits, copy=False)
|
4749
6379
|
|
4750
6380
|
def break_loop(self) -> InstructionSet:
|
4751
6381
|
"""Apply :class:`~qiskit.circuit.BreakLoopOp`.
|
@@ -4771,8 +6401,10 @@ class QuantumCircuit:
|
|
4771
6401
|
if self._control_flow_scopes:
|
4772
6402
|
operation = BreakLoopPlaceholder()
|
4773
6403
|
resources = operation.placeholder_resources()
|
4774
|
-
return self.append(operation, resources.qubits, resources.clbits)
|
4775
|
-
return self.append(
|
6404
|
+
return self.append(operation, resources.qubits, resources.clbits, copy=False)
|
6405
|
+
return self.append(
|
6406
|
+
BreakLoopOp(self.num_qubits, self.num_clbits), self.qubits, self.clbits, copy=False
|
6407
|
+
)
|
4776
6408
|
|
4777
6409
|
def continue_loop(self) -> InstructionSet:
|
4778
6410
|
"""Apply :class:`~qiskit.circuit.ContinueLoopOp`.
|
@@ -4798,9 +6430,9 @@ class QuantumCircuit:
|
|
4798
6430
|
if self._control_flow_scopes:
|
4799
6431
|
operation = ContinueLoopPlaceholder()
|
4800
6432
|
resources = operation.placeholder_resources()
|
4801
|
-
return self.append(operation, resources.qubits, resources.clbits)
|
6433
|
+
return self.append(operation, resources.qubits, resources.clbits, copy=False)
|
4802
6434
|
return self.append(
|
4803
|
-
ContinueLoopOp(self.num_qubits, self.num_clbits), self.qubits, self.clbits
|
6435
|
+
ContinueLoopOp(self.num_qubits, self.num_clbits), self.qubits, self.clbits, copy=False
|
4804
6436
|
)
|
4805
6437
|
|
4806
6438
|
def add_calibration(
|
@@ -4996,6 +6628,24 @@ class _OuterCircuitScopeInterface(CircuitScopeInterface):
|
|
4996
6628
|
raise CircuitError(f"Classical bit index {specifier} is out-of-range.") from None
|
4997
6629
|
raise CircuitError(f"Unknown classical resource specifier: '{specifier}'.")
|
4998
6630
|
|
6631
|
+
def add_uninitialized_var(self, var):
|
6632
|
+
var = self.circuit._prepare_new_var(var, None)
|
6633
|
+
self.circuit._vars_local[var.name] = var
|
6634
|
+
|
6635
|
+
def remove_var(self, var):
|
6636
|
+
self.circuit._vars_local.pop(var.name)
|
6637
|
+
|
6638
|
+
def get_var(self, name):
|
6639
|
+
if (out := self.circuit._vars_local.get(name)) is not None:
|
6640
|
+
return out
|
6641
|
+
if (out := self.circuit._vars_capture.get(name)) is not None:
|
6642
|
+
return out
|
6643
|
+
return self.circuit._vars_input.get(name)
|
6644
|
+
|
6645
|
+
def use_var(self, var):
|
6646
|
+
if self.get_var(var.name) != var:
|
6647
|
+
raise CircuitError(f"'{var}' is not present in this circuit")
|
6648
|
+
|
4999
6649
|
|
5000
6650
|
def _validate_expr(circuit_scope: CircuitScopeInterface, node: expr.Expr) -> expr.Expr:
|
5001
6651
|
# This takes the `circuit_scope` object as an argument rather than being a circuit method and
|