Skip to content

Commit

Permalink
Fix transpilation of control flow to no hardware (#11907)
Browse files Browse the repository at this point in the history
Previously we treated `basis_gates=None` the same as `basis_gates=()` in
the hardware check; that is, we treated it as meaning "nothing is
allowed", when the intention (and how it's treated elsewhere) is more
that "everything is allowed."

(cherry picked from commit d47a227)
  • Loading branch information
jakelishman authored and mergify[bot] committed Feb 28, 2024
1 parent 61a56ab commit d7cbfd4
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
7 changes: 5 additions & 2 deletions qiskit/transpiler/preset_passmanagers/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,12 @@ class _InvalidControlFlowForBackend:
def __init__(self, basis_gates=(), target=None):
if target is not None:
self.unsupported = [op for op in CONTROL_FLOW_OP_NAMES if op not in target]
else:
basis_gates = set(basis_gates) if basis_gates is not None else set()
elif basis_gates is not None:
basis_gates = set(basis_gates)
self.unsupported = [op for op in CONTROL_FLOW_OP_NAMES if op not in basis_gates]
else:
# Pass manager without basis gates or target; assume everything's valid.
self.unsupported = []

def message(self, property_set):
"""Create an error message for the given property set."""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
fixes:
- |
The preset pass managers of :func:`.transpile` will no longer fail on circuits
with control flow, if no hardware target or basis-gate set is specified. They
will now treat such abstract targets as permitting all control-flow operations.
Fixed `#11906 <https://github.com/Qiskit/qiskit/issues/11906>`__.
21 changes: 21 additions & 0 deletions test/python/compiler/test_transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -1646,6 +1646,27 @@ def test_target_ideal_gates(self, opt_level):

self.assertEqual(Operator.from_circuit(result), Operator.from_circuit(qc))

@data(0, 1, 2, 3)
def test_transpile_control_flow_no_backend(self, opt_level):
"""Test `transpile` with control flow and no specified hardware constraints."""
qc = QuantumCircuit(QuantumRegister(1, "q"), ClassicalRegister(1, "c"))
qc.h(0)
qc.measure(0, 0)
with qc.if_test((qc.clbits[0], False)):
qc.x(0)
with qc.while_loop((qc.clbits[0], True)):
qc.x(0)
with qc.for_loop(range(2)):
qc.x(0)
with qc.switch(qc.cregs[0]) as case:
with case(case.DEFAULT):
qc.x(0)
qc.measure(0, 0)

transpiled = transpile(qc, optimization_level=opt_level)
# There's nothing that can be optimized here.
self.assertEqual(qc, transpiled)

@data(0, 1, 2, 3)
def test_transpile_with_custom_control_flow_target(self, opt_level):
"""Test transpile() with a target and constrol flow ops."""
Expand Down

0 comments on commit d7cbfd4

Please sign in to comment.