Skip to content

Import and export restricted OpenQASM 3 circuits

Use import_program() and export_program() from cascaqit.interop to convert static digital circuits. The current parser accepts a defined subset of OpenQASM 3. A file’s version header does not guarantee that every statement can be converted.

Read a file into a string, then pass it to ProgramImportRequest(source_format="openqasm3", source=text). Check the returned program, diagnostics, unsupported_features and lossy_mappings before using the program. The default on_unsupported="diagnose" returns diagnostics; choose "raise" to request an exception.

Re-import the export and check a rejected statement

This example imports a rotation and controlled gate, exports the program and imports it again. It checks structure and the circuit’s local state probabilities, then replaces X with an unsupported reset to check rejection.

"""Check restricted OpenQASM conversion before using an imported program."""

from __future__ import annotations

import json

from cascaqit.digital import DigitalProgramIR
from cascaqit.interop import (
    ProgramExportRequest,
    ProgramImportRequest,
    export_program,
    import_program,
    prove_openqasm3_round_trip,
)
from cascaqit.simulators import compare_digital_program_semantics


def main() -> None:
    """Inspect a valid conversion, a round trip and an unsupported reset."""
    source = """
    OPENQASM 3;
    qubit[2] q;
    bit[2] c;
    ry(0.4) q[0];
    cx q[0], q[1];
    x q[1];
    measure q[0] -> c[0];
    measure q[1] -> c[1];
    """
    imported = import_program(
        ProgramImportRequest(source_format="openqasm3", source=source)
    )
    if (
        not isinstance(imported.program, DigitalProgramIR)
        or imported.unsupported_features
    ):
        raise RuntimeError("The supported source did not produce a digital program.")
    exported = export_program(
        ProgramExportRequest(program=imported.program, target_format="openqasm3")
    )
    if not isinstance(exported.payload, str):
        raise RuntimeError("The export did not produce OpenQASM source.")
    restored = import_program(
        ProgramImportRequest(source_format="openqasm3", source=exported.payload)
    )
    if not isinstance(restored.program, DigitalProgramIR):
        raise RuntimeError("The exported source could not be imported again.")
    structure = prove_openqasm3_round_trip(imported.program)
    probabilities = compare_digital_program_semantics(
        imported.program, restored.program
    )
    blocked = import_program(
        ProgramImportRequest(
            source_format="openqasm3", source=source.replace("x q[1];", "reset q[1];")
        )
    )
    if (
        structure.status != "passed"
        or probabilities.status != "equivalent"
        or blocked.program is not None
    ):
        raise RuntimeError("The conversion checks did not match the supported subset.")
    print(
        json.dumps(
            {
                "exported_source": exported.payload,
                "round_trip_status": structure.status,
                "matched_fields": list(structure.matched_fields),
                "probability_status": probabilities.status,
                "maximum_probability_delta": probabilities.max_probability_delta,
                "blocked_reset": blocked.program is None,
                "reset_diagnostics": [item.code for item in blocked.diagnostics],
            },
            sort_keys=True,
        )
    )


if __name__ == "__main__":
    main()

Download the full script

python examples/learning/guides/openqasm_interop_en.py
{
  "blocked_reset": true,
  "exported_source": "OPENQASM 3;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nry(0.40000000000000002) q[0];\ncx q[0], q[1];\nx q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];\n",
  "matched_fields": [
    "qubits",
    "gates",
    "measurements",
    "bit_order",
    "measurement_mapping"
  ],
  "maximum_probability_delta": 0.0,
  "probability_status": "equivalent",
  "reset_diagnostics": [
    "OPENQASM_RESET_UNSUPPORTED"
  ],
  "round_trip_status": "passed"
}

Expect round_trip_status: passed; the checked fields include gates, measurements, bit order and classical-bit mapping. probability_status should be equivalent, with zero probability difference here. This compares computational-basis probabilities for this circuit, not full unitary equivalence on arbitrary input states.

Expect blocked_reset: true and OPENQASM_RESET_UNSUPPORTED. Returning a diagnostic does not remove reset or execute the remainder as a complete program.

Supported syntax and checks after conversion

Content Current treatment
Fixed-size qubit/bit arrays, numeric angles and terminal measurements Accepted when written in the restricted syntax
I/X/Y/Z/H/S/SDG/T/TDG, RX/RY/RZ/P/U, CX/CY/CZ Corresponding static gate statements are supported
SWAP export Lowered to three CX gates; this does not imply support for importing a SWAP statement
Runtime conditions, loops, reset and intermediate measurements Rejected or require external conversion first
Custom gates, defcal, delay, box and barrier Outside the parser’s current subset
Arbitrary external SDK runtime objects Not loaded or executed automatically

The current measurement syntax is measure q[0] -> c[0];. Check parser results before relying on another equivalent spelling or expression. An export is ready to save as source only when payload contains a string; it is not a submitted device job.

Keep the original source, diagnostics, bit order and measurement mapping. Matching count strings alone cannot establish that gates, phases or ordering were preserved. See the bit-order lesson and package API map. When a format needs an adapter, the native SDK does not automatically import cascaqit-compat.

中文版

SDK 1.0.8a · `8b227bff`