Qx.Export.OpenQASM (Qx - Quantum Computing Simulator v0.6.0)

View Source

Export Qx quantum circuits to OpenQASM format and import OpenQASM 3.0 source back into a Qx.QuantumCircuit.

Importing OpenQASM (since v0.6.0)

from_qasm/1 parses OpenQASM 3 source produced by Qx, by Qiskit, or by IBM Quantum into a circuit:

{:ok, circuit} = Qx.Export.OpenQASM.from_qasm(qasm_source)

Round-trips with to_qasm/1 — any program emitted by to_qasm/1 parses back to a circuit with a matching state vector.

from_qasm_function/1 parses a gate name(p) a, b { … } definition and returns Elixir source for an equivalent function:

{:ok, %{name: "bell", arity: 3, source: source}} =
  Qx.Export.OpenQASM.from_qasm_function(qasm_with_gate)

The generated def name(circuit, params…, qubits…) body composes Qx.h/2, Qx.cx/3, etc. via the |> pipeline and can be Code.compile_string/1-ed.

Supported gate set on import

Direct mappings: h, x, y, z, s, sdg, t, rx, ry, rz, p, phase, u, u3, cx, CX, cz, swap, iswap, cp, cphase, ccx, cswap.

Decompositions: tdg → phase(-π/4), sx → u(π/2, -π/2, π/2), u1(λ) → phase(λ), u2(φ, λ) → u(π/2, φ, λ). id is dropped.

Not supported (raises Qx.QasmUnsupportedError)

Multi-register programs, gate modifiers (inv/pow/ctrl/negctrl), else branches, complex boolean conditions, classical types beyond bit, def, for, while, switch, defcal, let, pragma, extern, box, delay, reset, the stdgates cy/ch/crx/cry/crz/cu, and the Qiskit extensions rxx/ryy/rzz/rzx.

Exporting

This module provides functionality to convert Qx quantum circuits into OpenQASM code that can be executed on real quantum hardware platforms including:

  • IBM Quantum (IBM Q)
  • AWS Braket
  • Google Cirq (via OpenQASM import)
  • Rigetti (via AWS Braket)
  • IonQ (via AWS Braket or Azure Quantum)

Supports both OpenQASM 2.0 and 3.0 specifications.

OpenQASM Versions

  • OpenQASM 2.0: Legacy version, widely supported, no conditional operations
  • OpenQASM 3.0: Modern version with conditionals, mid-circuit measurements, and control flow

Supported Features

  • Single-qubit gates (H, X, Y, Z, S, T, RX, RY, RZ, Phase)
  • Multi-qubit gates (CNOT/CX, CZ, Toffoli/CCX)
  • Measurements and classical bits
  • Conditional operations (OpenQASM 3.0 only)
  • Barriers for visualization organization

Examples

# Export a Bell state circuit to OpenQASM 3.0
circuit = Qx.circuit(2)
  |> Qx.h(0)
  |> Qx.cnot(0, 1)
  |> Qx.measure(0, 0)
  |> Qx.measure(1, 1)

qasm = Qx.Export.OpenQASM.to_qasm(circuit)
File.write!("bell_state.qasm", qasm)

# Export to OpenQASM 2.0 (no conditionals)
qasm2 = Qx.Export.OpenQASM.to_qasm(circuit, version: 2)

# Export with custom options
qasm = Qx.Export.OpenQASM.to_qasm(circuit,
  version: 3,
  include_comments: true,
  gate_style: :verbose
)

Platform Compatibility

PlatformVersionMid-circuit MeasurementConditionals
IBM Quantum2.0, 3.03.0 only3.0 only
AWS Braket3.0YesYes
Google Cirq2.0NoNo
Rigetti2.0, 3.03.0 only3.0 only

Limitations

  • Circuits with conditionals cannot be exported to OpenQASM 2.0
  • Custom gate definitions are expanded to standard gates
  • Qubit ordering follows MSB convention (qubit 0 is leftmost)

Summary

Functions

Parses OpenQASM 3.0 source and returns a Qx.QuantumCircuit.

Like from_qasm/1 but raises on error.

Parses an OpenQASM 3.0 program containing a gate definition and returns Elixir source code for an equivalent function.

Converts a Qx quantum circuit to OpenQASM format.

Functions

from_qasm(source)

@spec from_qasm(String.t()) :: {:ok, Qx.QuantumCircuit.t()} | {:error, Exception.t()}

Parses OpenQASM 3.0 source and returns a Qx.QuantumCircuit.

Round-trips with to_qasm/1: any program produced by to_qasm/1 parses back to a circuit that simulates to the same state vector.

Returns

  • {:ok, %Qx.QuantumCircuit{}} on success
  • {:error, %Qx.QasmParseError{}} on grammar/syntax failures
  • {:error, %Qx.QasmUnsupportedError{}} for valid QASM that uses features Qx does not yet support (multi-register programs, gate modifiers, else branches, classical types beyond bit, …)
  • {:error, %Qx.QubitIndexError{}} / {:error, %Qx.ClassicalBitError{}} for index validation failures

Examples

iex> qasm = ~s"""
...> OPENQASM 3.0;
...> include "stdgates.inc";
...> qubit[2] q;
...> bit[2] c;
...> h q[0];
...> cx q[0], q[1];
...> c[0] = measure q[0];
...> c[1] = measure q[1];
...> """
iex> {:ok, circuit} = Qx.Export.OpenQASM.from_qasm(qasm)
iex> circuit.num_qubits
2

Supported features

See the module doc for the supported gate set, decompositions, and the list of QASM 3 features deliberately excluded from v1 (each raises a typed Qx.QasmUnsupportedError).

from_qasm!(source)

@spec from_qasm!(String.t()) :: Qx.QuantumCircuit.t()

Like from_qasm/1 but raises on error.

from_qasm_function(source)

@spec from_qasm_function(String.t()) :: {:ok, map()} | {:error, Exception.t()}

Parses an OpenQASM 3.0 program containing a gate definition and returns Elixir source code for an equivalent function.

The result map is %{name: String.t(), arity: pos_integer(), source: String.t()} where source is a def definition that can be inserted into a module via Code.compile_string/1 (or stored verbatim by callers like qxportal). The function takes (circuit, params..., qubits...) and returns the new circuit.

When the source contains multiple gate definitions, the last is treated as the "main" function — earlier ones are usually helpers which the main one references. Since user-defined gate references inside a gate body are rejected (Qx.QasmUnsupportedError), helpers themselves cannot be code-generated through this entry point.

If no gate definition is present, returns {:error, %Qx.QasmParseError{}}.

Example

iex> qasm = ~s"""
...> OPENQASM 3.0;
...> include "stdgates.inc";
...> gate bell a, b {
...>   h a;
...>   cx a, b;
...> }
...> """
iex> {:ok, %{name: "bell", arity: 3, source: source}} =
...>   Qx.Export.OpenQASM.from_qasm_function(qasm)
iex> source =~ "def bell(circuit, a, b)"
true

from_qasm_function!(source)

@spec from_qasm_function!(String.t()) :: map()

Like from_qasm_function/1 but raises on error.

to_qasm(circuit, options \\ [])

Converts a Qx quantum circuit to OpenQASM format.

Parameters

Options

  • :version - OpenQASM version (2 or 3, default: 3)
  • :include_comments - Add descriptive comments (default: false)
  • :gate_style - Gate naming style (:standard or :verbose, default: :standard)

Returns

A string containing the OpenQASM program.

Raises

Examples

circuit = Qx.circuit(2) |> Qx.h(0) |> Qx.cnot(0, 1)
qasm = Qx.Export.OpenQASM.to_qasm(circuit)

# Output:
# OPENQASM 3.0;
# include "stdgates.inc";
#
# qubit[2] q;
# bit[2] c;
#
# h q[0];
# cx q[0], q[1];