{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "ba5ec3d7-2a51-4ffa-b270-cbe18e98a454",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"El transpilador impulsado por IA pasa\"\n",
        "description: \"¿Qué son las pasadas del transpilador de IA y cómo se utilizan?\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore Eprint */}\n",
        "\n",
        "<span id=\"ai-powered-transpiler-passes\" />\n",
        "\n",
        "# El transpilador impulsado por IA pasa\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3c78c2c0-7afc-4cf3-988d-9e044b5d0fca",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7244dd08-62a0-4c10-8c0d-0bd01eebe68f",
      "metadata": {},
      "source": [
        "Las etapas de transpilación basadas en IA son etapas que sirven como sustituto directo de las etapas «tradicionales» de Qiskit para algunas tareas de transpilación. A menudo ofrecen mejores resultados que los algoritmos heurísticos existentes (por ejemplo, una menor profundidad y un menor número de CNOT), pero también son mucho más rápidos que los algoritmos de optimización, como los solucionadores de satisfacibilidad booleana. El transpilador de IA ejecuta las ejecuciones en tu entorno local.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Los pases de transpilador con IA están en estado de versión beta, sujetos a cambios.\n",
        "  Si tienes algún comentario o quieres ponerte en contacto con el equipo de desarrolladores, utiliza este [canal de Slack Workspace de Qiskit](https://qiskit.slack.com/archives/C06KF8YHUAU).\n",
        "</Admonition>\n",
        "\n",
        "Actualmente están disponibles los siguientes pases:\n",
        "\n",
        "**Pases de ruta**\n",
        "\n",
        "* `AIRouting`: Selección de la disposición y trazado de los circuitos\n",
        "\n",
        "**Pases de síntesis de circuitos**\n",
        "\n",
        "* `AICliffordSynthesis`: Síntesis de circuitos Clifford\n",
        "* `AILinearFunctionSynthesis`: Síntesis de circuitos de funciones lineales\n",
        "* `AIPermutationSynthesis`: Síntesis de circuitos de permutación\n",
        "\n",
        "Para utilizar las etapas del transpilador de IA, primero instala el `qiskit-ibm-transpiler` paquete. Visita la [documentación de la API de qiskit-ibm-transpiler](/docs/api/qiskit-ibm-transpiler) para obtener más información sobre las diferentes opciones disponibles.\n",
        "\n",
        "```sh\n",
        "pip install qiskit-ibm-transpiler\n",
        "```\n",
        "\n",
        "<span id=\"ai-routing-pass\" />\n",
        "\n",
        "## Pase de enrutamiento de IA\n",
        "\n",
        "El paso `AIRouting` actúa a la vez como etapa de trazado y etapa de enrutamiento. Puede utilizarse en `PassManager` de la siguiente manera:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "c104fcd0-4a85-4927-b026-93f4a6fdab51",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler import PassManager\n",
        "from qiskit.circuit.library import efficient_su2\n",
        "from qiskit_ibm_transpiler.ai.routing import AIRouting\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "import logging\n",
        "\n",
        "backend = QiskitRuntimeService().backend(\"ibm_fez\")\n",
        "ai_passmanager = PassManager(\n",
        "    [\n",
        "        AIRouting(\n",
        "            backend=backend,\n",
        "            optimization_level=2,\n",
        "            layout_mode=\"optimize\",\n",
        "        )\n",
        "    ]\n",
        ")\n",
        "\n",
        "\n",
        "circuit = efficient_su2(101, entanglement=\"circular\", reps=1)\n",
        "logging.getLogger(\n",
        "    \"qiskit_ibm_transpiler.wrappers.ai_local_synthesis\"\n",
        ").setLevel(logging.WARNING)\n",
        "transpiled_circuit = ai_passmanager.run(circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "28c2cfa3-e4d8-48d5-9d6c-b02fcf548ef1",
      "metadata": {},
      "source": [
        "En este caso, `backend` determina el mapa de acoplamiento que se va a trazar, `optimization_level` (1, 2 o 3) determina el esfuerzo computacional que se va a emplear en el proceso (un valor más alto suele dar mejores resultados, pero lleva más tiempo) y `layout_mode` especifica cómo manejar la selección del trazado.\n",
        "La página `layout_mode` incluye las siguientes opciones:\n",
        "\n",
        "* `keep`: Respeta el diseño establecido por las pasadas anteriores del transpilador (o utiliza el diseño trivial si no se ha establecido). Normalmente sólo se utiliza cuando el circuito debe ejecutarse en qubits específicos del dispositivo. A menudo produce peores resultados porque tiene menos margen de optimización.\n",
        "* `improve`: Utiliza como punto de partida la disposición establecida por los pases anteriores del transpilador. Es útil cuando se tiene una buena estimación inicial del trazado; por ejemplo, para circuitos que se construyen de una forma que sigue aproximadamente el mapa de acoplamiento del dispositivo. También es útil si desea probar otros pases de trazado específicos combinados con el pase `AIRouting` .\n",
        "* `optimize`: Este es el modo por defecto. Funciona mejor para circuitos generales en los que es posible que no tengas buenas suposiciones sobre el trazado. Este modo ignora las selecciones de diseño anteriores.\n",
        "\n",
        "<span id=\"ai-circuit-synthesis-passes\" />\n",
        "\n",
        "## La síntesis de circuitos de IA pasa\n",
        "\n",
        "Los pases de síntesis de circuitos AI permiten optimizar piezas de distintos tipos de circuitos ([Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford), [Función lineal](/docs/api/qiskit/qiskit.circuit.library.LinearFunction), [Permutación](/docs/api/qiskit/qiskit.circuit.library.Permutation#permutation), Red Pauli) resintetizándolas. Una forma típica de utilizar el pase de síntesis es la siguiente:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "8655f68d-f88a-4a15-ad89-f39f2ba3fe71",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler import PassManager\n",
        "\n",
        "from qiskit_ibm_transpiler.ai.routing import AIRouting\n",
        "from qiskit_ibm_transpiler.ai.synthesis import AILinearFunctionSynthesis\n",
        "from qiskit_ibm_transpiler.ai.collection import CollectLinearFunctions\n",
        "from qiskit.circuit.library import efficient_su2\n",
        "\n",
        "ibm_kingston = QiskitRuntimeService().backend(\"ibm_kingston\")\n",
        "ai_passmanager = PassManager(\n",
        "    [\n",
        "        AIRouting(\n",
        "            backend=ibm_kingston,\n",
        "            optimization_level=3,\n",
        "            layout_mode=\"optimize\",\n",
        "            local_mode=True,\n",
        "        ),  # Route circuit\n",
        "        CollectLinearFunctions(),  # Collect Linear Function blocks\n",
        "        AILinearFunctionSynthesis(\n",
        "            backend=ibm_kingston, local_mode=True\n",
        "        ),  # Re-synthesize Linear Function blocks\n",
        "    ]\n",
        ")\n",
        "\n",
        "circuit = efficient_su2(10, entanglement=\"full\", reps=1)\n",
        "\n",
        "transpiled_circuit = ai_passmanager.run(circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "779f180e-c29f-4a96-b4b0-e3d2a4c8a1b9",
      "metadata": {},
      "source": [
        "La síntesis respeta el mapa de acoplamiento del dispositivo: puede ejecutarse con seguridad después de otros pases de enrutamiento sin alterar el circuito, por lo que el circuito global seguirá respetando las restricciones del dispositivo. Por defecto, la síntesis sustituirá el subcircuito original sólo si el subcircuito sintetizado mejora el original (actualmente sólo comprueba el recuento CNOT), pero se puede forzar a que sustituya siempre el circuito configurando `replace_only_if_better=False`.\n",
        "\n",
        "Los siguientes pases de síntesis están disponibles en `qiskit_ibm_transpiler.ai.synthesis`:\n",
        "\n",
        "* *AICliffordSynthesis* : Síntesis para circuitos [Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford) (bloques de compuertas `H`, `S`, y `CX` ). Actualmente, hasta nueve bloques de qubits.\n",
        "* *AILinearFunctionSynthesis* : Síntesis para circuitos de [función lineal](/docs/api/qiskit/qiskit.circuit.library.LinearFunction) (bloques de compuertas `CX` y `SWAP` ). Actualmente, hasta nueve bloques de qubits.\n",
        "* *AIPermutationSynthesis* : Síntesis de circuitos de [permutación](/docs/api/qiskit/qiskit.circuit.library.Permutation#permutation) (bloques de puertas `SWAP` ). Actualmente disponible para bloques de 65, 33 y 27 qubits.\n",
        "* *AIPauliNetworkSynthesis* : Síntesis para circuitos de Red Pauli (bloques de compuertas `H`, `S`, `SX`, `CX`, `RX`, `RY` y `RZ` ). Actualmente, hasta seis bloques de qubits.\n",
        "\n",
        "Esperamos aumentar gradualmente el tamaño de los bloques admitidos.\n",
        "\n",
        "Todos los pases utilizan un pool de hilos para enviar varias peticiones en paralelo. Por defecto, el número de hilos máximos es el número de núcleos más cuatro (valores por defecto para el objeto `ThreadPoolExecutor` Python ). Sin embargo, puede establecer su propio valor con el argumento `max_threads` en la instanciación del pase. Por ejemplo, la siguiente línea instancia el pase `AILinearFunctionSynthesis` , lo que le permite utilizar un máximo de 20 hilos.\n",
        "\n",
        "```python\n",
        "AILinearFunctionSynthesis(backend=ibm_torino, max_threads=20)  # Re-synthesize Linear Function blocks using 20 threads max\n",
        "```\n",
        "\n",
        "También puede establecer la variable de entorno `AI_TRANSPILER_MAX_THREADS` en el número deseado de hilos máximos, y todos los pases de síntesis instanciados después utilizarán ese valor.\n",
        "\n",
        "Para que los pases de síntesis de IA sinteticen un subcircuito, éste debe estar en un subgrafo conectado del mapa de acoplamiento (una forma de hacerlo es con un pase de enrutamiento antes de reunir los bloques, pero no es la única forma de hacerlo). Los pases de síntesis comprobarán automáticamente si el subgrafo específico es compatible y, en caso contrario, emitirán una advertencia y dejarán el subcircuito original sin cambios.\n",
        "\n",
        "Los siguientes pases de colección personalizados para Cliffords, Funciones lineales y Permutaciones que pueden importarse de `qiskit_ibm_transpiler.ai.collection` también complementan los pases de síntesis:\n",
        "\n",
        "* *RecogerCliffords* : Recoge bloques Clifford como objetos `Instruction` y almacena el subcircuito original para compararlo con él después de la síntesis.\n",
        "* *RecopilarFuncionesLineales* : Recoge bloques de `SWAP` y `CX` como objetos `LinearFunction` y almacena el subcircuito original para compararlo con él después de la síntesis.\n",
        "* *RecogerPermutaciones* : Recoge bloques de circuitos de `SWAP` como `Permutations`.\n",
        "* *RecogerRedesPauli* : Recoge bloques de redes Pauli y almacena el subcircuito original para compararlo con él después de la síntesis.\n",
        "\n",
        "Estos pases de recopilación personalizados limitan los tamaños de los subcircuitos recopilados para que sean compatibles con los pases de síntesis basados en IA. Por lo tanto, se recomienda utilizarlos después de los pases de enrutamiento y antes de los pases de síntesis para una mejor optimización global.\n",
        "\n",
        "<span id=\"hybrid-heuristic-ai-circuit-transpilation\" />\n",
        "\n",
        "## Transpilación híbrida de circuitos heurísticos y de IA\n",
        "\n",
        "`qiskit-ibm-transpiler` permite configurar un gestor de pases híbrido que combina lo mejor de la heurística de Qiskit y los pases del transpilador basados en IA. Esta función se comporta de forma similar al método Qiskit `generate_pass_manager` . Una forma típica de utilizar `generate_ai_pass_manager` es la siguiente:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "2f5bbf22-22cd-46fa-885c-851f769552f0",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_transpiler import generate_ai_pass_manager\n",
        "from qiskit.circuit.library import efficient_su2\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "\n",
        "backend = QiskitRuntimeService().backend(\"ibm_kingston\")\n",
        "kingston_coupling_map = backend.coupling_map\n",
        "\n",
        "\n",
        "su2_circuit = efficient_su2(101, entanglement=\"circular\", reps=1)\n",
        "\n",
        "ai_transpiler_pass_manager = generate_ai_pass_manager(\n",
        "    coupling_map=kingston_coupling_map,\n",
        "    ai_optimization_level=3,\n",
        "    optimization_level=3,\n",
        "    ai_layout_mode=\"optimize\",\n",
        ")\n",
        "\n",
        "ai_su2_transpiled_circuit = ai_transpiler_pass_manager.run(su2_circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7f34294b-c520-439a-b1d7-2962af07aced",
      "metadata": {},
      "source": [
        "En este ejemplo se utilizan las siguientes opciones:\n",
        "\n",
        "* `coupling_map` - Especifica qué mapa de acoplamiento utilizar para la transpilación.\n",
        "* `ai_optimization_level` - Especifica el nivel de optimización (1-3) que se utilizará para los componentes de IA de PassManager.\n",
        "* `optimization_level` - Especifica cuánta optimización realizar en el circuito para los componentes heurísticos de PassManager.\n",
        "* `ai_layout_mode` - Especifica cómo la parte de enrutamiento AI de la PassManager maneja el diseño. Consulte la sección [AI routing pass](#ai-routing-pass) para revisar las opciones de configuración de este parámetro `ai_layout_mode` .\n",
        "\n",
        "<span id=\"citation\" />\n",
        "\n",
        "## Citación\n",
        "\n",
        "Referencia bibliográfica\n",
        "Si utilizas alguna función basada en inteligencia artificial del `qiskit-ibm-transpiler` paquete en tu investigación, utiliza la siguiente referencia bibliográfica recomendada:\n",
        "\n",
        "```\n",
        "@misc{2405.13196,\n",
        "Author = {David Kremer and Victor Villar and Hanhee Paik and Ivan Duran and Ismael Faro and Juan Cruz-Benito},\n",
        "Title = {Practical and efficient quantum circuit synthesis and transpiling with Reinforcement Learning},\n",
        "Year = {2024},\n",
        "Eprint = {arXiv:2405.13196},\n",
        "}\n",
        "```\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
}