Circuit formats
circuit is text in every format, and circuit_format says which format it is. A
Backend reports what it accepts as supported_formats; a Backend that reports none
places no constraint of its own.
CircuitFormat |
What it is |
|---|---|
OPENQASM_3 |
OpenQASM 3 program text. The default, and what this documentation uses. |
OPENQASM_2 |
OpenQASM 2 program text, for Backends that accept it. |
QPY |
Qiskit’s binary circuit serialisation. |
QIR |
Quantum Intermediate Representation. |
IONQ_CIRCUIT |
A JSON circuit document — a gateset, a qubit count and a list of gates. Still passed as a string. |
OpenQASM 3: what is accepted
Section titled “OpenQASM 3: what is accepted”OpenQASM 3 is a large language, and no importer implements all of it. The platform accepts static circuits with parameters and rejects dynamic circuits:
| Accepted | Rejected |
|---|---|
include "stdgates.inc"; |
for and while loops |
input declarations — this is how sweeps bind |
def subroutines |
both measure forms — c = measure q; and measure q -> c; |
classical int declarations |
gate modifiers ctrl@, inv@, pow@ |
if on a single bit compared to an integer |
custom gate declarations |
|
barrier and reset |
A circuit that stays inside the accepted column:
OPENQASM 3.0;include "stdgates.inc";
gate bell a, b { h a; cx a, b;}
input float[64] theta;
qubit[3] q;bit[3] c;
bell q[0], q[1];ry(theta) q[2];ctrl @ x q[0], q[2];barrier q;c = measure q;Custom gates, a parameter to sweep, a control modifier, a barrier and a measurement — all accepted, and sufficient for most textbook and benchmark circuits.
Dynamic circuits
Section titled “Dynamic circuits”The rejected column is one idea: anything whose control flow is decided while the circuit
runs. A for loop, a subroutine call, a classical register being computed, a branch on a
mid-circuit measurement — each requires the executing device to make a decision the
compiler cannot make in advance. The platform does not currently execute dynamic
circuits.
For running the same circuit at many values, use parameter_values rather than a loop in
the circuit — see Primitives and PUBs. For the rest, unroll: write
out the repetitions rather than looping, and inline what would have been a subroutine.
Custom gate declarations are accepted, so the readable factoring is still available.
How a parameter row binds
Section titled “How a parameter row binds”A row of parameter_values holds one value per input declaration, positionally, in the
order the declarations appear in the circuit text. Nothing in the row names a parameter,
so the order is the whole contract.
When you write the OpenQASM yourself, you also write the declarations, and reading them
top to bottom gives you the row. When a framework adapter writes it for you, the rule is
that declarations are sorted by parameter name — the order Qiskit’s
circuit.parameters already uses, and the order OpenQARP’s emitter declares its input
floats in. So a circuit with alpha, gamma and theta takes rows of
[alpha, gamma, theta] whatever order the gates used them in, on every path into the
platform.
input float[64] alpha;input float[64] theta;...parameter_values=[[0.1, 0.9]] # alpha=0.1, theta=0.9Which format to use
Section titled “Which format to use”from qubitra import CircuitFormat
backend = client.backends.get("sim-statevector-26q")for candidate in (CircuitFormat.OPENQASM_3, CircuitFormat.OPENQASM_2): if candidate in backend.supported_formats: chosen = candidate breakPrefer OpenQASM 3 where a Backend accepts it, and check supported_formats rather than
assuming. A format this SDK version does not recognise is dropped from
supported_formats rather than failing the read, so the tuple only ever contains formats
both you and the platform understand.
Submitting a format a Backend does not accept is rejected at submit with an error naming
the formats it does accept. A format the SDK does not know at all raises
InvalidRequestError without a request being sent.