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

Generalize effective noise channels #443

Merged
merged 50 commits into from
Jan 19, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
d668c75
depo noise added
Varda-star Dec 26, 2022
3bed4fe
Op matrix update.
Varda-star Dec 26, 2022
d65914e
depolarizing UT
Varda-star Dec 27, 2022
6ecf084
Why line 935 not verified.
Varda-star Dec 27, 2022
0cd0004
Trying to figure out why not 100% coverage for test_simulation
Varda-star Dec 29, 2022
44d70b8
Still not know why not 100% coverage.
Varda-star Dec 29, 2022
a47c0e1
Issue solved. Dephasing well added!
Varda-star Dec 29, 2022
b7434d5
uncorrelated noise approximation for dephasing channel
Varda-star Jan 5, 2023
8b903ae
reformating
Varda-star Jan 5, 2023
272cfc6
simconfig gen_noise
Varda-star Jan 5, 2023
a75211b
_check_gen_noise debugging.
Varda-star Jan 5, 2023
580001a
operator building in general noise setting 1.
Varda-star Jan 5, 2023
5761fd7
test_simconfig up to date.
Varda-star Jan 9, 2023
c57b0e5
simconfig 100% cov.
Varda-star Jan 9, 2023
9d5aba0
simulation 100% cov
Varda-star Jan 9, 2023
2273780
reformatting.
Varda-star Jan 9, 2023
f02db5b
Merge branch 'develop' into gen_eff_noise
Varda-star Jan 9, 2023
0e75f6b
Merge branch 'develop' into gen_eff_noise
Varda-star Jan 11, 2023
fc7b25a
Merge branch 'develop' into gen_eff_noise
Varda-star Jan 12, 2023
fd1f31c
Merge branch 'develop' into gen_eff_noise
Varda-star Jan 12, 2023
87fddbc
depolarizing model chosen
Varda-star Jan 12, 2023
5e53744
Merge branch 'gen_eff_noise' of https://github.com/Varda-star/Pulser …
Varda-star Jan 12, 2023
d41eb4c
gen-noise description updated.
Varda-star Jan 12, 2023
246dbb0
gen_noise description update.
Varda-star Jan 12, 2023
2935038
cov completed
Varda-star Jan 12, 2023
da58dc1
reformatting.
Varda-star Jan 12, 2023
8d6c251
Reformatting.
Varda-star Jan 13, 2023
54d5c6d
init issue solved
Varda-star Jan 13, 2023
51ce92b
np.isclose
Varda-star Jan 13, 2023
cb349cd
depolarizing noise description
Varda-star Jan 13, 2023
adbad66
warning updated.
Varda-star Jan 13, 2023
013ea6a
Update pulser-simulation/pulser_simulation/simulation.py
Varda-star Jan 13, 2023
9608ef9
Update pulser-simulation/pulser_simulation/simconfig.py
Varda-star Jan 13, 2023
009fcda
description updated
Varda-star Jan 13, 2023
a7bb15c
One effective noise channel allowed for one simulation
Varda-star Jan 16, 2023
10ec858
Collapse operator building relocated
Varda-star Jan 16, 2023
51c95e9
Merge branch 'develop' into gen_eff_noise
HGSilveri Jan 17, 2023
d1e2405
effecture noise type checking reformatted
Varda-star Jan 17, 2023
ca12a77
Update pulser-simulation/pulser_simulation/simconfig.py
Varda-star Jan 17, 2023
132a067
Update pulser-simulation/pulser_simulation/simconfig.py
Varda-star Jan 17, 2023
f58d4ec
Update pulser-simulation/pulser_simulation/simconfig.py
Varda-star Jan 17, 2023
6fa2ac0
Update pulser-simulation/pulser_simulation/simulation.py
Varda-star Jan 17, 2023
fa97d38
Merge branch 'develop' into gen_eff_noise
Varda-star Jan 18, 2023
07b74ee
test_eff_noise & test_depolarizing
Varda-star Jan 18, 2023
07cc94e
merge develop
Varda-star Jan 18, 2023
bab4dc8
coverage ok
Varda-star Jan 18, 2023
7a3fad0
separate UTs
Varda-star Jan 18, 2023
185fed7
UT naming
Varda-star Jan 18, 2023
66ad1b6
UT reviex 1
Varda-star Jan 18, 2023
7d075e0
variable naming
Varda-star Jan 19, 2023
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
91 changes: 90 additions & 1 deletion pulser-simulation/pulser_simulation/simconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
" `pip install typing-extensions`."
)

NOISE_TYPES = Literal["doppler", "amplitude", "SPAM", "dephasing"]
NOISE_TYPES = Literal[
"doppler", "amplitude", "SPAM", "dephasing", "depolarizing", "gen_noise"
]
MASS = 1.45e-25 # kg
KB = 1.38e-23 # J/K
KEFF = 8.7 # µm^-1
Expand All @@ -54,6 +56,11 @@ class SimConfig:
noise types:

- "dephasing": Random phase (Z) flip
- "depolarizing": model of decohering where the qubit undergoes a
bit-flip error, phase-flip error or both errors.
Varda-star marked this conversation as resolved.
Show resolved Hide resolved
- "gen_noise": general model of noise channels where the qubit
undergoes a modification according to the specified noise
operators, it encapsulates dephasing and depolarizing channels.
Varda-star marked this conversation as resolved.
Show resolved Hide resolved
- "doppler": Local atom detuning due to finite speed of the
atoms and Doppler effect with respect to laser frequency
- "amplitude": Gaussian damping due to finite laser waist
Expand Down Expand Up @@ -86,6 +93,13 @@ class SimConfig:
epsilon: float = 0.01
epsilon_prime: float = 0.05
dephasing_prob: float = 0.05
depolarizing_prob: float = 0.05
gen_noise_probs: list[float] = field(
init=True, default_factory=list, repr=False
)
HGSilveri marked this conversation as resolved.
Show resolved Hide resolved
gen_noise_opers: list[qutip.Qobj] = field(
init=True, default_factory=list, repr=False
Varda-star marked this conversation as resolved.
Show resolved Hide resolved
)
solver_options: Optional[qutip.Options] = None
spam_dict: dict[str, float] = field(
init=False, default_factory=dict, repr=False
Expand All @@ -101,6 +115,12 @@ def __post_init__(self) -> None:
f"{self.amp_sigma}) must be greater than or equal"
" to 0. and smaller than 1."
)
if len(self.gen_noise_opers) != len(self.gen_noise_probs):
raise ValueError(
f"The operators list length ({len(self.gen_noise_opers)}) "
f"and probabilities list length ({len(self.gen_noise_probs)})"
"are supposed to be equal."
Varda-star marked this conversation as resolved.
Show resolved Hide resolved
)
self._process_temperature()
self._change_attribute(
"spam_dict",
Expand All @@ -113,6 +133,7 @@ def __post_init__(self) -> None:
self._check_noise_types()
self._check_spam_dict()
self._calc_sigma_doppler()
self._check_gen_noise()

def __str__(self, solver_options: bool = False) -> str:
lines = [
Expand All @@ -125,13 +146,22 @@ def __str__(self, solver_options: bool = False) -> str:
lines.append("Noise types: " + ", ".join(self.noise))
if "SPAM" in self.noise:
lines.append(f"SPAM dictionary: {self.spam_dict}")
if "gen_noise" in self.noise:
lines.append(
f"General noise distribution: {self.gen_noise_probs}"
)
lines.append(
f"General noise operators: {self.gen_noise_opers}"
)
if "doppler" in self.noise:
lines.append(f"Temperature: {self.temperature*1.e6}µK")
lines.append(f"Amplitude standard dev.: {self.amp_sigma}")
if "amplitude" in self.noise:
lines.append(f"Laser waist: {self.laser_waist}μm")
if "dephasing" in self.noise:
lines.append(f"Dephasing probability: {self.dephasing_prob}")
if "depolarizing" in self.noise:
lines.append(f"Depolarizing probability: {self.depolarizing_prob}")
if solver_options:
lines.append(
"Solver Options: \n" + f"{str(self.solver_options)[10:-1]}"
Expand Down Expand Up @@ -176,3 +206,62 @@ def _calc_sigma_doppler(self) -> None:

def _change_attribute(self, attr_name: str, new_value: Any) -> None:
object.__setattr__(self, attr_name, new_value)

def _check_gen_noise(self) -> None:
# Check the validity of the distribution of probability
if "gen_noise" in self.noise:
if self.gen_noise_opers == [] or self.gen_noise_probs == []:
raise ValueError("Fill the general noise parameters.")
HGSilveri marked this conversation as resolved.
Show resolved Hide resolved

for prob in self.gen_noise_probs:
if not isinstance(prob, float):
raise TypeError(
"gen_noise_probs is a list of floats"
f" it must not contain a {type(prob)}."
)

prob_distr = np.array(self.gen_noise_probs)
lower_bound = np.any(prob_distr < 0.0)
upper_bound = np.any(prob_distr > 1.0)
sum_p = sum(prob_distr) != 1.0
Varda-star marked this conversation as resolved.
Show resolved Hide resolved
if sum_p or lower_bound or upper_bound:
raise ValueError(
"The distribution given is not a probability distribution."
)
# Check the validity of operators
for operator in self.gen_noise_opers:
# type checking

if type(operator) != qutip.qobj.Qobj:
raise TypeError(f"{operator} is not a Qobj.")
if operator.type != "oper":
raise TypeError(
"Operators are supposed to be of type oper."
)
if operator.shape != (2, 2):
raise NotImplementedError(
"Operator's shape must be (2,2) "
f"not {operator.shape}."
)
# Identity position
identity = qutip.qeye(2)
if self.gen_noise_opers[0] != identity:
raise NotImplementedError(
"You must put the identity matrix at the "
"beginning of the operator list."
)
# Completeness relation checking
sum_op = qutip.Qobj(shape=(2, 2))
length = len(self.gen_noise_probs)
for i in range(length):
sum_op += (
self.gen_noise_probs[i]
* self.gen_noise_opers[i]
* self.gen_noise_opers[i].dag()
)

if sum_op != identity:
raise ValueError(
"The completeness relation is not verified."
f" Ended up with {sum_op} instead of {identity}."
)
121 changes: 116 additions & 5 deletions pulser-simulation/pulser_simulation/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,14 @@
)

SUPPORTED_NOISE = {
"ising": {"dephasing", "doppler", "amplitude", "SPAM"},
"ising": {
"dephasing",
"doppler",
"amplitude",
"SPAM",
"depolarizing",
"gen_noise",
},
"XY": {"SPAM"},
}

Expand Down Expand Up @@ -202,7 +209,7 @@ def set_config(self, cfg: SimConfig) -> None:
)
# Probability of phase (Z) flip:
# First order in prob
prob = self.config.dephasing_prob / 2
prob = self.config.dephasing_prob
Varda-star marked this conversation as resolved.
Show resolved Hide resolved
n = self._size
if prob > 0.1 and n > 1:
warnings.warn(
Expand All @@ -225,6 +232,97 @@ def set_config(self, cfg: SimConfig) -> None:
for qid in self._qid_index
]

if "depolarizing" in self.config.noise:
if self.basis_name == "digital" or self.basis_name == "all":
# Go back to previous config
self.set_config(prev_config)
raise NotImplementedError(
"Cannot include depolarizing "
+ "noise in digital- or all-basis."
)

# Probability of error occurrence

prob = self.config.depolarizing_prob
n = self._size
if prob > 0.1 and n > 1:
warnings.warn(
"The depolarizing model is a first-order approximation"
f" in the depolarizing probability. p = {2*prob}"
" is too large for realistic results.",
stacklevel=2,
)
Varda-star marked this conversation as resolved.
Show resolved Hide resolved

k = np.sqrt((prob / 3) * (1 - prob) ** (n - 1))
self._collapse_ops = [
np.sqrt((1 - prob) ** n)
* qutip.tensor([self.op_matrix["I"] for _ in range(n)])
]
self._collapse_ops += [
k
* (
self.build_operator([("sigma_rr", [qid])])
- self.build_operator([("sigma_gg", [qid])])
)
for qid in self._qid_index
]
self._collapse_ops += [
k
* (
self.build_operator([("sigma_gr", [qid])]).dag()
+ self.build_operator([("sigma_gr", [qid])])
)
for qid in self._qid_index
]
self._collapse_ops += [
1j
* k
* (
self.build_operator([("sigma_gr", [qid])]).dag()
- self.build_operator([("sigma_gr", [qid])])
Varda-star marked this conversation as resolved.
Show resolved Hide resolved
)
for qid in self._qid_index
]
Varda-star marked this conversation as resolved.
Show resolved Hide resolved

if "gen_noise" in self.config.noise:
if self.basis_name == "digital" or self.basis_name == "all":
# Go back to previous config
self.set_config(prev_config)
raise NotImplementedError(
"Cannot include general "
+ "noise in digital- or all-basis."
)

# Probability distribution of error occurences
n = self._size
m = len(self.config.gen_noise_opers)
if n > 1:
for i in range(1, m):
prob_i = self.config.gen_noise_probs[i]
if prob_i > 0.1:
warnings.warn(
"The general noise model is a first-order"
" approximation in the noise probability."
f"p={2*prob_i} is large for realistic results.",
stacklevel=2,
)
break
# Building collapse operators
prob_id = self.config.gen_noise_probs[0]
self._collapse_ops += [
np.sqrt(prob_id**n)
* qutip.tensor([self.op_matrix["I"] for _ in range(n)])
]
for i in range(1, m):
k = np.sqrt(
self.config.gen_noise_probs[i] * prob_id ** (n - 1)
)
c_op = k * self.config.gen_noise_opers[i]
self._collapse_ops += [
self.build_operator([(c_op, [qid])])
for qid in self._qid_index
]
Varda-star marked this conversation as resolved.
Show resolved Hide resolved

def add_config(self, config: SimConfig) -> None:
"""Updates the current configuration with parameters of another one.

Expand Down Expand Up @@ -268,6 +366,11 @@ def add_config(self, config: SimConfig) -> None:
param_dict["laser_waist"] = config.laser_waist
if "dephasing" in diff_noise_set:
param_dict["dephasing_prob"] = config.dephasing_prob
if "depolarizing" in diff_noise_set:
param_dict["depolarizing_prob"] = config.depolarizing_prob
if "gen_noise" in diff_noise_set:
param_dict["gen_noise_opers"] = config.gen_noise_opers
param_dict["gen_noise_probs"] = config.gen_noise_probs
param_dict["temperature"] *= 1.0e6
# update runs:
param_dict["runs"] = config.runs
Expand Down Expand Up @@ -445,7 +548,9 @@ def draw(
def _extract_samples(self) -> None:
"""Populates samples dictionary with every pulse in the sequence."""
local_noises = True
if set(self.config.noise).issubset({"dephasing", "SPAM"}):
if set(self.config.noise).issubset(
{"dephasing", "SPAM", "depolarizing", "gen_noise"}
):
local_noises = "SPAM" in self.config.noise and self.config.eta > 0
samples = self.samples_obj.to_nested_dict(all_local=local_noises)

Expand Down Expand Up @@ -875,7 +980,11 @@ def _run_solver() -> CoherentResults:
else:
raise ValueError("`progress_bar` must be a bool.")

if "dephasing" in self.config.noise:
if (
"dephasing" in self.config.noise
or "depolarizing" in self.config.noise
or "gen_noise" in self.config.noise
):
result = qutip.mesolve(
self._hamiltonian,
self.initial_state,
Expand All @@ -902,7 +1011,9 @@ def _run_solver() -> CoherentResults:
)

# Check if noises ask for averaging over multiple runs:
if set(self.config.noise).issubset({"dephasing", "SPAM"}):
if set(self.config.noise).issubset(
{"dephasing", "SPAM", "depolarizing", "gen_noise"}
):
# If there is "SPAM", the preparation errors must be zero
if "SPAM" not in self.config.noise or self.config.eta == 0:
return _run_solver()
Expand Down
Loading