# IBM Q devices scheduling of gates with different durations

I was trying to figure out how scheduling works in IBM devices.

The thing that's bugging me is that in the quantum computer implementations I had seen before, the cycle concept is used. Say, for example, a cycle = 20ns. And all operations take that time or multiples of that time. This is handy because things like parallelism and depth can then be defined using this cycles concept, which makes things like scheduling very clear.

With IBM machines, however, the duration of the primitivies can vary a lot, as seen on IBM's Github repo containing this information. We can see that the time it takes to perform a CNOT gate varies a lot, depending on the link. Let's have an example to motivate the question. If I define the following circuit in Qiskit:

q = QuantumRegister(14, 'q')
c = ClassicalRegister(14, 'c')
circ = QuantumCircuit(q, c)
circ.cx(q[1], q[0])
circ.cx(q[1], q[0])
circ.h(q[3])
circ.h(q[3])
circ.h(q[3])
print(circ)


The output of the print command will be (with the tracks for q[x>=4] trimmed since nothing was happening on those qubits):

In IBM's Q16 Melbourne device, the duration of each Hadamard gate is 100ns (+ 20ns buffer) and for this specific CNOT gate (q[1], q[0]) is 678ns (+80ns buffer). These values can be checked on the repository mentioned before. If may look, from the printed circuit, that the 3 Hadamards on q[3] would take more than the 2 CNOTs, but that is not the case. This raises some questions regarding how gates are actually scheduled on the device:

1 - Which gates were executed in parallel? The 3 Had gates can be executed faster than a single CNOT gate. Or was each Hadamard gate synchronized with the CNOT? If it's the 1st then this circuit output is pretty misleading, if the 2nd, when there's a lot of lost time for qubit q[3].

So reformulating the question: would the gates on q[3] be executed asynchronously?

2 - Defining depth as the number of gates in the longest track, as compared to the number to cycles, or time to the circuit to end can be misleading. In this case, the depth of the circuit is 3, even though the upper track takes much more time. Is there a way to extract a circuit runtime?

3 - How does this synchrony / asynchrony gets translated when compiling to a OPENQasm file?

We should generally think of QASM as agnostic to timing. Time is not represented anywhere in a quantum circuit diagram. The wires between circuit operations simply represent a quantum state. I could move the CNOTs as far to the right as I want in your diagram, or generally modify any spacing between any operations however I like, and the circuits would be exactly equivalent. It's analogous to beads on a multi-chain necklace. The necklace is only different when we add new operations, or change the order of operations. For this reason, it's perfectly acceptable for the printed QASM output to be "misleading" about timing.

Time is a lower level construct. IBM's OpenPulse framework is the system for which asking these kinds of questions is more defined. Nonetheless, your questions do have answers.

### How does scheduling work on IBM devices?

If you would like to see some concrete code, IBM backends follow a scheduling procedure similar to what is implemented in this PR as the "as_late_as_possible" (ALAP) method: https://github.com/Qiskit/qiskit-terra/pull/2650 (It will be merged once a constraint on the backend is relaxed.)

In words, this scheduling procedure is roughly to reverse the circuit, schedule operations greedily, and then reverse again. This ALAP scheduling can improve fidelity by maximizing the time that qubits remain in the ground state.

Note: Keep in mind that IBM does not promise to schedule circuits this way. It is totally up to the respective backend/provider to decide how they want to schedule QASM operations. If the backends added an extra 10ns delay between every operation, that is totally within their right. Only in OpenPulse can you expect any real guarantee about the timing of the program execution.

Now, assuming scheduling does happen as described, let's think about how your circuit will be scheduled. Since qubits 0 and 1 are separate from qubit 3, as late as possible and as soon as possible scheduling is identical: it's just greedily scheduled. (I don't think the ending time is aligned.)

Your example would be more interesting if we add a global (across qubits 0, 1, 3) measure. The measure will be scheduled across all qubits at the same time. Then, ALAP is indeed different than ASAP. The timing would be:

CNOT q0 q1 @ t=0
CNOT q0 q1 @ t=758ns
MEASURE q0 q1 q3 @ t=1516ns
(solve for the H times backwards)
H q3 @ t=1156ns
H q3 @ t=1276ns
H q3 @ t=1396ns


I said circuits are timing agnostic, but we can use barriers to make requests to the compiler to add timing constraints. Barriers are pragmas (info for the compiler), not operations. It depends on the compiler to actually respect your request. If you want the Hadamards to be aligned with the CNOTs, you could use barriers:

c = ClassicalRegister(14, 'c')
circ = QuantumCircuit(q, c)
circ.cx(q[1], q[0])
circ.h(q[3])
circ.barrier(q[0], q[3])

circ.cx(q[1], q[0])
circ.h(q[3])
circ.barrier(q[0], q[3])

circ.h(q[3])


Then, given that the compiler listens to your request and still uses the ALAP scheduling method, the first H would play at t=(758-120)ns=638ns, the second would play at t=(1516-120)ns=1396ns, and the third would play at t=1516ns.

2) There are a couple ways. You could try to calculate the circuit runtime using backend.properties() and adding up gate_lengths if they are provided. If you have access to an OpenPulse enabled device, you can checkout the scheduler branch I linked and check the duration property on the resulting schedule. There has also been discussion to add this as a circuit feature: https://github.com/Qiskit/qiskit-terra/issues/2749
3) If I understand correctly, I think this goes back to the idea that timing is not acknowledged by QuantumCircuits or by QASM -- it doesn't get translated or represented.