Skip to content

Commit

Permalink
Bug Fix for missing qubit property (#11880)
Browse files Browse the repository at this point in the history
(cherry picked from commit c566b3f)
  • Loading branch information
nkanazawa1989 authored and mergify[bot] committed Mar 1, 2024
1 parent 2463f16 commit 3c7ee1c
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 21 deletions.
23 changes: 15 additions & 8 deletions qiskit/providers/backend_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,22 @@ def _get_value(prop_dict, prop_name):
faulty_qubits = {
q for q in range(configuration.num_qubits) if not properties.is_qubit_operational(q)
}
qubit_properties = [
QubitProperties(
t1=properties.qubit_property(qubit_idx)["T1"][0],
t2=properties.qubit_property(qubit_idx)["T2"][0],
frequency=properties.qubit_property(qubit_idx)["frequency"][0],
)
for qubit_idx in range(0, configuration.num_qubits)
]

qubit_properties = []
for qi in range(0, configuration.num_qubits):
# TODO faulty qubit handling might be needed since
# faulty qubit reporting qubit properties doesn't make sense.
try:
prop_dict = properties.qubit_property(qubit=qi)
except KeyError:
continue
qubit_properties.append(
QubitProperties(
t1=prop_dict.get("T1", (None, None))[0],
t2=prop_dict.get("T2", (None, None))[0],
frequency=prop_dict.get("frequency", (None, None))[0],
)
)
in_data["qubit_properties"] = qubit_properties

for name in all_instructions:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
A bug that crashes the :func:`.convert_to_target` function when qubit properties
(either T1, T2 or frequency) are missing was fixed.
The missing property values in :class:`.QubitProperties` are filled with ``None``.
12 changes: 12 additions & 0 deletions test/python/providers/faulty_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ def properties(self):
return BackendProperties.from_dict(props)


class Fake7QV1MissingQ1Property(Fake7QPulseV1):
"""A fake 7 qubit backend, with a missing T1 property in q1."""

def properties(self):
"""Returns a snapshot of device properties as recorded on 8/30/19.
Remove property from qubit 1.
"""
props = super().properties().to_dict()
props["qubits"][1] = filter(lambda q: q["name"] != "T1", props["qubits"][1])
return BackendProperties.from_dict(props)


class Fake7QV1FaultyCX01CX10(Fake7QPulseV1):
"""A fake 5 qubit backend, with faulty CX(Q1, Q0) and CX(Q0, Q1)
0 (↔) 1 ↔ 3 ↔ 4
Expand Down
63 changes: 50 additions & 13 deletions test/python/providers/test_faulty_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from .faulty_backends import (
Fake7QV1FaultyCX01CX10,
Fake7QV1FaultyQ1,
Fake7QV1MissingQ1Property,
Fake7QV1FaultyCX13CX31,
)

Expand All @@ -35,7 +36,7 @@ def test_faulty_qubits(self):
"""Test faulty_qubits method."""
self.assertEqual(self.backend.properties().faulty_qubits(), [1])

def test_convert_to_target(self):
def test_convert_to_target_with_filter(self):
"""Test converting legacy data structure to V2 target model with faulty qubits.
Measure and Delay are automatically added to the output Target
Expand All @@ -44,31 +45,40 @@ def test_convert_to_target(self):
"""

# Filter out faulty Q1
target_with_filter = convert_to_target(
target = convert_to_target(
configuration=self.backend.configuration(),
properties=self.backend.properties(),
add_delay=True,
filter_faulty=True,
)
self.assertFalse(
target_with_filter.instruction_supported(operation_name="measure", qargs=(1,))
)
self.assertFalse(
target_with_filter.instruction_supported(operation_name="delay", qargs=(1,))
)
self.assertFalse(target.instruction_supported(operation_name="measure", qargs=(1,)))
self.assertFalse(target.instruction_supported(operation_name="delay", qargs=(1,)))

def test_convert_to_target_without_filter(self):
"""Test converting legacy data structure to V2 target model with faulty qubits."""

# Include faulty Q1 even though data could be incomplete
target_without_filter = convert_to_target(
target = convert_to_target(
configuration=self.backend.configuration(),
properties=self.backend.properties(),
add_delay=True,
filter_faulty=False,
)
self.assertTrue(
target_without_filter.instruction_supported(operation_name="measure", qargs=(1,))
self.assertTrue(target.instruction_supported(operation_name="measure", qargs=(1,)))
self.assertTrue(target.instruction_supported(operation_name="delay", qargs=(1,)))

# Properties are preserved
self.assertEqual(
target.qubit_properties[1].t1,
self.backend.properties().t1(1),
)
self.assertEqual(
target.qubit_properties[1].t2,
self.backend.properties().t2(1),
)
self.assertTrue(
target_without_filter.instruction_supported(operation_name="delay", qargs=(1,))
self.assertEqual(
target.qubit_properties[1].frequency,
self.backend.properties().frequency(1),
)


Expand Down Expand Up @@ -108,3 +118,30 @@ def test_faulty_gates(self):
self.assertEqual(len(gates), 2)
self.assertEqual([gate.gate for gate in gates], ["cx", "cx"])
self.assertEqual(sorted(gate.qubits for gate in gates), [[0, 1], [1, 0]])


class MissingPropertyQubitBackendTestCase(QiskitTestCase):
"""Test operational-related methods of backend.properties() with Fake7QV1MissingQ1Property,
which is like Fake7QV1 but with Q1 with missing T1 property."""

backend = Fake7QV1MissingQ1Property()

def test_convert_to_target(self):
"""Test converting legacy data structure to V2 target model with missing qubit property."""

target = convert_to_target(
configuration=self.backend.configuration(),
properties=self.backend.properties(),
add_delay=True,
filter_faulty=True,
)

self.assertIsNone(target.qubit_properties[1].t1)
self.assertEqual(
target.qubit_properties[1].t2,
self.backend.properties().t2(1),
)
self.assertEqual(
target.qubit_properties[1].frequency,
self.backend.properties().frequency(1),
)

0 comments on commit 3c7ee1c

Please sign in to comment.