Skip to content

Commit

Permalink
Fix mypy errors (circuit) (Qiskit#8267)
Browse files Browse the repository at this point in the history
* Fix circuit mypy errors

* Fix 2

* Remove ignores

* Remove ignores for sure

* Remove TODO

* fix for docs

* Add annotation

* Fix control bug, remove unnecessary annotation

* Add test and fix description

* Fix test

* Reformat

* Fix test description

* Update releasenotes/notes/fix-control-with-string-parameter-4eb8a308170e08db.yaml

Co-authored-by: Julien Gacon <gaconju@gmail.com>

* More minor fixes

* Fix callable import

* Fix Instruction import for sphinx

* Replace list[Any] with list

---------

Co-authored-by: Julien Gacon <gaconju@gmail.com>
  • Loading branch information
2 people authored and giacomoRanieri committed Apr 16, 2023
1 parent b19ecde commit ebcaccc
Show file tree
Hide file tree
Showing 42 changed files with 487 additions and 396 deletions.
22 changes: 11 additions & 11 deletions qiskit/circuit/add_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@
# 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
from . import ControlledGate, Gate, QuantumRegister, QuantumCircuit
from ._utils import _ctrl_state_to_int


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().
Expand Down Expand Up @@ -51,8 +51,6 @@ def add_control(
Controlled version of gate.
"""
if ctrl_state is None:
ctrl_state = 2**num_ctrl_qubits - 1
if isinstance(operation, UnitaryGate):
# attempt decomposition
operation._define()
Expand All @@ -62,10 +60,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
Expand Down Expand Up @@ -93,6 +91,8 @@ def control(
# pylint: disable=cyclic-import
from qiskit.circuit import controlledgate

ctrl_state = _ctrl_state_to_int(ctrl_state, num_ctrl_qubits)

q_control = QuantumRegister(num_ctrl_qubits, name="control")
q_target = QuantumRegister(operation.num_qubits, name="target")
q_ancillae = None # TODO: add
Expand Down
5 changes: 3 additions & 2 deletions qiskit/circuit/controlflow/control_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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.
Expand Down
7 changes: 4 additions & 3 deletions qiskit/circuit/controlledgate.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down
19 changes: 9 additions & 10 deletions qiskit/circuit/gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@

"""Unitary gate."""

from typing import List, Optional, Union, Tuple
from __future__ import annotations
from typing import Iterator, Iterable
import numpy as np

from qiskit.circuit.parameterexpression import ParameterExpression
Expand All @@ -23,9 +24,7 @@
class Gate(Instruction):
"""Unitary gate."""

def __init__(
self, name: str, num_qubits: int, params: List, label: Optional[str] = None
) -> None:
def __init__(self, name: str, num_qubits: int, params: list, label: str | None = None) -> None:
"""Create a new gate.
Args:
Expand Down Expand Up @@ -95,8 +94,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.
Expand All @@ -120,7 +119,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) -> Iterator[tuple[list, list]]:
"""Expands a single argument.
For example: [q[0], q[1]] -> [q[0]], [q[1]]
Expand All @@ -131,7 +130,7 @@ 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, qarg1: list) -> Iterator[tuple[list, list]]:
if len(qarg0) == len(qarg1):
# [[q[0], q[1]], [r[0], r[1]]] -> [q[0], r[0]]
# -> [q[1], r[1]]
Expand All @@ -153,14 +152,14 @@ 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) -> Iterator[tuple[list, list]]:
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, cargs: list) -> Iterable[tuple[list, list]]:
"""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
Expand Down
24 changes: 17 additions & 7 deletions qiskit/circuit/instructionset.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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: list[ClassicalRegister] | None = 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
Expand Down Expand Up @@ -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'.")
Expand All @@ -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

Expand Down Expand Up @@ -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``.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -78,12 +80,12 @@ 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")
registers.append(qr_cin)
else:
qr_cin = []
qr_cin = QuantumRegister(0)

qr_a = QuantumRegister(num_state_qubits, name="a")
qr_b = QuantumRegister(num_state_qubits, name="b")
Expand All @@ -94,15 +96,15 @@ def __init__(
qr_cout = QuantumRegister(1, name="cout")
registers.append(qr_cout)
else:
qr_cout = []
qr_cout = QuantumRegister(0)

self.add_register(*registers)

if num_state_qubits > 1:
qr_help = AncillaRegister(num_state_qubits - 1, name="helper")
self.add_register(qr_help)
else:
qr_help = []
qr_help = AncillaRegister(0)

# the code is simplified a lot if we create a list of all carries and helpers
carries = qr_cin[:] + qr_help[:] + qr_cout[:]
Expand Down
10 changes: 5 additions & 5 deletions qiskit/circuit/library/arithmetic/integer_comparator.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

"""Integer Comparator."""

from typing import List, Optional
from __future__ import annotations
import warnings
import numpy as np

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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.
Expand All @@ -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:
Expand Down
12 changes: 6 additions & 6 deletions qiskit/circuit/library/arithmetic/linear_amplitude_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

"""A class implementing a (piecewise-) linear function on qubit amplitudes."""

from typing import Optional, List, Union, Tuple
from __future__ import annotations
import numpy as np
from qiskit.circuit import QuantumCircuit

Expand Down Expand Up @@ -77,12 +77,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"""
Expand Down
Loading

0 comments on commit ebcaccc

Please sign in to comment.