mirror of https://github.com/Qiskit/qiskit-aer.git
combine device noise models into single model
This commit is contained in:
parent
748a9d2cf8
commit
68edb62b96
|
@ -11,7 +11,7 @@ This module contains classes and functions to build a noise model for
|
||||||
simulating a Qiskit quantum circuit in the presence of errors.
|
simulating a Qiskit quantum circuit in the presence of errors.
|
||||||
|
|
||||||
Noise Models
|
Noise Models
|
||||||
----------------------
|
------------
|
||||||
Noise models for a noisy simulator are represented using the `NoiseModel`
|
Noise models for a noisy simulator are represented using the `NoiseModel`
|
||||||
class. This can be used to generate a custom noise model, or an automatic
|
class. This can be used to generate a custom noise model, or an automatic
|
||||||
noise model can be generated for a device using built in functions.
|
noise model can be generated for a device using built in functions.
|
||||||
|
@ -21,20 +21,14 @@ Automatically Generated Noise Models
|
||||||
Approximate noise models for a hardware device can be generated from the
|
Approximate noise models for a hardware device can be generated from the
|
||||||
device properties using the functions from the `device` submodule.
|
device properties using the functions from the `device` submodule.
|
||||||
|
|
||||||
* `device.depolarizing_noise_model`: Generates a noise model based on
|
Basic device noise model
|
||||||
one-qubit depolarizing errors acting after X90 pulses during u1, u2,
|
------------------------
|
||||||
and u3 gates, two-qubit depolarizing errors acting after cx gates,
|
Generates a noise mode based on 1 and 2 qubit gate errors consisting of
|
||||||
and readout errors acting after measurement. The error parameters
|
a depolarizing error followed by a thermal relaxation error, and readout
|
||||||
are tuned for each individual qubit based on 1 and 2-qubit error
|
errors on measurement outcomes. The error parameters are tuned for each
|
||||||
parameters from the device backend properties.
|
individual qubit based on the T_1, T_2, frequency and readout error
|
||||||
|
parameters for each qubit, and the gate error and gate time parameters
|
||||||
* `device.thermal_relaxation_noise_model`: Generates a noise mode
|
for each gate obtained from the device backend properties.
|
||||||
based on one-qubit thermal relaxation errors sacting after X90
|
|
||||||
pulses during u1, u2, and u3 gates, acting on both qubits after cx
|
|
||||||
gates, and readout errors acting after measurement. The error
|
|
||||||
parameters are tuned for each individual qubit based on the T_1,
|
|
||||||
T_2, and single qubit gate time parameters from the device backend
|
|
||||||
properties.
|
|
||||||
|
|
||||||
Custom Noise Models
|
Custom Noise Models
|
||||||
-------------------
|
-------------------
|
||||||
|
@ -42,26 +36,31 @@ Custom noise models may be constructed by adding errors to a NoiseModel
|
||||||
object. Errors are represented using by the `QuantumError` and
|
object. Errors are represented using by the `QuantumError` and
|
||||||
`ReadoutError` classes from the `noise.errors` module:
|
`ReadoutError` classes from the `noise.errors` module:
|
||||||
|
|
||||||
* `QuantumError`: Errors that affect the quantum state during a
|
Quantum errors
|
||||||
simulation. They may be applied after specific circuit gates or
|
--------------
|
||||||
reset operations, or before measure operations of qubits.
|
Errors that affect the quantum state during a simulation. They may be
|
||||||
|
applied after specific circuit gates or reset operations, or before
|
||||||
|
measure operations of qubits.
|
||||||
|
|
||||||
* `ReadoutError`: Errors that apply to classical bit registers
|
ReadoutError
|
||||||
after a measurement. They do not change the quantum state of the
|
------------
|
||||||
system, only the recorded classical measurement outcome.
|
Errors that apply to classical bit registers after a measurement. They
|
||||||
|
do not change the quantum state of the system, only the recorded
|
||||||
|
classical measurement outcome.
|
||||||
|
|
||||||
Helper functions exist for generating standard quantum error channels in
|
Helper functions exist for generating standard quantum error channels in
|
||||||
the `noise.errors` module. These functions are:
|
the `noise.errors` module. These allow simple generation of the follow
|
||||||
|
canonical types of quantum errors:
|
||||||
|
|
||||||
* `kraus_error`
|
Kraus error
|
||||||
* `mixed_unitary_error`
|
Mixed unitary error
|
||||||
* `coherent_unitary_error`
|
Coherent unitary error
|
||||||
* `pauli_error`
|
Pauli error
|
||||||
* `depolarizing_error`
|
Depolarizing error
|
||||||
* `thermal_relaxation_error`
|
Thermal relaxation error
|
||||||
* `phase_amplitude_damping_error`
|
Amplitude damping error
|
||||||
* `amplitude_damping_error`
|
Phase damping error
|
||||||
* `phase_damping_error`
|
Combined phase and amplitude damping error
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .noise_model import NoiseModel
|
from .noise_model import NoiseModel
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
"""Device noise models module Qiskit Aer."""
|
"""Device noise models module Qiskit Aer."""
|
||||||
|
|
||||||
from .models import depolarizing_noise_model
|
from .models import basic_device_noise_model
|
||||||
from .models import thermal_relaxation_noise_model
|
from .models import basic_device_readout_errors
|
||||||
|
from .models import basic_device_gate_errors
|
||||||
from . import parameters
|
from . import parameters
|
||||||
|
|
|
@ -12,39 +12,60 @@ Simplified noise models for devices backends.
|
||||||
from numpy import inf, exp
|
from numpy import inf, exp
|
||||||
|
|
||||||
from .parameters import readout_error_values
|
from .parameters import readout_error_values
|
||||||
from .parameters import gate_time_values
|
from .parameters import gate_param_values
|
||||||
from .parameters import gate_error_values
|
|
||||||
from .parameters import thermal_relaxation_values
|
from .parameters import thermal_relaxation_values
|
||||||
|
|
||||||
|
from ..noiseerror import NoiseError
|
||||||
from ..noise_model import NoiseModel
|
from ..noise_model import NoiseModel
|
||||||
from ..errors.readout_error import ReadoutError
|
from ..errors.readout_error import ReadoutError
|
||||||
from ..errors.standard_errors import depolarizing_error
|
from ..errors.standard_errors import depolarizing_error
|
||||||
from ..errors.standard_errors import thermal_relaxation_error
|
from ..errors.standard_errors import thermal_relaxation_error
|
||||||
|
|
||||||
|
|
||||||
def depolarizing_noise_model(properties,
|
def basic_device_noise_model(properties,
|
||||||
readout_error=True,
|
readout_error=True,
|
||||||
|
thermal_relaxation=True,
|
||||||
|
temperature=0,
|
||||||
|
gate_times=None,
|
||||||
standard_gates=True):
|
standard_gates=True):
|
||||||
"""Generae a depolarizing noise model from device backend properties.
|
"""Approximate device noise model derived from backend properties.
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
properties (BackendProperties): backend properties
|
properties (BackendProperties): backend properties
|
||||||
readout_error (Bool): Include readout errors in model
|
readout_errors (Bool): Include readout errors in model
|
||||||
(Default: True)
|
(Default: True).
|
||||||
|
thermal_relaxation (Bool): Include thermal relaxation errors
|
||||||
|
(Default: True).
|
||||||
|
temperature (double): qubit temperature in milli-Kelvin (mK) for
|
||||||
|
thermal relaxation errors (Default: 0).
|
||||||
|
gate_times (list): Custom gate times for thermal relaxation errors.
|
||||||
|
Used to extend or override the gate times in
|
||||||
|
the backend properties (Default: None).
|
||||||
standard_gates (bool): If true return errors as standard
|
standard_gates (bool): If true return errors as standard
|
||||||
qobj gates. If false return as unitary
|
qobj gates. If false return as unitary
|
||||||
qobj instructions (Default: True)
|
qobj instructions (Default: True)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
NoiseModel: An approximate noise model for the backend.
|
NoiseModel: An approximate noise model for the device backend.
|
||||||
|
|
||||||
Additional Information:
|
Additional Information:
|
||||||
|
|
||||||
The noise model will consist:
|
The noise model includes the following errors:
|
||||||
* Depolarizing errors on gates defined be defined in
|
|
||||||
`BackendProperties.gates`.
|
If readout_error is True:
|
||||||
* Single qubit readout errors on measurements if `readout_errors`
|
* Single qubit readout errors on measurements.
|
||||||
is set to True.
|
|
||||||
|
If thermal_relaxation is True:
|
||||||
|
* Single-qubit gate errors consisting of a depolarizing error
|
||||||
|
followed by a thermal relaxation error for the qubit the gate
|
||||||
|
acts on.
|
||||||
|
* Two-qubit gate errors consisting of a 2-qubit depolarizing
|
||||||
|
error followed by single qubit thermal relaxation errors for
|
||||||
|
all qubits participating in the gate.
|
||||||
|
|
||||||
|
Else if thermal_relaxation is False:
|
||||||
|
* Single-qubit depolarizing gate errors.
|
||||||
|
* Multi-qubit depolarizing gate errors.
|
||||||
|
|
||||||
For best practice in simulating a backend make sure that the
|
For best practice in simulating a backend make sure that the
|
||||||
circuit is compiled using the set of basis gates in the noise
|
circuit is compiled using the set of basis gates in the noise
|
||||||
|
@ -52,43 +73,6 @@ def depolarizing_noise_model(properties,
|
||||||
`basis_gates = noise_model.basis_gates`
|
`basis_gates = noise_model.basis_gates`
|
||||||
and using the device coupling map with:
|
and using the device coupling map with:
|
||||||
`coupling_map = backend.configuration().coupling_map`
|
`coupling_map = backend.configuration().coupling_map`
|
||||||
"""
|
|
||||||
noise_model = NoiseModel()
|
|
||||||
|
|
||||||
# Add single-qubit readout errors
|
|
||||||
if readout_error:
|
|
||||||
for qubits, error in device_readout_errors(properties):
|
|
||||||
noise_model.add_readout_error(error, qubits)
|
|
||||||
|
|
||||||
# Add depolarizing gate errors
|
|
||||||
gate_errors = device_depolarizing_errors(properties,
|
|
||||||
standard_gates=standard_gates)
|
|
||||||
for name, qubits, error in gate_errors:
|
|
||||||
noise_model.add_quantum_error(error, name, qubits)
|
|
||||||
|
|
||||||
return noise_model
|
|
||||||
|
|
||||||
|
|
||||||
def thermal_relaxation_noise_model(properties,
|
|
||||||
readout_error=True,
|
|
||||||
temperature=0,
|
|
||||||
gate_times=None):
|
|
||||||
"""Thermal relaxation noise model derived from backend properties.
|
|
||||||
|
|
||||||
Params:
|
|
||||||
properties (BackendProperties): backend properties
|
|
||||||
readout_errors (Bool): Include readout errors in model
|
|
||||||
(Default: True)
|
|
||||||
temperature (double): qubit temperature in milli-Kelvin (mK)
|
|
||||||
(Default: 0)
|
|
||||||
gate_times (list): Override device gate times with custom
|
|
||||||
values. If None use gate times from
|
|
||||||
backend properties. (Default: None)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
NoiseModel: An approximate noise model for the device backend.
|
|
||||||
|
|
||||||
Additional Information:
|
|
||||||
|
|
||||||
Secifying custom gate times:
|
Secifying custom gate times:
|
||||||
|
|
||||||
|
@ -103,62 +87,28 @@ def thermal_relaxation_noise_model(properties,
|
||||||
the backend properties, the `gate_times` value will override the
|
the backend properties, the `gate_times` value will override the
|
||||||
gate time value from the backend properties.
|
gate time value from the backend properties.
|
||||||
If non-default values are used gate_times should be a list
|
If non-default values are used gate_times should be a list
|
||||||
|
|
||||||
The noise model will consist:
|
|
||||||
|
|
||||||
* Single qubit readout errors on measurements.
|
|
||||||
* Single-qubit relaxation errors on all qubits participating in
|
|
||||||
a noisy quantum gate. The relaxation strength is determined by
|
|
||||||
the individual qubit T1 and T2 values and the gate_time of the
|
|
||||||
gate as defined in `BackendProperties.gates`.
|
|
||||||
|
|
||||||
For best practice in simulating a backend make sure that the
|
|
||||||
circuit is compiled using the set of basis gates in the noise
|
|
||||||
module by setting:
|
|
||||||
`basis_gates = noise_model.basis_gates`
|
|
||||||
and using the device coupling map with:
|
|
||||||
`coupling_map = backend.configuration().coupling_map`
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
noise_model = NoiseModel()
|
noise_model = NoiseModel()
|
||||||
|
|
||||||
# Add single-qubit readout errors
|
# Add single-qubit readout errors
|
||||||
if readout_error:
|
if readout_error:
|
||||||
for qubits, error in device_readout_errors(properties):
|
for qubits, error in basic_device_readout_errors(properties):
|
||||||
noise_model.add_readout_error(error, qubits)
|
noise_model.add_readout_error(error, qubits)
|
||||||
|
|
||||||
# Add depolarizing gate errors
|
# Add gate errors
|
||||||
gate_errors = device_thermal_relaxation_errors(properties,
|
gate_errors = basic_device_gate_errors(properties,
|
||||||
temperature=temperature,
|
thermal_relaxation=thermal_relaxation,
|
||||||
gate_times=gate_times)
|
gate_times=gate_times,
|
||||||
|
temperature=temperature,
|
||||||
|
standard_gates=standard_gates)
|
||||||
for name, qubits, error in gate_errors:
|
for name, qubits, error in gate_errors:
|
||||||
noise_model.add_quantum_error(error, name, qubits)
|
noise_model.add_quantum_error(error, name, qubits)
|
||||||
|
|
||||||
return noise_model
|
return noise_model
|
||||||
|
|
||||||
|
|
||||||
def device_depolarizing_errors(properties, standard_gates=True):
|
def basic_device_readout_errors(properties):
|
||||||
"""Get depolarizing noise quantum error objects for backend gates
|
|
||||||
|
|
||||||
Args:
|
|
||||||
properties (BackendProperties): device backend properties
|
|
||||||
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 (name, qubits, error).
|
|
||||||
"""
|
|
||||||
errors = []
|
|
||||||
for name, qubits, value in gate_error_values(properties):
|
|
||||||
if value is not None and value > 0:
|
|
||||||
error = depolarizing_error(value, len(qubits),
|
|
||||||
standard_gates=standard_gates)
|
|
||||||
errors.append((name, qubits, error))
|
|
||||||
return errors
|
|
||||||
|
|
||||||
|
|
||||||
def device_readout_errors(properties):
|
|
||||||
"""Get readout error objects for each qubit from backend properties
|
"""Get readout error objects for each qubit from backend properties
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -176,7 +126,9 @@ def device_readout_errors(properties):
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
|
|
||||||
def device_thermal_relaxation_errors(properties, temperature=0, gate_times=None):
|
def basic_device_gate_errors(properties, thermal_relaxation=True,
|
||||||
|
gate_times=None, temperature=0,
|
||||||
|
standard_gates=True):
|
||||||
"""Get depolarizing noise quantum error objects for backend gates
|
"""Get depolarizing noise quantum error objects for backend gates
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -193,55 +145,243 @@ def device_thermal_relaxation_errors(properties, temperature=0, gate_times=None)
|
||||||
|
|
||||||
Additional Information:
|
Additional Information:
|
||||||
If non-default values are used gate_times should be a list
|
If non-default values are used gate_times should be a list
|
||||||
of tuples (name, value) where name is the gate name string,
|
of tuples (name, qubits, value) where name is the gate name string,
|
||||||
and value is the gate time in nanoseconds.
|
qubits is 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.
|
||||||
"""
|
"""
|
||||||
# Generate custom gate time dict
|
# Generate custom gate time dict
|
||||||
custom_times = {}
|
custom_times = {}
|
||||||
if gate_times:
|
if thermal_relaxation:
|
||||||
custom_times = {name: value for name, value in gate_times}
|
# If including thermal relaxation errors load
|
||||||
else:
|
# T1, T2, and frequency values from properties
|
||||||
custom_times = {}
|
relax_params = thermal_relaxation_values(properties)
|
||||||
# Append device gate times to custom gate times
|
# If we are specifying custom gate times include
|
||||||
device_gate_times = gate_time_values(properties)
|
# them in the custom times dict
|
||||||
relax_values = thermal_relaxation_values(properties)
|
if gate_times:
|
||||||
errors = []
|
for name, qubits, value in gate_times:
|
||||||
for name, qubits, value in device_gate_times:
|
if name in custom_times:
|
||||||
if name in custom_times:
|
custom_times[name].append((qubits, value))
|
||||||
gate_time = custom_times[name]
|
|
||||||
else:
|
|
||||||
gate_time = value
|
|
||||||
if gate_time is not None and gate_time > 0:
|
|
||||||
# convert gate time to same units as T1 and T2 (microseconds)
|
|
||||||
gate_time = gate_time / 1000
|
|
||||||
# Construct a tensor product of single qubit relaxation errors
|
|
||||||
# for any multi qubit gates
|
|
||||||
first = True
|
|
||||||
error = None
|
|
||||||
for qubit in reversed(qubits):
|
|
||||||
t1, t2, freq = relax_values[qubit]
|
|
||||||
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
|
|
||||||
if first:
|
|
||||||
error = thermal_relaxation_error(t1, t2, gate_time,
|
|
||||||
population)
|
|
||||||
first = False
|
|
||||||
else:
|
else:
|
||||||
single = thermal_relaxation_error(t1, t2, gate_time,
|
custom_times[name] = [(qubits, value)]
|
||||||
population)
|
# Get the device gate parameters from properties
|
||||||
error = error.kron(single)
|
device_gate_params = gate_param_values(properties)
|
||||||
if error is not None:
|
|
||||||
errors.append((name, qubits, error))
|
# Construct quantum errors
|
||||||
|
errors = []
|
||||||
|
for name, qubits, gate_time, gate_error in device_gate_params:
|
||||||
|
# Check for custom gate time
|
||||||
|
relax_time = gate_time
|
||||||
|
# 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 depolarizing error channel
|
||||||
|
depol_error = _device_depolarizing_error(qubits, gate_error,
|
||||||
|
relax_time,
|
||||||
|
relax_params,
|
||||||
|
temperature,
|
||||||
|
thermal_relaxation,
|
||||||
|
standard_gates)
|
||||||
|
# Get relaxation error
|
||||||
|
relax_error = _device_thermal_relaxation_error(qubits, relax_time,
|
||||||
|
relax_params,
|
||||||
|
temperature,
|
||||||
|
thermal_relaxation)
|
||||||
|
# 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
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def _device_depolarizing_error(qubits, gate_error, gate_time, relax_params,
|
||||||
|
temperature, thermal_relaxation=True,
|
||||||
|
standard_gates=True):
|
||||||
|
"""Construct a depolarizing_error for device"""
|
||||||
|
error = None
|
||||||
|
if not thermal_relaxation:
|
||||||
|
# Model gate error entirely as depolarizing error
|
||||||
|
p_depol = _depol_error_value_one_qubit(gate_error)
|
||||||
|
else:
|
||||||
|
# Model gate error as thermal relaxation and depolarizing
|
||||||
|
# error.
|
||||||
|
# Get depolarizing probability
|
||||||
|
if len(qubits) == 1:
|
||||||
|
t1, t2, _ = relax_params[qubits[0]]
|
||||||
|
p_depol = _depol_error_value_one_qubit(gate_error,
|
||||||
|
gate_time,
|
||||||
|
t1=t1, t2=t2)
|
||||||
|
elif len(qubits) == 2:
|
||||||
|
q0_t1, q0_t2, _ = relax_params[qubits[0]]
|
||||||
|
q1_t1, q1_t2, _ = relax_params[qubits[1]]
|
||||||
|
p_depol = _depol_error_value_two_qubit(gate_error,
|
||||||
|
gate_time,
|
||||||
|
qubit0_t1=q0_t1,
|
||||||
|
qubit0_t2=q0_t2,
|
||||||
|
qubit1_t1=q1_t1,
|
||||||
|
qubit1_t2=q1_t2)
|
||||||
|
else:
|
||||||
|
raise NoiseError("Device noise model only supports" +
|
||||||
|
"1 and 2-qubit gates when using "
|
||||||
|
"thermal_relaxation=True.")
|
||||||
|
if p_depol > 0:
|
||||||
|
error = depolarizing_error(p_depol, len(qubits),
|
||||||
|
standard_gates=standard_gates)
|
||||||
|
return error
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
# convert gate time to same units as T1 and T2 (microseconds)
|
||||||
|
gate_time = gate_time / 1000
|
||||||
|
# Construct a tensor product of single qubit relaxation errors
|
||||||
|
# for any multi qubit gates
|
||||||
|
first = True
|
||||||
|
error = None
|
||||||
|
for qubit in reversed(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.kron(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
|
||||||
|
|
||||||
|
|
||||||
|
def _depol_error_value_one_qubit(gate_error, gate_time=0, t1=inf, t2=inf):
|
||||||
|
"""Return 2-qubit depolarizing channel probability for device model"""
|
||||||
|
# Check trivial case where there is no gate error
|
||||||
|
if gate_error is None:
|
||||||
|
return None
|
||||||
|
if gate_error == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Check t1 and t2 are valid
|
||||||
|
if t1 <= 0:
|
||||||
|
raise NoiseError("Invalid T_1 relaxation time parameter: T_1 <= 0.")
|
||||||
|
if t2 <= 0:
|
||||||
|
raise NoiseError("Invalid T_2 relaxation time parameter: T_2 <= 0.")
|
||||||
|
if t2 - 2 * t1 > 0:
|
||||||
|
raise NoiseError("Invalid T_2 relaxation time parameter: T_2 greater than 2 * T_1.")
|
||||||
|
|
||||||
|
# If T1 or T2 we have only a depolarizing error model
|
||||||
|
# in this case p_depol = dim * gate_error / (dim - 1)
|
||||||
|
# with dim = 2 for 1-qubit
|
||||||
|
if gate_time is None:
|
||||||
|
gate_time = 0
|
||||||
|
if gate_time == 0 or (t1 == inf and t2 == inf):
|
||||||
|
if gate_error is not None and gate_error > 0:
|
||||||
|
return 2 * gate_error
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Otherwise we calculate the depolarizing error probability to account
|
||||||
|
# for the difference between the relaxation error and gate error
|
||||||
|
if t1 == inf:
|
||||||
|
par1 = 1
|
||||||
|
else:
|
||||||
|
par1 = exp(-gate_time / t1)
|
||||||
|
if t2 == inf:
|
||||||
|
par2 = 1
|
||||||
|
else:
|
||||||
|
par2 = exp(-gate_time / t2)
|
||||||
|
p_depol = 1 + 3 * (2 * gate_error - 1) / (par1 + 2 * par2)
|
||||||
|
return p_depol
|
||||||
|
|
||||||
|
|
||||||
|
def _depol_error_value_two_qubit(gate_error, gate_time=0,
|
||||||
|
qubit0_t1=inf, qubit0_t2=inf,
|
||||||
|
qubit1_t1=inf, qubit1_t2=inf):
|
||||||
|
"""Return 2-qubit depolarizing channel probability for device model"""
|
||||||
|
# Check trivial case where there is no gate error
|
||||||
|
if gate_error is None:
|
||||||
|
return None
|
||||||
|
if gate_error == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Check t1 and t2 are valid
|
||||||
|
if qubit0_t1 <= 0 or qubit1_t1 <= 0:
|
||||||
|
raise NoiseError("Invalid T_1 relaxation time parameter: T_1 <= 0.")
|
||||||
|
if qubit0_t2 <= 0 or qubit1_t2 <= 0:
|
||||||
|
raise NoiseError("Invalid T_2 relaxation time parameter: T_2 <= 0.")
|
||||||
|
if qubit0_t2 - 2 * qubit0_t1 > 0 or qubit1_t2 - 2 * qubit1_t1 > 0:
|
||||||
|
raise NoiseError("Invalid T_2 relaxation time parameter: T_2 greater than 2 * T_1.")
|
||||||
|
|
||||||
|
# If T1 or T2 we have only a depolarizing error model
|
||||||
|
# in this case p_depol = dim * gate_error / (dim - 1)
|
||||||
|
# with dim = 4 for 2-qubits
|
||||||
|
if gate_time is None:
|
||||||
|
gate_time = 0
|
||||||
|
if gate_time == 0 or (qubit0_t1 == inf and qubit0_t2 == inf and
|
||||||
|
qubit1_t1 == inf and qubit1_t2 == inf):
|
||||||
|
if gate_error is not None and gate_error > 0:
|
||||||
|
return 4 * gate_error / 3
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Otherwise we calculate the depolarizing error probability to account
|
||||||
|
# for the difference between the relaxation error and gate error
|
||||||
|
if qubit0_t1 == inf:
|
||||||
|
q0_par1 = 1
|
||||||
|
else:
|
||||||
|
q0_par1 = exp(-gate_time / qubit0_t1)
|
||||||
|
if qubit0_t2 == inf:
|
||||||
|
q0_par2 = 1
|
||||||
|
else:
|
||||||
|
q0_par2 = exp(-gate_time / qubit0_t2)
|
||||||
|
if qubit1_t1 == inf:
|
||||||
|
q1_par1 = 1
|
||||||
|
else:
|
||||||
|
q1_par1 = exp(-gate_time / qubit1_t1)
|
||||||
|
if qubit1_t2 == inf:
|
||||||
|
q1_par2 = 1
|
||||||
|
else:
|
||||||
|
q1_par2 = exp(-gate_time / qubit1_t2)
|
||||||
|
denom = (q0_par1 + q1_par1 + q0_par1 * q1_par1 +
|
||||||
|
4 * q0_par2 * q1_par2 +
|
||||||
|
2 * (q0_par2 + q1_par2) +
|
||||||
|
2 * (q1_par1 * q0_par2 + q0_par1 * q1_par2))
|
||||||
|
p_depol = 1 + (5 / 3) * (4 * gate_error - 3) / denom
|
||||||
|
return p_depol
|
||||||
|
|
|
@ -17,6 +17,39 @@ _NANOSECOND_UNITS = {'s': 1e9, 'ms': 1e6, 'µs': 1e3, 'us': 1e3, 'ns': 1}
|
||||||
_GHZ_UNITS = {'Hz': 1e-9, 'KHz': 1e-6, 'MHz': 1e-3, 'GHz': 1, 'THz': 1e3}
|
_GHZ_UNITS = {'Hz': 1e-9, 'KHz': 1e-6, 'MHz': 1e-3, 'GHz': 1, 'THz': 1e3}
|
||||||
|
|
||||||
|
|
||||||
|
def gate_param_values(properties):
|
||||||
|
"""Get gate error values for backend gate from backend properties
|
||||||
|
|
||||||
|
Args:
|
||||||
|
properties (BackendProperties): device backend properties
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: A list of tuples (name, qubits, time, error). If gate
|
||||||
|
error or gate_time information is not available None will be
|
||||||
|
returned for value.
|
||||||
|
"""
|
||||||
|
values = []
|
||||||
|
for gate in properties.gates:
|
||||||
|
name = gate.gate
|
||||||
|
qubits = gate.qubits
|
||||||
|
# Check for gate time information
|
||||||
|
gate_time = None # default value
|
||||||
|
time_param = _check_for_item(gate.parameters, 'gate_time')
|
||||||
|
if hasattr(time_param, 'value'):
|
||||||
|
gate_time = time_param.value
|
||||||
|
if hasattr(time_param, 'unit'):
|
||||||
|
# Convert gate time to ns
|
||||||
|
gate_time *= _NANOSECOND_UNITS.get(time_param.unit, 1)
|
||||||
|
# Check for gate error information
|
||||||
|
gate_error = None # default value
|
||||||
|
error_param = _check_for_item(gate.parameters, 'gate_error')
|
||||||
|
if hasattr(error_param, 'value'):
|
||||||
|
gate_error = error_param.value
|
||||||
|
values.append((name, qubits, gate_time, gate_error))
|
||||||
|
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
def gate_error_values(properties):
|
def gate_error_values(properties):
|
||||||
"""Get gate error values for backend gate from backend properties
|
"""Get gate error values for backend gate from backend properties
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue