Skip to content

Commit

Permalink
Bring in changes from the v0.18.1 hotfix
Browse files Browse the repository at this point in the history
- Merges the changes on the v0.18.1 hotfix
- Fixes a typo in the `check-release` CI job that slipped through
  • Loading branch information
HGSilveri authored Jun 7, 2024
2 parents 3350807 + 51ea35e commit 101ef6c
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.11"]
python-version: ["3.8", "3.12"]
steps:
- name: Check out Pulser
uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.8", "3.9", "3.10", "3.11"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
steps:
- name: Check out Pulser
uses: actions/checkout@v4
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
# Python 3.8 and 3.9 does not run on macos-latest (14)
# Uses macos-13 for 3.8 and 3.9 and macos-latest for >=3.10
os: [ubuntu-latest, macos-13, macos-latest, windows-latest]
python-version: ["3.8", "3.9", "3.10", "3.11"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
exclude:
- os: macos-latest
python-version: "3.8"
Expand All @@ -28,6 +28,8 @@ jobs:
python-version: "3.10"
- os: macos-13
python-version: "3.11"
- os: macos-13
python-version: "3.12"
steps:
- name: Check out Pulser
uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.19dev0
0.19dev1
4 changes: 3 additions & 1 deletion pulser-core/pulser/channels/eom.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,9 @@ def __post_init__(self) -> None:
"There must be at least one beam in 'controlled_beams'."
)
for beam in chain((self.limiting_beam,), self.controlled_beams):
if not (isinstance(beam, RydbergBeam) and beam in RydbergBeam):
if not (
isinstance(beam, RydbergBeam) and beam in tuple(RydbergBeam)
):
raise TypeError(
"Every beam must be one of options of the `RydbergBeam`"
f" enumeration, not {self.limiting_beam}."
Expand Down
22 changes: 22 additions & 0 deletions pulser-core/pulser/pulse.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

__all__ = ["Pulse"]

PHASE_PRECISION = 1e-6


@dataclass(init=False, repr=False, frozen=True)
class Pulse:
Expand Down Expand Up @@ -263,6 +265,26 @@ def __repr__(self) -> str:
+ f"post_phase_shift={self.post_phase_shift:.3g})"
)

def __eq__(self, other: Any) -> bool:
if type(other) is not type(self):
return False

def check_phase_eq(phase1: float, phase2: float) -> np.bool_:
# Comparing with an offset ensures we don't fail just because
# we are very close to the wraping point
return np.isclose(phase1, phase2, atol=1e-6) or np.isclose(
(phase1 + 1) % (2 * np.pi),
(phase2 + 1) % (2 * np.pi),
atol=PHASE_PRECISION,
)

return bool(
self.amplitude == other.amplitude
and self.detuning == other.detuning
and check_phase_eq(self.phase, other.phase)
and check_phase_eq(self.post_phase_shift, other.post_phase_shift)
)


# Replicate __init__'s signature in __new__
functools.update_wrapper(Pulse.__new__, Pulse.__init__)
26 changes: 17 additions & 9 deletions pulser-core/pulser/sequence/sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -1169,7 +1169,10 @@ def enable_eom_mode(

if not self.is_parametrized():
phase_drift_params = _PhaseDriftParams(
drift_rate=-detuning_off, ti=self.get_duration(channel)
drift_rate=-detuning_off,
# enable_eom() calls wait for fall, so the block only
# starts after fall time
ti=self.get_duration(channel, include_fall_time=True),
)
self._schedule.enable_eom(
channel, amp_on, detuning_on, detuning_off, switching_beams
Expand Down Expand Up @@ -2073,16 +2076,21 @@ def _add(
phase_drift_params=phase_drift_params,
)

true_finish = self._last(channel).tf + pulse.fall_time(
channel_obj, in_eom_mode=self.is_in_eom_mode(channel)
)
new_pulse_slot = self._last(channel)
for qubit in last.targets:
self._basis_ref[basis][qubit].update_last_used(true_finish)

if pulse.post_phase_shift:
self._phase_shift(
pulse.post_phase_shift, *last.targets, basis=basis
self._basis_ref[basis][qubit].update_last_used(new_pulse_slot.tf)

total_phase_shift = pulse.post_phase_shift
if phase_drift_params:
# The phase correction done to the EOM pulse's phase must
# also be done to the phase shift, as the phase reference is
# effectively changed by -drift
total_phase_shift = (
total_phase_shift
- phase_drift_params.calc_phase_drift(new_pulse_slot.ti)
)
if total_phase_shift:
self._phase_shift(total_phase_shift, *last.targets, basis=basis)
if (
self._in_ising
and self._slm_mask_dmm
Expand Down
10 changes: 10 additions & 0 deletions tests/test_pulse.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,13 @@ def test_full_duration(eom_channel):
assert pls.get_full_duration(
eom_channel, in_eom_mode=True
) == pls.duration + pls.fall_time(eom_channel, in_eom_mode=True)


def test_eq():
assert (pls_ := Pulse.ConstantPulse(100, 1, -1, 0)) == Pulse(
ConstantWaveform(100, 1),
ConstantWaveform(100, -1),
1e-6,
post_phase_shift=-1e-6,
)
assert pls_ != repr(pls_)
45 changes: 34 additions & 11 deletions tests/test_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -2140,10 +2140,16 @@ def test_multiple_index_targets(reg):
assert built_seq._last("ch0").targets == {"q2", "q3"}


@pytest.mark.parametrize("check_wait_for_fall", (True, False))
@pytest.mark.parametrize("correct_phase_drift", (True, False))
@pytest.mark.parametrize("custom_buffer_time", (None, 400))
def test_eom_mode(
reg, mod_device, custom_buffer_time, correct_phase_drift, patch_plt_show
reg,
mod_device,
custom_buffer_time,
correct_phase_drift,
check_wait_for_fall,
patch_plt_show,
):
# Setting custom_buffer_time
channels = mod_device.channels
Expand Down Expand Up @@ -2199,8 +2205,14 @@ def test_eom_mode(
first_pulse_slot = seq._schedule["ch0"].last_pulse_slot()
assert first_pulse_slot.ti == delay_slot.tf
assert first_pulse_slot.tf == first_pulse_slot.ti + pulse_duration
phase = detuning_off * first_pulse_slot.ti * 1e-3 * correct_phase_drift
eom_pulse = Pulse.ConstantPulse(pulse_duration, amp_on, detuning_on, phase)
phase_ref = (
detuning_off * first_pulse_slot.ti * 1e-3 * correct_phase_drift
) % (2 * np.pi)
# The phase correction becomes the new phase reference point
assert seq.current_phase_ref("q0", basis="ground-rydberg") == phase_ref
eom_pulse = Pulse.ConstantPulse(
pulse_duration, amp_on, detuning_on, phase_ref
)
assert first_pulse_slot.type == eom_pulse
assert not seq._schedule["ch0"].is_detuned_delay(eom_pulse)

Expand All @@ -2219,9 +2231,9 @@ def test_eom_mode(
)
assert second_pulse_slot.ti == first_pulse_slot.tf + phase_buffer
# Corrects the phase acquired during the phase buffer
phase_ += detuning_off * phase_buffer * 1e-3 * correct_phase_drift
phase_ref += detuning_off * phase_buffer * 1e-3 * correct_phase_drift
assert second_pulse_slot.type == Pulse.ConstantPulse(
pulse_duration, amp_on, detuning_on, phase_
pulse_duration, amp_on, detuning_on, phase_ + phase_ref
)

# Check phase jump buffer is not enforced with "no-delay"
Expand Down Expand Up @@ -2253,8 +2265,15 @@ def test_eom_mode(
)
assert buffer_delay.type == "delay"

assert seq.current_phase_ref("q0", basis="ground-rydberg") == 0
assert seq.current_phase_ref("q0", basis="ground-rydberg") == phase_ref
# Check buffer when EOM is not enabled at the start of the sequence
interval_time = 0
if check_wait_for_fall:
cte_pulse = Pulse.ConstantPulse(100, 1, 0, 0)
seq.add(cte_pulse, "ch0")
interval_time = cte_pulse.duration + cte_pulse.fall_time(
seq.declared_channels["ch0"]
)
seq.enable_eom_mode(
"ch0",
amp_on,
Expand All @@ -2266,7 +2285,7 @@ def test_eom_mode(
assert len(seq._schedule["ch0"].eom_blocks) == 2
new_eom_block = seq._schedule["ch0"].eom_blocks[1]
assert new_eom_block.detuning_off != 0
assert last_slot.ti == buffer_delay.tf # Nothing else was added
assert last_slot.ti == buffer_delay.tf + interval_time
duration = last_slot.tf - last_slot.ti
assert (
duration == custom_buffer_time
Expand All @@ -2277,21 +2296,25 @@ def test_eom_mode(
duration, 0.0, new_eom_block.detuning_off, last_pulse_slot.type.phase
)
# Check the phase shift that corrects for the drift
phase_ref = (
phase_ref += (
(new_eom_block.detuning_off * duration * 1e-3)
% (2 * np.pi)
* correct_phase_drift
)
assert seq.current_phase_ref("q0", basis="ground-rydberg") == phase_ref
assert np.isclose(
seq.current_phase_ref("q0", basis="ground-rydberg"),
phase_ref % (2 * np.pi),
)

# Add delay to test the phase drift correction in disable_eom_mode
last_delay_time = 400
seq.delay(last_delay_time, "ch0")

seq.disable_eom_mode("ch0", correct_phase_drift=True)
phase_ref += new_eom_block.detuning_off * last_delay_time * 1e-3
assert seq.current_phase_ref("q0", basis="ground-rydberg") == phase_ref % (
2 * np.pi
assert np.isclose(
seq.current_phase_ref("q0", basis="ground-rydberg"),
phase_ref % (2 * np.pi),
)

# Test drawing in eom mode
Expand Down

0 comments on commit 101ef6c

Please sign in to comment.