Skip to content

Commit

Permalink
Merge branch 'Qiskit:main' into move-target
Browse files Browse the repository at this point in the history
  • Loading branch information
raynelfss authored Apr 5, 2024
2 parents 7135d72 + 99c0497 commit 7d0982e
Show file tree
Hide file tree
Showing 69 changed files with 1,497 additions and 524 deletions.
22 changes: 6 additions & 16 deletions docs/release_notes.rst
Original file line number Diff line number Diff line change
@@ -1,23 +1,13 @@
.. _release-notes:

=============
Release Notes
=============

This page contains the release notes for Qiskit, starting from Qiskit 0.45, the first time that Qiskit and Qiskit Terra had the same versions.
==============================
Qiskit |version| release notes
==============================

..
These release notes get converted into Markdown files via the infrastructure at https://github.com/Qiskit/documentation, which then gets deployed to https://docs.quantum.ibm.com/api/qiskit/release-notes. Changes to these release notes will update those release notes the next time the API docs are generated.
To change release notes prior to Qiskit 0.45, update the Qiskit/documentation repository directly.
These release notes get converted into Markdown files via the infrastructure at https://github.com/Qiskit/documentation, which then gets deployed to https://docs.quantum.ibm.com/api/qiskit/release-notes. Changes to these release notes will update those release notes the next time the API docs are generated for this version.
.. release-notes::
:earliest-version: 0.45.0rc1

.. release-notes::
:earliest-version: 0.45.0
:branch: stable/0.46
`:earliest-version:` should be set to the rc1 release for the current minor release series. For example, the stable/1.1 branch should set it to 1.1.0rc1. If on `main`, set to the prior minor version's rc1, like `1.0.0rc1`.

.. release-notes::
:earliest-version: 0.45.0
:branch: stable/0.45
:earliest-version: 1.0.0rc1
1,288 changes: 1,133 additions & 155 deletions qiskit/circuit/__init__.py

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions qiskit/circuit/_classical_resource_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ def map_condition(self, condition, /, *, allow_reorder=False):
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):
Expand Down
3 changes: 2 additions & 1 deletion qiskit/circuit/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
This module contains utility functions for circuits.
"""

import math
import numpy
from qiskit.exceptions import QiskitError
from qiskit.circuit.exceptions import CircuitError
Expand Down Expand Up @@ -56,7 +57,7 @@ def _compute_control_matrix(base_mat, num_ctrl_qubits, ctrl_state=None):
Raises:
QiskitError: unrecognized mode or invalid ctrl_state
"""
num_target = int(numpy.log2(base_mat.shape[0]))
num_target = int(math.log2(base_mat.shape[0]))
ctrl_dim = 2**num_ctrl_qubits
ctrl_grnd = numpy.repeat([[1], [0]], [1, ctrl_dim - 1])
if ctrl_state is None:
Expand Down
3 changes: 3 additions & 0 deletions qiskit/circuit/annotated_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,10 @@ def __init__(self, base_op: Operation, modifiers: Union[Modifier, List[Modifier]
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):
Expand Down
23 changes: 10 additions & 13 deletions qiskit/circuit/barrier.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,26 @@
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)
Expand Down
1 change: 0 additions & 1 deletion qiskit/circuit/bit.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"}
Expand Down
4 changes: 2 additions & 2 deletions qiskit/circuit/classical/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
4 changes: 2 additions & 2 deletions qiskit/circuit/classical/expr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
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
Expand Down
30 changes: 8 additions & 22 deletions qiskit/circuit/controlflow/break_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,17 @@


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)


Expand Down
2 changes: 1 addition & 1 deletion qiskit/circuit/controlflow/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ def remove_var(self, var: expr.Var):

@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
Expand Down
30 changes: 8 additions & 22 deletions qiskit/circuit/controlflow/continue_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,17 @@


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)


Expand Down
38 changes: 30 additions & 8 deletions qiskit/circuit/controlflow/control_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@


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)
Expand All @@ -36,17 +41,34 @@ def __init__(self, *args, **kwargs):
@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.
"""
31 changes: 8 additions & 23 deletions qiskit/circuit/controlflow/for_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__(
Expand All @@ -60,9 +38,16 @@ def __init__(
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
)
Expand Down
40 changes: 13 additions & 27 deletions qiskit/circuit/controlflow/if_else.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__(
Expand All @@ -85,6 +58,19 @@ def __init__(
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

Expand Down
Loading

0 comments on commit 7d0982e

Please sign in to comment.