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

Fix compiler pushing /measurement/ pulses to later time #1096

Draft
wants to merge 3 commits into
base: 0.1
Choose a base branch
from

Conversation

hay-k
Copy link
Contributor

@hay-k hay-k commented Nov 11, 2024

Consider the following circuit:

q0: ─GPI2─M──────
q1: ─GPI2─GPI2─M─

The current compiler will compile this to:

DrivePulse(0, 40, 0.05, 4_000_000_000.0, 0, Gaussian(5), drive-0, 0)
DrivePulse(0, 40, 0.15, 4_200_000_000.0, 1.570796, Drag(5, -0.02), drive-1, 1)
DrivePulse(40, 40, 0.15, 4_200_000_000.0, 3.141593, Drag(5, -0.02), drive-1, 1)
ReadoutPulse(40, 2000, 0.1, 5_200_000_000.0, 0, GaussianSquare(5, 0.75), readout, 0)
ReadoutPulse(2040, 2000, 0.1, 4_900_000_000.0, 0, GaussianSquare(5, 0.75), readout, 1)

Notice how the measurement on qubit 1 starts after the measurement of 0 (start time is 2040). Since measurement pulses are usually long (in this example 2000ns), this results into significant qubit state deterioration before the measurement of qubit 1 starts, hence poor results.

With the fix in this PR the circuit is compiled into the following sequence instead:

DrivePulse(0, 40, 0.05, 4_000_000_000.0, 0, Gaussian(5), drive-0, 0)
DrivePulse(0, 40, 0.15, 4_200_000_000.0, 1.570796, Drag(5, -0.02), drive-1, 1)
DrivePulse(40, 40, 0.15, 4_200_000_000.0, 3.141593, Drag(5, -0.02), drive-1, 1)
ReadoutPulse(40, 2000, 0.1, 5_200_000_000.0, 0, GaussianSquare(5, 0.75), readout, 0)
ReadoutPulse(80, 2000, 0.1, 4_900_000_000.0, 0, GaussianSquare(5, 0.75), readout, 1)

P.S. with measurement this issue is most apparent because of the typical long durations of the measurement pulses, however in principle pulses start times could be messed up in specific situations for other gates as well.

Copy link

codecov bot commented Nov 11, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 69.95%. Comparing base (49b6572) to head (985a953).

Additional details and impacted files
@@            Coverage Diff             @@
##              0.1    #1096      +/-   ##
==========================================
+ Coverage   69.88%   69.95%   +0.06%     
==========================================
  Files          64       64              
  Lines        6880     6879       -1     
==========================================
+ Hits         4808     4812       +4     
+ Misses       2072     2067       -5     
Flag Coverage Δ
unittests 69.95% <100.00%> (+0.06%) ⬆️

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

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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 @hay-k.

At this stage, I believe moments are not used by the compiler anymore, therefore we could probably even drop the nested loop and use for gate in circuit.queue directly. However, this will change the order in which gates are processed and I am not sure if this will affect the final result. In any case, for me it is fine as it is too.

src/qibolab/compilers/compiler.py Show resolved Hide resolved
# make sure they are in different moments before proceeding
assert not any(
[
len([gate for gate in m if isinstance(gate, gates.M)]) == 2
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
len([gate for gate in m if isinstance(gate, gates.M)]) == 2
len([gate for gate in m if isinstance(gate, gates.M)]) > 1

Silly remark, it's just slightly more readable for myself (it translates more literally the comment above)

]
)

circ._wire_names = [q0, q1]
Copy link
Member

Choose a reason for hiding this comment

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

Do you really need to force .wire_names?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Without this the wire names were strings and they caused problems when getting the qubit from platform. I saw a similar thing is done in the backend (here), so did it here as well. Is there any better way around this?

circ._wire_names = [q0, q1]
sequence, _ = compiler.compile(circ, dummy)

MEASUREMENT_DURATION = 2000
Copy link
Member

Choose a reason for hiding this comment

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

Maybe you could read this value from dummy, just to be relatively sure in case anyone will change it later on.

@hay-k hay-k marked this pull request as draft November 13, 2024 06:22
@hay-k
Copy link
Contributor Author

hay-k commented Nov 13, 2024

After some testing I found a case that this new compilation logic fails to compile correctly. Converting the PR to draft for now, until I get it fixed.

@alecandido
Copy link
Member

alecandido commented Nov 13, 2024

@hay-k this is what I was mentioning before: we have dedicated handling to make sure things are also synced per-qubit, even when the qubit is involved in an interaction but there is no pulse on any of its associated channels

# pad all qubits to have at least one channel busy for the duration of the gate
# (drive arbitrarily chosen, as always present)
end = start + gate_seq.duration
final = PulseSequence()
for q in gate.qubits:
qubit = platform.qubit(q)[1]
# all actual qubits have a non-null drive channel, and couplers are not
# explicitedly listed in gates
assert qubit.drive is not None
delay = end - channel_clock[qubit.drive]
if delay > 0:
final.append((qubit.drive, Delay(duration=delay)))
channel_clock[qubit.drive] += delay

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