Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
13592cc
docs: add PEP 484 type hints to transpiler analysis and utility passes
Hadar01 Mar 18, 2026
dd4df44
Merge branch 'main' into feat/add-type-hints-analysis-passes
Hadar01 Mar 19, 2026
8c5662d
Merge branch 'main' into feat/add-type-hints-analysis-passes
Hadar01 Mar 19, 2026
f53935c
Refactor import statements in count_ops.py
Hadar01 Mar 26, 2026
57e984d
Refactor imports and update docstring formatting
Hadar01 Mar 26, 2026
2b6a512
Refactor import statements and update docstring
Hadar01 Mar 26, 2026
f953847
Refactor imports and update docstring formatting
Hadar01 Mar 26, 2026
5962863
Refactor import statement for TYPE_CHECKING
Hadar01 Mar 26, 2026
0d614bc
Apply suggestion from @Cryoris
Hadar01 Mar 26, 2026
e9572cf
Refactor imports and docstring formatting
Hadar01 Mar 26, 2026
9680725
Refactor import statements and docstring formatting
Hadar01 Mar 26, 2026
0bc1b34
Refactor imports and update docstring format
Hadar01 Mar 26, 2026
74a9466
Refactor import statements in width.py
Hadar01 Mar 26, 2026
66ee428
Update instruction_name type to Iterable in ContainsInstruction
Hadar01 Mar 26, 2026
3507ba7
Update dag_fixed_point.py
Hadar01 Mar 26, 2026
ce141dd
Refactor imports and docstrings in fixed_point.py
Hadar01 Mar 26, 2026
5dd8d15
Add copyright notice and docstring to count_ops.py
Hadar01 Mar 26, 2026
2d5814a
Add docstring for counting operations in DAGCircuit
Hadar01 Mar 26, 2026
467e5f4
Add type checking for DAGCircuit import
Hadar01 Mar 26, 2026
fbf4347
Add copyright notice and docstring to depth.py
Hadar01 Mar 26, 2026
1090259
Add copyright notice and docstring to num_qubits.py
Hadar01 Mar 26, 2026
5c44af7
Import DAGCircuit for type checking
Hadar01 Mar 26, 2026
5c40f3c
Update resource_estimation.py for type checking
Hadar01 Mar 26, 2026
2f6dd11
Add copyright notice and docstring to size.py
Hadar01 Mar 26, 2026
4a7a027
Update width.py
Hadar01 Mar 26, 2026
9438f0d
Update copyright notice in contains_instruction.py
Hadar01 Mar 26, 2026
46127b0
Update copyright notice in dag_fixed_point.py
Hadar01 Mar 26, 2026
e6b3e69
Add copyright notice and docstring to fixed_point.py
Hadar01 Mar 26, 2026
5b0d5fb
Update fixed point tracking in DAG utility
Hadar01 Mar 26, 2026
6a38dd8
Fix fixed point property update logic
Hadar01 Mar 26, 2026
573b959
Remove unnecessary blank line in fixed_point.py
Hadar01 Mar 26, 2026
f18a82f
Remove unnecessary blank line in dag_fixed_point.py
Hadar01 Mar 26, 2026
ecc51c2
Merge branch 'main' into feat/add-type-hints-analysis-passes
Hadar01 Mar 28, 2026
7d5a06c
Merge branch 'main' into feat/add-type-hints-analysis-passes
Hadar01 Mar 30, 2026
b86fbd1
fix: use from __future__ import annotations with TYPE_CHECKING guard
Hadar01 Mar 30, 2026
c8021f2
Merge branch 'main' into feat/add-type-hints-analysis-passes
Hadar01 Apr 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions qiskit/transpiler/passes/analysis/count_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it's much easier to see the module docstring with this whitespace, could you leave these as they were?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about that! Restored the blank lines , will keep whitespace as in the originals going forward.

"""Count the operations in a DAG circuit."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from qiskit.dagcircuit import DAGCircuit

from qiskit.transpiler.basepasses import AnalysisPass


Expand All @@ -21,10 +28,15 @@ class CountOps(AnalysisPass):
The result is saved in ``property_set['count_ops']`` as an integer.
"""

def __init__(self, *, recurse=True):
def __init__(self, *, recurse: bool = True) -> None:
"""
Args:
recurse: If ``True`` (default), recursively count operations
inside control-flow blocks.
"""
super().__init__()
self.recurse = recurse

def run(self, dag):
"""Run the CountOps pass on `dag`."""
def run(self, dag: DAGCircuit) -> None:
"""Run the CountOps pass on ``dag``."""
self.property_set["count_ops"] = dag.count_ops(recurse=self.recurse)
11 changes: 9 additions & 2 deletions qiskit/transpiler/passes/analysis/count_ops_longest_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

"""Count the operations on the longest path in a DAGCircuit."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from qiskit.dagcircuit import DAGCircuit

from qiskit.transpiler.basepasses import AnalysisPass


Expand All @@ -21,6 +28,6 @@ class CountOpsLongestPath(AnalysisPass):
The result is saved in ``property_set['count_ops_longest_path']`` as an integer.
"""

def run(self, dag):
"""Run the CountOpsLongestPath pass on `dag`."""
def run(self, dag: DAGCircuit) -> None:
"""Run the CountOpsLongestPath pass on ``dag``."""
self.property_set["count_ops_longest_path"] = dag.count_ops_longest_path()
11 changes: 9 additions & 2 deletions qiskit/transpiler/passes/analysis/dag_longest_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,20 @@

"""Return the longest path in a :class:`.DAGCircuit` as a list of DAGNodes."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from qiskit.dagcircuit import DAGCircuit

from qiskit.transpiler.basepasses import AnalysisPass


class DAGLongestPath(AnalysisPass):
"""Return the longest path in a :class:`.DAGCircuit` as a list of
:class:`.DAGOpNode`\\ s, :class:`.DAGInNode`\\ s, and :class:`.DAGOutNode`\\ s."""

def run(self, dag):
"""Run the DAGLongestPath pass on `dag`."""
def run(self, dag: DAGCircuit) -> None:
"""Run the DAGLongestPath pass on ``dag``."""
self.property_set["dag_longest_path"] = dag.longest_path()
13 changes: 10 additions & 3 deletions qiskit/transpiler/passes/analysis/depth.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,20 @@

"""Calculate the depth of a DAG circuit."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from qiskit.dagcircuit import DAGCircuit

from qiskit.transpiler.basepasses import AnalysisPass


class Depth(AnalysisPass):
"""Calculate the depth of a DAG circuit."""

def __init__(self, *, recurse=False):
def __init__(self, *, recurse: bool = False) -> None:
"""
Args:
recurse: whether to allow recursion into control flow. If this is ``False`` (default),
Expand All @@ -28,6 +35,6 @@ def __init__(self, *, recurse=False):
super().__init__()
self.recurse = recurse

def run(self, dag):
"""Run the Depth pass on `dag`."""
def run(self, dag: DAGCircuit) -> None:
"""Run the Depth pass on ``dag``."""
self.property_set["depth"] = dag.depth(recurse=self.recurse)
11 changes: 9 additions & 2 deletions qiskit/transpiler/passes/analysis/num_qubits.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

"""Calculate the number of qubits of a DAG circuit."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from qiskit.dagcircuit import DAGCircuit

from qiskit.transpiler.basepasses import AnalysisPass


Expand All @@ -21,6 +28,6 @@ class NumQubits(AnalysisPass):
The result is saved in ``property_set['num_qubits']`` as an integer.
"""

def run(self, dag):
"""Run the NumQubits pass on `dag`."""
def run(self, dag: DAGCircuit) -> None:
"""Run the NumQubits pass on ``dag``."""
self.property_set["num_qubits"] = dag.num_qubits()
11 changes: 9 additions & 2 deletions qiskit/transpiler/passes/analysis/num_tensor_factors.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

"""Calculate the number of tensor factors of a DAG circuit."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from qiskit.dagcircuit import DAGCircuit

from qiskit.transpiler.basepasses import AnalysisPass


Expand All @@ -21,6 +28,6 @@ class NumTensorFactors(AnalysisPass):
The result is saved in ``property_set['num_tensor_factors']`` as an integer.
"""

def run(self, dag):
"""Run the NumTensorFactors pass on `dag`."""
def run(self, dag: DAGCircuit) -> None:
"""Run the NumTensorFactors pass on ``dag``."""
self.property_set["num_tensor_factors"] = dag.num_tensor_factors()
15 changes: 12 additions & 3 deletions qiskit/transpiler/passes/analysis/resource_estimation.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

"""Automatically require analysis passes for resource estimation."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from qiskit.dagcircuit import DAGCircuit

from qiskit.transpiler.basepasses import AnalysisPass
from qiskit.transpiler.passes.analysis.depth import Depth
from qiskit.transpiler.passes.analysis.width import Width
Expand All @@ -25,16 +32,18 @@ class ResourceEstimation(AnalysisPass):
"""Automatically require analysis passes for resource estimation.

An analysis pass for automatically running:

* Depth()
* Width()
* Size()
* CountOps()
* NumTensorFactors()
* NumQubits()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh nice catch 👍🏻

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! 😊

"""

def __init__(self):
def __init__(self) -> None:
super().__init__()
self.requires += [Depth(), Width(), Size(), CountOps(), NumTensorFactors(), NumQubits()]

def run(self, _):
"""Run the ResourceEstimation pass on `dag`."""
def run(self, dag: DAGCircuit) -> None:
"""Run the ResourceEstimation pass on ``dag``."""
13 changes: 10 additions & 3 deletions qiskit/transpiler/passes/analysis/size.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

"""Calculate the size of a DAG circuit."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from qiskit.dagcircuit import DAGCircuit

from qiskit.transpiler.basepasses import AnalysisPass


Expand All @@ -21,7 +28,7 @@ class Size(AnalysisPass):
The result is saved in ``property_set['size']`` as an integer.
"""

def __init__(self, *, recurse=False):
def __init__(self, *, recurse: bool = False) -> None:
"""
Args:
recurse: whether to allow recursion into control flow. If this is ``False`` (default),
Expand All @@ -31,6 +38,6 @@ def __init__(self, *, recurse=False):
super().__init__()
self.recurse = recurse

def run(self, dag):
"""Run the Size pass on `dag`."""
def run(self, dag: DAGCircuit) -> None:
"""Run the Size pass on ``dag``."""
self.property_set["size"] = dag.size(recurse=self.recurse)
11 changes: 9 additions & 2 deletions qiskit/transpiler/passes/analysis/width.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

"""Calculate the width of a DAG circuit."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from qiskit.dagcircuit import DAGCircuit

from qiskit.transpiler.basepasses import AnalysisPass


Expand All @@ -22,6 +29,6 @@ class Width(AnalysisPass):
contains the number of qubits + the number of clbits.
"""

def run(self, dag):
"""Run the Width pass on `dag`."""
def run(self, dag: DAGCircuit) -> None:
"""Run the Width pass on ``dag``."""
self.property_set["width"] = dag.width()
23 changes: 15 additions & 8 deletions qiskit/transpiler/passes/utils/contains_instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Check if a property reached a fixed point."""
"""Check if the DAG contains a specific instruction."""

from __future__ import annotations

from collections.abc import Iterable
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from qiskit.dagcircuit import DAGCircuit

from qiskit.transpiler.basepasses import AnalysisPass

Expand All @@ -23,23 +31,22 @@ class ContainsInstruction(AnalysisPass):
that instruction and ``False`` if it does not.
"""

def __init__(self, instruction_name, recurse: bool = True):
"""ContainsInstruction initializer.

def __init__(self, instruction_name: str | Iterable[str], recurse: bool = True) -> None:
"""
Args:
instruction_name (str | Iterable[str]): The instruction or instructions to check are in
instruction_name: The instruction or instructions to check are in
the DAG. The output in the property set is set to ``contains_`` prefixed on each
value for this parameter.
recurse (bool): if ``True`` (default), then recurse into control-flow operations.
recurse: if ``True`` (default), then recurse into control-flow operations.
"""
super().__init__()
self._instruction_names = (
{instruction_name} if isinstance(instruction_name, str) else set(instruction_name)
)
self._recurse = recurse

def run(self, dag):
"""Run the ContainsInstruction pass on dag."""
def run(self, dag: DAGCircuit) -> None:
"""Run the ContainsInstruction pass on ``dag``."""
names = dag.count_ops(recurse=self._recurse)
for name in self._instruction_names:
self.property_set[f"contains_{name}"] = name in names
10 changes: 8 additions & 2 deletions qiskit/transpiler/passes/utils/dag_fixed_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@

"""Check if the DAG has reached a fixed point."""

from __future__ import annotations

from copy import deepcopy
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from qiskit.dagcircuit import DAGCircuit

from qiskit.transpiler.basepasses import AnalysisPass

Expand All @@ -25,8 +31,8 @@ class DAGFixedPoint(AnalysisPass):
``property_set['dag_fixed_point']`` as a boolean.
"""

def run(self, dag):
"""Run the DAGFixedPoint pass on `dag`."""
def run(self, dag: DAGCircuit) -> None:
"""Run the DAGFixedPoint pass on ``dag``."""
if self.property_set["_dag_fixed_point_previous_dag"] is None:
self.property_set["dag_fixed_point"] = False
else:
Expand Down
18 changes: 11 additions & 7 deletions qiskit/transpiler/passes/utils/fixed_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@

"""Check if a property reached a fixed point."""

from __future__ import annotations

from copy import deepcopy
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from qiskit.dagcircuit import DAGCircuit

from qiskit.transpiler.basepasses import AnalysisPass

Expand All @@ -25,20 +31,18 @@ class FixedPoint(AnalysisPass):
as a boolean.
"""

def __init__(self, property_to_check):
"""FixedPoint initializer.

def __init__(self, property_to_check: str) -> None:
"""
Args:
property_to_check (str): The property to check if a fixed point was reached.
property_to_check: The property to check if a fixed point was reached.
"""
super().__init__()
self._property = property_to_check

def run(self, dag):
"""Run the FixedPoint pass on `dag`."""
def run(self, dag: DAGCircuit) -> None:
"""Run the FixedPoint pass on ``dag``."""
current_value = self.property_set[self._property]
fixed_point_previous_property = f"_fixed_point_previous_{self._property}"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it'd be best to just revert all these line removals generally 😄

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about that! Restored the blank lines ,will keep whitespace as in the originals going forward.

if self.property_set[fixed_point_previous_property] is None:
self.property_set[f"{self._property}_fixed_point"] = False
else:
Expand Down