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

Thermal noise model #4673

Merged
merged 23 commits into from
Jan 4, 2022
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
046b884
Remove files for subsequent PRs
95-martin-orion Dec 7, 2021
55069a9
Add coverage for OpId
95-martin-orion Dec 7, 2021
75dc3e8
Clarify if-case
95-martin-orion Dec 7, 2021
4f9fdc0
snake_case_gamma
95-martin-orion Dec 13, 2021
32011ca
Merge branch 'master' into cirq-noisegen-4a
CirqBot Dec 13, 2021
2baaaa7
Add insertion noise model.
95-martin-orion Nov 12, 2021
224ee36
Update to use new match methods
95-martin-orion Dec 13, 2021
3243b3c
Merge branch 'master' into cirq-noisegen-4b
95-martin-orion Dec 13, 2021
4d460c2
Apply review cleanup
95-martin-orion Dec 14, 2021
4a2caeb
Merge branch 'master' into cirq-noisegen-4b
CirqBot Dec 14, 2021
ee546c5
Introduce Thermal noise model.
95-martin-orion Nov 11, 2021
2e1cad8
Align with checks
95-martin-orion Nov 11, 2021
3593929
remove ThermalChannel ref
95-martin-orion Nov 12, 2021
5b6f251
Answer review comments
95-martin-orion Dec 15, 2021
f299581
Merge branch 'master' into cirq-noisegen-4c
95-martin-orion Dec 15, 2021
e8e6db6
Document mutli-type behavior.
95-martin-orion Dec 20, 2021
dc88cb1
qubit_dims -> qubits
95-martin-orion Dec 20, 2021
af4ce30
Extract methods, clean docstrings
95-martin-orion Dec 20, 2021
76c2df1
Cache kraus_ops_from_rates
95-martin-orion Dec 20, 2021
bcdbb4a
Document edge behaviors.
95-martin-orion Dec 20, 2021
bd49be5
Handle other qubits nicely
95-martin-orion Dec 20, 2021
d800119
Merge branch 'master' into cirq-noisegen-4c
CirqBot Jan 4, 2022
2ee401e
Merge branch 'master' into cirq-noisegen-4c
95-martin-orion Jan 4, 2022
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
5 changes: 4 additions & 1 deletion cirq-core/cirq/devices/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,17 @@
InsertionNoiseModel,
)

from cirq.devices.thermal_noise_model import (
ThermalNoiseModel,
)

from cirq.devices.noise_utils import (
OpIdentifier,
decay_constant_to_xeb_fidelity,
decay_constant_to_pauli_error,
pauli_error_to_decay_constant,
xeb_fidelity_to_decay_constant,
pauli_error_from_t1,
pauli_error_from_depolarization,
95-martin-orion marked this conversation as resolved.
Show resolved Hide resolved
average_error,
decoherence_pauli_error,
)
10 changes: 7 additions & 3 deletions cirq-core/cirq/devices/insertion_noise_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import dataclasses
from typing import TYPE_CHECKING, Dict, List, Optional, Sequence

from cirq import devices, ops
from cirq import devices
from cirq.devices import noise_utils

if TYPE_CHECKING:
Expand Down Expand Up @@ -63,6 +63,10 @@ def noisy_moment(
noise_ops.append(self.ops_added[match_id])
if not noise_ops:
return [moment]

from cirq import circuits

noise_steps = circuits.Circuit(noise_ops)
if self.prepend:
return [ops.Moment(noise_ops), moment]
return [moment, ops.Moment(noise_ops)]
return [*noise_steps.moments, moment]
return [moment, *noise_steps.moments]
95-martin-orion marked this conversation as resolved.
Show resolved Hide resolved
14 changes: 14 additions & 0 deletions cirq-core/cirq/devices/insertion_noise_model_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ def test_insertion_noise():
assert model.noisy_moment(moment_3, system_qubits=[q0, q1]) == [moment_3]


def test_colliding_noise_qubits():
# Check that noise affecting other qubits doesn't cause issues.
q0, q1, q2, q3 = cirq.LineQubit.range(4)
op_id0 = OpIdentifier(cirq.CZPowGate)
model = InsertionNoiseModel({op_id0: cirq.CNOT(q1, q2)}, require_physical_tag=False)

moment_0 = cirq.Moment(cirq.CZ(q0, q1), cirq.CZ(q2, q3))
assert model.noisy_moment(moment_0, system_qubits=[q0, q1, q2, q3]) == [
moment_0,
cirq.Moment(cirq.CNOT(q1, q2)),
cirq.Moment(cirq.CNOT(q1, q2)),
]


def test_prepend():
q0, q1 = cirq.LineQubit.range(2)
op_id0 = OpIdentifier(cirq.XPowGate, q0)
Expand Down
29 changes: 1 addition & 28 deletions cirq-core/cirq/devices/noise_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
# limitations under the License.

from typing import TYPE_CHECKING, Any, Dict, Tuple, Type, Union
import warnings
import numpy as np

from cirq import ops, protocols, value
Expand Down Expand Up @@ -47,9 +46,6 @@ def qubits(self) -> Tuple['cirq.Qid', ...]:
def _predicate(self, *args, **kwargs):
return self._gate_family._predicate(*args, **kwargs)

def swapped(self):
return OpIdentifier(self.gate_type, *self.qubits[::-1])

def is_proper_subtype_of(self, op_id: 'OpIdentifier'):
"""Returns true if this is contained within op_id, but not equal to it.

Expand Down Expand Up @@ -175,29 +171,6 @@ def pauli_error_from_t1(t_ns: float, t1_ns: float) -> float:
return (1 - np.exp(-t_ns / t2)) / 2 + (1 - np.exp(-t_ns / t1_ns)) / 4


def pauli_error_from_depolarization(t_ns: float, t1_ns: float, pauli_error: float = 0) -> float:
"""Calculates the amount of pauli error from depolarization.

This computes non-T1 error for a specific duration, `t`. If pauli error
from T1 decay is more than total pauli error, this returns zero; otherwise,
it returns the portion of pauli error not attributable to T1 error.

Args:
t_ns: The duration of the gate in ns.
t1_ns: The T1 decay constant in ns.
pauli_error: The total pauli error.

Returns:
Calculated Pauli error resulting from depolarization.
"""
t1_pauli_error = pauli_error_from_t1(t_ns, t1_ns)
if pauli_error >= t1_pauli_error:
return pauli_error - t1_pauli_error

warnings.warn("Pauli error from T1 decay is greater than total Pauli error", RuntimeWarning)
return 0


def average_error(decay_constant: float, num_qubits: int = 1) -> float:
"""Calculates the average error from the depolarization decay constant.

Expand All @@ -213,7 +186,7 @@ def average_error(decay_constant: float, num_qubits: int = 1) -> float:


def decoherence_pauli_error(t1_ns: float, tphi_ns: float, gate_time_ns: float) -> float:
"""The component of Pauli error caused by decoherence.
"""The component of Pauli error caused by decoherence on a single qubit.

Args:
t1_ns: T1 time in nanoseconds.
Expand Down
16 changes: 1 addition & 15 deletions cirq-core/cirq/devices/noise_utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
pauli_error_to_decay_constant,
xeb_fidelity_to_decay_constant,
pauli_error_from_t1,
pauli_error_from_depolarization,
average_error,
decoherence_pauli_error,
)
Expand Down Expand Up @@ -58,7 +57,7 @@ def test_op_id_str():
def test_op_id_swap():
q0, q1 = cirq.LineQubit.range(2)
base_id = OpIdentifier(cirq.CZPowGate, q0, q1)
swap_id = base_id.swapped()
swap_id = OpIdentifier(base_id.gate_type, *base_id.qubits[::-1])
assert cirq.CZ(q0, q1) in base_id
assert cirq.CZ(q0, q1) not in swap_id
assert cirq.CZ(q1, q0) not in base_id
Expand Down Expand Up @@ -125,19 +124,6 @@ def test_pauli_error_from_t1(t, t1_ns, expected_output):
assert val == expected_output


@pytest.mark.parametrize(
't,t1_ns,pauli_error,expected_output',
[
(20, 1e5, 0.01, 0.01 - ((1 - np.exp(-20 / 2e5)) / 2 + (1 - np.exp(-20 / 1e5)) / 4)),
# In this case, the formula produces a negative result.
(4000, 1e4, 0.01, 0),
],
)
def test_pauli_error_from_depolarization(t, t1_ns, pauli_error, expected_output):
val = pauli_error_from_depolarization(t, t1_ns, pauli_error)
assert val == expected_output


@pytest.mark.parametrize(
'decay_constant,num_qubits,expected_output',
[
Expand Down
Loading