diff --git a/qiskit/transpiler/preset_passmanagers/builtin_plugins.py b/qiskit/transpiler/preset_passmanagers/builtin_plugins.py index 2ecd4653707b..b6cf031f3f3a 100644 --- a/qiskit/transpiler/preset_passmanagers/builtin_plugins.py +++ b/qiskit/transpiler/preset_passmanagers/builtin_plugins.py @@ -27,6 +27,9 @@ from qiskit.transpiler.passes import NoiseAdaptiveLayout from qiskit.transpiler.passes import CheckMap from qiskit.transpiler.passes import BarrierBeforeFinalMeasurements +from qiskit.transpiler.passes import RemoveResetInZeroState +from qiskit.transpiler.passes import OptimizeSwapBeforeMeasure +from qiskit.transpiler.passes import RemoveDiagonalGatesBeforeMeasure from qiskit.transpiler.preset_passmanagers import common from qiskit.transpiler.preset_passmanagers.plugin import ( PassManagerStagePlugin, @@ -47,6 +50,45 @@ from qiskit.transpiler.passes.layout.vf2_layout import VF2LayoutStopReason +class DefaultInitPassManager(PassManagerStagePlugin): + """Plugin class for default init stage.""" + + def pass_manager(self, pass_manager_config, optimization_level=None) -> PassManager: + if optimization_level in {1, 2, 0}: + init = None + if ( + pass_manager_config.initial_layout + or pass_manager_config.coupling_map + or ( + pass_manager_config.target is not None + and pass_manager_config.target.build_coupling_map() is not None + ) + ): + init = common.generate_unroll_3q( + pass_manager_config.target, + pass_manager_config.basis_gates, + pass_manager_config.approximation_degree, + pass_manager_config.unitary_synthesis_method, + pass_manager_config.unitary_synthesis_plugin_config, + pass_manager_config.hls_config, + ) + elif optimization_level == 3: + init = common.generate_unroll_3q( + pass_manager_config.target, + pass_manager_config.basis_gates, + pass_manager_config.approximation_degree, + pass_manager_config.unitary_synthesis_method, + pass_manager_config.unitary_synthesis_plugin_config, + pass_manager_config.hls_config, + ) + init.append(RemoveResetInZeroState()) + init.append(OptimizeSwapBeforeMeasure()) + init.append(RemoveDiagonalGatesBeforeMeasure()) + else: + return TranspilerError(f"Invalid optimization level {optimization_level}") + return init + + class BasisTranslatorPassManager(PassManagerStagePlugin): """Plugin class for translation stage with :class:`~.BasisTranslator`""" diff --git a/qiskit/transpiler/preset_passmanagers/level0.py b/qiskit/transpiler/preset_passmanagers/level0.py index 471a9d91fab1..7289a8635c55 100644 --- a/qiskit/transpiler/preset_passmanagers/level0.py +++ b/qiskit/transpiler/preset_passmanagers/level0.py @@ -46,34 +46,21 @@ def level_0_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa basis_gates = pass_manager_config.basis_gates coupling_map = pass_manager_config.coupling_map initial_layout = pass_manager_config.initial_layout - init_method = pass_manager_config.init_method + 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 "stochastic" translation_method = pass_manager_config.translation_method or "translator" optimization_method = pass_manager_config.optimization_method or "default" scheduling_method = pass_manager_config.scheduling_method or "default" - approximation_degree = pass_manager_config.approximation_degree - unitary_synthesis_method = pass_manager_config.unitary_synthesis_method - unitary_synthesis_plugin_config = pass_manager_config.unitary_synthesis_plugin_config target = pass_manager_config.target - hls_config = pass_manager_config.hls_config # Choose routing pass routing_pm = plugin_manager.get_passmanager_stage( "routing", routing_method, pass_manager_config, optimization_level=0 ) - unroll_3q = None # Build pass manager if coupling_map or initial_layout: - unroll_3q = common.generate_unroll_3q( - target, - basis_gates, - approximation_degree, - unitary_synthesis_method, - unitary_synthesis_plugin_config, - hls_config, - ) layout = plugin_manager.get_passmanager_stage( "layout", layout_method, pass_manager_config, optimization_level=0 ) @@ -98,7 +85,7 @@ def level_0_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa "scheduling", scheduling_method, pass_manager_config, optimization_level=0 ) - init = common.generate_control_flow_options_check( + pre_init = common.generate_control_flow_options_check( layout_method=layout_method, routing_method=routing_method, translation_method=translation_method, @@ -107,17 +94,15 @@ def level_0_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa basis_gates=basis_gates, target=target, ) - if init_method is not None: - init += plugin_manager.get_passmanager_stage( - "init", init_method, pass_manager_config, optimization_level=0 - ) - elif unroll_3q is not None: - init += unroll_3q + init = plugin_manager.get_passmanager_stage( + "init", init_method, pass_manager_config, optimization_level=0 + ) optimization = plugin_manager.get_passmanager_stage( "optimization", optimization_method, pass_manager_config, optimization_level=0 ) return StagedPassManager( + pre_init=pre_init, init=init, layout=layout, routing=routing, diff --git a/qiskit/transpiler/preset_passmanagers/level1.py b/qiskit/transpiler/preset_passmanagers/level1.py index 22be66c4370c..4e585148c080 100644 --- a/qiskit/transpiler/preset_passmanagers/level1.py +++ b/qiskit/transpiler/preset_passmanagers/level1.py @@ -48,7 +48,7 @@ def level_1_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa basis_gates = pass_manager_config.basis_gates coupling_map = pass_manager_config.coupling_map initial_layout = pass_manager_config.initial_layout - init_method = pass_manager_config.init_method + 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" @@ -56,28 +56,15 @@ def level_1_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa translation_method = pass_manager_config.translation_method or "translator" optimization_method = pass_manager_config.optimization_method or "default" scheduling_method = pass_manager_config.scheduling_method or "default" - approximation_degree = pass_manager_config.approximation_degree - unitary_synthesis_method = pass_manager_config.unitary_synthesis_method - unitary_synthesis_plugin_config = pass_manager_config.unitary_synthesis_plugin_config target = pass_manager_config.target - hls_config = pass_manager_config.hls_config # Choose routing pass routing_pm = plugin_manager.get_passmanager_stage( "routing", routing_method, pass_manager_config, optimization_level=1 ) - unroll_3q = None # Build full pass manager if coupling_map or initial_layout: - unroll_3q = common.generate_unroll_3q( - target, - basis_gates, - approximation_degree, - unitary_synthesis_method, - unitary_synthesis_plugin_config, - hls_config, - ) layout = plugin_manager.get_passmanager_stage( "layout", layout_method, pass_manager_config, optimization_level=1 ) @@ -108,7 +95,7 @@ def level_1_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa "scheduling", scheduling_method, pass_manager_config, optimization_level=1 ) - init = common.generate_control_flow_options_check( + pre_init = common.generate_control_flow_options_check( layout_method=layout_method, routing_method=routing_method, translation_method=translation_method, @@ -117,14 +104,12 @@ def level_1_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa basis_gates=basis_gates, target=target, ) - if init_method is not None: - init += plugin_manager.get_passmanager_stage( - "init", init_method, pass_manager_config, optimization_level=1 - ) - elif unroll_3q is not None: - init += unroll_3q + init = plugin_manager.get_passmanager_stage( + "init", init_method, pass_manager_config, optimization_level=1 + ) return StagedPassManager( + pre_init=pre_init, init=init, layout=layout, routing=routing, diff --git a/qiskit/transpiler/preset_passmanagers/level2.py b/qiskit/transpiler/preset_passmanagers/level2.py index 8815a983ca61..941bf2fcf2ac 100644 --- a/qiskit/transpiler/preset_passmanagers/level2.py +++ b/qiskit/transpiler/preset_passmanagers/level2.py @@ -51,34 +51,21 @@ def level_2_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa basis_gates = pass_manager_config.basis_gates coupling_map = pass_manager_config.coupling_map initial_layout = pass_manager_config.initial_layout - init_method = pass_manager_config.init_method + 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" translation_method = pass_manager_config.translation_method or "translator" optimization_method = pass_manager_config.optimization_method or "default" scheduling_method = pass_manager_config.scheduling_method or "default" - approximation_degree = pass_manager_config.approximation_degree - unitary_synthesis_method = pass_manager_config.unitary_synthesis_method - unitary_synthesis_plugin_config = pass_manager_config.unitary_synthesis_plugin_config target = pass_manager_config.target - hls_config = pass_manager_config.hls_config # Choose routing pass routing_pm = plugin_manager.get_passmanager_stage( "routing", routing_method, pass_manager_config, optimization_level=2 ) - unroll_3q = None # Build pass manager if coupling_map or initial_layout: - unroll_3q = common.generate_unroll_3q( - target, - basis_gates, - approximation_degree, - unitary_synthesis_method, - unitary_synthesis_plugin_config, - hls_config, - ) layout = plugin_manager.get_passmanager_stage( "layout", layout_method, pass_manager_config, optimization_level=2 ) @@ -105,7 +92,7 @@ def level_2_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa "scheduling", scheduling_method, pass_manager_config, optimization_level=2 ) - init = common.generate_control_flow_options_check( + pre_init = common.generate_control_flow_options_check( layout_method=layout_method, routing_method=routing_method, translation_method=translation_method, @@ -114,14 +101,12 @@ def level_2_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa basis_gates=basis_gates, target=target, ) - if init_method is not None: - init += plugin_manager.get_passmanager_stage( - "init", init_method, pass_manager_config, optimization_level=2 - ) - elif unroll_3q is not None: - init += unroll_3q + init = plugin_manager.get_passmanager_stage( + "init", init_method, pass_manager_config, optimization_level=2 + ) return StagedPassManager( + pre_init=pre_init, init=init, layout=layout, routing=routing, diff --git a/qiskit/transpiler/preset_passmanagers/level3.py b/qiskit/transpiler/preset_passmanagers/level3.py index 1e4c7d589b35..90e3872adf64 100644 --- a/qiskit/transpiler/preset_passmanagers/level3.py +++ b/qiskit/transpiler/preset_passmanagers/level3.py @@ -18,9 +18,6 @@ from __future__ import annotations from qiskit.transpiler.passmanager_config import PassManagerConfig from qiskit.transpiler.passmanager import StagedPassManager -from qiskit.transpiler.passes import RemoveResetInZeroState -from qiskit.transpiler.passes import OptimizeSwapBeforeMeasure -from qiskit.transpiler.passes import RemoveDiagonalGatesBeforeMeasure from qiskit.transpiler.preset_passmanagers import common from qiskit.transpiler.preset_passmanagers.plugin import ( PassManagerStagePluginManager, @@ -54,18 +51,14 @@ def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa basis_gates = pass_manager_config.basis_gates coupling_map = pass_manager_config.coupling_map initial_layout = pass_manager_config.initial_layout - init_method = pass_manager_config.init_method + 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" translation_method = pass_manager_config.translation_method or "translator" scheduling_method = pass_manager_config.scheduling_method optimization_method = pass_manager_config.optimization_method or "default" scheduling_method = pass_manager_config.scheduling_method or "default" - approximation_degree = pass_manager_config.approximation_degree - unitary_synthesis_method = pass_manager_config.unitary_synthesis_method - unitary_synthesis_plugin_config = pass_manager_config.unitary_synthesis_plugin_config target = pass_manager_config.target - hls_config = pass_manager_config.hls_config # Choose routing pass routing_pm = plugin_manager.get_passmanager_stage( @@ -73,7 +66,7 @@ def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa ) # Build pass manager - init = common.generate_control_flow_options_check( + pre_init = common.generate_control_flow_options_check( layout_method=layout_method, routing_method=routing_method, translation_method=translation_method, @@ -82,22 +75,9 @@ def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa basis_gates=basis_gates, target=target, ) - if init_method is not None: - init += plugin_manager.get_passmanager_stage( - "init", init_method, pass_manager_config, optimization_level=2 - ) - else: - init += common.generate_unroll_3q( - target, - basis_gates, - approximation_degree, - unitary_synthesis_method, - unitary_synthesis_plugin_config, - hls_config, - ) - init.append(RemoveResetInZeroState()) - init.append(OptimizeSwapBeforeMeasure()) - init.append(RemoveDiagonalGatesBeforeMeasure()) + init = plugin_manager.get_passmanager_stage( + "init", init_method, pass_manager_config, optimization_level=3 + ) if coupling_map or initial_layout: layout = plugin_manager.get_passmanager_stage( "layout", layout_method, pass_manager_config, optimization_level=3 @@ -118,11 +98,6 @@ def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa target is not None and target.get_non_global_operation_names(strict_direction=True) ): pre_optimization = common.generate_pre_op_passmanager(target, coupling_map, True) - _direction = [ - pass_ - for x in common.generate_pre_op_passmanager(target, coupling_map).passes() - for pass_ in x["passes"] - ] else: pre_optimization = common.generate_pre_op_passmanager(remove_reset_in_zero=True) @@ -131,6 +106,7 @@ def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa ) return StagedPassManager( + pre_init=pre_init, init=init, layout=layout, routing=routing, diff --git a/qiskit/transpiler/preset_passmanagers/plugin.py b/qiskit/transpiler/preset_passmanagers/plugin.py index d46a892e11c7..e0fabffc9d85 100644 --- a/qiskit/transpiler/preset_passmanagers/plugin.py +++ b/qiskit/transpiler/preset_passmanagers/plugin.py @@ -47,7 +47,7 @@ - Description and expectations * - ``init`` - ``qiskit.transpiler.init`` - - No reserved names + - ``default`` - This stage runs first and is typically used for any initial logical optimization. Because most layout and routing algorithms are only designed to work with 1 and 2 qubit gates, this stage is also used to translate any gates that operate on more than 2 qubits into gates that only diff --git a/releasenotes/notes/default-reserved-plugin-name-3825c2000a579e38.yaml b/releasenotes/notes/default-reserved-plugin-name-3825c2000a579e38.yaml index ebb207eb837b..083c2ed90f83 100644 --- a/releasenotes/notes/default-reserved-plugin-name-3825c2000a579e38.yaml +++ b/releasenotes/notes/default-reserved-plugin-name-3825c2000a579e38.yaml @@ -2,7 +2,7 @@ upgrade: - | The plugin name ``default`` is reserved for the :ref:`stage_table` - ``layout``, ``optimization``, and ``scheduling``. These stages previously + ``init``, ``layout``, ``optimization``, and ``scheduling``. These stages previously did not reserve this plugin name, but the ``default`` name is now used to represent Qiskit's built-in default method for these stages. If you were using these names for plugins on these stages these will conflict with diff --git a/setup.py b/setup.py index 77f39a7aa068..c94693304d76 100644 --- a/setup.py +++ b/setup.py @@ -134,6 +134,9 @@ "permutation.basic = qiskit.transpiler.passes.synthesis.high_level_synthesis:BasicSynthesisPermutation", "permutation.acg = qiskit.transpiler.passes.synthesis.high_level_synthesis:ACGSynthesisPermutation", ], + "qiskit.transpiler.init": [ + "default = qiskit.transpiler.preset_passmanagers.builtin_plugins:DefaultInitPassManager", + ], "qiskit.transpiler.translation": [ "translator = qiskit.transpiler.preset_passmanagers.builtin_plugins:BasisTranslatorPassManager", "unroller = qiskit.transpiler.preset_passmanagers.builtin_plugins:UnrollerPassManager", diff --git a/test/python/transpiler/test_preset_passmanagers.py b/test/python/transpiler/test_preset_passmanagers.py index 7074d0f2a8ea..f84beb3e5bda 100644 --- a/test/python/transpiler/test_preset_passmanagers.py +++ b/test/python/transpiler/test_preset_passmanagers.py @@ -70,6 +70,8 @@ def mock_get_passmanager_stage( ] ) return pm + elif stage_name == "init": + return PassManager([]) elif stage_name == "routing": return PassManager([]) elif stage_name == "optimization":