-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pulse Compiler SetSequence
pass
#11980
Merged
nkanazawa1989
merged 18 commits into
Qiskit:feature/pulse-ir
from
TsafrirA:SequencePass
Mar 12, 2024
Merged
Changes from 17 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
7cd1396
Basic implementation
TsafrirA a35abed
Add align right, align sequential (sequence+schedule)
TsafrirA 592aba6
Add draw, flatten
TsafrirA 8c83957
Corrections
TsafrirA b670356
Split into separate IR PR (temporary remove tests which rely on passes)
TsafrirA edf3749
Merge remote-tracking branch 'upstream/feature/pulse-ir' into OnlyIR2
TsafrirA 52158f6
Update qiskit/pulse/ir/ir.py
TsafrirA 1f0e13c
Corrections.
TsafrirA 8c19fbf
Add to do.
TsafrirA 4b91f55
Merge branch 'feature/pulse-ir' into OnlyIR2
TsafrirA 21dc703
Fixes
TsafrirA 13393b4
Disable lint
TsafrirA c828ab5
MapMixedFrame + SetSequence passes
TsafrirA f363271
Merge remote-tracking branch 'upstream/feature/pulse-ir' into Sequenc…
TsafrirA 50ec916
Doc fixes
TsafrirA e185741
Corrections
TsafrirA 01803ed
add todo
TsafrirA 7cc9186
Corrections.
TsafrirA File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# This code is part of Qiskit. | ||
# | ||
# (C) Copyright IBM 2024. | ||
# | ||
# This code is licensed under the Apache License, Version 2.0. You may | ||
# obtain a copy of this license in the LICENSE.txt file in the root directory | ||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. | ||
# | ||
# Any modifications or derivative works of this code must retain this | ||
# copyright notice, and modified files need to carry a notice indicating | ||
# that they have been altered from the originals. | ||
|
||
"""MixedFrames mapping analysis pass""" | ||
|
||
from __future__ import annotations | ||
from collections import defaultdict | ||
|
||
from qiskit.pulse.compiler.basepasses import AnalysisPass | ||
from qiskit.pulse.ir import SequenceIR | ||
from qiskit.pulse.model import MixedFrame | ||
|
||
|
||
class MapMixedFrame(AnalysisPass): | ||
r"""Map the dependencies of all class:`.MixedFrame`\s | ||
on class:`~qiskit.pulse.PulseTaraget` and :class:`~qiskit.pulse.Frame`. | ||
|
||
The pass recursively scans the :class:`.SequenceIR`, identifies all :class:`.MixedFrame`\s and | ||
tracks the dependencies of them on class:`~qiskit.pulse.PulseTaraget` and | ||
:class:`~qiskit.pulse.Frame`. The analysis result | ||
is added as a dictionary to the property set under key "mixed_frames_mapping". The | ||
added dictionary is keyed on every class:`~qiskit.pulse.PulseTaraget` and | ||
:class:`~qiskit.pulse.Frame` in :class:`.SequenceIR` | ||
with the value being a set of all class:`.MixedFrame`\s associated with the key. | ||
""" | ||
|
||
def __init__(self): | ||
"""Create new ``MapMixedFrames`` pass""" | ||
super().__init__(target=None) | ||
|
||
def run( | ||
self, | ||
passmanager_ir: SequenceIR, | ||
) -> None: | ||
"""Run ``MapMixedFrame`` pass""" | ||
mixed_frames_mapping = defaultdict(set) | ||
|
||
for inst_target in passmanager_ir.inst_targets: | ||
if isinstance(inst_target, MixedFrame): | ||
mixed_frames_mapping[inst_target.frame].add(inst_target) | ||
mixed_frames_mapping[inst_target.pulse_target].add(inst_target) | ||
self.property_set["mixed_frames_mapping"] = mixed_frames_mapping | ||
|
||
def __hash__(self): | ||
TsafrirA marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return hash((self.__class__.__name__,)) | ||
|
||
def __eq__(self, other): | ||
return self.__class__.__name__ == other.__class__.__name__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
# This code is part of Qiskit. | ||
# | ||
# (C) Copyright IBM 2024. | ||
# | ||
# This code is licensed under the Apache License, Version 2.0. You may | ||
# obtain a copy of this license in the LICENSE.txt file in the root directory | ||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. | ||
# | ||
# Any modifications or derivative works of this code must retain this | ||
# copyright notice, and modified files need to carry a notice indicating | ||
# that they have been altered from the originals. | ||
|
||
"""Sequencing pass for Qiskit PulseIR compilation.""" | ||
|
||
from __future__ import annotations | ||
from functools import singledispatchmethod | ||
from rustworkx import PyDAG | ||
|
||
from qiskit.pulse.compiler.basepasses import TransformationPass | ||
from qiskit.pulse.ir import SequenceIR | ||
from qiskit.pulse.model import MixedFrame | ||
from qiskit.pulse.transforms import AlignmentKind, SequentialAlignment, ParallelAlignment | ||
from qiskit.pulse.exceptions import PulseCompilerError | ||
|
||
|
||
class SetSequence(TransformationPass): | ||
"""Sets the sequence of a :class:`.SequenceIR` object. | ||
|
||
The pass traverses the :class:`.SequenceIR` and recursively sets the sequence, by adding edges to | ||
the ``sequence`` property. Sequencing is done according to the alignment strategy. | ||
|
||
For parallel alignment types, the pass depends on the results of the analysis pass | ||
:class:`~qiskit.pulse.compiler.passes.MapMixedFrame`. | ||
""" | ||
|
||
def __init__(self): | ||
"""Create new SetSequence pass""" | ||
super().__init__(target=None) | ||
|
||
def run( | ||
self, | ||
passmanager_ir: SequenceIR, | ||
) -> SequenceIR: | ||
"""Run sequencing pass. | ||
|
||
Arguments: | ||
passmanager_ir: The IR object to be sequenced. | ||
""" | ||
|
||
self._sequence_instructions(passmanager_ir.alignment, passmanager_ir.sequence) | ||
return passmanager_ir | ||
|
||
@singledispatchmethod | ||
def _sequence_instructions(self, alignment: AlignmentKind, sequence: PyDAG): | ||
"""Finalize the sequence by adding edges to the DAG | ||
|
||
``sequence`` is mutated to include all the edges | ||
connecting the elements of the sequence. | ||
|
||
Nested :class:`.SequenceIR` objects are sequenced recursively. | ||
""" | ||
raise NotImplementedError | ||
|
||
# pylint: disable=unused-argument | ||
@_sequence_instructions.register(ParallelAlignment) | ||
def _sequence_instructions_parallel(self, alignment: ParallelAlignment, sequence: PyDAG): | ||
"""Finalize the sequence by adding edges to the DAG, following parallel alignment. | ||
|
||
``sequence`` is mutated to include all the edges | ||
connecting the elements of the sequence in parallel. | ||
|
||
Nested :class:`.SequenceIR` objects are sequenced recursively. | ||
|
||
Args: | ||
alignment: The IR alignment. | ||
sequence: The graph object to be sequenced. | ||
|
||
Raises: | ||
PulseCompilerError: if ``property_set`` does not include a mixed_frames_mapping dictionary. | ||
""" | ||
if self.property_set["mixed_frames_mapping"] is None: | ||
TsafrirA marked this conversation as resolved.
Show resolved
Hide resolved
|
||
raise PulseCompilerError( | ||
"Parallel sequencing requires mixed frames mapping." | ||
" Run MapMixedFrame before sequencing" | ||
) | ||
|
||
mixed_frame_mapping = self.property_set["mixed_frames_mapping"] | ||
|
||
idle_after = {} | ||
for ind in sequence.node_indices(): | ||
if ind in (0, 1): | ||
# In, Out node | ||
continue | ||
node = sequence.get_node_data(ind) | ||
node_mixed_frames = set() | ||
|
||
if isinstance(node, SequenceIR): | ||
self._sequence_instructions(node.alignment, node.sequence) | ||
inst_targets = node.inst_targets | ||
else: | ||
inst_targets = [node.inst_target] | ||
|
||
for inst_target in inst_targets: | ||
if isinstance(inst_target, MixedFrame): | ||
node_mixed_frames.add(inst_target) | ||
else: | ||
node_mixed_frames |= mixed_frame_mapping[inst_target] | ||
|
||
pred_nodes = [ | ||
idle_after[mixed_frame] | ||
for mixed_frame in node_mixed_frames | ||
if mixed_frame in idle_after | ||
] | ||
if len(pred_nodes) == 0: | ||
pred_nodes = [0] | ||
for pred_node in pred_nodes: | ||
sequence.add_edge(pred_node, ind, None) | ||
for mixed_frame in node_mixed_frames: | ||
idle_after[mixed_frame] = ind | ||
sequence.add_edges_from_no_data([(ni, 1) for ni in idle_after.values()]) | ||
|
||
# pylint: disable=unused-argument | ||
@_sequence_instructions.register(SequentialAlignment) | ||
def _sequence_instructions_sequential(self, alignment: SequentialAlignment, sequence: PyDAG): | ||
"""Finalize the sequence by adding edges to the DAG, following sequential alignment. | ||
|
||
``sequence`` is mutated to include all the edges | ||
connecting the elements of the sequence sequentially. | ||
|
||
Nested :class:`.SequenceIR` objects are sequenced recursively. | ||
|
||
Args: | ||
alignment: The IR alignment. | ||
sequence: The graph object to be sequenced. | ||
""" | ||
nodes = sequence.node_indices() | ||
prev = 0 | ||
# TODO : What's the correct order to use here? Addition index? Actual index? | ||
# Should at least be documented. | ||
# The first two nodes are the in\out nodes. | ||
for ind in nodes[2:]: | ||
sequence.add_edge(prev, ind, None) | ||
prev = ind | ||
if isinstance(elem := sequence.get_node_data(ind), SequenceIR): | ||
self._sequence_instructions(elem.alignment, elem.sequence) | ||
sequence.add_edge(prev, 1, None) | ||
|
||
def __hash__(self): | ||
return hash((self.__class__.__name__,)) | ||
|
||
def __eq__(self, other): | ||
return self.__class__.__name__ == other.__class__.__name__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# This code is part of Qiskit. | ||
# | ||
# (C) Copyright IBM 2024. | ||
# | ||
# This code is licensed under the Apache License, Version 2.0. You may | ||
# obtain a copy of this license in the LICENSE.txt file in the root directory | ||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. | ||
# | ||
# Any modifications or derivative works of this code must retain this | ||
# copyright notice, and modified files need to carry a notice indicating | ||
# that they have been altered from the originals. | ||
|
||
"""Qiskit pulse compiler tests.""" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This violates typehint (though type is not important in Python). Do you want to remove Target from the base passes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I commented on the original compiler PR, we don't always need Target. I think we can make it optional.