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

Remove legacy NoiseModel interface #734

Merged
merged 4 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
48 changes: 2 additions & 46 deletions pulser-core/pulser/noise_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class NoiseModel:

Supported noise types:

- "leakage": Adds an error state 'x' to the computational
- **leakage**: Adds an error state 'x' to the computational
HGSilveri marked this conversation as resolved.
Show resolved Hide resolved
basis, that can interact with the other states via an
effective noise channel. Must be defined with an effective
noise channel, but is incompatible with dephasing and
Expand Down Expand Up @@ -132,10 +132,6 @@ class NoiseModel:
``p_false_pos`` and ``p_false_neg``.

Args:
noise_types: *Deprecated, simply define the approriate parameters
instead*. Noise types to include in the emulation. Defining
noise in this way will rely on legacy defaults for the relevant
parameters whenever a custom value is not provided.
runs: When reconstructing the Hamiltonian from random noise is
necessary, this determines how many times that happens. Not
to be confused with the number of times the resulting
Expand Down Expand Up @@ -188,7 +184,6 @@ class NoiseModel:

def __init__(
self,
noise_types: tuple[NoiseTypes, ...] | None = None,
runs: int | None = None,
samples_per_run: int | None = None,
state_prep_error: float | None = None,
Expand Down Expand Up @@ -229,30 +224,6 @@ def to_tuple(obj: tuple) -> tuple:
eff_noise_opers=to_tuple(eff_noise_opers),
with_leakage=with_leakage,
)
if noise_types is not None:
with warnings.catch_warnings():
warnings.simplefilter("always")
warnings.warn(
"The explicit definition of noise types is deprecated; "
"doing so will use legacy default values for all relevant "
"parameters that are not given a custom value. Instead, "
"defining only the necessary parameters is recommended; "
"doing so (when the noise types are not explicitly given) "
"will disregard all undefined parameters.",
DeprecationWarning,
stacklevel=2,
)
self._check_noise_types(noise_types)
for nt_ in noise_types:
if nt_ == "leakage":
raise ValueError(
"'leakage' cannot be explicitely defined in the noise"
" types. Set 'with_leakage' to True instead."
)
for p_ in _NOISE_TYPE_PARAMS[nt_]:
# Replace undefined relevant params by the legacy default
if param_vals[p_] is None:
param_vals[p_] = _LEGACY_DEFAULTS[p_]
true_noise_types: set[NoiseTypes] = {
_PARAM_TO_NOISE_TYPE[p_]
for p_ in param_vals
Expand All @@ -262,7 +233,7 @@ def to_tuple(obj: tuple) -> tuple:
self._check_eff_noise(
cast(tuple, param_vals["eff_noise_rates"]),
cast(tuple, param_vals["eff_noise_opers"]),
"eff_noise" in (noise_types or true_noise_types),
"eff_noise" in true_noise_types,
with_leakage=cast(bool, param_vals["with_leakage"]),
)

Expand All @@ -277,21 +248,6 @@ def to_tuple(obj: tuple) -> tuple:
cast(Union[float, None], param_vals["laser_waist"]),
)

if noise_types is not None:
if true_noise_types != set(noise_types):
raise ValueError(
"The explicit definition of noise types (deprecated) is"
" not compatible with the modification of unrelated noise "
"parameters. Defining only the relevant noise parameters "
"(without specifying the noise types) is recommended."
)
# Only now that we know the relevant_params can we determine if
# we need to use the legacy defaults for the run parameters (ie in
# case they were not provided by the user)
run_params_ = relevant_params & {"runs", "samples_per_run"}
for p_ in run_params_:
param_vals[p_] = param_vals[p_] or _LEGACY_DEFAULTS[p_]

relevant_param_vals = {
p: param_vals[p]
for p in param_vals
Expand Down
87 changes: 0 additions & 87 deletions tests/test_noise_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
# limitations under the License.
from __future__ import annotations

import dataclasses
import re

import numpy as np
import pytest

Expand Down Expand Up @@ -349,87 +346,3 @@ def test_repr(self):
"eff_noise_rates=(0.1,), eff_noise_opers=(((1, 0, 0), (0, 1, 0), "
"(0, 0, 1)),), with_leakage=True)"
)


class TestLegacyNoiseModel:
def test_noise_type_errors(self):
with pytest.raises(
ValueError, match="'bad_noise' is not a valid noise type."
):
with pytest.deprecated_call():
NoiseModel(noise_types=("bad_noise",))

with pytest.raises(
ValueError,
match="The effective noise parameters have not been filled.",
):
with pytest.deprecated_call():
NoiseModel(noise_types=("eff_noise",))

with pytest.raises(
ValueError,
match=re.escape(
"The explicit definition of noise types (deprecated) is"
" not compatible with the modification of unrelated noise "
"parameters"
),
):
with pytest.deprecated_call():
NoiseModel(noise_types=("SPAM",), laser_waist=100.0)

@pytest.mark.parametrize(
"noise_type", ["SPAM", "doppler", "amplitude", "dephasing"]
)
def test_legacy_init(self, noise_type):
expected_relevant_params = dict(
SPAM={
"state_prep_error",
"p_false_pos",
"p_false_neg",
"runs",
"samples_per_run",
},
amplitude={"laser_waist", "amp_sigma", "runs", "samples_per_run"},
doppler={"temperature", "runs", "samples_per_run"},
dephasing={"dephasing_rate", "hyperfine_dephasing_rate"},
)
non_zero_param = tuple(expected_relevant_params[noise_type])[0]

with pytest.warns(
DeprecationWarning,
match="The explicit definition of noise types is deprecated",
):
noise_model = NoiseModel(
**{"noise_types": (noise_type,), non_zero_param: 1}
)

# Check that the parameter is not overwritten by the default
assert getattr(noise_model, non_zero_param) == 1

with pytest.raises(
ValueError,
match="'leakage' cannot be explicitely defined in the noise",
):
with pytest.warns(
DeprecationWarning,
match="The explicit definition of noise types is deprecated",
):
NoiseModel(noise_types=("leakage",))

relevant_params = NoiseModel._find_relevant_params(
{noise_type},
# These values don't matter, they just have to be > 0
state_prep_error=0.1,
amp_sigma=0.5,
laser_waist=100.0,
)
assert relevant_params == expected_relevant_params[noise_type]

for f in dataclasses.fields(noise_model):
val = getattr(noise_model, f.name)
if f.name == "noise_types":
assert val == (noise_type,)
elif f.name in relevant_params:
assert val > 0.0
else:
assert not val
5 changes: 5 additions & 0 deletions tests/test_simconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ def test_init():
):
SimConfig(amp_sigma=-0.001)

with pytest.raises(
ValueError, match="'bad_noise' is not a valid noise type."
):
SimConfig(noise=("bad_noise",))


def test_eff_noise_opers(matrices):
# Some of these checks are repeated in the NoiseModel UTs
Expand Down