Skip to content

Commit

Permalink
Use TOQM routing staged pass manager. (#9042)
Browse files Browse the repository at this point in the history
* Update toqm requirements-dev version.

* Remove toqm special casing.

* Remove unused imports from preset pass managers.

* Add release note.

* Apply suggestions from code review

Co-authored-by: Jake Lishman <jake@binhbar.com>

Co-authored-by: Jake Lishman <jake@binhbar.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 1, 2022
1 parent e4a7c40 commit d56ef8c
Show file tree
Hide file tree
Showing 9 changed files with 28 additions and 172 deletions.
3 changes: 1 addition & 2 deletions qiskit/compiler/transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,7 @@ def transpile(
You can see a list of installed plugins by using :func:`~.list_stage_plugins` with
``"layout"`` for the ``stage_name`` argument.
routing_method: Name of routing pass
('basic', 'lookahead', 'stochastic', 'sabre', 'toqm', 'none'). Note
that to use method 'toqm', package 'qiskit-toqm' must be installed.
('basic', 'lookahead', 'stochastic', 'sabre', 'none'). Note
This can also be the external plugin name to use for the ``routing`` stage.
You can see a list of installed plugins by using :func:`~.list_stage_plugins` with
``"routing"`` for the ``stage_name`` argument.
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 @@ -64,7 +64,7 @@
working={"trivial", "dense"}, not_working={"sabre", "noise_adaptive"}
),
"routing_method": _ControlFlowState(
working={"none", "stochastic"}, not_working={"sabre", "lookahead", "basic", "toqm"}
working={"none", "stochastic"}, not_working={"sabre", "lookahead", "basic"}
),
# 'synthesis' is not a supported translation method because of the block-collection passes
# involved; we currently don't have a neat way to pass the information about nested blocks - the
Expand Down
41 changes: 3 additions & 38 deletions qiskit/transpiler/preset_passmanagers/level0.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@
from qiskit.transpiler.preset_passmanagers import common
from qiskit.transpiler.preset_passmanagers.plugin import (
PassManagerStagePluginManager,
list_stage_plugins,
)
from qiskit.transpiler import TranspilerError
from qiskit.utils.optionals import HAS_TOQM


def level_0_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassManager:
Expand Down Expand Up @@ -91,38 +88,10 @@ def _choose_layout_condition(property_set):
coupling_map, max_iterations=1, seed=seed_transpiler, swap_trials=5
)

toqm_pass = False
# Choose routing pass
# TODO: Remove when qiskit-toqm has it's own plugin and we can rely on just the plugin interface
if routing_method == "toqm" and "toqm" not in list_stage_plugins("routing"):
HAS_TOQM.require_now("TOQM-based routing")
from qiskit_toqm import ToqmSwap, ToqmStrategyO0, latencies_from_target

if initial_layout:
raise TranspilerError("Initial layouts are not supported with TOQM-based routing.")

toqm_pass = True
# Note: BarrierBeforeFinalMeasurements is skipped intentionally since ToqmSwap
# does not yet support barriers.
routing_pass = ToqmSwap(
coupling_map,
strategy=ToqmStrategyO0(
latencies_from_target(
coupling_map, instruction_durations, basis_gates, backend_properties, target
)
),
)
routing_pm = common.generate_routing_passmanager(
routing_pass,
target,
coupling_map=coupling_map,
seed_transpiler=seed_transpiler,
use_barrier_before_measurement=not toqm_pass,
)
else:
routing_pm = plugin_manager.get_passmanager_stage(
"routing", routing_method, pass_manager_config, optimization_level=0
)
routing_pm = plugin_manager.get_passmanager_stage(
"routing", routing_method, pass_manager_config, optimization_level=0
)

unroll_3q = None
# Build pass manager
Expand Down Expand Up @@ -164,9 +133,6 @@ def _choose_layout_condition(property_set):
unitary_synthesis_plugin_config,
hls_config,
)
pre_routing = None
if toqm_pass:
pre_routing = translation

if (coupling_map and not coupling_map.is_symmetric) or (
target is not None and target.get_non_global_operation_names(strict_direction=True)
Expand Down Expand Up @@ -205,7 +171,6 @@ def _choose_layout_condition(property_set):
return StagedPassManager(
init=init,
layout=layout,
pre_routing=pre_routing,
routing=routing,
translation=translation,
pre_optimization=pre_opt,
Expand Down
44 changes: 2 additions & 42 deletions qiskit/transpiler/preset_passmanagers/level1.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,8 @@
from qiskit.transpiler.preset_passmanagers import common
from qiskit.transpiler.passes.layout.vf2_layout import VF2LayoutStopReason

from qiskit.transpiler import TranspilerError
from qiskit.utils.optionals import HAS_TOQM
from qiskit.transpiler.preset_passmanagers.plugin import (
PassManagerStagePluginManager,
list_stage_plugins,
)


Expand Down Expand Up @@ -149,41 +146,9 @@ def _vf2_match_not_found(property_set):
SabreLayout(coupling_map, max_iterations=2, seed=seed_transpiler, swap_trials=5),
).to_flow_controller()

toqm_pass = False
# Choose routing pass
routing_pm = None
# TODO: Remove when qiskit-toqm has it's own plugin and we can rely on just the plugin interface
if routing_method == "toqm" and "toqm" not in list_stage_plugins("routing"):
HAS_TOQM.require_now("TOQM-based routing")
from qiskit_toqm import ToqmSwap, ToqmStrategyO1, latencies_from_target

if initial_layout:
raise TranspilerError("Initial layouts are not supported with TOQM-based routing.")

toqm_pass = True
# Note: BarrierBeforeFinalMeasurements is skipped intentionally since ToqmSwap
# does not yet support barriers.
routing_pass = ToqmSwap(
coupling_map,
strategy=ToqmStrategyO1(
latencies_from_target(
coupling_map, instruction_durations, basis_gates, backend_properties, target
)
),
)
vf2_call_limit = common.get_vf2_call_limit(
1, pass_manager_config.layout_method, pass_manager_config.initial_layout
)
routing_pm = common.generate_routing_passmanager(
routing_pass,
target,
coupling_map,
vf2_call_limit=vf2_call_limit,
backend_properties=backend_properties,
seed_transpiler=seed_transpiler,
check_trivial=True,
use_barrier_before_measurement=not toqm_pass,
)
elif routing_method is None:
if routing_method is None:
_stochastic_routing = plugin_manager.get_passmanager_stage(
"routing",
"stochastic",
Expand Down Expand Up @@ -261,10 +226,6 @@ def _opt_control(property_set):
hls_config,
)

pre_routing = None
if toqm_pass:
pre_routing = translation

if (coupling_map and not coupling_map.is_symmetric) or (
target is not None and target.get_non_global_operation_names(strict_direction=True)
):
Expand Down Expand Up @@ -318,7 +279,6 @@ def _unroll_condition(property_set):
return StagedPassManager(
init=init,
layout=layout,
pre_routing=pre_routing,
routing=routing,
translation=translation,
pre_optimization=pre_optimization,
Expand Down
49 changes: 5 additions & 44 deletions qiskit/transpiler/preset_passmanagers/level2.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,8 @@
from qiskit.transpiler.preset_passmanagers import common
from qiskit.transpiler.passes.layout.vf2_layout import VF2LayoutStopReason

from qiskit.transpiler import TranspilerError
from qiskit.utils.optionals import HAS_TOQM
from qiskit.transpiler.preset_passmanagers.plugin import (
PassManagerStagePluginManager,
list_stage_plugins,
)


Expand Down Expand Up @@ -134,43 +131,10 @@ def _vf2_match_not_found(property_set):
coupling_map, max_iterations=2, seed=seed_transpiler, swap_trials=10
)

toqm_pass = False
routing_pm = None
# TODO: Remove when qiskit-toqm has it's own plugin and we can rely on just the plugin interface
if routing_method == "toqm" and "toqm" not in list_stage_plugins("routing"):
HAS_TOQM.require_now("TOQM-based routing")
from qiskit_toqm import ToqmSwap, ToqmStrategyO2, latencies_from_target

if initial_layout:
raise TranspilerError("Initial layouts are not supported with TOQM-based routing.")
toqm_pass = True

# Note: BarrierBeforeFinalMeasurements is skipped intentionally since ToqmSwap
# does not yet support barriers.
routing_pass = ToqmSwap(
coupling_map,
strategy=ToqmStrategyO2(
latencies_from_target(
coupling_map, instruction_durations, basis_gates, backend_properties, target
)
),
)
vf2_call_limit = common.get_vf2_call_limit(
2, pass_manager_config.layout_method, pass_manager_config.initial_layout
)
routing_pm = common.generate_routing_passmanager(
routing_pass,
target,
coupling_map=coupling_map,
vf2_call_limit=vf2_call_limit,
backend_properties=backend_properties,
seed_transpiler=seed_transpiler,
use_barrier_before_measurement=not toqm_pass,
)
else:
routing_pm = plugin_manager.get_passmanager_stage(
"routing", routing_method, pass_manager_config, optimization_level=2
)
# Choose routing pass
routing_pm = plugin_manager.get_passmanager_stage(
"routing", routing_method, pass_manager_config, optimization_level=2
)

# Build optimization loop: 1q rotation merge and commutative cancellation iteratively until
# no more change in depth
Expand Down Expand Up @@ -226,9 +190,7 @@ def _opt_control(property_set):
unitary_synthesis_plugin_config,
hls_config,
)
pre_routing = None
if toqm_pass:
pre_routing = translation

if (coupling_map and not coupling_map.is_symmetric) or (
target is not None and target.get_non_global_operation_names(strict_direction=True)
):
Expand Down Expand Up @@ -275,7 +237,6 @@ def _unroll_condition(property_set):
return StagedPassManager(
init=init,
layout=layout,
pre_routing=pre_routing,
routing=routing,
translation=translation,
pre_optimization=pre_optimization,
Expand Down
48 changes: 5 additions & 43 deletions qiskit/transpiler/preset_passmanagers/level3.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,7 @@
from qiskit.transpiler.passes.layout.vf2_layout import VF2LayoutStopReason
from qiskit.transpiler.preset_passmanagers.plugin import (
PassManagerStagePluginManager,
list_stage_plugins,
)
from qiskit.transpiler import TranspilerError
from qiskit.utils.optionals import HAS_TOQM


def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassManager:
Expand Down Expand Up @@ -140,42 +137,10 @@ def _vf2_match_not_found(property_set):
coupling_map, max_iterations=4, seed=seed_transpiler, swap_trials=20
)

toqm_pass = False
# TODO: Remove when qiskit-toqm has it's own plugin and we can rely on just the plugin interface
if routing_method == "toqm" and "toqm" not in list_stage_plugins("routing"):
HAS_TOQM.require_now("TOQM-based routing")
from qiskit_toqm import ToqmSwap, ToqmStrategyO3, latencies_from_target

if initial_layout:
raise TranspilerError("Initial layouts are not supported with TOQM-based routing.")

toqm_pass = True
# Note: BarrierBeforeFinalMeasurements is skipped intentionally since ToqmSwap
# does not yet support barriers.
routing_pass = ToqmSwap(
coupling_map,
strategy=ToqmStrategyO3(
latencies_from_target(
coupling_map, instruction_durations, basis_gates, backend_properties, target
)
),
)
vf2_call_limit = common.get_vf2_call_limit(
3, pass_manager_config.layout_method, pass_manager_config.initial_layout
)
routing_pm = common.generate_routing_passmanager(
routing_pass,
target,
coupling_map=coupling_map,
vf2_call_limit=vf2_call_limit,
backend_properties=backend_properties,
seed_transpiler=seed_transpiler,
use_barrier_before_measurement=not toqm_pass,
)
else:
routing_pm = plugin_manager.get_passmanager_stage(
"routing", routing_method, pass_manager_config, optimization_level=3
)
# Choose routing pass
routing_pm = plugin_manager.get_passmanager_stage(
"routing", routing_method, pass_manager_config, optimization_level=3
)

# 8. Optimize iteratively until no more change in depth. Removes useless gates
# after reset and before measure, commutes gates and optimizes contiguous blocks.
Expand Down Expand Up @@ -252,9 +217,7 @@ def _opt_control(property_set):
unitary_synthesis_plugin_config,
hls_config,
)
pre_routing = None
if toqm_pass:
pre_routing = translation

if optimization_method is None:
optimization = PassManager()
unroll = [pass_ for x in translation.passes() for pass_ in x["passes"]]
Expand Down Expand Up @@ -322,7 +285,6 @@ def _unroll_condition(property_set):
return StagedPassManager(
init=init,
layout=layout,
pre_routing=pre_routing,
routing=routing,
translation=translation,
pre_optimization=pre_optimization,
Expand Down
9 changes: 9 additions & 0 deletions releasenotes/notes/toqm-extra-0.1.0-4fedfa1ff0fedfa0.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
upgrade:
- |
The version requirement for the optional feature package ``qiskit-toqm`` installable via
``pip install qiskit-terra[toqm]`` has been upgraded from version
``0.0.4`` to ``0.1.0``. To use the ``toqm`` routing method
with :func:`~.transpile` you must now use qiskit-toqm version
``0.1.0`` or newer. Older versions are no longer discoverable by
the transpiler.
2 changes: 1 addition & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ seaborn>=0.9.0
reno>=3.4.0
Sphinx>=3.0.0
qiskit-sphinx-theme>=1.6
qiskit-toqm>=0.0.4;platform_machine != 'aarch64' or platform_system != 'Linux'
qiskit-toqm>=0.1.0;platform_machine != 'aarch64' or platform_system != 'Linux'
sphinx-autodoc-typehints~=1.18,!=1.19.3
jupyter-sphinx
sphinx-design>=0.2.0
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
]
bip_requirements = ["cplex", "docplex"]
csp_requirements = ["python-constraint>=1.4"]
toqm_requirements = ["qiskit-toqm>=0.0.4"]
toqm_requirements = ["qiskit-toqm>=0.1.0"]

setup(
name="qiskit-terra",
Expand Down

0 comments on commit d56ef8c

Please sign in to comment.