Skip to content
Closed
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
40 changes: 40 additions & 0 deletions qiskit/providers/backend_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
from qiskit.circuit.measure import Measure
from qiskit.providers.models.backendconfiguration import BackendConfiguration
from qiskit.providers.models.backendproperties import BackendProperties
<<<<<<< HEAD
=======
from qiskit.circuit.controlflow import CONTROL_FLOW_OP_NAMES
>>>>>>> 65ab96508 (Fix handling of control flow instructions in convert_to_target() (#11877))
from qiskit.providers.models.pulsedefaults import PulseDefaults
from qiskit.providers.options import Options
from qiskit.providers.exceptions import BackendPropertyError
Expand Down Expand Up @@ -58,12 +62,48 @@ def convert_to_target(
InstructionProperties,
)

<<<<<<< HEAD
# Standard gates library mapping, multicontrolled gates not included since they're
# variable width
name_mapping = get_standard_gate_name_mapping()
target = None
if custom_name_mapping is not None:
name_mapping.update(custom_name_mapping)
=======
required = ["measure", "delay"]

# Load Qiskit object representation
qiskit_inst_mapping = get_standard_gate_name_mapping()
if custom_name_mapping:
qiskit_inst_mapping.update(custom_name_mapping)

qiskit_control_flow_mapping = {
"if_else": IfElseOp,
"while_loop": WhileLoopOp,
"for_loop": ForLoopOp,
"switch_case": SwitchCaseOp,
}

in_data = {"num_qubits": configuration.n_qubits}

# Parse global configuration properties
if hasattr(configuration, "dt"):
in_data["dt"] = configuration.dt
if hasattr(configuration, "timing_constraints"):
in_data.update(configuration.timing_constraints)

# 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), supported_instructions.intersection(CONTROL_FLOW_OP_NAMES)
)

inst_name_map = {} # type: Dict[str, Instruction]

faulty_ops = set()
>>>>>>> 65ab96508 (Fix handling of control flow instructions in convert_to_target() (#11877))
faulty_qubits = set()
# Parse from properties if it exsits
if properties is not None:
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/Qiskit/qiskit/issues/11872>`__.
58 changes: 57 additions & 1 deletion test/python/providers/test_fake_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
FakeSherbrooke,
FakePrague,
)
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.utils import optionals
Expand Down Expand Up @@ -635,3 +635,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,)))