From 33c0a3cf6390f87cabb0460c102fa471fb77fb0a Mon Sep 17 00:00:00 2001 From: Evgenii Zheltonozhskii Date: Mon, 20 Mar 2023 17:02:11 +0200 Subject: [PATCH] Fix circuit mypy errors --- qiskit/circuit/add_control.py | 20 +- qiskit/circuit/controlflow/control_flow.py | 5 +- qiskit/circuit/controlledgate.py | 7 +- qiskit/circuit/gate.py | 21 +- qiskit/circuit/instructionset.py | 24 +- .../adders/vbe_ripple_carry_adder.py | 12 +- .../library/arithmetic/integer_comparator.py | 16 +- .../arithmetic/linear_amplitude_function.py | 15 +- .../library/arithmetic/piecewise_chebyshev.py | 33 +- .../piecewise_linear_pauli_rotations.py | 28 +- .../arithmetic/polynomial_pauli_rotations.py | 16 +- .../library/arithmetic/quadratic_form.py | 2 +- qiskit/circuit/library/blueprintcircuit.py | 11 +- .../library/boolean_logic/quantum_and.py | 7 +- .../library/boolean_logic/quantum_or.py | 6 +- .../data_preparation/state_preparation.py | 2 +- .../library/generalized_gates/diagonal.py | 4 +- .../circuit/library/generalized_gates/mcmt.py | 1 + .../library/generalized_gates/permutation.py | 8 +- qiskit/circuit/library/graph_state.py | 6 +- qiskit/circuit/library/grover_operator.py | 5 +- qiskit/circuit/library/iqp.py | 4 +- qiskit/circuit/library/n_local/n_local.py | 131 ++++--- .../library/n_local/pauli_two_design.py | 8 +- qiskit/circuit/library/n_local/qaoa_ansatz.py | 22 +- qiskit/circuit/library/n_local/two_local.py | 5 +- .../standard_gates/equivalence_library.py | 16 +- qiskit/circuit/library/standard_gates/p.py | 25 +- qiskit/circuit/library/standard_gates/u1.py | 15 +- qiskit/circuit/library/standard_gates/x.py | 6 +- .../circuit/library/templates/rzx/rzx_cy.py | 6 +- .../circuit/library/templates/rzx/rzx_xz.py | 6 +- .../circuit/library/templates/rzx/rzx_yz.py | 5 +- .../circuit/library/templates/rzx/rzx_zz1.py | 5 +- .../circuit/library/templates/rzx/rzx_zz2.py | 6 +- .../circuit/library/templates/rzx/rzx_zz3.py | 5 +- qiskit/circuit/operation.py | 6 +- qiskit/circuit/parameterexpression.py | 18 +- qiskit/circuit/quantumcircuit.py | 335 +++++++++--------- qiskit/circuit/register.py | 4 +- 40 files changed, 489 insertions(+), 388 deletions(-) diff --git a/qiskit/circuit/add_control.py b/qiskit/circuit/add_control.py index 03a176956840..444615e61072 100644 --- a/qiskit/circuit/add_control.py +++ b/qiskit/circuit/add_control.py @@ -11,8 +11,7 @@ # that they have been altered from the originals. """Add control to operation if supported.""" - -from typing import Union, Optional +from __future__ import annotations from qiskit.circuit.exceptions import CircuitError from qiskit.extensions import UnitaryGate @@ -20,10 +19,10 @@ def add_control( - operation: Union[Gate, ControlledGate], + operation: Gate | ControlledGate, num_ctrl_qubits: int, - label: Union[str, None], - ctrl_state: Union[int, str, None], + label: str | None, + ctrl_state: str | int | None, ) -> ControlledGate: """For standard gates, if the controlled version already exists in the library, it will be returned (e.g. XGate.control() = CnotGate(). @@ -62,10 +61,10 @@ def add_control( def control( - operation: Union[Gate, ControlledGate], - num_ctrl_qubits: Optional[int] = 1, - label: Optional[Union[None, str]] = None, - ctrl_state: Optional[Union[None, int, str]] = None, + operation: Gate | ControlledGate, + num_ctrl_qubits: int | None = 1, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> ControlledGate: """Return controlled version of gate using controlled rotations. This function first checks the name of the operation to see if it knows of a method from which @@ -218,7 +217,8 @@ def control( if isinstance(operation, controlledgate.ControlledGate): operation.ctrl_state = original_ctrl_state new_num_ctrl_qubits = num_ctrl_qubits + operation.num_ctrl_qubits - new_ctrl_state = operation.ctrl_state << num_ctrl_qubits | ctrl_state + # TODO: what if ctrl_state is str? + new_ctrl_state: str | int | None = operation.ctrl_state << num_ctrl_qubits | ctrl_state base_name = operation.base_gate.name base_gate = operation.base_gate else: diff --git a/qiskit/circuit/controlflow/control_flow.py b/qiskit/circuit/controlflow/control_flow.py index f33077bd1f1d..11ac283132f4 100644 --- a/qiskit/circuit/controlflow/control_flow.py +++ b/qiskit/circuit/controlflow/control_flow.py @@ -12,8 +12,9 @@ "Container to encapsulate all control flow operations." +from __future__ import annotations from abc import ABC, abstractmethod -from typing import Tuple, Iterable +from typing import Iterable from qiskit.circuit import QuantumCircuit, Instruction @@ -23,7 +24,7 @@ class ControlFlowOp(Instruction, ABC): @property @abstractmethod - def blocks(self) -> Tuple[QuantumCircuit, ...]: + 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. diff --git a/qiskit/circuit/controlledgate.py b/qiskit/circuit/controlledgate.py index 6efaa64c4a7e..8def8bbae209 100644 --- a/qiskit/circuit/controlledgate.py +++ b/qiskit/circuit/controlledgate.py @@ -12,8 +12,9 @@ """Controlled unitary gate.""" +from __future__ import annotations import copy -from typing import List, Optional, Union +from typing import Optional, Union from qiskit.circuit.exceptions import CircuitError @@ -31,7 +32,7 @@ def __init__( self, name: str, num_qubits: int, - params: List, + params: list, label: Optional[str] = None, num_ctrl_qubits: Optional[int] = 1, definition: Optional["QuantumCircuit"] = None, @@ -103,7 +104,7 @@ def __init__( self._name = name @property - def definition(self) -> List: + 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 definition is conjugated with X without changing the internal diff --git a/qiskit/circuit/gate.py b/qiskit/circuit/gate.py index b7eb43fef0f1..5e2fd18284f5 100644 --- a/qiskit/circuit/gate.py +++ b/qiskit/circuit/gate.py @@ -12,7 +12,8 @@ """Unitary gate.""" -from typing import List, Optional, Union, Tuple +from __future__ import annotations +from typing import Any, Iterator, Iterable import numpy as np from qiskit.circuit.parameterexpression import ParameterExpression @@ -24,7 +25,7 @@ class Gate(Instruction): """Unitary gate.""" def __init__( - self, name: str, num_qubits: int, params: List, label: Optional[str] = None + self, name: str, num_qubits: int, params: list[Any], label: str | None = None ) -> None: """Create a new gate. @@ -95,8 +96,8 @@ def _return_repeat(self, exponent: float) -> "Gate": def control( self, num_ctrl_qubits: int = 1, - label: Optional[str] = None, - ctrl_state: Optional[Union[int, str]] = None, + label: str | None = None, + ctrl_state: int | str | None = None, ): """Return controlled version of gate. See :class:`.ControlledGate` for usage. @@ -120,7 +121,7 @@ def control( return add_control(self, num_ctrl_qubits, label, ctrl_state) @staticmethod - def _broadcast_single_argument(qarg: List) -> List: + def _broadcast_single_argument(qarg: list[Any]) -> Iterator[tuple[list[Any], list[Any]]]: """Expands a single argument. For example: [q[0], q[1]] -> [q[0]], [q[1]] @@ -131,7 +132,9 @@ def _broadcast_single_argument(qarg: List) -> List: yield [arg0], [] @staticmethod - def _broadcast_2_arguments(qarg0: List, qarg1: List) -> List: + def _broadcast_2_arguments( + qarg0: list[Any], qarg1: list[Any] + ) -> Iterator[tuple[list[Any], list[Any]]]: if len(qarg0) == len(qarg1): # [[q[0], q[1]], [r[0], r[1]]] -> [q[0], r[0]] # -> [q[1], r[1]] @@ -153,14 +156,16 @@ def _broadcast_2_arguments(qarg0: List, qarg1: List) -> List: ) @staticmethod - def _broadcast_3_or_more_args(qargs: List) -> List: + def _broadcast_3_or_more_args(qargs: list[Any]) -> Iterator[tuple[list[Any], list[Any]]]: if all(len(qarg) == len(qargs[0]) for qarg in qargs): for arg in zip(*qargs): yield list(arg), [] else: raise CircuitError("Not sure how to combine these qubit arguments:\n %s\n" % qargs) - def broadcast_arguments(self, qargs: List, cargs: List) -> Tuple[List, List]: + def broadcast_arguments( + self, qargs: list[Any], cargs: list[Any] + ) -> Iterable[tuple[list[Any], list[Any]]]: """Validation and handling of the arguments and its relationship. For example, ``cx([q[0],q[1]], q[2])`` means ``cx(q[0], q[2]); cx(q[1], q[2])``. This diff --git a/qiskit/circuit/instructionset.py b/qiskit/circuit/instructionset.py index 188b98fef8dc..85c31d96fc7f 100644 --- a/qiskit/circuit/instructionset.py +++ b/qiskit/circuit/instructionset.py @@ -14,9 +14,10 @@ Instruction collection. """ +from __future__ import annotations import functools import warnings -from typing import Callable, Optional, Tuple, Union +from typing import Callable from qiskit.circuit.exceptions import CircuitError from .classicalregister import Clbit, ClassicalRegister @@ -28,7 +29,9 @@ # its creation, so caching this allows us to only pay the register-unrolling penalty once. The # cache does not need to be large, because in general only one circuit is constructed at once. @functools.lru_cache(4) -def _requester_from_cregs(cregs: Tuple[ClassicalRegister]) -> Callable: +def _requester_from_cregs( + cregs: tuple[ClassicalRegister], +) -> Callable[[Clbit | ClassicalRegister | int], ClassicalRegister | Clbit]: """Get a classical resource requester from an iterable of classical registers. This implements the deprecated functionality of constructing an :obj:`.InstructionSet` with a @@ -60,7 +63,7 @@ def _requester_from_cregs(cregs: Tuple[ClassicalRegister]) -> Callable: clbit_set = frozenset(clbit_flat) creg_set = frozenset(cregs) - def requester(classical): + def requester(classical: Clbit | ClassicalRegister | int) -> ClassicalRegister | Clbit: if isinstance(classical, Clbit): if classical not in clbit_set: raise CircuitError( @@ -92,7 +95,12 @@ class InstructionSet: __slots__ = ("_instructions", "_requester") - def __init__(self, circuit_cregs=None, *, resource_requester: Optional[Callable] = None): + def __init__( + self, + circuit_cregs=None, + *, + resource_requester: Callable[..., ClassicalRegister | Clbit] | None = None, + ): """New collection of instructions. The context (``qargs`` and ``cargs`` that each instruction is attached to) is also stored @@ -124,7 +132,7 @@ def __init__(self, circuit_cregs=None, *, resource_requester: Optional[Callable] CircuitError: if both ``resource_requester`` and ``circuit_cregs`` are passed. Only one of these may be passed, and it should be ``resource_requester``. """ - self._instructions = [] + self._instructions: list[CircuitInstruction] = [] if circuit_cregs is not None: if resource_requester is not None: raise CircuitError("Cannot pass both 'circuit_cregs' and 'resource_requester'.") @@ -135,7 +143,9 @@ def __init__(self, circuit_cregs=None, *, resource_requester: Optional[Callable] DeprecationWarning, stacklevel=2, ) - self._requester: Optional[Callable] = _requester_from_cregs(tuple(circuit_cregs)) + self._requester: Callable[..., ClassicalRegister | Clbit] = _requester_from_cregs( + tuple(circuit_cregs) + ) else: self._requester = resource_requester @@ -163,7 +173,7 @@ def inverse(self): self._instructions[i] = instruction.replace(operation=instruction.operation.inverse()) return self - def c_if(self, classical: Union[Clbit, ClassicalRegister, int], val: int) -> "InstructionSet": + def c_if(self, classical: Clbit | ClassicalRegister | int, val: int) -> "InstructionSet": """Set a classical equality condition on all the instructions in this set between the :obj:`.ClassicalRegister` or :obj:`.Clbit` ``classical`` and value ``val``. diff --git a/qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py b/qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py index a8e18f6d57c4..6e0dcf221582 100644 --- a/qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py +++ b/qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py @@ -11,6 +11,8 @@ # that they have been altered from the originals. """Compute the sum of two qubit registers using Classical Addition.""" +from __future__ import annotations +from qiskit.circuit.bit import Bit from qiskit.circuit import QuantumCircuit, QuantumRegister, AncillaRegister @@ -78,9 +80,9 @@ def __init__( super().__init__(num_state_qubits, name=name) # define the input registers - registers = [] + registers: list[QuantumRegister | list[Bit]] = [] if kind == "full": - qr_cin = QuantumRegister(1, name="cin") + qr_cin: QuantumRegister | list[Bit] = QuantumRegister(1, name="cin") registers.append(qr_cin) else: qr_cin = [] @@ -91,7 +93,7 @@ def __init__( registers += [qr_a, qr_b] if kind in ["half", "full"]: - qr_cout = QuantumRegister(1, name="cout") + qr_cout: QuantumRegister | list[Bit] = QuantumRegister(1, name="cout") registers.append(qr_cout) else: qr_cout = [] @@ -99,7 +101,9 @@ def __init__( self.add_register(*registers) if num_state_qubits > 1: - qr_help = AncillaRegister(num_state_qubits - 1, name="helper") + qr_help: AncillaRegister | list[Bit] = AncillaRegister( + num_state_qubits - 1, name="helper" + ) self.add_register(qr_help) else: qr_help = [] diff --git a/qiskit/circuit/library/arithmetic/integer_comparator.py b/qiskit/circuit/library/arithmetic/integer_comparator.py index e52068964ff9..2bfbd659dd45 100644 --- a/qiskit/circuit/library/arithmetic/integer_comparator.py +++ b/qiskit/circuit/library/arithmetic/integer_comparator.py @@ -13,7 +13,7 @@ """Integer Comparator.""" -from typing import List, Optional +from __future__ import annotations import warnings import numpy as np @@ -41,8 +41,8 @@ class IntegerComparator(BlueprintCircuit): def __init__( self, - num_state_qubits: Optional[int] = None, - value: Optional[int] = None, + num_state_qubits: int | None = None, + value: int | None = None, geq: bool = True, name: str = "cmp", ) -> None: @@ -57,9 +57,9 @@ def __init__( """ super().__init__(name=name) - self._value = None - self._geq = None - self._num_state_qubits = None + self._value: int | None = None + self._geq: bool | None = None + self._num_state_qubits: int | None = None self.value = value self.geq = geq @@ -120,7 +120,7 @@ def num_state_qubits(self) -> int: return self._num_state_qubits @num_state_qubits.setter - def num_state_qubits(self, num_state_qubits: Optional[int]) -> None: + def num_state_qubits(self, num_state_qubits: int | None) -> None: """Set the number of state qubits. Note that this will change the quantum registers. @@ -145,7 +145,7 @@ def num_state_qubits(self, num_state_qubits: Optional[int]) -> None: qr_ancilla = AncillaRegister(num_ancillas) self.add_register(qr_ancilla) - def _get_twos_complement(self) -> List[int]: + def _get_twos_complement(self) -> list[int]: """Returns the 2's complement of ``self.value`` as array. Returns: diff --git a/qiskit/circuit/library/arithmetic/linear_amplitude_function.py b/qiskit/circuit/library/arithmetic/linear_amplitude_function.py index 49972797e81e..840f563d959d 100644 --- a/qiskit/circuit/library/arithmetic/linear_amplitude_function.py +++ b/qiskit/circuit/library/arithmetic/linear_amplitude_function.py @@ -12,7 +12,8 @@ """A class implementing a (piecewise-) linear function on qubit amplitudes.""" -from typing import Optional, List, Union, Tuple +from __future__ import annotations +from typing import cast, List import numpy as np from qiskit.circuit import QuantumCircuit @@ -77,12 +78,12 @@ class LinearAmplitudeFunction(QuantumCircuit): def __init__( self, num_state_qubits: int, - slope: Union[float, List[float]], - offset: Union[float, List[float]], - domain: Tuple[float, float], - image: Tuple[float, float], + slope: float | list[float], + offset: float | list[float], + domain: tuple[float, float], + image: tuple[float, float], rescaling_factor: float = 1, - breakpoints: Optional[List[float]] = None, + breakpoints: list[float] | None = None, name: str = "F", ) -> None: r""" @@ -102,8 +103,10 @@ def __init__( """ if not hasattr(slope, "__len__"): slope = [slope] + slope = cast(List[float], slope) if not hasattr(offset, "__len__"): offset = [offset] + offset = cast(List[float], offset) # ensure that the breakpoints include the first point of the domain if breakpoints is None: diff --git a/qiskit/circuit/library/arithmetic/piecewise_chebyshev.py b/qiskit/circuit/library/arithmetic/piecewise_chebyshev.py index 67f808278f2d..9061113245b4 100644 --- a/qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +++ b/qiskit/circuit/library/arithmetic/piecewise_chebyshev.py @@ -11,7 +11,9 @@ # that they have been altered from the originals. """Piecewise polynomial Chebyshev approximation to a given f(x).""" -from typing import Callable, List, Optional, Union + +from __future__ import annotations +from typing import Callable, cast import numpy as np from numpy.polynomial.chebyshev import Chebyshev @@ -60,10 +62,10 @@ class PiecewiseChebyshev(BlueprintCircuit): def __init__( self, - f_x: Union[float, Callable[[int], float]], - degree: Optional[int] = None, - breakpoints: Optional[List[int]] = None, - num_state_qubits: Optional[int] = None, + f_x: float | Callable[[int], float], + degree: int | None = None, + breakpoints: list[int] | None = None, + num_state_qubits: int | None = None, name: str = "pw_cheb", ) -> None: r""" @@ -87,7 +89,7 @@ def __init__( self._degree = degree if degree is not None else 1 self._breakpoints = breakpoints if breakpoints is not None else [0] - self._polynomials = None + self._polynomials: list[list[float]] | None = None self.num_state_qubits = num_state_qubits @@ -126,7 +128,7 @@ def _check_configuration(self, raise_on_failure: bool = True) -> bool: return valid @property - def f_x(self) -> Union[float, Callable[[int], float]]: + def f_x(self) -> float | Callable[[int], float]: """The function to be approximated. Returns: @@ -135,7 +137,7 @@ def f_x(self) -> Union[float, Callable[[int], float]]: return self._f_x @f_x.setter - def f_x(self, f_x: Optional[Union[float, Callable[[int], float]]]) -> None: + def f_x(self, f_x: float | Callable[[int], float] | None) -> None: """Set the function to be approximated. Note that this may change the underlying quantum register, if the number of state qubits @@ -160,7 +162,7 @@ def degree(self) -> int: return self._degree @degree.setter - def degree(self, degree: Optional[int]) -> None: + def degree(self, degree: int | None) -> None: """Set the error tolerance. Note that this may change the underlying quantum register, if the number of state qubits @@ -176,7 +178,7 @@ def degree(self, degree: Optional[int]) -> None: self._reset_registers(self.num_state_qubits) @property - def breakpoints(self) -> List[int]: + def breakpoints(self) -> list[int]: """The breakpoints for the piecewise approximation. Returns: @@ -199,7 +201,7 @@ def breakpoints(self) -> List[int]: return breakpoints @breakpoints.setter - def breakpoints(self, breakpoints: Optional[List[int]]) -> None: + def breakpoints(self, breakpoints: list[int] | None) -> None: """Set the breakpoints for the piecewise approximation. Note that this may change the underlying quantum register, if the number of state qubits @@ -215,7 +217,7 @@ def breakpoints(self, breakpoints: Optional[List[int]]) -> None: self._reset_registers(self.num_state_qubits) @property - def polynomials(self) -> List[List[float]]: + def polynomials(self) -> list[list[float]]: """The polynomials for the piecewise approximation. Returns: @@ -247,6 +249,7 @@ def polynomials(self) -> List[List[float]]: # Append directly to list of polynomials polynomials.append([self.f_x]) else: + self.f_x = cast(Callable[[int], float], self.f_x) poly = Chebyshev.interpolate( self.f_x, self.degree, domain=[breakpoints[i], breakpoints[i + 1]] ) @@ -273,7 +276,7 @@ def polynomials(self) -> List[List[float]]: return polynomials @polynomials.setter - def polynomials(self, polynomials: Optional[List[List[float]]]) -> None: + def polynomials(self, polynomials: list[list[float]] | None) -> None: """Set the polynomials for the piecewise approximation. Note that this may change the underlying quantum register, if the number of state qubits @@ -298,7 +301,7 @@ def num_state_qubits(self) -> int: return self._num_state_qubits @num_state_qubits.setter - def num_state_qubits(self, num_state_qubits: Optional[int]) -> None: + def num_state_qubits(self, num_state_qubits: int | None) -> None: """Set the number of state qubits. Note that this may change the underlying quantum register, if the number of state qubits @@ -317,7 +320,7 @@ def num_state_qubits(self, num_state_qubits: Optional[int]) -> None: self._reset_registers(num_state_qubits) - def _reset_registers(self, num_state_qubits: Optional[int]) -> None: + def _reset_registers(self, num_state_qubits: int | None) -> None: """Reset the registers.""" self.qregs = [] diff --git a/qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py b/qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py index d9c7f622e9b0..b74f6f72997e 100644 --- a/qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +++ b/qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py @@ -13,7 +13,7 @@ """Piecewise-linearly-controlled rotation.""" -from typing import List, Optional +from __future__ import annotations import numpy as np from qiskit.circuit import QuantumRegister, AncillaRegister, QuantumCircuit @@ -46,10 +46,10 @@ class PiecewiseLinearPauliRotations(FunctionalPauliRotations): def __init__( self, - num_state_qubits: Optional[int] = None, - breakpoints: Optional[List[int]] = None, - slopes: Optional[List[float]] = None, - offsets: Optional[List[float]] = None, + num_state_qubits: int | None = None, + breakpoints: list[int] | None = None, + slopes: list[float] | np.ndarray | None = None, + offsets: list[float] | np.ndarray | None = None, basis: str = "Y", name: str = "pw_lin", ) -> None: @@ -74,7 +74,7 @@ def __init__( super().__init__(num_state_qubits=num_state_qubits, basis=basis, name=name) @property - def breakpoints(self) -> List[int]: + def breakpoints(self) -> list[int]: """The breakpoints of the piecewise linear function. The function is linear in the intervals ``[point_i, point_{i+1}]`` where the last @@ -83,7 +83,7 @@ def breakpoints(self) -> List[int]: return self._breakpoints @breakpoints.setter - def breakpoints(self, breakpoints: List[int]) -> None: + def breakpoints(self, breakpoints: list[int]) -> None: """Set the breakpoints. Args: @@ -96,7 +96,7 @@ def breakpoints(self, breakpoints: List[int]) -> None: self._reset_registers(self.num_state_qubits) @property - def slopes(self) -> List[int]: + def slopes(self) -> list[float] | np.ndarray: """The breakpoints of the piecewise linear function. The function is linear in the intervals ``[point_i, point_{i+1}]`` where the last @@ -105,7 +105,7 @@ def slopes(self) -> List[int]: return self._slopes @slopes.setter - def slopes(self, slopes: List[float]) -> None: + def slopes(self, slopes: list[float]) -> None: """Set the slopes. Args: @@ -115,7 +115,7 @@ def slopes(self, slopes: List[float]) -> None: self._slopes = slopes @property - def offsets(self) -> List[float]: + def offsets(self) -> list[float] | np.ndarray: """The breakpoints of the piecewise linear function. The function is linear in the intervals ``[point_i, point_{i+1}]`` where the last @@ -124,7 +124,7 @@ def offsets(self) -> List[float]: return self._offsets @offsets.setter - def offsets(self, offsets: List[float]) -> None: + def offsets(self, offsets: list[float]) -> None: """Set the offsets. Args: @@ -134,7 +134,7 @@ def offsets(self, offsets: List[float]) -> None: self._offsets = offsets @property - def mapped_slopes(self) -> List[float]: + def mapped_slopes(self) -> np.ndarray: """The slopes mapped to the internal representation. Returns: @@ -147,7 +147,7 @@ def mapped_slopes(self) -> List[float]: return mapped_slopes @property - def mapped_offsets(self) -> List[float]: + def mapped_offsets(self) -> np.ndarray: """The offsets mapped to the internal representation. Returns: @@ -212,7 +212,7 @@ def _check_configuration(self, raise_on_failure: bool = True) -> bool: return valid - def _reset_registers(self, num_state_qubits: Optional[int]) -> None: + def _reset_registers(self, num_state_qubits: int | None) -> None: """Reset the registers.""" self.qregs = [] diff --git a/qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py b/qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py index 84e1568b29f8..42011e0c0b59 100644 --- a/qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py +++ b/qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py @@ -13,8 +13,8 @@ """Polynomially controlled Pauli-rotations.""" +from __future__ import annotations import warnings -from typing import List, Optional, Dict, Sequence from itertools import product @@ -160,8 +160,8 @@ class PolynomialPauliRotations(FunctionalPauliRotations): def __init__( self, - num_state_qubits: Optional[int] = None, - coeffs: Optional[List[float]] = None, + num_state_qubits: int | None = None, + coeffs: list[float] | None = None, basis: str = "Y", name: str = "poly", ) -> None: @@ -181,7 +181,7 @@ def __init__( super().__init__(num_state_qubits=num_state_qubits, basis=basis, name=name) @property - def coeffs(self) -> List[float]: + def coeffs(self) -> list[float]: """The multiplicative factor in the rotation angle of the controlled rotations. The rotation angles are ``slope * 2^0``, ``slope * 2^1``, ... , ``slope * 2^(n-1)`` where @@ -193,7 +193,7 @@ def coeffs(self) -> List[float]: return self._coeffs @coeffs.setter - def coeffs(self, coeffs: List[float]) -> None: + def coeffs(self, coeffs: list[float]) -> None: """Set the multiplicative factor of the rotation angles. Args: @@ -255,7 +255,7 @@ def _check_configuration(self, raise_on_failure: bool = True) -> bool: return valid - def _get_rotation_coefficients(self) -> Dict[Sequence[int], float]: + def _get_rotation_coefficients(self) -> dict[tuple[int, ...], float]: """Compute the coefficient of each monomial. Returns: @@ -269,7 +269,7 @@ def _get_rotation_coefficients(self) -> Dict[Sequence[int], float]: if 0 < sum(combination) <= self.degree: valid_combinations += [combination] - rotation_coeffs = {control_state: 0 for control_state in valid_combinations} + rotation_coeffs = {control_state: 0.0 for control_state in valid_combinations} # compute the coefficients for the control states for i, coeff in enumerate(self.coeffs[1:]): @@ -277,7 +277,7 @@ def _get_rotation_coefficients(self) -> Dict[Sequence[int], float]: # iterate over the multinomial coefficients for comb, num_combs in _multinomial_coefficients(self.num_state_qubits, i).items(): - control_state = () + control_state: tuple[int, ...] = () power = 1 for j, qubit in enumerate(comb): if qubit > 0: # means we control on qubit i diff --git a/qiskit/circuit/library/arithmetic/quadratic_form.py b/qiskit/circuit/library/arithmetic/quadratic_form.py index 36f226d6dcfb..bd0bca1664a3 100644 --- a/qiskit/circuit/library/arithmetic/quadratic_form.py +++ b/qiskit/circuit/library/arithmetic/quadratic_form.py @@ -182,7 +182,7 @@ def required_result_qubits( bounds = [] # bounds = [minimum value, maximum value] for condition in [lambda x: x < 0, lambda x: x > 0]: - bound = 0 + bound = 0.0 bound += sum(sum(q_ij for q_ij in q_i if condition(q_ij)) for q_i in quadratic) bound += sum(l_i for l_i in linear if condition(l_i)) bound += offset if condition(offset) else 0 diff --git a/qiskit/circuit/library/blueprintcircuit.py b/qiskit/circuit/library/blueprintcircuit.py index da2d6348c720..415ae8ecd117 100644 --- a/qiskit/circuit/library/blueprintcircuit.py +++ b/qiskit/circuit/library/blueprintcircuit.py @@ -12,9 +12,10 @@ """Blueprint circuit object.""" -from typing import Optional +from __future__ import annotations from abc import ABC, abstractmethod -from qiskit.circuit import QuantumCircuit + +from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister from qiskit.circuit.parametertable import ParameterTable, ParameterView @@ -29,11 +30,11 @@ class BlueprintCircuit(QuantumCircuit, ABC): accessed, the ``_build`` method is called. There the configuration of the circuit is checked. """ - def __init__(self, *regs, name: Optional[str] = None) -> None: + def __init__(self, *regs, name: str | None = None) -> None: """Create a new blueprint circuit.""" super().__init__(*regs, name=name) - self._qregs = [] - self._cregs = [] + self._qregs: list[QuantumRegister] = [] + self._cregs: list[ClassicalRegister] = [] self._qubits = [] self._qubit_indices = {} self._is_built = False diff --git a/qiskit/circuit/library/boolean_logic/quantum_and.py b/qiskit/circuit/library/boolean_logic/quantum_and.py index 7b598c4ad7c8..b68c50d30fda 100644 --- a/qiskit/circuit/library/boolean_logic/quantum_and.py +++ b/qiskit/circuit/library/boolean_logic/quantum_and.py @@ -12,8 +12,9 @@ """Implementations of boolean logic quantum circuits.""" +from __future__ import annotations -from typing import List, Optional +from qiskit.circuit.bit import Bit from qiskit.circuit import QuantumRegister, QuantumCircuit, AncillaRegister from qiskit.circuit.library.standard_gates import MCXGate @@ -53,7 +54,7 @@ class AND(QuantumCircuit): def __init__( self, num_variable_qubits: int, - flags: Optional[List[int]] = None, + flags: list[int] | None = None, mcx_mode: str = "noancilla", ) -> None: """Create a new logical AND circuit. @@ -83,7 +84,7 @@ def __init__( # determine the number of ancillas num_ancillas = MCXGate.get_num_ancilla_qubits(len(control_qubits), mode=mcx_mode) if num_ancillas > 0: - qr_ancilla = AncillaRegister(num_ancillas, "ancilla") + qr_ancilla: AncillaRegister | list[Bit] = AncillaRegister(num_ancillas, "ancilla") circuit.add_register(qr_ancilla) else: qr_ancilla = [] diff --git a/qiskit/circuit/library/boolean_logic/quantum_or.py b/qiskit/circuit/library/boolean_logic/quantum_or.py index 4e885c23b44e..007440a2d658 100644 --- a/qiskit/circuit/library/boolean_logic/quantum_or.py +++ b/qiskit/circuit/library/boolean_logic/quantum_or.py @@ -12,9 +12,11 @@ """Implementations of boolean logic quantum circuits.""" - +from __future__ import annotations from typing import List, Optional +from qiskit.circuit.bit import Bit + from qiskit.circuit import QuantumRegister, QuantumCircuit, AncillaRegister from qiskit.circuit.library.standard_gates import MCXGate @@ -82,7 +84,7 @@ def __init__( # determine the number of ancillas num_ancillas = MCXGate.get_num_ancilla_qubits(len(control_qubits), mode=mcx_mode) if num_ancillas > 0: - qr_ancilla = AncillaRegister(num_ancillas, "ancilla") + qr_ancilla: AncillaRegister | list[Bit] = AncillaRegister(num_ancillas, "ancilla") circuit.add_register(qr_ancilla) else: qr_ancilla = [] diff --git a/qiskit/circuit/library/data_preparation/state_preparation.py b/qiskit/circuit/library/data_preparation/state_preparation.py index 65b1c9162990..84e348cd38ce 100644 --- a/qiskit/circuit/library/data_preparation/state_preparation.py +++ b/qiskit/circuit/library/data_preparation/state_preparation.py @@ -514,4 +514,4 @@ def prepare_state(self, state, qubits=None, label=None): return self.append(StatePreparation(state, num_qubits, label=label), qubits) -QuantumCircuit.prepare_state = prepare_state +QuantumCircuit.prepare_state = prepare_state # type:ignore[attr-defined] diff --git a/qiskit/circuit/library/generalized_gates/diagonal.py b/qiskit/circuit/library/generalized_gates/diagonal.py index f31720260671..af601d88cac3 100644 --- a/qiskit/circuit/library/generalized_gates/diagonal.py +++ b/qiskit/circuit/library/generalized_gates/diagonal.py @@ -13,7 +13,7 @@ """Diagonal matrix circuit.""" -from typing import Union, List +from __future__ import annotations import cmath import numpy as np @@ -71,7 +71,7 @@ class Diagonal(QuantumCircuit): `arXiv:0406176 `_ """ - def __init__(self, diag: Union[List, np.array]) -> None: + def __init__(self, diag: list[complex] | np.ndarray) -> None: """Create a new Diagonal circuit. Args: diff --git a/qiskit/circuit/library/generalized_gates/mcmt.py b/qiskit/circuit/library/generalized_gates/mcmt.py index c9392b74df1c..b2387121d7df 100644 --- a/qiskit/circuit/library/generalized_gates/mcmt.py +++ b/qiskit/circuit/library/generalized_gates/mcmt.py @@ -229,6 +229,7 @@ def _ccx_v_chain_rule( Raises: QiskitError: If an insufficient number of ancilla qubits was provided. """ + # TODO: should it actually return anyting? if len(ancilla_qubits) == 0: return diff --git a/qiskit/circuit/library/generalized_gates/permutation.py b/qiskit/circuit/library/generalized_gates/permutation.py index 732d056ce761..e386317c7ebc 100644 --- a/qiskit/circuit/library/generalized_gates/permutation.py +++ b/qiskit/circuit/library/generalized_gates/permutation.py @@ -15,7 +15,7 @@ gate (the new way to specify permutations, allowing a variety of synthesis algorithms). """ -from typing import List, Optional +from __future__ import annotations import numpy as np @@ -30,8 +30,8 @@ class Permutation(QuantumCircuit): def __init__( self, num_qubits: int, - pattern: Optional[List[int]] = None, - seed: Optional[int] = None, + pattern: list[int] | np.ndarray | None = None, + seed: int | None = None, ) -> None: """Return an n_qubit permutation circuit implemented using SWAPs. @@ -99,7 +99,7 @@ class PermutationGate(Gate): def __init__( self, - pattern: List[int], + pattern: list[int], ) -> None: """Return a permutation gate. diff --git a/qiskit/circuit/library/graph_state.py b/qiskit/circuit/library/graph_state.py index 3c6705206b1d..4a79fa19444b 100644 --- a/qiskit/circuit/library/graph_state.py +++ b/qiskit/circuit/library/graph_state.py @@ -12,7 +12,9 @@ """Graph State circuit.""" -from typing import Union, List +from __future__ import annotations + +from typing import Any import numpy as np from qiskit.circuit.quantumcircuit import QuantumCircuit @@ -56,7 +58,7 @@ class GraphState(QuantumCircuit): `arXiv:1512.07892 `_ """ - def __init__(self, adjacency_matrix: Union[List, np.array]) -> None: + def __init__(self, adjacency_matrix: list[Any] | np.ndarray) -> None: """Create graph state preparation circuit. Args: diff --git a/qiskit/circuit/library/grover_operator.py b/qiskit/circuit/library/grover_operator.py index 28d373341f47..22d64c656130 100644 --- a/qiskit/circuit/library/grover_operator.py +++ b/qiskit/circuit/library/grover_operator.py @@ -12,8 +12,11 @@ """The Grover operator.""" +from __future__ import annotations from typing import List, Optional, Union import numpy +from qiskit.circuit.bit import Bit + from qiskit.circuit import QuantumCircuit, QuantumRegister, AncillaRegister from qiskit.exceptions import QiskitError from qiskit.quantum_info import Statevector, Operator, DensityMatrix @@ -292,7 +295,7 @@ def _zero_reflection( num_ancillas = MCXGate.get_num_ancilla_qubits(len(qubits) - 1, mcx_mode) if num_ancillas > 0: - qr_ancilla = AncillaRegister(num_ancillas, "ancilla") + qr_ancilla: AncillaRegister | list[Bit] = AncillaRegister(num_ancillas, "ancilla") reflection.add_register(qr_ancilla) else: qr_ancilla = [] diff --git a/qiskit/circuit/library/iqp.py b/qiskit/circuit/library/iqp.py index 0b55d7c0720b..e18c49d531d0 100644 --- a/qiskit/circuit/library/iqp.py +++ b/qiskit/circuit/library/iqp.py @@ -12,7 +12,7 @@ """Instantaneous quantum polynomial circuit.""" -from typing import Union, List +from __future__ import annotations import numpy as np from qiskit.circuit import QuantumCircuit @@ -60,7 +60,7 @@ class IQP(QuantumCircuit): `arXiv:1504.07999 `_ """ - def __init__(self, interactions: Union[List, np.array]) -> None: + def __init__(self, interactions: list | np.ndarray) -> None: """Create IQP circuit. Args: diff --git a/qiskit/circuit/library/n_local/n_local.py b/qiskit/circuit/library/n_local/n_local.py index 3c5765cbde0b..5352638dea92 100644 --- a/qiskit/circuit/library/n_local/n_local.py +++ b/qiskit/circuit/library/n_local/n_local.py @@ -12,7 +12,10 @@ """The n-local circuit class.""" -from typing import Union, Optional, List, Any, Tuple, Sequence, Set, Callable +from __future__ import annotations + +import typing +from typing import Union, List, Optional, Any, Sequence, Callable, Mapping, cast from itertools import combinations import numpy @@ -23,6 +26,9 @@ from ..blueprintcircuit import BlueprintCircuit +if typing.TYPE_CHECKING: + import qiskit # pylint: disable=cyclic-import + class NLocal(BlueprintCircuit): """The n-local circuit class. @@ -64,22 +70,26 @@ class NLocal(BlueprintCircuit): def __init__( self, - num_qubits: Optional[int] = None, - rotation_blocks: Optional[ - Union[QuantumCircuit, List[QuantumCircuit], Instruction, List[Instruction]] - ] = None, - entanglement_blocks: Optional[ - Union[QuantumCircuit, List[QuantumCircuit], Instruction, List[Instruction]] - ] = None, - entanglement: Optional[Union[List[int], List[List[int]]]] = None, + num_qubits: int | None = None, + rotation_blocks: QuantumCircuit + | list[QuantumCircuit] + | qiskit.circuit.Instruction + | list[qiskit.circuit.Instruction] + | None = None, + entanglement_blocks: QuantumCircuit + | list[QuantumCircuit] + | qiskit.circuit.Instruction + | list[qiskit.circuit.Instruction] + | None = None, + entanglement: list[int] | list[list[int]] | None = None, reps: int = 1, insert_barriers: bool = False, parameter_prefix: str = "θ", - overwrite_block_parameters: Union[bool, List[List[Parameter]]] = True, + overwrite_block_parameters: bool | list[list[Parameter]] = True, skip_final_rotation_layer: bool = False, skip_unentangled_qubits: bool = False, - initial_state: Optional[QuantumCircuit] = None, - name: Optional[str] = "nlocal", + initial_state: QuantumCircuit | None = None, + name: str | None = "nlocal", ) -> None: """Create a new n-local circuit. @@ -114,23 +124,26 @@ def __init__( """ super().__init__(name=name) - self._num_qubits = None + self._num_qubits: int | None = None self._insert_barriers = insert_barriers self._reps = reps - self._entanglement_blocks = [] - self._rotation_blocks = [] - self._prepended_blocks = [] - self._prepended_entanglement = [] - self._appended_blocks = [] - self._appended_entanglement = [] + self._entanglement_blocks: list[QuantumCircuit] = [] + self._rotation_blocks: list[QuantumCircuit] = [] + self._prepended_blocks: list[QuantumCircuit] = [] + self._prepended_entanglement: list[list[list[int]] | str] = [] + self._appended_blocks: list[QuantumCircuit] = [] + self._appended_entanglement: list[list[list[int]] | str] = [] self._entanglement = None self._entangler_maps = None - self._ordered_parameters = ParameterVector(name=parameter_prefix) + self._ordered_parameters: ParameterVector | list[Parameter] = ParameterVector( + name=parameter_prefix + ) self._overwrite_block_parameters = overwrite_block_parameters self._skip_final_rotation_layer = skip_final_rotation_layer self._skip_unentangled_qubits = skip_unentangled_qubits - self._initial_state, self._initial_state_circuit = None, None - self._bounds = None + self._initial_state: QuantumCircuit | None = None + self._initial_state_circuit: QuantumCircuit | None = None + self._bounds: list[tuple[float | None, float | None]] | None = None if int(reps) != reps: raise TypeError("The value of reps should be int") @@ -205,7 +218,7 @@ def _convert_to_block(self, layer: Any) -> QuantumCircuit: raise TypeError(f"Adding a {type(layer)} to an NLocal is not supported.") @property - def rotation_blocks(self) -> List[Instruction]: + def rotation_blocks(self) -> list[QuantumCircuit]: """The blocks in the rotation layers. Returns: @@ -215,7 +228,7 @@ def rotation_blocks(self) -> List[Instruction]: @rotation_blocks.setter def rotation_blocks( - self, blocks: Union[QuantumCircuit, List[QuantumCircuit], Instruction, List[Instruction]] + self, blocks: QuantumCircuit | list[QuantumCircuit] | Instruction | list[Instruction] ) -> None: """Set the blocks in the rotation layers. @@ -225,12 +238,13 @@ def rotation_blocks( # cannot check for the attribute ``'__len__'`` because a circuit also has this attribute if not isinstance(blocks, (list, numpy.ndarray)): blocks = [blocks] + blocks = cast(Union[List[QuantumCircuit], List[Instruction]], blocks) self._invalidate() self._rotation_blocks = [self._convert_to_block(block) for block in blocks] @property - def entanglement_blocks(self) -> List[Instruction]: + def entanglement_blocks(self) -> list[QuantumCircuit]: """The blocks in the entanglement layers. Returns: @@ -240,7 +254,7 @@ def entanglement_blocks(self) -> List[Instruction]: @entanglement_blocks.setter def entanglement_blocks( - self, blocks: Union[QuantumCircuit, List[QuantumCircuit], Instruction, List[Instruction]] + self, blocks: QuantumCircuit | list[QuantumCircuit] | Instruction | list[Instruction] ) -> None: """Set the blocks in the entanglement layers. @@ -250,6 +264,7 @@ def entanglement_blocks( # cannot check for the attribute ``'__len__'`` because a circuit also has this attribute if not isinstance(blocks, (list, numpy.ndarray)): blocks = [blocks] + blocks = cast(Union[List[QuantumCircuit], List[Instruction]], blocks) self._invalidate() self._entanglement_blocks = [self._convert_to_block(block) for block in blocks] @@ -259,14 +274,14 @@ def entanglement( self, ) -> Union[ str, - List[str], - List[List[str]], - List[int], - List[List[int]], - List[List[List[int]]], - List[List[List[List[int]]]], + list[str], + list[list[str]], + list[int], + list[list[int]], + list[list[list[int]]], + list[list[list[list[int]]]], Callable[[int], str], - Callable[[int], List[List[int]]], + Callable[[int], list[list[int]]], ]: """Get the entanglement strategy. @@ -282,14 +297,14 @@ def entanglement( entanglement: Optional[ Union[ str, - List[str], - List[List[str]], - List[int], - List[List[int]], - List[List[List[int]]], - List[List[List[List[int]]]], + list[str], + list[list[str]], + list[int], + list[list[int]], + list[list[list[int]]], + list[list[list[list[int]]]], Callable[[int], str], - Callable[[int], List[List[int]]], + Callable[[int], list[list[int]]], ] ], ) -> None: @@ -347,7 +362,7 @@ def _check_configuration(self, raise_on_failure: bool = True) -> bool: return valid @property - def ordered_parameters(self) -> List[Parameter]: + def ordered_parameters(self) -> list[Parameter]: """The parameters used in the underlying circuit. This includes float values and duplicates. @@ -374,7 +389,7 @@ def ordered_parameters(self) -> List[Parameter]: return self._ordered_parameters @ordered_parameters.setter - def ordered_parameters(self, parameters: Union[ParameterVector, List[Parameter]]) -> None: + def ordered_parameters(self, parameters: ParameterVector | list[Parameter]) -> None: """Set the parameters used in the underlying circuit. Args: @@ -420,7 +435,7 @@ def insert_barriers(self, insert_barriers: bool) -> None: self._invalidate() self._insert_barriers = insert_barriers - def get_unentangled_qubits(self) -> Set[int]: + def get_unentangled_qubits(self) -> set[int]: """Get the indices of unentangled qubits in a set. Returns: @@ -520,7 +535,7 @@ def print_settings(self) -> str: return ret @property - def preferred_init_points(self) -> Optional[List[float]]: + def preferred_init_points(self) -> list[float] | None: """The initial points for the parameters. Can be stored as initial guess in optimization. Returns: @@ -531,7 +546,7 @@ def preferred_init_points(self) -> Optional[List[float]]: # pylint: disable=too-many-return-statements def get_entangler_map( self, rep_num: int, block_num: int, num_block_qubits: int - ) -> List[List[int]]: + ) -> Sequence[Sequence[int]]: """Get the entangler map for in the repetition ``rep_num`` and the block ``block_num``. The entangler map for the current block is derived from the value of ``self.entanglement``. @@ -675,7 +690,7 @@ def initial_state(self, initial_state: QuantumCircuit) -> None: self._invalidate() @property - def parameter_bounds(self) -> Optional[List[Tuple[float, float]]]: + def parameter_bounds(self) -> list[tuple[float, float]] | None: """The parameter bounds for the unbound parameters in the circuit. Returns: @@ -688,7 +703,7 @@ def parameter_bounds(self) -> Optional[List[Tuple[float, float]]]: return self._bounds @parameter_bounds.setter - def parameter_bounds(self, bounds: List[Tuple[float, float]]) -> None: + def parameter_bounds(self, bounds: list[tuple[float, float]]) -> None: """Set the parameter bounds. Args: @@ -698,8 +713,8 @@ def parameter_bounds(self, bounds: List[Tuple[float, float]]) -> None: def add_layer( self, - other: Union["NLocal", Instruction, QuantumCircuit], - entanglement: Optional[Union[List[int], str, List[List[int]]]] = None, + other: Union["NLocal", qiskit.circuit.Instruction, QuantumCircuit], + entanglement: list[int] | str | list[list[int]] | None = None, front: bool = False, ) -> "NLocal": """Append another layer to the NLocal. @@ -723,7 +738,7 @@ def add_layer( entanglement = [list(range(block.num_qubits))] elif isinstance(entanglement, list) and not isinstance(entanglement[0], list): entanglement = [entanglement] - + entanglement = cast(Union[List[List[int]], str], entanglement) if front: self._prepended_blocks += [block] self._prepended_entanglement += [entanglement] @@ -743,7 +758,9 @@ def add_layer( self.barrier() if isinstance(entanglement, str): - entangler_map = get_entangler_map(block.num_qubits, self.num_qubits, entanglement) + entangler_map: Sequence[Sequence[int]] = get_entangler_map( + block.num_qubits, self.num_qubits, entanglement + ) else: entangler_map = entanglement @@ -762,9 +779,10 @@ def add_layer( def assign_parameters( self, - parameters: Union[dict, List[float], List[Parameter], ParameterVector], + parameters: Mapping[Parameter, ParameterExpression | float] + | Sequence[ParameterExpression | float], inplace: bool = False, - ) -> Optional[QuantumCircuit]: + ) -> QuantumCircuit | None: """Assign parameters to the n-local circuit. This method also supports passing a list instead of a dictionary. If a list @@ -869,6 +887,7 @@ def _build_additional_layers(self, circuit, which): layer = QuantumCircuit(*self.qregs) if isinstance(ent, str): ent = get_entangler_map(block.num_qubits, self.num_qubits, ent) + ent = cast(Sequence[Sequence[int]], ent) for indices in ent: layer.compose(block, indices, inplace=True) @@ -936,12 +955,12 @@ def _build(self) -> None: self.append(block, self.qubits) # pylint: disable=unused-argument - def _parameter_generator(self, rep: int, block: int, indices: List[int]) -> Optional[Parameter]: + def _parameter_generator(self, rep: int, block: int, indices: list[int]) -> Parameter | None: """If certain blocks should use certain parameters this method can be overriden.""" return None -def get_parameters(block: Union[QuantumCircuit, Instruction]) -> List[Parameter]: +def get_parameters(block: QuantumCircuit | Instruction) -> list[Parameter]: """Return the list of Parameters objects inside a circuit or instruction. This is required since, in a standard gate the parameters are not necessarily Parameter @@ -956,7 +975,7 @@ def get_parameters(block: Union[QuantumCircuit, Instruction]) -> List[Parameter] def get_entangler_map( num_block_qubits: int, num_circuit_qubits: int, entanglement: str, offset: int = 0 -) -> List[Sequence[int]]: +) -> Sequence[tuple[int, ...]]: """Get an entangler map for an arbitrary number of qubits. Args: diff --git a/qiskit/circuit/library/n_local/pauli_two_design.py b/qiskit/circuit/library/n_local/pauli_two_design.py index a8dc91e273b3..fa63c8c6f3a8 100644 --- a/qiskit/circuit/library/n_local/pauli_two_design.py +++ b/qiskit/circuit/library/n_local/pauli_two_design.py @@ -12,7 +12,7 @@ """The Random Pauli circuit class.""" -from typing import Optional +from __future__ import annotations import numpy as np from qiskit.circuit import QuantumCircuit @@ -69,9 +69,9 @@ class PauliTwoDesign(TwoLocal): def __init__( self, - num_qubits: Optional[int] = None, + num_qubits: int | None = None, reps: int = 3, - seed: Optional[int] = None, + seed: int | None = None, insert_barriers: bool = False, name: str = "PauliTwoDesign", ): @@ -82,7 +82,7 @@ def __init__( self._rng = np.random.default_rng(seed) # store a dict to keep track of the random gates - self._gates = {} + self._gates: dict[int, list[str]] = {} super().__init__( num_qubits, diff --git a/qiskit/circuit/library/n_local/qaoa_ansatz.py b/qiskit/circuit/library/n_local/qaoa_ansatz.py index cc6d531f6663..33b880caf4ff 100644 --- a/qiskit/circuit/library/n_local/qaoa_ansatz.py +++ b/qiskit/circuit/library/n_local/qaoa_ansatz.py @@ -13,7 +13,7 @@ """A generalized QAOA quantum circuit with a support of custom initial states and mixers.""" # pylint: disable=cyclic-import -from typing import Optional, List, Tuple +from __future__ import annotations import numpy as np from qiskit.circuit.library.evolved_operator_ansatz import EvolvedOperatorAnsatz, _is_pauli_identity @@ -35,7 +35,7 @@ def __init__( self, cost_operator=None, reps: int = 1, - initial_state: Optional[QuantumCircuit] = None, + initial_state: QuantumCircuit | None = None, mixer_operator=None, name: str = "QAOA", ): @@ -59,11 +59,11 @@ def __init__( self._cost_operator = None self._reps = reps - self._initial_state = initial_state + self._initial_state: QuantumCircuit | None = initial_state self._mixer = mixer_operator # set this circuit as a not-built circuit - self._bounds = None + self._bounds: list[tuple[float | None, float | None]] | None = None # store cost operator and set the registers if the operator is not None self.cost_operator = cost_operator @@ -105,7 +105,7 @@ def _check_configuration(self, raise_on_failure: bool = True) -> bool: return valid @property - def parameter_bounds(self) -> Optional[List[Tuple[Optional[float], Optional[float]]]]: + def parameter_bounds(self) -> list[tuple[float | None, float | None]] | None: """The parameter bounds for the unbound parameters in the circuit. Returns: @@ -123,7 +123,7 @@ def parameter_bounds(self) -> Optional[List[Tuple[Optional[float], Optional[floa # default bounds: None for gamma (cost operator), [0, 2pi] for gamma (mixer operator) beta_bounds = (0, 2 * np.pi) gamma_bounds = (None, None) - bounds = [] + bounds: list[tuple[float | None, float | None]] = [] if not _is_pauli_identity(self.mixer_operator): bounds += self.reps * [beta_bounds] @@ -134,9 +134,7 @@ def parameter_bounds(self) -> Optional[List[Tuple[Optional[float], Optional[floa return bounds @parameter_bounds.setter - def parameter_bounds( - self, bounds: Optional[List[Tuple[Optional[float], Optional[float]]]] - ) -> None: + def parameter_bounds(self, bounds: list[tuple[float | None, float | None]] | None) -> None: """Set the parameter bounds. Args: @@ -145,7 +143,7 @@ def parameter_bounds( self._bounds = bounds @property - def operators(self): + def operators(self) -> list: """The operators that are evolved in this circuit. Returns: @@ -186,7 +184,7 @@ def reps(self, reps: int) -> None: self._invalidate() @property - def initial_state(self) -> Optional[QuantumCircuit]: + def initial_state(self) -> QuantumCircuit | None: """Returns an optional initial state as a circuit""" if self._initial_state is not None: return self._initial_state @@ -201,7 +199,7 @@ def initial_state(self) -> Optional[QuantumCircuit]: return None @initial_state.setter - def initial_state(self, initial_state: Optional[QuantumCircuit]) -> None: + def initial_state(self, initial_state: QuantumCircuit | None) -> None: """Sets initial state.""" self._initial_state = initial_state self._invalidate() diff --git a/qiskit/circuit/library/n_local/two_local.py b/qiskit/circuit/library/n_local/two_local.py index 2b4337c55c48..b6d9f72486b0 100644 --- a/qiskit/circuit/library/n_local/two_local.py +++ b/qiskit/circuit/library/n_local/two_local.py @@ -12,7 +12,8 @@ """The two-local gate circuit.""" -from typing import Union, Optional, List, Callable, Any +from __future__ import annotations +from typing import Union, Optional, List, Callable, Any, Sequence from qiskit.circuit.quantumcircuit import QuantumCircuit from qiskit.circuit import Gate, Instruction, Parameter @@ -308,7 +309,7 @@ def _convert_to_block(self, layer: Union[str, type, Gate, QuantumCircuit]) -> Qu def get_entangler_map( self, rep_num: int, block_num: int, num_block_qubits: int - ) -> List[List[int]]: + ) -> Sequence[Sequence[int]]: """Overloading to handle the special case of 1 qubit where the entanglement are ignored.""" if self.num_qubits <= 1: return [] diff --git a/qiskit/circuit/library/standard_gates/equivalence_library.py b/qiskit/circuit/library/standard_gates/equivalence_library.py index fa17cf1ba3e0..3c2c82ed155f 100644 --- a/qiskit/circuit/library/standard_gates/equivalence_library.py +++ b/qiskit/circuit/library/standard_gates/equivalence_library.py @@ -12,9 +12,17 @@ """Standard gates.""" - +from __future__ import annotations from qiskit.qasm import pi -from qiskit.circuit import EquivalenceLibrary, Parameter, QuantumCircuit, QuantumRegister +from qiskit.circuit import ( + EquivalenceLibrary, + Parameter, + QuantumCircuit, + QuantumRegister, + Gate, + Qubit, + Clbit, +) from qiskit.quantum_info.synthesis.ion_decompose import cnot_rxx_decompose @@ -1488,7 +1496,7 @@ xxplusyy = QuantumCircuit(q) beta = Parameter("beta") theta = Parameter("theta") -rules = [ +rules: list[tuple[Gate, list[Qubit], list[Clbit]]] = [ (RZGate(beta), [q[0]], []), (RZGate(-pi / 2), [q[1]], []), (SXGate(), [q[1]], []), @@ -1523,7 +1531,7 @@ xxminusyy = QuantumCircuit(q) beta = Parameter("beta") theta = Parameter("theta") -rules = [ +rules: list[tuple[Gate, list[Qubit], list[Clbit]]] = [ (RZGate(-beta), [q[1]], []), (RZGate(-pi / 2), [q[0]], []), (SXGate(), [q[0]], []), diff --git a/qiskit/circuit/library/standard_gates/p.py b/qiskit/circuit/library/standard_gates/p.py index 12a1528b8bd2..f8cbf7008d3d 100644 --- a/qiskit/circuit/library/standard_gates/p.py +++ b/qiskit/circuit/library/standard_gates/p.py @@ -11,8 +11,9 @@ # that they have been altered from the originals. """Phase Gate.""" + +from __future__ import annotations from cmath import exp -from typing import Optional, Union import numpy from qiskit.circuit.controlledgate import ControlledGate from qiskit.circuit.gate import Gate @@ -74,7 +75,7 @@ class PhaseGate(Gate): `1612.00858 `_ """ - def __init__(self, theta: ParameterValueType, label: Optional[str] = None): + def __init__(self, theta: ParameterValueType, label: str | None = None): """Create new Phase gate.""" super().__init__("p", 1, [theta], label=label) @@ -91,8 +92,8 @@ def _define(self): def control( self, num_ctrl_qubits: int = 1, - label: Optional[str] = None, - ctrl_state: Optional[Union[int, str]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ): """Return a (multi-)controlled-Phase gate. @@ -106,7 +107,7 @@ def control( ControlledGate: controlled version of this gate. """ if num_ctrl_qubits == 1: - gate = CPhaseGate(self.params[0], label=label, ctrl_state=ctrl_state) + gate: Gate = CPhaseGate(self.params[0], label=label, ctrl_state=ctrl_state) elif ctrl_state is None and num_ctrl_qubits > 1: gate = MCPhaseGate(self.params[0], num_ctrl_qubits, label=label) else: @@ -174,8 +175,8 @@ class CPhaseGate(ControlledGate): def __init__( self, theta: ParameterValueType, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ): """Create new CPhase gate.""" super().__init__( @@ -216,8 +217,8 @@ def _define(self): def control( self, num_ctrl_qubits: int = 1, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ): """Controlled version of this gate. @@ -283,7 +284,7 @@ class MCPhaseGate(ControlledGate): The singly-controlled-version of this gate. """ - def __init__(self, lam: ParameterValueType, num_ctrl_qubits: int, label: Optional[str] = None): + def __init__(self, lam: ParameterValueType, num_ctrl_qubits: int, label: str | None = None): """Create new MCPhase gate.""" super().__init__( "mcphase", @@ -317,8 +318,8 @@ def _define(self): def control( self, num_ctrl_qubits: int = 1, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ): """Controlled version of this gate. diff --git a/qiskit/circuit/library/standard_gates/u1.py b/qiskit/circuit/library/standard_gates/u1.py index e39c9cc5f46b..8fc66fb96e0d 100644 --- a/qiskit/circuit/library/standard_gates/u1.py +++ b/qiskit/circuit/library/standard_gates/u1.py @@ -11,6 +11,7 @@ # that they have been altered from the originals. """U1 Gate.""" +from __future__ import annotations from cmath import exp from typing import Optional, Union import numpy @@ -92,7 +93,7 @@ class U1Gate(Gate): `1612.00858 `_ """ - def __init__(self, theta: ParameterValueType, label: Optional[str] = None): + def __init__(self, theta: ParameterValueType, label: str | None = None): """Create new U1 gate.""" super().__init__("u1", 1, [theta], label=label) @@ -112,7 +113,7 @@ def _define(self): def control( self, num_ctrl_qubits: int = 1, - label: Optional[str] = None, + label: str | None = None, ctrl_state: Optional[Union[str, int]] = None, ): """Return a (multi-)controlled-U1 gate. @@ -127,7 +128,7 @@ def control( ControlledGate: controlled version of this gate. """ if num_ctrl_qubits == 1: - gate = CU1Gate(self.params[0], label=label, ctrl_state=ctrl_state) + gate: Gate = CU1Gate(self.params[0], label=label, ctrl_state=ctrl_state) elif ctrl_state is None and num_ctrl_qubits > 1: gate = MCU1Gate(self.params[0], num_ctrl_qubits, label=label) else: @@ -187,7 +188,7 @@ class CU1Gate(ControlledGate): def __init__( self, theta: ParameterValueType, - label: Optional[str] = None, + label: str | None = None, ctrl_state: Optional[Union[str, int]] = None, ): """Create new CU1 gate.""" @@ -235,7 +236,7 @@ def _define(self): def control( self, num_ctrl_qubits: int = 1, - label: Optional[str] = None, + label: str | None = None, ctrl_state: Optional[Union[str, int]] = None, ): """Controlled version of this gate. @@ -301,7 +302,7 @@ def __init__( self, lam: ParameterValueType, num_ctrl_qubits: int, - label: Optional[str] = None, + label: str | None = None, ctrl_state: Optional[Union[str, int]] = None, ): """Create new MCU1 gate.""" @@ -339,7 +340,7 @@ def _define(self): def control( self, num_ctrl_qubits: int = 1, - label: Optional[str] = None, + label: str | None = None, ctrl_state: Optional[Union[str, int]] = None, ): """Controlled version of this gate. diff --git a/qiskit/circuit/library/standard_gates/x.py b/qiskit/circuit/library/standard_gates/x.py index 2ebee778683e..01a867f8ca38 100644 --- a/qiskit/circuit/library/standard_gates/x.py +++ b/qiskit/circuit/library/standard_gates/x.py @@ -11,8 +11,8 @@ # that they have been altered from the originals. """X, CX, CCX and multi-controlled X gates.""" - -from typing import Optional, Union +from __future__ import annotations +from typing import Optional, Union, Type from math import ceil import numpy from qiskit.circuit.controlledgate import ControlledGate @@ -930,7 +930,7 @@ def __new__( """ # The CXGate and CCXGate will be implemented for all modes of the MCX, and # the C3XGate and C4XGate will be implemented in the MCXGrayCode class. - explicit = {1: CXGate, 2: CCXGate} + explicit: dict[int, Type[ControlledGate]] = {1: CXGate, 2: CCXGate} if num_ctrl_qubits in explicit: gate_class = explicit[num_ctrl_qubits] gate = gate_class.__new__(gate_class, label=label, ctrl_state=ctrl_state) diff --git a/qiskit/circuit/library/templates/rzx/rzx_cy.py b/qiskit/circuit/library/templates/rzx/rzx_cy.py index 2ca641ab8ede..6f1caf6116b3 100644 --- a/qiskit/circuit/library/templates/rzx/rzx_cy.py +++ b/qiskit/circuit/library/templates/rzx/rzx_cy.py @@ -20,11 +20,15 @@ └───┘└───────┘└───┘└────────┘└──────────┘└───────┘└──────────┘└─────────┘ """ +from __future__ import annotations + import numpy as np + from qiskit.circuit import Parameter, QuantumCircuit +from qiskit.circuit.parameterexpression import ParameterValueType -def rzx_cy(theta: float = None): +def rzx_cy(theta: ParameterValueType | None = None): """Template for CX - RYGate - CX.""" if theta is None: theta = Parameter("ϴ") diff --git a/qiskit/circuit/library/templates/rzx/rzx_xz.py b/qiskit/circuit/library/templates/rzx/rzx_xz.py index 4def8657e9aa..5be019c17efe 100644 --- a/qiskit/circuit/library/templates/rzx/rzx_xz.py +++ b/qiskit/circuit/library/templates/rzx/rzx_xz.py @@ -25,11 +25,15 @@ « """ +from __future__ import annotations + import numpy as np + from qiskit.circuit import Parameter, QuantumCircuit +from qiskit.circuit.parameterexpression import ParameterValueType -def rzx_xz(theta: float = None): +def rzx_xz(theta: ParameterValueType | None = None): """Template for CX - RXGate - CX.""" if theta is None: theta = Parameter("ϴ") diff --git a/qiskit/circuit/library/templates/rzx/rzx_yz.py b/qiskit/circuit/library/templates/rzx/rzx_yz.py index 96c4655f6d5e..552ad0e2daf9 100644 --- a/qiskit/circuit/library/templates/rzx/rzx_yz.py +++ b/qiskit/circuit/library/templates/rzx/rzx_yz.py @@ -19,12 +19,15 @@ q_1: ┤ X ├──────────┤ X ├───────────┤1 ├──────────── └───┘ └───┘ └─────────┘ """ +from __future__ import annotations import numpy as np + from qiskit.circuit import Parameter, QuantumCircuit +from qiskit.circuit.parameterexpression import ParameterValueType -def rzx_yz(theta: float = None): +def rzx_yz(theta: ParameterValueType | None = None): """Template for CX - RYGate - CX.""" if theta is None: theta = Parameter("ϴ") diff --git a/qiskit/circuit/library/templates/rzx/rzx_zz1.py b/qiskit/circuit/library/templates/rzx/rzx_zz1.py index 8eb715c3bcbc..628af513eaff 100644 --- a/qiskit/circuit/library/templates/rzx/rzx_zz1.py +++ b/qiskit/circuit/library/templates/rzx/rzx_zz1.py @@ -29,12 +29,15 @@ «q_1: ┤ RZ(π/2) ├ « └─────────┘ """ +from __future__ import annotations import numpy as np + from qiskit.circuit import Parameter, QuantumCircuit +from qiskit.circuit.parameterexpression import ParameterValueType -def rzx_zz1(theta: float = None): +def rzx_zz1(theta: ParameterValueType | None = None): """Template for CX - RZGate - CX.""" if theta is None: theta = Parameter("ϴ") diff --git a/qiskit/circuit/library/templates/rzx/rzx_zz2.py b/qiskit/circuit/library/templates/rzx/rzx_zz2.py index cd6774b337c2..334f25fffe9f 100644 --- a/qiskit/circuit/library/templates/rzx/rzx_zz2.py +++ b/qiskit/circuit/library/templates/rzx/rzx_zz2.py @@ -25,11 +25,15 @@ « └──────────┘└─────────┘└─────────┘└─────────┘ """ +from __future__ import annotations + import numpy as np + from qiskit.circuit import Parameter, QuantumCircuit +from qiskit.circuit.parameterexpression import ParameterValueType -def rzx_zz2(theta: float = None): +def rzx_zz2(theta: ParameterValueType | None = None): """Template for CX - RZGate - CX.""" if theta is None: theta = Parameter("ϴ") diff --git a/qiskit/circuit/library/templates/rzx/rzx_zz3.py b/qiskit/circuit/library/templates/rzx/rzx_zz3.py index b1e117367f73..83c8e1d66425 100644 --- a/qiskit/circuit/library/templates/rzx/rzx_zz3.py +++ b/qiskit/circuit/library/templates/rzx/rzx_zz3.py @@ -24,12 +24,15 @@ «q_1: ┤1 ├┤ RZ(π/2) ├┤ RX(π/2) ├┤ RZ(π/2) ├ « └──────────┘└─────────┘└─────────┘└─────────┘ """ +from __future__ import annotations import numpy as np + from qiskit.circuit import Parameter, QuantumCircuit +from qiskit.circuit.parameterexpression import ParameterValueType -def rzx_zz3(theta: float = None): +def rzx_zz3(theta: ParameterValueType | None = None): """Template for CX - RZGate - CX.""" if theta is None: theta = Parameter("ϴ") diff --git a/qiskit/circuit/operation.py b/qiskit/circuit/operation.py index d4d2a719a9b8..6a17ae7cd69b 100644 --- a/qiskit/circuit/operation.py +++ b/qiskit/circuit/operation.py @@ -43,19 +43,19 @@ class Operation(ABC): __slots__ = () - @property + @property # type: ignore @abstractmethod def name(self): """Unique string identifier for operation type.""" raise NotImplementedError - @property + @property # type: ignore @abstractmethod def num_qubits(self): """Number of qubits.""" raise NotImplementedError - @property + @property # type: ignore @abstractmethod def num_clbits(self): """Number of classical bits.""" diff --git a/qiskit/circuit/parameterexpression.py b/qiskit/circuit/parameterexpression.py index 31879cf57e31..488ab394994a 100644 --- a/qiskit/circuit/parameterexpression.py +++ b/qiskit/circuit/parameterexpression.py @@ -12,7 +12,9 @@ """ ParameterExpression Class to enable creating simple expressions of Parameters. """ -from typing import Callable, Dict, Set, Union + +from __future__ import annotations +from typing import Callable, Union import numbers import operator @@ -33,7 +35,7 @@ class ParameterExpression: __slots__ = ["_parameter_symbols", "_parameters", "_symbol_expr", "_name_map"] - def __init__(self, symbol_map: Dict, expr): + def __init__(self, symbol_map: dict, expr): """Create a new :class:`ParameterExpression`. Not intended to be called directly, but to be instantiated via operations @@ -48,15 +50,15 @@ def __init__(self, symbol_map: Dict, expr): self._parameter_symbols = symbol_map self._parameters = set(self._parameter_symbols) self._symbol_expr = expr - self._name_map = None + self._name_map: dict | None = None @property - def parameters(self) -> Set: + def parameters(self) -> set: """Returns a set of the unbound Parameters in the expression.""" return self._parameters @property - def _names(self) -> Dict: + def _names(self) -> dict: """Returns a mapping of parameter names to Parameters in the expression.""" if self._name_map is None: self._name_map = {p.name: p for p in self._parameters} @@ -91,7 +93,7 @@ def assign(self, parameter, value: ParameterValueType) -> "ParameterExpression": return self.bind({parameter: value}) def bind( - self, parameter_values: Dict, allow_unknown_parameters: bool = False + self, parameter_values: dict, allow_unknown_parameters: bool = False ) -> "ParameterExpression": """Binds the provided set of parameters to their corresponding values. @@ -147,7 +149,7 @@ def bind( return ParameterExpression(free_parameter_symbols, bound_symbol_expr) def subs( - self, parameter_map: Dict, allow_unknown_parameters: bool = False + self, parameter_map: dict, allow_unknown_parameters: bool = False ) -> "ParameterExpression": """Returns a new Expression with replacement Parameters. @@ -557,4 +559,4 @@ def sympify(self): # Redefine the type so external imports get an evaluated reference; Sphinx needs this to understand # the type hints. -ParameterValueType = Union[ParameterExpression, float] +ParameterValueType = Union[ParameterExpression, float] # TODO: should include ParameterVector? diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index f75aef9db0bd..0b1c5b203268 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -22,22 +22,22 @@ import multiprocessing as mp import string import re +import typing from collections import OrderedDict, defaultdict, namedtuple from typing import ( Union, - Optional, List, - Dict, - Tuple, + Optional, Type, TypeVar, Sequence, Callable, Mapping, - Set, Iterable, + Any, + DefaultDict, + cast, ) -import typing import numpy as np from qiskit.exceptions import QiskitError, MissingOptionalLibraryError from qiskit.utils.multiprocessing import is_main_process @@ -224,16 +224,16 @@ class QuantumCircuit: def __init__( self, - *regs: Union[Register, int, Sequence[Bit]], - name: Optional[str] = None, + *regs: Register | int | Sequence[Bit], + name: str | None = None, global_phase: ParameterValueType = 0, - metadata: Optional[Dict] = None, + metadata: dict | None = None, ): if any(not isinstance(reg, (list, QuantumRegister, ClassicalRegister)) for reg in regs): # check if inputs are integers, but also allow e.g. 2.0 try: - valid_reg_size = all(reg == int(reg) for reg in regs) + valid_reg_size = all(reg == int(reg) for reg in regs) # type:ignore[arg-type] except (ValueError, TypeError): valid_reg_size = False @@ -259,7 +259,7 @@ def __init__( # Data contains a list of instructions and their contexts, # in the order they were applied. - self._data = [] + self._data: list[CircuitInstruction] = [] self._op_start_times = None # A stack to hold the instruction sets that are being built up during for-, if- and @@ -268,22 +268,24 @@ def __init__( # builder interfaces need to wait until they are completed before they can fill in things # like `break` and `continue`. This is because these instructions need to "operate" on the # full width of bits, but the builder interface won't know what bits are used until the end. - self._control_flow_scopes = [] + self._control_flow_scopes: list[ + "qiskit.circuit.controlflow.builder.ControlFlowBuilderBlock" + ] = [] - self.qregs = [] - self.cregs = [] - self._qubits = [] - self._clbits = [] + self.qregs: list[QuantumRegister] = [] + self.cregs: list[ClassicalRegister] = [] + self._qubits: list[Qubit] = [] + self._clbits: list[Clbit] = [] # Dict mapping Qubit or Clbit instances to tuple comprised of 0) the # corresponding index in circuit.{qubits,clbits} and 1) a list of # Register-int pairs for each Register containing the Bit and its index # within that register. - self._qubit_indices = {} - self._clbit_indices = {} + self._qubit_indices: dict[Qubit, BitLocations] = {} + self._clbit_indices: dict[Clbit, BitLocations] = {} - self._ancillas = [] - self._calibrations = defaultdict(dict) + self._ancillas: list[AncillaQubit] = [] + self._calibrations: DefaultDict[str, dict[tuple, Any]] = defaultdict(dict) self.add_register(*regs) # Parameter table tracks instructions with variable parameters. @@ -313,9 +315,9 @@ def from_instructions( *, qubits: Iterable[Qubit] = (), clbits: Iterable[Clbit] = (), - name: Optional[str] = None, + name: str | None = None, global_phase: ParameterValueType = 0, - metadata: Optional[dict] = None, + metadata: dict | None = None, ) -> "QuantumCircuit": """Construct a circuit from an iterable of CircuitInstructions. @@ -365,27 +367,6 @@ def data(self) -> QuantumCircuitData: """ return QuantumCircuitData(self) - @property - def op_start_times(self) -> List[int]: - """Return a list of operation start times. - - This attribute is enabled once one of scheduling analysis passes - runs on the quantum circuit. - - Returns: - List of integers representing instruction start times. - The index corresponds to the index of instruction in :attr:`QuantumCircuit.data`. - - Raises: - AttributeError: When circuit is not scheduled. - """ - if self._op_start_times is None: - raise AttributeError( - "This circuit is not scheduled. " - "To schedule it run the circuit through one of the transpiler scheduling passes." - ) - return self._op_start_times - @data.setter def data(self, data_input: Iterable): """Sets the circuit data from a list of instructions and context. @@ -412,6 +393,27 @@ def data(self, data_input: Iterable): for instruction, qargs, cargs in data_input: self.append(instruction, qargs, cargs) + @property + def op_start_times(self) -> list[int]: + """Return a list of operation start times. + + This attribute is enabled once one of scheduling analysis passes + runs on the quantum circuit. + + Returns: + List of integers representing instruction start times. + The index corresponds to the index of instruction in :attr:`QuantumCircuit.data`. + + Raises: + AttributeError: When circuit is not scheduled. + """ + if self._op_start_times is None: + raise AttributeError( + "This circuit is not scheduled. " + "To schedule it run the circuit through one of the transpiler scheduling passes." + ) + return self._op_start_times + @property def calibrations(self) -> dict: """Return calibration dictionary. @@ -431,7 +433,7 @@ def calibrations(self, calibrations: dict): """ self._calibrations = defaultdict(dict, calibrations) - def has_calibration_for(self, instr_context: Tuple): + def has_calibration_for(self, instr_context: tuple): """Return True if the circuit has a calibration defined for the instruction context. In this case, the operation does not need to be translated to the device basis. """ @@ -462,7 +464,7 @@ def metadata(self) -> dict: return self._metadata @metadata.setter - def metadata(self, metadata: Optional[dict]): + def metadata(self, metadata: dict | None): """Update the circuit metadata""" if not isinstance(metadata, dict) and metadata is not None: raise TypeError("Only a dictionary or None is accepted for circuit metadata") @@ -748,8 +750,8 @@ def power(self, power: float, matrix_power: bool = False) -> "QuantumCircuit": def control( self, num_ctrl_qubits: int = 1, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> "QuantumCircuit": """Control this circuit on ``num_ctrl_qubits`` qubits. @@ -786,8 +788,8 @@ def control( def compose( self, other: Union["QuantumCircuit", Instruction], - qubits: Optional[Union[QubitSpecifier, Sequence[QubitSpecifier]]] = None, - clbits: Optional[Union[ClbitSpecifier, Sequence[ClbitSpecifier]]] = None, + qubits: QubitSpecifier | Sequence[QubitSpecifier] | None = None, + clbits: ClbitSpecifier | Sequence[ClbitSpecifier] | None = None, front: bool = False, inplace: bool = False, wrap: bool = False, @@ -877,8 +879,10 @@ def compose( if not isinstance(other, QuantumCircuit): if qubits is None: qubits = self.qubits[: other.num_qubits] + qubits = cast(List[Qubit], qubits) if clbits is None: clbits = self.clbits[: other.num_clbits] + clbits = cast(List[Clbit], clbits) if front: # Need to keep a reference to the data for use after we've emptied it. old_data = list(dest.data) @@ -898,7 +902,7 @@ def compose( ) # number of qubits and clbits must match number in circuit or None - edge_map = {} + edge_map: dict[Qubit | Clbit, Qubit | Clbit] = {} if qubits is None: edge_map.update(zip(other.qubits, dest.qubits)) else: @@ -921,11 +925,11 @@ def compose( ) edge_map.update(zip(other.clbits, dest.cbit_argument_conversion(clbits))) - mapped_instrs = [] + mapped_instrs: list[CircuitInstruction] = [] condition_register_map = {} for instr in other.data: - n_qargs = [edge_map[qarg] for qarg in instr.qubits] - n_cargs = [edge_map[carg] for carg in instr.clbits] + n_qargs: list[Qubit] = [cast(Qubit, edge_map[qarg]) for qarg in instr.qubits] + n_cargs: list[Clbit] = [cast(Clbit, edge_map[carg]) for carg in instr.clbits] n_op = instr.operation.copy() # Map their registers over to ours, adding an extra one if there's no exact match. @@ -1057,21 +1061,21 @@ def tensor(self, other: "QuantumCircuit", inplace: bool = False) -> Optional["Qu return dest @property - def qubits(self) -> List[Qubit]: + def qubits(self) -> list[Qubit]: """ Returns a list of quantum bits in the order that the registers were added. """ return self._qubits @property - def clbits(self) -> List[Clbit]: + def clbits(self) -> list[Clbit]: """ Returns a list of classical bits in the order that the registers were added. """ return self._clbits @property - def ancillas(self) -> List[AncillaQubit]: + def ancillas(self) -> list[AncillaQubit]: """ Returns a list of ancilla bits in the order that the registers were added. """ @@ -1104,7 +1108,7 @@ def __getitem__(self, item: int) -> CircuitInstruction: ... @typing.overload - def __getitem__(self, item: slice) -> List[CircuitInstruction]: + def __getitem__(self, item: slice) -> list[CircuitInstruction]: ... def __getitem__(self, item): @@ -1119,7 +1123,7 @@ def cast(value: S, type_: Callable[..., T]) -> Union[S, T]: except (ValueError, TypeError): return value - def qbit_argument_conversion(self, qubit_representation: QubitSpecifier) -> List[Qubit]: + def qbit_argument_conversion(self, qubit_representation: QubitSpecifier) -> list[Qubit]: """ Converts several qubit representations (such as indexes, range, etc.) into a list of qubits. @@ -1134,7 +1138,7 @@ def qbit_argument_conversion(self, qubit_representation: QubitSpecifier) -> List qubit_representation, self.qubits, self._qubit_indices, Qubit ) - def cbit_argument_conversion(self, clbit_representation: ClbitSpecifier) -> List[Clbit]: + def cbit_argument_conversion(self, clbit_representation: ClbitSpecifier) -> list[Clbit]: """ Converts several classical bit representations (such as indexes, range, etc.) into a list of classical bits. @@ -1191,9 +1195,9 @@ def _resolve_classical_resource(self, specifier): def append( self, - instruction: Union[Operation, CircuitInstruction], - qargs: Optional[Sequence[QubitSpecifier]] = None, - cargs: Optional[Sequence[ClbitSpecifier]] = None, + instruction: Operation | CircuitInstruction, + qargs: Sequence[QubitSpecifier] | None = None, + cargs: Sequence[ClbitSpecifier] | None = None, ) -> InstructionSet: """Append one or more instructions to the end of the circuit, modifying the circuit in place. @@ -1293,7 +1297,12 @@ def _append( ) -> Operation: ... - def _append(self, instruction, qargs=None, cargs=None): + def _append( + self, + instruction, + qargs: Sequence[Qubit] | None = None, + cargs: Sequence[Clbit] | None = None, + ): """Append an instruction to the end of the circuit, modifying the circuit in place. .. warning:: @@ -1356,7 +1365,7 @@ def _update_parameter_table(self, instruction: CircuitInstruction): # clear cache if new parameter is added self._parameters = None - def add_register(self, *regs: Union[Register, int, Sequence[Bit]]) -> None: + def add_register(self, *regs: Register | int | Sequence[Bit]) -> None: """Add registers.""" if not regs: return @@ -1372,11 +1381,11 @@ def add_register(self, *regs: Union[Register, int, Sequence[Bit]]) -> None: elif len(regs) == 2 and all(isinstance(reg, int) for reg in regs): # QuantumCircuit with anonymous wires e.g. QuantumCircuit(2, 3) if regs[0] == 0: - qregs = () + qregs: tuple[QuantumRegister, ...] = () else: qregs = (QuantumRegister(regs[0], "q"),) if regs[1] == 0: - cregs = () + cregs: tuple[ClassicalRegister, ...] = () else: cregs = (ClassicalRegister(regs[1], "c"),) regs = qregs + cregs @@ -1491,8 +1500,8 @@ def _check_dups(self, qubits: Sequence[Qubit]) -> None: def to_instruction( self, - parameter_map: Optional[Dict[Parameter, ParameterValueType]] = None, - label: Optional[str] = None, + parameter_map: dict[Parameter, ParameterValueType] | None = None, + label: str | None = None, ) -> Instruction: """Create an Instruction out of this circuit. @@ -1513,8 +1522,8 @@ def to_instruction( def to_gate( self, - parameter_map: Optional[Dict[Parameter, ParameterValueType]] = None, - label: Optional[str] = None, + parameter_map: dict[Parameter, ParameterValueType] | None = None, + label: str | None = None, ) -> Gate: """Create a Gate out of this circuit. @@ -1535,9 +1544,7 @@ def to_gate( def decompose( self, - gates_to_decompose: Optional[ - Union[Type[Gate], Sequence[Type[Gate]], Sequence[str], str] - ] = None, + gates_to_decompose: Type[Gate] | Sequence[Type[Gate]] | Sequence[str] | str | None = None, reps: int = 1, ) -> "QuantumCircuit": """Call a decomposition pass on this circuit, @@ -1569,9 +1576,9 @@ def decompose( def qasm( self, formatted: bool = False, - filename: Optional[str] = None, - encoding: Optional[str] = None, - ) -> Optional[str]: + filename: str | None = None, + encoding: str | None = None, + ) -> str | None: """Return OpenQASM string. Args: @@ -1644,25 +1651,25 @@ def qasm( "c4x", ] - existing_composite_circuits = [] + existing_composite_circuits: list[Instruction] = [] string_temp = self.header + "\n" string_temp += self.extension_lib + "\n" regless_qubits = [bit for bit in self.qubits if not self.find_bit(bit).registers] regless_clbits = [bit for bit in self.clbits if not self.find_bit(bit).registers] - dummy_registers = [] + dummy_registers: list[QuantumRegister | ClassicalRegister] = [] if regless_qubits: dummy_registers.append(QuantumRegister(name="qregless", bits=regless_qubits)) if regless_clbits: dummy_registers.append(ClassicalRegister(name="cregless", bits=regless_clbits)) - register_escaped_names = {} + register_escaped_names: dict[str, QuantumRegister | ClassicalRegister] = {} for regs in (self.qregs, self.cregs, dummy_registers): for reg in regs: register_escaped_names[ _make_unique(_qasm_escape_name(reg.name, "reg_"), register_escaped_names) ] = reg - bit_labels = { + bit_labels: dict[Qubit | Clbit, str] = { bit: "%s[%d]" % (name, idx) for name, register in register_escaped_names.items() for (idx, bit) in enumerate(register) @@ -1751,21 +1758,21 @@ def qasm( def draw( self, - output: Optional[str] = None, - scale: Optional[float] = None, - filename: Optional[str] = None, - style: Optional[Union[dict, str]] = None, + output: str | None = None, + scale: float | None = None, + filename: str | None = None, + style: dict | str | None = None, interactive: bool = False, plot_barriers: bool = True, reverse_bits: bool = None, - justify: Optional[str] = None, - vertical_compression: Optional[str] = "medium", + justify: str | None = None, + vertical_compression: str | None = "medium", idle_wires: bool = True, with_layout: bool = True, - fold: Optional[int] = None, + fold: int | None = None, # The type of ax is matplotlib.axes.Axes, but this is not a fixed dependency, so cannot be # safely forward-referenced. - ax: Optional[typing.Any] = None, + ax: Any | None = None, initial_state: bool = False, cregbundle: bool = None, wire_order: list = None, @@ -1911,7 +1918,7 @@ def draw( def size( self, - filter_function: Optional[callable] = lambda x: not getattr( + filter_function: Callable[..., int] = lambda x: not getattr( x.operation, "_directive", False ), ) -> int: @@ -1929,7 +1936,7 @@ def size( def depth( self, - filter_function: Optional[callable] = lambda x: not getattr( + filter_function: Callable[..., int] = lambda x: not getattr( x.operation, "_directive", False ), ) -> int: @@ -1951,7 +1958,9 @@ def depth( """ # Assign each bit in the circuit a unique integer # to index into op_stack. - bit_indices = {bit: idx for idx, bit in enumerate(self.qubits + self.clbits)} + bit_indices: dict[Qubit | Clbit, int] = { + bit: idx for idx, bit in enumerate(self.qubits + self.clbits) + } # If no bits, return 0 if not bit_indices: @@ -2034,7 +2043,7 @@ def count_ops(self) -> "OrderedDict[Instruction, int]": Returns: OrderedDict: a breakdown of how many operations of each kind, sorted by amount. """ - count_ops: Dict[Instruction, int] = {} + count_ops: dict[Instruction, int] = {} for instruction in self._data: count_ops[instruction.operation.name] = count_ops.get(instruction.operation.name, 0) + 1 return OrderedDict(sorted(count_ops.items(), key=lambda kv: kv[1], reverse=True)) @@ -2052,7 +2061,7 @@ def num_nonlocal_gates(self) -> int: multi_qubit_gates += 1 return multi_qubit_gates - def get_instructions(self, name: str) -> List[CircuitInstruction]: + def get_instructions(self, name: str) -> list[CircuitInstruction]: """Get instructions matching name. Args: @@ -2074,7 +2083,7 @@ def num_connected_components(self, unitary_only: bool = False) -> int: """ # Convert registers to ints (as done in depth). bits = self.qubits if unitary_only else (self.qubits + self.clbits) - bit_indices = {bit: idx for idx, bit in enumerate(bits)} + bit_indices: dict[Qubit | Clbit, int] = {bit: idx for idx, bit in enumerate(bits)} # Start with each qubit or cbit being its own subgraph. sub_graphs = [[bit] for bit in range(len(bit_indices))] @@ -2153,7 +2162,7 @@ def num_tensor_factors(self) -> int: """ return self.num_unitary_factors() - def copy(self, name: Optional[str] = None) -> "QuantumCircuit": + def copy(self, name: str | None = None) -> "QuantumCircuit": """Copy the circuit. Args: @@ -2185,7 +2194,7 @@ def copy(self, name: Optional[str] = None) -> "QuantumCircuit": return cpy - def copy_empty_like(self, name: Optional[str] = None) -> "QuantumCircuit": + def copy_empty_like(self, name: str | None = None) -> "QuantumCircuit": """Return a copy of self with the same structure but empty. That structure includes: @@ -2590,7 +2599,7 @@ def num_parameters(self) -> int: """The number of parameter objects in the circuit.""" return len(self._unsorted_parameters()) - def _unsorted_parameters(self) -> Set[Parameter]: + def _unsorted_parameters(self) -> set[Parameter]: """Efficiently get all parameters in the circuit, without any sorting overhead.""" parameters = set(self._parameter_table) if isinstance(self.global_phase, ParameterExpression): @@ -2742,8 +2751,8 @@ def bind_parameters( def _unroll_param_dict( self, value_dict: Mapping[Parameter, ParameterValueType] - ) -> Dict[Parameter, ParameterValueType]: - unrolled_value_dict: Dict[Parameter, ParameterValueType] = {} + ) -> dict[Parameter, ParameterValueType]: + unrolled_value_dict: dict[Parameter, ParameterValueType] = {} for (param, value) in value_dict.items(): if isinstance(param, ParameterVector): if not len(param) == len(value): @@ -2871,7 +2880,7 @@ def barrier(self, *qargs: QubitSpecifier, label=None) -> InstructionSet: """ from .barrier import Barrier - qubits: List[QubitSpecifier] = [] + qubits: list[QubitSpecifier] = [] if not qargs: # None qubits.extend(self.qubits) @@ -2893,7 +2902,7 @@ def barrier(self, *qargs: QubitSpecifier, label=None) -> InstructionSet: def delay( self, duration: ParameterValueType, - qarg: Optional[QubitSpecifier] = None, + qarg: QubitSpecifier | None = None, unit: str = "dt", ) -> InstructionSet: """Apply :class:`~.circuit.Delay`. If qarg is ``None``, applies to all qubits. @@ -2912,7 +2921,7 @@ def delay( Raises: CircuitError: if arguments have bad format. """ - qubits: List[QubitSpecifier] = [] + qubits: list[QubitSpecifier] = [] if qarg is None: # -> apply delays to all qubits for q in self.qubits: qubits.append(q) @@ -2930,7 +2939,9 @@ def delay( instructions = InstructionSet(resource_requester=self._resolve_classical_resource) for q in qubits: - inst = (Delay(duration, unit), [q], []) + inst: tuple[ + Instruction, Sequence[QubitSpecifier] | None, Sequence[ClbitSpecifier] | None + ] = (Delay(duration, unit), [q], []) self.append(*inst) instructions.add(*inst) return instructions @@ -2954,8 +2965,8 @@ def ch( self, control_qubit: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: """Apply :class:`~qiskit.circuit.library.CHGate`. @@ -3047,8 +3058,8 @@ def cp( theta: ParameterValueType, control_qubit: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: """Apply :class:`~qiskit.circuit.library.CPhaseGate`. @@ -3192,7 +3203,7 @@ def rcccx( ) def rx( - self, theta: ParameterValueType, qubit: QubitSpecifier, label: Optional[str] = None + self, theta: ParameterValueType, qubit: QubitSpecifier, label: str | None = None ) -> InstructionSet: """Apply :class:`~qiskit.circuit.library.RXGate`. @@ -3215,8 +3226,8 @@ def crx( theta: ParameterValueType, control_qubit: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: """Apply :class:`~qiskit.circuit.library.CRXGate`. @@ -3260,7 +3271,7 @@ def rxx( return self.append(RXXGate(theta), [qubit1, qubit2], []) def ry( - self, theta: ParameterValueType, qubit: QubitSpecifier, label: Optional[str] = None + self, theta: ParameterValueType, qubit: QubitSpecifier, label: str | None = None ) -> InstructionSet: """Apply :class:`~qiskit.circuit.library.RYGate`. @@ -3283,8 +3294,8 @@ def cry( theta: ParameterValueType, control_qubit: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: """Apply :class:`~qiskit.circuit.library.CRYGate`. @@ -3348,8 +3359,8 @@ def crz( theta: ParameterValueType, control_qubit: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: """Apply :class:`~qiskit.circuit.library.CRZGate`. @@ -3460,8 +3471,8 @@ def cs( self, control_qubit: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: """Apply :class:`~qiskit.circuit.library.CSGate`. @@ -3490,8 +3501,8 @@ def csdg( self, control_qubit: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: """Apply :class:`~qiskit.circuit.library.CSdgGate`. @@ -3551,8 +3562,8 @@ def cswap( control_qubit: QubitSpecifier, target_qubit1: QubitSpecifier, target_qubit2: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: """Apply :class:`~qiskit.circuit.library.CSwapGate`. @@ -3635,8 +3646,8 @@ def csx( self, control_qubit: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: """Apply :class:`~qiskit.circuit.library.CSXGate`. @@ -3723,8 +3734,8 @@ def cu( gamma: ParameterValueType, control_qubit: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: r"""Apply :class:`~qiskit.circuit.library.CUGate`. @@ -3753,7 +3764,7 @@ def cu( [], ) - def x(self, qubit: QubitSpecifier, label: Optional[str] = None) -> InstructionSet: + def x(self, qubit: QubitSpecifier, label: str | None = None) -> InstructionSet: r"""Apply :class:`~qiskit.circuit.library.XGate`. For the full matrix form of this gate, see the underlying gate documentation. @@ -3773,8 +3784,8 @@ def cx( self, control_qubit: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: r"""Apply :class:`~qiskit.circuit.library.CXGate`. @@ -3802,8 +3813,8 @@ def cnot( self, control_qubit: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: r"""Apply :class:`~qiskit.circuit.library.CXGate`. @@ -3846,7 +3857,7 @@ def ccx( control_qubit1: QubitSpecifier, control_qubit2: QubitSpecifier, target_qubit: QubitSpecifier, - ctrl_state: Optional[Union[str, int]] = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: r"""Apply :class:`~qiskit.circuit.library.CCXGate`. @@ -3898,7 +3909,7 @@ def mcx( self, control_qubits: Sequence[QubitSpecifier], target_qubit: QubitSpecifier, - ancilla_qubits: Optional[Union[QubitSpecifier, Sequence[QubitSpecifier]]] = None, + ancilla_qubits: QubitSpecifier | Sequence[QubitSpecifier] | None = None, mode: str = "noancilla", ) -> InstructionSet: """Apply :class:`~qiskit.circuit.library.MCXGate`. @@ -3961,6 +3972,9 @@ def mcx( # convert ancilla qubits to a list if they were passed as int or qubit if not hasattr(ancilla_qubits, "__len__"): ancilla_qubits = [ancilla_qubits] + ancilla_qubits = cast( + Union[QuantumRegister, Sequence[Qubit], Sequence[int]], ancilla_qubits + ) if len(ancilla_qubits) < required: actually = len(ancilla_qubits) @@ -3976,7 +3990,7 @@ def mct( self, control_qubits: Sequence[QubitSpecifier], target_qubit: QubitSpecifier, - ancilla_qubits: Optional[Union[QubitSpecifier, Sequence[QubitSpecifier]]] = None, + ancilla_qubits: QubitSpecifier | Sequence[QubitSpecifier] | None = None, mode: str = "noancilla", ) -> InstructionSet: """Apply :class:`~qiskit.circuit.library.MCXGate`. @@ -4028,8 +4042,8 @@ def cy( self, control_qubit: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: r"""Apply :class:`~qiskit.circuit.library.CYGate`. @@ -4071,8 +4085,8 @@ def cz( self, control_qubit: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: r"""Apply :class:`~qiskit.circuit.library.CZGate`. @@ -4100,8 +4114,8 @@ def ccz( control_qubit1: QubitSpecifier, control_qubit2: QubitSpecifier, target_qubit: QubitSpecifier, - label: Optional[str] = None, - ctrl_state: Optional[Union[str, int]] = None, + label: str | None = None, + ctrl_state: str | int | None = None, ) -> InstructionSet: r"""Apply :class:`~qiskit.circuit.library.CCZGate`. @@ -4229,7 +4243,7 @@ def _update_parameter_table_on_instruction_removal(self, instruction: CircuitIns :meth:`.QuantumCircuit.append`, so this should be safe. Trying to account for it would involve adding a potentially quadratic-scaling loop to check each entry in ``data``. """ - atomic_parameters = [] + atomic_parameters: list[tuple[Parameter, int]] = [] for index, parameter in enumerate(instruction.operation.params): if isinstance(parameter, (ParameterExpression, QuantumCircuit)): atomic_parameters.extend((p, index) for p in parameter.parameters) @@ -4246,24 +4260,24 @@ def _update_parameter_table_on_instruction_removal(self, instruction: CircuitIns @typing.overload def while_loop( self, - condition: Tuple[Union[ClassicalRegister, Clbit], int], + condition: tuple[ClassicalRegister | Clbit, int], body: None, qubits: None, clbits: None, *, - label: Optional[str], + label: str | None, ) -> "qiskit.circuit.controlflow.while_loop.WhileLoopContext": ... @typing.overload def while_loop( self, - condition: Tuple[Union[ClassicalRegister, Clbit], int], + condition: tuple[ClassicalRegister | Clbit, int], body: "QuantumCircuit", qubits: Sequence[QubitSpecifier], clbits: Sequence[ClbitSpecifier], *, - label: Optional[str], + label: str | None, ) -> InstructionSet: ... @@ -4333,12 +4347,12 @@ def while_loop(self, condition, body=None, qubits=None, clbits=None, *, label=No def for_loop( self, indexset: Iterable[int], - loop_parameter: Optional[Parameter], + loop_parameter: Parameter | None, body: None, qubits: None, clbits: None, *, - label: Optional[str], + label: str | None, ) -> "qiskit.circuit.controlflow.for_loop.ForLoopContext": ... @@ -4351,7 +4365,7 @@ def for_loop( qubits: Sequence[QubitSpecifier], clbits: Sequence[ClbitSpecifier], *, - label: Optional[str], + label: str | None, ) -> InstructionSet: ... @@ -4426,24 +4440,24 @@ def for_loop( @typing.overload def if_test( self, - condition: Tuple[Union[ClassicalRegister, Clbit], int], + condition: tuple[ClassicalRegister | Clbit, int], true_body: None, qubits: None, clbits: None, *, - label: Optional[str], + label: str | None, ) -> "qiskit.circuit.controlflow.if_else.IfContext": ... @typing.overload def if_test( self, - condition: Tuple[Union[ClassicalRegister, Clbit], int], + condition: tuple[ClassicalRegister | Clbit, int], true_body: "QuantumCircuit", qubits: Sequence[QubitSpecifier], clbits: Sequence[ClbitSpecifier], *, - label: Optional[str] = None, + label: str | None = None, ) -> InstructionSet: ... @@ -4536,16 +4550,12 @@ def if_test( def if_else( self, - condition: Union[ - Tuple[ClassicalRegister, int], - Tuple[Clbit, int], - Tuple[Clbit, bool], - ], + condition: tuple[ClassicalRegister, int] | tuple[Clbit, int] | tuple[Clbit, bool], true_body: "QuantumCircuit", false_body: "QuantumCircuit", qubits: Sequence[QubitSpecifier], clbits: Sequence[ClbitSpecifier], - label: Optional[str] = None, + label: str | None = None, ) -> InstructionSet: """Apply :class:`~qiskit.circuit.IfElseOp`. @@ -4662,7 +4672,7 @@ def add_calibration( # needs the types available at runtime, whereas mypy will accept it, because it handles the # type checking by static analysis. schedule, - params: Optional[Sequence[ParameterValueType]] = None, + params: Sequence[ParameterValueType] | None = None, ) -> None: """Register a low-level, custom pulse definition for the given gate. @@ -4700,6 +4710,7 @@ def _format(operand): params = tuple(map(_format, params)) else: params = () + gate = cast(str, gate) self._calibrations[gate][(tuple(qubits), params)] = schedule @@ -4831,8 +4842,8 @@ def _compare_parameters(param1: Parameter, param2: Parameter) -> int: def _add_sub_instruction_to_existing_composite_circuits( instruction: Instruction, - existing_gate_names: List[str], - existing_composite_circuits: List[Instruction], + existing_gate_names: list[str], + existing_composite_circuits: list[Instruction], ) -> None: """Recursively add undefined sub-instructions in the definition of the given instruction to existing_composite_circuit list. @@ -4931,7 +4942,7 @@ def _get_composite_circuit_qasm_from_instruction(instruction: Instruction) -> st def _insert_composite_gate_definition_qasm( - string_temp: str, existing_composite_circuits: List[Instruction], extension_lib: str + string_temp: str, existing_composite_circuits: list[Instruction], extension_lib: str ) -> str: """Insert composite gate definition QASM code right after extension library in the header""" @@ -4940,7 +4951,7 @@ def _insert_composite_gate_definition_qasm( # Generate gate definition string for instruction in existing_composite_circuits: if hasattr(instruction, "_qasm_definition"): - qasm_string = instruction._qasm_definition + qasm_string = instruction._qasm_definition # type: ignore[attr-defined] else: qasm_string = _get_composite_circuit_qasm_from_instruction(instruction) gate_definition_string += "\n" + qasm_string @@ -4949,7 +4960,7 @@ def _insert_composite_gate_definition_qasm( return string_temp -def _bit_argument_conversion(specifier, bit_sequence, bit_set, type_): +def _bit_argument_conversion(specifier, bit_sequence, bit_set, type_) -> list[Bit]: """Get the list of bits referred to by the specifier ``specifier``. Valid types for ``specifier`` are integers, bits of the correct type (as given in ``type_``), or diff --git a/qiskit/circuit/register.py b/qiskit/circuit/register.py index 7038a7e9cd3c..60b92e94ccc1 100644 --- a/qiskit/circuit/register.py +++ b/qiskit/circuit/register.py @@ -15,6 +15,8 @@ """ Base register reference object. """ + +from __future__ import annotations import re import itertools import warnings @@ -59,7 +61,7 @@ class Register: prefix = "reg" bit_type = None - def __init__(self, size=None, name=None, bits=None): + def __init__(self, size: int | None = None, name: str | None = None, bits=None): """Create a new generic register. Either the ``size`` or the ``bits`` argument must be provided. If