Skip to content

Commit

Permalink
Add release notes for manual Var and Store (Qiskit#12421)
Browse files Browse the repository at this point in the history
* Add release notes for manual `Var` and `Store`

This adds the release notes and updates some small portions of
documentation that were previously missed surrounding the new manual
`Var` storage locations.

This includes documenting all new keyword arguments to methods, upgrade
instructions for providers, and adding the `Var.new` method to the
documentation, which was previously erroneously omitted.

* Fix Sphinx typo

* Fix another Sphinx typo

* Move QPY version bump to upgrade

* Unify base release note

* Reword providers upgrade note

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>

---------

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
  • Loading branch information
jakelishman and mtreinish committed May 16, 2024
1 parent 72ad545 commit 554e661
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 2 deletions.
2 changes: 1 addition & 1 deletion qiskit/circuit/classical/expr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
real-time variable, or a wrapper around a :class:`.Clbit` or :class:`.ClassicalRegister`.
.. autoclass:: Var
:members: var, name
:members: var, name, new
Similarly, literals used in expressions (such as integers) should be lifted to :class:`Value` nodes
with associated types.
Expand Down
39 changes: 38 additions & 1 deletion qiskit/providers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,8 +452,45 @@ def get_translation_stage_plugin(self):
efficient output on ``Mybackend`` the transpiler will be able to perform these
custom steps without any manual user input.
.. _providers-guide-real-time-variables:
Real-time variables
^^^^^^^^^^^^^^^^^^^
The transpiler will automatically handle real-time typed classical variables (see
:mod:`qiskit.circuit.classical`) and treat the :class:`.Store` instruction as a built-in
"directive", similar to :class:`.Barrier`. No special handling from backends is necessary to permit
this.
If your backend is *unable* to handle classical variables and storage, we recommend that you comment
on this in your documentation, and insert a check into your :meth:`~.BackendV2.run` method (see
:ref:`providers-guide-backend-run`) to eagerly reject circuits containing them. You can examine
:attr:`.QuantumCircuit.num_vars` for the presence of variables at the top level. If you accept
:ref:`control-flow operations <circuit-control-flow-repr>`, you might need to recursively search the
internal :attr:`~.ControlFlowOp.blocks` of each for scope-local variables with
:attr:`.QuantumCircuit.num_declared_vars`.
For example, a function to check for the presence of any manual storage locations, or manual stores
to memory::
from qiskit.circuit import Store, ControlFlowOp, QuantumCircuit
def has_realtime_logic(circuit: QuantumCircuit) -> bool:
if circuit.num_vars:
return True
for instruction in circuit.data:
if isinstance(instruction.operation, Store):
return True
elif isinstance(instruction.operation, ControlFlowOp):
for block in instruction.operation.blocks:
if has_realtime_logic(block):
return True
return False
.. _providers-guide-backend-run:
Backend.run Method
--------------------
------------------
Of key importance is the :meth:`~qiskit.providers.BackendV2.run` method, which
is used to actually submit circuits to a device or simulator. The run method
Expand Down
13 changes: 13 additions & 0 deletions releasenotes/notes/1.1/classical-store-e64ee1286219a862.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,16 @@ features_circuits:
Variables can be used wherever classical expressions (see :mod:`qiskit.circuit.classical.expr`)
are valid. Currently this is the target expressions of control-flow operations, though we plan
to expand this to gate parameters in the future, as the type and expression system are expanded.
See :ref:`circuit-repr-real-time-classical` for more discussion of these variables, and the
associated data model.
These are supported throughout the transpiler, through QPY serialization (:mod:`qiskit.qpy`),
OpenQASM 3 export (:mod:`qiskit.qasm3`), and have initial support through the circuit visualizers
(see :meth:`.QuantumCircuit.draw`).
.. note::
The new classical variables and storage will take some time to become supported on hardware
and simulator backends. They are not supported in the primitives interfaces
(:mod:`qiskit.primitives`), but will likely inform those interfaces as they evolve.
122 changes: 122 additions & 0 deletions releasenotes/notes/storage-var-a00a33fcf9a71f3f.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
---
features_circuits:
- |
:class:`.QuantumCircuit` has several new methods to work with and inspect manual :class:`.Var`
variables.
See :ref:`circuit-real-time-methods` for more in-depth discussion on all of these.
The new methods are:
* :meth:`~.QuantumCircuit.add_var`
* :meth:`~.QuantumCircuit.add_input`
* :meth:`~.QuantumCircuit.add_capture`
* :meth:`~.QuantumCircuit.add_uninitialized_var`
* :meth:`~.QuantumCircuit.get_var`
* :meth:`~.QuantumCircuit.has_var`
* :meth:`~.QuantumCircuit.iter_vars`
* :meth:`~.QuantumCircuit.iter_declared_vars`
* :meth:`~.QuantumCircuit.iter_captured_vars`
* :meth:`~.QuantumCircuit.iter_input_vars`
* :meth:`~.QuantumCircuit.store`
In addition, there are several new dynamic attributes on :class:`.QuantumCircuit` surrounding
these variables:
* :attr:`~.QuantumCircuit.num_vars`
* :attr:`~.QuantumCircuit.num_input_vars`
* :attr:`~.QuantumCircuit.num_captured_vars`
* :attr:`~.QuantumCircuit.num_declared_vars`
- |
:class:`.ControlFlowOp` and its subclasses now have a :meth:`~.ControlFlowOp.iter_captured_vars`
method, which will return an iterator over the unique variables captured in any of its immediate
blocks.
- |
:class:`.DAGCircuit` has several new methods to work with and inspect manual :class:`.Var`
variables. These are largely equivalent to their :class:`.QuantumCircuit` counterparts, except
that the :class:`.DAGCircuit` ones are optimized for programmatic access with already defined
objects, while the :class:`.QuantumCircuit` methods are more focussed on interactive human use.
The new methods are:
* :meth:`~.DAGCircuit.add_input_var`
* :meth:`~.DAGCircuit.add_captured_var`
* :meth:`~.DAGCircuit.add_declared_var`
* :meth:`~.DAGCircuit.has_var`
* :meth:`~.DAGCircuit.iter_vars`
* :meth:`~.DAGCircuit.iter_declared_vars`
* :meth:`~.DAGCircuit.iter_captured_vars`
* :meth:`~.DAGCircuit.iter_input_vars`
There are also new public attributes:
* :attr:`~.DAGCircuit.num_vars`
* :attr:`~.DAGCircuit.num_input_vars`
* :attr:`~.DAGCircuit.num_captured_vars`
* :attr:`~.DAGCircuit.num_declared_vars`
- |
:attr:`.DAGCircuit.wires` will now also contain any :class:`.Var` manual variables in the
circuit as well, as these are also classical data flow.
- |
A new method, :meth:`.Var.new`, is added to manually construct a real-time classical variable
that owns its memory.
- |
:meth:`.QuantumCircuit.compose` has two need keyword arguments, ``var_remap`` and ``inline_captures``
to better support real-time classical variables.
``var_remap`` can be used to rewrite :class:`.Var` nodes in the circuit argument as its
instructions are inlined onto the base circuit. This can be used to avoid naming conflicts.
``inline_captures`` can be set to ``True`` (defaults to ``False``) to link all :class:`.Var`
nodes tracked as "captures" in the argument circuit with the same :class:`.Var` nodes in the
base circuit, without attempting to redeclare the variables. This can be used, in combination
with :meth:`.QuantumCircuit.copy_empty_like`'s ``vars_mode="captures"`` handling, to build up
a circuit layer by layer, containing variables.
- |
:meth:`.DAGCircuit.compose` has a new keyword argument, ``inline_captures``, which can be set to
``True`` to inline "captured" :class:`.Var` nodes on the argument circuit onto the base circuit
without redeclaring them. In conjunction with the ``vars_mode="captures"`` option to several
:class:`.DAGCircuit` methods, this can be used to combine DAGs that operate on the same variables.
- |
:meth:`.QuantumCircuit.copy_empty_like` and :meth:`.DAGCircuit.copy_empty_like` have a new
keyword argument, ``vars_mode`` which controls how any memory-owning :class:`.Var` nodes are
tracked in the output. By default (``"alike"``), the variables are declared in the same
input/captured/local mode as the source. This can be set to ``"captures"`` to convert all
variables to captures (useful with :meth:`~.QuantumCircuit.compose`) or ``"drop"`` to remove
them.
- |
A new ``vars_mode`` keyword argument has been added to the :class:`.DAGCircuit` methods:
* :meth:`~.DAGCircuit.separable_circuits`
* :meth:`~.DAGCircuit.layers`
* :meth:`~.DAGCircuit.serial_layers`
which has the same meaning as it does for :meth:`~.DAGCircuit.copy_empty_like`.
features_qasm:
- |
The OpenQASM 3 exporter supports manual-storage :class:`.Var` nodes on circuits.
features_qpy:
- |
QPY (:mod:`qiskit.qpy`) format version 12 has been added, which includes support for memory-owning
:class:`.Var` variables. See :ref:`qpy_version_12` for more detail on the format changes.
features_visualization:
- |
The text and `Matplotlib <https://matplotlib.org>`__ circuit drawers (:meth:`.QuantumCircuit.draw`)
have minimal support for displaying expressions involving manual real-time variables. The
:class:`.Store` operation and the variable initializations are not yet supported; for large-scale
dynamic circuits, we recommend using the OpenQASM 3 export capabilities (:func:`.qasm3.dumps`) to
get a textual representation of a circuit.
upgrade_qpy:
- |
The value of :attr:`qiskit.qpy.QPY_VERSION` is now 12. :attr:`.QPY_COMPATIBILITY_VERSION` is
unchanged at 10.
upgrade_providers:
- |
Implementations of :class:`.BackendV2` (and :class:`.BackendV1`) may desire to update their
:meth:`~.BackendV2.run` methods to eagerly reject inputs containing typed
classical variables (see :mod:`qiskit.circuit.classical`) and the :class:`.Store` instruction,
if they do not have support for them. The new :class:`.Store` instruction is treated by the
transpiler as an always-available "directive" (like :class:`.Barrier`); if your backends do not
support this won't be caught by the :mod:`~qiskit.transpiler`.
See :ref:`providers-guide-real-time-variables` for more information.

0 comments on commit 554e661

Please sign in to comment.