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

Sequence sampler #345

Merged
merged 48 commits into from
Mar 28, 2022
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
e122aea
A first gist of sequence sampler
lvignoli Feb 24, 2022
94fbdb2
Refactor sampler in independent module
lvignoli Mar 14, 2022
f027757
Consistent support for noises, SLM and modulation of Global and Local
lvignoli Mar 14, 2022
5b5f95b
Refactor the noises module
lvignoli Mar 14, 2022
7459af5
Improve docstrings and small refactoring
lvignoli Mar 14, 2022
c0ff5d7
Small typos in comments
lvignoli Mar 15, 2022
79fcd26
Fix the decay of global channels to local ones
lvignoli Mar 16, 2022
d983031
Fix the modulation feature
lvignoli Mar 16, 2022
922ffd3
Refactor
lvignoli Mar 16, 2022
e7f1798
Simplify the flow of samples.samples()
lvignoli Mar 21, 2022
9269cdd
Improve test and get total coverage
lvignoli Mar 21, 2022
1220cbd
Simplify the sampling by removing the Samples dataclass
lvignoli Mar 22, 2022
949cfd0
Fix a docstring
lvignoli Mar 22, 2022
b2f0e3e
Fix docstrings formatting and content
lvignoli Mar 23, 2022
8d09f12
Remove unnecessary nonzero check in amplitude noise
lvignoli Mar 23, 2022
9f35042
Fix the noise seed default value: defaults to None
lvignoli Mar 23, 2022
03e8558
Improve docstrings of helper functions in noise module
lvignoli Mar 23, 2022
19af68d
Apply noises before the SLM masking
lvignoli Mar 23, 2022
14f9c8b
Rename misnamed variables
lvignoli Mar 23, 2022
41d175d
Change the scope of _key_func() and remove the _GroupType class
lvignoli Mar 23, 2022
4c8b160
Fix dictionary construction with defaultdict
lvignoli Mar 23, 2022
1af88d0
Fix misnamed keys in tests
lvignoli Mar 23, 2022
8084b6e
Add a match to pytest.raises
lvignoli Mar 23, 2022
ff38f10
Move the noises to the simulation module
lvignoli Mar 23, 2022
96db04c
Improve the simulation.noises docstring
lvignoli Mar 23, 2022
7129c95
Remove noisy helper functions
lvignoli Mar 23, 2022
578c78d
Write test case for _write_dict exception
lvignoli Mar 23, 2022
f1b2f23
Reorder tests
lvignoli Mar 23, 2022
802e86e
Add a more fundamental test
lvignoli Mar 23, 2022
4b36792
Reword and add docstrings
lvignoli Mar 23, 2022
d3f207b
Fix other misnamed keys in tests
lvignoli Mar 23, 2022
85cbdbf
Fix SLM masking: consider only the seq._mask_times
lvignoli Mar 25, 2022
a88c31d
Change for defaultdict in new_qdict
lvignoli Mar 25, 2022
97126fc
Add a note about performance for sampling of global channels
lvignoli Mar 25, 2022
0d752fd
Simply testing of sequence
lvignoli Mar 25, 2022
77d97e0
Refactor the testing of sequence with a helper function
lvignoli Mar 25, 2022
fe65aa4
Fix the testing of blackman modulation
lvignoli Mar 25, 2022
1f05e03
Move noise-related tests to an independent testing files
lvignoli Mar 25, 2022
2c8c07a
Fix the unneeded # pragma: no cover in _sample_slots
lvignoli Mar 25, 2022
9697a2d
Add a Failing test for the SLM, for discussion
lvignoli Mar 25, 2022
198c094
Move the comment on performance
lvignoli Mar 28, 2022
373e10f
Make the SLM detectino more idiomatic
lvignoli Mar 28, 2022
0720c50
Simplify the assertions for sequence in XY
lvignoli Mar 28, 2022
eeeba30
Remove superfluous print statements
lvignoli Mar 28, 2022
0201e14
Test SLM sampling alongside the check against simulation
lvignoli Mar 28, 2022
aefbc9e
Refactor using a helper for nested dicts
lvignoli Mar 28, 2022
35d4b75
Rearrange the test file
lvignoli Mar 28, 2022
12c9344
Merge branch 'develop' into WIP/sampling
HGSilveri Mar 28, 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
26 changes: 15 additions & 11 deletions pulser/sampler/sampler.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""Exposes the sample() functions.

It contains many helpers.

NOTE(perf): it not very efficient to hold the same data for all qubit in global
channels, but i remains manageable for register # with less than 100 qubits.
lvignoli marked this conversation as resolved.
Show resolved Hide resolved
"""
from __future__ import annotations

Expand Down Expand Up @@ -61,12 +64,10 @@ def sample(

ch_noises = list(common_noises)

slm_on = len(seq._slm_mask_targets) > 0 and len(seq._slm_mask_time) > 0
lvignoli marked this conversation as resolved.
Show resolved Hide resolved

if addr == "Global":
decay = (
len(seq._slm_mask_targets) > 0
or len(global_noises) > 0
or len(common_noises) > 0
)
decay = slm_on or len(global_noises) > 0 or len(common_noises) > 0
if decay:
addr = "Decayed"
ch_noises.extend(global_noises)
Expand All @@ -80,8 +81,12 @@ def sample(

s = noises.apply(s, ch_noises)

unmasked_qubits = seq._qids - seq._slm_mask_targets
s = [x for x in s if x.qubit in unmasked_qubits] # SLM
if slm_on: # Update the samples of masked qubits during SLM on times
for i, _ in enumerate(s):
if s[i].qubit in seq._slm_mask_targets:
ti, tf = seq._slm_mask_time[0], seq._slm_mask_time[1]
s[i].amp[ti:tf] = 0.0
# apply only on amp since it's just a shutter

samples[ch_name] = s

Expand All @@ -105,7 +110,7 @@ def new_qty_dict() -> dict:
}

def new_qdict() -> dict:
return {qubit: new_qty_dict() for qubit in seq._qids}
return defaultdict(new_qty_dict)

if seq._in_xy:
return {
Expand Down Expand Up @@ -180,9 +185,8 @@ def _sample_slots(N: int, *slots: _TimeSlot) -> list[QubitSamples]:
# weird, it's not enforced by the structure,bad design?)
qubits = slots[0].targets
amp, det, phase = np.zeros(N), np.zeros(N), np.zeros(N)
for s in slots:
if type(s.type) is str: # pragma: no cover
continue
pulse_slots = [s for s in slots if isinstance(s.type, Pulse)]
for s in pulse_slots:
pulse = cast(Pulse, s.type)
amp[s.ti : s.tf] += pulse.amplitude.samples
det[s.ti : s.tf] += pulse.detuning.samples
Expand Down
93 changes: 93 additions & 0 deletions pulser/tests/test_sampling_noises.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
from __future__ import annotations

import numpy as np
import pytest

import pulser
import pulser.simulation.noises as noises
from pulser.devices import MockDevice
from pulser.pulse import Pulse
from pulser.sampler import sample
from pulser.waveforms import ConstantWaveform


def test_amplitude_noise():
"""Test the noise related to the amplitude profile of global pulses."""
N = 100
amplitude = 1.0
waist_width = 2.0 # µm

coords = np.array([[-2.0, 0.0], [0.0, 0.0], [2.0, 0.0]])
reg = pulser.Register.from_coordinates(coords, prefix="q")
seq = pulser.Sequence(reg, MockDevice)
seq.declare_channel("ch0", "rydberg_global")
seq.add(
Pulse.ConstantAmplitude(amplitude, ConstantWaveform(N, 0.0), 0.0),
"ch0",
)
seq.measure()

def expected_samples(vec: np.ndarray) -> np.ndarray:
"""Defines the non-noisy effect of a gaussian amplitude profile."""
r = np.linalg.norm(vec)
a = np.ones(N)
a *= amplitude
a *= np.exp(-((r / waist_width) ** 2))
return a

s = sample(
seq, global_noises=[noises.amplitude(reg, waist_width, random=False)]
)

for q, coords in reg.qubits.items():
got = s["Local"]["ground-rydberg"][q]["amp"]
want = expected_samples(coords)
np.testing.assert_equal(got, want)


@pytest.mark.xfail(
reason="Test a different doppler effect than the one implemented; "
"no surprise it fails."
)
def test_doppler_noise():
"""What is exactly the doppler noise here?

A constant detuning shift per pulse seems weird. A global shift seems more
reasonable, but how can it be constant during the all sequence? It is not
clear to me here, I find the current implementation in the simulation
module to be unsatisfactory.

No surprise I make it fail on purpose right now 😅
"""
N = 100
det_value = np.pi

reg = pulser.Register.from_coordinates(np.array([[0.0, 0.0]]), prefix="q")
seq = pulser.Sequence(reg, MockDevice)
seq.declare_channel("ch0", "rydberg_global")
for _ in range(3):
seq.add(
Pulse.ConstantDetuning(ConstantWaveform(N, 1.0), det_value, 0.0),
"ch0",
)
seq.delay(100, "ch0")
seq.measure()

MASS = 1.45e-25 # kg
KB = 1.38e-23 # J/K
KEFF = 8.7 # µm^-1
doppler_sigma = KEFF * np.sqrt(KB * 50.0e-6 / MASS)
seed = 42
rng = np.random.default_rng(seed)

shifts = rng.normal(0, doppler_sigma, 3)
want = np.zeros(6 * N)
want[0:100] = det_value + shifts[0]
want[200:300] = det_value + shifts[1]
want[400:500] = det_value + shifts[2]

local_noises = [noises.doppler(reg, doppler_sigma, seed=seed)]
samples = sample(seq, common_noises=local_noises)
got = samples["Local"]["ground-rydberg"]["q0"]["det"]

np.testing.assert_array_equal(got, want)
Loading