Skip to content

Commit

Permalink
Fix qft-plugins for custom 'qft' gates (#13181) (#13189)
Browse files Browse the repository at this point in the history
(cherry picked from commit 2245a4f)

Co-authored-by: Jake Lishman <[email protected]>
  • Loading branch information
mergify[bot] and jakelishman committed Sep 19, 2024
1 parent f9c262b commit 5d47963
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 6 deletions.
22 changes: 16 additions & 6 deletions qiskit/transpiler/passes/synthesis/high_level_synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,10 @@ class QFTSynthesisFull(HighLevelSynthesisPlugin):
This plugin name is :``qft.full`` which can be used as the key on
an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
Note that the plugin mechanism is not applied if the gate is called ``qft`` but
is not an instance of ``QFTGate``. This allows users to create custom gates with
name ``qft``.
The plugin supports the following additional options:
* reverse_qubits (bool): Whether to synthesize the "QFT" operation (if ``False``,
Expand Down Expand Up @@ -995,10 +999,11 @@ class QFTSynthesisFull(HighLevelSynthesisPlugin):

def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
"""Run synthesis for the given QFTGate."""

# Even though the gate is called "qft", it's not a QFTGate,
# and we should not synthesize it using the plugin.
if not isinstance(high_level_object, QFTGate):
raise TranspilerError(
"The synthesis plugin 'qft.full` only applies to objects of type QFTGate."
)
return None

reverse_qubits = options.get("reverse_qubits", False)
approximation_degree = options.get("approximation_degree", 0)
Expand All @@ -1023,6 +1028,10 @@ class QFTSynthesisLine(HighLevelSynthesisPlugin):
This plugin name is :``qft.line`` which can be used as the key on
an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
Note that the plugin mechanism is not applied if the gate is called ``qft`` but
is not an instance of ``QFTGate``. This allows users to create custom gates with
name ``qft``.
The plugin supports the following additional options:
* reverse_qubits (bool): Whether to synthesize the "QFT" operation (if ``False``,
Expand All @@ -1047,10 +1056,11 @@ class QFTSynthesisLine(HighLevelSynthesisPlugin):

def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
"""Run synthesis for the given QFTGate."""

# Even though the gate is called "qft", it's not a QFTGate,
# and we should not synthesize it using the plugin.
if not isinstance(high_level_object, QFTGate):
raise TranspilerError(
"The synthesis plugin 'qft.line` only applies to objects of type QFTGate."
)
return None

reverse_qubits = options.get("reverse_qubits", False)
approximation_degree = options.get("approximation_degree", 0)
Expand Down
9 changes: 9 additions & 0 deletions releasenotes/notes/fix-qft-plugins-7106029d33c44b96.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
fixes:
- |
The ``HighLevelSynthesis`` transpiler pass no longer raises an exception when
encountering a custom gate that is called "qft" but is not an instance of
:class:`~qiskit.circuit.library.QFTGate`. Instead, the synthesis plugins for
QFT gates ignore such a gate, and the gate's definition is used (if provided).
16 changes: 16 additions & 0 deletions test/python/transpiler/test_high_level_synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -2136,6 +2136,22 @@ def test_qft_line_plugin_annotated_qft(self, qft_plugin_name):
ops = set(qct.count_ops().keys())
self.assertEqual(ops, {"u", "cx"})

@data("line", "full")
def test_skip_non_qft(self, qft_plugin_name):
"""Test that synthesis plugins are not applied on gates that are called `qft`, yet
that are not of type `QFTGate`.
"""
qc = QuantumCircuit(1)
qc2 = QuantumCircuit(1, name="qft")
qc2.s(0)
qc.append(qc2.to_instruction(), qc.qregs[0])
hls_config = HLSConfig(qft=[qft_plugin_name])
hls_pass = HighLevelSynthesis(hls_config=hls_config)
qct = hls_pass(qc)
# HighLevelSynthesis should replace the custom gate called "qft"
# by the user-provided definition.
self.assertEqual(Operator(qc2), Operator(qct))


if __name__ == "__main__":
unittest.main()

0 comments on commit 5d47963

Please sign in to comment.