Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix device noise model from BackendV2 not to have excessive quantum errors on measures/resets #1649

Merged
merged 5 commits into from
Nov 30, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
42 changes: 32 additions & 10 deletions qiskit_aer/noise/device/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from numpy import inf, exp, allclose

import qiskit.quantum_info as qi
from qiskit.circuit import Gate, Measure
from .parameters import _NANOSECOND_UNITS
from .parameters import gate_param_values
from .parameters import readout_error_values
Expand Down Expand Up @@ -78,7 +79,7 @@ def basic_device_readout_errors(properties=None, target=None):
return errors


def basic_device_gate_errors(properties,
def basic_device_gate_errors(properties=None,
gate_error=True,
thermal_relaxation=True,
gate_lengths=None,
Expand All @@ -88,16 +89,21 @@ def basic_device_gate_errors(properties,
warnings=None,
target=None):
"""
Return QuantumErrors derived from a devices BackendProperties.
Return QuantumErrors derived from either of a devices BackendProperties or Target.
If non-default values are used gate_lengths should be a list
of tuples ``(name, qubits, value)`` where ``name`` is the gate
name string, ``qubits`` is either a list of qubits or ``None``
to apply gate time to this gate one any set of qubits,
and ``value`` is the gate time in nanoseconds.
The resulting errors may contains two types of errors: gate errors and relaxation errors.
The gate errors are generated only for ``Gate`` objects while the relaxation errors are
generated for all ``Instruction`` objects. Exceptionally, no ``QuantumError`` s are
generated for ``Measure`` since ``ReadoutError`` s are generated separately instead.
Args:
properties (BackendProperties): device backend properties
properties (BackendProperties): device backend properties.
gate_error (bool): Include depolarizing gate errors (Default: True).
thermal_relaxation (Bool): Include thermal relaxation errors
(Default: True).
Expand Down Expand Up @@ -126,6 +132,9 @@ def basic_device_gate_errors(properties,
Raises:
NoiseError: If invalid arguments are supplied.
"""
if properties is None and target is None:
raise NoiseError("Either properties or target must be supplied.")

if standard_gates is not None:
warn(
'"standard_gates" option has been deprecated as of qiskit-aer 0.10.0'
Expand Down Expand Up @@ -156,9 +165,6 @@ def basic_device_gate_errors(properties,
temperature=temperature
)

# Initilize empty errors
depol_error = None
relax_error = None
# Generate custom gate time dict
custom_times = {}
relax_params = []
Expand All @@ -182,6 +188,9 @@ def basic_device_gate_errors(properties,
# Construct quantum errors
errors = []
for name, qubits, gate_length, error_param in device_gate_params:
# Initilize empty errors
depol_error = None
relax_error = None
# Check for custom gate time
relax_time = gate_length
# Override with custom value
Expand Down Expand Up @@ -232,9 +241,16 @@ def _basic_device_target_gate_errors(target,
gate_error=True,
thermal_relaxation=True,
temperature=0):
"""Return QuantumErrors derived from a devices Target."""
"""Return QuantumErrors derived from a devices Target.
Note that, in the resulting error list, non-Gate instructions (e.g. Reset) will have
no gate errors while they may have thermal relaxation errors. Exceptionally,
Measure instruction will have no errors, neither gate errors nor relaxation errors.
"""
errors = []
for op_name, inst_prop_dic in target.items():
operation = target.operation_from_name(op_name)
if isinstance(operation, Measure):
continue
if inst_prop_dic is None: # ideal simulator
continue
for qubits, inst_prop in inst_prop_dic.items():
Expand All @@ -255,7 +271,7 @@ def _basic_device_target_gate_errors(target,
temperature=temperature,
)
# Get depolarizing error
if gate_error and inst_prop.error:
if gate_error and inst_prop.error and isinstance(operation, Gate):
depol_error = _device_depolarizing_error(
qubits=qubits,
error_param=inst_prop.error,
Expand Down Expand Up @@ -315,8 +331,14 @@ def _device_depolarizing_error(qubits,
max_param = 4**num_qubits / (4**num_qubits - 1)
if depol_param > max_param:
depol_param = min(depol_param, max_param)
return depolarizing_error(
depol_param, num_qubits, standard_gates=standard_gates)
with catch_warnings():
filterwarnings(
"ignore",
category=DeprecationWarning,
module="qiskit_aer.noise.device.models"
)
return depolarizing_error(
depol_param, num_qubits, standard_gates=standard_gates)
return None


Expand Down
11 changes: 11 additions & 0 deletions releasenotes/notes/fix-device-noise-models-2eca2f9c9dc25771.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
fixes:
- |
Fixes a bug where :meth:`NoiseModel.from_backend` with a ``BackendV2`` object may generate
a noise model with excessive ``QuantumError`` s on non-Gate instructions while,
for example, only ``ReadoutError`` s should be sufficient for measures.
This commit updates :meth:`NoiseModel.from_backend` with a ``BackendV2`` object so that
it returns the same noise model as that called with the corresponding ``BackendV1`` object.
That is, the resulting noise model does not contain any ``QuantumError`` s on measures and
it may contain only thermal relaxation errors on other non-gate instructions such as resets.
Note that it still contains ``ReadoutError`` s on measures.
46 changes: 46 additions & 0 deletions test/terra/noise/test_device_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2022.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""
Tests for utility functions to create device noise model.
"""

from test.terra.common import QiskitAerTestCase

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


class TestDeviceNoiseModel(QiskitAerTestCase):
"""Testing device noise model"""

def test_basic_device_gate_errors_from_target(self):
"""Test if the resulting gate errors never include errors on non-gate instructions"""
target = FakeNairobiV2().target
gate_errors = basic_device_gate_errors(target=target)
errors_on_measure = [name for name, _, _ in gate_errors if name == "measure"]
errors_on_reset = [name for name, _, _ in gate_errors if name == "reset"]
self.assertEqual(len(errors_on_measure), 0)
self.assertEqual(len(errors_on_reset), 7)
self.assertEqual(len(gate_errors), 40)

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())
errors_from_target = basic_device_gate_errors(target=FakeNairobiV2().target)
self.assertEqual(len(errors_from_properties), len(errors_from_target))
for err_properties, err_target in zip(errors_from_properties, errors_from_target):
name1, qargs1, err1 = err_properties
name2, qargs2, err2 = err_target
self.assertEqual(name1, name2)
self.assertEqual(tuple(qargs1), qargs2)
self.assertEqual(err1, err2)