-
Notifications
You must be signed in to change notification settings - Fork 17
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
Replace pulse.start
with delays and refactor native.py
#789
Conversation
Fine, but then create a union (at least typewise, like
Fine, these are the things that should be handled internally anyhow. |
Fine for me, there is no another meaningful
Yes, that was the goal since #683 |
Personally, I would only keep
I would, because with the logical channels there should be no overlap. In case this will become useful for validation, and when it will be needed, we may reintroduce it. But for as long as unused, let's drop it. |
This could be part of what I called the "high-level Pulse API". Let's just stick to stabilizing the low-level one first, and rediscuss the first right after. |
pulse.start
with delayspulse.start
with delays
I agree with all things said above. Just wanted to mention, that an alternative to accepting union |
I would expose the internal API as it is. If we want to add convenience methods in the "high-level" API that's fine, but I would not overcomplicate the basic one.
Exactly. And the main deal is not the |
I would compile the However, we could decide if this should happen in two steps (first define the whole sequence, then compile to the machine one) or directly at insertion level. class Sequence(dict[Channel, list[Pulse | Delay]):
...
class SequenceBuilder:
...
def compile(self) -> Sequence:
.... |
For sure we can do that, I just did not do it yet because I did not find any place where this type is required (at least yet). For example
Will do the rename ( On this point, it is worth noting that yesterday we had a discussion with @hay-k about whether A potential argument for not keeping in the pulse is that in QM (and I think also Qblox), phases are controlled via separate sequencer instructions instead of encoding them to waveforms. Therefore, a X-pulse and a Y-pulse (=X + pi/2 relative phase) is essentially the same pulse used in a different way in the program: play("x", "channel_id") for X and frame_rotation_2pi(0.25, "channel_id")
play("x", "channel_id")
reset_frame("channel_id") for Y. In both cases we only need to upload the X-pulse with zero phase.
I am not sure about this, because if all instruments provide such instruction, then it is probably simpler from our side to expose it to the pulse API and just pass it directly to the instrument, instead of compiling it ourselves. Then the question is if all instruments support it. I only know that QM does and I believe ZI provides something similar (I have heard of some Another issue that I encountered with QM in particular, is that depending on the rest of the program, Regardless of compiling or no, this instruction would be useful to have in some cases such as the unrolling function qibolab/src/qibolab/platform.py Line 25 in 13bdcb4
but we could consider this at a later stage. |
Conceptually, Even though all APIs were exposing an interface for that, it could be still simpler to use |
About this I'm not sure either. At the moment, it could be fine both ways. However, consider that this would be in a completely opposite direction to To avoid this kind of confusion, maybe we could split user's pulses from executed pulses (or something similar). Keep the first just as an interface, which could be featureful, and the second as minimal as possible. |
This point is not correct (or I don't understand it properly). |
I believe it's just the perspective that is shifted: I'm thinking about a minimal hardware-close representation, and in this sense we both don't need optional features for that, but also the required ones could be presented in a more abstract or explicit way. The rationale to move the phase out of That's why I was pushing for "layers": to keep one as close as possible to one end, and the other one to the other. flowchart LR
u1[user 1] --> up[user-pulse API]
u2[user 2] --> up
u3[...] --> up
qibocal["(qibocal)"] --> up
up --> llp[low-level pulses]
llp --> Zurich
llp --> qm[Quantum Machine]
llp --> Qblox
llp --> driver[...]
My other point was to start from the low-level, and postpone UI to a later effort (as soon as we complete the other one), since we will benefit of the low-level for all the other internal operations. |
@stavros11 since it was getting complex (after the recent I know it could be annoying, but since we have to deal with the parallel development in (@hay-k, I tag also you to be aware, no one else is working on |
I have skipped temporarily the instrument tests and added very few pylint exceptions in instruments (in d0a1567) since I am not going to touch drivers in this PR but I would still like to make the rest (and the CI) pass. Still TODO before this is ready for review:
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## 0.2 #789 +/- ##
===========================================
- Coverage 65.58% 49.63% -15.95%
===========================================
Files 58 58
Lines 5654 5573 -81
===========================================
- Hits 3708 2766 -942
- Misses 1946 2807 +861
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
@alecandido @hay-k tests are now passing, so I will mark this as ready for review. Because the diff is quite huge (sorry for this - may be because I ended up doing two things: removing start and refactoring native.py), I will summarize here the main changes and decisions I took that are up for discussion:
(*) In ed1a4dd I decided to add a new The rest of changes are trivial adjustments to make the code work with the new I will start refactoring the QM driver to see how it works with the |
pulse.start
with delayspulse.start
with delays and refactor native.py
for more information, see https://pre-commit.ci
@alecandido this branch has been rebased on top of 0.2 (which is now on top of current main) and tests are passing locally. I will soon start implementing some of your comments above, but feel free to put your branch on top of it. |
I fixed some of the review comments. As discussed with @alecandido I will skip the following as they are going to be addressed in #818 (or when the pydantic serialization is implemented):
Other than these, this should now be ready. Tests are passing but instrument tests are skipped until we update the drivers (I would wait for #792) for that. |
@alecandido @hay-k following what we discussed last week, the goal of this PR is to replace
pulse.start
with a newDelay
object. In the next days I will try to propagate the changes to native, platform and eventually the QM driver as a first driver test (although for this I'd prefer to have #733 and #738 available). In the meantime, feel free to have a look and let me know if you have any suggestions so that this moves towards a direction that all of us like (as much as possible).Here is a summary of the affected objects so far:
Delay
New class added to represent delays. Decided to go with a new object, completely seperate from
Pulse
because:Pulse
Dropped the following methods/properties:
finish
: not applicable ifPulse
does not havestart
(dropped).global_phase
: requiresstart
so it should be handled by the sequence but we can probably drop altogether because it is only used for software modulation.phase
: should we renamerelative_phase
tophase
?is_equal_ignoring_start
: it can probably be replaced by dataclass autogenerated__eq__
.PulseSequence
Some implementations will depend on the choice between (internal vs external) pulse sequence
(internal=channel attribute, sequence is just list / external=sequence has a list for each channel)
Require modification:
duration
: implementation depends on (internal vs external). I did a temporary implementation based on the current internal representation of channels, essentially by constructing the external.start
: probably not useful (dropped)finish
: equivalent toduration
if we dropstart
(dropped)get_pulse_overlaps
: implementation depends on (internal vs external) (dropped)seperate_overlapping_pulses
: same as above (used by qblox)Align
(not implemented)A suggestion of an additional non-pulse instruction which can be used to synchronize different channels, without explicit use of delays. For example, the README example would look like:
I did not implement this because it may be biased towards QM and complicate other drivers, so I would prefer to wait for feedback first.
Sweeper
Parameter.start
Native gates
NativePulse
,NativeSequence
, etc. as they are duplicates ofPulse
andPulseSequence
.from_dict
andraw
) to serialize.py since they are more associated with the YAML/JSON runcard rather than the qibolab API.Platform
start
fromplatform.create_*
methods.Pulse
to be frozen.unroll_sequences
.