diff --git a/qiskit/providers/backend_compat.py b/qiskit/providers/backend_compat.py index 3d54656545b4..fcd82765eeb6 100644 --- a/qiskit/providers/backend_compat.py +++ b/qiskit/providers/backend_compat.py @@ -21,7 +21,7 @@ from qiskit.providers.backend import QubitProperties from qiskit.providers.models.backendconfiguration import BackendConfiguration from qiskit.providers.models.backendproperties import BackendProperties - +from qiskit.circuit.controlflow import CONTROL_FLOW_OP_NAMES from qiskit.providers.models.pulsedefaults import PulseDefaults from qiskit.providers.options import Options from qiskit.providers.exceptions import BackendPropertyError @@ -92,8 +92,12 @@ def convert_to_target( # Create instruction property placeholder from backend configuration basis_gates = set(getattr(configuration, "basis_gates", [])) + supported_instructions = set(getattr(configuration, "supported_instructions", [])) gate_configs = {gate.name: gate for gate in configuration.gates} - all_instructions = set.union(basis_gates, set(required)) + all_instructions = set.union( + basis_gates, set(required), supported_instructions.intersection(CONTROL_FLOW_OP_NAMES) + ) + inst_name_map = {} # type: Dict[str, Instruction] faulty_ops = set() diff --git a/releasenotes/notes/fix-control-flow-convert-to-target-ae838418a7ad2a20.yaml b/releasenotes/notes/fix-control-flow-convert-to-target-ae838418a7ad2a20.yaml new file mode 100644 index 000000000000..be29520fad89 --- /dev/null +++ b/releasenotes/notes/fix-control-flow-convert-to-target-ae838418a7ad2a20.yaml @@ -0,0 +1,9 @@ +--- +fixes: + - | + Fixed an issue with the :func:`.convert_to_target` where the converter + would incorrectly ignore control flow instructions if they were specified + in the :attr:`.BackendConfiguration.supported_instructions` attribute which + is the typical location that control flow instructions are specified in a + :class:`.BackendConfiguration` object. + Fixed `#11872 `__. diff --git a/test/python/providers/test_fake_backends.py b/test/python/providers/test_fake_backends.py index f4f42e839f4d..101e35acc8e1 100644 --- a/test/python/providers/test_fake_backends.py +++ b/test/python/providers/test_fake_backends.py @@ -34,7 +34,7 @@ FakeOpenPulse2Q, GenericBackendV2, ) -from qiskit.providers.backend_compat import BackendV2Converter +from qiskit.providers.backend_compat import BackendV2Converter, convert_to_target from qiskit.providers.models.backendproperties import BackendProperties from qiskit.providers.backend import BackendV2 from qiskit.providers.models import GateConfig @@ -709,3 +709,59 @@ def test_faulty_full_path_transpile_connected_cmap(self, opt_level): tqc = transpile(qc, v2_backend, seed_transpiler=433, optimization_level=opt_level) connections = [tuple(sorted(tqc.find_bit(q).index for q in x.qubits)) for x in tqc.data] self.assertNotIn((0, 1), connections) + + def test_convert_to_target_control_flow(self): + backend = Fake27QPulseV1() + properties = backend.properties() + configuration = backend.configuration() + configuration.supported_instructions = [ + "cx", + "id", + "delay", + "measure", + "reset", + "rz", + "sx", + "x", + "if_else", + "for_loop", + "switch_case", + ] + defaults = backend.defaults() + target = convert_to_target(configuration, properties, defaults) + self.assertTrue(target.instruction_supported("if_else", ())) + self.assertFalse(target.instruction_supported("while_loop", ())) + self.assertTrue(target.instruction_supported("for_loop", ())) + self.assertTrue(target.instruction_supported("switch_case", ())) + + def test_convert_unrelated_supported_instructions(self): + backend = Fake27QPulseV1() + properties = backend.properties() + configuration = backend.configuration() + configuration.supported_instructions = [ + "cx", + "id", + "delay", + "measure", + "reset", + "rz", + "sx", + "x", + "play", + "u2", + "u3", + "u1", + "shiftf", + "acquire", + "setf", + "if_else", + "for_loop", + "switch_case", + ] + defaults = backend.defaults() + target = convert_to_target(configuration, properties, defaults) + self.assertTrue(target.instruction_supported("if_else", ())) + self.assertFalse(target.instruction_supported("while_loop", ())) + self.assertTrue(target.instruction_supported("for_loop", ())) + self.assertTrue(target.instruction_supported("switch_case", ())) + self.assertFalse(target.instruction_supported("u3", (0,)))