Full Reference →

Pyquil Cheat Sheet

Install: pip install pyquil

Background and History

PyQuil was created by Rigetti Computing and first released in 2017 as a Python interface for writing programs in Quil (Quantum Instruction Language), Rigetti’s quantum assembly language. Rigetti Computing was founded in 2013 by Chad Rigetti, a former researcher at IBM, with the goal of building superconducting quantum processors and a full-stack quantum cloud platform. PyQuil was the software layer that made Rigetti’s hardware accessible to external users through what became Rigetti Quantum Cloud Services (QCS).

Quil itself was introduced as a companion to PyQuil, serving as a low-level instruction set for quantum programs. Unlike OpenQASM, which was primarily a circuit interchange format, Quil was designed with classical control flow and hybrid quantum-classical computation in mind from the start. The Quilc compiler, released alongside PyQuil, handles compilation from abstract gate sequences to Rigetti’s native gate set and performs circuit optimization. The Quantum Virtual Machine (QVM) provides local simulation of Quil programs without hardware access.

PyQuil went through several major versions as Rigetti’s platform evolved. Version 2.0, released in 2018, introduced the get_qc interface for connecting to both simulators and real hardware. Version 3.0 brought updates to match Rigetti’s transition to their Aspen-series processors. Version 4.0, released in 2023, reflected further changes to the QCS platform, including updated authentication and job submission workflows. Each version tracked changes in Rigetti’s hardware topology and cloud infrastructure.

As of 2025, PyQuil continues to be maintained as Rigetti’s primary SDK, though its community is smaller than Qiskit’s or Cirq’s. Rigetti’s hardware is also accessible through Amazon Braket and Azure Quantum, meaning some users interact with Rigetti processors through those platforms’ SDKs rather than PyQuil directly. PyQuil remains the preferred choice for users who want direct access to Quil’s low-level control features or who need Rigetti-specific optimizations that are not available through third-party access layers.

Installation

pip install pyquil

For local QVM and Quilc (required for simulation):

# Download from Rigetti: https://docs.rigetti.com/qcs/get-started/installing-locally
quilc --server &
qvm --server &

Key Imports

from pyquil import Program, get_qc
from pyquil.gates import H, CNOT, MEASURE, X, Y, Z, CZ, SWAP, RX, RY, RZ
from pyquil.quilbase import Declare

Core Classes

Program

The fundamental object - a sequence of Quil instructions.

p = Program()

# Add gates by += or >>
p += H(0)
p += CNOT(0, 1)
p >> X(2)         # equivalent to +=

Declaring classical memory

ro = p.declare('ro', 'BIT', 2)    # 2-bit classical register
angle = p.declare('angle', 'REAL', 1)  # real parameter register

Gates

H(qubit)            # Hadamard
X(qubit)            # Pauli-X
Y(qubit)            # Pauli-Y
Z(qubit)            # Pauli-Z
S(qubit)            # S gate
T(qubit)            # T gate
CNOT(control, target)    # Controlled-NOT
CZ(q1, q2)          # Controlled-Z
SWAP(q1, q2)        # SWAP
CCNOT(q1, q2, q3)   # Toffoli

# Rotation gates (angles in radians)
RX(angle, qubit)
RY(angle, qubit)
RZ(angle, qubit)

# Native Rigetti gates (used on hardware)
CPHASE(angle, q1, q2)
CPHASE00(angle, q1, q2)
CPHASE01(angle, q1, q2)
CPHASE10(angle, q1, q2)
XY(angle, q1, q2)

Measurement

p = Program()
ro = p.declare('ro', 'BIT', 2)

p += H(0)
p += CNOT(0, 1)
p += MEASURE(0, ro[0])
p += MEASURE(1, ro[1])

Execution

QVM (local simulator)

from pyquil import Program, get_qc
from pyquil.gates import H, CNOT, MEASURE

p = Program()
ro = p.declare('ro', 'BIT', 2)
p += H(0)
p += CNOT(0, 1)
p += MEASURE(0, ro[0])
p += MEASURE(1, ro[1])
p.wrap_in_numshots_loop(1000)   # set shot count (mutates in place)

qc = get_qc('2q-qvm')           # local 2-qubit QVM
results = qc.run(p).readout_data.get('ro')

from collections import Counter
counts = Counter(map(tuple, results))
print(counts)

Statevector QVM

qc = get_qc('2q-qvm', as_qvm=True, noisy=False)
# No shots needed for wavefunction
from pyquil.api import WavefunctionSimulator
wfs = WavefunctionSimulator()
wf = wfs.wavefunction(p)
print(wf)
print(wf.probabilities())

Real hardware (QCS)

qc = get_qc('Aspen-M-3')   # Rigetti hardware name
results = qc.run(p).readout_data.get('ro')

Quilc Compiler

PyQuil automatically compiles programs to native Rigetti gates via Quilc. You can inspect the native program:

native = qc.compiler.quil_to_native_quil(p)
print(native)

Quantum Instruction Language (Quil)

PyQuil generates Quil - Rigetti’s assembly-like language. You can also write it directly:

from pyquil import Program
from pyquil.quilbase import Pragma

p = Program()
p += Pragma('INITIAL_REWIRING', freeform_string='"PARTIAL"')
p.inst("H 0")
p.inst("CNOT 0 1")

Common Patterns

Bell state

p = Program()
ro = p.declare('ro', 'BIT', 2)
p += H(0)
p += CNOT(0, 1)
p += MEASURE(0, ro[0])
p += MEASURE(1, ro[1])
p.wrap_in_numshots_loop(1000)
qc = get_qc('2q-qvm')
results = qc.run(p).readout_data.get('ro')

Parameterised gate

from pyquil.quilbase import MemoryReference

p = Program()
angle = p.declare('angle', 'REAL', 1)
p += RY(angle, 0)
ro = p.declare('ro', 'BIT', 1)
p += MEASURE(0, ro[0])

qc = get_qc('1q-qvm')
result = qc.run(p, memory_map={'angle': [1.57]}).readout_data.get('ro')