Skip to content

Commit

Permalink
Fix handling of None in noise model construction from BackendV2 (#1818)
Browse files Browse the repository at this point in the history
Fixes `NoiseModel.from_backend` not to fail when calling it with a V2 backend having
faulty qubits such that T1 and T2 are `None` in the `target.qubit_properties`. 

* fix handling of None in noise model construction from BackendV2
* add reno
* simplify a bit
* update docs
  • Loading branch information
itoko authored May 22, 2023
1 parent e3a968f commit eeec1af
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 15 deletions.
28 changes: 19 additions & 9 deletions qiskit_aer/noise/device/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,21 +106,26 @@ def basic_device_gate_errors(
Args:
properties (BackendProperties): device backend properties.
gate_error (bool): Include depolarizing gate errors (Default: True).
thermal_relaxation (Bool): Include thermal relaxation errors
(Default: True).
thermal_relaxation (Bool): Include thermal relaxation errors (Default: True).
If no ``t1`` and ``t2`` values are provided (i.e. None) in ``target`` for a qubit,
an identity ``QuantumError` (i.e. effectively no thermal relaxation error)
will be added to the qubit even if this flag is set to True.
If no ``frequency`` is not defined (i.e. None) in ``target`` for a qubit,
no excitation is considered in the thermal relaxation error on the qubit
even with non-zero ``temperature``.
gate_lengths (list): Override device gate times with custom
values. If None use gate times from
backend properties. (Default: None).
gate_length_units (str): Time units for gate length values in gate_lengths.
gate_length_units (str): Time units for gate length values in ``gate_lengths``.
Can be 'ns', 'ms', 'us', or 's' (Default: 'ns').
temperature (double): qubit temperature in milli-Kelvin (mK)
(Default: 0).
warnings (bool): DEPRECATED, Display warnings (Default: None).
target (Target): device backend target (Default: None). When this is supplied,
several options are disabled:
`properties`, `gate_lengths` and `gate_length_units` are not used
``properties``, ``gate_lengths`` and ``gate_length_units`` are not used
during the construction of gate errors.
Default values are always used for `warnings`.
Default values are always used for ``warnings``.
Returns:
list: A list of tuples ``(label, qubits, QuantumError)``, for gates
Expand Down Expand Up @@ -339,6 +344,10 @@ def _device_thermal_relaxation_error(
for qubit in qubits:
t1, t2, freq = relax_params[qubit]
t2 = _truncate_t2_value(t1, t2)
if t1 is None:
t1 = inf
if t2 is None:
t2 = inf
population = _excited_population(freq, temperature)
if first:
error = thermal_relaxation_error(t1, t2, gate_time, population)
Expand All @@ -351,14 +360,15 @@ def _device_thermal_relaxation_error(

def _truncate_t2_value(t1, t2):
"""Return t2 value truncated to 2 * t1 (for t2 > 2 * t1)"""
new_t2 = t2
if t2 > 2 * t1:
new_t2 = 2 * t1
return new_t2
if t1 is None or t2 is None:
return t2
return min(t2, 2 * t1)


def _excited_population(freq, temperature):
"""Return excited state population from freq [GHz] and temperature [mK]."""
if freq is None or temperature is None:
return 0
population = 0
if freq != inf and temperature != 0:
# Compute the excited state population from qubit frequency and temperature
Expand Down
16 changes: 10 additions & 6 deletions qiskit_aer/noise/noise_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,8 @@ def from_backend(
t1s = [prop.t1 for prop in all_qubit_properties]
t2s = [_truncate_t2_value(prop.t1, prop.t2) for prop in all_qubit_properties]
delay_pass = RelaxationNoisePass(
t1s=t1s,
t2s=t2s,
t1s=[np.inf if x is None else x for x in t1s], # replace None with np.inf
t2s=[np.inf if x is None else x for x in t2s], # replace None with np.inf
dt=dt,
op_types=Delay,
excited_state_populations=excited_state_populations,
Expand Down Expand Up @@ -474,10 +474,14 @@ def from_backend_properties(
Args:
backend_properties (BackendProperties): The property of backend.
gate_error (Bool): Include depolarizing gate errors (Default: True).
readout_error (Bool): Include readout errors in model
(Default: True).
thermal_relaxation (Bool): Include thermal relaxation errors
(Default: True).
readout_error (Bool): Include readout errors in model (Default: True).
thermal_relaxation (Bool): Include thermal relaxation errors (Default: True).
If no ``t1`` and ``t2`` values are provided (i.e. None) in ``target`` for a qubit,
an identity ``QuantumError` (i.e. effectively no thermal relaxation error)
will be added to the qubit even if this flag is set to True.
If no ``frequency`` is not defined (i.e. None) in ``target`` for a qubit,
no excitation is considered in the thermal relaxation error on the qubit
even with non-zero ``temperature``.
temperature (double): qubit temperature in milli-Kelvin (mK) for
thermal relaxation errors (Default: 0).
gate_lengths (Optional[list]): Custom gate times for thermal relaxation errors.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
fixes:
- |
Fixed a bug in :meth:`~.NoiseModel.from_backend` that raised an error when
the backend has no T1 and T2 values (i.e. None) for a qubit in its qubit properties.
This commit updates :meth:`NoiseModel.from_backend` and :func:`basic_device_gate_errors`
so that they add an identity ``QuantumError`` (i.e. effectively no thermal relaxation error)
to a qubit with no T1 and T2 values for all gates acting on qubits including the qubit.
Fixed `#1779 <https://github.com/Qiskit/qiskit-aer/issues/1779>`__
and `#1815 <https://github.com/Qiskit/qiskit-aer/issues/1815>`__.
19 changes: 19 additions & 0 deletions test/terra/noise/test_device_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from test.terra.common import QiskitAerTestCase

from qiskit.providers import QubitProperties
from qiskit.providers.fake_provider import FakeNairobi, FakeNairobiV2
from qiskit_aer.noise.device.models import basic_device_gate_errors

Expand All @@ -33,6 +34,24 @@ def test_basic_device_gate_errors_from_target(self):
self.assertEqual(len(errors_on_reset), 7)
self.assertEqual(len(gate_errors), 40)

def test_basic_device_gate_errors_from_target_with_non_operational_qubits(self):
"""Test if no thermal relaxation errors are generated for qubits with undefined T1 and T2."""
target = FakeNairobiV2().target
# tweak target to have non-operational qubits
faulty_qubits = (1, 2)
for q in faulty_qubits:
target.qubit_properties[q] = QubitProperties(t1=None, t2=None, frequency=0)
# build gate errors with only relaxation errors i.e. without depolarizing errors
gate_errors = basic_device_gate_errors(target=target, gate_error=False)
errors_on_sx = {qubits: error for name, qubits, error in gate_errors if name == "sx"}
errors_on_cx = {qubits: error for name, qubits, error in gate_errors if name == "cx"}
self.assertEqual(len(gate_errors), 40)
# check if no errors are added on sx gates on qubits without T1 and T2 definitions
for q in faulty_qubits:
self.assertTrue(errors_on_sx[(q,)].ideal())
# check if no error is added on cx gate on a qubit pair without T1 and T2 definitions
self.assertTrue(errors_on_cx[faulty_qubits].ideal())

def test_basic_device_gate_errors_from_target_and_properties(self):
"""Test if the device same gate errors are produced both from target and properties"""
errors_from_properties = basic_device_gate_errors(properties=FakeNairobi().properties())
Expand Down
20 changes: 20 additions & 0 deletions test/terra/noise/test_noise_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from qiskit.circuit.library.generalized_gates import PauliGate
from qiskit.circuit.library.standard_gates import IGate, XGate
from qiskit.compiler import transpile
from qiskit.providers import QubitProperties
from qiskit.providers.fake_provider import (
FakeBackend,
FakeAlmaden,
Expand Down Expand Up @@ -258,6 +259,25 @@ def test_noise_model_from_lagos_v2(self):
result = AerSimulator().run(circ, noise_model=noise_model).result()
self.assertTrue(result.success)

def test_noise_model_from_backend_v2_with_non_operational_qubits(self):
"""Test if possible to create a noise model from backend with non-operational qubits.
See issues #1779 and #1815 for the details."""
backend = FakeLagosV2()
# tweak target to have non-operational qubits
faulty_qubits = [0, 1]
for qubit in faulty_qubits:
backend.target.qubit_properties[qubit] = QubitProperties(t1=None, t2=None, frequency=0)

noise_model = NoiseModel.from_backend(backend)

circ = QuantumCircuit(2)
circ.h(0)
circ.cx(0, 1)
circ.measure_all()
circ = transpile(circ, backend, scheduling_method="alap")
result = AerSimulator().run(circ, noise_model=noise_model).result()
self.assertTrue(result.success)

def test_noise_model_from_invalid_t2_backend(self):
"""Test if silently truncate invalid T2 values when creating a noise model from backend"""
from qiskit.providers.models.backendproperties import BackendProperties, Gate, Nduv
Expand Down

0 comments on commit eeec1af

Please sign in to comment.