Skip to content

QASM Import

quanta.export.qasm_import

quanta.export.qasm_import -- QASM 2.0/3.0 to Quanta DAG import pipeline.

Parses OpenQASM files and converts them to Quanta's internal DAG representation. Essential for QASMBench integration and Benchpress.

Supports
  • QASM 2.0 (qelib1.inc gates) and QASM 3.0 (stdgates.inc)
  • Standard gates: h, x, y, z, s, t, cx, cz, swap, ccx, rx, ry, rz
  • Qubit/bit register declarations
  • Parametric gates with float params
  • Measurement statements
Example

from quanta.export.qasm_import import from_qasm dag = from_qasm(''' ... OPENQASM 2.0; ... include "qelib1.inc"; ... qreg q[2]; ... creg c[2]; ... h q[0]; ... cx q[0],q[1]; ... measure q -> c; ... ''') print(dag.gate_count()) 2

from_qasm

from_qasm(qasm_str: str) -> DAGCircuit

Parses QASM 2.0/3.0 string and returns a Quanta DAGCircuit.

Parameters:

Name Type Description Default
qasm_str str

OpenQASM string (2.0 or 3.0).

required

Returns:

Type Description
DAGCircuit

DAGCircuit ready for simulation or compilation.

Source code in quanta/export/qasm_import.py
def from_qasm(qasm_str: str) -> DAGCircuit:
    """Parses QASM 2.0/3.0 string and returns a Quanta DAGCircuit.

    Args:
        qasm_str: OpenQASM string (2.0 or 3.0).

    Returns:
        DAGCircuit ready for simulation or compilation.
    """
    lines = qasm_str.strip().split("\n")

    num_qubits = 0
    num_cbits = 0
    instructions: list[Instruction] = []
    has_measure = False
    qubit_offset: dict[str, int] = {}  # register_name -> starting index

    for line in lines:
        line = line.strip()
        if not line or line.startswith("//"):
            continue

        # Remove trailing semicolons and comments
        line = line.split("//")[0].strip().rstrip(";").strip()

        # Skip headers
        if line.startswith(("OPENQASM", "include")):
            continue

        # QASM 2.0: qreg q[N];
        m = re.match(r"qreg\s+(\w+)\s*\[\s*(\d+)\s*\]", line)
        if m:
            reg_name, size = m.group(1), int(m.group(2))
            qubit_offset[reg_name] = num_qubits
            num_qubits += size
            continue

        # QASM 3.0: qubit[N] q;
        m = re.match(r"qubit\s*\[\s*(\d+)\s*\]\s+(\w+)", line)
        if m:
            size, reg_name = int(m.group(1)), m.group(2)
            qubit_offset[reg_name] = num_qubits
            num_qubits += size
            continue

        # Classical registers
        m = re.match(r"(?:creg|bit)\s*\[?\s*(\d+)\s*\]?\s*(\w*)", line)
        if m and (line.startswith("creg") or line.startswith("bit")):
            num_cbits = max(num_cbits, int(m.group(1)))
            continue

        # Measurement (QASM 2.0: measure q -> c; QASM 3.0: c = measure q;)
        if "measure" in line:
            has_measure = True
            continue

        # Barrier (skip)
        if line.startswith("barrier"):
            continue

        # Gate application
        parsed = _parse_gate_line(line, qubit_offset)
        if parsed:
            instructions.append(parsed)

    if num_qubits == 0:
        num_qubits = _infer_qubits(instructions)

    # Build DAG
    builder = CircuitBuilder(num_qubits)
    for inst in instructions:
        builder.record(inst)

    if has_measure:
        builder.measurement = MeasureSpec(qubits=tuple(range(num_qubits)))

    return DAGCircuit.from_builder(builder)

from_qasm_file

from_qasm_file(filepath: str) -> DAGCircuit

Loads a QASM file and returns a DAGCircuit.

Source code in quanta/export/qasm_import.py
def from_qasm_file(filepath: str) -> DAGCircuit:
    """Loads a QASM file and returns a DAGCircuit."""
    with open(filepath) as f:
        return from_qasm(f.read())