{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "35492576-b15e-43e6-8b9b-293631c6b194",
      "metadata": {},
      "source": [
        "---\n",
        "title: OpenQASM 2 and the Qiskit SDK\n",
        "description: How to convert code between OpenQASM 2 and the Qiskit SDK.\n",
        "---\n",
        "\n",
        "# OpenQASM 2 and the Qiskit SDK\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f1330cdd-036e-4a99-b2d1-0348a4d70cb3",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "{/*\n",
        "  DO NOT EDIT THIS CELL!!!\n",
        "  This cell's content is generated automatically by a script. Anything you add\n",
        "  here will be removed next time the notebook is run. To add new content, create\n",
        "  a new cell before or after this one.\n",
        "  */}\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Package versions\">\n",
        "    The code on this page was developed using the following requirements.\n",
        "    We recommend using these versions or newer.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.3.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "328f6a16-5ec4-4d80-8507-f5d97aa02f26",
      "metadata": {},
      "source": [
        "The Qiskit SDK provides some tools for converting between OpenQASM representations of quantum programs, and the [QuantumCircuit](/docs/api/qiskit/qiskit.circuit.QuantumCircuit) class.\n",
        "\n",
        "<span id=\"qasm2-import\" />\n",
        "\n",
        "## Import an OpenQASM 2 program into Qiskit\n",
        "\n",
        "Two functions import OpenQASM 2 programs into Qiskit.\n",
        "These are [`qasm2.load()`](../api/qiskit/qasm2#load), which takes a filename, and [`qasm2.loads()`](../api/qiskit/qasm2#loads), which takes the OpenQASM 2 program as a string.\n",
        "\n",
        "```python\n",
        "import qiskit.qasm2\n",
        "\n",
        "qiskit.qasm2.load(filename, include_path=('.',), include_input_directory='append', custom_instructions=(), custom_classical=(), strict=False)\n",
        "qiskit.qasm2.loads(program, include_path=('.',), custom_instructions=(), custom_classical=(), strict=False)\n",
        "```\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "52d909cd-6332-46a3-9a1a-330e1c4a66cf",
      "metadata": {},
      "source": [
        "See the [OpenQASM 2 Qiskit API](/docs/api/qiskit/qasm2) for more information.\n",
        "\n",
        "### Import simple programs\n",
        "\n",
        "For most OpenQASM 2 programs, you can simply use `qasm2.load` and `qasm2.loads` with a single argument.\n",
        "\n",
        "#### Example: import an OpenQASM 2 program as a string\n",
        "\n",
        "Use `qasm2.loads()` to import an OpenQASM 2 program as a string into a QuantumCircuit:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "f7d62945-1899-4b39-acee-6aaf6b37db09",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "     ┌───┐     ┌─┐   \n",
              "q_0: ┤ H ├──■──┤M├───\n",
              "     └───┘┌─┴─┐└╥┘┌─┐\n",
              "q_1: ─────┤ X ├─╫─┤M├\n",
              "          └───┘ ║ └╥┘\n",
              "c: 2/═══════════╩══╩═\n",
              "                0  1 "
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "import qiskit.qasm2\n",
        "\n",
        "program = \"\"\"\n",
        "    OPENQASM 2.0;\n",
        "    include \"qelib1.inc\";\n",
        "    qreg q[2];\n",
        "    creg c[2];\n",
        "\n",
        "    h q[0];\n",
        "    cx q[0], q[1];\n",
        "\n",
        "    measure q -> c;\n",
        "\"\"\"\n",
        "circuit = qiskit.qasm2.loads(program)\n",
        "circuit.draw()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6556b10e-7d15-4c51-a917-a969a23babff",
      "metadata": {},
      "source": [
        "#### Example: import an OpenQASM 2 program from a file\n",
        "\n",
        "Use `load()` to import an OpenQASM 2 program from a file into a QuantumCircuit:\n",
        "\n",
        "```python\n",
        "import qiskit.qasm2\n",
        "circuit = qiskit.qasm2.load(\"myfile.qasm\")\n",
        "```\n",
        "\n",
        "<span id=\"custom-instructions\" />\n",
        "\n",
        "### Link OpenQASM 2 gates with Qiskit gates\n",
        "\n",
        "By default, Qiskit's OpenQASM 2 importer treats the include file `\"qelib1.inc\"` as a *de facto* standard library.\n",
        "The importer treats this file as containing precisely the gates it is described to contain in [the original paper defining OpenQASM 2](https://arxiv.org/abs/1707.03429).\n",
        "Qiskit will use the built-in gates in [the circuit library](../api/qiskit/circuit_library) to represent the gates in `\"qelib1.inc\"`.\n",
        "Gates defined in the program by manual OpenQASM 2 `gate` statements will, by default, be constructed as custom [Qiskit `Gate` subclasses](../api/qiskit/qiskit.circuit.Gate).\n",
        "\n",
        "You can tell the importer to use specific [`Gate`](../api/qiskit/qiskit.circuit.Gate) classes for the given `gate` statements it encounters.\n",
        "You can also use this mechanism to treat additional gate names as \"built-in\", that is, not requiring an explicit definition.\n",
        "If you specify which gate classes to use for `gate` statements outside of `\"qelib1.inc\"`, the resulting circuit will typically be more efficient to work with.\n",
        "\n",
        "<Admonition type=\"warning\">\n",
        "  As of Qiskit SDK v1.0, Qiskit's OpenQASM 2 *exporter* (see [Export a Qiskit circuit to OpenQASM 2](#qasm2-export)) still behaves as if `\"qelib1.inc\"` has more gates than it really does.\n",
        "  This means that the default settings of the importer might not be able to import a program exported by our importer.\n",
        "  See [the specific example on working with the legacy exporter](#qasm2-import-legacy) to resolve this problem.\n",
        "\n",
        "  This discrepancy is legacy behavior of Qiskit, and [it will be resolved in a later release of Qiskit](https://github.com/Qiskit/qiskit/issues/10737).\n",
        "</Admonition>\n",
        "\n",
        "To pass information about a custom instruction to the OpenQASM 2 importer, use [the `qasm2.CustomInstruction` class](../api/qiskit/qasm2#qiskit.qasm2.CustomInstruction).\n",
        "This has four required pieces of information, in order:\n",
        "\n",
        "* The **name** of the gate, used in the OpenQASM 2 program\n",
        "* The **number of angle parameters** that the gate takes\n",
        "* The **number of qubits** that the gate acts on\n",
        "* The Python **constructor** class or function for the gate, which takes the gate parameters (but not qubits) as individual arguments\n",
        "\n",
        "If the importer encounters a `gate` definition that matches a given custom instruction, it will use that custom information to reconstruct the gate object.\n",
        "If a `gate` statement is encountered that matches the `name` of a custom instruction, but does not match both the number of parameters and the number of qubits, the importer will raise a [`QASM2ParseError`](../api/qiskit/qasm2#qasm2parseerror), to indicate the mismatch between the supplied information and program.\n",
        "\n",
        "In addition, a fifth argument `builtin` can be optionally set to `True` to make the gate automatically available within the OpenQASM 2 program, even if it is not explicitly defined.\n",
        "If the importer does encounter an explicit `gate` definition for a built-in custom instruction, it will accept it silently.\n",
        "As before, if an explicit definition of the same name is not compatible with the provided custom instruction, a [`QASM2ParseError`](../api/qiskit/qasm2#qasm2parseerror) will be raised.\n",
        "This is useful for compatibility with older OpenQASM 2 exporters, and with certain other quantum platforms that treat the \"basis gates\" of their hardware as built-in instructions.\n",
        "\n",
        "Qiskit provides a data attribute for working with OpenQASM 2 programs produced by legacy versions of [Qiskit's OpenQASM 2 exporting capabilities](#qasm2-export).\n",
        "This is [`qasm2.LEGACY_CUSTOM_INSTRUCTIONS`](../api/qiskit/qasm2#legacy-compatibility), which can be given as the `custom_instructions` argument to [`qasm2.load()`](../api/qiskit/qasm2#load) and [`qasm2.loads()`](../api/qiskit/qasm2#loads).\n",
        "\n",
        "<span id=\"qasm2-import-legacy\" />\n",
        "\n",
        "#### Example: import a program created by Qiskit's legacy exporter\n",
        "\n",
        "This OpenQASM 2 program uses gates that are not in the original version of `\"qelib1.inc\"` without declaring them, but are standard gates in Qiskit's library.\n",
        "You can use [`qasm2.LEGACY_CUSTOM_INSTRUCTIONS`](../api/qiskit/qasm2#legacy-compatibility) to easily tell the importer to use the same set of gates that Qiskit's OpenQASM 2 exporter previously used.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "a4b52b96-1b2d-48bb-8aa4-bd413aa3acea",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit import qasm2\n",
        "\n",
        "program = \"\"\"\n",
        "    OPENQASM 2.0;\n",
        "    include \"qelib1.inc\";\n",
        "\n",
        "    qreg q[4];\n",
        "    creg c[4];\n",
        "\n",
        "    h q[0];\n",
        "    cx q[0], q[1];\n",
        "\n",
        "    // 'rxx' is not actually in `qelib1.inc`,\n",
        "    // but Qiskit used to behave as if it were.\n",
        "    rxx(0.75) q[2], q[3];\n",
        "\n",
        "    measure q -> c;\n",
        "\"\"\"\n",
        "circuit = qasm2.loads(\n",
        "    program,\n",
        "    custom_instructions=qasm2.LEGACY_CUSTOM_INSTRUCTIONS,\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0de0c75d-3890-4138-a994-e8dcf728d7f3",
      "metadata": {},
      "source": [
        "#### Example: use a particular gate class when importing an OpenQASM 2 program\n",
        "\n",
        "Qiskit cannot, in general, verify if the definition in an OpenQASM 2 `gate` statement corresponds exactly to a Qiskit standard-library gate.\n",
        "Instead, Qiskit chooses a custom gate using the precise definition supplied.\n",
        "This can be less efficient that using one of the built-in standard gates, or a user-defined custom gate.\n",
        "You can manually define `gate` statements with particular classes.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "73432f4a-c5c1-4cec-ba5d-85ad4787ef52",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit import qasm2\n",
        "from qiskit.circuit import Gate\n",
        "from qiskit.circuit.library import RZXGate\n",
        "\n",
        "\n",
        "# Define a custom gate that takes one qubit and two angles.\n",
        "class MyGate(Gate):\n",
        "    def __init__(self, theta, phi):\n",
        "        super().__init__(\"my\", 1, [theta, phi])\n",
        "\n",
        "\n",
        "custom_instructions = [\n",
        "    # Link the OpenQASM 2 name 'my' with our custom gate.\n",
        "    qasm2.CustomInstruction(\"my\", 2, 1, MyGate),\n",
        "    # Link the OpenQASM 2 name 'rzx' with Qiskit's\n",
        "    # built-in RZXGate.\n",
        "    qasm2.CustomInstruction(\"rzx\", 1, 2, RZXGate),\n",
        "]\n",
        "\n",
        "program = \"\"\"\n",
        "    OPENQASM 2.0;\n",
        "\n",
        "    gate my(theta, phi) q {\n",
        "        U(theta / 2, phi, -theta / 2) q;\n",
        "    }\n",
        "    gate rzx(theta) a, b {\n",
        "        // It doesn't matter what definition is\n",
        "        // supplied, if the parameters match;\n",
        "        // Qiskit will still use `RZXGate`.\n",
        "    }\n",
        "\n",
        "    qreg q[2];\n",
        "    my(0.25, 0.125) q[0];\n",
        "    rzx(pi) q[0], q[1];\n",
        "\"\"\"\n",
        "\n",
        "circuit = qasm2.loads(\n",
        "    program,\n",
        "    custom_instructions=custom_instructions,\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "eb78c9cc-e600-4be0-8616-b9bc5ddad511",
      "metadata": {},
      "source": [
        "#### Example: define a new built-in gate in an OpenQASM 2 program\n",
        "\n",
        "If the argument `builtin=True` is set, a custom gate does not need to have an associated definition.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "c37eb527-bed0-4c62-8404-f79e49d42318",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit import qasm2\n",
        "from qiskit.circuit import Gate\n",
        "\n",
        "\n",
        "# Define a custom gate that takes one qubit and two angles.\n",
        "class MyGate(Gate):\n",
        "    def __init__(self, theta, phi):\n",
        "        super().__init__(\"my\", 1, [theta, phi])\n",
        "\n",
        "\n",
        "custom_instructions = [\n",
        "    qasm2.CustomInstruction(\"my\", 2, 1, MyGate, builtin=True),\n",
        "]\n",
        "\n",
        "program = \"\"\"\n",
        "    OPENQASM 2.0;\n",
        "    qreg q[1];\n",
        "\n",
        "    my(0.25, 0.125) q[0];\n",
        "\"\"\"\n",
        "\n",
        "circuit = qasm2.loads(\n",
        "    program,\n",
        "    custom_instructions=custom_instructions,\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4145ce48-0001-42e2-be5e-83c2e31f0fd9",
      "metadata": {},
      "source": [
        "<span id=\"custom-classical\" />\n",
        "\n",
        "### Define custom classical functions\n",
        "\n",
        "OpenQASM 2 includes some built-in classical functions to use in gate arguments.\n",
        "You can extend the language with more functions by using the `custom_classical` argument to [`qasm2.load()`](../api/qiskit/qasm2#load) and [`qasm2.loads()`](../api/qiskit/qasm3#loads), with the [`qasm2.CustomClassical`](../api/qiskit/qasm2#qiskit.qasm2.CustomClassical) class.\n",
        "\n",
        "To define a custom classical function, you must supply:\n",
        "\n",
        "* The *name* of the function as it appears in the OpenQASM 2 program\n",
        "* The number of floating-point arguments it accepts\n",
        "* A callable Python object that evaluates the function\n",
        "\n",
        "All defined custom classical functions are treated as built-in to the OpenQASM 2 language by the importer.\n",
        "There is no official way within the OpenQASM 2 language to define new functions; this is a Qiskit extension.\n",
        "\n",
        "#### Example: use custom classical instructions\n",
        "\n",
        "Here we provide two custom classical functions.\n",
        "The first is simple, and just adds one to its input.\n",
        "The second is the function `math.atan2`, which represents the mathematical operation $\\arctan(y/x)$ in a quadrant-aware manner.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "b135de19-4b54-4820-8f9d-84a42494debe",
      "metadata": {},
      "outputs": [],
      "source": [
        "import math\n",
        "from qiskit import qasm2\n",
        "\n",
        "program = \"\"\"\n",
        "    include \"qelib1.inc\";\n",
        "    qreg q[2];\n",
        "    rx(arctan(pi, 3 + add_one(0.2))) q[0];\n",
        "    cx q[0], q[1];\n",
        "\"\"\"\n",
        "\n",
        "\n",
        "def add_one(x):\n",
        "    return x + 1\n",
        "\n",
        "\n",
        "customs = [\n",
        "    # Our `add_one` takes only one parameter.\n",
        "    qasm2.CustomClassical(\"add_one\", 1, add_one),\n",
        "    # `arctan` takes two parameters, and `math.atan2` implements it.\n",
        "    qasm2.CustomClassical(\"arctan\", 2, math.atan2),\n",
        "]\n",
        "circuit = qasm2.loads(program, custom_classical=customs)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4373999e-9df1-4078-ab83-d1c88a577aaf",
      "metadata": {},
      "source": [
        "<span id=\"strict\" />\n",
        "\n",
        "### Strict mode\n",
        "\n",
        "By default, this parser is more relaxed than the official specification.\n",
        "It allows trailing commas in parameter lists; unnecessary (empty-statement) semicolons; omission of the `OPENQASM 2.0;` version statement; and several other quality-of-life improvements without emitting any errors.\n",
        "However, you can use the \"letter-of-the-spec\" mode with `strict=True`.\n",
        "\n",
        "<span id=\"qasm2-export\" />\n",
        "\n",
        "## Export a Qiskit circuit to OpenQASM 2\n",
        "\n",
        "Qiskit can also export a [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) to OpenQASM 2.\n",
        "You use the function [`qasm2.dump()`](../api/qiskit/qasm2#dump) to write to a file, and [`qasm2.dumps()`](../api/qiskit/qasm2#dumps) to write to a string.\n",
        "These functions currently have a very simple interface: they accept a circuit and, only in the case of [`qasm2.dump()`](../api/qiskit/qasm2#dump), a location to write the output to.\n",
        "\n",
        "<Admonition type=\"warning\">\n",
        "  Qiskit's OpenQASM 2 exporter still assumes a legacy, non-standard version of the `\"qelib1.inc\"` include file.\n",
        "  [This will be resolved in a later release of Qiskit](https://github.com/Qiskit/qiskit/issues/10737), but in the meantime, if you need to re-import an OpenQASM 2 program created with Qiskit, use [the example above for how to tell the importer about the legacy gates](#qasm2-import-legacy).\n",
        "</Admonition>\n",
        "\n",
        "### Example: export a circuit to OpenQASM 2\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "70f4d657-8be3-400d-a793-d36962a855ef",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit import QuantumCircuit, qasm2\n",
        "\n",
        "# Define any circuit.\n",
        "circuit = QuantumCircuit(2, 2)\n",
        "circuit.h(0)\n",
        "circuit.cx(0, 1)\n",
        "circuit.measure([0, 1], [0, 1])\n",
        "\n",
        "# Export to a string.\n",
        "program = qasm2.dumps(circuit)\n",
        "\n",
        "# Export to a file.\n",
        "qasm2.dump(circuit, \"my_file.qasm\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1c0fd601-51ec-4d82-8821-20e0554a3662",
      "metadata": {},
      "source": [
        "## Next steps\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recommendations\">\n",
        "  * Learn how to generate OpenQASM code in the [IBM Quantum Composer](/docs/guides/composer) guide.\n",
        "  * See the [OpenQASM 2 Qiskit API](/docs/api/qiskit/qasm2) reference.\n",
        "  * Review the [Verify your program](./debugging-tools) topic.\n",
        "  * Visit the [OpenQASM Live Specification](https://openqasm.com/).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}