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

Update transpiler pipeline to (only) use target internally #12850

Merged
merged 33 commits into from
Mar 6, 2025
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
8eea4cf
First attempt at supporting a virtual target (FakeTarget) with no bas…
ElePT Oct 17, 2024
6204af4
Remove prints
ElePT Oct 17, 2024
77eff6e
Fix control-flow failures with fake target
ElePT Oct 24, 2024
efca6d2
Fix init stage, add instruction_supported method to FakeTarget
ElePT Oct 24, 2024
91947e4
Tweak preset pass manager
ElePT Oct 24, 2024
0c771e6
Merge branch 'main' of https://github.com/Qiskit/qiskit into transpil…
ElePT Nov 1, 2024
1ac1f59
Handle inst_map deprecation warning
ElePT Nov 1, 2024
472cf64
Handle annotated operations
ElePT Nov 1, 2024
1ba5381
Do not skip stages with FakeTarget
ElePT Nov 1, 2024
c3a2573
Deprecate custom basis gates
ElePT Nov 1, 2024
cbd0973
Cleanup
ElePT Nov 1, 2024
2df8a27
Remove reno
ElePT Nov 5, 2024
e79f06c
Refactor creation of _FakeTarget, add tests
ElePT Nov 5, 2024
ab1bc10
Merge branch 'main' of https://github.com/Qiskit/qiskit into transpil…
ElePT Nov 5, 2024
75a5535
Fix handling of pre-optimization stage and gate direction passes
ElePT Nov 5, 2024
390a322
* Merge branch 'main' of https://github.com/Qiskit/qiskit into transp…
ElePT Jan 10, 2025
33dc0c4
Restore cargo.lock
ElePT Jan 10, 2025
0008e52
Address most lint complaints
ElePT Jan 10, 2025
a46ec06
Fix dt issue
ElePT Jan 13, 2025
dafa66b
Merge branch 'main' of https://github.com/Qiskit/qiskit into transpil…
ElePT Jan 14, 2025
570c1e8
Address HLS issue
ElePT Jan 14, 2025
c11219b
Address GateDirection issue
ElePT Jan 14, 2025
321ce00
Fix lint and improve style
ElePT Jan 14, 2025
92fad86
Refactor plugin logic, handle target with no basis gates at the pass …
ElePT Jan 15, 2025
10affb9
Merge branch 'main' of https://github.com/Qiskit/qiskit into transpil…
ElePT Jan 20, 2025
f8afe3b
Merge branch 'main' of https://github.com/Qiskit/qiskit into transpil…
ElePT Mar 4, 2025
1d449ea
Remove deprecated arguments: instruction_durations, timing_constrants…
ElePT Mar 5, 2025
d1dc700
Merge branch 'main' of https://github.com/Qiskit/qiskit into transpil…
ElePT Mar 6, 2025
8528114
Apply suggestions from Eli's code review
ElePT Mar 6, 2025
881cb26
Merge branch 'transpile-only-target-pipeline' of https://github.com/E…
ElePT Mar 6, 2025
6a53a58
Clean up
ElePT Mar 6, 2025
591664c
Apply suggestions from Eli's code review. Add reno for API changes. F…
ElePT Mar 6, 2025
2b12e65
Fix merge conflict
ElePT Mar 6, 2025
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
2 changes: 1 addition & 1 deletion qiskit/transpiler/passes/layout/vf2_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def build_average_error_map(target, properties, coupling_map):
# running the fallback heuristic
if not built and target is not None and coupling_map is None:
coupling_map = target.build_coupling_map()
if not built and coupling_map is not None:
if not built and coupling_map is not None and num_qubits is not None:
for qubit in range(num_qubits):
avg_map.add_error(
(qubit, qubit),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,9 @@ def __init__(
self._basis_gates = basis_gates
self._min_qubits = min_qubits

self._top_level_only = self._basis_gates is None and self._target is None
self._top_level_only = (self._basis_gates is None or len(self._basis_gates) == 0) and (
self._target is None or len(self._target.operation_names) == 0
)

# include path for when target exists but target.num_qubits is None (BasicSimulator)
if not self._top_level_only and (self._target is None or self._target.num_qubits is None):
Expand Down
121 changes: 80 additions & 41 deletions qiskit/transpiler/preset_passmanagers/builtin_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ def pass_manager(self, pass_manager_config, optimization_level=None) -> PassMana


class UnitarySynthesisPassManager(PassManagerStagePlugin):
"""Plugin class for translation stage with :class:`~.BasisTranslator`"""
"""Plugin class for translation stage with :class:`~.UnitarySynthesis`"""

def pass_manager(self, pass_manager_config, optimization_level=None) -> PassManager:
return common.generate_translation_passmanager(
Expand Down Expand Up @@ -558,10 +558,18 @@ def _opt_control(property_set):
)
if optimization_level == 1:
# Steps for optimization level 1
_opt = [
Optimize1qGatesDecomposition(
basis=pass_manager_config.basis_gates, target=pass_manager_config.target
),
if (
pass_manager_config.basis_gates is not None
and len(pass_manager_config.basis_gates) > 0
):
_opt = [
Optimize1qGatesDecomposition(
basis=pass_manager_config.basis_gates, target=pass_manager_config.target
)
]
else:
_opt = []
_opt += [
InverseCancellation(
[
CXGate(),
Expand All @@ -581,10 +589,18 @@ def _opt_control(property_set):
]

elif optimization_level == 2:
_opt = [
Optimize1qGatesDecomposition(
basis=pass_manager_config.basis_gates, target=pass_manager_config.target
),
if (
pass_manager_config.basis_gates is not None
and len(pass_manager_config.basis_gates) > 0
):
_opt = [
Optimize1qGatesDecomposition(
basis=pass_manager_config.basis_gates, target=pass_manager_config.target
)
]
else:
_opt = []
_opt += [
CommutativeCancellation(target=pass_manager_config.target),
]
elif optimization_level == 3:
Expand All @@ -596,21 +612,29 @@ def _opt_control(property_set):
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),
]

if (
pass_manager_config.basis_gates is not None
and len(pass_manager_config.basis_gates) > 0
):
_opt += [
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
),
]

_opt += [CommutativeCancellation(target=pass_manager_config.target)]

def _opt_control(property_set):
return not property_set["optimization_loop_minimum_point"]

Expand All @@ -632,25 +656,40 @@ def _unroll_condition(property_set):
if optimization_level == 3:
optimization.append(_minimum_point_check)
elif optimization_level == 2:
optimization.append(
[
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,
),
]
)
if (
pass_manager_config.basis_gates is not None
and len(pass_manager_config.basis_gates) > 0
):
optimization.append(
[
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,
),
]
)
else:
optimization.append(
[
Collect2qBlocks(),
ConsolidateBlocks(
basis_gates=pass_manager_config.basis_gates,
target=pass_manager_config.target,
approximation_degree=pass_manager_config.approximation_degree,
),
]
)
optimization.append(_depth_check + _size_check)
else:
optimization.append(_depth_check + _size_check)
Expand Down
196 changes: 124 additions & 72 deletions qiskit/transpiler/preset_passmanagers/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ class _InvalidControlFlowForBackend:
# Explicitly stateful closure to allow pickling.

def __init__(self, basis_gates=(), target=None):
if target is not None:
if target is not None and len(target.operation_names) > 0:
self.unsupported = [op for op in CONTROL_FLOW_OP_NAMES if op not in target]
elif basis_gates is not None:
elif basis_gates is not None and len(basis_gates) > 0:
basis_gates = set(basis_gates)
self.unsupported = [op for op in CONTROL_FLOW_OP_NAMES if op not in basis_gates]
else:
Expand Down Expand Up @@ -237,7 +237,12 @@ def generate_unroll_3q(
)
# If there are no target instructions revert to using unroll3qormore so
# routing works.
if basis_gates is None and target is None:
if (
basis_gates is None
and target is None
or target is not None
and len(target.operation_names) == 0
):
unroll_3q.append(Unroll3qOrMore(target, basis_gates))
else:
unroll_3q.append(BasisTranslator(sel, basis_gates, target=target, min_qubits=3))
Expand Down Expand Up @@ -454,77 +459,124 @@ def generate_translation_passmanager(
Raises:
TranspilerError: If the ``method`` kwarg is not a valid value
"""
if basis_gates is None and target is None:
return PassManager([])

if method == "translator":
unroll = [
# Use unitary synthesis for basis aware decomposition of
# UnitaryGates before custom unrolling
UnitarySynthesis(
basis_gates,
approximation_degree=approximation_degree,
coupling_map=coupling_map,
backend_props=backend_props,
plugin_config=unitary_synthesis_plugin_config,
method=unitary_synthesis_method,
target=target,
),
HighLevelSynthesis(
hls_config=hls_config,
coupling_map=coupling_map,
target=target,
use_qubit_indices=True,
equivalence_library=sel,
basis_gates=basis_gates,
qubits_initially_zero=qubits_initially_zero,
),
BasisTranslator(sel, basis_gates, target),
]
if target is not None and len(target.operation_names) == 0:
unroll = [
HighLevelSynthesis(
hls_config=hls_config,
coupling_map=coupling_map,
target=target,
use_qubit_indices=True,
equivalence_library=sel,
basis_gates=basis_gates,
qubits_initially_zero=qubits_initially_zero,
),
]
else:
unroll = [
# Use unitary synthesis for basis aware decomposition of
# UnitaryGates before custom unrolling
UnitarySynthesis(
basis_gates,
approximation_degree=approximation_degree,
coupling_map=coupling_map,
backend_props=backend_props,
plugin_config=unitary_synthesis_plugin_config,
method=unitary_synthesis_method,
target=target,
),
HighLevelSynthesis(
hls_config=hls_config,
coupling_map=coupling_map,
target=target,
use_qubit_indices=True,
equivalence_library=sel,
basis_gates=basis_gates,
qubits_initially_zero=qubits_initially_zero,
),
BasisTranslator(sel, basis_gates, target),
]
elif method == "synthesis":
unroll = [
# # Use unitary synthesis for basis aware decomposition of
# UnitaryGates > 2q before collection
UnitarySynthesis(
basis_gates,
approximation_degree=approximation_degree,
coupling_map=coupling_map,
backend_props=backend_props,
plugin_config=unitary_synthesis_plugin_config,
method=unitary_synthesis_method,
min_qubits=3,
target=target,
),
HighLevelSynthesis(
hls_config=hls_config,
coupling_map=coupling_map,
target=target,
use_qubit_indices=True,
basis_gates=basis_gates,
min_qubits=3,
qubits_initially_zero=qubits_initially_zero,
),
Unroll3qOrMore(target=target, basis_gates=basis_gates),
Collect2qBlocks(),
Collect1qRuns(),
ConsolidateBlocks(
basis_gates=basis_gates, target=target, approximation_degree=approximation_degree
),
UnitarySynthesis(
basis_gates=basis_gates,
approximation_degree=approximation_degree,
coupling_map=coupling_map,
backend_props=backend_props,
plugin_config=unitary_synthesis_plugin_config,
method=unitary_synthesis_method,
target=target,
),
HighLevelSynthesis(
hls_config=hls_config,
coupling_map=coupling_map,
target=target,
use_qubit_indices=True,
basis_gates=basis_gates,
qubits_initially_zero=qubits_initially_zero,
),
]
if target is not None and len(target.operation_names) == 0:
unroll = [
HighLevelSynthesis(
hls_config=hls_config,
coupling_map=coupling_map,
target=target,
use_qubit_indices=True,
basis_gates=basis_gates,
min_qubits=3,
qubits_initially_zero=qubits_initially_zero,
),
Unroll3qOrMore(target=target, basis_gates=basis_gates),
Collect2qBlocks(),
Collect1qRuns(),
ConsolidateBlocks(
basis_gates=basis_gates,
target=target,
approximation_degree=approximation_degree,
),
HighLevelSynthesis(
hls_config=hls_config,
coupling_map=coupling_map,
target=target,
use_qubit_indices=True,
basis_gates=basis_gates,
qubits_initially_zero=qubits_initially_zero,
),
]
else:
unroll = [
# # Use unitary synthesis for basis aware decomposition of
# UnitaryGates > 2q before collection
UnitarySynthesis(
basis_gates,
approximation_degree=approximation_degree,
coupling_map=coupling_map,
backend_props=backend_props,
plugin_config=unitary_synthesis_plugin_config,
method=unitary_synthesis_method,
min_qubits=3,
target=target,
),
HighLevelSynthesis(
hls_config=hls_config,
coupling_map=coupling_map,
target=target,
use_qubit_indices=True,
basis_gates=basis_gates,
min_qubits=3,
qubits_initially_zero=qubits_initially_zero,
),
Unroll3qOrMore(target=target, basis_gates=basis_gates),
Collect2qBlocks(),
Collect1qRuns(),
ConsolidateBlocks(
basis_gates=basis_gates,
target=target,
approximation_degree=approximation_degree,
),
UnitarySynthesis(
basis_gates=basis_gates,
approximation_degree=approximation_degree,
coupling_map=coupling_map,
backend_props=backend_props,
plugin_config=unitary_synthesis_plugin_config,
method=unitary_synthesis_method,
target=target,
),
HighLevelSynthesis(
hls_config=hls_config,
coupling_map=coupling_map,
target=target,
use_qubit_indices=True,
basis_gates=basis_gates,
qubits_initially_zero=qubits_initially_zero,
),
]
else:
raise TranspilerError(f"Invalid translation method {method}.")
return PassManager(unroll)
Expand Down
Loading