Skip to content

Commit

Permalink
Merge pull request #1115 from qiboteam/interpolated
Browse files Browse the repository at this point in the history
Fix duration interpolated sweeper for QM
  • Loading branch information
stavros11 authored Dec 16, 2024
2 parents 80bd287 + ca35c73 commit cbaf2c6
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 7 deletions.
31 changes: 25 additions & 6 deletions src/qibolab/_core/instruments/qm/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,16 @@ def register_pulses(self, configs: dict[str, Config], sequence: PulseSequence):
def register_duration_sweeper_pulses(
self, args: ExecutionArguments, configs: dict[str, Config], sweeper: Sweeper
):
"""Register pulse with many different durations.
"""Register pulses needed to implement a duration sweep.
Needed when sweeping duration.
For standard (non-interpolated) duration sweeps, we need to
upload distinct waveforms for every different duration.
When interpolation is used, we need to upload a single pulse
with the minimum duration of the sweeper, because the QM real-
time interpolation can only stretch and not compress arbitrary
waveforms, as documented in
https://docs.quantum-machines.co/latest/docs/Guides/features/?h=interpo#dynamic-pulse-duration
"""
for pulse in sweeper.pulses:
if isinstance(pulse, (Align, Delay)):
Expand All @@ -359,10 +366,20 @@ def register_duration_sweeper_pulses(
original_pulse = (
pulse if params.amplitude_pulse is None else params.amplitude_pulse
)
for value in sweeper.values.astype(int):
sweep_pulse = original_pulse.model_copy(update={"duration": value})
sweep_op = self.register_pulse(ids[0], configs[ids[0]], sweep_pulse)
params.duration_ops.append((value, sweep_op))
values = sweeper.values.astype(int)
if sweeper.parameter is Parameter.duration_interpolated:
sweep_pulse = original_pulse.model_copy(
update={"duration": min(values)}
)
params.interpolated_op = self.register_pulse(
ids[0], configs[ids[0]], sweep_pulse
)
else:
assert sweeper.parameter is Parameter.duration
for value in values:
sweep_pulse = original_pulse.model_copy(update={"duration": value})
sweep_op = self.register_pulse(ids[0], configs[ids[0]], sweep_pulse)
params.duration_ops.append((value, sweep_op))

def register_amplitude_sweeper_pulses(
self, args: ExecutionArguments, configs: dict[str, Config], sweeper: Sweeper
Expand Down Expand Up @@ -448,6 +465,8 @@ def preprocess_sweeps(
self.register_amplitude_sweeper_pulses(args, configs, sweeper)
for sweeper in find_sweepers(sweepers, Parameter.duration):
self.register_duration_sweeper_pulses(args, configs, sweeper)
for sweeper in find_sweepers(sweepers, Parameter.duration_interpolated):
self.register_duration_sweeper_pulses(args, configs, sweeper)

def execute_program(self, program):
"""Executes an arbitrary program written in QUA language."""
Expand Down
1 change: 1 addition & 0 deletions src/qibolab/_core/instruments/qm/program/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Parameters:
duration: Optional[_Variable] = None
duration_ops: list[tuple[float, str]] = field(default_factory=list)
interpolated: bool = False
interpolated_op: Optional[str] = None

element: Optional[str] = None
lo_frequency: Optional[int] = None
Expand Down
10 changes: 9 additions & 1 deletion src/qibolab/_core/instruments/qm/program/instructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ def _delay(pulse: Delay, element: str, parameters: Parameters):

def _play_multiple_waveforms(element: str, parameters: Parameters):
"""Sweeping pulse duration using distinctly uploaded waveforms."""
assert not parameters.interpolated
assert parameters.interpolated_op is None
with qua.switch_(parameters.duration, unsafe=True):
for value, sweep_op in parameters.duration_ops:
if parameters.amplitude is not None:
Expand All @@ -52,7 +54,13 @@ def _play_single_waveform(
if acquisition is not None:
acquisition.measure(op)
else:
qua.play(op, element, duration=parameters.duration)
if parameters.duration is not None:
# sweeping duration using interpolation
# distinctly uploaded waveforms are handled by ``_play_multiple_waveforms``
assert len(parameters.duration_ops) == 0
qua.play(parameters.interpolated_op, element, duration=parameters.duration)
else:
qua.play(op, element)


def _play(
Expand Down

0 comments on commit cbaf2c6

Please sign in to comment.