Source code for qiskit.providers.aer.noise.device.models

# This code is part of Qiskit.
#
# (C) Copyright IBM 2018, 2019.
#
# 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.

# pylint: disable=invalid-name
"""
Simplified noise models for devices backends.
"""

import logging

from numpy import inf, exp, allclose

import qiskit.quantum_info as qi
from .parameters import readout_error_values
from .parameters import gate_param_values
from .parameters import thermal_relaxation_values
from .parameters import _NANOSECOND_UNITS

from ..errors.readout_error import ReadoutError
from ..errors.standard_errors import depolarizing_error
from ..errors.standard_errors import thermal_relaxation_error

logger = logging.getLogger(__name__)


[docs]def basic_device_readout_errors(properties): """ Return readout error parameters from a devices BackendProperties. Args: properties (BackendProperties): device backend properties Returns: list: A list of pairs ``(qubits, ReadoutError)`` for qubits with non-zero readout error values. """ errors = [] for qubit, value in enumerate(readout_error_values(properties)): if value is not None and not allclose(value, [0, 0]): probabilities = [[1 - value[0], value[0]], [value[1], 1 - value[1]]] errors.append(([qubit], ReadoutError(probabilities))) return errors
[docs]def basic_device_gate_errors(properties, gate_error=True, thermal_relaxation=True, gate_lengths=None, gate_length_units='ns', temperature=0, standard_gates=True): """ Return QuantumErrors derived from a devices BackendProperties. 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. Args: properties (BackendProperties): device backend properties gate_error (bool): Include depolarizing gate errors (Default: True). thermal_relaxation (Bool): Include thermal relaxation errors (Default: True). 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. Can be 'ns', 'ms', 'us', or 's' (Default: 'ns'). temperature (double): qubit temperature in milli-Kelvin (mK) (Default: 0). standard_gates (bool): If true return errors as standard qobj gates. If false return as unitary qobj instructions (Default: True). Returns: list: A list of tuples ``(label, qubits, QuantumError)``, for gates with non-zero quantum error terms, where `label` is the label of the noisy gate, `qubits` is the list of qubits for the gate. """ # Initilize empty errors depol_error = None relax_error = None # Generate custom gate time dict custom_times = {} relax_params = [] if thermal_relaxation: # If including thermal relaxation errors load # T1, T2, and frequency values from properties relax_params = thermal_relaxation_values(properties) # If we are specifying custom gate times include # them in the custom times dict if gate_lengths: for name, qubits, value in gate_lengths: # Convert all gate lengths to nanosecond units time = value * _NANOSECOND_UNITS[gate_length_units] if name in custom_times: custom_times[name].append((qubits, time)) else: custom_times[name] = [(qubits, time)] # Get the device gate parameters from properties device_gate_params = gate_param_values(properties) # Construct quantum errors errors = [] for name, qubits, gate_length, error_param in device_gate_params: # Check for custom gate time relax_time = gate_length # Override with custom value if name in custom_times: filtered = [ val for q, val in custom_times[name] if q is None or q == qubits ] if filtered: # get first value relax_time = filtered[0] # Get relaxation error if thermal_relaxation: relax_error = _device_thermal_relaxation_error( qubits, relax_time, relax_params, temperature, thermal_relaxation) # Get depolarizing error channel if gate_error: depol_error = _device_depolarizing_error( qubits, error_param, relax_error, standard_gates) # Combine errors if depol_error is None and relax_error is None: # No error for this gate pass elif depol_error is not None and relax_error is None: # Append only the depolarizing error errors.append((name, qubits, depol_error)) # Append only the relaxation error elif relax_error is not None and depol_error is None: errors.append((name, qubits, relax_error)) else: # Append a combined error of depolarizing error # followed by a relaxation error combined_error = depol_error.compose(relax_error) errors.append((name, qubits, combined_error)) return errors
def _device_depolarizing_error(qubits, error_param, relax_error=None, standard_gates=True): """Construct a depolarizing_error for device""" # We now deduce the depolarizing channel error parameter in the # presence of T1/T2 thermal relaxation. We assume the gate error # parameter is given by e = 1 - F where F is the average gate fidelity, # and that this average gate fidelity is for the composition # of a T1/T2 thermal relaxation channel and a depolarizing channel. # For the n-qubit depolarizing channel E_dep = (1-p) * I + p * D, where # I is the identity channel and D is the completely depolarizing # channel. To compose the errors we solve for the equation # F = F(E_dep * E_relax) # = (1 - p) * F(I * E_relax) + p * F(D * E_relax) # = (1 - p) * F(E_relax) + p * F(D) # = F(E_relax) - p * (dim * F(E_relax) - 1) / dim # Hence we have that the depolarizing error probability # for the composed depolarization channel is # p = dim * (F(E_relax) - F) / (dim * F(E_relax) - 1) if relax_error is not None: relax_fid = qi.average_gate_fidelity(relax_error) relax_infid = 1 - relax_fid else: relax_fid = 1 relax_infid = 0 if error_param is not None and error_param > relax_infid: num_qubits = len(qubits) dim = 2 ** num_qubits error_max = dim / (dim + 1) # Check if reported error param is un-physical # The minimum average gate fidelity is F_min = 1 / (dim + 1) # So the maximum gate error is 1 - F_min = dim / (dim + 1) if error_param > error_max: logger.warning( 'Device reported a gate error parameter greater' ' than maximum allowed value (%f > %f). Truncating to' ' maximum value.', error_param, error_max) error_param = error_max # Model gate error entirely as depolarizing error num_qubits = len(qubits) dim = 2 ** num_qubits depol_param = dim * (error_param - relax_infid) / (dim * relax_fid - 1) max_param = 4**num_qubits / (4**num_qubits - 1) if depol_param > max_param: logger.warning( 'Device model returned a depolarizing error parameter greater' ' than maximum allowed value (%f > %f). Truncating to' ' maximum value.', depol_param, max_param) depol_param = min(depol_param, max_param) return depolarizing_error( depol_param, num_qubits, standard_gates=standard_gates) return None def _device_thermal_relaxation_error(qubits, gate_time, relax_params, temperature, thermal_relaxation=True): """Construct a thermal_relaxation_error for device""" # Check trivial case if not thermal_relaxation or gate_time is None or gate_time == 0: return None # Construct a tensor product of single qubit relaxation errors # for any multi qubit gates first = True error = None for qubit in qubits: t1, t2, freq = relax_params[qubit] population = _excited_population(freq, temperature) if first: error = thermal_relaxation_error(t1, t2, gate_time, population) first = False else: single = thermal_relaxation_error(t1, t2, gate_time, population) error = error.expand(single) return error def _excited_population(freq, temperature): """Return excited state population""" population = 0 if freq != inf and temperature != 0: # Compute the excited state population from qubit # frequency and temperature # Boltzman constant kB = 6.62607015e-34 (eV/K) # Planck constant h = 6.62607015e-34 (eV.s) # qubit temperature temperatue = T (mK) # qubit frequency frequency = f (GHz) # excited state population = 1/(1+exp((2hf*1e9)/(kbT*1e-3))) exp_param = exp((95.9849 * freq) / abs(temperature)) population = 1 / (1 + exp_param) if temperature < 0: # negative temperate implies |1> is thermal ground population = 1 - population return population