Support subschedules and control-flow in circuit diagram
Explanation of changes
Supersedes !1031 (closed) since I decided to go in a direction that is too different. The way the circuit diagram is generated has been refactored quite a bit.
In short, the way it works now is:
- We check what qubits (gates) or ports (pulses/acquisitions) are used, so that we know how big the figure will be. Based on the port name, the pulses/acquisitions end up on the corresponding qubit "wire" or they end up on the "other" wire.
- We walk through all the (nested) schedulables in the schedule (depth-first). Boxes for operations, or brackets/arrows etc. for control-flow are drawn on the fly.
Style-wise I am very open to suggestions
Here are some examples:
inner_schedule = Schedule("inner", repetitions=1)
ref = inner_schedule.add(Rxy(0, 0, "q0"), label="inner0")
inner_schedule.add(Rxy(0, 1, "q0"), rel_time=40e-9, ref_op=ref, label="inner1")
outer_schedule = Schedule("outer", repetitions=10)
ref = outer_schedule.add(Rxy(1, 0, "q0"), label="outer0")
outer_schedule.add(inner_schedule, rel_time=80e-9, ref_op=ref)
outer_schedule.add(Measure("q0"), label="measure")
outer_schedule.plot_circuit_diagram()
inner_schedule = Schedule("inner", repetitions=1)
ref = inner_schedule.add(Rxy(0, 0, "q0"), label="inner0")
inner_schedule.add(Rxy(0, 1, "q0"), rel_time=40e-9, ref_op=ref, label="inner1")
outer_schedule = Schedule("outer", repetitions=1)
ref = outer_schedule.add(Rxy(1, 0, "q0"), label="outer0")
outer_schedule.add(
LoopOperation(body=inner_schedule, repetitions=10),
label="loop",
)
outer_schedule.add(Measure("q0"), label="measure")
outer_schedule.plot_circuit_diagram()
schedule = Schedule("")
schedule.add(ConditionalReset("q0"))
schedule.add(ConditionalReset("q4"))
schedule.plot_circuit_diagram()
inner = Schedule("inner")
inner.add(X("q2"))
inner2 = Schedule("inner2")
inner2.add(Y("q1"))
inner.add(
LoopOperation(body=inner2, repetitions=2),
)
inner.add(Measure("q0"))
sched = Schedule("amp_ref")
sched.add(X90("q0"))
sched.add(LoopOperation(body=inner, repetitions=3))
sched.add(X90("q0"))
sched.add(LoopOperation(body=inner2, repetitions=4))
sched.add(X90("q0"))
sched.add(LoopOperation(X("q0"), repetitions=2))
fig, ax = sched.plot_circuit_diagram()
inner = Schedule("inner")
inner.add(X("q0"))
inner2 = Schedule("inner2")
inner2.add(Y("q0"))
inner.add(
LoopOperation(body=inner2, repetitions=2),
)
inner.add(Measure("q0"))
sched = Schedule("amp_ref")
sched.add(Measure("q0", acq_protocol="ThresholdedAcquisition", feedback_trigger_label="q0"))
sched.add(ConditionalOperation(body=inner, qubit_name="q0"), rel_time=364e-9)
fig, ax = sched.plot_circuit_diagram()
Merge checklist
See also merge request guidelines
-
Merge request has been reviewed (in-depth by a knowledgeable contributor), and is approved by a project maintainer. -
New code is covered by unit tests (or N/A). -
New code is documented and docstrings use numpydoc format (or N/A). -
New functionality: considered making private instead of extending public API (or N/A). -
Public API changed: added @deprecatedand entry in deprecated code suggestions (or N/A). -
Newly added/adjusted documentation and docstrings render properly (or N/A). -
Pipeline fix or dependency update: post in #software-for-developerschannel to mergemainback in or update local packages (or N/A). -
Tested on hardware (or N/A). -
CHANGELOG.mdandAUTHORS.mdhave been updated (or N/A). -
Update Hardware backends documentation if backend interface change or N/A -
Check whether performance is significantly affected by looking at the Performance metrics results. -
Windows tests in CI pipeline pass (manually triggered by maintainers before merging). - Maintainers do not hit Auto-merge, we need to actively check as manual tests do not block pipeline
For reference, the issues workflow is described in the contribution guidelines.
Edited by Thomas Middelburg




