From 553c79561c60a301c75f3de2fb99a49304c3150f Mon Sep 17 00:00:00 2001 From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> Date: Mon, 7 Aug 2023 17:02:48 -0400 Subject: [PATCH 1/4] Initial: Optimization stage as a plugin. --- .../preset_passmanagers/builtin_plugins.py | 136 ++++++++++++++++++ .../transpiler/preset_passmanagers/level0.py | 10 +- .../transpiler/preset_passmanagers/level1.py | 42 +----- .../transpiler/preset_passmanagers/level2.py | 44 +----- .../transpiler/preset_passmanagers/level3.py | 94 ++---------- ...timization-as-plugin-ffd28171e9c5a3c3.yaml | 5 + setup.py | 3 + 7 files changed, 169 insertions(+), 165 deletions(-) create mode 100644 releasenotes/notes/optimization-as-plugin-ffd28171e9c5a3c3.yaml diff --git a/qiskit/transpiler/preset_passmanagers/builtin_plugins.py b/qiskit/transpiler/preset_passmanagers/builtin_plugins.py index 8a44950d4367..54f63ca19f94 100644 --- a/qiskit/transpiler/preset_passmanagers/builtin_plugins.py +++ b/qiskit/transpiler/preset_passmanagers/builtin_plugins.py @@ -21,6 +21,20 @@ from qiskit.transpiler.passes import Error from qiskit.transpiler.preset_passmanagers import common from qiskit.transpiler.preset_passmanagers.plugin import PassManagerStagePlugin +from qiskit.transpiler.preset_passmanagers.plugin import ( + PassManagerStagePluginManager, +) +from qiskit.transpiler.passes.optimization import ( + Optimize1qGatesDecomposition, + CommutativeCancellation, + Collect2qBlocks, + ConsolidateBlocks, + CXCancellation, +) +from qiskit.transpiler.passes import Depth, Size, FixedPoint, MinimumPoint +from qiskit.transpiler.passes.utils.gates_basis import GatesInBasis +from qiskit.transpiler.passes.synthesis.unitary_synthesis import UnitarySynthesis +from qiskit.passmanager.flow_controllers import ConditionalController class BasicSwapPassManager(PassManagerStagePlugin): @@ -315,3 +329,125 @@ def pass_manager(self, pass_manager_config, optimization_level=None) -> PassMana seed_transpiler=seed_transpiler, use_barrier_before_measurement=True, ) + + +class OptimizationPassManager(PassManagerStagePlugin): + """Plugin class for optimization stage""" + + def pass_manager(self, pass_manager_config, optimization_level=None) -> PassManager: + """Build pass manager for optimization stage.""" + # Obtain the translation method required for this pass to work + translation_method = pass_manager_config.translation_method or "translator" + optimization = PassManager() + if optimization_level != 0: + plugin_manager = PassManagerStagePluginManager() + _depth_check = [Depth(recurse=True), FixedPoint("depth")] + _size_check = [Size(recurse=True), FixedPoint("size")] + # Minimum point check for optimization level 3. + _minimum_point_check = [ + Depth(recurse=True), + Size(recurse=True), + MinimumPoint(["depth", "size"], "optimization_loop"), + ] + + def _opt_control(property_set): + return (not property_set["depth_fixed_point"]) or ( + not property_set["size_fixed_point"] + ) + + if translation_method not in { + "translator", + "synthesis", + "unroller", + }: + translation = plugin_manager.get_passmanager_stage( + "translation", + translation_method, + pass_manager_config, + optimization_level=1, + ) + else: + translation = common.generate_translation_passmanager( + pass_manager_config.target, + pass_manager_config.basis_gates, + translation_method, + pass_manager_config.approximation_degree, + pass_manager_config.coupling_map, + pass_manager_config.backend_properties, + pass_manager_config.unitary_synthesis_method, + pass_manager_config.unitary_synthesis_plugin_config, + pass_manager_config.hls_config, + ) + + if optimization_level == 2: + # Steps for optimization level 2 + _opt = [ + Optimize1qGatesDecomposition( + basis=pass_manager_config.basis_gates, target=pass_manager_config.target + ), + CommutativeCancellation( + basis_gates=pass_manager_config.basis_gates, + target=pass_manager_config.target, + ), + ] + + elif optimization_level == 3: + # Steps for optimization level 3 + _opt = [ + Collect2qBlocks(), + ConsolidateBlocks( + basis_gates=pass_manager_config.basis_gates, + target=pass_manager_config.target, + approximation_degree=pass_manager_config.approximation_degree, + ), + UnitarySynthesis( + pass_manager_config.basis_gates, + approximation_degree=pass_manager_config.approximation_degree, + coupling_map=pass_manager_config.coupling_map, + backend_props=pass_manager_config.backend_properties, + method=pass_manager_config.unitary_synthesis_method, + plugin_config=pass_manager_config.unitary_synthesis_plugin_config, + target=pass_manager_config.target, + ), + Optimize1qGatesDecomposition( + basis=pass_manager_config.basis_gates, target=pass_manager_config.target + ), + CommutativeCancellation(target=pass_manager_config.target), + ] + + def _opt_control(property_set): + return not property_set["optimization_loop_minimum_point"] + + else: + # Steps for optimization level 1 + _opt = [ + Optimize1qGatesDecomposition( + basis=pass_manager_config.basis_gates, target=pass_manager_config.target + ), + CXCancellation(), + ] + + unroll = [pass_ for x in translation.passes() for pass_ in x["passes"]] + # Build nested Flow controllers + def _unroll_condition(property_set): + return not property_set["all_gates_in_basis"] + + # Check if any gate is not in the basis, and if so, run unroll passes + _unroll_if_out_of_basis = [ + GatesInBasis(pass_manager_config.basis_gates, target=pass_manager_config.target), + ConditionalController(unroll, condition=_unroll_condition), + ] + + if optimization_level == 3: + optimization.append(_minimum_point_check) + else: + optimization.append(_depth_check + _size_check) + opt_loop = ( + _opt + _unroll_if_out_of_basis + _minimum_point_check + if optimization_level == 3 + else _opt + _unroll_if_out_of_basis + _depth_check + _size_check + ) + optimization.append(opt_loop, do_while=_opt_control) + return optimization + else: + return None diff --git a/qiskit/transpiler/preset_passmanagers/level0.py b/qiskit/transpiler/preset_passmanagers/level0.py index b0790f1026f2..6c0704d996ba 100644 --- a/qiskit/transpiler/preset_passmanagers/level0.py +++ b/qiskit/transpiler/preset_passmanagers/level0.py @@ -60,7 +60,7 @@ def level_0_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa layout_method = pass_manager_config.layout_method or "trivial" 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 + optimization_method = pass_manager_config.optimization_method or "default" scheduling_method = pass_manager_config.scheduling_method instruction_durations = pass_manager_config.instruction_durations seed_transpiler = pass_manager_config.seed_transpiler @@ -186,11 +186,9 @@ def _swap_mapped(property_set): ) elif unroll_3q is not None: init += unroll_3q - optimization = None - if optimization_method is not None: - optimization = plugin_manager.get_passmanager_stage( - "optimization", optimization_method, pass_manager_config, optimization_level=0 - ) + optimization = plugin_manager.get_passmanager_stage( + "optimization", optimization_method, pass_manager_config, optimization_level=0 + ) return StagedPassManager( init=init, diff --git a/qiskit/transpiler/preset_passmanagers/level1.py b/qiskit/transpiler/preset_passmanagers/level1.py index c56cd820262c..9e3bf11eea7b 100644 --- a/qiskit/transpiler/preset_passmanagers/level1.py +++ b/qiskit/transpiler/preset_passmanagers/level1.py @@ -20,21 +20,14 @@ from qiskit.transpiler.timing_constraints import TimingConstraints from qiskit.transpiler.passmanager import PassManager from qiskit.transpiler.passmanager import StagedPassManager -from qiskit.transpiler import ConditionalController, FlowController -from qiskit.transpiler.passes import CXCancellation from qiskit.transpiler.passes import SetLayout from qiskit.transpiler.passes import VF2Layout from qiskit.transpiler.passes import TrivialLayout from qiskit.transpiler.passes import DenseLayout from qiskit.transpiler.passes import NoiseAdaptiveLayout from qiskit.transpiler.passes import SabreLayout -from qiskit.transpiler.passes import FixedPoint -from qiskit.transpiler.passes import Depth -from qiskit.transpiler.passes import Size -from qiskit.transpiler.passes import Optimize1qGatesDecomposition from qiskit.transpiler.passes import CheckMap -from qiskit.transpiler.passes import GatesInBasis from qiskit.transpiler.passes import BarrierBeforeFinalMeasurements from qiskit.transpiler.preset_passmanagers import common from qiskit.transpiler.passes.layout.vf2_layout import VF2LayoutStopReason @@ -76,7 +69,7 @@ def level_1_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa 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 + optimization_method = pass_manager_config.optimization_method or "default" scheduling_method = pass_manager_config.scheduling_method instruction_durations = pass_manager_config.instruction_durations seed_transpiler = pass_manager_config.seed_transpiler @@ -163,16 +156,6 @@ def _vf2_match_not_found(property_set): "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 - _depth_check = [Depth(recurse=True), FixedPoint("depth")] - _size_check = [Size(recurse=True), FixedPoint("size")] - - def _opt_control(property_set): - return (not property_set["depth_fixed_point"]) or (not property_set["size_fixed_point"]) - - _opt = [Optimize1qGatesDecomposition(basis=basis_gates, target=target), CXCancellation()] - unroll_3q = None # Build full pass manager if coupling_map or initial_layout: @@ -236,26 +219,9 @@ def _swap_mapped(property_set): ) else: pre_optimization = common.generate_pre_op_passmanager(remove_reset_in_zero=True) - if optimization_method is None: - optimization = PassManager() - unroll = [pass_ for x in translation.passes() for pass_ in x["passes"]] - # Build nested Flow controllers - def _unroll_condition(property_set): - return not property_set["all_gates_in_basis"] - - # Check if any gate is not in the basis, and if so, run unroll passes - _unroll_if_out_of_basis: list[BasePass | FlowController] = [ - GatesInBasis(basis_gates, target=target), - ConditionalController(unroll, condition=_unroll_condition), - ] - - optimization.append(_depth_check + _size_check) - opt_loop = _opt + _unroll_if_out_of_basis + _depth_check + _size_check - optimization.append(opt_loop, do_while=_opt_control) - else: - optimization = plugin_manager.get_passmanager_stage( - "optimization", optimization_method, pass_manager_config, optimization_level=1 - ) + optimization = plugin_manager.get_passmanager_stage( + "optimization", optimization_method, pass_manager_config, optimization_level=1 + ) if scheduling_method is None or scheduling_method in {"alap", "asap"}: sched = common.generate_scheduling( instruction_durations, scheduling_method, timing_constraints, inst_map, target=target diff --git a/qiskit/transpiler/preset_passmanagers/level2.py b/qiskit/transpiler/preset_passmanagers/level2.py index 62880e3eeec9..a8094534b1b0 100644 --- a/qiskit/transpiler/preset_passmanagers/level2.py +++ b/qiskit/transpiler/preset_passmanagers/level2.py @@ -21,7 +21,6 @@ from qiskit.transpiler.timing_constraints import TimingConstraints from qiskit.transpiler.passmanager import PassManager from qiskit.transpiler.passmanager import StagedPassManager -from qiskit.transpiler import ConditionalController, FlowController from qiskit.transpiler.passes import SetLayout from qiskit.transpiler.passes import VF2Layout @@ -29,12 +28,6 @@ from qiskit.transpiler.passes import DenseLayout from qiskit.transpiler.passes import NoiseAdaptiveLayout from qiskit.transpiler.passes import SabreLayout -from qiskit.transpiler.passes import FixedPoint -from qiskit.transpiler.passes import Depth -from qiskit.transpiler.passes import Size -from qiskit.transpiler.passes import Optimize1qGatesDecomposition -from qiskit.transpiler.passes import CommutativeCancellation -from qiskit.transpiler.passes import GatesInBasis from qiskit.transpiler.passes import BarrierBeforeFinalMeasurements from qiskit.transpiler.preset_passmanagers import common from qiskit.transpiler.passes.layout.vf2_layout import VF2LayoutStopReason @@ -76,7 +69,7 @@ def level_2_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa 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 + optimization_method = pass_manager_config.optimization_method or "default" scheduling_method = pass_manager_config.scheduling_method instruction_durations = pass_manager_config.instruction_durations seed_transpiler = pass_manager_config.seed_transpiler @@ -153,19 +146,6 @@ def _vf2_match_not_found(property_set): "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 - _depth_check = [Depth(recurse=True), FixedPoint("depth")] - _size_check = [Size(recurse=True), FixedPoint("size")] - - def _opt_control(property_set): - return (not property_set["depth_fixed_point"]) or (not property_set["size_fixed_point"]) - - _opt: list[BasePass] = [ - Optimize1qGatesDecomposition(basis=basis_gates, target=target), - CommutativeCancellation(basis_gates=basis_gates, target=target), - ] - unroll_3q = None # Build pass manager if coupling_map or initial_layout: @@ -223,25 +203,9 @@ def _swap_mapped(property_set): pre_optimization = common.generate_pre_op_passmanager(target, coupling_map, True) else: pre_optimization = common.generate_pre_op_passmanager(remove_reset_in_zero=True) - if optimization_method is None: - optimization = PassManager() - unroll = [pass_ for x in translation.passes() for pass_ in x["passes"]] - # Build nested Flow controllers - def _unroll_condition(property_set): - return not property_set["all_gates_in_basis"] - - # Check if any gate is not in the basis, and if so, run unroll passes - _unroll_if_out_of_basis: list[BasePass | FlowController] = [ - GatesInBasis(basis_gates, target=target), - ConditionalController(unroll, condition=_unroll_condition), - ] - optimization.append(_depth_check + _size_check) - opt_loop = _opt + _unroll_if_out_of_basis + _depth_check + _size_check - optimization.append(opt_loop, do_while=_opt_control) - else: - optimization = plugin_manager.get_passmanager_stage( - "optimization", optimization_method, pass_manager_config, optimization_level=2 - ) + optimization = plugin_manager.get_passmanager_stage( + "optimization", optimization_method, pass_manager_config, optimization_level=2 + ) if scheduling_method is None or scheduling_method in {"alap", "asap"}: sched = common.generate_scheduling( instruction_durations, diff --git a/qiskit/transpiler/preset_passmanagers/level3.py b/qiskit/transpiler/preset_passmanagers/level3.py index 81ca9af75eee..48dec24c8dea 100644 --- a/qiskit/transpiler/preset_passmanagers/level3.py +++ b/qiskit/transpiler/preset_passmanagers/level3.py @@ -28,20 +28,10 @@ from qiskit.transpiler.passes import DenseLayout from qiskit.transpiler.passes import NoiseAdaptiveLayout from qiskit.transpiler.passes import SabreLayout -from qiskit.transpiler.passes import MinimumPoint -from qiskit.transpiler.passes import Depth -from qiskit.transpiler.passes import Size from qiskit.transpiler.passes import RemoveResetInZeroState -from qiskit.transpiler.passes import Optimize1qGatesDecomposition -from qiskit.transpiler.passes import CommutativeCancellation from qiskit.transpiler.passes import OptimizeSwapBeforeMeasure from qiskit.transpiler.passes import RemoveDiagonalGatesBeforeMeasure -from qiskit.transpiler.passes import Collect2qBlocks -from qiskit.transpiler.passes import ConsolidateBlocks -from qiskit.transpiler.passes import UnitarySynthesis -from qiskit.transpiler.passes import GatesInBasis from qiskit.transpiler.passes import BarrierBeforeFinalMeasurements -from qiskit.transpiler.runningpassmanager import ConditionalController, FlowController from qiskit.transpiler.preset_passmanagers import common from qiskit.transpiler.passes.layout.vf2_layout import VF2LayoutStopReason from qiskit.transpiler.preset_passmanagers.plugin import ( @@ -81,7 +71,7 @@ def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa 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 + optimization_method = pass_manager_config.optimization_method or "default" scheduling_method = pass_manager_config.scheduling_method instruction_durations = pass_manager_config.instruction_durations seed_transpiler = pass_manager_config.seed_transpiler @@ -159,35 +149,6 @@ def _vf2_match_not_found(property_set): "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. - _minimum_point_check: list[BasePass | FlowController] = [ - Depth(recurse=True), - Size(recurse=True), - MinimumPoint(["depth", "size"], "optimization_loop"), - ] - - def _opt_control(property_set): - return not property_set["optimization_loop_minimum_point"] - - _opt: list[BasePass | FlowController] = [ - Collect2qBlocks(), - ConsolidateBlocks( - basis_gates=basis_gates, target=target, approximation_degree=approximation_degree - ), - UnitarySynthesis( - basis_gates, - approximation_degree=approximation_degree, - coupling_map=coupling_map, - backend_props=backend_properties, - method=unitary_synthesis_method, - plugin_config=unitary_synthesis_plugin_config, - target=target, - ), - Optimize1qGatesDecomposition(basis=basis_gates, target=target), - CommutativeCancellation(target=target), - ] - # Build pass manager init = common.generate_control_flow_options_check( layout_method=layout_method, @@ -255,49 +216,20 @@ def _swap_mapped(property_set): hls_config, ) - if optimization_method is None: - optimization = PassManager() - unroll = [pass_ for x in translation.passes() for pass_ in x["passes"]] - # Build nested Flow controllers - def _unroll_condition(property_set): - return not property_set["all_gates_in_basis"] - - # Check if any gate is not in the basis, and if so, run unroll passes - _unroll_if_out_of_basis: list[BasePass | FlowController] = [ - GatesInBasis(basis_gates, target=target), - ConditionalController(unroll, condition=_unroll_condition), + optimization = plugin_manager.get_passmanager_stage( + "optimization", optimization_method, pass_manager_config, optimization_level=3 + ) + if (coupling_map and not coupling_map.is_symmetric) or ( + 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"] ] - - optimization.append(_minimum_point_check) - if (coupling_map and not coupling_map.is_symmetric) or ( - 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"] - ] - if optimization is not None: - optimization.append( - _opt + _unroll_if_out_of_basis + _minimum_point_check, - do_while=_opt_control, - ) - else: - pre_optimization = common.generate_pre_op_passmanager(remove_reset_in_zero=True) - optimization.append( - _opt + _unroll_if_out_of_basis + _minimum_point_check, do_while=_opt_control - ) else: - optimization = plugin_manager.get_passmanager_stage( - "optimization", optimization_method, pass_manager_config, optimization_level=3 - ) - if (coupling_map and not coupling_map.is_symmetric) or ( - 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) - else: - pre_optimization = common.generate_pre_op_passmanager(remove_reset_in_zero=True) + pre_optimization = common.generate_pre_op_passmanager(remove_reset_in_zero=True) if scheduling_method is None or scheduling_method in {"alap", "asap"}: sched = common.generate_scheduling( diff --git a/releasenotes/notes/optimization-as-plugin-ffd28171e9c5a3c3.yaml b/releasenotes/notes/optimization-as-plugin-ffd28171e9c5a3c3.yaml new file mode 100644 index 000000000000..d5688ead9754 --- /dev/null +++ b/releasenotes/notes/optimization-as-plugin-ffd28171e9c5a3c3.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Added :class:`qiskit.transpiler.preset_passmanagers.builtin_plugins.OptimizationPassManager`. + as the plugin representation of the `optimization` stage of the transpiler. diff --git a/setup.py b/setup.py index 21f64a17b94d..7dd41659125c 100644 --- a/setup.py +++ b/setup.py @@ -146,5 +146,8 @@ "sabre = qiskit.transpiler.preset_passmanagers.builtin_plugins:SabreSwapPassManager", "none = qiskit.transpiler.preset_passmanagers.builtin_plugins:NoneRoutingPassManager", ], + "qiskit.transpiler.optimization": [ + "default = qiskit.transpiler.preset_passmanagers.builtin_plugins:OptimizationPassManager", + ], }, ) From 70cf13d2365c9e9d371629c5c60349b406ef6dd2 Mon Sep 17 00:00:00 2001 From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> Date: Mon, 7 Aug 2023 21:58:12 -0400 Subject: [PATCH 2/4] CI: Added fix to preset_passmanager test --- test/python/transpiler/test_preset_passmanagers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/python/transpiler/test_preset_passmanagers.py b/test/python/transpiler/test_preset_passmanagers.py index b7c496fabb62..3cbc1acb0fa9 100644 --- a/test/python/transpiler/test_preset_passmanagers.py +++ b/test/python/transpiler/test_preset_passmanagers.py @@ -47,6 +47,7 @@ from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager from qiskit.transpiler.preset_passmanagers import level0, level1, level2, level3 from qiskit.transpiler.passes import Collect2qBlocks, GatesInBasis +from qiskit.transpiler.preset_passmanagers.builtin_plugins import OptimizationPassManager def mock_get_passmanager_stage( @@ -71,6 +72,8 @@ def mock_get_passmanager_stage( return pm elif stage_name == "routing": return PassManager([]) + elif stage_name == "optimization": + return OptimizationPassManager().pass_manager(pm_config, optimization_level) else: raise Exception("Failure, unexpected stage plugin combo for test") From 52ece9dbfb1c2784adf222f45e4cbc15c446209d Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 22 Aug 2023 09:53:50 -0400 Subject: [PATCH 3/4] Simplify inner translation stage creation logic This commit changes the plugin construction logic slightly to adjust how the embedded translation stage is created. After #10621 merged we only need to use the plugin interface to get the translation stage pass manager. --- .../preset_passmanagers/builtin_plugins.py | 49 ++++++------------- .../transpiler/preset_passmanagers/level1.py | 2 - .../transpiler/preset_passmanagers/level2.py | 2 - .../transpiler/preset_passmanagers/level3.py | 3 -- 4 files changed, 16 insertions(+), 40 deletions(-) diff --git a/qiskit/transpiler/preset_passmanagers/builtin_plugins.py b/qiskit/transpiler/preset_passmanagers/builtin_plugins.py index 3bb950ff64f3..2ecd4653707b 100644 --- a/qiskit/transpiler/preset_passmanagers/builtin_plugins.py +++ b/qiskit/transpiler/preset_passmanagers/builtin_plugins.py @@ -416,31 +416,21 @@ def _opt_control(property_set): not property_set["size_fixed_point"] ) - if translation_method not in { - "translator", - "synthesis", - "unroller", - }: - translation = plugin_manager.get_passmanager_stage( - "translation", - translation_method, - pass_manager_config, - optimization_level=1, - ) - else: - translation = common.generate_translation_passmanager( - pass_manager_config.target, - pass_manager_config.basis_gates, - translation_method, - pass_manager_config.approximation_degree, - pass_manager_config.coupling_map, - pass_manager_config.backend_properties, - pass_manager_config.unitary_synthesis_method, - pass_manager_config.unitary_synthesis_plugin_config, - pass_manager_config.hls_config, - ) - - if optimization_level == 2: + translation = plugin_manager.get_passmanager_stage( + "translation", + translation_method, + pass_manager_config, + optimization_level=optimization_level, + ) + if optimization_level == 1: + # Steps for optimization level 1 + _opt = [ + Optimize1qGatesDecomposition( + basis=pass_manager_config.basis_gates, target=pass_manager_config.target + ), + CXCancellation(), + ] + elif optimization_level == 2: # Steps for optimization level 2 _opt = [ Optimize1qGatesDecomposition( @@ -451,7 +441,6 @@ def _opt_control(property_set): target=pass_manager_config.target, ), ] - elif optimization_level == 3: # Steps for optimization level 3 _opt = [ @@ -480,13 +469,7 @@ def _opt_control(property_set): return not property_set["optimization_loop_minimum_point"] else: - # Steps for optimization level 1 - _opt = [ - Optimize1qGatesDecomposition( - basis=pass_manager_config.basis_gates, target=pass_manager_config.target - ), - CXCancellation(), - ] + raise TranspilerError(f"Invalid optimization_level: {optimization_level}") unroll = [pass_ for x in translation.passes() for pass_ in x["passes"]] # Build nested Flow controllers diff --git a/qiskit/transpiler/preset_passmanagers/level1.py b/qiskit/transpiler/preset_passmanagers/level1.py index 2204456fb65e..22be66c4370c 100644 --- a/qiskit/transpiler/preset_passmanagers/level1.py +++ b/qiskit/transpiler/preset_passmanagers/level1.py @@ -15,9 +15,7 @@ Level 1 pass manager: light optimization by simple adjacent gate collapsing. """ from __future__ import annotations -from qiskit.transpiler.basepasses import BasePass from qiskit.transpiler.passmanager_config import PassManagerConfig -from qiskit.transpiler.passmanager import PassManager from qiskit.transpiler.passmanager import StagedPassManager from qiskit.transpiler.preset_passmanagers import common from qiskit.transpiler.preset_passmanagers.plugin import ( diff --git a/qiskit/transpiler/preset_passmanagers/level2.py b/qiskit/transpiler/preset_passmanagers/level2.py index 8d2005ea4d78..8815a983ca61 100644 --- a/qiskit/transpiler/preset_passmanagers/level2.py +++ b/qiskit/transpiler/preset_passmanagers/level2.py @@ -16,9 +16,7 @@ gate cancellation using commutativity rules. """ from __future__ import annotations -from qiskit.transpiler.basepasses import BasePass from qiskit.transpiler.passmanager_config import PassManagerConfig -from qiskit.transpiler.passmanager import PassManager from qiskit.transpiler.passmanager import StagedPassManager from qiskit.transpiler.preset_passmanagers import common from qiskit.transpiler.preset_passmanagers.plugin import ( diff --git a/qiskit/transpiler/preset_passmanagers/level3.py b/qiskit/transpiler/preset_passmanagers/level3.py index e6c253be4781..1e4c7d589b35 100644 --- a/qiskit/transpiler/preset_passmanagers/level3.py +++ b/qiskit/transpiler/preset_passmanagers/level3.py @@ -16,9 +16,7 @@ gate cancellation using commutativity rules and unitary synthesis. """ from __future__ import annotations -from qiskit.transpiler.basepasses import BasePass from qiskit.transpiler.passmanager_config import PassManagerConfig -from qiskit.transpiler.passmanager import PassManager from qiskit.transpiler.passmanager import StagedPassManager from qiskit.transpiler.passes import RemoveResetInZeroState from qiskit.transpiler.passes import OptimizeSwapBeforeMeasure @@ -63,7 +61,6 @@ def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa 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" - backend_properties = pass_manager_config.backend_properties 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 From 708cbad8e89b709416e33ded5131742153944ce9 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 22 Aug 2023 10:39:13 -0400 Subject: [PATCH 4/4] Update documentation --- qiskit/transpiler/preset_passmanagers/plugin.py | 2 +- .../default-reserved-plugin-name-3825c2000a579e38.yaml | 10 +++++----- .../notes/optimization-as-plugin-ffd28171e9c5a3c3.yaml | 5 ----- 3 files changed, 6 insertions(+), 11 deletions(-) delete mode 100644 releasenotes/notes/optimization-as-plugin-ffd28171e9c5a3c3.yaml diff --git a/qiskit/transpiler/preset_passmanagers/plugin.py b/qiskit/transpiler/preset_passmanagers/plugin.py index aa935fd7bb77..d46a892e11c7 100644 --- a/qiskit/transpiler/preset_passmanagers/plugin.py +++ b/qiskit/transpiler/preset_passmanagers/plugin.py @@ -76,7 +76,7 @@ instruction on the target backend. * - ``optimization`` - ``qiskit.transpiler.optimization`` - - There are no reserved plugin names + - ``default`` - This stage is expected to perform optimization and simplification. The constraints from earlier stages still apply to the output of this stage. After the ``optimization`` stage is run we expect the circuit diff --git a/releasenotes/notes/default-reserved-plugin-name-3825c2000a579e38.yaml b/releasenotes/notes/default-reserved-plugin-name-3825c2000a579e38.yaml index 904ad9b4b926..ebb207eb837b 100644 --- a/releasenotes/notes/default-reserved-plugin-name-3825c2000a579e38.yaml +++ b/releasenotes/notes/default-reserved-plugin-name-3825c2000a579e38.yaml @@ -2,8 +2,8 @@ upgrade: - | The plugin name ``default`` is reserved for the :ref:`stage_table` - ``layout`` 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 Qiskit's usage and - you should rename your plugin. + ``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 + Qiskit's usage and you should rename your plugin. diff --git a/releasenotes/notes/optimization-as-plugin-ffd28171e9c5a3c3.yaml b/releasenotes/notes/optimization-as-plugin-ffd28171e9c5a3c3.yaml deleted file mode 100644 index d5688ead9754..000000000000 --- a/releasenotes/notes/optimization-as-plugin-ffd28171e9c5a3c3.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -features: - - | - Added :class:`qiskit.transpiler.preset_passmanagers.builtin_plugins.OptimizationPassManager`. - as the plugin representation of the `optimization` stage of the transpiler.