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

Fix qft-plugins for custom 'qft' gates #13181

Merged
merged 1 commit into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 16 additions & 6 deletions qiskit/transpiler/passes/synthesis/hls_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,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 @@ -532,10 +536,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 @@ -560,6 +565,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 @@ -584,10 +593,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 @@ -2309,6 +2309,22 @@ def test_qft_line_plugin_annotated_qft(self, qft_plugin_name):
qct = hls_pass(qc)
self.assertEqual(Operator(qc), Operator(qct))

@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))
Comment on lines +2324 to +2326
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test confused me at first, because I was expecting the test to be that HighLevelSynthesis had not turned it into a QFT equivalent, but the trick is that qc2 doesn't actually encode a QFT, so the test does the right thing.

I'm fine to merge like this, just commenting more because I got a bit confused and felt like broadcasting that fact.



@ddt
class TestMCXSynthesisPlugins(QiskitTestCase):
Expand Down
Loading