Skip to content

Commit 52af478

Browse files
Unitary synthesis bug fix (Qiskit#15286)
1 parent 56db921 commit 52af478

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

qiskit/transpiler/passes/synthesis/unitary_synthesis.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ def __init__(
143143
self._target = target if target is not None and len(target.operation_names) > 0 else None
144144
if target is not None:
145145
self._coupling_map = target.build_coupling_map()
146+
self._basis_gates = set(target.operation_names)
146147
if synth_gates:
147148
self._synth_gates = synth_gates
148149
else:
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
fixes:
3+
- |
4+
Fixed a bug in :class:`.UnitarySynthesis` transpiler pass, when it is called
5+
with a non-default synthesis plugin (specified via ``method``) that supports
6+
``basis_gates`` but not ``target``. The pass now correctly passes the basis
7+
gates from the ``target`` to the plugin.

test/python/transpiler/test_unitary_synthesis_plugin.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
from qiskit.circuit import QuantumCircuit
2525
from qiskit.converters import circuit_to_dag
26-
from qiskit.transpiler import PassManager
26+
from qiskit.transpiler import PassManager, Target, CouplingMap
2727
from qiskit.transpiler.passes import UnitarySynthesis
2828
from qiskit.transpiler.passes.synthesis.plugin import (
2929
UnitarySynthesisPlugin,
@@ -304,6 +304,40 @@ def test_config_not_passed_to_default_on_fallback(self):
304304
self.MOCK_PLUGINS["_controllable"].run.assert_not_called()
305305
self.assertNotIn("config", call_kwargs)
306306

307+
def test_target_overrides_basis_gates(self):
308+
"""Test that when both target and basis gates are specified, but the plugin only supports
309+
basis gates, the basis gates that it gets come from the target."""
310+
311+
self.MOCK_PLUGINS["_controllable"].support(["basis_gates"])
312+
313+
qc = QuantumCircuit(2)
314+
qc.unitary(np.eye(4, dtype=np.complex128), [0, 1])
315+
316+
target_basis_gates = ["rx", "rz"]
317+
standalone_basis_gates = ["cx", "u"]
318+
target = Target.from_configuration(
319+
num_qubits=2, basis_gates=target_basis_gates, coupling_map=CouplingMap.from_line(2)
320+
)
321+
pm = PassManager(
322+
[
323+
UnitarySynthesis(
324+
target=target, basis_gates=standalone_basis_gates, method="_controllable"
325+
)
326+
]
327+
)
328+
329+
with self.mock_default_run_method():
330+
pm.run(qc)
331+
self.DEFAULT_PLUGIN.run.assert_not_called() # pylint: disable=no-member
332+
self.MOCK_PLUGINS["_controllable"].run.assert_called() # pylint: disable=no-member
333+
call_kwargs = self.MOCK_PLUGINS["_controllable"].run.call_args[
334+
1
335+
] # pylint: disable=no-member
336+
337+
self.assertIn("basis_gates", call_kwargs)
338+
self.assertEqual(call_kwargs["basis_gates"], set(target_basis_gates))
339+
self.assertNotEqual(call_kwargs["basis_gates"], set(standalone_basis_gates))
340+
307341

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

0 commit comments

Comments
 (0)