Skip to content

Commit

Permalink
Migrate init stage to plugins
Browse files Browse the repository at this point in the history
This commit updates the preset pass manager construction to only use
plugins for the init stage. To accomplish this the previously hard
coded built-in pass manager used for each optimization level are
refactored to be in a plugin named "default". One thing that is changed
in this PR is that the use of `generate_control_flow_options_check()`
is moved to the `pre_init` stage. The reason for this is because the way
the init stage was being constructed in the preset pass managers was to
do initial checking of any methods, and this was unconditionally being
run. This is a more logical fit for pre_init stage because it should run
before any specified plugin.

Fixes: Qiskit#10687
Fixes: Qiskit#8661
  • Loading branch information
mtreinish committed Aug 22, 2023
1 parent 4ab2ef8 commit 6e5dab6
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 87 deletions.
42 changes: 42 additions & 0 deletions qiskit/transpiler/preset_passmanagers/builtin_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,54 @@
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
from qiskit.transpiler.timing_constraints import TimingConstraints
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`"""

Expand Down
27 changes: 6 additions & 21 deletions qiskit/transpiler/preset_passmanagers/level0.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
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
)
Expand All @@ -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,
Expand All @@ -107,19 +94,17 @@ 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 = None
if optimization_method is not None:
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,
Expand Down
27 changes: 6 additions & 21 deletions qiskit/transpiler/preset_passmanagers/level1.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,15 @@ 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"
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 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(
Expand All @@ -86,17 +82,8 @@ def _opt_control(property_set):

_opt = [Optimize1qGatesDecomposition(basis=basis_gates, target=target), CXCancellation()]

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
)
Expand Down Expand Up @@ -143,7 +130,7 @@ def _unroll_condition(property_set):
"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,
Expand All @@ -152,14 +139,12 @@ def _unroll_condition(property_set):
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,
Expand Down
27 changes: 6 additions & 21 deletions qiskit/transpiler/preset_passmanagers/level2.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,13 @@ 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
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(
Expand All @@ -90,17 +86,8 @@ def _opt_control(property_set):
CommutativeCancellation(basis_gates=basis_gates, target=target),
]

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
)
Expand Down Expand Up @@ -142,7 +129,7 @@ def _unroll_condition(property_set):
"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,
Expand All @@ -151,14 +138,12 @@ def _unroll_condition(property_set):
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,
Expand Down
28 changes: 6 additions & 22 deletions qiskit/transpiler/preset_passmanagers/level3.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,8 @@
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
Expand Down Expand Up @@ -66,7 +63,7 @@ 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"
Expand All @@ -77,7 +74,6 @@ def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa
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(
Expand Down Expand Up @@ -114,7 +110,7 @@ def _opt_control(property_set):
]

# 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,
Expand All @@ -123,22 +119,9 @@ def _opt_control(property_set):
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
Expand Down Expand Up @@ -201,6 +184,7 @@ def _unroll_condition(property_set):
)

return StagedPassManager(
pre_init=pre_init,
init=init,
layout=layout,
routing=routing,
Expand Down
2 changes: 1 addition & 1 deletion qiskit/transpiler/preset_passmanagers/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
upgrade:
- |
The plugin name ``default`` is reserved for the :ref:`stage_table`
``layout`` and ``scheduling``. These stages previously did not reserve this
``init``, ``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
Expand Down
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 2 additions & 0 deletions test/python/transpiler/test_preset_passmanagers.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ def mock_get_passmanager_stage(
]
)
return pm
elif stage_name == "init":
return PassManager([])
elif stage_name == "routing":
return PassManager([])
elif stage_name == "layout":
Expand Down

0 comments on commit 6e5dab6

Please sign in to comment.