{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "35492576-b15e-43e6-8b9b-293631c6b194",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"OpenQASM 2 y el Qiskit SDK\"\n",
        "description: \"Cómo convertir código entre OpenQASM 2 y Qiskit SDK.\"\n",
        "---\n",
        "\n",
        "<span id=\"openqasm-2-and-the-qiskit-sdk\" />\n",
        "\n",
        "# OpenQASM 2 y el 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=\"Versiones del paquete\">\n",
        "    El código de esta página se ha desarrollado teniendo en cuenta los siguientes requisitos.\n",
        "    Recomendamos utilizar estas versiones o versiones más recientes.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "328f6a16-5ec4-4d80-8507-f5d97aa02f26",
      "metadata": {},
      "source": [
        "El SDK de Qiskit proporciona algunas herramientas para convertir entre OpenQASM representaciones de programas cuánticos, y la clase [QuantumCircuit](/docs/api/qiskit/qiskit.circuit.QuantumCircuit) clase.\n",
        "\n",
        "<span id=\"qasm2-import\" />\n",
        "\n",
        "<span id=\"import-an-openqasm-2-program-into-qiskit\" />\n",
        "\n",
        "## Importar un programa de OpenQASM 2 a Qiskit\n",
        "\n",
        "Dos funciones importan programas de OpenQASM 2 a Qiskit.\n",
        "Estos son [`qasm2.load()`](../api/qiskit/qasm2#load)que toma un nombre de archivo, y [`qasm2.loads()`](../api/qiskit/qasm2#loads)que toma el programa OpenQASM 2 como cadena.\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": [
        "Consulte la [API Qiskit de OpenQASM 2](/docs/api/qiskit/qasm2) para obtener más información.\n",
        "\n",
        "<span id=\"import-simple-programs\" />\n",
        "\n",
        "### Importar programas sencillos\n",
        "\n",
        "Para la mayoría de los programas OpenQASM 2, puede utilizar simplemente `qasm2.load` y `qasm2.loads` con un único argumento.\n",
        "\n",
        "<span id=\"example-import-an-openqasm-2-program-as-a-string\" />\n",
        "\n",
        "#### Ejemplo: importar un programa OpenQASM 2 como una cadena\n",
        "\n",
        "Utilice `qasm2.loads()` para importar un programa OpenQASM 2 como una cadena en un 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": [
        "<span id=\"example-import-an-openqasm-2-program-from-a-file\" />\n",
        "\n",
        "#### Ejemplo: importar un programa OpenQASM 2 desde un archivo\n",
        "\n",
        "Utilice `load()` para importar un programa OpenQASM 2 de un archivo a un QuantumCircuit:\n",
        "\n",
        "```python\n",
        "import qiskit.qasm2\n",
        "circuit = qiskit.qasm2.load(\"myfile.qasm\")\n",
        "```\n",
        "\n",
        "<span id=\"custom-instructions\" />\n",
        "\n",
        "<span id=\"link-openqasm-2-gates-with-qiskit-gates\" />\n",
        "\n",
        "### Enlace OpenQASM 2 puertas con puertas Qiskit\n",
        "\n",
        "Por defecto, el importador de Qiskit OpenQASM 2 trata el archivo de inclusión `\"qelib1.inc\"` como una biblioteca estándar *de facto*.\n",
        "El importador trata este archivo como si contuviera precisamente las puertas que se describe que contiene en [el documento original que define OpenQASM 2](https://arxiv.org/abs/1707.03429).\n",
        "Qiskit utilizará las puertas incorporadas en [la biblioteca de circuitos](../api/qiskit/circuit_library) para representar las puertas en `\"qelib1.inc\"`.\n",
        "Las puertas definidas en el programa mediante sentencias manuales OpenQASM 2 `gate` se construirán, por defecto, como personalizadas [Qiskit `Gate` subclases](../api/qiskit/qiskit.circuit.Gate).\n",
        "\n",
        "Puede indicar al importador que utilice clases [`Gate`](../api/qiskit/qiskit.circuit.Gate) específicas para las sentencias `gate` que encuentre.\n",
        "También puede utilizar este mecanismo para tratar nombres de puerta adicionales como \"incorporados\", es decir, que no requieren una definición explícita.\n",
        "Si especifica qué clases de compuerta utilizar para las declaraciones `gate` fuera de `\"qelib1.inc\"`, el circuito resultante será normalmente más eficiente para trabajar.\n",
        "\n",
        "<Admonition type=\"warning\">\n",
        "  Según Qiskit SDKv1.0, *el exportador* de Qiskit OpenQASM 2 (véase [Exportar un circuito Qiskit a OpenQASM 2](#qasm2-export) ) sigue comportándose como si `\"qelib1.inc\"` tuviera más puertas de las que realmente tiene.\n",
        "  Esto significa que es posible que la configuración predeterminada del importador no permita importar un programa exportado por nuestro importador.\n",
        "  Consulte [el ejemplo específico sobre cómo trabajar con el exportador heredado](#qasm2-import-legacy) para resolver este problema.\n",
        "\n",
        "  Esta discrepancia es un comportamiento heredado de Qiskit, y [se resolverá en una versión posterior de Qiskit](https://github.com/Qiskit/qiskit/issues/10737).\n",
        "</Admonition>\n",
        "\n",
        "Para pasar información sobre una instrucción personalizada al importador de OpenQASM 2, utilice [la clase `qasm2.CustomInstruction` ](../api/qiskit/qasm2#qiskit.qasm2.CustomInstruction).\n",
        "Tiene cuatro datos obligatorios, por orden:\n",
        "\n",
        "* El **nombre** de la puerta, utilizado en el programa OpenQASM 2\n",
        "* El **número de parámetros angulares** que toma la puerta\n",
        "* **Número de qubits** sobre los que actúa la puerta\n",
        "* La clase o función **constructora** Python para la puerta, que toma los parámetros de la puerta (pero no los qubits) como argumentos individuales\n",
        "\n",
        "Si el importador encuentra una definición de `gate` que coincide con una instrucción personalizada determinada, utilizará esa información personalizada para reconstruir el objeto de puerta.\n",
        "Si se encuentra una sentencia `gate` que coincide con `name` de una instrucción personalizada, pero no coincide ni con el número de parámetros ni con el número de qubits, el importador emitirá un mensaje [`QASM2ParseError`](../api/qiskit/qasm2#qasm2parseerror)para indicar el desajuste entre la información suministrada y el programa.\n",
        "\n",
        "Además, se puede establecer opcionalmente un quinto argumento `builtin` a `True` para que la puerta esté disponible automáticamente dentro del programa OpenQASM 2, aunque no esté definida explícitamente.\n",
        "Si el importador encuentra una definición explícita de `gate` para una instrucción personalizada incorporada, la aceptará en silencio.\n",
        "Como antes, si una definición explícita del mismo nombre no es compatible con la instrucción personalizada proporcionada, se producirá un error [`QASM2ParseError`](../api/qiskit/qasm2#qasm2parseerror) .\n",
        "Esto es útil para la compatibilidad con antiguos exportadores de OpenQASM 2, y con algunas otras plataformas cuánticas que tratan las \"puertas base\" de su hardware como instrucciones incorporadas.\n",
        "\n",
        "Qiskit proporciona un atributo de datos para trabajar con programas OpenQASM 2 producidos por versiones heredadas de [las capacidades de exportación de OpenQASM 2 de Qiskit](#qasm2-export).\n",
        "Es decir [`qasm2.LEGACY_CUSTOM_INSTRUCTIONS`](../api/qiskit/qasm2#legacy-compatibility)que se puede dar como argumento de `custom_instructions` a [`qasm2.load()`](../api/qiskit/qasm2#load) y [`qasm2.loads()`](../api/qiskit/qasm2#loads).\n",
        "\n",
        "<span id=\"qasm2-import-legacy\" />\n",
        "\n",
        "<span id=\"example-import-a-program-created-by-qiskits-legacy-exporter\" />\n",
        "\n",
        "#### Ejemplo: importar un programa creado por el exportador heredado de Qiskit\n",
        "\n",
        "Este programa OpenQASM 2 utiliza compuertas que no están en la versión original de `\"qelib1.inc\"` sin declararlas, pero son compuertas estándar en la biblioteca de Qiskit.\n",
        "Puedes usar [`qasm2.LEGACY_CUSTOM_INSTRUCTIONS`](../api/qiskit/qasm2#legacy-compatibility) para indicar al importador que utilice el mismo conjunto de puertas que el exportador de Qiskit OpenQASM 2.\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": [
        "<span id=\"example-use-a-particular-gate-class-when-importing-an-openqasm-2-program\" />\n",
        "\n",
        "#### Ejemplo: utilizar una clase de puerta concreta al importar un programa de OpenQASM 2\n",
        "\n",
        "Qiskit no puede, en general, verificar si la definición en una declaración OpenQASM 2 `gate` corresponde exactamente a una puerta de la biblioteca estándar Qiskit.\n",
        "En su lugar, Qiskit elige una puerta personalizada a partir de la definición precisa suministrada.\n",
        "Esto puede ser menos eficaz que utilizar una de las puertas estándar incorporadas, o una puerta personalizada definida por el usuario.\n",
        "Puede definir manualmente las sentencias `gate` con clases concretas.\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": [
        "<span id=\"example-define-a-new-built-in-gate-in-an-openqasm-2-program\" />\n",
        "\n",
        "#### Ejemplo: definir una nueva puerta integrada en un programa OpenQASM 2\n",
        "\n",
        "Si se establece el argumento `builtin=True` , una puerta personalizada no necesita tener una definición asociada.\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",
        "<span id=\"define-custom-classical-functions\" />\n",
        "\n",
        "### Definir funciones clásicas personalizadas\n",
        "\n",
        "OpenQASM 2 incluye algunas funciones clásicas incorporadas para utilizar en argumentos de puerta.\n",
        "Puede ampliar el lenguaje con más funciones utilizando el argumento `custom_classical` de [`qasm2.load()`](../api/qiskit/qasm2#load) y [`qasm2.loads()`](../api/qiskit/qasm3#loads)con la clase [`qasm2.CustomClassical`](../api/qiskit/qasm2#qiskit.qasm2.CustomClassical) clase.\n",
        "\n",
        "Para definir una función clásica personalizada, debe suministrar:\n",
        "\n",
        "* El *nombre* de la función tal y como aparece en el programa OpenQASM 2\n",
        "* El número de argumentos de coma flotante que acepta\n",
        "* Un objeto invocable Python que evalúa la función\n",
        "\n",
        "Todas las funciones clásicas personalizadas definidas son tratadas por el importador como incorporadas al lenguaje OpenQASM 2.\n",
        "No existe una forma oficial dentro del lenguaje OpenQASM 2 para definir nuevas funciones; se trata de una extensión de Qiskit.\n",
        "\n",
        "<span id=\"example-use-custom-classical-instructions\" />\n",
        "\n",
        "#### Ejemplo: utilizar instrucciones clásicas personalizadas\n",
        "\n",
        "Aquí proporcionamos dos funciones clásicas personalizadas.\n",
        "La primera es sencilla, y sólo añade uno a su entrada.\n",
        "La segunda es la función `math.atan2`, que representa la operación matemática $\\arctan(y/x)$ de forma sensible a los cuadrantes.\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",
        "<span id=\"strict-mode\" />\n",
        "\n",
        "### Modalidad estricta\n",
        "\n",
        "Por defecto, este analizador sintáctico es más relajado que la especificación oficial.\n",
        "Permite comas finales en las listas de parámetros; puntos y comas innecesarios (declaración vacía); omisión de la declaración de versión `OPENQASM 2.0;` ; y varias otras mejoras de calidad de vida sin emitir ningún error.\n",
        "Sin embargo, puede utilizar el modo \"letra-de-la-específica\" con `strict=True`.\n",
        "\n",
        "<span id=\"qasm2-export\" />\n",
        "\n",
        "<span id=\"export-a-qiskit-circuit-to-openqasm-2\" />\n",
        "\n",
        "## Exportar un circuito Qiskit a OpenQASM 2\n",
        "\n",
        "Qiskit también puede exportar un [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit) a OpenQASM 2.\n",
        "Se utiliza la función [`qasm2.dump()`](../api/qiskit/qasm2#dump) para escribir en un fichero, y [`qasm2.dumps()`](../api/qiskit/qasm2#dumps) para escribir en una cadena.\n",
        "Actualmente, estas funciones tienen una interfaz muy sencilla: aceptan un circuito y, sólo en el caso de [`qasm2.dump()`](../api/qiskit/qasm2#dump)una ubicación en la que escribir la salida.\n",
        "\n",
        "<Admonition type=\"warning\">\n",
        "  El exportador OpenQASM 2 de Qiskit sigue asumiendo una versión heredada y no estándar del archivo de inclusión `\"qelib1.inc\"` .\n",
        "  [Esto se resolverá en una versión posterior de Qiskit](https://github.com/Qiskit/qiskit/issues/10737), pero mientras tanto, si necesita volver a importar un programa OpenQASM 2 creado con Qiskit, utilice [el ejemplo anterior para saber cómo decirle al importador acerca de las puertas de legado](#qasm2-import-legacy).\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"example-export-a-circuit-to-openqasm-2\" />\n",
        "\n",
        "### Ejemplo: exportar un circuito a 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": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximos pasos\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendaciones\">\n",
        "  * Aprenda a generar código OpenQASM en la guía [IBM Quantum Composer](/docs/guides/composer).\n",
        "  * Consulte la referencia de [la API de Qiskit en OpenQASM 2](/docs/api/qiskit/qasm2).\n",
        "  * Consulte el apartado «[Verificar su programa](/docs/guides/debugging-tools) ».\n",
        "  * Visite la [especificación OpenQASM Live](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
}