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

Include update methods in all protocols #526

Merged
merged 14 commits into from
Sep 25, 2023
Merged

Conversation

andrea-pasquale
Copy link
Contributor

@andrea-pasquale andrea-pasquale commented Sep 20, 2023

This PR aims at removing the platform.updatemethod in qibolab by delegating to qibocal the update of the platform.
This is possible since qibocal has access to all the primitives in qibolab to peform this operation.

@alecandido @stavros11 I think that this is more or less what we discussed yesterday.
I'm encapsulating each parameter update in a function in update.py for two reasons:

  1. some routines update the same parameters
  2. the update sometimes is not trivial see for example the update of the readout frequency
    def update_readout_frequency(results: dict[QubitId, float], platform: Platform):
    """Update readout frequency value in platform for each qubit in results."""
    for qubit, freq in results.items():
    mz = platform.qubits[qubit].native_gates.MZ
    freq_hz = int(freq * GHZ_TO_HZ)
    mz.frequency = freq_hz
    if mz.if_frequency is not None:
    mz.if_frequency = freq_hz - platform.get_lo_readout_frequency(qubit)
    platform.qubits[qubit].readout_frequency = freq_hz
  3. it is easier to write tests for each update_* function as I am doing here

For now I implemented the new proposal only for resonator spectroscopy.
If you agree with it I will propagate the change for all protocols in qibocal.

Checklist:

  • Reviewers confirm new code works as expected.
  • Tests are passing.
  • Coverage does not decrease.
  • Documentation is updated.
  • Compatibility with Qibo modules (Please edit this section if the current pull request is not compatible with the following branches).
    • Qibo: master
    • Qibolab: main
    • Qibolab_platforms_qrc: main

Copy link
Member

@stavros11 stavros11 left a comment

Choose a reason for hiding this comment

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

Thanks for implementing this @andrea-pasquale. It looks good to me, so I would say to go ahead with the rest of methods (after @alecandido's review).

The only thing that seems a bit annoying is that the for loop over qubits is repeated in all update methods. One way to solve this would be to lift it to Task.update_platform but I am not sure if this will create problems in the longer term, maybe for two-qubit gate routines, etc. where we may need full flexibility when defining _update.

src/qibocal/update.py Outdated Show resolved Hide resolved
src/qibocal/auto/task.py Outdated Show resolved Hide resolved
src/qibocal/update.py Outdated Show resolved Hide resolved
src/qibocal/update.py Outdated Show resolved Hide resolved
@alecandido
Copy link
Member

I agree with @stavros11, this is mostly fine, in that the overall structure is perfect (at least I'd not have any better proposal right now).
We might slightly improve the helper update functions (maybe), but I believe they should be in Qibocal. So, we'll always be in time to improve them.

Please, keep going. And thanks for this :)

@andrea-pasquale andrea-pasquale changed the base branch from main to chevron_fit September 22, 2023 04:32
@andrea-pasquale andrea-pasquale changed the base branch from chevron_fit to main September 22, 2023 04:32
@andrea-pasquale andrea-pasquale self-assigned this Sep 22, 2023
@andrea-pasquale andrea-pasquale added the enhancement New feature or request label Sep 22, 2023
@andrea-pasquale andrea-pasquale added this to the Qibocal 0.0.4 milestone Sep 22, 2023
@codecov
Copy link

codecov bot commented Sep 22, 2023

Codecov Report

Merging #526 (6ef4b00) into main (4077637) will increase coverage by 0.12%.
Report is 10 commits behind head on main.
The diff coverage is 98.74%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #526      +/-   ##
==========================================
+ Coverage   96.47%   96.59%   +0.12%     
==========================================
  Files          66       67       +1     
  Lines        4846     4998     +152     
==========================================
+ Hits         4675     4828     +153     
+ Misses        171      170       -1     
Flag Coverage Δ
unittests 96.59% <98.74%> (+0.12%) ⬆️

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

Files Changed Coverage
src/qibocal/update.py 95.94%
src/qibocal/auto/execute.py 100.00%
src/qibocal/auto/operation.py 100.00%
src/qibocal/auto/task.py 100.00%
src/qibocal/fitting/classifier/run.py 100.00%
...tocols/characterization/allxy/drag_pulse_tuning.py 100.00%
...bocal/protocols/characterization/classification.py 100.00%
.../protocols/characterization/coherence/spin_echo.py 100.00%
...qibocal/protocols/characterization/coherence/t1.py 100.00%
...otocols/characterization/coherence/t1_sequences.py 100.00%
... and 20 more

@andrea-pasquale
Copy link
Contributor Author

In principle this is done, I think.
I will see if I can find a way to repeat those for loops every time.
If I don't manage to do it, I will open an issue.

Comment on lines 163 to 167
for qubit, beta in results.items():
shape = platform.qubits[qubit].native_gates.RX.shape
rel_sigma = re.findall(r"[\d]+[.\d]+|[\d]*[.][\d]+|[\d]+", shape)[0]
drag_pulse = pulses.Drag(rel_sigma=rel_sigma, beta=beta)
platform.qubits[qubit].native_gates.RX.shape = repr(drag_pulse)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@stavros11 I had to these weird shenanigans since apparently native_gates.RX.shape will give me the serial of the pulse shape and not the pulse shape object by itself.
Is there any reason to return the str and not the object itself?
I'm guessing that this is mostly related to the serialization of the native pulse

Copy link
Member

@alecandido alecandido left a comment

Choose a reason for hiding this comment

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

Thanks @andrea-pasquale for this. To me, it's perfect (and it has been incredibly fast).

The problem of the loops (repeated operations for qubits and pairs) in a sense is a long-standing one, because it is related to the multi-qubit calibration, for which we never had a very clear plan.
The message is: if there is not already one, open a dedicated issue, and we will solve anyhow in a dedicated PR.

The only tiny remark is that you're mixing this relevant and general update with something specific to the Chevron, that maybe would have been worth to examine in a separate PR as well.

@andrea-pasquale
Copy link
Contributor Author

The problem of the loops (repeated operations for qubits and pairs) in a sense is a long-standing one, because it is related to the multi-qubit calibration, for which we never had a very clear plan.
The message is: if there is not already one, open a dedicated issue, and we will solve anyhow in a dedicated PR.

Actually I might be close to find a solution for this.

The only tiny remark is that you're mixing this relevant and general update with something specific to the Chevron, that maybe would have been worth to examine in a separate PR as well.

Yeah, I know. I just did it since #520 is ready to merge I just need a second approval and I already fixed a few things there. I didn't want to open a second PR just for the chevron.

Finally, this PR does not tackle the update of the twpa parameters since the interface is currently being developed in qiboteam/qibolab#585

@andrea-pasquale
Copy link
Contributor Author

Actually I might be close to find a solution for this.

For loop implemented :)

@andrea-pasquale andrea-pasquale changed the base branch from main to chevron_fit September 22, 2023 10:25
@alecandido
Copy link
Member

For loop implemented :)

Saw it, that's definitely a possible solution.

I wonder if it's worth to have the whole routines working just for individual qubit/pair.
I believe the case of the fit will be similar to the update, but maybe it is convenient to make the acquisition in parallel (or maybe not, in which case we could really write the routines per qubit/pair, and keep the multi-thing at the level of the executor - in a separate PR, of course).

@@ -94,6 +94,11 @@ def update(self):
"""Local update parameter."""
return self.action.update

def update_platform(self, results: Results, platform: Platform):
if self.update:
for qubit in self.qubits:
Copy link
Member

Choose a reason for hiding this comment

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

self.qubits are actually pairs for two-qubits routines, isn't it?

(btw, maybe a brief docstring for this function would be nice)

@alecandido
Copy link
Member

@andrea-pasquale since the Chevron might require slightly more time, would you consider removing it from here, such that we can immediately merge this in main?
If you wish, operationally:

  • make another branch update_chevron that duplicates this
  • edit this to remove the Chevron related part
  • merge this into main
  • merge update_chevron into chevron_fit
  • merge main into update_chevron (in principle, this step should do nothing)

Or is there any other limitation for which we need the Chevron to merge the update?

Copy link
Member

@stavros11 stavros11 left a comment

Choose a reason for hiding this comment

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

Or is there any other limitation for which we need the Chevron to merge the update?

I think they are independent, so it should be possible to merge this before the Chevron fit. However, given that the Chevron fit is an enhancement and does not break any existing functionality, I am not sure if it is worth going through the trouble reversing the order now. The fit most likely won't be perfect but if it is on main it will be easier to test and improve.

The current PR also looks good to be merged.

I wonder if it's worth to have the whole routines working just for individual qubit/pair. I believe the case of the fit will be similar to the update, but maybe it is convenient to make the acquisition in parallel (or maybe not, in which case we could really write the routines per qubit/pair, and keep the multi-thing at the level of the executor - in a separate PR, of course).

For fit it may be possible, however for the acquisition it may be complex. With the current qibolab, if you want to take advantage of multiplex, you need to create a PulseSequence that targets multiple qubits and send it in a single platform.execute_pulse_sequence call. Lifting that to the executor will reduce our flexibility when writing routines, for example what if you want to execute two different sequences, on multiple qubits each. There may be a better design that allows this though.

Comment on lines 142 to 143
shape = platform.qubits[qubit].native_gates.RX.shape
rel_sigma = re.findall(r"[\d]+[.\d]+|[\d]*[.][\d]+|[\d]+", shape)[0]
Copy link
Member

Choose a reason for hiding this comment

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

I have not tested but this can probably be simplified using

Suggested change
shape = platform.qubits[qubit].native_gates.RX.shape
rel_sigma = re.findall(r"[\d]+[.\d]+|[\d]*[.][\d]+|[\d]+", shape)[0]
pulse = platform.qubits[qubit].native_gates.RX.pulse(start=0)
rel_sigma = pulse.shape.rel_sigma

This will basically delegate the shenanigans to qibolab's pulse constructor, but better to have them in a single place instead of two.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @stavros11, I'll give it a try.

@andrea-pasquale
Copy link
Contributor Author

Or is there any other limitation for which we need the Chevron to merge the update?

I think they are independent, so it should be possible to merge this before the Chevron fit. However, given that the Chevron fit is an enhancement and does not break any existing functionality, I am not sure if it is worth going through the trouble reversing the order now. The fit most likely won't be perfect but if it is on main it will be easier to test and improve.

In theory they are independent, I decided to make this PR point to chevron_fit only because I could already implement the update for the chevron given that I the fitting is working in that branch.

I wonder if it's worth to have the whole routines working just for individual qubit/pair. I believe the case of the fit will be similar to the update, but maybe it is convenient to make the acquisition in parallel (or maybe not, in which case we could really write the routines per qubit/pair, and keep the multi-thing at the level of the executor - in a separate PR, of course).

For fit it may be possible, however for the acquisition it may be complex. With the current qibolab, if you want to take advantage of multiplex, you need to create a PulseSequence that targets multiple qubits and send it in a single platform.execute_pulse_sequence call. Lifting that to the executor will reduce our flexibility when writing routines, for example what if you want to execute two different sequences, on multiple qubits each. There may be a better design that allows this though.

I agree with pretty much everything that @stavros11 said.
The main problem here is multiplexing. A possible way to solve it would be to have another function before acquisition something like setup which should prepare the pulse sequence so that in the acquisition we merge and execute multiple pulse sequences...
I would say that this is out of scope of this PR, but we should definitely think about it.

@alecandido
Copy link
Member

I would say that this is out of scope of this PR, but we should definitely think about it.

I agree it is out of scope for the PR, but it is not even urgent right now in general. We can rediscuss when we'll have lifted the main bottlenecks for autocalibration (and this is not one of them).

@alecandido
Copy link
Member

I'd like this to be merged asap, in order to:

So, if you want to merge #520 before, that's even fine. But if possible, let's do it soon.

Otherwise, the proposal above is because I do not feel much pressure about merging #520, but I'd like to merge this soon.
If you wish, I could follow the procedure above myself, and you can provide feedback.

@andrea-pasquale
Copy link
Contributor Author

I'd like this to be merged asap, in order to:

So, if you want to merge #520 before, that's even fine. But if possible, let's do it soon.

Otherwise, the proposal above is because I do not feel much pressure about merging #520, but I'd like to merge this soon. If you wish, I could follow the procedure above myself, and you can provide feedback.

I'm about to push a few fixes here but in principle both this PR and #520 are ready to merge. I prefer to merge #520 first I don't think that it is necessary to merge this one and afterwards #520.

Base automatically changed from chevron_fit to main September 25, 2023 11:02
@andrea-pasquale
Copy link
Contributor Author

As soon as CI passes I will merge also this one.

@alecandido
Copy link
Member

As soon as CI passes I will merge also this one.

Thank you very much :D

@andrea-pasquale andrea-pasquale added this pull request to the merge queue Sep 25, 2023
Merged via the queue into main with commit aef9c74 Sep 25, 2023
21 checks passed
@andrea-pasquale andrea-pasquale deleted the refactor_update branch September 25, 2023 12:19
This was referenced Sep 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants