Improve interfaces for multiple reference operations.
After a brief discussion during yesterday's developer meeting (2023/07/13), we decided to re-open this issue and update it's contents.
Currently, it is possible to set multiple reference operations for a Schedulable
by manually adding timing constraints. For example, one could do
schedule=Schedule("test_schedule")
x0 = schedule.add(X("q0"))
y1 = schedule.add(X("q1"), ref_op=x0, ref_pt="start")
y0 = schedule.add(Y("q0"), ref_op=x0)
cz = schedule.add(CZ("q0", "q1"))
cz.add_timing_constraints(ref_op=y1)
cz.add_timing_constraints(ref_op=y0)
This will schedule the CZ
after both y0
and y1
, which is a very useful feature. However, this is (to my knowledge) not documented, which would be very nice.
An even better improvement would be to improve the interface to do this, such as
schedule=Schedule("test_schedule")
x0 = schedule.add(X("q0"))
y1 = schedule.add(X("q1"), ref_op=x0, ref_pt="start")
y0 = schedule.add(Y("q0"), ref_op=x0)
cz = schedule.add(CZ("q0", "q1"), ref_op=(y0, y1))
which is arguably more intuitive and user-friendly.
Hence, this issue can be broken into two parts:
-
Add the timing_constraints
to the documentation about schedule create (might be nice to put it in the Bell state example). -
Improve the interface for adding multiple reference operations (and other timing constraints).
Previous issue description, which (still) describes the desired functionality
Previous description
Description
Support adding multiple operations as ref_op
s in a schedule.
Motivation
Take the following snippet from the documentation
import numpy as np
from quantify_scheduler import Schedule
from quantify_scheduler.operations.gate_library import CZ, Measure, Reset, Rxy, X90
sched = Schedule("Bell experiment")
for acq_idx, theta in enumerate(np.linspace(0, 360, 21)):
sched.add(Reset(q0, q1))
sched.add(X90(q0))
sched.add(X90(q1), ref_pt="start") # Start at the same time as the other X90
sched.add(CZ(q0, q1))
sched.add(Rxy(theta=theta, phi=0, qubit=q0))
sched.add(Measure(q0, acq_index=acq_idx), label="M q0 {:.2f} deg".format(theta))
sched.add(
Measure(q1, acq_index=acq_idx),
label="M q1 {:.2f} deg".format(theta),
ref_pt="start", # Start at the same time as the other measure
)
sched
In this case, the two X90
operations are assumed to have the same duration. As an example, lets say that q0
has a weak coupling to its driveline. In this case, we may set its rxy.duration
to 80 ns, and that of q1
to 20 ns (the default we use in our lab).
Now, the CZ(q0, q1)
will have the X90(q1)
as reference operation, so it will be executed 20 ns after X90(q0)
and X90(q1)
start. Hence, there will be a 60 ns overlap between CZ(q0, q1)
and X90(q0)
. If we swap the order in which we added X90(q0)
and X90(q1)
, all would be fine.
Hence, if we could do something like
sched.add(X90(q0), label="x90_q0")
sched.add(X90(q1), ref_pt="start", label="x90_q1") # Start at the same time as the other X90
sched.add(CZ(q0, q1), ref_op=("x90_q0", "x90_q1"))
which would schedule the CZ
after both reference operations are done, this would be resolved. Of course, a question may be how to handle different ref_pt
s, like "start"
.
I'm also open to any alternative implementations that provide a simple way of scheduling relative to multiple operations that are possible already with the current version of quantify.
You can also find us on Slack. For reference, the issues workflow is described in the contribution guidelines.