OpenQASM
The open quantum assembly language - a hardware-neutral circuit description format
Quick install
pip install openqasm3 qiskit-qasm3-import Background and History
OpenQASM (Open Quantum Assembly Language) was created at IBM Research by Andrew Cross and colleagues, with version 2.0 published in a 2017 paper that accompanied the expansion of IBM’s cloud quantum computing platform. The language was designed to serve as a lightweight, human-readable intermediate representation for quantum circuits, filling the role that classical assembly languages play in conventional computing. OpenQASM 2.0 was deliberately minimal: it supported qubit and classical bit declarations, a fixed set of gates, and measurement, but lacked classical control flow, subroutines, or timing constructs.
Despite its simplicity, OpenQASM 2.0 became the de facto interchange format for quantum circuits across the industry. Qiskit, Cirq, pytket, and many other frameworks implemented import and export functions for QASM 2.0, making it the closest thing to a universal circuit description language. The .qasm file extension became widely recognized in the quantum computing community. IBM’s Quantum Experience platform used OpenQASM as the underlying circuit representation for its visual circuit composer.
Development of OpenQASM 3.0 began around 2020, with a formal specification published in 2022. The new version was a substantial expansion of the language, adding classical types (integers, floats, booleans), classical control flow (if/else, for, while), subroutines (def and gate blocks), timing and delay instructions, and pulse-level control. These additions were motivated by the needs of real hardware experiments, where mid-circuit measurement, conditional logic, and precise timing are essential for error correction and dynamic circuits. The OpenQASM 3 specification was developed collaboratively, with input from IBM, AWS, Quantinuum, and academic researchers.
As of 2025, OpenQASM 3 support is available in Qiskit (through the qiskit.qasm3 module), and the standalone openqasm3 Python parser allows any tool to read and manipulate QASM 3 programs. Adoption of the full QASM 3 feature set across other frameworks has been gradual, with most tools supporting a subset of the specification. OpenQASM remains governed by an open specification process, with the language definition and grammar hosted publicly on GitHub.
What Is OpenQASM?
OpenQASM (Open Quantum Assembly Language) is a text-based format for describing quantum circuits. It is not a Python library - it is a language standard that quantum SDKs can read and write. Version 3 added classical control flow, subroutines, and timing control.
Use cases:
- Interchange format between quantum tools
- Directly targeting specific hardware gate sets
- Embedding in Qiskit, Cirq, and other frameworks
Basic Structure
OPENQASM 3;
include "stdgates.inc"; // standard gate library
qubit[2] q;
bit[2] c;
h q[0];
cx q[0], q[1];
c = measure q;
Types
qubit q; // single qubit
qubit[4] qs; // 4-qubit register
bit b; // single classical bit
bit[4] c; // 4-bit classical register
int[32] n = 5; // 32-bit integer
float[64] theta = 1.5708;
bool flag = true;
Standard Gates (stdgates.inc)
| Gate | Description |
|---|---|
h q | Hadamard |
x q | Pauli-X |
y q | Pauli-Y |
z q | Pauli-Z |
s q | S gate |
sdg q | S-dagger |
t q | T gate |
tdg q | T-dagger |
cx q1, q2 | CNOT |
cz q1, q2 | Controlled-Z |
swap q1, q2 | SWAP |
ccx q1, q2, q3 | Toffoli |
rx(theta) q | Rx rotation |
ry(theta) q | Ry rotation |
rz(theta) q | Rz rotation |
u(theta, phi, lambda) q | Generic single-qubit gate |
u1(lambda) q | Phase gate |
u2(phi, lambda) q | Two-parameter gate |
Measurement
bit[2] c;
qubit[2] q;
c[0] = measure q[0]; // measure single qubit
c = measure q; // measure full register
Custom Gates
gate bell q0, q1 {
h q0;
cx q0, q1;
}
qubit[2] q;
bell q[0], q[1];
Classical Control Flow
OpenQASM 3 adds full classical control flow - a major upgrade from QASM 2.
// if statement
bit c;
c = measure q[0];
if (c == 1) x q[1];
// if-else
if (c == 0) {
h q[1];
} else {
x q[1];
}
// while loop
int i = 0;
while (i < 5) {
h q[0];
i = i + 1;
}
// for loop
for int j in [0:3] {
h q[j];
}
Subroutines
def grover_diffusion(qubit[3] q) -> bit[3] {
h q;
x q;
ctrl @ h q[2];
ctrl @ ctrl @ x q[2]; // CCX
ctrl @ h q[2];
x q;
h q;
return measure q;
}
Timing and Delays
delay[100ns] q[0]; // wait 100 nanoseconds
stretch s; // flexible delay (compiler-managed)
box [100ns] { // force a timing box
h q[0];
}
Using in Qiskit
from qiskit import QuantumCircuit
qasm_str = """
OPENQASM 3;
include "stdgates.inc";
qubit[2] q;
bit[2] c;
h q[0];
cx q[0], q[1];
c = measure q;
"""
qc = QuantumCircuit.from_qasm_str(qasm_str)
print(qc.draw())
Export from Qiskit:
from qiskit.qasm3 import dumps
print(dumps(qc))
Parsing with openqasm3
import openqasm3
program = openqasm3.parse("""
OPENQASM 3;
qubit q;
h q;
""")
print(program.statements)