Fix handling of 1q gates in UnitarySynthesis with target (#8847)

This commit fixes a bug in the UnitarySynthesis pass with 1q gates and a
Target set. Previously the pass unconditionally expected that it would
only ever encounter 2 or more qubits when it was running on a node if
the target was set. This would cause a failure if it ever encountered a
1q node in the dag. This commit fixes the handling so the pass will
synthesize 1 qubit unitaries it encounters too.

Fixes #8845

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
Matthew Treinish 2022-10-06 20:22:07 -04:00 committed by GitHub
parent 7bc3cb62bd
commit 3bb60b4c1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 16 deletions

View File

@ -529,27 +529,30 @@ class DefaultUnitarySynthesis(plugin.UnitarySynthesisPlugin):
qubits = options["coupling_map"][1]
target = options["target"]
euler_basis = _choose_euler_basis(basis_gates)
if euler_basis is not None:
decomposer1q = one_qubit_decompose.OneQubitEulerDecomposer(euler_basis)
else:
decomposer1q = None
preferred_direction = None
if target is not None:
decomposer2q, preferred_direction = self._find_decomposer_2q_from_target(
target, qubits, pulse_optimize
)
else:
decomposer2q = _basis_gates_to_decomposer_2q(basis_gates, pulse_optimize=pulse_optimize)
synth_dag = None
wires = None
if unitary.shape == (2, 2):
if target is not None:
euler_basis = _choose_euler_basis(target.operation_names_for_qargs(tuple(qubits)))
else:
euler_basis = _choose_euler_basis(basis_gates)
if euler_basis is not None:
decomposer1q = one_qubit_decompose.OneQubitEulerDecomposer(euler_basis)
else:
decomposer1q = None
if decomposer1q is None:
return None
synth_dag = circuit_to_dag(decomposer1q._decompose(unitary))
elif unitary.shape == (4, 4):
preferred_direction = None
if target is not None:
decomposer2q, preferred_direction = self._find_decomposer_2q_from_target(
target, qubits, pulse_optimize
)
else:
decomposer2q = _basis_gates_to_decomposer_2q(
basis_gates, pulse_optimize=pulse_optimize
)
if not decomposer2q:
return None
synth_dag, wires = self._synth_natural_direction(

View File

@ -0,0 +1,6 @@
---
fixes:
- |
Fixed an issue with the :class:`~.UnitarySynthesis` pass where a circuit
with 1 qubit gates and a :class:`~.Target` input would sometimes fail
instead of processing the circuit as expected.

View File

@ -24,7 +24,7 @@ from ddt import ddt, data
from qiskit import transpile
from qiskit.test import QiskitTestCase
from qiskit.providers.fake_provider import FakeVigo, FakeMumbaiFractionalCX
from qiskit.providers.fake_provider import FakeVigo, FakeMumbaiFractionalCX, FakeBelemV2
from qiskit.providers.fake_provider.fake_backend_v2 import FakeBackendV2, FakeBackend5QV2
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.circuit.library import QuantumVolume
@ -51,7 +51,7 @@ from qiskit.transpiler.passes import (
SabreSwap,
TrivialLayout,
)
from qiskit.circuit.library import CXGate, ECRGate, UGate
from qiskit.circuit.library import CXGate, ECRGate, UGate, ZGate
from qiskit.circuit import Parameter
@ -766,6 +766,26 @@ class TestUnitarySynthesis(QiskitTestCase):
self.assertEqual(cbody.count_ops().keys(), {"u", "cx"})
self.assertEqual(qc_uni1_mat, Operator(cbody))
def test_single_qubit_with_target(self):
"""Test input circuit with only 1q works with target."""
qc = QuantumCircuit(1)
qc.append(ZGate(), [qc.qubits[0]])
dag = circuit_to_dag(qc)
unitary_synth_pass = UnitarySynthesis(target=FakeBelemV2().target)
result_dag = unitary_synth_pass.run(dag)
result_qc = dag_to_circuit(result_dag)
self.assertEqual(qc, result_qc)
def test_single_qubit_identity_with_target(self):
"""Test input single qubit identity works with target."""
qc = QuantumCircuit(1)
qc.unitary([[1.0, 0.0], [0.0, 1.0]], 0)
dag = circuit_to_dag(qc)
unitary_synth_pass = UnitarySynthesis(target=FakeBelemV2().target)
result_dag = unitary_synth_pass.run(dag)
result_qc = dag_to_circuit(result_dag)
self.assertEqual(result_qc, QuantumCircuit(1))
if __name__ == "__main__":
unittest.main()