diff --git a/qiskit/transpiler/passes/synthesis/hls_plugins.py b/qiskit/transpiler/passes/synthesis/hls_plugins.py index 3dce030c1982..ff483c9a5643 100644 --- a/qiskit/transpiler/passes/synthesis/hls_plugins.py +++ b/qiskit/transpiler/passes/synthesis/hls_plugins.py @@ -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``, @@ -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) @@ -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``, @@ -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) diff --git a/releasenotes/notes/fix-qft-plugins-7106029d33c44b96.yaml b/releasenotes/notes/fix-qft-plugins-7106029d33c44b96.yaml new file mode 100644 index 000000000000..3024432af714 --- /dev/null +++ b/releasenotes/notes/fix-qft-plugins-7106029d33c44b96.yaml @@ -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). + + diff --git a/test/python/transpiler/test_high_level_synthesis.py b/test/python/transpiler/test_high_level_synthesis.py index f3b11c98bfc7..a7dd806e63e9 100644 --- a/test/python/transpiler/test_high_level_synthesis.py +++ b/test/python/transpiler/test_high_level_synthesis.py @@ -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)) + @ddt class TestMCXSynthesisPlugins(QiskitTestCase):