Skip to content

Commit

Permalink
Fix mypy errors (transpiler) (#8266)
Browse files Browse the repository at this point in the history
* Fix transpiler mypy errors

* Fix review comments, add a bit more annotations

* Fix annotation

* Fix sphinx

* Fix lint

* Update dynamical_decoupling.py

* Replace deprecated function call

* Update qiskit/transpiler/passes/layout/disjoint_utils.py

Co-authored-by: Luciano Bello <bel@zurich.ibm.com>

* Fix type definition

---------

Co-authored-by: Luciano Bello <bel@zurich.ibm.com>
  • Loading branch information
Randl and 1ucian0 committed May 22, 2023
1 parent 7b677ed commit e1056ee
Show file tree
Hide file tree
Showing 27 changed files with 239 additions and 204 deletions.
30 changes: 17 additions & 13 deletions qiskit/transpiler/instruction_durations.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
# that they have been altered from the originals.

"""Durations of instructions, one of transpiler configurations."""
from typing import Optional, List, Tuple, Union, Iterable, Set
from __future__ import annotations
from typing import Optional, List, Tuple, Union, Iterable

import qiskit.circuit
from qiskit.circuit import Barrier, Delay
from qiskit.circuit import Instruction, Qubit, ParameterExpression
from qiskit.circuit.duration import duration_in_dt
Expand All @@ -22,7 +24,7 @@
from qiskit.utils.units import apply_prefix


def _is_deprecated_qubits_argument(qubits: Union[int, List[int], Qubit, List[Qubit]]) -> bool:
def _is_deprecated_qubits_argument(qubits: Union[int, list[int], Qubit, list[Qubit]]) -> bool:
if isinstance(qubits, (int, Qubit)):
qubits = [qubits]
return isinstance(qubits[0], Qubit)
Expand All @@ -41,11 +43,13 @@ class InstructionDurations:
"""

def __init__(
self, instruction_durations: Optional["InstructionDurationsType"] = None, dt: float = None
self, instruction_durations: "InstructionDurationsType" | None = None, dt: float = None
):
self.duration_by_name = {}
self.duration_by_name_qubits = {}
self.duration_by_name_qubits_params = {}
self.duration_by_name: dict[str, tuple[float, str]] = {}
self.duration_by_name_qubits: dict[tuple[str, tuple[int, ...]], tuple[float, str]] = {}
self.duration_by_name_qubits_params: dict[
tuple[str, tuple[int, ...], tuple[float, ...]], tuple[float, str]
] = {}
self.dt = dt
if instruction_durations:
self.update(instruction_durations)
Expand Down Expand Up @@ -99,7 +103,7 @@ def from_backend(cls, backend: Backend):

return InstructionDurations(instruction_durations, dt=dt)

def update(self, inst_durations: Optional["InstructionDurationsType"], dt: float = None):
def update(self, inst_durations: "InstructionDurationsType" | None, dt: float = None):
"""Update self with inst_durations (inst_durations overwrite self).
Args:
Expand Down Expand Up @@ -177,10 +181,10 @@ def update(self, inst_durations: Optional["InstructionDurationsType"], dt: float
)
def get(
self,
inst: Union[str, Instruction],
qubits: Union[int, List[int], Qubit, List[Qubit]],
inst: str | qiskit.circuit.Instruction,
qubits: int | list[int] | Qubit | list[Qubit] | list[int | Qubit],
unit: str = "dt",
parameters: Optional[List[float]] = None,
parameters: list[float] | None = None,
) -> float:
"""Get the duration of the instruction with the name, qubits, and parameters.
Expand Down Expand Up @@ -224,9 +228,9 @@ def get(
def _get(
self,
name: str,
qubits: List[int],
qubits: list[int],
to_unit: str,
parameters: Optional[Iterable[float]] = None,
parameters: Iterable[float] | None = None,
) -> float:
"""Get the duration of the instruction with the name, qubits, and parameters."""
if name == "barrier":
Expand Down Expand Up @@ -270,7 +274,7 @@ def _convert_unit(self, duration: float, from_unit: str, to_unit: str) -> float:
else:
raise TranspilerError(f"Conversion from '{from_unit}' to '{to_unit}' is not supported")

def units_used(self) -> Set[str]:
def units_used(self) -> set[str]:
"""Get the set of all units used in this instruction durations.
Returns:
Expand Down
9 changes: 4 additions & 5 deletions qiskit/transpiler/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
Virtual (qu)bits are tuples, e.g. `(QuantumRegister(3, 'qr'), 2)` or simply `qr[2]`.
Physical (qu)bits are integers.
"""

from __future__ import annotations
from dataclasses import dataclass
from typing import Dict, Optional

from qiskit.circuit.quantumregister import Qubit, QuantumRegister
from qiskit.transpiler.exceptions import LayoutError
Expand Down Expand Up @@ -262,7 +261,7 @@ def combine_into_edge_map(self, another_layout):

return edge_map

def reorder_bits(self, bits):
def reorder_bits(self, bits) -> list[int]:
"""Given an ordered list of bits, reorder them according to this layout.
The list of bits must exactly match the virtual bits in this layout.
Expand Down Expand Up @@ -401,5 +400,5 @@ class TranspileLayout:
"""

initial_layout: Layout
input_qubit_mapping: Dict[Qubit, int]
final_layout: Optional[Layout] = None
input_qubit_mapping: dict[Qubit, int]
final_layout: Layout | None = None
15 changes: 8 additions & 7 deletions qiskit/transpiler/passes/calibration/rzx_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
# that they have been altered from the originals.

"""RZX calibration builders."""
from __future__ import annotations

import enum
import warnings
from collections.abc import Sequence
from math import pi, erf
from typing import List, Tuple, Union

import numpy as np
from qiskit.circuit import Instruction as CircuitInst
Expand Down Expand Up @@ -68,7 +69,7 @@ class RZXCalibrationBuilder(CalibrationBuilder):
def __init__(
self,
instruction_schedule_map: InstructionScheduleMap = None,
qubit_channel_mapping: List[List[str]] = None,
qubit_channel_mapping: list[list[str]] = None,
verbose: bool = True,
target: Target = None,
):
Expand Down Expand Up @@ -97,7 +98,7 @@ def __init__(
if self._inst_map is None:
raise QiskitError("Calibrations can only be added to Pulse-enabled backends")

def supported(self, node_op: CircuitInst, qubits: List) -> bool:
def supported(self, node_op: CircuitInst, qubits: list) -> bool:
"""Determine if a given node supports the calibration.
Args:
Expand Down Expand Up @@ -166,7 +167,7 @@ def rescale_cr_inst(instruction: Play, theta: float, sample_mult: int = 16) -> i

return round_duration

def get_calibration(self, node_op: CircuitInst, qubits: List) -> Union[Schedule, ScheduleBlock]:
def get_calibration(self, node_op: CircuitInst, qubits: list) -> Schedule | ScheduleBlock:
"""Builds the calibration schedule for the RZXGate(theta) with echos.
Args:
Expand Down Expand Up @@ -260,7 +261,7 @@ class RZXCalibrationBuilderNoEcho(RZXCalibrationBuilder):
of the CX gate.
"""

def get_calibration(self, node_op: CircuitInst, qubits: List) -> Union[Schedule, ScheduleBlock]:
def get_calibration(self, node_op: CircuitInst, qubits: list) -> Schedule | ScheduleBlock:
"""Builds the calibration schedule for the RZXGate(theta) without echos.
Args:
Expand Down Expand Up @@ -336,8 +337,8 @@ def _filter_comp_tone(time_inst_tup):


def _check_calibration_type(
inst_sched_map: InstructionScheduleMap, qubits: List[int]
) -> Tuple[CRCalType, List[Play], List[Play]]:
inst_sched_map: InstructionScheduleMap, qubits: Sequence[int]
) -> tuple[CRCalType, list[Play], list[Play]]:
"""A helper function to check type of CR calibration.
Args:
Expand Down
22 changes: 16 additions & 6 deletions qiskit/transpiler/passes/layout/disjoint_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
# that they have been altered from the originals.

"""This module contains common utils for disjoint coupling maps."""

from __future__ import annotations
from collections import defaultdict
from typing import List, Callable, TypeVar, Dict, Union
import uuid

import rustworkx as rx
from qiskit.dagcircuit import DAGOpNode

from qiskit.circuit import Qubit, Barrier, Clbit
from qiskit.dagcircuit.dagcircuit import DAGCircuit
Expand Down Expand Up @@ -65,7 +66,7 @@ def run_pass_over_connected_components(
for qreg in dag.qregs:
out_dag.add_qreg(qreg)
for creg in dag.cregs:
out_dag.add_cregs(creg)
out_dag.add_creg(creg)
out_dag.compose(dag, qubits=dag.qubits, clbits=dag.clbits)
out_component_pairs.append((out_dag, cmap_components[cmap_index]))
res = [run_func(out_dag, cmap) for out_dag, cmap in out_component_pairs]
Expand Down Expand Up @@ -119,7 +120,7 @@ def split_barriers(dag: DAGCircuit):
def combine_barriers(dag: DAGCircuit, retain_uuid: bool = True):
"""Mutate input dag to combine barriers with UUID labels into a single barrier."""
qubit_indices = {bit: index for index, bit in enumerate(dag.qubits)}
uuid_map = {}
uuid_map: dict[uuid.UUID, DAGOpNode] = {}
for node in dag.op_nodes(Barrier):
if isinstance(node.op.label, uuid.UUID):
barrier_uuid = node.op.label
Expand All @@ -139,9 +140,18 @@ def combine_barriers(dag: DAGCircuit, retain_uuid: bool = True):

def require_layout_isolated_to_component(
dag: DAGCircuit, components_source: Union[Target, CouplingMap]
) -> bool:
"""Check that the layout of the dag does not require connectivity across connected components
in the CouplingMap"""
):
"""
Check that the layout of the dag does not require connectivity across connected components
in the CouplingMap
Args:
dag: DAGCircuit to check.
components_source: Target to check against.
Raises:
TranspilerError: Chosen layout is not valid for the target disjoint connectivity.
"""
if isinstance(components_source, Target):
coupling_map = components_source.build_coupling_map(filter_idle_qubits=True)
else:
Expand Down
11 changes: 5 additions & 6 deletions qiskit/transpiler/passes/routing/algorithms/token_swapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@

"""Permutation algorithms for general graphs."""

from __future__ import annotations
import copy
import logging
from typing import Iterator, Mapping, MutableMapping, MutableSet, List, Iterable, Union
from collections.abc import Mapping, MutableSet, MutableMapping, Iterator, Iterable

import numpy as np
import rustworkx as rx
Expand All @@ -46,9 +47,7 @@ class ApproximateTokenSwapper:
Internally caches the graph and associated datastructures for re-use.
"""

def __init__(
self, graph: rx.PyGraph, seed: Union[int, np.random.Generator, None] = None
) -> None:
def __init__(self, graph: rx.PyGraph, seed: int | np.random.Generator | None = None) -> None:
"""Construct an ApproximateTokenSwapping object.
Args:
Expand Down Expand Up @@ -80,7 +79,7 @@ def permutation_circuit(self, permutation: Permutation, trials: int = 4) -> Perm
parallel_swaps = [[swap] for swap in sequential_swaps]
return permutation_circuit(parallel_swaps)

def map(self, mapping: Mapping[int, int], trials: int = 4) -> List[Swap[int]]:
def map(self, mapping: Mapping[int, int], trials: int = 4) -> list[Swap[int]]:
"""Perform an approximately optimal Token Swapping algorithm to implement the permutation.
Supports partial mappings (i.e. not-permutations) for graphs with missing tokens.
Expand Down Expand Up @@ -113,7 +112,7 @@ def map(self, mapping: Mapping[int, int], trials: int = 4) -> List[Swap[int]]:
)

# Once we find a zero solution we stop.
def take_until_zero(results: Iterable[List[int]]) -> Iterator[List[int]]:
def take_until_zero(results: Iterable[list[Swap[int]]]) -> Iterable[list[Swap[int]]]:
"""Take results until one is emitted of length zero (and also emit that)."""
for result in results:
yield result
Expand Down
11 changes: 7 additions & 4 deletions qiskit/transpiler/passes/routing/algorithms/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@

"""Utility functions shared between permutation functionality."""

from typing import List, TypeVar, Iterable, MutableMapping
from __future__ import annotations

from collections.abc import Iterable
from typing import TypeVar, MutableMapping

from qiskit.circuit import QuantumRegister
from qiskit.dagcircuit import DAGCircuit
Expand All @@ -53,8 +56,8 @@ def swap_permutation(
for swap_step in swaps:
for sw1, sw2 in swap_step:
# Take into account non-existent keys.
val1 = None # type: Optional[_V]
val2 = None # type: Optional[_V]
val1: _V | None = None
val2: _V | None = None
if allow_missing_keys:
val1 = mapping.pop(sw1, None)
val2 = mapping.pop(sw2, None)
Expand All @@ -68,7 +71,7 @@ def swap_permutation(
mapping[sw1] = val2


def permutation_circuit(swaps: Iterable[List[Swap[_V]]]) -> PermutationCircuit:
def permutation_circuit(swaps: Iterable[list[Swap[_V]]]) -> PermutationCircuit:
"""Produce a circuit description of a list of swaps.
With a given permutation and permuter you can compute the swaps using the permuter function
then feed it into this circuit function to obtain a circuit description.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
# that they have been altered from the originals.

"""A gate made of commuting two-qubit gates."""
from __future__ import annotations

from typing import Iterable
from collections.abc import Iterable

from qiskit.exceptions import QiskitError
from qiskit.circuit import Gate
from qiskit.circuit import Gate, Qubit, Clbit
from qiskit.dagcircuit import DAGOpNode


Expand All @@ -34,7 +35,8 @@ def __init__(self, node_block: Iterable[DAGOpNode]) -> None:
Raises:
QiskitError: If the nodes in the node block do not apply to two-qubits.
"""
qubits, cbits = set(), set()
qubits: set[Qubit] = set()
cbits: set[Clbit] = set()
for node in node_block:
if len(node.qargs) != 2:
raise QiskitError(f"Node {node.name} does not apply to two-qubits.")
Expand Down
Loading

0 comments on commit e1056ee

Please sign in to comment.