Skip to content

Add sweeper support for flipping_amplitude - #1508

Merged
lballerio merged 4 commits into
flipping_amplitudefrom
flipping_amplitude_sweeper
Jun 1, 2026
Merged

Add sweeper support for flipping_amplitude#1508
lballerio merged 4 commits into
flipping_amplitudefrom
flipping_amplitude_sweeper

Conversation

@sorewachigauyo

Copy link
Copy Markdown
Contributor

As discussed in PR #1504, an implementation of the routine with amplitude sweeper

This probably has to be modified based on how 42aea44 goes and if #1507 gets merged due to

            # First two pulses are the pi/2 pulse and unused alignment and the last pulse is a readout alignment
            # So we add every pulse in-between
            # Technically we can reduce the number of pulses by filtering by unique UUID
            pulses_to_sweep[qubit].extend(
                list(seq.channel(platform.qubits[qubit].drive))[2:-1]
            )

which I'm not super happy about, but it works for now

@sorewachigauyo sorewachigauyo changed the title feat(flipping): add sweeper support for amp protocol Add sweeper support for flipping_amplitude May 19, 2026
@codecov

codecov Bot commented May 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 5.26316% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.71%. Comparing base (97f919c) to head (ffa5908).

Files with missing lines Patch % Lines
src/qibocal/protocols/flipping_amplitude.py 5.26% 18 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@                  Coverage Diff                   @@
##           flipping_amplitude    #1508      +/-   ##
======================================================
- Coverage               93.76%   93.71%   -0.06%     
======================================================
  Files                     137      137              
  Lines                   10799    10803       +4     
======================================================
- Hits                    10126    10124       -2     
- Misses                    673      679       +6     
Flag Coverage Δ
unittests 93.71% <5.26%> (-0.06%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/qibocal/protocols/flipping_amplitude.py 39.84% <5.26%> (-2.10%) ⬇️

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@lballerio lballerio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @sorewachigauyo for this implementation.
As I said, I think there is still something we can refactor and simplify, but we can postpone this discussion after we merge this PR on PR #1504.
As you mentioned here and in PR #1507, in your implementation we are recycling the same pulse, which I am getting convinced might be the more practical solution since we are sweeping the same way all the pulses in the experiment, so we might actually recycle the pulse so we don't have a huge list of pulses which differ only for the UUID we sweep in the same way...
Btw did you test it?
I am simply waiting for @jevillegasd review.

Comment thread src/qibocal/protocols/flipping_amplitude.py Outdated
Comment thread src/qibocal/protocols/flipping_amplitude.py Outdated
Comment on lines +175 to +194
for flips, sequence in zip(flips_range, sequences):
for qubit, sweeper in zip(targets, parallel_sweepers):
acq_channel = platform.qubits[qubit].acquisition
assert acq_channel is not None
ro_pulse = list(sequence.channel(acq_channel))[-1]
assert isinstance(ro_pulse, Readout)
prob = results[ro_pulse.id]
error = np.sqrt(prob * (1 - prob) / params.nshots)
native_amp = data.pulse_amplitudes[qubit]
data.register_qubit(
FlippingAmplitudeType,
qubit,
{
"flips": np.array([flips]),
"amplitude": np.array([native_amp + delta_amp]),
"prob": np.array([prob]),
"error": np.array([error]),
},
)
prob_array = results[ro_pulse.id]
assert len(prob_array) == len(sweeper.values)
for amp, prob in zip(sweeper.values, prob_array):
error = np.sqrt(prob * (1 - prob) / params.nshots)
data.register_qubit(
FlippingAmplitudeType,
qubit,
{
"flips": np.array([flips]),
"amplitude": np.array([amp]),
"prob": np.array([prob]),
"error": np.array([error]),
},
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe can be simplified, but we can do it in PR #1504.

Comment on lines +148 to +153
# First two pulses are the pi/2 pulse and unused alignment and the last pulse is a readout alignment
# So we add every pulse in-between
# Technically we can reduce the number of pulses by filtering by unique UUID
pulses_to_sweep[qubit].extend(
list(seq.channel(platform.qubits[qubit].drive))[2:-1]
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not an expert on this experiment, but should we also sweep on the initial RX90 pulse amplitude?

@sorewachigauyo sorewachigauyo May 20, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I don't think we have to.

This particular experiment is looking for the minimum variance between adding multiple $2\pi$ rotations from the initial state, so the initial state doesn't have to be the exact middle, so long as we return to it. (And I guess in that sense, we don't have to start from the middle either)

I think the initial state affects the original experiment more under certain conditions, as that decides under/over-rotation fitting.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point, yeah probably your right, then probably won't make such a difference.

@sorewachigauyo

sorewachigauyo commented May 20, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @sorewachigauyo for this implementation. As I said, I think there is still something we can refactor and simplify, but we can postpone this discussion after we merge this PR on PR #1504. As you mentioned here and in PR #1507, in your implementation we are recycling the same pulse, which I am getting convinced might be the more practical solution since we are sweeping the same way all the pulses in the experiment, so we might actually recycle the pulse so we don't have a huge list of pulses which differ only for the UUID we sweep in the same way...

On my driver implementation, sweeping/playing multiple pulses with the same UUID is not an issue. My concern from the other PR is if that was an issue with QM/Qblox, which I don't have in my lab to test. If this isn't a problem, then yeah, we should go ahead with the recycling, because in the current implementation (prior to #1507), each call of flipping_sequence generates flips number of UUIDs due to replace making a new pulse and replace being used in a loop.

Btw did you test it?

Yeah, it was actually in the other PR, but here is a new test
flipping_2d.tar.gz

@lballerio

Copy link
Copy Markdown
Contributor

Hi @sorewachigauyo, I just tried to run this implementation on qblox and actually the sweeper is too big and does not fit, it raises an error.
I am trying to modify a bit the code.

@sorewachigauyo

Copy link
Copy Markdown
Contributor Author

Hi @lballerio
Could you try this branch https://github.com/qiboteam/qibocal/tree/flipping_amplitude_sweeper_minpulses?

Its a bit more extreme rewrite that doesn't reuse the existing sequence generation and should make qibolab happier
QPU data flipping_2d.tar.gz

If this doesn't work, then I'll probably change this into a separate PR for sweepers

@lballerio

lballerio commented May 20, 2026

Copy link
Copy Markdown
Contributor

This is the memory issue on the sweepers, as you can see from the error message:

image

I also tried to run by repeating always the same pulse, trying to see if inserting only once the pulse to sweep it effectively sweeps over all the pulses in the sequence, but at the time being it seems it is not working as it should, but I need to see in more detail.

Ok let me see your branch, thanks!

@lballerio

lballerio commented May 20, 2026

Copy link
Copy Markdown
Contributor

Hi @sorewachigauyo I tried your new branch and the results I think a re very satifying!
In this way you are simply using the same UUID throughout the entire experiment, right?
Maybe this is better.

image

I also worked on this sweeper implementation and ended up with https://github.com/qiboteam/qibocal/tree/flipping_amplitude_sweeper_lballerio.
In my case I was calling flipping_sequence for each nflips values, hence I am sweeping over N pulses, with N total number of nflips, since within the same sequence the UUID is the same. However these modifications didn't measure good signal, as you can see from the picture below:

image

if you want to have a look, but I think you're implementation is more than fine...maybe we should move the PR on that branch.
I think in my implementation there is probably some error in the sweeper usage, better to use your which is just the same pulse

@sorewachigauyo

sorewachigauyo commented May 20, 2026

Copy link
Copy Markdown
Contributor Author

Yeah, its the same UUID/pulse object for the entire experiment

Okay, good to see that it works with Qblox
I'll just push the commit here

@lballerio

Copy link
Copy Markdown
Contributor

perfect, yeah I like your implementation!

@lballerio lballerio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested with Qblox on TII qw5q_platinum QPU, I think is good

@scarrazza
scarrazza requested a review from a team May 21, 2026 08:15
@lballerio
lballerio merged commit 89cae79 into flipping_amplitude Jun 1, 2026
38 of 39 checks passed
@lballerio
lballerio deleted the flipping_amplitude_sweeper branch June 1, 2026 14:03
jevillegasd added a commit that referenced this pull request Jun 15, 2026
…cation. This is still however unable to run for long pulse durations in the spin lock pulse.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants