Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,6 @@ fn name_to_packed_operation(name: &str, num_qubits: u32) -> Option<PackedOperati
_ => unreachable!(),
};
Some(inst.into())
} else if name == "unitary" {
unreachable!("Having a unitary result from an `EquivalenceLibrary is not possible")
} else {
None
}
Expand Down
12 changes: 10 additions & 2 deletions crates/transpiler/src/passes/basis_translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,11 @@ fn extract_basis(circuit: &DAGCircuit, min_qubits: usize) -> AhashIndexSet<GateI
basis: &mut AhashIndexSet<GateIdentifier>,
min_qubits: usize,
) {
for (_, operation) in circuit.op_nodes(true) {
// We should skip any instances of UnitaryGate as these should be handled by UnitarySynthesis
for (_, operation) in circuit
.op_nodes(true)
.filter(|(_, inst)| !matches!(inst.op.view(), OperationRef::Unitary(_)))
{
if circuit.get_qargs(operation.qubits).len() >= min_qubits {
basis.insert((operation.op.name().to_string(), operation.op.num_qubits()));
}
Expand Down Expand Up @@ -252,7 +256,11 @@ fn extract_basis_target(
qarg_mapping: Option<&HashMap<Qubit, Qubit>>,
) {
let qarg_mapping = |q: &Qubit| qarg_mapping.map(|map| map[q]).unwrap_or(*q);
for (_, node) in dag.op_nodes(true) {
// We should skip any instances of UnitaryGate as these should be handled by UnitarySynthesis
for (_, node) in dag
.op_nodes(true)
.filter(|(_, inst)| !matches!(inst.op.view(), OperationRef::Unitary(_)))
{
let qargs: &[Qubit] = dag.get_qargs(node.qubits);
if qargs.len() < min_qubits {
continue;
Expand Down
11 changes: 11 additions & 0 deletions releasenotes/notes/fix-basis-panic-7cf361c5ed5912f6.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fixes:
- |
Fixed error in :class:`.BasisTranslator` in which if a backend
defined a :class:`.UnitaryGate` as part of its :class:`.Target`'s
basis gate set, the transpiler pipeline would panic.

The pass now filters out :class:`.UnitaryGate`'s by instance
ensuring none will ever get processed as part of the basis set.

See `#15278 <https://github.com/Qiskit/qiskit/issues/15278>`__
and `#15733 <https://github.com/Qiskit/qiskit/issues/15733>`__.
24 changes: 24 additions & 0 deletions test/python/transpiler/test_basis_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1314,3 +1314,27 @@ def test_basis_nested_control_flow_op_aer(self):
pass

self.assertEqual(transpiled, expected)

@unittest.skipUnless(HAS_AER, "Aer backend required for simulation")
def test_basis_with_unitary_basis_aer(self):
"""Test that a circuit with a unitary gate in its target basis gets
skipped by the BasisTranslator"""
from qiskit_aer import AerSimulator

qr = QuantumRegister(3, "q")
cr = ClassicalRegister(3, "c")
qc = QuantumCircuit(qr, cr)

qc.cx(0, 1)
qc.h(0)
qc.cx(0, 1)
qc.sx(0)
qc.dcx(0, 2)

backend = AerSimulator()
pm = generate_preset_pass_manager(
optimization_level=2, backend=backend, seed_transpiler=134
)
transpiled = pm.run(qc)

self.assertEqual(Operator(qc), Operator(transpiled))