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

HLS fix to not synthesize instructions already supported #13417

Merged
merged 5 commits into from
Nov 14, 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
10 changes: 4 additions & 6 deletions qiskit/transpiler/passes/synthesis/high_level_synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,7 @@ def _definitely_skip_node(
dag._has_calibration_for(node)
or len(node.qargs) < self._min_qubits
or node.is_directive()
or (self._instruction_supported(node.name, qubits) and not node.is_control_flow())
):
return True

Expand All @@ -830,15 +831,12 @@ def _definitely_skip_node(
# If all the above constraints hold, and it's already supported or the basis translator
# can handle it, we'll leave it be.
and (
self._instruction_supported(node.name, qubits)
# This uses unfortunately private details of `EquivalenceLibrary`, but so does the
# `BasisTranslator`, and this is supposed to just be temporary til this is moved
# into Rust space.
or (
self._equiv_lib is not None
and equivalence.Key(name=node.name, num_qubits=node.num_qubits)
in self._equiv_lib.keys()
)
self._equiv_lib is not None
and equivalence.Key(name=node.name, num_qubits=node.num_qubits)
in self._equiv_lib.keys()
)
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
fixes:
- |
Previously the :class:`.HighLevelSynthesis` transpiler pass synthesized an
instruction for which a synthesis plugin is available, regardless of
whether the instruction is already supported by the target or a part of
the explicitly passed ``basis_gates``. This behavior is now fixed, so that
such already supported instructions are no longer synthesized.
13 changes: 13 additions & 0 deletions test/python/transpiler/test_high_level_synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
IGate,
MCXGate,
SGate,
QAOAAnsatz,
)
from qiskit.circuit.library import LinearFunction, PauliEvolutionGate
from qiskit.quantum_info import Clifford, Operator, Statevector, SparsePauliOp
Expand Down Expand Up @@ -664,6 +665,18 @@ def test_synth_fails_definition_exists(self):
out = hls(circuit)
self.assertEqual(out.count_ops(), {"u": 1})

def test_both_basis_gates_and_plugin_specified(self):
"""Test that a gate is not synthesized when it belongs to basis_gates,
regardless of whether there is a plugin method available.

See: https://github.com/Qiskit/qiskit/issues/13412 for more
details.
"""
qc = QAOAAnsatz(SparsePauliOp("Z"), initial_state=QuantumCircuit(1))
pm = PassManager([HighLevelSynthesis(basis_gates=["PauliEvolution"])])
qct = pm.run(qc)
self.assertEqual(qct.count_ops()["PauliEvolution"], 2)


class TestPMHSynthesisLinearFunctionPlugin(QiskitTestCase):
"""Tests for the PMHSynthesisLinearFunction plugin for synthesizing linear functions."""
Expand Down