mirror of https://github.com/Qiskit/qiskit.git
Write module-level `qiskit.circuit` documentation (#11904)
* Write module-level `qiskit.circuit` documentation I was pretty surprised to see that we had very little written for our principal module, and the first entry in our API docs. This is a totally new set of documentation for the `qiskit.circuit` module, including discussion of what circuits are, what they represent in Qiskit, how all the different data elements fit together, and where to go for more information on things. This commit is intended to be followed by a later one that does a similar rewrite for the whole `QuantumCircuit` class, including structuring its references to all its attributes and methods, and adding a holistic view of how the methods fit together. This is why there are some (hidden to Sphinx) `TODO` comments scattered throughout this documentation. * Apply suggestions from Sebastian's review Co-authored-by: Sebastian Brandhofer <148463728+sbrandhsn@users.noreply.github.com> * Move larger classes to separate pages This moves the larger class definitions (basically those that actually have any public methods) to separate pages, at the request of the docs team. Much of this is intended to be temporary, and for most of these classes to be moved back inline once the IBM docs platform can better support that. * Fix docs build with autosummary * Switch "near time"/"runtime" terminology to "real time" This avoids overloading "runtime" with too many meanings, and appears to be more consistent with other messaging coming out of IBM Quantum. * Remove misleading 'bitwise' terminology --------- Co-authored-by: Sebastian Brandhofer <148463728+sbrandhsn@users.noreply.github.com>
This commit is contained in:
parent
2cbbe2bee2
commit
99c0497052
File diff suppressed because it is too large
Load Diff
|
@ -110,8 +110,8 @@ class VariableMapper(expr.ExprVisitor[expr.Expr]):
|
|||
return (mapped_theirs, mapped_value)
|
||||
|
||||
def map_target(self, target, /):
|
||||
"""Map the runtime variables in a ``target`` of a :class:`.SwitchCaseOp` to the new circuit,
|
||||
as defined in the ``circuit`` argument of the initialiser of this class."""
|
||||
"""Map the real-time variables in a ``target`` of a :class:`.SwitchCaseOp` to the new
|
||||
circuit, as defined in the ``circuit`` argument of the initialiser of this class."""
|
||||
if isinstance(target, Clbit):
|
||||
return self.bit_map[target]
|
||||
if isinstance(target, ClassicalRegister):
|
||||
|
|
|
@ -97,7 +97,10 @@ class AnnotatedOperation(Operation):
|
|||
inverted and then controlled by 2 qubits.
|
||||
"""
|
||||
self.base_op = base_op
|
||||
"""The base operation that the modifiers in this annotated operation applies to."""
|
||||
self.modifiers = modifiers if isinstance(modifiers, List) else [modifiers]
|
||||
"""Ordered sequence of the modifiers to apply to :attr:`base_op`. The modifiers are applied
|
||||
in order from lowest index to highest index."""
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
|
|
|
@ -16,29 +16,26 @@ Can be applied to a :class:`~qiskit.circuit.QuantumCircuit`
|
|||
with the :meth:`~qiskit.circuit.QuantumCircuit.barrier` method.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from qiskit.exceptions import QiskitError
|
||||
from .instruction import Instruction
|
||||
|
||||
|
||||
class Barrier(Instruction):
|
||||
"""Barrier instruction.
|
||||
"""A directive for circuit compilation to separate pieces of a circuit so that any optimizations
|
||||
or re-writes are constrained to only act between barriers.
|
||||
|
||||
A barrier is a visual indicator of the grouping of a circuit section.
|
||||
It also acts as a directive for circuit compilation to separate pieces
|
||||
of a circuit so that any optimizations or re-writes are constrained
|
||||
to only act between barriers."""
|
||||
This will also appear in visualizations as a visual marker.
|
||||
"""
|
||||
|
||||
_directive = True
|
||||
|
||||
def __init__(self, num_qubits, label=None):
|
||||
"""Create new barrier instruction.
|
||||
|
||||
def __init__(self, num_qubits: int, label: str | None = None):
|
||||
"""
|
||||
Args:
|
||||
num_qubits (int): the number of qubits for the barrier type [Default: 0].
|
||||
label (str): the barrier label
|
||||
|
||||
Raises:
|
||||
TypeError: if barrier label is invalid.
|
||||
num_qubits: the number of qubits for the barrier.
|
||||
label: the optional label of this barrier.
|
||||
"""
|
||||
self._label = label
|
||||
super().__init__("barrier", num_qubits, 0, [], label=label)
|
||||
|
|
|
@ -24,7 +24,6 @@ class Bit:
|
|||
.. note::
|
||||
This class should not be instantiated directly. This is just a superclass
|
||||
for :class:`~.Clbit` and :class:`~.circuit.Qubit`.
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = {"_register", "_index", "_hash", "_repr"}
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
Classical expressions (:mod:`qiskit.circuit.classical`)
|
||||
=======================================================
|
||||
|
||||
This module contains an exploratory representation of runtime operations on classical values during
|
||||
circuit execution.
|
||||
This module contains an exploratory representation of real-time operations on classical values
|
||||
during circuit execution.
|
||||
|
||||
Currently, only simple expressions on bits and registers that result in a Boolean value are
|
||||
supported, and these are only valid for use in the conditions of :meth:`.QuantumCircuit.if_test`
|
||||
|
|
|
@ -39,8 +39,8 @@ The expression system is based on tree representation. All nodes in the tree ar
|
|||
|
||||
These objects are mutable and should not be reused in a different location without a copy.
|
||||
|
||||
The base for dynamic variables is the :class:`Var`, which can be either an arbitrarily typed runtime
|
||||
variable, or a wrapper around a :class:`.Clbit` or :class:`.ClassicalRegister`.
|
||||
The base for dynamic variables is the :class:`Var`, which can be either an arbitrarily typed
|
||||
real-time variable, or a wrapper around a :class:`.Clbit` or :class:`.ClassicalRegister`.
|
||||
|
||||
.. autoclass:: Var
|
||||
:members: var, name
|
||||
|
|
|
@ -19,31 +19,17 @@ from .builder import InstructionPlaceholder, InstructionResources
|
|||
|
||||
|
||||
class BreakLoopOp(Instruction):
|
||||
"""A circuit operation which, when encountered, jumps to the end of
|
||||
the nearest enclosing loop.
|
||||
|
||||
.. note:
|
||||
|
||||
Can be inserted only within the body of a loop op, and must span
|
||||
the full width of that block.
|
||||
|
||||
**Circuit symbol:**
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
┌──────────────┐
|
||||
q_0: ┤0 ├
|
||||
│ │
|
||||
q_1: ┤1 ├
|
||||
│ break_loop │
|
||||
q_2: ┤2 ├
|
||||
│ │
|
||||
c_0: ╡0 ╞
|
||||
└──────────────┘
|
||||
|
||||
"""A circuit operation which, when encountered, jumps to the end of the nearest enclosing loop.
|
||||
Can only be used inside loops.
|
||||
"""
|
||||
|
||||
def __init__(self, num_qubits: int, num_clbits: int, label: Optional[str] = None):
|
||||
"""
|
||||
Args:
|
||||
num_qubits: the number of qubits this affects.
|
||||
num_clbits: the number of qubits this affects.
|
||||
label: an optional string label for the instruction.
|
||||
"""
|
||||
super().__init__("break_loop", num_qubits, num_clbits, [], label=label)
|
||||
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ class CircuitScopeInterface(abc.ABC):
|
|||
|
||||
@abc.abstractmethod
|
||||
def use_var(self, var: expr.Var):
|
||||
"""Called for every standalone classical runtime variable being used by some circuit
|
||||
"""Called for every standalone classical real-time variable being used by some circuit
|
||||
instruction.
|
||||
|
||||
The given variable is guaranteed to be a stand-alone variable; bit-like resource-wrapping
|
||||
|
|
|
@ -19,31 +19,17 @@ from .builder import InstructionPlaceholder, InstructionResources
|
|||
|
||||
|
||||
class ContinueLoopOp(Instruction):
|
||||
"""A circuit operation which, when encountered, moves to the next iteration of
|
||||
the nearest enclosing loop.
|
||||
|
||||
.. note::
|
||||
|
||||
Can be inserted only within the body of a loop op, and must span the full
|
||||
width of that block.
|
||||
|
||||
**Circuit symbol:**
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
┌─────────────────┐
|
||||
q_0: ┤0 ├
|
||||
│ │
|
||||
q_1: ┤1 ├
|
||||
│ continue_loop │
|
||||
q_2: ┤2 ├
|
||||
│ │
|
||||
c_0: ╡0 ╞
|
||||
└─────────────────┘
|
||||
|
||||
"""A circuit operation which, when encountered, moves to the next iteration of the nearest
|
||||
enclosing loop. Can only be used inside loops.
|
||||
"""
|
||||
|
||||
def __init__(self, num_qubits: int, num_clbits: int, label: Optional[str] = None):
|
||||
"""
|
||||
Args:
|
||||
num_qubits: the number of qubits this affects.
|
||||
num_clbits: the number of qubits this affects.
|
||||
label: an optional string label for the instruction.
|
||||
"""
|
||||
super().__init__("continue_loop", num_qubits, num_clbits, [], label=label)
|
||||
|
||||
|
||||
|
|
|
@ -25,7 +25,12 @@ if typing.TYPE_CHECKING:
|
|||
|
||||
|
||||
class ControlFlowOp(Instruction, ABC):
|
||||
"""Abstract class to encapsulate all control flow operations."""
|
||||
"""Abstract class to encapsulate all control flow operations.
|
||||
|
||||
All subclasses of :class:`ControlFlowOp` have an internal attribute,
|
||||
:attr:`~ControlFlowOp.blocks`, which exposes the inner subcircuits used in the different blocks
|
||||
of the control flow.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
@ -36,17 +41,34 @@ class ControlFlowOp(Instruction, ABC):
|
|||
@property
|
||||
@abstractmethod
|
||||
def blocks(self) -> tuple[QuantumCircuit, ...]:
|
||||
"""Tuple of QuantumCircuits which may be executed as part of the
|
||||
execution of this ControlFlowOp. May be parameterized by a loop
|
||||
parameter to be resolved at run time.
|
||||
"""
|
||||
"""Tuple of :class:`.QuantumCircuit`\\ s which may be executed as part of the
|
||||
execution of this :class:`ControlFlowOp`."""
|
||||
|
||||
@abstractmethod
|
||||
def replace_blocks(self, blocks: typing.Iterable[QuantumCircuit]) -> ControlFlowOp:
|
||||
"""Replace blocks and return new instruction.
|
||||
"""Return a new version of this control-flow operations with the :attr:`blocks` mapped to
|
||||
the given new ones.
|
||||
|
||||
Typically this is used in a workflow such as::
|
||||
|
||||
existing_op = ...
|
||||
|
||||
def map_block(block: QuantumCircuit) -> QuantumCircuit:
|
||||
new_block = block.copy_empty_like()
|
||||
# ... do something to `new_block` ...
|
||||
return new_block
|
||||
|
||||
new_op = existing_op.replace_blocks(
|
||||
map_block(block) for block in existing_op.blocks
|
||||
)
|
||||
|
||||
It is the caller's responsibility to ensure that the mapped blocks are defined over a
|
||||
unified set of circuit resources, much like constructing a :class:`ControlFlowOp` using its
|
||||
default constructor.
|
||||
|
||||
Args:
|
||||
blocks: Tuple of QuantumCircuits to replace in instruction.
|
||||
blocks: the new subcircuit blocks to use.
|
||||
|
||||
Returns:
|
||||
New ControlFlowOp with replaced blocks.
|
||||
New :class:`ControlFlowOp` with replaced blocks.
|
||||
"""
|
||||
|
|
|
@ -29,28 +29,6 @@ class ForLoopOp(ControlFlowOp):
|
|||
"""A circuit operation which repeatedly executes a subcircuit
|
||||
(``body``) parameterized by a parameter ``loop_parameter`` through
|
||||
the set of integer values provided in ``indexset``.
|
||||
|
||||
Parameters:
|
||||
indexset: A collection of integers to loop over.
|
||||
loop_parameter: The placeholder parameterizing ``body`` to which
|
||||
the values from ``indexset`` will be assigned.
|
||||
body: The loop body to be repeatedly executed.
|
||||
label: An optional label for identifying the instruction.
|
||||
|
||||
**Circuit symbol:**
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
┌───────────┐
|
||||
q_0: ┤0 ├
|
||||
│ │
|
||||
q_1: ┤1 ├
|
||||
│ for_loop │
|
||||
q_2: ┤2 ├
|
||||
│ │
|
||||
c_0: ╡0 ╞
|
||||
└───────────┘
|
||||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
@ -60,9 +38,16 @@ class ForLoopOp(ControlFlowOp):
|
|||
body: QuantumCircuit,
|
||||
label: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
indexset: A collection of integers to loop over.
|
||||
loop_parameter: The placeholder parameterizing ``body`` to which
|
||||
the values from ``indexset`` will be assigned.
|
||||
body: The loop body to be repeatedly executed.
|
||||
label: An optional label for identifying the instruction.
|
||||
"""
|
||||
num_qubits = body.num_qubits
|
||||
num_clbits = body.num_clbits
|
||||
|
||||
super().__init__(
|
||||
"for_loop", num_qubits, num_clbits, [indexset, loop_parameter, body], label=label
|
||||
)
|
||||
|
|
|
@ -44,38 +44,11 @@ class IfElseOp(ControlFlowOp):
|
|||
provided condition (``condition``) evaluates to true, and
|
||||
optionally evaluates another program (``false_body``) otherwise.
|
||||
|
||||
Parameters:
|
||||
condition: A condition to be evaluated at circuit runtime which,
|
||||
if true, will trigger the evaluation of ``true_body``. Can be
|
||||
specified as either a tuple of a ``ClassicalRegister`` to be
|
||||
tested for equality with a given ``int``, or as a tuple of a
|
||||
``Clbit`` to be compared to either a ``bool`` or an ``int``.
|
||||
true_body: A program to be executed if ``condition`` evaluates
|
||||
to true.
|
||||
false_body: A optional program to be executed if ``condition``
|
||||
evaluates to false.
|
||||
label: An optional label for identifying the instruction.
|
||||
|
||||
If provided, ``false_body`` must be of the same ``num_qubits`` and
|
||||
``num_clbits`` as ``true_body``.
|
||||
|
||||
The classical bits used in ``condition`` must be a subset of those attached
|
||||
to the circuit on which this ``IfElseOp`` will be appended.
|
||||
|
||||
**Circuit symbol:**
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
┌───────────┐
|
||||
q_0: ┤0 ├
|
||||
│ │
|
||||
q_1: ┤1 ├
|
||||
│ if_else │
|
||||
q_2: ┤2 ├
|
||||
│ │
|
||||
c_0: ╡0 ╞
|
||||
└───────────┘
|
||||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
@ -85,6 +58,19 @@ class IfElseOp(ControlFlowOp):
|
|||
false_body: QuantumCircuit | None = None,
|
||||
label: str | None = None,
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
condition: A condition to be evaluated in real time during circuit execution which,
|
||||
if true, will trigger the evaluation of ``true_body``. Can be
|
||||
specified as either a tuple of a ``ClassicalRegister`` to be
|
||||
tested for equality with a given ``int``, or as a tuple of a
|
||||
``Clbit`` to be compared to either a ``bool`` or an ``int``.
|
||||
true_body: A program to be executed if ``condition`` evaluates
|
||||
to true.
|
||||
false_body: A optional program to be executed if ``condition``
|
||||
evaluates to false.
|
||||
label: An optional label for identifying the instruction.
|
||||
"""
|
||||
# pylint: disable=cyclic-import
|
||||
from qiskit.circuit import QuantumCircuit
|
||||
|
||||
|
|
|
@ -32,39 +32,25 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class _DefaultCaseType:
|
||||
"""The type of the default-case singleton. This is used instead of just having
|
||||
``CASE_DEFAULT = object()`` so we can set the pretty-printing properties, which are class-level
|
||||
only."""
|
||||
# Note: Sphinx uses the docstring of this singleton class object as the documentation of the
|
||||
# `CASE_DEFAULT` object.
|
||||
|
||||
"""A special object that represents the "default" case of a switch statement. If you use this
|
||||
as a case target, it must be the last case, and will match anything that wasn't already matched.
|
||||
When using the builder interface of :meth:`.QuantumCircuit.switch`, this can also be accessed as
|
||||
the ``DEFAULT`` attribute of the bound case-builder object."""
|
||||
|
||||
def __repr__(self):
|
||||
return "<default case>"
|
||||
|
||||
|
||||
CASE_DEFAULT = _DefaultCaseType()
|
||||
"""A special object that represents the "default" case of a switch statement. If you use this
|
||||
as a case target, it must be the last case, and will match anything that wasn't already matched.
|
||||
When using the builder interface of :meth:`.QuantumCircuit.switch`, this can also be accessed as the
|
||||
``DEFAULT`` attribute of the bound case-builder object."""
|
||||
|
||||
|
||||
class SwitchCaseOp(ControlFlowOp):
|
||||
"""A circuit operation that executes one particular circuit block based on matching a given
|
||||
``target`` against an ordered list of ``values``. The special value :data:`.CASE_DEFAULT` can
|
||||
be used to represent a default condition.
|
||||
|
||||
This is the low-level interface for creating a switch-case statement; in general, the circuit
|
||||
method :meth:`.QuantumCircuit.switch` should be used as a context manager to access the
|
||||
builder interface. At the low level, you must ensure that all the circuit blocks contain equal
|
||||
numbers of qubits and clbits, and that the order the virtual bits of the containing circuit
|
||||
should be bound is the same for all blocks. This will likely mean that each circuit block is
|
||||
wider than its natural width, as each block must span the union of all the spaces covered by
|
||||
*any* of the blocks.
|
||||
|
||||
Args:
|
||||
target: the runtime value to switch on.
|
||||
cases: an ordered iterable of the corresponding value of the ``target`` and the circuit
|
||||
block that should be executed if this is matched. There is no fall-through between
|
||||
blocks, and the order matters.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
@ -74,6 +60,13 @@ class SwitchCaseOp(ControlFlowOp):
|
|||
*,
|
||||
label: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
target: the real-time value to switch on.
|
||||
cases: an ordered iterable of the corresponding value of the ``target`` and the circuit
|
||||
block that should be executed if this is matched. There is no fall-through between
|
||||
blocks, and the order matters.
|
||||
"""
|
||||
# pylint: disable=cyclic-import
|
||||
from qiskit.circuit import QuantumCircuit
|
||||
|
||||
|
|
|
@ -30,31 +30,8 @@ class WhileLoopOp(ControlFlowOp):
|
|||
"""A circuit operation which repeatedly executes a subcircuit (``body``) until
|
||||
a condition (``condition``) evaluates as False.
|
||||
|
||||
Parameters:
|
||||
condition: A condition to be checked prior to executing ``body``. Can be
|
||||
specified as either a tuple of a ``ClassicalRegister`` to be tested
|
||||
for equality with a given ``int``, or as a tuple of a ``Clbit`` to
|
||||
be compared to either a ``bool`` or an ``int``.
|
||||
body: The loop body to be repeatedly executed.
|
||||
label: An optional label for identifying the instruction.
|
||||
|
||||
The classical bits used in ``condition`` must be a subset of those attached
|
||||
to ``body``.
|
||||
|
||||
**Circuit symbol:**
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
┌─────────────┐
|
||||
q_0: ┤0 ├
|
||||
│ │
|
||||
q_1: ┤1 ├
|
||||
│ while_loop │
|
||||
q_2: ┤2 ├
|
||||
│ │
|
||||
c_0: ╡0 ╞
|
||||
└─────────────┘
|
||||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
@ -63,6 +40,15 @@ class WhileLoopOp(ControlFlowOp):
|
|||
body: QuantumCircuit,
|
||||
label: str | None = None,
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
condition: A condition to be checked prior to executing ``body``. Can be
|
||||
specified as either a tuple of a ``ClassicalRegister`` to be tested
|
||||
for equality with a given ``int``, or as a tuple of a ``Clbit`` to
|
||||
be compared to either a ``bool`` or an ``int``.
|
||||
body: The loop body to be repeatedly executed.
|
||||
label: An optional label for identifying the instruction.
|
||||
"""
|
||||
num_qubits = body.num_qubits
|
||||
num_clbits = body.num_clbits
|
||||
|
||||
|
|
|
@ -111,9 +111,9 @@ class ControlledGate(Gate):
|
|||
@property
|
||||
def definition(self) -> QuantumCircuit:
|
||||
"""Return definition in terms of other basic gates. If the gate has
|
||||
open controls, as determined from `self.ctrl_state`, the returned
|
||||
open controls, as determined from :attr:`ctrl_state`, the returned
|
||||
definition is conjugated with X without changing the internal
|
||||
`_definition`.
|
||||
``_definition``.
|
||||
"""
|
||||
if self._open_ctrl:
|
||||
closed_gate = self.to_mutable()
|
||||
|
|
|
@ -24,7 +24,11 @@ class Delay(Instruction):
|
|||
"""Do nothing and just delay/wait/idle for a specified duration."""
|
||||
|
||||
def __init__(self, duration, unit="dt"):
|
||||
"""Create new delay instruction."""
|
||||
"""
|
||||
Args:
|
||||
duration: the length of time of the duration. Given in units of ``unit``.
|
||||
unit: the unit of the duration. Must be ``"dt"`` or an SI-prefixed seconds unit.
|
||||
"""
|
||||
if unit not in {"s", "ms", "us", "ns", "ps", "dt"}:
|
||||
raise CircuitError("Unknown unit %s is specified." % unit)
|
||||
|
||||
|
|
|
@ -268,12 +268,17 @@ class Instruction(Operation):
|
|||
return True
|
||||
|
||||
def _define(self):
|
||||
"""Populates self.definition with a decomposition of this gate."""
|
||||
"""Populate the cached :attr:`_definition` field of this :class:`Instruction`.
|
||||
|
||||
Subclasses should implement this method to provide lazy construction of their public
|
||||
:attr:`definition` attribute. A subclass can use its :attr:`params` at the time of the
|
||||
call. The method should populate :attr:`_definition` with a :class:`.QuantumCircuit` and
|
||||
not return a value."""
|
||||
pass
|
||||
|
||||
@property
|
||||
def params(self):
|
||||
"""return instruction params."""
|
||||
"""The parameters of this :class:`Instruction`. Ideally these will be gate angles."""
|
||||
return self._params
|
||||
|
||||
@params.setter
|
||||
|
@ -290,7 +295,8 @@ class Instruction(Operation):
|
|||
return parameter
|
||||
|
||||
def is_parameterized(self):
|
||||
"""Return True .IFF. instruction is parameterized else False"""
|
||||
"""Return whether the :class:`Instruction` contains :ref:`compile-time parameters
|
||||
<circuit-compile-time-parameters>`."""
|
||||
return any(
|
||||
isinstance(param, ParameterExpression) and param.parameters for param in self.params
|
||||
)
|
||||
|
|
|
@ -87,7 +87,11 @@ class InstructionSet:
|
|||
self._instructions.append((data, pos))
|
||||
|
||||
def inverse(self, annotated: bool = False):
|
||||
"""Invert all instructions."""
|
||||
"""Invert all instructions.
|
||||
|
||||
.. note::
|
||||
It is preferable to take the inverse *before* appending the gate(s) to the circuit.
|
||||
"""
|
||||
for i, instruction in enumerate(self._instructions):
|
||||
if isinstance(instruction, CircuitInstruction):
|
||||
self._instructions[i] = instruction.replace(
|
||||
|
@ -105,6 +109,10 @@ class InstructionSet:
|
|||
"""Set a classical equality condition on all the instructions in this set between the
|
||||
:obj:`.ClassicalRegister` or :obj:`.Clbit` ``classical`` and value ``val``.
|
||||
|
||||
.. note::
|
||||
You should prefer to use the :meth:`.QuantumCircuit.if_test` builder interface, rather
|
||||
than using this method.
|
||||
|
||||
.. note::
|
||||
|
||||
This is a setter method, not an additive one. Calling this multiple times will silently
|
||||
|
@ -124,27 +132,6 @@ class InstructionSet:
|
|||
Raises:
|
||||
CircuitError: if the passed classical resource is invalid, or otherwise not resolvable
|
||||
to a concrete resource that these instructions are permitted to access.
|
||||
|
||||
Example:
|
||||
.. plot::
|
||||
:include-source:
|
||||
|
||||
from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit
|
||||
|
||||
qr = QuantumRegister(2)
|
||||
cr = ClassicalRegister(2)
|
||||
qc = QuantumCircuit(qr, cr)
|
||||
qc.h(range(2))
|
||||
qc.measure(range(2), range(2))
|
||||
|
||||
# apply x gate if the classical register has the value 2 (10 in binary)
|
||||
qc.x(0).c_if(cr, 2)
|
||||
|
||||
# apply y gate if bit 0 is set to 1
|
||||
qc.y(1).c_if(0, 1)
|
||||
|
||||
qc.draw('mpl')
|
||||
|
||||
"""
|
||||
if self._requester is None and not isinstance(classical, (Clbit, ClassicalRegister)):
|
||||
raise CircuitError(
|
||||
|
|
|
@ -137,8 +137,11 @@ Directives are operations to the quantum stack that are meant to be interpreted
|
|||
the transpiler. In general, the transpiler or backend might optionally ignore them if there is no
|
||||
implementation for them.
|
||||
|
||||
..
|
||||
This summary table deliberately does not generate toctree entries; these directives are "owned"
|
||||
by ``qiskit.circuit``.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: ../stubs/
|
||||
|
||||
Barrier
|
||||
|
||||
|
@ -147,8 +150,11 @@ Standard Operations
|
|||
|
||||
Operations are non-reversible changes in the quantum state of the circuit.
|
||||
|
||||
..
|
||||
This summary table deliberately does not generate toctree entries; these directives are "owned"
|
||||
by ``qiskit.circuit``.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: ../stubs/
|
||||
|
||||
Measure
|
||||
Reset
|
||||
|
|
|
@ -22,7 +22,10 @@ class Measure(SingletonInstruction):
|
|||
"""Quantum measurement in the computational basis."""
|
||||
|
||||
def __init__(self, label=None, *, duration=None, unit="dt"):
|
||||
"""Create new measurement instruction."""
|
||||
"""
|
||||
Args:
|
||||
label: optional string label for this instruction.
|
||||
"""
|
||||
super().__init__("measure", 1, 1, [], label=label, duration=duration, unit=unit)
|
||||
|
||||
_singleton_lookup_key = stdlib_singleton_key()
|
||||
|
|
|
@ -16,17 +16,22 @@ from abc import ABC, abstractmethod
|
|||
|
||||
|
||||
class Operation(ABC):
|
||||
"""Quantum Operation Interface Class.
|
||||
For objects that can be added to a :class:`~qiskit.circuit.QuantumCircuit`.
|
||||
These objects include :class:`~qiskit.circuit.Gate`, :class:`~qiskit.circuit.Reset`,
|
||||
:class:`~qiskit.circuit.Barrier`, :class:`~qiskit.circuit.Measure`,
|
||||
and operators such as :class:`~qiskit.quantum_info.Clifford`.
|
||||
The main purpose is to add an :class:`~qiskit.circuit.Operation` to a
|
||||
:class:`~qiskit.circuit.QuantumCircuit` without synthesizing it before the transpilation.
|
||||
"""Quantum operation interface.
|
||||
|
||||
The minimal interface that any object must fulfil in order to be added to a
|
||||
:class:`.QuantumCircuit`.
|
||||
|
||||
Concrete instances of this interface include :class:`~qiskit.circuit.Gate`,
|
||||
:class:`~qiskit.circuit.Reset`, :class:`~qiskit.circuit.Barrier`,
|
||||
:class:`~qiskit.circuit.Measure`, and operators such as :class:`~qiskit.quantum_info.Clifford`.
|
||||
|
||||
The main purpose is to add allow abstract mathematical objects to be added directly onto
|
||||
abstract circuits, and for the exact syntheses of these to be determined later, during
|
||||
compilation.
|
||||
|
||||
Example:
|
||||
|
||||
Add a Clifford and a Toffoli gate to a QuantumCircuit.
|
||||
Add a Clifford and a Toffoli gate to a :class:`QuantumCircuit`.
|
||||
|
||||
.. plot::
|
||||
:include-source:
|
||||
|
|
|
@ -25,10 +25,16 @@ from .parameterexpression import ParameterExpression
|
|||
|
||||
|
||||
class Parameter(ParameterExpression):
|
||||
"""Parameter Class for variable parameters.
|
||||
"""A compile-time symbolic parameter.
|
||||
|
||||
A parameter is a variable value that is not required to be fixed
|
||||
at circuit definition.
|
||||
The value of a :class:`Parameter` must be entirely determined before a circuit begins execution.
|
||||
Typically this will mean that you should supply values for all :class:`Parameter`\\ s in a
|
||||
circuit using :meth:`.QuantumCircuit.assign_parameters`, though certain hardware vendors may
|
||||
allow you to give them a circuit in terms of these parameters, provided you also pass the values
|
||||
separately.
|
||||
|
||||
This is the atom of :class:`.ParameterExpression`, and is itself an expression. The numeric
|
||||
value of a parameter need not be fixed while the circuit is being defined.
|
||||
|
||||
Examples:
|
||||
|
||||
|
@ -62,11 +68,10 @@ class Parameter(ParameterExpression):
|
|||
def __init__(
|
||||
self, name: str, *, uuid: UUID | None = None
|
||||
): # pylint: disable=super-init-not-called
|
||||
"""Create a new named :class:`Parameter`.
|
||||
|
||||
"""
|
||||
Args:
|
||||
name: name of the ``Parameter``, used for visual representation. This can
|
||||
be any unicode string, e.g. "ϕ".
|
||||
be any Unicode string, e.g. "ϕ".
|
||||
uuid: For advanced usage only. Override the UUID of this parameter, in order to make it
|
||||
compare equal to some other parameter object. By default, two parameters with the
|
||||
same name do not compare equal to help catch shadowing bugs when two circuits
|
||||
|
|
|
@ -144,7 +144,7 @@ class QuantumCircuit:
|
|||
circuit. This gets stored as free-form data in a dict in the
|
||||
:attr:`~qiskit.circuit.QuantumCircuit.metadata` attribute. It will
|
||||
not be directly used in the circuit.
|
||||
inputs: any variables to declare as ``input`` runtime variables for this circuit. These
|
||||
inputs: any variables to declare as ``input`` real-time variables for this circuit. These
|
||||
should already be existing :class:`.expr.Var` nodes that you build from somewhere else;
|
||||
if you need to create the inputs as well, use :meth:`QuantumCircuit.add_input`. The
|
||||
variables given in this argument will be passed directly to :meth:`add_input`. A
|
||||
|
@ -1171,14 +1171,14 @@ class QuantumCircuit:
|
|||
|
||||
@property
|
||||
def num_vars(self) -> int:
|
||||
"""The number of runtime classical variables in the circuit.
|
||||
"""The number of real-time classical variables in the circuit.
|
||||
|
||||
This is the length of the :meth:`iter_vars` iterable."""
|
||||
return self.num_input_vars + self.num_captured_vars + self.num_declared_vars
|
||||
|
||||
@property
|
||||
def num_input_vars(self) -> int:
|
||||
"""The number of runtime classical variables in the circuit marked as circuit inputs.
|
||||
"""The number of real-time classical variables in the circuit marked as circuit inputs.
|
||||
|
||||
This is the length of the :meth:`iter_input_vars` iterable. If this is non-zero,
|
||||
:attr:`num_captured_vars` must be zero."""
|
||||
|
@ -1186,7 +1186,7 @@ class QuantumCircuit:
|
|||
|
||||
@property
|
||||
def num_captured_vars(self) -> int:
|
||||
"""The number of runtime classical variables in the circuit marked as captured from an
|
||||
"""The number of real-time classical variables in the circuit marked as captured from an
|
||||
enclosing scope.
|
||||
|
||||
This is the length of the :meth:`iter_captured_vars` iterable. If this is non-zero,
|
||||
|
@ -1195,14 +1195,14 @@ class QuantumCircuit:
|
|||
|
||||
@property
|
||||
def num_declared_vars(self) -> int:
|
||||
"""The number of runtime classical variables in the circuit that are declared by this
|
||||
"""The number of real-time classical variables in the circuit that are declared by this
|
||||
circuit scope, excluding inputs or captures.
|
||||
|
||||
This is the length of the :meth:`iter_declared_vars` iterable."""
|
||||
return len(self._vars_local)
|
||||
|
||||
def iter_vars(self) -> typing.Iterable[expr.Var]:
|
||||
"""Get an iterable over all runtime classical variables in scope within this circuit.
|
||||
"""Get an iterable over all real-time classical variables in scope within this circuit.
|
||||
|
||||
This method will iterate over all variables in scope. For more fine-grained iterators, see
|
||||
:meth:`iter_declared_vars`, :meth:`iter_input_vars` and :meth:`iter_captured_vars`."""
|
||||
|
@ -1214,7 +1214,7 @@ class QuantumCircuit:
|
|||
)
|
||||
|
||||
def iter_declared_vars(self) -> typing.Iterable[expr.Var]:
|
||||
"""Get an iterable over all runtime classical variables that are declared with automatic
|
||||
"""Get an iterable over all real-time classical variables that are declared with automatic
|
||||
storage duration in this scope. This excludes input variables (see :meth:`iter_input_vars`)
|
||||
and captured variables (see :meth:`iter_captured_vars`)."""
|
||||
if self._control_flow_scopes:
|
||||
|
@ -1222,15 +1222,15 @@ class QuantumCircuit:
|
|||
return self._vars_local.values()
|
||||
|
||||
def iter_input_vars(self) -> typing.Iterable[expr.Var]:
|
||||
"""Get an iterable over all runtime classical variables that are declared as inputs to this
|
||||
circuit scope. This excludes locally declared variables (see :meth:`iter_declared_vars`)
|
||||
and captured variables (see :meth:`iter_captured_vars`)."""
|
||||
"""Get an iterable over all real-time classical variables that are declared as inputs to
|
||||
this circuit scope. This excludes locally declared variables (see
|
||||
:meth:`iter_declared_vars`) and captured variables (see :meth:`iter_captured_vars`)."""
|
||||
if self._control_flow_scopes:
|
||||
return ()
|
||||
return self._vars_input.values()
|
||||
|
||||
def iter_captured_vars(self) -> typing.Iterable[expr.Var]:
|
||||
"""Get an iterable over all runtime classical variables that are captured by this circuit
|
||||
"""Get an iterable over all real-time classical variables that are captured by this circuit
|
||||
scope from a containing scope. This excludes input variables (see :meth:`iter_input_vars`)
|
||||
and locally declared variables (see :meth:`iter_declared_vars`)."""
|
||||
if self._control_flow_scopes:
|
||||
|
@ -1730,8 +1730,8 @@ class QuantumCircuit:
|
|||
qc.cx(0, i)
|
||||
qc.measure(range(8), cr2)
|
||||
|
||||
# Now when we add the variable, it is initialized using the runtime state of the two
|
||||
# classical registers we measured into above.
|
||||
# Now when we add the variable, it is initialized using the real-time state of the
|
||||
# two classical registers we measured into above.
|
||||
qc.add_var(my_var, expr.bit_and(cr1, cr2))
|
||||
"""
|
||||
# Validate the initialiser first to catch cases where the variable to be declared is being
|
||||
|
@ -2619,7 +2619,7 @@ class QuantumCircuit:
|
|||
return self.append(Reset(), [qubit], [])
|
||||
|
||||
def store(self, lvalue: typing.Any, rvalue: typing.Any, /) -> InstructionSet:
|
||||
"""Store the result of the given runtime classical expression ``rvalue`` in the memory
|
||||
"""Store the result of the given real-time classical expression ``rvalue`` in the memory
|
||||
location defined by ``lvalue``.
|
||||
|
||||
Typically ``lvalue`` will be a :class:`~.expr.Var` node and ``rvalue`` will be some
|
||||
|
@ -2631,7 +2631,7 @@ class QuantumCircuit:
|
|||
a :class:`~.expr.Var` node, but you can also write to :class:`.Clbit` or
|
||||
:class:`.ClassicalRegister` memory locations if your hardware supports it. The
|
||||
memory location must already be present in the circuit.
|
||||
rvalue: a runtime classical expression whose result should be written into the given
|
||||
rvalue: a real-time classical expression whose result should be written into the given
|
||||
memory location.
|
||||
|
||||
.. seealso::
|
||||
|
@ -5023,11 +5023,11 @@ class QuantumCircuit:
|
|||
qc.z(2)
|
||||
|
||||
Args:
|
||||
condition (Tuple[Union[ClassicalRegister, Clbit], int]): A condition to be evaluated at
|
||||
circuit runtime which, if true, will trigger the evaluation of ``true_body``. Can be
|
||||
specified as either a tuple of a ``ClassicalRegister`` to be tested for equality
|
||||
with a given ``int``, or as a tuple of a ``Clbit`` to be compared to either a
|
||||
``bool`` or an ``int``.
|
||||
condition (Tuple[Union[ClassicalRegister, Clbit], int]): A condition to be evaluated in
|
||||
real time during circuit execution, which, if true, will trigger the evaluation of
|
||||
``true_body``. Can be specified as either a tuple of a ``ClassicalRegister`` to be
|
||||
tested for equality with a given ``int``, or as a tuple of a ``Clbit`` to be
|
||||
compared to either a ``bool`` or an ``int``.
|
||||
true_body (Optional[QuantumCircuit]): The circuit body to be run if ``condition`` is
|
||||
true.
|
||||
qubits (Optional[Sequence[QubitSpecifier]]): The circuit qubits over which the if/else
|
||||
|
@ -5099,7 +5099,7 @@ class QuantumCircuit:
|
|||
qc.x(0)
|
||||
|
||||
Args:
|
||||
condition: A condition to be evaluated at circuit runtime which,
|
||||
condition: A condition to be evaluated in real time at circuit execution, which,
|
||||
if true, will trigger the evaluation of ``true_body``. Can be
|
||||
specified as either a tuple of a ``ClassicalRegister`` to be
|
||||
tested for equality with a given ``int``, or as a tuple of a
|
||||
|
|
|
@ -18,10 +18,13 @@ from qiskit.circuit.singleton import SingletonInstruction, stdlib_singleton_key
|
|||
|
||||
|
||||
class Reset(SingletonInstruction):
|
||||
"""Qubit reset."""
|
||||
r"""Incoherently reset a qubit to the :math:`\lvert0\rangle` state."""
|
||||
|
||||
def __init__(self, label=None, *, duration=None, unit="dt"):
|
||||
"""Create new reset instruction."""
|
||||
"""
|
||||
Args:
|
||||
label: optional string label of this instruction.
|
||||
"""
|
||||
super().__init__("reset", 1, 0, [], label=label, duration=duration, unit=unit)
|
||||
|
||||
_singleton_lookup_key = stdlib_singleton_key()
|
||||
|
|
|
@ -57,10 +57,14 @@ class Store(Instruction):
|
|||
|
||||
This is a low-level primitive of the classical-expression handling (similar to how
|
||||
:class:`~.circuit.Measure` is a primitive for quantum measurement), and is not safe for
|
||||
subclassing. It is likely to become a special-case instruction in later versions of Qiskit
|
||||
circuit and compiler internal representations."""
|
||||
subclassing."""
|
||||
|
||||
def __init__(self, lvalue: expr.Expr, rvalue: expr.Expr):
|
||||
"""
|
||||
Args:
|
||||
lvalue: the memory location being stored into.
|
||||
rvalue: the expression result being stored.
|
||||
"""
|
||||
if not expr.is_lvalue(lvalue):
|
||||
raise CircuitError(f"'{lvalue}' is not an l-value")
|
||||
|
||||
|
@ -82,6 +86,7 @@ class Store(Instruction):
|
|||
return self.params[1]
|
||||
|
||||
def c_if(self, classical, val):
|
||||
""":meta hidden:"""
|
||||
raise NotImplementedError(
|
||||
"stores cannot be conditioned with `c_if`; use a full `if_test` context instead"
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue