Dynamic Control Flow

The Quil language specifies classical control flow instructions that give programs the ability to conditionally execute code during run-time. These instructions can be used as primitives to create classical control flow constructs like branches and loops. Conditional instructions allow programs to specify conditions using memory values, allowing them to dynamically branch using run-time values. In short, these instructions enable programs to use dynamic control flow. These instructions are supported on both the QVM and on Rigetti QPUs. This guide will walk through some of the basics of using dynamic control flow on a Rigetti QPU and what behavior you can expect.

Conditional branches with JUMP and LABEL

Let's start with an example that expands on the classic bell state program to illustrate dynamic control flow.

DECLARE ro BIT[2]
H 0
CNOT 0 1
MEASURE 0 ro[0]
JUMP-WHEN @IS_ONE ro[0]
JUMP @END
LABEL @IS_ONE
MEASURE 1 ro[1]
LABEL @END

This program will perfectly entangle qubits 0 and 1, so we can measure either qubit and know the state of the other. In this case, we measure qubit 0 and only measure qubit 1 if qubit 0 was measured to 1. This gives us two predictable outputs (assuming a noiseless environment for the sake of example).

If qubit 0 measures to 1

In this case, when the statementJUMP-WHEN @IS_ONE ro[0] is evaluated, the value inside of ro[0] will be checked. Because it is 1, the program will jump to LABEL @IS_ONE. The program continues as normal from that point, so qubit 1 is measured into ro[1]. Since the qubits were perfectly entangled, we know that qubit 1 also measured to 1. In this case, we get predictable readout data:

{
   "ro[0]": [1],
   "ro[1]": [1]
}

If qubit 0 measures to 0

In this case, when the statementJUMP-WHEN @IS_ONE ro[0] is evaluated, the program will not jump to the @IS_ONE label, since ro[0] will contain 0. Instead, it continues as normal to the JUMP @END instruction. This unconditional jump will skip to the LABEL @END instruction, effectively ending the program. Importantly, this skips over MEASURE 1 ro[1] entirely. This impacts readout data in a potentially surprising way:

{ 
  "ro[0]": [0]
}

Instead of using shot count, you can wrap the code that executes your job in a loop and join the results.

his template should be applicable to any program:

# Make any declarations you need here
DECLARE shot_count INTEGER[1]
LABEL @START
# Put the rest of your program here
SUB shot_count[0] 1
JUMP-UNLESS @END shot_count[0]
JUMP @START
LABEL @END

While not directly related to control flow, it's important to note that many of the comparison instructions that can be used to create conditions are not yet supported on QPUs. This includes AND, IOR, NEG, NOT, OR, XOR, EQ, GE, GT, LE, and LT.

Last updated