From f52480c8890cd747e39d8aefed5a8f8c334f8369 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Mon, 1 Nov 2021 12:44:20 -0400 Subject: [PATCH] Switch default routing/layout method to sabre for opt level 3 This commit switches the default routing and layout method for optimization level 3 to use SabreSwap and Sabre layout passes. The quality of results is typically better with sabre than the default stochastic swap and dense layout we're using now. For optimization level 3 where we try to produce the best quality result and runtime is of secondary concern using sabre makes the most sense (especially after #7036 which improves the runtime performance). Also for optimization level 3 currently sabre is typically faster because we increase the number of trials for stochastic swap (which is generally significantly faster) which slows it down as it's doing more work. This should improve the quality and speed of the results in general when running with optimization level 3. In the future we can do more work to improve the runtime performance of the sabre passes and hopefully make it fast enough to use for all the optimization levels which have more constraints on the run time performance than level 3. Related to #7112 and #7200 --- .../transpiler/preset_passmanagers/level3.py | 4 +-- ...bre-opt-lvl3-default-550924470d683112.yaml | 18 +++++++++++++ .../transpiler/test_preset_passmanagers.py | 25 ++++++++++++++++++- 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 releasenotes/notes/sabre-opt-lvl3-default-550924470d683112.yaml diff --git a/qiskit/transpiler/preset_passmanagers/level3.py b/qiskit/transpiler/preset_passmanagers/level3.py index e43192f5c9f6..8d2b5a76e5c0 100644 --- a/qiskit/transpiler/preset_passmanagers/level3.py +++ b/qiskit/transpiler/preset_passmanagers/level3.py @@ -96,8 +96,8 @@ def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> PassManager: inst_map = pass_manager_config.inst_map coupling_map = pass_manager_config.coupling_map initial_layout = pass_manager_config.initial_layout - layout_method = pass_manager_config.layout_method or "dense" - routing_method = pass_manager_config.routing_method or "stochastic" + 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" scheduling_method = pass_manager_config.scheduling_method instruction_durations = pass_manager_config.instruction_durations diff --git a/releasenotes/notes/sabre-opt-lvl3-default-550924470d683112.yaml b/releasenotes/notes/sabre-opt-lvl3-default-550924470d683112.yaml new file mode 100644 index 000000000000..e5b5a85d01ca --- /dev/null +++ b/releasenotes/notes/sabre-opt-lvl3-default-550924470d683112.yaml @@ -0,0 +1,18 @@ +--- +upgrade: + - | + The default routing pass and layout pass for optimization level 3 has + changed to use :class:`~qiskit.transpiler.passes.SabreSwap` and + :class:`~qiskit.transpiler.passes.SabreLayout` respectively. This + was done to improve the quality of the output result as using the sabre + passes produces better results than using + :class:`~qiskit.transpiler.passes.StochasticSwap` and + :class:`~qiskit.transpiler.passes.DenseLayout` which were used as the + defaults in prior releases. This change will improve the quality of the + results when running :func:`~qiskit.compiler.transpile` or + :func:`~qiskit.execute_function.execute` functions with the + ``optimization_level`` kwarg set to ``3``. While this is generally an + improvement if you need to retain the previous behavior for any reason + you can do this by explicitly setting the ``routing_method="stochastic"`` + and ``layout_method="dense"`` when calling + :func:`~qiskit.compiler.transpile` with ``optimization_level=3``. diff --git a/test/python/transpiler/test_preset_passmanagers.py b/test/python/transpiler/test_preset_passmanagers.py index c1211dff5b01..62430edf6f34 100644 --- a/test/python/transpiler/test_preset_passmanagers.py +++ b/test/python/transpiler/test_preset_passmanagers.py @@ -674,10 +674,33 @@ def test_layout_tokyo_fully_connected_cx(self, level): 19: ancilla[14], } + sabre_layout = { + 0: ancilla[0], + 1: ancilla[1], + 2: ancilla[2], + 3: ancilla[3], + 4: ancilla[4], + 5: ancilla[5], + 6: ancilla[6], + 7: qr[4], + 8: qr[1], + 9: ancilla[7], + 10: ancilla[8], + 11: ancilla[9], + 12: qr[2], + 13: qr[0], + 14: ancilla[10], + 15: ancilla[11], + 16: ancilla[12], + 17: ancilla[13], + 18: ancilla[14], + 19: qr[3], + } + expected_layout_level0 = trivial_layout expected_layout_level1 = dense_layout expected_layout_level2 = dense_layout - expected_layout_level3 = dense_layout + expected_layout_level3 = sabre_layout expected_layouts = [ expected_layout_level0,