emu-base 2.2.0__py3-none-any.whl → 2.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- emu_base/__init__.py +3 -1
- emu_base/noise.py +11 -0
- emu_base/pulser_adapter.py +21 -16
- emu_base/utils.py +38 -0
- {emu_base-2.2.0.dist-info → emu_base-2.3.0.dist-info}/METADATA +1 -1
- {emu_base-2.2.0.dist-info → emu_base-2.3.0.dist-info}/RECORD +7 -6
- {emu_base-2.2.0.dist-info → emu_base-2.3.0.dist-info}/WHEEL +0 -0
emu_base/__init__.py
CHANGED
|
@@ -5,6 +5,7 @@ from .math.krylov_exp import krylov_exp, DEFAULT_MAX_KRYLOV_DIM
|
|
|
5
5
|
from .jump_lindblad_operators import compute_noise_from_lindbladians
|
|
6
6
|
from .math.matmul import matmul_2x2_with_batched
|
|
7
7
|
from .aggregators import AggregationType, aggregate
|
|
8
|
+
from .utils import apply_measurement_errors
|
|
8
9
|
|
|
9
10
|
__all__ = [
|
|
10
11
|
"__version__",
|
|
@@ -18,6 +19,7 @@ __all__ = [
|
|
|
18
19
|
"HamiltonianType",
|
|
19
20
|
"DEFAULT_MAX_KRYLOV_DIM",
|
|
20
21
|
"DEVICE_COUNT",
|
|
22
|
+
"apply_measurement_errors",
|
|
21
23
|
]
|
|
22
24
|
|
|
23
|
-
__version__ = "2.
|
|
25
|
+
__version__ = "2.3.0"
|
emu_base/noise.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def pick_dark_qubits(eta: float, n: int) -> torch.Tensor:
|
|
5
|
+
"""
|
|
6
|
+
Randomly pick n booleans such that ℙ(True) = eta
|
|
7
|
+
|
|
8
|
+
Returns:
|
|
9
|
+
A BoolTensor of shape (n,) where each element is True with probability eta.
|
|
10
|
+
"""
|
|
11
|
+
return torch.rand(n) < eta
|
emu_base/pulser_adapter.py
CHANGED
|
@@ -294,6 +294,26 @@ def _get_all_lindblad_noise_operators(
|
|
|
294
294
|
]
|
|
295
295
|
|
|
296
296
|
|
|
297
|
+
def _get_target_times(
|
|
298
|
+
sequence: pulser.Sequence, config: EmulationConfig, dt: int
|
|
299
|
+
) -> list[int]:
|
|
300
|
+
sequence_duration = sequence.get_duration(include_fall_time=config.with_modulation)
|
|
301
|
+
# the end value is exclusive, so add +1
|
|
302
|
+
observable_times = set(range(0, sequence_duration + 1, dt))
|
|
303
|
+
observable_times.add(sequence_duration)
|
|
304
|
+
for obs in config.observables:
|
|
305
|
+
times: Sequence[float]
|
|
306
|
+
if obs.evaluation_times is not None:
|
|
307
|
+
times = obs.evaluation_times
|
|
308
|
+
elif config.default_evaluation_times != "Full":
|
|
309
|
+
times = config.default_evaluation_times.tolist() # type: ignore[union-attr,assignment]
|
|
310
|
+
observable_times |= set([round(time * sequence_duration) for time in times])
|
|
311
|
+
|
|
312
|
+
target_times: list[int] = list(observable_times)
|
|
313
|
+
target_times.sort()
|
|
314
|
+
return target_times
|
|
315
|
+
|
|
316
|
+
|
|
297
317
|
class PulserData:
|
|
298
318
|
slm_end_time: float
|
|
299
319
|
full_interaction_matrix: torch.Tensor
|
|
@@ -308,22 +328,7 @@ class PulserData:
|
|
|
308
328
|
def __init__(self, *, sequence: pulser.Sequence, config: EmulationConfig, dt: int):
|
|
309
329
|
self.qubit_ids = sequence.register.qubit_ids
|
|
310
330
|
self.qubit_count = len(self.qubit_ids)
|
|
311
|
-
|
|
312
|
-
# the end value is exclusive, so add +1
|
|
313
|
-
observable_times = set(torch.arange(0, sequence.get_duration() + 1, dt).tolist())
|
|
314
|
-
observable_times.add(sequence.get_duration())
|
|
315
|
-
for obs in config.observables:
|
|
316
|
-
times: Sequence[float]
|
|
317
|
-
if obs.evaluation_times is not None:
|
|
318
|
-
times = obs.evaluation_times
|
|
319
|
-
elif config.default_evaluation_times != "Full":
|
|
320
|
-
times = (
|
|
321
|
-
config.default_evaluation_times.tolist() # type: ignore[union-attr,assignment]
|
|
322
|
-
)
|
|
323
|
-
observable_times |= set([round(time * sequence_duration) for time in times])
|
|
324
|
-
|
|
325
|
-
self.target_times: list[int] = list(observable_times)
|
|
326
|
-
self.target_times.sort()
|
|
331
|
+
self.target_times = _get_target_times(sequence=sequence, config=config, dt=dt)
|
|
327
332
|
|
|
328
333
|
laser_waist = config.noise_model.laser_waist
|
|
329
334
|
amp_sigma = config.noise_model.amp_sigma
|
emu_base/utils.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from collections import Counter
|
|
2
|
+
import random
|
|
1
3
|
import torch
|
|
2
4
|
|
|
3
5
|
|
|
@@ -33,3 +35,39 @@ def deallocate_tensor(t: torch.Tensor) -> None:
|
|
|
33
35
|
if t._base is not None:
|
|
34
36
|
t._base.resize_(0)
|
|
35
37
|
t._base.set_(source=replacement_storage)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def readout_with_error(c: str, *, p_false_pos: float, p_false_neg: float) -> str:
|
|
41
|
+
# p_false_pos = false positive, p_false_neg = false negative
|
|
42
|
+
r = random.random()
|
|
43
|
+
if c == "0" and r < p_false_pos:
|
|
44
|
+
return "1"
|
|
45
|
+
|
|
46
|
+
if c == "1" and r < p_false_neg:
|
|
47
|
+
return "0"
|
|
48
|
+
|
|
49
|
+
return c
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def apply_measurement_errors(
|
|
53
|
+
bitstrings: Counter[str], *, p_false_pos: float, p_false_neg: float
|
|
54
|
+
) -> Counter[str]:
|
|
55
|
+
"""
|
|
56
|
+
Given a bag of sampled bitstrings, returns another bag of bitstrings
|
|
57
|
+
sampled with readout/measurement errors.
|
|
58
|
+
|
|
59
|
+
p_false_pos: probability of false positive
|
|
60
|
+
p_false_neg: probability of false negative
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
result: Counter[str] = Counter()
|
|
64
|
+
for bitstring, count in bitstrings.items():
|
|
65
|
+
for _ in range(count):
|
|
66
|
+
bitstring_with_error = "".join(
|
|
67
|
+
readout_with_error(c, p_false_pos=p_false_pos, p_false_neg=p_false_neg)
|
|
68
|
+
for c in bitstring
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
result[bitstring_with_error] += 1
|
|
72
|
+
|
|
73
|
+
return result
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
emu_base/__init__.py,sha256=
|
|
1
|
+
emu_base/__init__.py,sha256=wD_KJ7LfcWPbEbnskS46DOhToP4r6D_y2EyztecGMqg,757
|
|
2
2
|
emu_base/aggregators.py,sha256=bB-rldoDAErxQMpL715K5lpiabGOpkCY0GyxW7mfHuc,5000
|
|
3
3
|
emu_base/constants.py,sha256=41LYkKLUCz-oxPbd-j7nUDZuhIbUrnez6prT0uR0jcE,56
|
|
4
4
|
emu_base/jump_lindblad_operators.py,sha256=Y30f8emVFS4Dazljc_Rh4lX9qU4QQY_AxPNahnzcsfY,2101
|
|
5
|
-
emu_base/
|
|
6
|
-
emu_base/
|
|
5
|
+
emu_base/noise.py,sha256=h47DhEsFdAN783VnisJ50QJIiAPeRPKpU0SYtt8bAEQ,273
|
|
6
|
+
emu_base/pulser_adapter.py,sha256=NlZ1nNuNdU7D8S0XJqtjgu1b-qW2jFVzXOCAroH4Vuk,14660
|
|
7
|
+
emu_base/utils.py,sha256=17gca5uQfPaXiH3z4Leqd_rAJEZKQUqlSHj7OzFvCkU,2495
|
|
7
8
|
emu_base/math/__init__.py,sha256=6BbIytYV5uC-e5jLMtIErkcUl_PvfSNnhmVFY9Il8uQ,97
|
|
8
9
|
emu_base/math/brents_root_finding.py,sha256=AVx6L1Il6rpPJWrLJ7cn6oNmJyZOPRgEaaZaubC9lsU,3711
|
|
9
10
|
emu_base/math/double_krylov.py,sha256=X16dyCbyzdP7fFK-hmKS03Q-DJtC6TZ8sJrGTJ6akIc,3708
|
|
10
11
|
emu_base/math/krylov_energy_min.py,sha256=hm_B5qtBXHY1hl-r_LgDUKNDsdqVCDBHprQB3D-UFR8,4009
|
|
11
12
|
emu_base/math/krylov_exp.py,sha256=mGFddVQ8mEbwypbZtnlRPFpi4Nf8JZT6OKLHloIwCDQ,3934
|
|
12
13
|
emu_base/math/matmul.py,sha256=lEAnV0b5z_f1xEA-9p-WXxA8bM3QbShiHdXQ3ZkZFcQ,877
|
|
13
|
-
emu_base-2.
|
|
14
|
-
emu_base-2.
|
|
15
|
-
emu_base-2.
|
|
14
|
+
emu_base-2.3.0.dist-info/METADATA,sha256=AAanXBVpBx2__3ojtFYDqPjgLF-9WqNmKcXH4V3JiJA,3604
|
|
15
|
+
emu_base-2.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
16
|
+
emu_base-2.3.0.dist-info/RECORD,,
|
|
File without changes
|