Skip to content

UnitarySynthesis() interprets an empty basis as Clifford+T, causing unintended approximation and extreme circuit expansion #16688

Description

@weucode

Environment

  • Qiskit version: * 2.6.0.dev0 (built from main @ 4d7f9bbc11d34f7c4b82c4bd73675e8ddb7cdbcf, 2026-07-29).
  • Python version: 3.12.13
  • Operating system: Linux

What is happening?

UnitarySynthesis() incorrectly interprets an empty loose basis as a Clifford+T-only basis.

When the pass is constructed with neither basis_gates nor target, a 1-qubit UnitaryGate is unexpectedly routed through SolovayKitaevSynthesis, even though no Clifford+T target was requested and the pass's default approximation_degree is 1.0 ("no approximation").

As a result, a single 1-qubit unitary can be silently expanded into approximately 24,600 H/T/Tdg gates, and the resulting circuit is only approximate rather than equivalent to the input. By contrast, the existing ≥3-qubit path treats an empty loose basis as "cannot synthesize" and leaves the unitary untouched.

How can we reproduce the issue?

import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Operator
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import UnitarySynthesis

qc = QuantumCircuit(1)
unitary = np.array(
    [[1.0, 0.0], [0.0, np.exp(1j * np.pi / 6)]],
    dtype=complex,
)
qc.unitary(unitary, [0])

# No basis_gates and no target are supplied.
compiled = PassManager([UnitarySynthesis()]).run(qc)

op_in = Operator.from_circuit(qc)
op_out = Operator.from_circuit(compiled)

print(compiled.count_ops())
print("depth      =", compiled.depth())
print("max |diff| =", np.max(np.abs(op_in.data - op_out.data)))
print("allclose   =", np.allclose(op_in.data, op_out.data))

Output:

OrderedDict({'h': 10948, 't': 6839, 'tdg': 6838})
depth      = 24625
max |diff| = 9.263061707534654e-06
allclose   = False

What should happen?

An empty basis must not be interpreted as a Clifford+T-only basis.

When neither basis_gates nor target is supplied, the pass should do one of the following:

  1. Raise a TranspilerError for the missing target constraints, consistent with the documentation stating that target must be used when basis_gates is not specified;

  2. Leave the UnitaryGate unsynthesized, consistent with the existing ≥3-qubit path; or

  3. Use an explicitly defined exact fallback.

Happy to open a PR with the final fix and a regression test if useful.

Any suggestions?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions