Skip to content
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

Enable Sabre for control flow circuits at O1 #10371

Merged
merged 3 commits into from
Jul 19, 2023
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
42 changes: 5 additions & 37 deletions qiskit/transpiler/preset_passmanagers/level1.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ def level_1_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa
init_method = pass_manager_config.init_method
# 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
routing_method = pass_manager_config.routing_method
layout_method = pass_manager_config.layout_method or "sabre"
routing_method = pass_manager_config.routing_method or "sabre"
translation_method = pass_manager_config.translation_method or "translator"
optimization_method = pass_manager_config.optimization_method
scheduling_method = pass_manager_config.scheduling_method
Expand Down Expand Up @@ -157,43 +157,11 @@ def _vf2_match_not_found(property_set):
skip_routing=pass_manager_config.routing_method is not None
and routing_method != "sabre",
)
elif layout_method is None:
_improve_layout = common.if_has_control_flow_else(
DenseLayout(coupling_map, backend_properties, target=target),
SabreLayout(
coupling_map_layout,
max_iterations=2,
seed=seed_transpiler,
swap_trials=5,
layout_trials=5,
skip_routing=pass_manager_config.routing_method is not None
and routing_method != "sabre",
),
).to_flow_controller()

# Choose routing pass
routing_pm = None
if routing_method is None:
_stochastic_routing = plugin_manager.get_passmanager_stage(
"routing",
"stochastic",
pass_manager_config,
optimization_level=1,
)
_sabre_routing = plugin_manager.get_passmanager_stage(
"routing",
"sabre",
pass_manager_config,
optimization_level=1,
)
routing_pm = common.if_has_control_flow_else(_stochastic_routing, _sabre_routing)
else:
routing_pm = plugin_manager.get_passmanager_stage(
"routing",
routing_method,
pass_manager_config,
optimization_level=1,
)
routing_pm = plugin_manager.get_passmanager_stage(
"routing", routing_method, pass_manager_config, optimization_level=1
)

# Build optimization loop: merge 1q rotations and cancel CNOT gates iteratively
# until no more change in depth
Expand Down
11 changes: 11 additions & 0 deletions releasenotes/notes/sabre-ctrl-flow-o1-431cd25a19adbcdc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
upgrade:
- |
The Sabre family of transpiler passes (namely :class:`.SabreLayout`
and :class:`.SabreSwap`) are now used by default for all circuits
when invoking the transpiler at optimization level 1 (e.g. calling
:func:`.transpile` or :func:`.generate_preset_pass_manager` with
keyword argument ``optimization_level=1``). Previously, circuits
with control flow operations used :class:`.DenseLayout` and
:class:`.StochasticSwap` with this profile.

17 changes: 8 additions & 9 deletions test/python/transpiler/test_preset_passmanagers.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ def test_no_coupling_map(self, level):
self.assertNotIn("TrivialLayout", self.passes)
self.assertNotIn("ApplyLayout", self.passes)
self.assertNotIn("StochasticSwap", self.passes)
self.assertNotIn("SabreSwap", self.passes)
self.assertNotIn("CheckGateDirection", self.passes)

@data(0, 1, 2, 3)
Expand Down Expand Up @@ -568,13 +569,11 @@ def test_level1_runs_vf2post_layout_when_routing_required_control_flow(self):
# Expected call path for layout and routing is:
# 1. TrivialLayout (no perfect match)
# 2. VF2Layout (no perfect match)
# 3. DenseLayout (heuristic layout)
# 4. StochasticSwap
# 3. SabreLayout (heuristic layout)
# 4. VF2PostLayout (applies a better layout)
self.assertIn("TrivialLayout", self.passes)
self.assertIn("VF2Layout", self.passes)
self.assertIn("DenseLayout", self.passes)
self.assertIn("StochasticSwap", self.passes)
self.assertIn("SabreLayout", self.passes)
self.assertIn("VF2PostLayout", self.passes)

def test_level1_not_runs_vf2post_layout_when_layout_method_set_control_flow(self):
Expand All @@ -599,7 +598,7 @@ def test_level1_not_runs_vf2post_layout_when_layout_method_set_control_flow(self
self.assertNotIn("SabreLayout", self.passes)
self.assertNotIn("VF2PostLayout", self.passes)
self.assertIn("DenseLayout", self.passes)
self.assertIn("StochasticSwap", self.passes)
self.assertIn("SabreSwap", self.passes)

def test_level1_not_run_vf2post_layout_when_trivial_is_perfect_control_flow(self):
"""Test that if we find a trivial perfect layout we don't run vf2post."""
Expand All @@ -615,8 +614,8 @@ def test_level1_not_run_vf2post_layout_when_trivial_is_perfect_control_flow(self
_ = transpile(qc, target, optimization_level=1, callback=self.callback)
self.assertIn("TrivialLayout", self.passes)
self.assertNotIn("VF2Layout", self.passes)
self.assertNotIn("DenseLayout", self.passes)
self.assertNotIn("StochasticSwap", self.passes)
self.assertNotIn("SabreLayout", self.passes)
self.assertNotIn("SabreSwap", self.passes)
self.assertNotIn("VF2PostLayout", self.passes)

def test_level1_not_run_vf2post_layout_when_vf2layout_is_perfect_control_flow(self):
Expand All @@ -635,9 +634,9 @@ def test_level1_not_run_vf2post_layout_when_vf2layout_is_perfect_control_flow(se
_ = transpile(qc, target, optimization_level=1, callback=self.callback)
self.assertIn("TrivialLayout", self.passes)
self.assertIn("VF2Layout", self.passes)
self.assertNotIn("DenseLayout", self.passes)
self.assertNotIn("SabreLayout", self.passes)
self.assertNotIn("VF2PostLayout", self.passes)
self.assertNotIn("StochasticSwap", self.passes)
self.assertNotIn("SabreSwap", self.passes)


@ddt
Expand Down