Skip to content

Add default routing stage plugin #13802

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

Merged
merged 1 commit into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ synthesis = "qiskit.transpiler.preset_passmanagers.builtin_plugins:UnitarySynthe
translator = "qiskit.transpiler.preset_passmanagers.builtin_plugins:BasisTranslatorPassManager"

[project.entry-points."qiskit.transpiler.routing"]
default = "qiskit.transpiler.preset_passmanagers.builtin_plugins:DefaultRoutingPassManager"
basic = "qiskit.transpiler.preset_passmanagers.builtin_plugins:BasicSwapPassManager"
lookahead = "qiskit.transpiler.preset_passmanagers.builtin_plugins:LookaheadSwapPassManager"
none = "qiskit.transpiler.preset_passmanagers.builtin_plugins:NoneRoutingPassManager"
Expand Down
13 changes: 13 additions & 0 deletions qiskit/transpiler/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,9 @@
* - Method
- Summary

* - :ref:`default <transpiler-preset-stage-routing-default>`
- Use a Qiskit-chosen default routing method.

* - :ref:`sabre <transpiler-preset-stage-routing-sabre>`
- Default. Uses `Qiskit's modified Sabre routing algorithm <sabre-lightsabre-paper_>`_ to
swap map.
Expand All @@ -522,6 +525,16 @@
* - :ref:`lookahead <transpiler-preset-stage-routing-lookahead>`
- Breadth-first search with heuristic pruning to find swaps that make gates executable.

.. _transpiler-preset-stage-routing-default:

Built-in ``default`` plugin
...........................

Use a Qiskit-chosen default method for routing. As of Qiskit 2.0, the chosen algorithm is the same
as :ref:`transpiler-preset-stage-routing-sabre`, though in practice, usually the :ref:`built-in
default layout-stage plugin <transpiler-preset-stage-layout-default>` will run the Sabre-based
routing algorithm, and the routing stage will only be used to run :class:`.VF2PostLayout`.

.. _transpiler-preset-stage-routing-none:

Built-in ``none`` plugin
Expand Down
32 changes: 18 additions & 14 deletions qiskit/transpiler/preset_passmanagers/builtin_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,17 @@ def pass_manager(self, pass_manager_config, optimization_level=None) -> PassMana
)


class DefaultRoutingPassManager(PassManagerStagePlugin):
"""Plugin class for the "default" routing stage implementation."""

def pass_manager(self, pass_manager_config, optimization_level=None) -> PassManager:
# The Sabre-based PM is the default implementation currently, but semantically the "default"
# plugin has more scope to change its logic than one called "sabre". In practice, we don't
# run the actually `SabreSwap` logic from this pass most of the time, because we do that
# during default layout; we're looking for the VF2PostLayout stuff mostly.
return SabreSwapPassManager().pass_manager(pass_manager_config, optimization_level)


class BasicSwapPassManager(PassManagerStagePlugin):
"""Plugin class for routing stage with :class:`~.BasicSwap`"""

Expand Down Expand Up @@ -817,8 +828,7 @@ def _swap_mapped(property_set):
seed=pass_manager_config.seed_transpiler,
swap_trials=trial_count,
layout_trials=trial_count,
skip_routing=pass_manager_config.routing_method is not None
and pass_manager_config.routing_method != "sabre",
skip_routing=pass_manager_config.routing_method not in (None, "default", "sabre"),
)
layout.append(
ConditionalController(
Expand Down Expand Up @@ -852,8 +862,7 @@ def _swap_mapped(property_set):
seed=pass_manager_config.seed_transpiler,
swap_trials=trial_count,
layout_trials=trial_count,
skip_routing=pass_manager_config.routing_method is not None
and pass_manager_config.routing_method != "sabre",
skip_routing=pass_manager_config.routing_method not in (None, "default", "sabre"),
)
layout.append(
ConditionalController(
Expand Down Expand Up @@ -887,8 +896,7 @@ def _swap_mapped(property_set):
seed=pass_manager_config.seed_transpiler,
swap_trials=trial_count,
layout_trials=trial_count,
skip_routing=pass_manager_config.routing_method is not None
and pass_manager_config.routing_method != "sabre",
skip_routing=pass_manager_config.routing_method not in (None, "default", "sabre"),
)
layout.append(
ConditionalController(
Expand Down Expand Up @@ -990,8 +998,7 @@ def _swap_mapped(property_set):
seed=pass_manager_config.seed_transpiler,
swap_trials=trial_count,
layout_trials=trial_count,
skip_routing=pass_manager_config.routing_method is not None
and pass_manager_config.routing_method != "sabre",
skip_routing=pass_manager_config.routing_method not in (None, "default", "sabre"),
)
elif optimization_level == 1:
trial_count = _get_trial_count(5)
Expand All @@ -1002,8 +1009,7 @@ def _swap_mapped(property_set):
seed=pass_manager_config.seed_transpiler,
swap_trials=trial_count,
layout_trials=trial_count,
skip_routing=pass_manager_config.routing_method is not None
and pass_manager_config.routing_method != "sabre",
skip_routing=pass_manager_config.routing_method not in (None, "default", "sabre"),
)
elif optimization_level == 2:
trial_count = _get_trial_count(20)
Expand All @@ -1014,8 +1020,7 @@ def _swap_mapped(property_set):
seed=pass_manager_config.seed_transpiler,
swap_trials=trial_count,
layout_trials=trial_count,
skip_routing=pass_manager_config.routing_method is not None
and pass_manager_config.routing_method != "sabre",
skip_routing=pass_manager_config.routing_method not in (None, "default", "sabre"),
)
elif optimization_level == 3:
trial_count = _get_trial_count(20)
Expand All @@ -1026,8 +1031,7 @@ def _swap_mapped(property_set):
seed=pass_manager_config.seed_transpiler,
swap_trials=trial_count,
layout_trials=trial_count,
skip_routing=pass_manager_config.routing_method is not None
and pass_manager_config.routing_method != "sabre",
skip_routing=pass_manager_config.routing_method not in (None, "default", "sabre"),
)
else:
raise TranspilerError(f"Invalid optimization level: {optimization_level}")
Expand Down
2 changes: 1 addition & 1 deletion qiskit/transpiler/preset_passmanagers/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
working={"default", "trivial", "dense", "sabre"}, not_working=set()
),
"routing_method": _ControlFlowState(
working={"none", "stochastic", "sabre"}, not_working={"lookahead", "basic"}
working={"default", "none", "stochastic", "sabre"}, not_working={"lookahead", "basic"}
),
"translation_method": _ControlFlowState(
working={"default", "translator", "synthesis"},
Expand Down
2 changes: 1 addition & 1 deletion qiskit/transpiler/preset_passmanagers/level0.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def level_0_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa
initial_layout = pass_manager_config.initial_layout
init_method = pass_manager_config.init_method or "default"
layout_method = pass_manager_config.layout_method or "default"
routing_method = pass_manager_config.routing_method or "sabre"
routing_method = pass_manager_config.routing_method or "default"
translation_method = pass_manager_config.translation_method or "default"
optimization_method = pass_manager_config.optimization_method or "default"
scheduling_method = pass_manager_config.scheduling_method or "default"
Expand Down
4 changes: 1 addition & 3 deletions qiskit/transpiler/preset_passmanagers/level1.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,8 @@ def level_1_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa
coupling_map = pass_manager_config.coupling_map
initial_layout = pass_manager_config.initial_layout
init_method = pass_manager_config.init_method or "default"
# Unlike other presets, the layout and routing defaults aren't set here because they change
# based on whether the input circuit has control flow.
layout_method = pass_manager_config.layout_method or "default"
routing_method = pass_manager_config.routing_method or "sabre"
routing_method = pass_manager_config.routing_method or "default"
translation_method = pass_manager_config.translation_method or "default"
optimization_method = pass_manager_config.optimization_method or "default"
scheduling_method = pass_manager_config.scheduling_method or "default"
Expand Down
2 changes: 1 addition & 1 deletion qiskit/transpiler/preset_passmanagers/level2.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def level_2_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa
initial_layout = pass_manager_config.initial_layout
init_method = pass_manager_config.init_method or "default"
layout_method = pass_manager_config.layout_method or "default"
routing_method = pass_manager_config.routing_method or "sabre"
routing_method = pass_manager_config.routing_method or "default"
translation_method = pass_manager_config.translation_method or "default"
optimization_method = pass_manager_config.optimization_method or "default"
scheduling_method = pass_manager_config.scheduling_method or "default"
Expand Down
2 changes: 1 addition & 1 deletion qiskit/transpiler/preset_passmanagers/level3.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa
initial_layout = pass_manager_config.initial_layout
init_method = pass_manager_config.init_method or "default"
layout_method = pass_manager_config.layout_method or "default"
routing_method = pass_manager_config.routing_method or "sabre"
routing_method = pass_manager_config.routing_method or "default"
translation_method = pass_manager_config.translation_method or "default"
scheduling_method = pass_manager_config.scheduling_method
optimization_method = pass_manager_config.optimization_method or "default"
Expand Down
2 changes: 1 addition & 1 deletion qiskit/transpiler/preset_passmanagers/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@

* - :ref:`routing <transpiler-preset-stage-routing>`
- ``qiskit.transpiler.routing``
- ``basic``, ``stochastic``, ``lookahead``, ``sabre``
- ``default``, ``basic``, ``stochastic``, ``lookahead``, ``sabre``
- Insert gates into the circuit to ensure it matches the connectivity constraints of the
:class:`.Target`. The inserted gates do not need to be in the target ISA yet, so are often
just output as ``swap`` instructions. This stage is sometimes subsumed by ``layout``.
Expand Down
19 changes: 19 additions & 0 deletions releasenotes/notes/default-routing-e63e1bf5a1a78891.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

---
features_transpiler:
- |
A new :ref:`routing plugin stage <transpiler-preset-stage-routing>` is added, called
``"default"``. In Qiskit 2.0, this is simply an alias for the previous default ``"sabre"``.
The underlying default algorithm may change over the course of the Qiskit 2.x series for some or
all targets, but you can always set ``routing_method="sabre"`` explicitly to maintain
the current behavior.
upgrade_transpiler:
- |
The :ref:`routing plugin stage <transpiler-preset-stage-routing>` name ``default`` is
now reserved for the Qiskit built-in plugin of the same name.
- |
The default :ref:`routing plugin stage <transpiler-preset-stage-routing>` is now
``"default"``. In Qiskit 2.0, this is simply an alias for the previous default ``"sabre"``.
The underlying default algorithm may change over the course of the Qiskit 2.x series for some or
all targets, but you can always set ``routing_method="sabre"`` explicitly to maintain
the current behavior.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ features_transpiler:
A new :ref:`translation plugin stage <transpiler-preset-stage-translation>` is added, called
``"default"``. In Qiskit 2.0, this is simply an alias for the previous default ``"translator"``.
The underlying default algorithm may change over the course of the Qiskit 2.x series for some or
all targets, but you can always set ``translation_method=="translator"`` explicitly to maintain
all targets, but you can always set ``translation_method="translator"`` explicitly to maintain
the current behavior.
upgrade_transpiler:
- |
Expand All @@ -14,5 +14,5 @@ upgrade_transpiler:
The default :ref:`translation plugin stage <transpiler-preset-stage-translation>` is now
``"default"``. In Qiskit 2.0, this is simply an alias for the previous default ``"translator"``.
The underlying default algorithm may change over the course of the Qiskit 2.x series for some or
all targets, but you can always set ``translation_method=="translator"`` explicitly to maintain
all targets, but you can always set ``translation_method="translator"`` explicitly to maintain
the current behavior.